[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>
#else
#include <unistd.h>
// Only OK to use here because this is test code.
#include <thread>
#endif
#include <setjmp.h>
@ -26,6 +29,14 @@
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.
@ -481,30 +492,30 @@ DART_EXPORT float InventFloatValue() {
// Functions for stress-testing.
DART_EXPORT int64_t MinInt64() {
Dart_ExecuteInternalCommand("gc-on-next-allocation");
Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
return 0x8000000000000000;
}
DART_EXPORT int64_t MinInt32() {
Dart_ExecuteInternalCommand("gc-on-next-allocation");
Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
return 0x80000000;
}
DART_EXPORT double SmallDouble() {
Dart_ExecuteInternalCommand("gc-on-next-allocation");
Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
return 0x80000000 * -1.0;
}
// Requires boxing on 32-bit and 64-bit systems, even if the top 32-bits are
// truncated.
DART_EXPORT void* LargePointer() {
Dart_ExecuteInternalCommand("gc-on-next-allocation");
Dart_ExecuteInternalCommand("gc-on-next-allocation", nullptr);
uint64_t origin = 0x8100000082000000;
return reinterpret_cast<void*>(origin);
}
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
@ -520,20 +531,57 @@ DART_EXPORT void Regress37069(uint64_t a,
uint64_t i,
uint64_t j,
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.
#define CHECK(X) \
if (!(X)) { \
fprintf(stderr, "%s\n", "Check failed: " #X); \
return 1; \
}
#define CHECK_EQ(X, Y) CHECK((X) == (Y))
// Sanity test.
DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) {
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.
*/
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 */

View file

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

View file

@ -4400,6 +4400,15 @@ class FfiCallInstr : public Definition {
virtual Representation RequiredInputRepresentation(intptr_t idx) 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
private:

View file

@ -1036,13 +1036,28 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
RawPcDescriptors::Kind::kOther, locs());
// Update information in the thread object and enter a safepoint.
__ TransitionGeneratedToNative(branch, FPREG, saved_fp,
locs()->temp(1).reg());
const Register tmp = 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.
__ TransitionNativeToGenerated(saved_fp, locs()->temp(1).reg());
// Update information in the thread object and leave the safepoint.
__ 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
// moving, so the GOP could have been relocated).

View file

@ -912,20 +912,35 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ StoreToOffset(temp, FPREG, kSavedCallerPcSlotFromFp * kWordSize);
// Update information in the thread object and enter a safepoint.
__ TransitionGeneratedToNative(branch, FPREG, temp);
if (CanExecuteGeneratedCodeInSafepoint()) {
// 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
// the stack limit to the top of the stack.
__ mov(CSP, SP);
// We are entering runtime code, so the C stack pointer must be restored
// from the stack limit to the top of the stack.
__ mov(CSP, SP);
__ blr(branch);
__ blr(branch);
// Restore the Dart stack pointer.
__ mov(SP, CSP);
// Restore the Dart stack pointer.
__ mov(SP, CSP);
// Update information in the thread object and leave the safepoint.
__ TransitionNativeToGenerated(temp);
// Update information in the thread object and leave the safepoint.
__ 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.
__ ldr(BARRIER_MASK,

View file

@ -953,8 +953,24 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ popl(tmp);
__ movl(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), tmp);
__ TransitionGeneratedToNative(branch, FPREG, tmp);
__ call(branch);
if (CanExecuteGeneratedCodeInSafepoint()) {
__ 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 "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));
}
__ TransitionNativeToGenerated(tmp);
// Leave dummy exit frame.
__ LeaveFrame();
@ -5610,7 +5624,7 @@ static void EmitShiftInt64ByConstant(FlowGraphCompiler* compiler,
switch (op_kind) {
case Token::kSHR: {
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.
if (shift > 32) {
__ sarl(left_lo, compiler::Immediate(shift > 63 ? 31 : shift - 32));
@ -5658,9 +5672,9 @@ static void EmitShiftInt64ByECX(FlowGraphCompiler* compiler,
__ Bind(&large_shift);
// 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_lo, ECX); // Shift count: CL % 32.
__ sarl(left_lo, ECX); // Shift count: CL % 32.
break;
}
case Token::kSHL: {

View file

@ -965,13 +965,29 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
RawPcDescriptors::Kind::kOther, locs());
__ movq(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
// Update information in the thread object and enter a safepoint.
__ TransitionGeneratedToNative(target_address, FPREG);
if (CanExecuteGeneratedCodeInSafepoint()) {
// 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.
__ TransitionNativeToGenerated();
// Update information in the thread object and leave the safepoint.
__ 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.
__ LeaveDartFrame(compiler::kRestoreCallerPP);

View file

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

View file

@ -660,6 +660,7 @@ class Thread : public AllStatic {
static uword safepoint_state_acquired();
static word execution_state_offset();
static uword vm_execution_state();
static uword native_execution_state();
static uword generated_execution_state();
static word stack_overflow_flags_offset();
@ -695,6 +696,8 @@ class Thread : public AllStatic {
static word deoptimize_stub_offset();
static word enter_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)
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 SubtypeTestCache_cache_offset = 4;
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 =
616;
624;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
620;
628;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 112;
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 =
84;
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_true_offset = 100;
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
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 =
224;
228;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
228;
232;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
160;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
260;
268;
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_enter_safepoint_stub_offset = 180;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
632;
640;
static constexpr dart::compiler::target::word
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
Thread_fix_allocation_stub_code_offset = 120;
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 116;
static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 272;
Thread_float_absolute_address_offset = 280;
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 =
264;
272;
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 =
624;
632;
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
Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
static constexpr dart::compiler::target::word
@ -259,38 +263,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 72;
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
Thread_monomorphic_miss_entry_offset = 220;
Thread_monomorphic_miss_entry_offset = 224;
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 152;
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
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
Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
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
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_predefined_symbols_address_offset = 248;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 628;
Thread_predefined_symbols_address_offset = 256;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 636;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
636;
644;
static constexpr dart::compiler::target::word
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_overflow_flags_offset = 40;
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
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
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
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
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 =
108;
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 =
44;
static constexpr dart::compiler::target::word
Thread_verify_callback_entry_offset = 232;
static constexpr dart::compiler::target::word Thread_callback_code_offset = 640;
Thread_verify_callback_entry_offset = 236;
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 TwoByteString_data_offset = 12;
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};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
580, 584, 588, 592, 596, -1, 600, 604,
608, 612, -1, -1, -1, -1, -1, -1};
588, 592, 596, 600, 604, -1, 608, 612,
616, 620, -1, -1, -1, -1, -1, -1};
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 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 SubtypeTestCache_cache_offset = 8;
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 =
1240;
1256;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
1248;
1264;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 216;
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 =
168;
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_true_offset = 192;
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
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 =
440;
448;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
448;
456;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
312;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
512;
528;
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_enter_safepoint_stub_offset = 352;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
1272;
1288;
static constexpr dart::compiler::target::word
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
Thread_fix_allocation_stub_code_offset = 232;
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 224;
static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 536;
Thread_float_absolute_address_offset = 552;
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 =
520;
536;
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 =
1256;
1272;
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
Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
static constexpr dart::compiler::target::word
@ -614,38 +622,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 144;
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
Thread_monomorphic_miss_entry_offset = 432;
Thread_monomorphic_miss_entry_offset = 440;
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 296;
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
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
Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
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
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_predefined_symbols_address_offset = 488;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1264;
Thread_predefined_symbols_address_offset = 504;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1280;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
1280;
1296;
static constexpr dart::compiler::target::word
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_overflow_flags_offset = 80;
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
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
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
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
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 =
208;
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 =
88;
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 =
1288;
1304;
static constexpr dart::compiler::target::word TimelineStream_enabled_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};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
1152, 1160, 1168, 1176, -1, -1, 1184, 1192,
1200, 1208, 1216, -1, 1224, 1232, -1, -1};
1168, 1176, 1184, 1192, -1, -1, 1200, 1208,
1216, 1224, 1232, -1, 1240, 1248, -1, -1};
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 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 SubtypeTestCache_cache_offset = 4;
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 =
580;
588;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
584;
592;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 112;
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 =
84;
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_true_offset = 100;
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
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 =
224;
228;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
228;
232;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
160;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
260;
268;
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_enter_safepoint_stub_offset = 180;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
596;
604;
static constexpr dart::compiler::target::word
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
Thread_fix_allocation_stub_code_offset = 120;
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 116;
static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 272;
Thread_float_absolute_address_offset = 280;
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 =
264;
272;
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 =
588;
596;
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
Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
static constexpr dart::compiler::target::word
@ -969,38 +981,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 72;
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
Thread_monomorphic_miss_entry_offset = 220;
Thread_monomorphic_miss_entry_offset = 224;
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 152;
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
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
Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
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
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_predefined_symbols_address_offset = 248;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 592;
Thread_predefined_symbols_address_offset = 256;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 600;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
600;
608;
static constexpr dart::compiler::target::word
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_overflow_flags_offset = 40;
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
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
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
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
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 =
108;
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 =
44;
static constexpr dart::compiler::target::word
Thread_verify_callback_entry_offset = 232;
static constexpr dart::compiler::target::word Thread_callback_code_offset = 604;
Thread_verify_callback_entry_offset = 236;
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 TwoByteString_data_offset = 12;
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 SubtypeTestCache_cache_offset = 8;
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 =
1328;
1344;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
1336;
1352;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 216;
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 =
168;
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_true_offset = 192;
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
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 =
440;
448;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304;
static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
448;
456;
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
312;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
512;
528;
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_enter_safepoint_stub_offset = 352;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
1360;
1376;
static constexpr dart::compiler::target::word
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
Thread_fix_allocation_stub_code_offset = 232;
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 224;
static constexpr dart::compiler::target::word
Thread_float_absolute_address_offset = 536;
Thread_float_absolute_address_offset = 552;
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 =
520;
536;
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 =
1344;
1360;
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
Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
static constexpr dart::compiler::target::word
@ -1320,38 +1336,38 @@ static constexpr dart::compiler::target::word
static constexpr dart::compiler::target::word
Thread_marking_stack_block_offset = 144;
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
Thread_monomorphic_miss_entry_offset = 432;
Thread_monomorphic_miss_entry_offset = 440;
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 296;
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
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
Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
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
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_predefined_symbols_address_offset = 488;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1352;
Thread_predefined_symbols_address_offset = 504;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1368;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
1368;
1384;
static constexpr dart::compiler::target::word
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_overflow_flags_offset = 80;
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
Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
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
Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
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 =
208;
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 =
88;
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 =
1376;
1392;
static constexpr dart::compiler::target::word TimelineStream_enabled_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};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
1152, 1160, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232,
1240, 1248, 1256, 1264, -1, -1, -1, -1, 1272, 1280, 1288,
1296, 1304, 1312, 1320, -1, -1, -1, -1, -1, -1};
1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232, 1240, 1248,
1256, 1264, 1272, 1280, -1, -1, -1, -1, 1288, 1296, 1304,
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 Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;

View file

@ -167,6 +167,8 @@
NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset)) \
FIELD(Thread, execution_state_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_callers_target_code_offset)) \
FIELD(Thread, float_absolute_address_offset) \

View file

@ -291,6 +291,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ EnterFrame((1 << FP) | (1 << LR), 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()));
__ blx(R0);
__ LeaveFrame((1 << FP) | (1 << LR), 0);
@ -299,6 +306,31 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ 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) {
__ EnterFrame(1 << FP | 1 << LR, 0);
__ ReserveAlignedFrameSpace(0);
@ -3200,7 +3232,7 @@ void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
__ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
__ Drop(2);
__ Pop(CODE_REG); // result = stub
__ Pop(R9); // result = IC
__ Pop(R9); // result = IC
__ Pop(R0); // Restore receiver.
__ LeaveStubFrame();
@ -3242,7 +3274,7 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
__ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
__ Drop(1);
__ Pop(CODE_REG); // result = stub
__ Pop(R9); // result = IC
__ Pop(R9); // result = IC
__ Pop(R0); // Restore receiver.
__ LeaveStubFrame();
@ -3266,7 +3298,7 @@ void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
__ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
__ Drop(1);
__ Pop(CODE_REG); // result = stub
__ Pop(R9); // result = IC
__ Pop(R9); // result = IC
__ Pop(R0); // Restore receiver.
__ LeaveStubFrame();

View file

@ -236,6 +236,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ ReserveAlignedFrameSpace(0);
__ 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()));
__ blr(R0);
__ mov(SP, CALLEE_SAVED_TEMP);
@ -245,6 +252,40 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ 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) {
__ EnterFrame(0);
__ ReserveAlignedFrameSpace(0);
@ -3279,7 +3320,7 @@ void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
__ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
__ Drop(2);
__ Pop(CODE_REG); // result = stub
__ Pop(R5); // result = IC
__ Pop(R5); // result = IC
__ Pop(R0); // Restore receiver.
__ LeaveStubFrame();
@ -3322,7 +3363,7 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
__ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
__ Drop(1);
__ Pop(CODE_REG); // result = stub
__ Pop(R5); // result = IC
__ Pop(R5); // result = IC
__ Pop(R0); // Restore receiver.
__ LeaveStubFrame();
@ -3346,7 +3387,7 @@ void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
__ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
__ Drop(1);
__ Pop(CODE_REG); // result = stub
__ Pop(R5); // result = IC
__ Pop(R5); // result = IC
__ Pop(R0); // Restore receiver.
__ LeaveStubFrame();

View file

@ -162,6 +162,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ EnterFrame(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()));
__ call(EAX);
__ LeaveFrame();
@ -172,6 +179,26 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ 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) {
__ EnterFrame(0);
__ ReserveAlignedFrameSpace(0);

View file

@ -223,6 +223,13 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ EnterFrame(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()));
__ CallCFunction(RAX);
__ LeaveFrame();
@ -245,6 +252,29 @@ void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
__ 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.
// RDX: The type_arguments_field_offset (or 0)
void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@ -3284,7 +3314,7 @@ void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
__ popq(RBX);
__ popq(RBX);
__ popq(CODE_REG); // result = stub
__ popq(RBX); // result = IC
__ popq(RBX); // result = IC
__ popq(RDX); // Restore receiver.
__ LeaveStubFrame();
@ -3326,7 +3356,7 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
__ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
__ popq(RBX);
__ popq(CODE_REG); // result = stub
__ popq(RBX); // result = IC
__ popq(RBX); // result = IC
__ popq(RDX); // Restore receiver.
__ LeaveStubFrame();
@ -3350,7 +3380,7 @@ void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
__ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
__ popq(RBX);
__ popq(CODE_REG); // result = stub
__ popq(RBX); // result = IC
__ popq(RBX); // result = IC
__ popq(RDX); // Restore receiver.
__ LeaveStubFrame();

View file

@ -371,6 +371,7 @@ class CallingConventions {
static constexpr Register kFirstNonArgumentRegister = R8;
static constexpr Register kSecondNonArgumentRegister = R9;
static constexpr Register kFirstCalleeSavedCpuReg = NOTFP;
static constexpr Register kSecondCalleeSavedCpuReg = R4;
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
// BSD-style license that can be found in the LICENSE file.
#include <functional>
#include "include/dart_native_api.h"
#include "platform/assert.h"
@ -241,14 +243,47 @@ DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() {
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT void Dart_ExecuteInternalCommand(const char* command) {
if (!FLAG_enable_testing_pragmas) return;
struct RunInSafepointAndRWCodeArgs {
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")) {
TransitionNativeToVM _(Thread::Current());
Isolate::Current()->heap()->CollectOnNextAllocation();
return nullptr;
} 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 {
UNREACHABLE();
}

View file

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

View file

@ -1853,8 +1853,16 @@ SwitchDispatch:
Exit(thread, FP, SP, pc);
{
TransitionGeneratedToNative transition(thread);
thread->set_execution_state(Thread::kThreadInNative);
thread->EnterSafepoint();
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();

View file

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

View file

@ -123,7 +123,9 @@ class Zone;
V(RawCode*, lazy_specialize_type_test_stub_, \
StubCode::LazySpecializeTypeTest().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
@ -168,7 +170,9 @@ class Zone;
0) \
V(uword, optimize_entry_, StubCode::OptimizeFunction().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
#define CACHED_ADDRESSES_LIST(V) \

View file

@ -6,6 +6,7 @@
#define RUNTIME_VM_VIRTUAL_MEMORY_H_
#include "platform/utils.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/memory_region.h"
@ -32,6 +33,9 @@ class VirtualMemory {
static void Init();
// Returns true if dual mapping is enabled.
static bool DualMappingEnabled();
bool Contains(uword addr) const { return region_.Contains(addr); }
bool ContainsAlias(uword addr) const {
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,
intptr_t alignment,
bool is_executable,

View file

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

View file

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

View file

@ -4,6 +4,8 @@
//
// VMOptions=--deterministic --optimization-counter-threshold=500 --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
// trampolines.
@ -25,6 +27,7 @@ main() async {
testBoxPointer();
testAllocateInNative();
testRegress37069();
testWriteProtection();
}
typedef NativeNullaryOp64 = ffi.Int64 Function();
@ -106,3 +109,11 @@ final regress37069 = ffiTestFunctions
void testRegress37069() {
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=--deterministic --optimization-counter-threshold=10
// 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
library FfiTest;