[vm/ffi] Call natives through stubs if write-protection is enabled without dual-mapping.

Addresses the Dart -> Native half of dartbug.com/37629

Change-Id: I242b7f3a14dd105334a8b6e5c089b173c398491e
Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111280
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Samir Jindel 2019-08-07 11:37:20 +00:00 committed by commit-bot@chromium.org
parent e323684f09
commit e59a4a2b42
28 changed files with 549 additions and 193 deletions

View file

@ -14,6 +14,9 @@
#include <psapi.h> #include <psapi.h>
#else #else
#include <unistd.h> #include <unistd.h>
// Only OK to use here because this is test code.
#include <thread>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
@ -26,6 +29,14 @@
namespace dart { namespace dart {
#define CHECK(X) \
if (!(X)) { \
fprintf(stderr, "%s\n", "Check failed: " #X); \
return 1; \
}
#define CHECK_EQ(X, Y) CHECK((X) == (Y))
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Tests for Dart -> native calls. // Tests for Dart -> native calls.
@ -481,30 +492,30 @@ DART_EXPORT float InventFloatValue() {
// Functions for stress-testing. // Functions for stress-testing.
DART_EXPORT int64_t MinInt64() { DART_EXPORT int64_t MinInt64() {
Dart_ExecuteInternalCommand("gc-on-next-allocation"); Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
return 0x8000000000000000; return 0x8000000000000000;
} }
DART_EXPORT int64_t MinInt32() { DART_EXPORT int64_t MinInt32() {
Dart_ExecuteInternalCommand("gc-on-next-allocation"); Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
return 0x80000000; return 0x80000000;
} }
DART_EXPORT double SmallDouble() { DART_EXPORT double SmallDouble() {
Dart_ExecuteInternalCommand("gc-on-next-allocation"); Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
return 0x80000000 * -1.0; return 0x80000000 * -1.0;
} }
// Requires boxing on 32-bit and 64-bit systems, even if the top 32-bits are // Requires boxing on 32-bit and 64-bit systems, even if the top 32-bits are
// truncated. // truncated.
DART_EXPORT void* LargePointer() { DART_EXPORT void* LargePointer() {
Dart_ExecuteInternalCommand("gc-on-next-allocation"); Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
uint64_t origin = 0x8100000082000000; uint64_t origin = 0x8100000082000000;
return reinterpret_cast<void*>(origin); return reinterpret_cast<void*>(origin);
} }
DART_EXPORT void TriggerGC(uint64_t count) { DART_EXPORT void TriggerGC(uint64_t count) {
Dart_ExecuteInternalCommand("gc-now"); Dart_ExecuteInternalCommand("gc-now", nullptr);
} }
// Triggers GC. Has 11 dummy arguments as unboxed odd integers which should be // Triggers GC. Has 11 dummy arguments as unboxed odd integers which should be
@ -520,20 +531,57 @@ DART_EXPORT void Regress37069(uint64_t a,
uint64_t i, uint64_t i,
uint64_t j, uint64_t j,
uint64_t k) { uint64_t k) {
Dart_ExecuteInternalCommand("gc-now"); Dart_ExecuteInternalCommand("gc-now", nullptr);
} }
#if !defined(HOST_OS_WINDOWS) && !defined(TARGET_ARCH_DBC)
DART_EXPORT void* UnprotectCodeOtherThread(void* isolate,
std::condition_variable* var,
std::mutex* mut) {
std::function<void()> callback = [&]() {
mut->lock();
var->notify_all();
mut->unlock();
// Wait for mutator thread to continue (and block) before leaving the
// safepoint.
while (Dart_ExecuteInternalCommand("is-mutator-in-native", isolate) !=
nullptr) {
usleep(10 * 1000 /*10 ms*/);
}
};
struct {
void* isolate;
std::function<void()>* callback;
} args = {.isolate = isolate, .callback = &callback};
Dart_ExecuteInternalCommand("run-in-safepoint-and-rw-code", &args);
return nullptr;
}
DART_EXPORT int UnprotectCode() {
std::mutex mutex;
std::condition_variable cvar;
std::unique_lock<std::mutex> lock(mutex); // locks the mutex
std::thread helper(UnprotectCodeOtherThread, Dart_CurrentIsolate(), &cvar,
&mutex);
helper.detach();
cvar.wait(lock);
return 0;
}
#else
// Our version of VSC++ doesn't support std::thread yet.
DART_EXPORT int UnprotectCode() {
return 0;
}
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Tests for callbacks. // Tests for callbacks.
#define CHECK(X) \
if (!(X)) { \
fprintf(stderr, "%s\n", "Check failed: " #X); \
return 1; \
}
#define CHECK_EQ(X, Y) CHECK((X) == (Y))
// Sanity test. // Sanity test.
DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) { DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) {
CHECK_EQ(add(10, 20), 30); CHECK_EQ(add(10, 20), 30);

View file

@ -179,6 +179,6 @@ DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses();
* *
* It should not be used outside internal tests. * It should not be used outside internal tests.
*/ */
DART_EXPORT void Dart_ExecuteInternalCommand(const char* command); DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg);
#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */ #endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */

View file

@ -5524,9 +5524,10 @@ LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
ASSERT(((1 << CallingConventions::kFirstCalleeSavedCpuReg) & ASSERT(((1 << CallingConventions::kFirstCalleeSavedCpuReg) &
CallingConventions::kArgumentRegisters) == 0); CallingConventions::kArgumentRegisters) == 0);
#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_IA32) || \ #if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_IA32)
defined(TARGET_ARCH_ARM)
constexpr intptr_t kNumTemps = 2; constexpr intptr_t kNumTemps = 2;
#elif defined(TARGET_ARCH_ARM)
constexpr intptr_t kNumTemps = 3;
#else #else
constexpr intptr_t kNumTemps = 1; constexpr intptr_t kNumTemps = 1;
#endif #endif
@ -5544,6 +5545,10 @@ LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
defined(TARGET_ARCH_ARM) defined(TARGET_ARCH_ARM)
summary->set_temp(1, Location::RegisterLocation( summary->set_temp(1, Location::RegisterLocation(
CallingConventions::kFirstCalleeSavedCpuReg)); CallingConventions::kFirstCalleeSavedCpuReg));
#endif
#if defined(TARGET_ARCH_ARM)
summary->set_temp(2, Location::RegisterLocation(
CallingConventions::kSecondCalleeSavedCpuReg));
#endif #endif
summary->set_out(0, compiler::ffi::ResultLocation( summary->set_out(0, compiler::ffi::ResultLocation(
compiler::ffi::ResultRepresentation(signature_))); compiler::ffi::ResultRepresentation(signature_)));

View file

@ -4400,6 +4400,15 @@ class FfiCallInstr : public Definition {
virtual Representation RequiredInputRepresentation(intptr_t idx) const; virtual Representation RequiredInputRepresentation(intptr_t idx) const;
virtual Representation representation() const; virtual Representation representation() const;
// Returns true if we can assume generated code will be executable during a
// safepoint.
//
// TODO(#37739): This should be true when dual-mapping is enabled as well, but
// there are some bugs where it still switches code protections currently.
static bool CanExecuteGeneratedCodeInSafepoint() {
return FLAG_precompiled_mode;
}
PRINT_OPERANDS_TO_SUPPORT PRINT_OPERANDS_TO_SUPPORT
private: private:

View file

@ -1036,13 +1036,28 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
RawPcDescriptors::Kind::kOther, locs()); RawPcDescriptors::Kind::kOther, locs());
// Update information in the thread object and enter a safepoint. // Update information in the thread object and enter a safepoint.
__ TransitionGeneratedToNative(branch, FPREG, saved_fp, const Register tmp = locs()->temp(1).reg();
locs()->temp(1).reg()); if (CanExecuteGeneratedCodeInSafepoint()) {
__ TransitionGeneratedToNative(branch, FPREG, saved_fp, tmp);
__ blx(branch); __ blx(branch);
// Update information in the thread object and leave the safepoint. // Update information in the thread object and leave the safepoint.
__ TransitionNativeToGenerated(saved_fp, locs()->temp(1).reg()); __ TransitionNativeToGenerated(saved_fp, tmp);
} else {
// We cannot trust that this code will be executable within a safepoint.
// Therefore we delegate the responsibility of entering/exiting the
// safepoint to a stub which in the VM isolate's heap, which will never lose
// execute permission.
__ ldr(TMP,
compiler::Address(
THR, compiler::target::Thread::
call_native_through_safepoint_entry_point_offset()));
// Calls R8 in a safepoint and clobbers NOTFP and R4.
ASSERT(branch == R8 && tmp == NOTFP && locs()->temp(2).reg() == R4);
__ blx(TMP);
}
// Restore the global object pool after returning from runtime (old space is // Restore the global object pool after returning from runtime (old space is
// moving, so the GOP could have been relocated). // moving, so the GOP could have been relocated).

View file

@ -912,20 +912,35 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ StoreToOffset(temp, FPREG, kSavedCallerPcSlotFromFp * kWordSize); __ StoreToOffset(temp, FPREG, kSavedCallerPcSlotFromFp * kWordSize);
// Update information in the thread object and enter a safepoint. if (CanExecuteGeneratedCodeInSafepoint()) {
__ TransitionGeneratedToNative(branch, FPREG, temp); // Update information in the thread object and enter a safepoint.
__ TransitionGeneratedToNative(branch, FPREG, temp);
// We are entering runtime code, so the C stack pointer must be restored from // We are entering runtime code, so the C stack pointer must be restored
// the stack limit to the top of the stack. // from the stack limit to the top of the stack.
__ mov(CSP, SP); __ mov(CSP, SP);
__ blr(branch); __ blr(branch);
// Restore the Dart stack pointer. // Restore the Dart stack pointer.
__ mov(SP, CSP); __ mov(SP, CSP);
// Update information in the thread object and leave the safepoint. // Update information in the thread object and leave the safepoint.
__ TransitionNativeToGenerated(temp); __ TransitionNativeToGenerated(temp);
} else {
// We cannot trust that this code will be executable within a safepoint.
// Therefore we delegate the responsibility of entering/exiting the
// safepoint to a stub which in the VM isolate's heap, which will never lose
// execute permission.
__ ldr(TMP,
compiler::Address(
THR, compiler::target::Thread::
call_native_through_safepoint_entry_point_offset()));
// Calls R8 and clobbers R19 (along with volatile registers).
ASSERT(branch == R8 && temp == R19);
__ blr(TMP);
}
// Refresh write barrier mask. // Refresh write barrier mask.
__ ldr(BARRIER_MASK, __ ldr(BARRIER_MASK,

View file

@ -953,8 +953,24 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ popl(tmp); __ popl(tmp);
__ movl(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), tmp); __ movl(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), tmp);
__ TransitionGeneratedToNative(branch, FPREG, tmp); if (CanExecuteGeneratedCodeInSafepoint()) {
__ call(branch); __ TransitionGeneratedToNative(branch, FPREG, tmp);
__ call(branch);
__ TransitionNativeToGenerated(tmp);
} else {
// We cannot trust that this code will be executable within a safepoint.
// Therefore we delegate the responsibility of entering/exiting the
// safepoint to a stub which in the VM isolate's heap, which will never lose
// execute permission.
__ movl(tmp,
compiler::Address(
THR, compiler::target::Thread::
call_native_through_safepoint_entry_point_offset()));
// Calls EAX within a safepoint and clobbers EBX.
ASSERT(tmp == EBX && branch == EAX);
__ call(tmp);
}
// The x86 calling convention requires floating point values to be returned on // The x86 calling convention requires floating point values to be returned on
// the "floating-point stack" (aka. register ST0). We don't use the // the "floating-point stack" (aka. register ST0). We don't use the
@ -968,8 +984,6 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ movss(XMM0, compiler::Address(SPREG, -kFloatSize)); __ movss(XMM0, compiler::Address(SPREG, -kFloatSize));
} }
__ TransitionNativeToGenerated(tmp);
// Leave dummy exit frame. // Leave dummy exit frame.
__ LeaveFrame(); __ LeaveFrame();
@ -5610,7 +5624,7 @@ static void EmitShiftInt64ByConstant(FlowGraphCompiler* compiler,
switch (op_kind) { switch (op_kind) {
case Token::kSHR: { case Token::kSHR: {
if (shift > 31) { if (shift > 31) {
__ movl(left_lo, left_hi); // Shift by 32. __ movl(left_lo, left_hi); // Shift by 32.
__ sarl(left_hi, compiler::Immediate(31)); // Sign extend left hi. __ sarl(left_hi, compiler::Immediate(31)); // Sign extend left hi.
if (shift > 32) { if (shift > 32) {
__ sarl(left_lo, compiler::Immediate(shift > 63 ? 31 : shift - 32)); __ sarl(left_lo, compiler::Immediate(shift > 63 ? 31 : shift - 32));
@ -5658,9 +5672,9 @@ static void EmitShiftInt64ByECX(FlowGraphCompiler* compiler,
__ Bind(&large_shift); __ Bind(&large_shift);
// No need to subtract 32 from CL, only 5 bits used by sarl. // No need to subtract 32 from CL, only 5 bits used by sarl.
__ movl(left_lo, left_hi); // Shift by 32. __ movl(left_lo, left_hi); // Shift by 32.
__ sarl(left_hi, compiler::Immediate(31)); // Sign extend left hi. __ sarl(left_hi, compiler::Immediate(31)); // Sign extend left hi.
__ sarl(left_lo, ECX); // Shift count: CL % 32. __ sarl(left_lo, ECX); // Shift count: CL % 32.
break; break;
} }
case Token::kSHL: { case Token::kSHL: {

View file

@ -965,13 +965,29 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
RawPcDescriptors::Kind::kOther, locs()); RawPcDescriptors::Kind::kOther, locs());
__ movq(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP); __ movq(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
// Update information in the thread object and enter a safepoint. if (CanExecuteGeneratedCodeInSafepoint()) {
__ TransitionGeneratedToNative(target_address, FPREG); // Update information in the thread object and enter a safepoint.
__ TransitionGeneratedToNative(target_address, FPREG);
__ CallCFunction(target_address); __ CallCFunction(target_address);
// Update information in the thread object and leave the safepoint. // Update information in the thread object and leave the safepoint.
__ TransitionNativeToGenerated(); __ TransitionNativeToGenerated();
} else {
// We cannot trust that this code will be executable within a safepoint.
// Therefore we delegate the responsibility of entering/exiting the
// safepoint to a stub which in the VM isolate's heap, which will never lose
// execute permission.
__ movq(TMP,
compiler::Address(
THR, compiler::target::Thread::
call_native_through_safepoint_entry_point_offset()));
// Calls RBX within a safepoint.
ASSERT(saved_fp == RBX);
__ movq(RBX, target_address);
__ call(TMP);
}
// Although PP is a callee-saved register, it may have been moved by the GC. // Although PP is a callee-saved register, it may have been moved by the GC.
__ LeaveDartFrame(compiler::kRestoreCallerPP); __ LeaveDartFrame(compiler::kRestoreCallerPP);

View file

@ -532,6 +532,10 @@ uword Thread::native_execution_state() {
return dart::Thread::ExecutionState::kThreadInNative; return dart::Thread::ExecutionState::kThreadInNative;
} }
uword Thread::vm_execution_state() {
return dart::Thread::ExecutionState::kThreadInVM;
}
uword Thread::vm_tag_compiled_id() { uword Thread::vm_tag_compiled_id() {
return dart::VMTag::kDartCompiledTagId; return dart::VMTag::kDartCompiledTagId;
} }

View file

@ -660,6 +660,7 @@ class Thread : public AllStatic {
static uword safepoint_state_acquired(); static uword safepoint_state_acquired();
static word execution_state_offset(); static word execution_state_offset();
static uword vm_execution_state();
static uword native_execution_state(); static uword native_execution_state();
static uword generated_execution_state(); static uword generated_execution_state();
static word stack_overflow_flags_offset(); static word stack_overflow_flags_offset();
@ -695,6 +696,8 @@ class Thread : public AllStatic {
static word deoptimize_stub_offset(); static word deoptimize_stub_offset();
static word enter_safepoint_stub_offset(); static word enter_safepoint_stub_offset();
static word exit_safepoint_stub_offset(); static word exit_safepoint_stub_offset();
static word call_native_through_safepoint_stub_offset();
static word call_native_through_safepoint_entry_point_offset();
#endif // !defined(TARGET_ARCH_DBC) #endif // !defined(TARGET_ARCH_DBC)
static word no_scope_native_wrapper_entry_point_offset(); static word no_scope_native_wrapper_entry_point_offset();

View file

@ -191,60 +191,64 @@ static constexpr dart::compiler::target::word String_hash_offset = 8;
static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 4;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 280; Thread_AllocateArray_entry_point_offset = 288;
static constexpr dart::compiler::target::word Thread_active_exception_offset = static constexpr dart::compiler::target::word Thread_active_exception_offset =
616; 624;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset = static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
620; 628;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 112; Thread_array_write_barrier_code_offset = 112;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_entry_point_offset = 192; Thread_array_write_barrier_entry_point_offset = 196;
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset = static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
84; 84;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 240; Thread_auto_scope_native_wrapper_entry_point_offset = 248;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 104; static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 100; static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 196; Thread_call_to_runtime_entry_point_offset = 200;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 132; Thread_call_to_runtime_stub_offset = 132;
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 648; static constexpr dart::compiler::target::word Thread_dart_stream_offset = 656;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset = static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
224; 228;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset = static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
228; 232;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset = static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
160; 160;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset = static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
260; 268;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_double_negate_address_offset = 256; Thread_double_negate_address_offset = 264;
static constexpr dart::compiler::target::word Thread_end_offset = 60; static constexpr dart::compiler::target::word Thread_end_offset = 60;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 180; Thread_enter_safepoint_stub_offset = 180;
static constexpr dart::compiler::target::word Thread_execution_state_offset = static constexpr dart::compiler::target::word Thread_execution_state_offset =
632; 640;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 184; Thread_exit_safepoint_stub_offset = 184;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_stub_offset = 188;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_entry_point_offset = 240;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_allocation_stub_code_offset = 120; Thread_fix_allocation_stub_code_offset = 120;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 116; Thread_fix_callers_target_code_offset = 116;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 272; Thread_float_absolute_address_offset = 280;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_negate_address_offset = 268; Thread_float_negate_address_offset = 276;
static constexpr dart::compiler::target::word Thread_float_not_address_offset = static constexpr dart::compiler::target::word Thread_float_not_address_offset =
264; 272;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 276; Thread_float_zerow_address_offset = 284;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset = static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
624; 632;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_interpret_call_entry_point_offset = 244; Thread_interpret_call_entry_point_offset = 252;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 128; Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
@ -259,38 +263,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 72; Thread_marking_stack_block_offset = 72;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_megamorphic_call_checked_entry_offset = 216; Thread_megamorphic_call_checked_entry_offset = 220;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_entry_offset = 220; Thread_monomorphic_miss_entry_offset = 224;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 152; Thread_monomorphic_miss_stub_offset = 152;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_no_scope_native_wrapper_entry_point_offset = 236; Thread_no_scope_native_wrapper_entry_point_offset = 244;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 204; Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_stub_offset = 140; Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_entry_point_offset = 200; Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_stub_offset = 136; Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
static constexpr dart::compiler::target::word Thread_object_null_offset = 96; static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 248; Thread_predefined_symbols_address_offset = 256;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 628; static constexpr dart::compiler::target::word Thread_resume_pc_offset = 636;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset = static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
636; 644;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 172; Thread_slow_type_test_stub_offset = 172;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36; static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_flags_offset = 40; Thread_stack_overflow_flags_offset = 40;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 212; Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148; Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 208; Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144; Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
static constexpr dart::compiler::target::word Thread_store_buffer_block_offset = static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@ -305,12 +309,12 @@ static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
static constexpr dart::compiler::target::word Thread_write_barrier_code_offset = static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
108; 108;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_entry_point_offset = 188; Thread_write_barrier_entry_point_offset = 192;
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset = static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
44; 44;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_verify_callback_entry_offset = 232; Thread_verify_callback_entry_offset = 236;
static constexpr dart::compiler::target::word Thread_callback_code_offset = 640; static constexpr dart::compiler::target::word Thread_callback_code_offset = 648;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8; static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12; static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16; static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@ -345,8 +349,8 @@ static constexpr dart::compiler::target::word
Code_function_entry_point_offset[] = {4, 8}; Code_function_entry_point_offset[] = {4, 8};
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = { Thread_write_barrier_wrappers_thread_offset[] = {
580, 584, 588, 592, 596, -1, 600, 604, 588, 592, 596, 600, 604, -1, 608, 612,
608, 612, -1, -1, -1, -1, -1, -1}; 616, 620, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word Array_header_size = 12; static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Context_header_size = 12; static constexpr dart::compiler::target::word Context_header_size = 12;
static constexpr dart::compiler::target::word Double_InstanceSize = 16; static constexpr dart::compiler::target::word Double_InstanceSize = 16;
@ -546,60 +550,64 @@ static constexpr dart::compiler::target::word String_hash_offset = 4;
static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 8;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 552; Thread_AllocateArray_entry_point_offset = 568;
static constexpr dart::compiler::target::word Thread_active_exception_offset = static constexpr dart::compiler::target::word Thread_active_exception_offset =
1240; 1256;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset = static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
1248; 1264;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 216; Thread_array_write_barrier_code_offset = 216;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_entry_point_offset = 376; Thread_array_write_barrier_entry_point_offset = 384;
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset = static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
168; 168;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 472; Thread_auto_scope_native_wrapper_entry_point_offset = 488;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 200; static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 192; static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 384; Thread_call_to_runtime_entry_point_offset = 392;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 256; Thread_call_to_runtime_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1304; static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1320;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset = static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
440; 448;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset = static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
448; 456;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset = static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
312; 312;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset = static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
512; 528;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_double_negate_address_offset = 504; Thread_double_negate_address_offset = 520;
static constexpr dart::compiler::target::word Thread_end_offset = 120; static constexpr dart::compiler::target::word Thread_end_offset = 120;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 352; Thread_enter_safepoint_stub_offset = 352;
static constexpr dart::compiler::target::word Thread_execution_state_offset = static constexpr dart::compiler::target::word Thread_execution_state_offset =
1272; 1288;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 360; Thread_exit_safepoint_stub_offset = 360;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_stub_offset = 368;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_entry_point_offset = 472;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_allocation_stub_code_offset = 232; Thread_fix_allocation_stub_code_offset = 232;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 224; Thread_fix_callers_target_code_offset = 224;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 536; Thread_float_absolute_address_offset = 552;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_negate_address_offset = 528; Thread_float_negate_address_offset = 544;
static constexpr dart::compiler::target::word Thread_float_not_address_offset = static constexpr dart::compiler::target::word Thread_float_not_address_offset =
520; 536;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 544; Thread_float_zerow_address_offset = 560;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset = static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
1256; 1272;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_interpret_call_entry_point_offset = 480; Thread_interpret_call_entry_point_offset = 496;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 248; Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
@ -614,38 +622,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 144; Thread_marking_stack_block_offset = 144;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_megamorphic_call_checked_entry_offset = 424; Thread_megamorphic_call_checked_entry_offset = 432;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_entry_offset = 432; Thread_monomorphic_miss_entry_offset = 440;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 296; Thread_monomorphic_miss_stub_offset = 296;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_no_scope_native_wrapper_entry_point_offset = 464; Thread_no_scope_native_wrapper_entry_point_offset = 480;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 400; Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_stub_offset = 272; Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_entry_point_offset = 392; Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_stub_offset = 264; Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
static constexpr dart::compiler::target::word Thread_object_null_offset = 184; static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 488; Thread_predefined_symbols_address_offset = 504;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1264; static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1280;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset = static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
1280; 1296;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 336; Thread_slow_type_test_stub_offset = 336;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72; static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_flags_offset = 80; Thread_stack_overflow_flags_offset = 80;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 416; Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288; Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 408; Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280; Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
static constexpr dart::compiler::target::word Thread_store_buffer_block_offset = static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@ -660,13 +668,13 @@ static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
static constexpr dart::compiler::target::word Thread_write_barrier_code_offset = static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
208; 208;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_entry_point_offset = 368; Thread_write_barrier_entry_point_offset = 376;
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset = static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
88; 88;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_verify_callback_entry_offset = 456; Thread_verify_callback_entry_offset = 464;
static constexpr dart::compiler::target::word Thread_callback_code_offset = static constexpr dart::compiler::target::word Thread_callback_code_offset =
1288; 1304;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16; 16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16; static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@ -702,8 +710,8 @@ static constexpr dart::compiler::target::word
Code_function_entry_point_offset[] = {8, 16}; Code_function_entry_point_offset[] = {8, 16};
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = { Thread_write_barrier_wrappers_thread_offset[] = {
1152, 1160, 1168, 1176, -1, -1, 1184, 1192, 1168, 1176, 1184, 1192, -1, -1, 1200, 1208,
1200, 1208, 1216, -1, 1224, 1232, -1, -1}; 1216, 1224, 1232, -1, 1240, 1248, -1, -1};
static constexpr dart::compiler::target::word Array_header_size = 24; static constexpr dart::compiler::target::word Array_header_size = 24;
static constexpr dart::compiler::target::word Context_header_size = 24; static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16; static constexpr dart::compiler::target::word Double_InstanceSize = 16;
@ -901,60 +909,64 @@ static constexpr dart::compiler::target::word String_hash_offset = 8;
static constexpr dart::compiler::target::word String_length_offset = 4; static constexpr dart::compiler::target::word String_length_offset = 4;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 280; Thread_AllocateArray_entry_point_offset = 288;
static constexpr dart::compiler::target::word Thread_active_exception_offset = static constexpr dart::compiler::target::word Thread_active_exception_offset =
580; 588;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset = static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
584; 592;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 112; Thread_array_write_barrier_code_offset = 112;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_entry_point_offset = 192; Thread_array_write_barrier_entry_point_offset = 196;
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset = static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
84; 84;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 240; Thread_auto_scope_native_wrapper_entry_point_offset = 248;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 104; static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 100; static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 196; Thread_call_to_runtime_entry_point_offset = 200;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 132; Thread_call_to_runtime_stub_offset = 132;
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 612; static constexpr dart::compiler::target::word Thread_dart_stream_offset = 620;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset = static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
224; 228;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset = static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
228; 232;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset = static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
160; 160;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset = static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
260; 268;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_double_negate_address_offset = 256; Thread_double_negate_address_offset = 264;
static constexpr dart::compiler::target::word Thread_end_offset = 60; static constexpr dart::compiler::target::word Thread_end_offset = 60;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 180; Thread_enter_safepoint_stub_offset = 180;
static constexpr dart::compiler::target::word Thread_execution_state_offset = static constexpr dart::compiler::target::word Thread_execution_state_offset =
596; 604;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 184; Thread_exit_safepoint_stub_offset = 184;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_stub_offset = 188;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_entry_point_offset = 240;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_allocation_stub_code_offset = 120; Thread_fix_allocation_stub_code_offset = 120;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 116; Thread_fix_callers_target_code_offset = 116;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 272; Thread_float_absolute_address_offset = 280;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_negate_address_offset = 268; Thread_float_negate_address_offset = 276;
static constexpr dart::compiler::target::word Thread_float_not_address_offset = static constexpr dart::compiler::target::word Thread_float_not_address_offset =
264; 272;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 276; Thread_float_zerow_address_offset = 284;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset = static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
588; 596;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_interpret_call_entry_point_offset = 244; Thread_interpret_call_entry_point_offset = 252;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 128; Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
@ -969,38 +981,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 72; Thread_marking_stack_block_offset = 72;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_megamorphic_call_checked_entry_offset = 216; Thread_megamorphic_call_checked_entry_offset = 220;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_entry_offset = 220; Thread_monomorphic_miss_entry_offset = 224;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 152; Thread_monomorphic_miss_stub_offset = 152;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_no_scope_native_wrapper_entry_point_offset = 236; Thread_no_scope_native_wrapper_entry_point_offset = 244;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 204; Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_stub_offset = 140; Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_entry_point_offset = 200; Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_stub_offset = 136; Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
static constexpr dart::compiler::target::word Thread_object_null_offset = 96; static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 248; Thread_predefined_symbols_address_offset = 256;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 592; static constexpr dart::compiler::target::word Thread_resume_pc_offset = 600;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset = static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
600; 608;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 172; Thread_slow_type_test_stub_offset = 172;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36; static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_flags_offset = 40; Thread_stack_overflow_flags_offset = 40;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 212; Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148; Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 208; Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144; Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
static constexpr dart::compiler::target::word Thread_store_buffer_block_offset = static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@ -1015,12 +1027,12 @@ static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
static constexpr dart::compiler::target::word Thread_write_barrier_code_offset = static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
108; 108;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_entry_point_offset = 188; Thread_write_barrier_entry_point_offset = 192;
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset = static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
44; 44;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_verify_callback_entry_offset = 232; Thread_verify_callback_entry_offset = 236;
static constexpr dart::compiler::target::word Thread_callback_code_offset = 604; static constexpr dart::compiler::target::word Thread_callback_code_offset = 612;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8; static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12; static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16; static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@ -1252,60 +1264,64 @@ static constexpr dart::compiler::target::word String_hash_offset = 4;
static constexpr dart::compiler::target::word String_length_offset = 8; static constexpr dart::compiler::target::word String_length_offset = 8;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 552; Thread_AllocateArray_entry_point_offset = 568;
static constexpr dart::compiler::target::word Thread_active_exception_offset = static constexpr dart::compiler::target::word Thread_active_exception_offset =
1328; 1344;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset = static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
1336; 1352;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 216; Thread_array_write_barrier_code_offset = 216;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_array_write_barrier_entry_point_offset = 376; Thread_array_write_barrier_entry_point_offset = 384;
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset = static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
168; 168;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 472; Thread_auto_scope_native_wrapper_entry_point_offset = 488;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 200; static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 192; static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 384; Thread_call_to_runtime_entry_point_offset = 392;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 256; Thread_call_to_runtime_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1392; static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1408;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset = static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
440; 448;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304; static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset = static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
448; 456;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset = static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
312; 312;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset = static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
512; 528;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_double_negate_address_offset = 504; Thread_double_negate_address_offset = 520;
static constexpr dart::compiler::target::word Thread_end_offset = 120; static constexpr dart::compiler::target::word Thread_end_offset = 120;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 352; Thread_enter_safepoint_stub_offset = 352;
static constexpr dart::compiler::target::word Thread_execution_state_offset = static constexpr dart::compiler::target::word Thread_execution_state_offset =
1360; 1376;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 360; Thread_exit_safepoint_stub_offset = 360;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_stub_offset = 368;
static constexpr dart::compiler::target::word
Thread_call_native_through_safepoint_entry_point_offset = 472;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_allocation_stub_code_offset = 232; Thread_fix_allocation_stub_code_offset = 232;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 224; Thread_fix_callers_target_code_offset = 224;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 536; Thread_float_absolute_address_offset = 552;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_negate_address_offset = 528; Thread_float_negate_address_offset = 544;
static constexpr dart::compiler::target::word Thread_float_not_address_offset = static constexpr dart::compiler::target::word Thread_float_not_address_offset =
520; 536;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 544; Thread_float_zerow_address_offset = 560;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset = static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
1344; 1360;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_interpret_call_entry_point_offset = 480; Thread_interpret_call_entry_point_offset = 496;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 248; Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
@ -1320,38 +1336,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 144; Thread_marking_stack_block_offset = 144;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_megamorphic_call_checked_entry_offset = 424; Thread_megamorphic_call_checked_entry_offset = 432;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_entry_offset = 432; Thread_monomorphic_miss_entry_offset = 440;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 296; Thread_monomorphic_miss_stub_offset = 296;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_no_scope_native_wrapper_entry_point_offset = 464; Thread_no_scope_native_wrapper_entry_point_offset = 480;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 400; Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_stub_offset = 272; Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_entry_point_offset = 392; Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_null_error_shared_without_fpu_regs_stub_offset = 264; Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
static constexpr dart::compiler::target::word Thread_object_null_offset = 184; static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 488; Thread_predefined_symbols_address_offset = 504;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1352; static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1368;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset = static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
1368; 1384;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 336; Thread_slow_type_test_stub_offset = 336;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72; static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_flags_offset = 80; Thread_stack_overflow_flags_offset = 80;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 416; Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288; Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 408; Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280; Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
static constexpr dart::compiler::target::word Thread_store_buffer_block_offset = static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@ -1366,13 +1382,13 @@ static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
static constexpr dart::compiler::target::word Thread_write_barrier_code_offset = static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
208; 208;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_entry_point_offset = 368; Thread_write_barrier_entry_point_offset = 376;
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset = static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
88; 88;
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_verify_callback_entry_offset = 456; Thread_verify_callback_entry_offset = 464;
static constexpr dart::compiler::target::word Thread_callback_code_offset = static constexpr dart::compiler::target::word Thread_callback_code_offset =
1376; 1392;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16; 16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16; static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@ -1408,9 +1424,9 @@ static constexpr dart::compiler::target::word
Code_function_entry_point_offset[] = {8, 16}; Code_function_entry_point_offset[] = {8, 16};
static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = { Thread_write_barrier_wrappers_thread_offset[] = {
1152, 1160, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232, 1240, 1248,
1240, 1248, 1256, 1264, -1, -1, -1, -1, 1272, 1280, 1288, 1256, 1264, 1272, 1280, -1, -1, -1, -1, 1288, 1296, 1304,
1296, 1304, 1312, 1320, -1, -1, -1, -1, -1, -1}; 1312, 1320, 1328, 1336, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word Array_header_size = 24; static constexpr dart::compiler::target::word Array_header_size = 24;
static constexpr dart::compiler::target::word Context_header_size = 24; static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16; static constexpr dart::compiler::target::word Double_InstanceSize = 16;

View file

@ -167,6 +167,8 @@
NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset)) \ NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset)) \
FIELD(Thread, execution_state_offset) \ FIELD(Thread, execution_state_offset) \
NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset)) \ NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset)) \
NOT_IN_DBC(FIELD(Thread, call_native_through_safepoint_stub_offset)) \
NOT_IN_DBC(FIELD(Thread, call_native_through_safepoint_entry_point_offset)) \
NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset)) \ NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset)) \
NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset)) \ NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset)) \
FIELD(Thread, float_absolute_address_offset) \ FIELD(Thread, float_absolute_address_offset) \

View file

@ -291,6 +291,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ EnterFrame((1 << FP) | (1 << LR), 0); __ EnterFrame((1 << FP) | (1 << LR), 0);
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);
// Set the execution state to VM while waiting for the safepoint to end.
// This isn't strictly necessary but enables tests to check that we're not
// in native code anymore. See tests/ffi/function_gc_test.dart for example.
__ LoadImmediate(R0, target::Thread::vm_execution_state());
__ str(R0, Address(THR, target::Thread::execution_state_offset()));
__ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread())); __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ blx(R0); __ blx(R0);
__ LeaveFrame((1 << FP) | (1 << LR), 0); __ LeaveFrame((1 << FP) | (1 << LR), 0);
@ -299,6 +306,31 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ Ret(); __ Ret();
} }
// Call a native function within a safepoint.
//
// On entry:
// Stack: set up for call, incl. alignment
// R8: target to call
//
// On exit:
// Stack: preserved
// NOTFP, R4: clobbered, although normally callee-saved
void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
Assembler* assembler) {
COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R4)) != 0);
// TransitionGeneratedToNative might clobber LR if it takes the slow path.
__ mov(R4, Operand(LR));
__ TransitionGeneratedToNative(R8, FPREG, R9 /*volatile*/, NOTFP);
__ blx(R8);
__ TransitionNativeToGenerated(R9 /*volatile*/, NOTFP);
__ bx(R4);
}
void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) { void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
__ EnterFrame(1 << FP | 1 << LR, 0); __ EnterFrame(1 << FP | 1 << LR, 0);
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);
@ -3200,7 +3232,7 @@ void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
__ CallRuntime(kUnlinkedCallRuntimeEntry, 3); __ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
__ Drop(2); __ Drop(2);
__ Pop(CODE_REG); // result = stub __ Pop(CODE_REG); // result = stub
__ Pop(R9); // result = IC __ Pop(R9); // result = IC
__ Pop(R0); // Restore receiver. __ Pop(R0); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();
@ -3242,7 +3274,7 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
__ CallRuntime(kSingleTargetMissRuntimeEntry, 2); __ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
__ Drop(1); __ Drop(1);
__ Pop(CODE_REG); // result = stub __ Pop(CODE_REG); // result = stub
__ Pop(R9); // result = IC __ Pop(R9); // result = IC
__ Pop(R0); // Restore receiver. __ Pop(R0); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();
@ -3266,7 +3298,7 @@ void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
__ CallRuntime(kMonomorphicMissRuntimeEntry, 2); __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
__ Drop(1); __ Drop(1);
__ Pop(CODE_REG); // result = stub __ Pop(CODE_REG); // result = stub
__ Pop(R9); // result = IC __ Pop(R9); // result = IC
__ Pop(R0); // Restore receiver. __ Pop(R0); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();

