Commit d0650ae1 authored by Pierre Langlois's avatar Pierre Langlois Committed by Commit Bot

[arm64][builtins] Allow simulator instructions in builtins.

Simulator-specific instructions are very useful, we can:

  - Place breakpoints that enable the simulator's interactive debugger, allowing
    us to see registers, the stack and print JS objects.

  - Enable and disable simulator tracing dynamically.

  - Call printf() directly, as the simulator cannot easily support its calling
    convention.

However these tools are not available when generating builtins. The reason is
that when cross-compiling, builtins are generated for real hardware but may
still run inside the simulator on the host if we have a custom snapshot. Using
the `v8_embed_script` GN option will do that for example but embedders may also
do this with the V8 API.

mksnapshot cannot tell the difference between generating code for a simulator
build and a cross-build. If we change this, we can allow us to use
simulator-specific features in builtins in simulator builds.

So in this patch we:

  - Introduce a --target_is_simulator mksnapshot flag to drive the
    enable_simulator_code Assembler option.

  - Make sure the assembler respect the option instead of the USE_SIMULATOR
    macro.


Change-Id: I7a7249f514427c1a2518a1af3679679596a72c7e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1991497Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Pierre Langlois <pierre.langlois@arm.com>
Cr-Commit-Position: refs/heads/master@{#65734}
parent a374cc97
...@@ -20,7 +20,7 @@ import("gni/v8.gni") ...@@ -20,7 +20,7 @@ import("gni/v8.gni")
# Specifies if the target build is a simulator build. Comparing target cpu # Specifies if the target build is a simulator build. Comparing target cpu
# with v8 target cpu to not affect simulator builds for making cross-compile # with v8 target cpu to not affect simulator builds for making cross-compile
# snapshots. # snapshots.
is_target_simulator = (target_cpu != v8_target_cpu && !v8_multi_arch_build) || target_is_simulator = (target_cpu != v8_target_cpu && !v8_multi_arch_build) ||
(current_cpu != v8_current_cpu && v8_multi_arch_build) (current_cpu != v8_current_cpu && v8_multi_arch_build)
# For faster Windows builds. See https://crbug.com/v8/8475. # For faster Windows builds. See https://crbug.com/v8/8475.
...@@ -170,7 +170,7 @@ declare_args() { ...@@ -170,7 +170,7 @@ declare_args() {
# site-isolation in Chrome and on simulator builds which test code generation # site-isolation in Chrome and on simulator builds which test code generation
# on these platforms. # on these platforms.
v8_untrusted_code_mitigations = v8_untrusted_code_mitigations =
v8_current_cpu != "x86" && (is_android || is_target_simulator) v8_current_cpu != "x86" && (is_android || target_is_simulator)
# Enable minor mark compact. # Enable minor mark compact.
v8_enable_minor_mc = true v8_enable_minor_mc = true
...@@ -542,7 +542,7 @@ config("toolchain") { ...@@ -542,7 +542,7 @@ config("toolchain") {
} }
# Mips64el/mipsel simulators. # Mips64el/mipsel simulators.
if (is_target_simulator && if (target_is_simulator &&
(v8_current_cpu == "mipsel" || v8_current_cpu == "mips64el")) { (v8_current_cpu == "mipsel" || v8_current_cpu == "mips64el")) {
defines += [ "_MIPS_TARGET_SIMULATOR" ] defines += [ "_MIPS_TARGET_SIMULATOR" ]
} }
...@@ -1291,6 +1291,13 @@ template("run_mksnapshot") { ...@@ -1291,6 +1291,13 @@ template("run_mksnapshot") {
rebase_path("$target_gen_dir/embedded${suffix}.S", root_build_dir), rebase_path("$target_gen_dir/embedded${suffix}.S", root_build_dir),
] ]
# This is needed to distinguish between generating code for the simulator
# and cross-compiling. The latter may need to run code on the host with the
# simulator but cannot use simulator-specific instructions.
if (target_is_simulator) {
args += [ "--target_is_simulator" ]
}
args += invoker.args args += invoker.args
outputs += [ "$target_gen_dir/embedded${suffix}.S" ] outputs += [ "$target_gen_dir/embedded${suffix}.S" ]
......
...@@ -476,14 +476,7 @@ Operand MemOperand::OffsetAsOperand() const { ...@@ -476,14 +476,7 @@ Operand MemOperand::OffsetAsOperand() const {
} }
} }
void Assembler::Unreachable() { void Assembler::Unreachable() { debug("UNREACHABLE", __LINE__, BREAK); }
#ifdef USE_SIMULATOR
debug("UNREACHABLE", __LINE__, BREAK);
#else
// Crash by branching to 0. lr now points near the fault.
Emit(BLR | Rn(xzr));
#endif
}
Address Assembler::target_pointer_address_at(Address pc) { Address Assembler::target_pointer_address_at(Address pc) {
Instruction* instr = reinterpret_cast<Instruction*>(pc); Instruction* instr = reinterpret_cast<Instruction*>(pc);
......
...@@ -3654,7 +3654,6 @@ void Assembler::EmitStringData(const char* string) { ...@@ -3654,7 +3654,6 @@ void Assembler::EmitStringData(const char* string) {
} }
void Assembler::debug(const char* message, uint32_t code, Instr params) { void Assembler::debug(const char* message, uint32_t code, Instr params) {
#ifdef USE_SIMULATOR
if (options().enable_simulator_code) { if (options().enable_simulator_code) {
// The arguments to the debug marker need to be contiguous in memory, so // The arguments to the debug marker need to be contiguous in memory, so
// make sure we don't try to emit pools. // make sure we don't try to emit pools.
...@@ -3676,12 +3675,6 @@ void Assembler::debug(const char* message, uint32_t code, Instr params) { ...@@ -3676,12 +3675,6 @@ void Assembler::debug(const char* message, uint32_t code, Instr params) {
return; return;
} }
// Fall through if Serializer is enabled.
#else
// Make sure we haven't dynamically enabled simulator code when there is no
// simulator built in.
DCHECK(!options().enable_simulator_code);
#endif
if (params & BREAK) { if (params & BREAK) {
brk(0); brk(0);
......
...@@ -3138,11 +3138,10 @@ void TurboAssembler::PrintfNoPreserve(const char* format, ...@@ -3138,11 +3138,10 @@ void TurboAssembler::PrintfNoPreserve(const char* format,
} }
void TurboAssembler::CallPrintf(int arg_count, const CPURegister* args) { void TurboAssembler::CallPrintf(int arg_count, const CPURegister* args) {
// A call to printf needs special handling for the simulator, since the system // A call to printf needs special handling for the simulator, since the system
// printf function will use a different instruction set and the procedure-call // printf function will use a different instruction set and the procedure-call
// standard will not be compatible. // standard will not be compatible.
#ifdef USE_SIMULATOR if (options().enable_simulator_code) {
{
InstructionAccurateScope scope(this, kPrintfLength / kInstrSize); InstructionAccurateScope scope(this, kPrintfLength / kInstrSize);
hlt(kImmExceptionIsPrintf); hlt(kImmExceptionIsPrintf);
dc32(arg_count); // kPrintfArgCountOffset dc32(arg_count); // kPrintfArgCountOffset
...@@ -3161,10 +3160,10 @@ void TurboAssembler::CallPrintf(int arg_count, const CPURegister* args) { ...@@ -3161,10 +3160,10 @@ void TurboAssembler::CallPrintf(int arg_count, const CPURegister* args) {
arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i)); arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
} }
dc32(arg_pattern_list); // kPrintfArgPatternListOffset dc32(arg_pattern_list); // kPrintfArgPatternListOffset
return;
} }
#else
Call(ExternalReference::printf_function()); Call(ExternalReference::printf_function());
#endif
} }
void TurboAssembler::Printf(const char* format, CPURegister arg0, void TurboAssembler::Printf(const char* format, CPURegister arg0,
......
...@@ -58,9 +58,15 @@ AssemblerOptions AssemblerOptions::Default(Isolate* isolate) { ...@@ -58,9 +58,15 @@ AssemblerOptions AssemblerOptions::Default(Isolate* isolate) {
options.enable_root_array_delta_access = options.enable_root_array_delta_access =
!serializer && !generating_embedded_builtin; !serializer && !generating_embedded_builtin;
#ifdef USE_SIMULATOR #ifdef USE_SIMULATOR
// Don't generate simulator specific code if we are building a snapshot, which // Even though the simulator is enabled, we may still need to generate code
// might be run on real hardware. // that may need to run on both the simulator and real hardware. For example,
options.enable_simulator_code = !serializer; // if we are cross-compiling and embedding a script into the snapshot, the
// script will need to run on the host causing the embedded builtins to run in
// the simulator. While the final cross-compiled V8 will not have a simulator.
// So here we enable simulator specific code if not generating the snapshot or
// if we are but we are targetting the simulator *only*.
options.enable_simulator_code = !serializer || FLAG_target_is_simulator;
#endif #endif
options.inline_offheap_trampolines &= !generating_embedded_builtin; options.inline_offheap_trampolines &= !generating_embedded_builtin;
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
......
...@@ -1332,6 +1332,10 @@ DEFINE_STRING(startup_blob, nullptr, ...@@ -1332,6 +1332,10 @@ DEFINE_STRING(startup_blob, nullptr,
DEFINE_STRING(target_arch, nullptr, DEFINE_STRING(target_arch, nullptr,
"The mksnapshot target arch. (mksnapshot only)") "The mksnapshot target arch. (mksnapshot only)")
DEFINE_STRING(target_os, nullptr, "The mksnapshot target os. (mksnapshot only)") DEFINE_STRING(target_os, nullptr, "The mksnapshot target os. (mksnapshot only)")
DEFINE_BOOL(target_is_simulator, false,
"Instruct mksnapshot that the target is meant to run in the "
"simulator and it can generate simulator-specific instructions. "
"(mksnapshot only)")
// //
// Minor mark compact collector flags. // Minor mark compact collector flags.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment