[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/+/1991497 Reviewed-by: Jakob Gruber <jgruber@chromium.org> Commit-Queue: Pierre Langlois <pierre.langlois@arm.com> Cr-Commit-Position: refs/heads/master@{#65734}
This commit is contained in:
parent
a374cc97cc
commit
d0650ae18c
13
BUILD.gn
13
BUILD.gn
@ -20,7 +20,7 @@ import("gni/v8.gni")
|
||||
# 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
|
||||
# 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)
|
||||
|
||||
# For faster Windows builds. See https://crbug.com/v8/8475.
|
||||
@ -170,7 +170,7 @@ declare_args() {
|
||||
# site-isolation in Chrome and on simulator builds which test code generation
|
||||
# on these platforms.
|
||||
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.
|
||||
v8_enable_minor_mc = true
|
||||
@ -542,7 +542,7 @@ config("toolchain") {
|
||||
}
|
||||
|
||||
# Mips64el/mipsel simulators.
|
||||
if (is_target_simulator &&
|
||||
if (target_is_simulator &&
|
||||
(v8_current_cpu == "mipsel" || v8_current_cpu == "mips64el")) {
|
||||
defines += [ "_MIPS_TARGET_SIMULATOR" ]
|
||||
}
|
||||
@ -1291,6 +1291,13 @@ template("run_mksnapshot") {
|
||||
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
|
||||
|
||||
outputs += [ "$target_gen_dir/embedded${suffix}.S" ]
|
||||
|
@ -476,14 +476,7 @@ Operand MemOperand::OffsetAsOperand() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::Unreachable() {
|
||||
#ifdef USE_SIMULATOR
|
||||
debug("UNREACHABLE", __LINE__, BREAK);
|
||||
#else
|
||||
// Crash by branching to 0. lr now points near the fault.
|
||||
Emit(BLR | Rn(xzr));
|
||||
#endif
|
||||
}
|
||||
void Assembler::Unreachable() { debug("UNREACHABLE", __LINE__, BREAK); }
|
||||
|
||||
Address Assembler::target_pointer_address_at(Address pc) {
|
||||
Instruction* instr = reinterpret_cast<Instruction*>(pc);
|
||||
|
@ -3654,7 +3654,6 @@ void Assembler::EmitStringData(const char* string) {
|
||||
}
|
||||
|
||||
void Assembler::debug(const char* message, uint32_t code, Instr params) {
|
||||
#ifdef USE_SIMULATOR
|
||||
if (options().enable_simulator_code) {
|
||||
// The arguments to the debug marker need to be contiguous in memory, so
|
||||
// make sure we don't try to emit pools.
|
||||
@ -3676,12 +3675,6 @@ void Assembler::debug(const char* message, uint32_t code, Instr params) {
|
||||
|
||||
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) {
|
||||
brk(0);
|
||||
|
@ -3138,11 +3138,10 @@ void TurboAssembler::PrintfNoPreserve(const char* format,
|
||||
}
|
||||
|
||||
void TurboAssembler::CallPrintf(int arg_count, const CPURegister* args) {
|
||||
// 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
|
||||
// standard will not be compatible.
|
||||
#ifdef USE_SIMULATOR
|
||||
{
|
||||
// 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
|
||||
// standard will not be compatible.
|
||||
if (options().enable_simulator_code) {
|
||||
InstructionAccurateScope scope(this, kPrintfLength / kInstrSize);
|
||||
hlt(kImmExceptionIsPrintf);
|
||||
dc32(arg_count); // kPrintfArgCountOffset
|
||||
@ -3161,10 +3160,10 @@ void TurboAssembler::CallPrintf(int arg_count, const CPURegister* args) {
|
||||
arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
|
||||
}
|
||||
dc32(arg_pattern_list); // kPrintfArgPatternListOffset
|
||||
return;
|
||||
}
|
||||
#else
|
||||
|
||||
Call(ExternalReference::printf_function());
|
||||
#endif
|
||||
}
|
||||
|
||||
void TurboAssembler::Printf(const char* format, CPURegister arg0,
|
||||
|
@ -58,9 +58,15 @@ AssemblerOptions AssemblerOptions::Default(Isolate* isolate) {
|
||||
options.enable_root_array_delta_access =
|
||||
!serializer && !generating_embedded_builtin;
|
||||
#ifdef USE_SIMULATOR
|
||||
// Don't generate simulator specific code if we are building a snapshot, which
|
||||
// might be run on real hardware.
|
||||
options.enable_simulator_code = !serializer;
|
||||
// Even though the simulator is enabled, we may still need to generate code
|
||||
// that may need to run on both the simulator and real hardware. For example,
|
||||
// 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
|
||||
options.inline_offheap_trampolines &= !generating_embedded_builtin;
|
||||
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
|
||||
|
@ -1332,6 +1332,10 @@ DEFINE_STRING(startup_blob, nullptr,
|
||||
DEFINE_STRING(target_arch, nullptr,
|
||||
"The mksnapshot target arch. (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.
|
||||
|
Loading…
Reference in New Issue
Block a user