View file

@ -236,6 +236,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);
__ mov(CSP, SP); __ mov(CSP, SP);
// Set the execution state to VM while waiting for the safepoint to end.
// This isn't strictly necessary but enables tests to check that we're not
// in native code anymore. See tests/ffi/function_gc_test.dart for example.
__ LoadImmediate(R0, target::Thread::vm_execution_state());
__ str(R0, Address(THR, target::Thread::execution_state_offset()));
__ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread())); __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ blr(R0); __ blr(R0);
__ mov(SP, CALLEE_SAVED_TEMP); __ mov(SP, CALLEE_SAVED_TEMP);
@ -245,6 +252,40 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ Ret(); __ Ret();
} }
// Calls native code within a safepoint.
//
// On entry:
// R8: target to call
// Stack: set up for native call (SP), aligned, CSP < SP
//
// On exit:
// R19: clobbered, although normally callee-saved
// Stack: preserved, CSP == SP
void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
Assembler* assembler) {
COMPILE_ASSERT((1 << R19) & kAbiPreservedCpuRegs);
__ mov(R19, LR);
__ TransitionGeneratedToNative(R8, FPREG, R9 /*volatile*/);
__ mov(CSP, SP);
#if defined(DEBUG)
// Check CSP alignment.
__ andi(R10 /*volatile*/, SP,
Immediate(~(OS::ActivationFrameAlignment() - 1)));
__ cmp(R10, Operand(SP));
Label done;
__ b(&done, EQ);
__ Breakpoint();
__ Bind(&done);
#endif
__ blr(R8);
__ mov(SP, CSP);
__ TransitionNativeToGenerated(R9);
__ ret(R19);
}
void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) { void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
__ EnterFrame(0); __ EnterFrame(0);
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);
@ -3279,7 +3320,7 @@ void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
__ CallRuntime(kUnlinkedCallRuntimeEntry, 3); __ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
__ Drop(2); __ Drop(2);
__ Pop(CODE_REG); // result = stub __ Pop(CODE_REG); // result = stub
__ Pop(R5); // result = IC __ Pop(R5); // result = IC
__ Pop(R0); // Restore receiver. __ Pop(R0); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();
@ -3322,7 +3363,7 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
__ CallRuntime(kSingleTargetMissRuntimeEntry, 2); __ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
__ Drop(1); __ Drop(1);
__ Pop(CODE_REG); // result = stub __ Pop(CODE_REG); // result = stub
__ Pop(R5); // result = IC __ Pop(R5); // result = IC
__ Pop(R0); // Restore receiver. __ Pop(R0); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();
@ -3346,7 +3387,7 @@ void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
__ CallRuntime(kMonomorphicMissRuntimeEntry, 2); __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
__ Drop(1); __ Drop(1);
__ Pop(CODE_REG); // result = stub __ Pop(CODE_REG); // result = stub
__ Pop(R5); // result = IC __ Pop(R5); // result = IC
__ Pop(R0); // Restore receiver. __ Pop(R0); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();

View file

@ -162,6 +162,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ EnterFrame(0); __ EnterFrame(0);
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);
// Set the execution state to VM while waiting for the safepoint to end.
// This isn't strictly necessary but enables tests to check that we're not
// in native code anymore. See tests/ffi/function_gc_test.dart for example.
__ movl(Address(THR, target::Thread::execution_state_offset()),
Immediate(target::Thread::vm_execution_state()));
__ movl(EAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread())); __ movl(EAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ call(EAX); __ call(EAX);
__ LeaveFrame(); __ LeaveFrame();
@ -172,6 +179,26 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ ret(); __ ret();
} }
// Calls a native function inside a safepoint.
//
// On entry:
// Stack: set up for native call
// EAX: target to call
//
// On exit:
// Stack: preserved
// EBX: clobbered (even though it's normally callee-saved)
void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
Assembler* assembler) {
__ popl(EBX);
__ TransitionGeneratedToNative(EAX, FPREG, ECX /*volatile*/);
__ call(EAX);
__ TransitionNativeToGenerated(ECX /*volatile*/);
__ jmp(EBX);
}
void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) { void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
__ EnterFrame(0); __ EnterFrame(0);
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);

View file

@ -223,6 +223,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ EnterFrame(0); __ EnterFrame(0);
__ ReserveAlignedFrameSpace(0); __ ReserveAlignedFrameSpace(0);
// Set the execution state to VM while waiting for the safepoint to end.
// This isn't strictly necessary but enables tests to check that we're not
// in native code anymore. See tests/ffi/function_gc_test.dart for example.
__ movq(Address(THR, target::Thread::execution_state_offset()),
Immediate(target::Thread::vm_execution_state()));
__ movq(RAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread())); __ movq(RAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ CallCFunction(RAX); __ CallCFunction(RAX);
__ LeaveFrame(); __ LeaveFrame();
@ -245,6 +252,29 @@ void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
__ ret(); __ ret();
} }
// Calls native code within a safepoint.
//
// On entry:
// Stack: arguments set up and aligned for native call, excl. shadow space
// RBX = target address to call
//
// On exit:
// Stack pointer lowered by shadow space
// RBX, R12 clobbered
void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
Assembler* assembler) {
__ TransitionGeneratedToNative(RBX, FPREG);
__ popq(R12);
__ CallCFunction(RBX);
__ TransitionNativeToGenerated();
// Faster than jmp because it doesn't confuse the branch predictor.
__ pushq(R12);
__ ret();
}
// RBX: The extracted method. // RBX: The extracted method.
// RDX: The type_arguments_field_offset (or 0) // RDX: The type_arguments_field_offset (or 0)
void StubCodeCompiler::GenerateBuildMethodExtractorStub( void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@ -3284,7 +3314,7 @@ void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
__ popq(RBX); __ popq(RBX);
__ popq(RBX); __ popq(RBX);
__ popq(CODE_REG); // result = stub __ popq(CODE_REG); // result = stub
__ popq(RBX); // result = IC __ popq(RBX); // result = IC
__ popq(RDX); // Restore receiver. __ popq(RDX); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();
@ -3326,7 +3356,7 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
__ CallRuntime(kSingleTargetMissRuntimeEntry, 2); __ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
__ popq(RBX); __ popq(RBX);
__ popq(CODE_REG); // result = stub __ popq(CODE_REG); // result = stub
__ popq(RBX); // result = IC __ popq(RBX); // result = IC
__ popq(RDX); // Restore receiver. __ popq(RDX); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();
@ -3350,7 +3380,7 @@ void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
__ CallRuntime(kMonomorphicMissRuntimeEntry, 2); __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
__ popq(RBX); __ popq(RBX);
__ popq(CODE_REG); // result = stub __ popq(CODE_REG); // result = stub
__ popq(RBX); // result = IC __ popq(RBX); // result = IC
__ popq(RDX); // Restore receiver. __ popq(RDX); // Restore receiver.
__ LeaveStubFrame(); __ LeaveStubFrame();

View file

@ -371,6 +371,7 @@ class CallingConventions {
static constexpr Register kFirstNonArgumentRegister = R8; static constexpr Register kFirstNonArgumentRegister = R8;
static constexpr Register kSecondNonArgumentRegister = R9; static constexpr Register kSecondNonArgumentRegister = R9;
static constexpr Register kFirstCalleeSavedCpuReg = NOTFP; static constexpr Register kFirstCalleeSavedCpuReg = NOTFP;
static constexpr Register kSecondCalleeSavedCpuReg = R4;
static constexpr Register kStackPointerRegister = SPREG; static constexpr Register kStackPointerRegister = SPREG;
}; };

View file

@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a // for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file. // BSD-style license that can be found in the LICENSE file.
#include <functional>
#include "include/dart_native_api.h" #include "include/dart_native_api.h"
#include "platform/assert.h" #include "platform/assert.h"
@ -241,14 +243,47 @@ DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() {
#endif // defined(DART_PRECOMPILED_RUNTIME) #endif // defined(DART_PRECOMPILED_RUNTIME)
} }
DART_EXPORT void Dart_ExecuteInternalCommand(const char* command) { struct RunInSafepointAndRWCodeArgs {
if (!FLAG_enable_testing_pragmas) return; Isolate* isolate;
std::function<void()>* callback;
};
DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg) {
if (!FLAG_enable_testing_pragmas) return nullptr;
TransitionNativeToVM _(Thread::Current());
if (!strcmp(command, "gc-on-next-allocation")) { if (!strcmp(command, "gc-on-next-allocation")) {
TransitionNativeToVM _(Thread::Current());
Isolate::Current()->heap()->CollectOnNextAllocation(); Isolate::Current()->heap()->CollectOnNextAllocation();
return nullptr;
} else if (!strcmp(command, "gc-now")) { } else if (!strcmp(command, "gc-now")) {
Isolate::Current()->heap()->CollectAllGarbage(Heap::kDebugging); TransitionNativeToVM _(Thread::Current());
Isolate::Current()->heap()->CollectAllGarbage();
return nullptr;
} else if (!strcmp(command, "is-mutator-in-native")) {
Isolate* const isolate = reinterpret_cast<Isolate*>(arg);
if (isolate->mutator_thread()->execution_state() ==
Thread::kThreadInNative) {
return arg;
} else {
return nullptr;
}
} else if (!strcmp(command, "run-in-safepoint-and-rw-code")) {
const RunInSafepointAndRWCodeArgs* const args =
reinterpret_cast<RunInSafepointAndRWCodeArgs*>(arg);
Thread::EnterIsolateAsHelper(args->isolate, Thread::TaskKind::kUnknownTask);
Thread* const thread = Thread::Current();
{
SafepointOperationScope scope(thread);
args->isolate->heap()->WriteProtectCode(/*read_only=*/false);
(*args->callback)();
args->isolate->heap()->WriteProtectCode(/*read_only=*/true);
}
Thread::ExitIsolateAsHelper();
return nullptr;
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }

View file

@ -3012,7 +3012,8 @@ extern "C" void DFLRT_ExitSafepoint(NativeArguments __unusable_) {
CHECK_STACK_ALIGNMENT; CHECK_STACK_ALIGNMENT;
Thread* thread = Thread::Current(); Thread* thread = Thread::Current();
ASSERT(thread->top_exit_frame_info() != 0); ASSERT(thread->top_exit_frame_info() != 0);
ASSERT(thread->execution_state() == Thread::kThreadInNative);
ASSERT(thread->execution_state() == Thread::kThreadInVM);
thread->ExitSafepoint(); thread->ExitSafepoint();
} }
DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepoint, 0, false, &DFLRT_ExitSafepoint); DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepoint, 0, false, &DFLRT_ExitSafepoint);

View file

@ -1853,8 +1853,16 @@ SwitchDispatch:
Exit(thread, FP, SP, pc); Exit(thread, FP, SP, pc);
{ {
TransitionGeneratedToNative transition(thread); thread->set_execution_state(Thread::kThreadInNative);
thread->EnterSafepoint();
FfiTrampolineCall(marshalled_args_data); FfiTrampolineCall(marshalled_args_data);
// We set the execution state to kThreadInVM before waiting for the
// safepoint to end for the benefit of tests like ffi/function_gc_test.
thread->set_execution_state(Thread::kThreadInVM);
thread->ExitSafepoint();
thread->set_execution_state(Thread::kThreadInGenerated);
} }
const Representation result_rep = sig_desc.ResultRepresentation(); const Representation result_rep = sig_desc.ResultRepresentation();

View file

@ -78,7 +78,8 @@ namespace dart {
V(OneArgOptimizedCheckInlineCacheWithExactnessCheck) \ V(OneArgOptimizedCheckInlineCacheWithExactnessCheck) \
V(EnterSafepoint) \ V(EnterSafepoint) \
V(ExitSafepoint) \ V(ExitSafepoint) \
V(VerifyCallback) V(VerifyCallback) \
V(CallNativeThroughSafepoint)
#else #else
#define VM_STUB_CODE_LIST(V) \ #define VM_STUB_CODE_LIST(V) \

View file

@ -123,7 +123,9 @@ class Zone;
V(RawCode*, lazy_specialize_type_test_stub_, \ V(RawCode*, lazy_specialize_type_test_stub_, \
StubCode::LazySpecializeTypeTest().raw(), NULL) \ StubCode::LazySpecializeTypeTest().raw(), NULL) \
V(RawCode*, enter_safepoint_stub_, StubCode::EnterSafepoint().raw(), NULL) \ V(RawCode*, enter_safepoint_stub_, StubCode::EnterSafepoint().raw(), NULL) \
V(RawCode*, exit_safepoint_stub_, StubCode::ExitSafepoint().raw(), NULL) V(RawCode*, exit_safepoint_stub_, StubCode::ExitSafepoint().raw(), NULL) \
V(RawCode*, call_native_through_safepoint_stub_, \
StubCode::CallNativeThroughSafepoint().raw(), NULL)
#endif #endif
@ -168,7 +170,9 @@ class Zone;
0) \ 0) \
V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0) \ V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0) \
V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0) \ V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0) \
V(uword, verify_callback_entry_, StubCode::VerifyCallback().EntryPoint(), 0) V(uword, verify_callback_entry_, StubCode::VerifyCallback().EntryPoint(), 0) \
V(uword, call_native_through_safepoint_entry_point_, \
StubCode::CallNativeThroughSafepoint().EntryPoint(), 0)
#endif #endif
#define CACHED_ADDRESSES_LIST(V) \ #define CACHED_ADDRESSES_LIST(V) \

View file

@ -6,6 +6,7 @@
#define RUNTIME_VM_VIRTUAL_MEMORY_H_ #define RUNTIME_VM_VIRTUAL_MEMORY_H_
#include "platform/utils.h" #include "platform/utils.h"
#include "vm/flags.h"
#include "vm/globals.h" #include "vm/globals.h"
#include "vm/memory_region.h" #include "vm/memory_region.h"
@ -32,6 +33,9 @@ class VirtualMemory {
static void Init(); static void Init();
// Returns true if dual mapping is enabled.
static bool DualMappingEnabled();
bool Contains(uword addr) const { return region_.Contains(addr); } bool Contains(uword addr) const { return region_.Contains(addr); }
bool ContainsAlias(uword addr) const { bool ContainsAlias(uword addr) const {
return (AliasOffset() != 0) && alias_.Contains(addr); return (AliasOffset() != 0) && alias_.Contains(addr);

View file

@ -57,6 +57,10 @@ static void Unmap(zx_handle_t vmar, uword start, uword end) {
} }
} }
bool VirtualMemory::DualMappingEnabled() {
return FLAG_dual_map_code;
}
VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size, VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
intptr_t alignment, intptr_t alignment,
bool is_executable, bool is_executable,

View file

@ -83,6 +83,10 @@ void VirtualMemory::Init() {
#endif // defined(DUAL_MAPPING_SUPPORTED) #endif // defined(DUAL_MAPPING_SUPPORTED)
} }
bool VirtualMemory::DualMappingEnabled() {
return FLAG_dual_map_code;
}
static void unmap(uword start, uword end) { static void unmap(uword start, uword end) {
ASSERT(start <= end); ASSERT(start <= end);
uword size = end - start; uword size = end - start;

View file

@ -24,6 +24,10 @@ void VirtualMemory::Init() {
page_size_ = info.dwPageSize; page_size_ = info.dwPageSize;
} }
bool VirtualMemory::DualMappingEnabled() {
return false;
}
VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size, VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
intptr_t alignment, intptr_t alignment,
bool is_executable, bool is_executable,

View file

@ -4,6 +4,8 @@
// //
// VMOptions=--deterministic --optimization-counter-threshold=500 --enable-testing-pragmas // VMOptions=--deterministic --optimization-counter-threshold=500 --enable-testing-pragmas
// VMOptions=--deterministic --optimization-counter-threshold=-1 --enable-testing-pragmas // VMOptions=--deterministic --optimization-counter-threshold=-1 --enable-testing-pragmas
// VMOptions=--deterministic --optimization-counter-threshold=500 --enable-testing-pragmas --no-dual-map-code --write-protect-code
// VMOptions=--deterministic --optimization-counter-threshold=-1 --enable-testing-pragmas --no-dual-map-code --write-protect-code
// //
// Dart test program for stress-testing boxing and GC in return paths from FFI // Dart test program for stress-testing boxing and GC in return paths from FFI
// trampolines. // trampolines.
@ -25,6 +27,7 @@ main() async {
testBoxPointer(); testBoxPointer();
testAllocateInNative(); testAllocateInNative();
testRegress37069(); testRegress37069();
testWriteProtection();
} }
typedef NativeNullaryOp64 = ffi.Int64 Function(); typedef NativeNullaryOp64 = ffi.Int64 Function();
@ -106,3 +109,11 @@ final regress37069 = ffiTestFunctions
void testRegress37069() { void testRegress37069() {
regress37069(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); regress37069(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
} }
final unprotectCode = ffiTestFunctions
.lookupFunction<NativeNullaryOp32, NullaryOp>("UnprotectCode");
void testWriteProtection() {
int result = unprotectCode();
Expect.equals(result, 0);
}

View file

@ -7,6 +7,8 @@
// VMOptions= // VMOptions=
// VMOptions=--deterministic --optimization-counter-threshold=10 // VMOptions=--deterministic --optimization-counter-threshold=10
// VMOptions=--use-slow-path // VMOptions=--use-slow-path
// VMOptions=--write-protect-code --no-dual-map-code
// VMOptions=--write-protect-code --no-dual-map-code --use-slow-path
// SharedObjects=ffi_test_functions // SharedObjects=ffi_test_functions
library FfiTest; library FfiTest;