12#define SHOULD_NOT_INCLUDE_RUNTIME
16#if defined(TARGET_ARCH_ARM)
45 __ LoadFromOffset(
TMP,
TMP, target::Page::original_top_offset());
55 rt.Call(kEnsureRememberedAndMarkingDeferredRuntimeEntry, 2);
68void StubCodeCompiler::GenerateCallToRuntimeStub() {
69 const intptr_t thread_offset = target::NativeArguments::thread_offset();
70 const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
71 const intptr_t argv_offset = target::NativeArguments::argv_offset();
72 const intptr_t retval_offset = target::NativeArguments::retval_offset();
74 __ ldr(
CODE_REG, Address(
THR, target::Thread::call_to_runtime_stub_offset()));
79 __ StoreToOffset(
FP,
THR, target::Thread::top_exit_frame_info_offset());
82 __ LoadImmediate(
R8, target::Thread::exit_through_runtime_call());
83 __ StoreToOffset(
R8,
THR, target::Thread::exit_through_ffi_offset());
89 __ LoadFromOffset(
R8,
THR, target::Thread::vm_tag_offset());
90 __ CompareImmediate(
R8, VMTag::kDartTagId);
92 __ Stop(
"Not coming from Dart code.");
98 __ StoreToOffset(
R9,
THR, target::Thread::vm_tag_offset());
102 ASSERT(target::NativeArguments::StructSize() == 4 * target::kWordSize);
103 __ ReserveAlignedFrameSpace(0);
108 ASSERT(thread_offset == 0 * target::kWordSize);
112 ASSERT(argc_tag_offset == 1 * target::kWordSize);
115 ASSERT(argv_offset == 2 * target::kWordSize);
119 target::frame_layout.param_end_from_fp * target::kWordSize);
121 ASSERT(retval_offset == 3 * target::kWordSize);
123 Operand(target::kWordSize));
129 __ LoadImmediate(
R2, VMTag::kDartTagId);
130 __ StoreToOffset(
R2,
THR, target::Thread::vm_tag_offset());
133 __ LoadImmediate(
R2, 0);
134 __ StoreToOffset(
R2,
THR, target::Thread::exit_through_ffi_offset());
137 __ StoreToOffset(
R2,
THR, target::Thread::top_exit_frame_info_offset());
141 if (FLAG_precompiled_mode) {
142 __ SetupGlobalPoolAndDispatchTable();
152 __ LoadImmediate(
R0, 0);
156void StubCodeCompiler::GenerateSharedStubGeneric(
157 bool save_fpu_registers,
158 intptr_t self_code_stub_offset_from_thread,
160 std::function<
void()> perform_runtime_call) {
163 RegisterSet all_registers;
164 all_registers.AddAllNonReservedRegisters(save_fpu_registers);
168 READS_RETURN_ADDRESS_FROM_LR(
__ Push(
LR));
169 __ PushRegisters(all_registers);
170 __ ldr(
CODE_REG, Address(
THR, self_code_stub_offset_from_thread));
172 perform_runtime_call();
178 __ PopRegisters(all_registers);
180 READS_RETURN_ADDRESS_FROM_LR(
__ bx(
LR));
183void StubCodeCompiler::GenerateSharedStub(
184 bool save_fpu_registers,
185 const RuntimeEntry*
target,
186 intptr_t self_code_stub_offset_from_thread,
188 bool store_runtime_result_in_result_register) {
189 ASSERT(!store_runtime_result_in_result_register || allow_return);
190 auto perform_runtime_call = [&]() {
191 if (store_runtime_result_in_result_register) {
197 if (store_runtime_result_in_result_register) {
200 Address(
FP, target::kWordSize *
205 GenerateSharedStubGeneric(save_fpu_registers,
206 self_code_stub_offset_from_thread, allow_return,
207 perform_runtime_call);
210void StubCodeCompiler::GenerateEnterSafepointStub() {
211 RegisterSet all_registers;
212 all_registers.AddAllGeneralRegisters();
213 __ PushRegisters(all_registers);
215 SPILLS_LR_TO_FRAME(
__ EnterFrame((1 <<
FP) | (1 <<
LR), 0));
216 __ ReserveAlignedFrameSpace(0);
217 __ ldr(
R0, Address(
THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
219 RESTORES_LR_FROM_FRAME(
__ LeaveFrame((1 <<
FP) | (1 <<
LR), 0));
221 __ PopRegisters(all_registers);
225static void GenerateExitSafepointStubCommon(Assembler* assembler,
226 uword runtime_entry_offset) {
227 RegisterSet all_registers;
228 all_registers.AddAllGeneralRegisters();
229 __ PushRegisters(all_registers);
231 SPILLS_LR_TO_FRAME(
__ EnterFrame((1 <<
FP) | (1 <<
LR), 0));
232 __ ReserveAlignedFrameSpace(0);
237 __ LoadImmediate(
R0, target::Thread::vm_execution_state());
238 __ str(
R0, Address(
THR, target::Thread::execution_state_offset()));
240 __ ldr(
R0, Address(
THR, runtime_entry_offset));
242 RESTORES_LR_FROM_FRAME(
__ LeaveFrame((1 <<
FP) | (1 <<
LR), 0));
244 __ PopRegisters(all_registers);
248void StubCodeCompiler::GenerateExitSafepointStub() {
249 GenerateExitSafepointStubCommon(
250 assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
253void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub() {
254 GenerateExitSafepointStubCommon(
256 kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
268void StubCodeCompiler::GenerateCallNativeThroughSafepointStub() {
272 SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
__ mov(
R4, Operand(
LR)));
274 __ LoadImmediate(
R9, target::Thread::exit_through_ffi());
280 __ TransitionNativeToGenerated(
R9 ,
NOTFP,
289 compiler::Label skip_reloc;
291 InsertBSSRelocation(relocation);
292 __ Bind(&skip_reloc);
300 __ ldr(dst, compiler::Address(tmp));
304 __ add(tmp, tmp, compiler::Operand(dst));
308 __ ldr(dst, compiler::Address(tmp));
311void StubCodeCompiler::GenerateLoadFfiCallbackMetadataRuntimeFunction(
312 uword function_index,
318 const intptr_t code_size =
__ CodeSize();
325 __ LoadFromOffset(dst, dst,
329void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
330#if defined(USING_SIMULATOR) && !defined(DART_PRECOMPILER)
348 FfiCallbackMetadata::kNativeCallbackTrampolineSize *
353 const intptr_t shared_stub_start =
__ CodeSize();
356 COMPILE_ASSERT(FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta == 4);
358 __ PushList((1 <<
LR) | (1 <<
THR) | (1 <<
R4) | (1 <<
R5)));
367 RegisterSet argument_registers;
368 argument_registers.AddAllArgumentRegisters();
369 __ PushRegisters(argument_registers);
381 __ sub(
SP,
SP, Operand(compiler::target::kWordSize));
386 __ sub(
SP,
SP, Operand(compiler::target::kWordSize));
389 __ EnterFrame(1 <<
FP, 0);
390 __ ReserveAlignedFrameSpace(0);
392 GenerateLoadFfiCallbackMetadataRuntimeFunction(
398 __ LeaveFrame(1 <<
FP);
407 __ PopRegisters(argument_registers);
414 __ cmp(
THR, Operand(0));
433 __ EnterFullSafepoint(
R4,
R5);
449 __ EnterFrame(1 <<
FP, 0);
450 __ ReserveAlignedFrameSpace(0);
452 GenerateLoadFfiCallbackMetadataRuntimeFunction(
457 __ LeaveFrame(1 <<
FP);
463 __ PopList((1 <<
PC) | (1 <<
THR) | (1 <<
R4) | (1 <<
R5));
466 FfiCallbackMetadata::kNativeCallbackSharedStubSize);
477void StubCodeCompiler::GenerateDispatchTableNullErrorStub() {
481 __ CallRuntime(kDispatchTableNullErrorRuntimeEntry, 1);
486void StubCodeCompiler::GenerateRangeError(
bool with_fpu_regs) {
487 auto perform_runtime_call = [&]() {
489 __ PushRegistersInOrder(
491 __ CallRuntime(kRangeErrorRuntimeEntry, 2);
495 GenerateSharedStubGeneric(
498 ? target::Thread::range_error_shared_with_fpu_regs_stub_offset()
499 : target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
500 false, perform_runtime_call);
503void StubCodeCompiler::GenerateWriteError(
bool with_fpu_regs) {
504 auto perform_runtime_call = [&]() {
505 __ CallRuntime(kWriteErrorRuntimeEntry, 2);
509 GenerateSharedStubGeneric(
512 ? target::Thread::write_error_shared_with_fpu_regs_stub_offset()
513 : target::Thread::write_error_shared_without_fpu_regs_stub_offset(),
514 false, perform_runtime_call);
523static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
525 const intptr_t thread_offset = target::NativeArguments::thread_offset();
526 const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
527 const intptr_t argv_offset = target::NativeArguments::argv_offset();
528 const intptr_t retval_offset = target::NativeArguments::retval_offset();
534 __ StoreToOffset(
FP,
THR, target::Thread::top_exit_frame_info_offset());
537 __ LoadImmediate(
R8, target::Thread::exit_through_runtime_call());
538 __ StoreToOffset(
R8,
THR, target::Thread::exit_through_ffi_offset());
544 __ LoadFromOffset(
R8,
THR, target::Thread::vm_tag_offset());
545 __ CompareImmediate(
R8, VMTag::kDartTagId);
547 __ Stop(
"Not coming from Dart code.");
553 __ StoreToOffset(
R9,
THR, target::Thread::vm_tag_offset());
558 __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
563 ASSERT(thread_offset == 0 * target::kWordSize);
567 ASSERT(argc_tag_offset == 1 * target::kWordSize);
570 ASSERT(argv_offset == 2 * target::kWordSize);
574 ASSERT(retval_offset == 3 * target::kWordSize);
576 Operand((target::frame_layout.param_end_from_fp + 1) *
591 __ LoadImmediate(
R2, VMTag::kDartTagId);
592 __ StoreToOffset(
R2,
THR, target::Thread::vm_tag_offset());
595 __ LoadImmediate(
R2, 0);
596 __ StoreToOffset(
R2,
THR, target::Thread::exit_through_ffi_offset());
599 __ StoreToOffset(
R2,
THR, target::Thread::top_exit_frame_info_offset());
603 if (FLAG_precompiled_mode) {
604 __ SetupGlobalPoolAndDispatchTable();
611void StubCodeCompiler::GenerateCallNoScopeNativeStub() {
612 GenerateCallNativeWithWrapperStub(
615 target::Thread::no_scope_native_wrapper_entry_point_offset()));
618void StubCodeCompiler::GenerateCallAutoScopeNativeStub() {
619 GenerateCallNativeWithWrapperStub(
622 target::Thread::auto_scope_native_wrapper_entry_point_offset()));
631void StubCodeCompiler::GenerateCallBootstrapNativeStub() {
632 GenerateCallNativeWithWrapperStub(
635 target::Thread::bootstrap_native_wrapper_entry_point_offset()));
640void StubCodeCompiler::GenerateCallStaticFunctionStub() {
645 __ LoadImmediate(
R0, 0);
647 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
654 __ Branch(FieldAddress(
R0, target::Code::entry_point_offset()));
660void StubCodeCompiler::GenerateFixCallersTargetStub() {
662 __ BranchOnMonomorphicCheckedEntryJIT(&monomorphic);
668 Address(
THR, target::Thread::fix_callers_target_code_offset()));
673 __ LoadImmediate(
R0, 0);
675 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
682 __ Branch(FieldAddress(
R0, target::Code::entry_point_offset()));
684 __ Bind(&monomorphic);
689 Address(
THR, target::Thread::fix_callers_target_code_offset()));
693 __ LoadImmediate(
R1, 0);
697 __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
704 __ Branch(FieldAddress(
710void StubCodeCompiler::GenerateFixAllocationStubTargetStub() {
715 Address(
THR, target::Thread::fix_allocation_stub_code_offset()));
718 __ LoadImmediate(
R0, 0);
720 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
727 __ Branch(FieldAddress(
R0, target::Code::entry_point_offset()));
732void StubCodeCompiler::GenerateFixParameterizedAllocationStubTargetStub() {
737 Address(
THR, target::Thread::fix_allocation_stub_code_offset()));
742 __ LoadImmediate(
R0, 0);
744 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
753 __ Branch(FieldAddress(
R0, target::Code::entry_point_offset()));
759static void PushArrayOfArguments(Assembler* assembler) {
769 target::frame_layout.param_end_from_fp * target::kWordSize);
812static void GenerateDeoptimizationSequence(Assembler* assembler,
816 __ EnterDartFrame(0);
817 __ LoadPoolPointer();
821 const intptr_t saved_result_slot_from_fp =
822 target::frame_layout.first_local_from_fp + 1 -
824 const intptr_t saved_exception_slot_from_fp =
825 target::frame_layout.first_local_from_fp + 1 -
827 const intptr_t saved_stacktrace_slot_from_fp =
828 target::frame_layout.first_local_from_fp + 1 -
838 __ ldr(
IP, Address(
FP, 2 * target::kWordSize));
840 }
else if (i ==
SP) {
859 LeafRuntimeScope rt(assembler,
864 __ mov(
R1, Operand(is_lazy ? 1 : 0));
865 rt.Call(kDeoptimizeCopyFrameRuntimeEntry, 2);
871 __ ldr(
R1, Address(
FP, saved_result_slot_from_fp * target::kWordSize));
874 __ ldr(
R1, Address(
FP, saved_exception_slot_from_fp * target::kWordSize));
875 __ ldr(
R2, Address(
FP, saved_stacktrace_slot_from_fp * target::kWordSize));
878 __ RestoreCodePointer();
893 LeafRuntimeScope rt(assembler,
896 rt.Call(kDeoptimizeFillFrameRuntimeEntry, 1);
900 __ ldr(
R1, Address(
FP, target::frame_layout.first_local_from_fp *
904 __ ldr(
R1, Address(
FP, target::frame_layout.first_local_from_fp *
906 __ ldr(
R2, Address(
FP, (target::frame_layout.first_local_from_fp - 1) *
910 __ RestoreCodePointer();
927 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
953 __ CallRuntime(kReThrowRuntimeEntry, 3);
959void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub() {
966 Address(
THR, target::Thread::lazy_deopt_from_return_stub_offset()));
973void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub() {
980 Address(
THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
985void StubCodeCompiler::GenerateDeoptimizeStub() {
987 __ ldr(
CODE_REG, Address(
THR, target::Thread::deoptimize_stub_offset()));
993static void GenerateNoSuchMethodDispatcherBody(Assembler* assembler) {
998 target::CallSiteData::arguments_descriptor_offset()));
1002 target::ArgumentsDescriptor::size_offset()));
1004 __ ldr(
R8, Address(
IP, target::frame_layout.param_end_from_fp *
1005 target::kWordSize));
1006 __ LoadImmediate(
IP, 0);
1014 target::ArgumentsDescriptor::type_args_len_offset()));
1015 __ cmp(
R3, Operand(0));
1020 PushArrayOfArguments(assembler);
1021 const intptr_t kNumArgs = 4;
1022 __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
1025 __ LeaveStubFrame();
1029static void GenerateDispatcherCode(Assembler* assembler,
1030 Label* call_target_function) {
1031 __ Comment(
"NoSuchMethodDispatch");
1035 __ b(call_target_function,
NE);
1037 GenerateNoSuchMethodDispatcherBody(assembler);
1043void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub() {
1044 GenerateNoSuchMethodDispatcherBody(
assembler);
1056void StubCodeCompiler::GenerateAllocateArrayStub() {
1057 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1066 __ b(&slow_case,
NE);
1069 const intptr_t max_len =
1071 __ CompareImmediate(
R3, max_len);
1072 __ b(&slow_case,
HI);
1074 const intptr_t
cid = kArrayCid;
1077 const intptr_t fixed_size_plus_alignment_padding =
1078 target::Array::header_size() +
1080 __ LoadImmediate(
R9, fixed_size_plus_alignment_padding);
1088 Address(
THR, target::Thread::top_offset()));
1091 __ b(&slow_case,
CS);
1097 __ ldr(
TMP, Address(
THR, target::Thread::end_offset()));
1099 __ b(&slow_case,
CS);
1104 __ str(
R3, Address(
THR, target::Thread::top_offset()));
1113 const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
1116 __ CompareImmediate(
R9, target::UntaggedObject::kSizeTagMaxSizeTag);
1118 __ mov(
R8, Operand(0),
HI);
1124 __ LoadImmediate(
TMP, tags);
1127 target::Array::tags_offset()));
1133 __ StoreIntoObjectNoBarrier(
1136 target::Array::type_arguments_offset()),
1142 target::Array::length_offset()),
1161 __ Bind(&slow_case);
1166 __ EnterStubFrame();
1167 __ LoadImmediate(
TMP, 0);
1172 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
1184 __ LeaveStubFrame();
1189void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub() {
1191 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1197 __ Bind(&slow_case);
1201 GenerateSharedStub(
true, &kAllocateMintRuntimeEntry,
1202 target::Thread::allocate_mint_with_fpu_regs_stub_offset(),
1208void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub() {
1210 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1216 __ Bind(&slow_case);
1221 false, &kAllocateMintRuntimeEntry,
1222 target::Thread::allocate_mint_without_fpu_regs_stub_offset(),
1234void StubCodeCompiler::GenerateInvokeDartCodeStub() {
1235 SPILLS_LR_TO_FRAME(
__ EnterFrame((1 <<
FP) | (1 <<
LR), 0));
1238 __ ldr(
IP, Address(
R3, target::Thread::invoke_dart_code_stub_offset()));
1241 __ PushNativeCalleeSavedRegisters();
1248#if defined(USING_SHADOW_CALL_STACK)
1253 __ LoadFromOffset(
R9,
THR, target::Thread::vm_tag_offset());
1258 __ LoadFromOffset(
R4,
THR, target::Thread::top_resource_offset());
1260 __ LoadImmediate(
R8, 0);
1261 __ StoreToOffset(
R8,
THR, target::Thread::top_resource_offset());
1263 __ LoadFromOffset(
R8,
THR, target::Thread::exit_through_ffi_offset());
1265 __ LoadImmediate(
R8, 0);
1266 __ StoreToOffset(
R8,
THR, target::Thread::exit_through_ffi_offset());
1268 __ LoadFromOffset(
R9,
THR, target::Thread::top_exit_frame_info_offset());
1269 __ StoreToOffset(
R8,
THR, target::Thread::top_exit_frame_info_offset());
1273#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
1274 ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -27);
1276 ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -28);
1280 __ EmitEntryFrameVerification(
R9);
1284 __ LoadImmediate(
R9, VMTag::kDartTagId);
1285 __ StoreToOffset(
R9,
THR, target::Thread::vm_tag_offset());
1292 FieldAddress(
R4, target::ArgumentsDescriptor::type_args_len_offset()));
1293 __ ldr(
R9, FieldAddress(
R4, target::ArgumentsDescriptor::count_offset()));
1294 __ cmp(
R3, Operand(0));
1303 Label push_arguments;
1304 Label done_push_arguments;
1305 __ CompareImmediate(
R9, 0);
1306 __ b(&done_push_arguments,
EQ);
1307 __ LoadImmediate(
R1, 0);
1308 __ Bind(&push_arguments);
1311 __ AddImmediate(
R2, target::kWordSize);
1312 __ AddImmediate(
R1, 1);
1314 __ b(&push_arguments,
LT);
1315 __ Bind(&done_push_arguments);
1318 if (FLAG_precompiled_mode) {
1319 __ SetupGlobalPoolAndDispatchTable();
1322 __ LoadImmediate(
PP, 0);
1324 __ ldr(
R0, FieldAddress(
CODE_REG, target::Code::entry_point_offset()));
1331 target::frame_layout.exit_link_slot_from_entry_fp * target::kWordSize);
1336 __ StoreToOffset(
R9,
THR, target::Thread::top_exit_frame_info_offset());
1338 __ StoreToOffset(
R9,
THR, target::Thread::exit_through_ffi_offset());
1340 __ StoreToOffset(
R9,
THR, target::Thread::top_resource_offset());
1344 __ StoreToOffset(
R4,
THR, target::Thread::vm_tag_offset());
1346#if defined(USING_SHADOW_CALL_STACK)
1350 __ PopNativeCalleeSavedRegisters();
1352 __ set_constant_pool_allowed(
false);
1355 RESTORES_LR_FROM_FRAME(
__ LeaveFrame((1 <<
FP) | (1 <<
LR)));
1367static void GenerateAllocateContext(Assembler* assembler, Label* slow_case) {
1370 const intptr_t fixed_size_plus_alignment_padding =
1371 target::Context::header_size() +
1373 __ LoadImmediate(
R2, fixed_size_plus_alignment_padding);
1382 __ ldr(
R0, Address(
THR, target::Thread::top_offset()));
1389 __ ldr(
IP, Address(
THR, target::Thread::end_offset()));
1391 __ b(slow_case,
CS);
1392 __ CheckAllocationCanary(
R0);
1400 __ str(
R3, Address(
THR, target::Thread::top_offset()));
1408 const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
1410 __ CompareImmediate(
R2, target::UntaggedObject::kSizeTagMaxSizeTag);
1413 __ mov(
R9, Operand(0),
HI);
1420 __ LoadImmediate(
IP, tags);
1422 __ str(
R9, FieldAddress(
R0, target::Object::tags_offset()));
1429 __ str(
R1, FieldAddress(
R0, target::Context::num_variables_offset()));
1439void StubCodeCompiler::GenerateAllocateContextStub() {
1440 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1443 GenerateAllocateContext(
assembler, &slow_case);
1451 __ StoreIntoObjectNoBarrier(
1452 R0, FieldAddress(
R0, target::Context::parent_offset()),
R8);
1467 __ Bind(&slow_case);
1472 __ EnterStubFrame();
1474 __ LoadImmediate(
R2, 0);
1476 __ PushList((1 <<
R1) | (1 <<
R2));
1477 __ CallRuntime(kAllocateContextRuntimeEntry, 1);
1488 __ LeaveStubFrame();
1500void StubCodeCompiler::GenerateCloneContextStub() {
1501 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1505 __ ldr(
R1, FieldAddress(
R4, target::Context::num_variables_offset()));
1507 GenerateAllocateContext(
assembler, &slow_case);
1510 __ ldr(
R2, FieldAddress(
R4, target::Context::parent_offset()));
1513 __ StoreIntoObjectNoBarrier(
1514 R0, FieldAddress(
R0, target::Context::parent_offset()),
R2);
1527 __ subs(
R1,
R1, Operand(1));
1530 __ ldr(
R9, Address(
R3,
R1,
LSL, target::kWordSizeLog2));
1531 __ str(
R9, Address(
R2,
R1,
LSL, target::kWordSizeLog2));
1542 __ Bind(&slow_case);
1547 __ EnterStubFrame();
1549 __ LoadImmediate(
R0, 0);
1550 __ PushRegisterPair(
R4,
R0);
1551 __ CallRuntime(kCloneContextRuntimeEntry, 1);
1554 __ PopRegisterPair(
R4,
R0);
1563 __ LeaveStubFrame();
1567void StubCodeCompiler::GenerateWriteBarrierWrappersStub() {
1572 intptr_t
start =
__ CodeSize();
1575 __ Call(Address(
THR, target::Thread::write_barrier_entry_point_offset()));
1576 RESTORES_LR_FROM_FRAME(
1578 READS_RETURN_ADDRESS_FROM_LR(
__ bx(
LR));
1579 intptr_t
end =
__ CodeSize();
1595static void GenerateWriteBarrierStubHelper(Assembler* assembler,
bool cards) {
1598 __ ldr(
TMP, FieldAddress(
R0, target::Object::tags_offset()));
1599 __ ldr(
R2, Address(
THR, target::Thread::write_barrier_mask_offset()));
1602 __ tst(
TMP, Operand(target::UntaggedObject::kIncrementalBarrierMask));
1608 __ PushList((1 <<
R2) | (1 <<
R3) | (1 <<
R4));
1613 __ tst(
R2, Operand(1 << target::UntaggedObject::kNotMarkedBit));
1615 __ bic(
R2,
R2, Operand(1 << target::UntaggedObject::kNotMarkedBit));
1617 __ cmp(
R4, Operand(1));
1620 __ ldr(
R4, Address(
THR, target::Thread::marking_stack_block_offset()));
1622 __ add(
R3,
R4, Operand(
R2,
LSL, target::kWordSizeLog2));
1624 __ add(
R2,
R2, Operand(1));
1630 LeafRuntimeScope rt(assembler, 0,
1633 rt.Call(kMarkingStackBlockProcessRuntimeEntry, 1);
1638 __ PopList((1 <<
R2) | (1 <<
R3) | (1 <<
R4));
1641 Label add_to_remembered_set, remember_card;
1642 __ Bind(&skip_marking);
1644 __ ldr(
TMP, FieldAddress(
R1, target::Object::tags_offset()));
1645 __ ldr(
R2, FieldAddress(
R0, target::Object::tags_offset()));
1647 Operand(
TMP,
LSR, target::UntaggedObject::kBarrierOverlapShift));
1649 __ tst(
TMP, Operand(target::UntaggedObject::kGenerationalBarrierMask));
1653 __ Bind(&add_to_remembered_set);
1655 __ ldr(
TMP, FieldAddress(
R1, target::Object::tags_offset()));
1656 __ tst(
TMP, Operand(1 << target::UntaggedObject::kCardRememberedBit));
1661 __ ldr(
TMP, FieldAddress(
R1, target::Object::tags_offset()));
1662 __ tst(
TMP, Operand(1 << target::UntaggedObject::kCardRememberedBit));
1664 __ Stop(
"Wrong barrier");
1672 __ PushList((1 <<
R2) | (1 <<
R3) | (1 <<
R4));
1677 __ tst(
R2, Operand(1 << target::UntaggedObject::kOldAndNotRememberedBit));
1680 Operand(1 << target::UntaggedObject::kOldAndNotRememberedBit));
1682 __ cmp(
R4, Operand(1));
1687 __ ldr(
R4, Address(
THR, target::Thread::store_buffer_block_offset()));
1689 __ add(
R3,
R4, Operand(
R2,
LSL, target::kWordSizeLog2));
1695 __ add(
R2,
R2, Operand(1));
1701 LeafRuntimeScope rt(assembler, 0,
1704 rt.Call(kStoreBufferBlockProcessRuntimeEntry, 1);
1708 __ PopList((1 <<
R2) | (1 <<
R3) | (1 <<
R4));
1712 Label remember_card_slow;
1715 __ Bind(&remember_card);
1718 Address(
TMP, target::Page::card_table_offset()));
1719 __ cmp(
TMP, Operand(0));
1720 __ b(&remember_card_slow,
EQ);
1724 __ PushList((1 <<
R0) | (1 <<
R1));
1727 __ Lsr(
R9,
R9, Operand(target::Page::kBytesPerCardLog2));
1728 __ AndImmediate(
R1,
R9, target::kBitsPerWord - 1);
1729 __ LoadImmediate(
R0, 1);
1732 Address(
TMP, target::Page::card_table_offset()));
1733 __ Lsr(
R9,
R9, Operand(target::kBitsPerWordLog2));
1738 __ PopList((1 <<
R0) | (1 <<
R1));
1742 __ Bind(&remember_card_slow);
1744 LeafRuntimeScope rt(assembler, 0,
1748 rt.Call(kRememberCardRuntimeEntry, 2);
1754void StubCodeCompiler::GenerateWriteBarrierStub() {
1755 GenerateWriteBarrierStubHelper(
assembler,
false);
1758void StubCodeCompiler::GenerateArrayWriteBarrierStub() {
1759 GenerateWriteBarrierStubHelper(
assembler,
true);
1762static void GenerateAllocateObjectHelper(Assembler* assembler,
1763 bool is_cls_parameterized) {
1769#if !defined(PRODUCT)
1774 __ MaybeTraceAllocation(kCidRegister, &slow_case,
1775 kTraceAllocationTempReg);
1786 __ ExtractInstanceSizeFromTags(kInstanceSizeReg, kTagsReg);
1791 target::Thread::top_offset());
1794 Operand(kInstanceSizeReg));
1796 __ CompareRegisters(kEndReg, kNewTopReg);
1801 __ str(kNewTopReg, Address(
THR, target::Thread::top_offset()));
1806 target::Object::tags_offset()));
1816 target::Instance::first_field_offset());
1817 Label
done, init_loop;
1818 __ Bind(&init_loop);
1819 __ CompareRegisters(kFieldReg, kNewTopReg);
1829 if (is_cls_parameterized) {
1830 Label not_parameterized_case;
1835 __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
1838 __ LoadClassById(kTypeOffsetReg, kClsIdReg);
1841 FieldAddress(kTypeOffsetReg,
1843 host_type_arguments_field_offset_in_words_offset()));
1846 __ StoreIntoObjectNoBarrier(
1849 target::kWordSizeLog2),
1852 __ Bind(¬_parameterized_case);
1860 __ Bind(&slow_case);
1867 if (!is_cls_parameterized) {
1874 target::Thread::allocate_object_slow_entry_point_offset()));
1880void StubCodeCompiler::GenerateAllocateObjectStub() {
1881 GenerateAllocateObjectHelper(
assembler,
false);
1884void StubCodeCompiler::GenerateAllocateObjectParameterizedStub() {
1885 GenerateAllocateObjectHelper(
assembler,
true);
1888void StubCodeCompiler::GenerateAllocateObjectSlowStub() {
1891 if (!FLAG_precompiled_mode) {
1893 Address(
THR, target::Thread::call_to_runtime_stub_offset()));
1898 __ EnterStubFrame();
1911 __ CallRuntime(kAllocateObjectRuntimeEntry, 2);
1920 __ LeaveDartFrameAndReturn();
1927 const Code& allocate_object,
1928 const Code& allocat_object_parametrized) {
1929 classid_t cls_id = target::Class::GetId(cls);
1933 const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
1934 ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
1935 cls) != target::Class::kNoTypeArguments);
1937 const intptr_t instance_size = target::Class::GetInstanceSize(cls);
1938 ASSERT(instance_size > 0);
1945 __ LoadImmediate(kTagsReg, tags);
1947 if (!FLAG_use_slow_path && FLAG_inline_alloc &&
1948 !target::Class::TraceAllocation(cls) &&
1951 RELEASE_ASSERT(target::Heap::IsAllocatableInNewSpace(instance_size));
1953 if (is_cls_parameterized) {
1955 CastHandle<Object>(allocat_object_parametrized))) {
1956 __ GenerateUnRelocatedPcRelativeTailCall();
1957 unresolved_calls->Add(
new UnresolvedPcRelativeCall(
1958 __ CodeSize(), allocat_object_parametrized,
true));
1963 allocate_object_parameterized_entry_point_offset()));
1967 __ GenerateUnRelocatedPcRelativeTailCall();
1968 unresolved_calls->Add(
new UnresolvedPcRelativeCall(
1969 __ CodeSize(), allocate_object,
true));
1973 Address(
THR, target::Thread::allocate_object_entry_point_offset()));
1977 if (!is_cls_parameterized) {
1982 target::Thread::allocate_object_slow_entry_point_offset()));
1993void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub() {
1994 __ EnterStubFrame();
1997 __ ldr(
R2, FieldAddress(
R4, target::ArgumentsDescriptor::count_offset()));
1999 __ ldr(
R8, Address(
IP, target::frame_layout.param_end_from_fp *
2000 target::kWordSize));
2003 __ ldr(
R6, FieldAddress(
R8, target::Closure::function_offset()));
2008 __ LoadImmediate(
IP, 0);
2009 __ PushList((1 <<
R4) | (1 <<
R6) | (1 <<
R8) | (1 <<
IP));
2013 FieldAddress(
R4, target::ArgumentsDescriptor::type_args_len_offset()));
2014 __ cmp(
R3, Operand(0));
2021 const intptr_t kNumArgs = 4;
2022 __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
2034 if (FLAG_precompiled_mode) {
2038 if (FLAG_trace_optimized_ic_calls) {
2039 __ EnterStubFrame();
2040 __ PushList((1 <<
R9) | (1 <<
R8));
2043 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
2045 __ PopList((1 <<
R9) | (1 <<
R8));
2046 __ LeaveStubFrame();
2048 __ ldr(
TMP, FieldAddress(func_reg, target::Function::usage_counter_offset()));
2050 __ str(
TMP, FieldAddress(func_reg, target::Function::usage_counter_offset()));
2055 if (FLAG_precompiled_mode) {
2059 if (FLAG_optimization_counter_threshold >= 0) {
2062 __ Comment(
"Increment function counter");
2063 __ ldr(func_reg, FieldAddress(
IC_DATA_REG, target::ICData::owner_offset()));
2065 FieldAddress(func_reg, target::Function::usage_counter_offset()));
2068 FieldAddress(func_reg, target::Function::usage_counter_offset()));
2076static void EmitFastSmiOp(Assembler* assembler,
2079 Label* not_smi_or_overflow) {
2080 __ Comment(
"Fast Smi op");
2081 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
2082 __ ldr(
R1, Address(
SP, 0 * target::kWordSize));
2085 __ b(not_smi_or_overflow,
NE);
2089 __ b(not_smi_or_overflow,
VS);
2108 __ ldr(
R8, FieldAddress(
R9, target::ICData::entries_offset()));
2116 __ ldr(
R1, Address(
R8, 0));
2117 __ CompareImmediate(
R1, imm_smi_cid);
2119 __ ldr(
R1, Address(
R8, target::kWordSize));
2120 __ CompareImmediate(
R1, imm_smi_cid);
2123 __ Stop(
"Incorrect IC data");
2126 if (FLAG_optimization_counter_threshold >= 0) {
2128 const intptr_t count_offset =
2129 target::ICData::CountIndexFor(num_args) * target::kWordSize;
2130 __ LoadFromOffset(
R1,
R8, count_offset);
2132 __ StoreIntoSmiField(Address(
R8, count_offset),
R1);
2141static void GenerateRecordEntryPoint(Assembler* assembler) {
2145 __ BindUncheckedEntryPoint();
2166 const RuntimeEntry& handle_ic_miss,
2168 Optimized optimized,
2170 Exactness exactness) {
2171 if (FLAG_precompiled_mode) {
2176 const bool save_entry_point = kind == Token::kILLEGAL;
2177 if (save_entry_point) {
2187 __ CheckCodePointer();
2188 ASSERT(num_args == 1 || num_args == 2);
2194 __ ldr(
R8, FieldAddress(
R9, target::ICData::state_bits_offset()));
2195 ASSERT(target::ICData::NumArgsTestedShift() == 0);
2196 __ and_(
R8,
R8, Operand(target::ICData::NumArgsTestedMask()));
2197 __ CompareImmediate(
R8, num_args);
2199 __ Stop(
"Incorrect stub for IC data");
2204#if !defined(PRODUCT)
2205 Label stepping, done_stepping;
2207 __ Comment(
"Check single stepping");
2209 __ ldrb(
R8, Address(
R8, target::Isolate::single_step_offset()));
2210 __ CompareImmediate(
R8, 0);
2211 __ b(&stepping,
NE);
2212 __ Bind(&done_stepping);
2216 Label not_smi_or_overflow;
2217 if (kind != Token::kILLEGAL) {
2218 EmitFastSmiOp(
assembler, kind, num_args, ¬_smi_or_overflow);
2220 __ Bind(¬_smi_or_overflow);
2222 __ Comment(
"Extract ICData initial values and receiver cid");
2224 __ ldr(
R8, FieldAddress(
R9, target::ICData::entries_offset()));
2226 const int kIcDataOffset = target::Array::data_offset() -
kHeapObjectTag;
2230 __ LoadTaggedClassIdMayBeSmi(
NOTFP,
R0);
2233 FieldAddress(
R9, target::CallSiteData::arguments_descriptor_offset()));
2234 if (num_args == 2) {
2236 target::ArgumentsDescriptor::count_offset()));
2239 __ LoadTaggedClassIdMayBeSmi(
R1,
R1);
2245 FieldAddress(
R9, target::CallSiteData::arguments_descriptor_offset()));
2250 target::ArgumentsDescriptor::count_offset()));
2255 __ LoadTaggedClassIdMayBeSmi(
NOTFP,
R0);
2257 if (num_args == 2) {
2260 __ LoadTaggedClassIdMayBeSmi(
R1,
R1);
2268 Label loop, found, miss;
2269 __ Comment(
"ICData loop");
2272 const bool optimize = kind == Token::kILLEGAL;
2275 for (
int unroll =
optimize ? 4 : 2; unroll >= 0; unroll--) {
2278 __ ldr(
R2, Address(
R8, kIcDataOffset));
2280 if (num_args == 2) {
2282 __ ldr(
R2, Address(
R8, kIcDataOffset + target::kWordSize));
2289 const intptr_t entry_size = target::ICData::TestEntryLengthFor(
2292 __ AddImmediate(
R8, entry_size);
2303 __ Comment(
"IC miss");
2306 target::ArgumentsDescriptor::count_offset()));
2313 __ EnterStubFrame();
2314 __ LoadImmediate(
R0, 0);
2318 if (save_entry_point) {
2324 for (intptr_t i = 0; i < num_args; i++) {
2325 __ LoadFromOffset(
TMP,
R1, -i * target::kWordSize);
2330 __ CallRuntime(handle_ic_miss, num_args + 1);
2332 __ Drop(num_args + 1);
2337 if (save_entry_point) {
2340 __ RestoreCodePointer();
2341 __ LeaveStubFrame();
2342 Label call_target_function;
2343 if (!FLAG_lazy_dispatchers) {
2344 GenerateDispatcherCode(
assembler, &call_target_function);
2346 __ b(&call_target_function);
2351 const intptr_t target_offset =
2352 target::ICData::TargetIndexFor(num_args) * target::kWordSize;
2353 const intptr_t count_offset =
2354 target::ICData::CountIndexFor(num_args) * target::kWordSize;
2355 const intptr_t exactness_offset =
2356 target::ICData::ExactnessIndexFor(num_args) * target::kWordSize;
2358 Label call_target_function_through_unchecked_entry;
2362 __ ldr(
R1, Address(
R8, kIcDataOffset + exactness_offset));
2363 __ CompareImmediate(
2366 __ BranchIf(
LESS, &exactness_ok);
2367 __ BranchIf(
EQUAL, &call_target_function_through_unchecked_entry);
2373 FieldAddress(
R9, target::ICData::receivers_static_type_offset()));
2374 __ ldr(
R2, FieldAddress(
R2, target::Type::arguments_offset()));
2379 __ CompareObjectRegisters(
R2,
TMP);
2380 __ BranchIf(
EQUAL, &call_target_function_through_unchecked_entry);
2385 __ str(
R1, Address(
R8, kIcDataOffset + exactness_offset));
2386 __ Bind(&exactness_ok);
2390 if (FLAG_optimization_counter_threshold >= 0) {
2391 __ Comment(
"Update caller's counter");
2392 __ LoadFromOffset(
R1,
R8, kIcDataOffset + count_offset);
2394 __ StoreIntoSmiField(Address(
R8, kIcDataOffset + count_offset),
R1);
2397 __ Comment(
"Call target");
2398 __ Bind(&call_target_function);
2402 if (save_entry_point) {
2406 FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
2410 __ Bind(&call_target_function_through_unchecked_entry);
2411 if (FLAG_optimization_counter_threshold >= 0) {
2412 __ Comment(
"Update ICData counter");
2413 __ LoadFromOffset(
R1,
R8, kIcDataOffset + count_offset);
2415 __ StoreIntoSmiField(Address(
R8, kIcDataOffset + count_offset),
R1);
2417 __ Comment(
"Call target (via unchecked entry point)");
2420 FieldAddress(
FUNCTION_REG, target::Function::code_offset()));
2421 __ Branch(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset(
2425#if !defined(PRODUCT)
2428 __ EnterStubFrame();
2433 if (save_entry_point) {
2438 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2440 if (save_entry_point) {
2446 __ RestoreCodePointer();
2447 __ LeaveStubFrame();
2448 __ b(&done_stepping);
2456void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub() {
2458 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
2465void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub() {
2467 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
2474void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub() {
2476 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2483void StubCodeCompiler::GenerateSmiAddInlineCacheStub() {
2485 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
kUnoptimized,
2492void StubCodeCompiler::GenerateSmiLessInlineCacheStub() {
2494 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
kUnoptimized,
2501void StubCodeCompiler::GenerateSmiEqualInlineCacheStub() {
2503 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
kUnoptimized,
2511void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub() {
2513 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
kOptimized,
2521void StubCodeCompiler::
2522 GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub() {
2524 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
kOptimized,
2532void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub() {
2534 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2540void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub() {
2548 __ ldr(
R8, FieldAddress(
R9, target::ICData::state_bits_offset()));
2549 ASSERT(target::ICData::NumArgsTestedShift() == 0);
2550 __ and_(
R8,
R8, Operand(target::ICData::NumArgsTestedMask()));
2551 __ CompareImmediate(
R8, 0);
2553 __ Stop(
"Incorrect IC data for unoptimized static call");
2558#if !defined(PRODUCT)
2560 Label stepping, done_stepping;
2562 __ ldrb(
R8, Address(
R8, target::Isolate::single_step_offset()));
2563 __ CompareImmediate(
R8, 0);
2564 __ b(&stepping,
NE);
2565 __ Bind(&done_stepping);
2569 __ ldr(
R8, FieldAddress(
R9, target::ICData::entries_offset()));
2573 const intptr_t target_offset =
2574 target::ICData::TargetIndexFor(0) * target::kWordSize;
2575 const intptr_t count_offset =
2576 target::ICData::CountIndexFor(0) * target::kWordSize;
2578 if (FLAG_optimization_counter_threshold >= 0) {
2580 __ LoadFromOffset(
R1,
R8, count_offset);
2582 __ StoreIntoSmiField(Address(
R8, count_offset),
R1);
2587 FieldAddress(
R9, target::CallSiteData::arguments_descriptor_offset()));
2595#if !defined(PRODUCT)
2597 __ EnterStubFrame();
2599 __ PushList((1 <<
R9) | (1 <<
R3));
2600 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2601 __ PopList((1 <<
R9) | (1 <<
R3));
2603 __ RestoreCodePointer();
2604 __ LeaveStubFrame();
2605 __ b(&done_stepping);
2611void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub() {
2620void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub() {
2623 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2630void StubCodeCompiler::GenerateLazyCompileStub() {
2631 __ EnterStubFrame();
2635 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
2637 __ LeaveStubFrame();
2640 __ Branch(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
2644void StubCodeCompiler::GenerateICCallBreakpointStub() {
2646 __ Stop(
"No debugging in PRODUCT mode");
2648 __ EnterStubFrame();
2651 __ PushImmediate(0);
2652 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
2656 __ LeaveStubFrame();
2657 __ Branch(FieldAddress(
CODE_REG, target::Code::entry_point_offset()));
2661void StubCodeCompiler::GenerateUnoptStaticCallBreakpointStub() {
2663 __ Stop(
"No debugging in PRODUCT mode");
2665 __ EnterStubFrame();
2667 __ PushImmediate(0);
2668 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
2671 __ LeaveStubFrame();
2672 __ Branch(FieldAddress(
CODE_REG, target::Code::entry_point_offset()));
2676void StubCodeCompiler::GenerateRuntimeCallBreakpointStub() {
2678 __ Stop(
"No debugging in PRODUCT mode");
2680 __ EnterStubFrame();
2681 __ LoadImmediate(
R0, 0);
2683 __ PushList((1 <<
R0));
2684 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
2686 __ LeaveStubFrame();
2687 __ Branch(FieldAddress(
CODE_REG, target::Code::entry_point_offset()));
2692void StubCodeCompiler::GenerateDebugStepCheckStub() {
2694 __ Stop(
"No debugging in PRODUCT mode");
2697 Label stepping, done_stepping;
2699 __ ldrb(
R1, Address(
R1, target::Isolate::single_step_offset()));
2700 __ CompareImmediate(
R1, 0);
2701 __ b(&stepping,
NE);
2702 __ Bind(&done_stepping);
2706 __ EnterStubFrame();
2707 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2708 __ LeaveStubFrame();
2709 __ b(&done_stepping);
2725void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
2732 RegisterSet saved_registers;
2737 saved_registers.AddRegister(kCacheArrayReg);
2750 kInstanceInstantiatorTypeArgumentsReg =
PP;
2751 saved_registers.AddRegister(kInstanceInstantiatorTypeArgumentsReg);
2757 kInstanceParentFunctionTypeArgumentsReg =
2759 saved_registers.AddRegister(kInstanceParentFunctionTypeArgumentsReg);
2769 saved_registers.AddRegister(kInstanceDelayedFunctionTypeArgumentsReg);
2780 kCacheContentsSizeReg =
2782 saved_registers.AddRegister(kCacheContentsSizeReg);
2788 saved_registers.AddRegister(kProbeDistanceReg);
2797 __ PushRegisters(saved_registers);
2800 GenerateSubtypeTestCacheSearch(
2803 kInstanceInstantiatorTypeArgumentsReg,
2804 kInstanceParentFunctionTypeArgumentsReg,
2805 kInstanceDelayedFunctionTypeArgumentsReg, kCacheEntryEndReg,
2806 kCacheContentsSizeReg, kProbeDistanceReg,
2810 Address(kCacheArrayReg, target::kCompressedWordSize *
2811 target::SubtypeTestCache::kTestResult));
2812 __ PopRegisters(saved_registers);
2817 __ PopRegisters(saved_registers);
2823void StubCodeCompiler::GenerateGetCStackPointerStub() {
2837void StubCodeCompiler::GenerateJumpToFrameStub() {
2848#if defined(USING_SHADOW_CALL_STACK)
2851 Label exit_through_non_ffi;
2859 __ LoadFromOffset(tmp1,
THR,
2860 compiler::target::Thread::exit_through_ffi_offset());
2861 __ LoadImmediate(tmp2, target::Thread::exit_through_ffi());
2862 __ cmp(tmp1, Operand(tmp2));
2863 __ b(&exit_through_non_ffi,
NE);
2864 __ TransitionNativeToGenerated(tmp1, tmp2,
2867 __ Bind(&exit_through_non_ffi);
2870 __ LoadImmediate(
R2, VMTag::kDartTagId);
2871 __ StoreToOffset(
R2,
THR, target::Thread::vm_tag_offset());
2873 __ LoadImmediate(
R2, 0);
2874 __ StoreToOffset(
R2,
THR, target::Thread::top_exit_frame_info_offset());
2876 __ RestoreCodePointer();
2877 if (FLAG_precompiled_mode) {
2878 __ SetupGlobalPoolAndDispatchTable();
2879 __ set_constant_pool_allowed(
true);
2881 __ LoadPoolPointer();
2891void StubCodeCompiler::GenerateRunExceptionHandlerStub() {
2892 WRITES_RETURN_ADDRESS_TO_LR(
2893 __ LoadFromOffset(
LR,
THR, target::Thread::resume_pc_offset()));
2895 word offset_from_thread = 0;
2898 __ LoadFromOffset(
R2,
THR, offset_from_thread);
2901 __ LoadFromOffset(
R0,
THR, target::Thread::active_exception_offset());
2902 __ StoreToOffset(
R2,
THR, target::Thread::active_exception_offset());
2905 __ LoadFromOffset(
R1,
THR, target::Thread::active_stacktrace_offset());
2906 __ StoreToOffset(
R2,
THR, target::Thread::active_stacktrace_offset());
2908 READS_RETURN_ADDRESS_FROM_LR(
2915void StubCodeCompiler::GenerateDeoptForRewindStub() {
2921 WRITES_RETURN_ADDRESS_TO_LR(
2922 __ LoadFromOffset(
LR,
THR, target::Thread::resume_pc_offset()));
2926 __ EnterStubFrame();
2927 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0);
2928 __ LeaveStubFrame();
2935void StubCodeCompiler::GenerateOptimizeFunctionStub() {
2936 __ ldr(
CODE_REG, Address(
THR, target::Thread::optimize_stub_offset()));
2937 __ EnterStubFrame();
2939 __ LoadImmediate(
IP, 0);
2942 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
2946 __ LeaveStubFrame();
2948 __ Branch(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
2957static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
2961 Label reference_compare,
done, check_mint;
2964 __ b(&reference_compare,
EQ);
2966 __ b(&reference_compare,
EQ);
2969 __ CompareClassId(
left, kDoubleCid, temp);
2970 __ b(&check_mint,
NE);
2971 __ CompareClassId(
right, kDoubleCid, temp);
2975 __ ldr(temp, FieldAddress(
left, target::Double::value_offset() +
2976 0 * target::kWordSize));
2977 __ ldr(
IP, FieldAddress(
right, target::Double::value_offset() +
2978 0 * target::kWordSize));
2979 __ cmp(temp, Operand(
IP));
2981 __ ldr(temp, FieldAddress(
left, target::Double::value_offset() +
2982 1 * target::kWordSize));
2983 __ ldr(
IP, FieldAddress(
right, target::Double::value_offset() +
2984 1 * target::kWordSize));
2985 __ cmp(temp, Operand(
IP));
2988 __ Bind(&check_mint);
2989 __ CompareClassId(
left, kMintCid, temp);
2990 __ b(&reference_compare,
NE);
2991 __ CompareClassId(
right, kMintCid, temp);
2993 __ ldr(temp, FieldAddress(
2994 left, target::Mint::value_offset() + 0 * target::kWordSize));
2995 __ ldr(
IP, FieldAddress(
2996 right, target::Mint::value_offset() + 0 * target::kWordSize));
2997 __ cmp(temp, Operand(
IP));
2999 __ ldr(temp, FieldAddress(
3000 left, target::Mint::value_offset() + 1 * target::kWordSize));
3001 __ ldr(
IP, FieldAddress(
3002 right, target::Mint::value_offset() + 1 * target::kWordSize));
3003 __ cmp(temp, Operand(
IP));
3006 __ Bind(&reference_compare);
3016void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub() {
3017#if !defined(PRODUCT)
3019 Label stepping, done_stepping;
3021 __ ldrb(
R1, Address(
R1, target::Isolate::single_step_offset()));
3022 __ CompareImmediate(
R1, 0);
3023 __ b(&stepping,
NE);
3024 __ Bind(&done_stepping);
3030 __ ldr(
left, Address(
SP, 1 * target::kWordSize));
3031 __ ldr(
right, Address(
SP, 0 * target::kWordSize));
3035#if !defined(PRODUCT)
3037 __ EnterStubFrame();
3038 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
3039 __ RestoreCodePointer();
3040 __ LeaveStubFrame();
3041 __ b(&done_stepping);
3050void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub() {
3054 __ ldr(
left, Address(
SP, 1 * target::kWordSize));
3055 __ ldr(
right, Address(
SP, 0 * target::kWordSize));
3067void StubCodeCompiler::GenerateMegamorphicCallStub() {
3068 __ LoadTaggedClassIdMayBeSmi(
R8,
R0);
3071 FieldAddress(
IC_DATA_REG, target::MegamorphicCache::buckets_offset()));
3073 FieldAddress(
IC_DATA_REG, target::MegamorphicCache::mask_offset()));
3078 ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
3086 const intptr_t
base = target::Array::data_offset();
3092 __ b(&probe_failed,
NE);
3095 __ Bind(&load_target);
3101 if (!FLAG_precompiled_mode) {
3103 FieldAddress(
FUNCTION_REG, target::Function::code_offset()));
3107 target::CallSiteData::arguments_descriptor_offset()));
3108 __ Branch(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
3111 __ Bind(&probe_failed);
3122 GenerateSwitchableCallMissStub();
3125void StubCodeCompiler::GenerateICCallThroughCodeStub() {
3126 Label loop, found, miss;
3127 __ ldr(
R8, FieldAddress(
IC_DATA_REG, target::ICData::entries_offset()));
3129 target::CallSiteData::arguments_descriptor_offset()));
3132 __ LoadTaggedClassIdMayBeSmi(
R1,
R0);
3136 __ ldr(
R2, Address(
R8, 0));
3142 const intptr_t entry_length =
3143 target::ICData::TestEntryLengthFor(1,
false) *
3145 __ AddImmediate(
R8, entry_length);
3149 if (FLAG_precompiled_mode) {
3150 const intptr_t entry_offset =
3151 target::ICData::EntryPointIndexFor(1) * target::kWordSize;
3152 __ LoadCompressed(
R0, Address(
R8, entry_offset));
3153 __ Branch(FieldAddress(
R0, target::Function::entry_point_offset()));
3155 const intptr_t code_offset =
3156 target::ICData::CodeIndexFor(1) * target::kWordSize;
3158 __ Branch(FieldAddress(
CODE_REG, target::Code::entry_point_offset()));
3162 __ Branch(Address(
THR, target::Thread::switchable_call_miss_entry_offset()));
3172void StubCodeCompiler::GenerateMonomorphicSmiableCheckStub() {
3173 __ LoadClassIdMayBeSmi(
IP,
R0);
3176 ASSERT(target::MonomorphicSmiableCall::entrypoint_offset() ==
3177 target::MonomorphicSmiableCall::expected_cid_offset() +
3184 target::MonomorphicSmiableCall::expected_cid_offset() -
kHeapObjectTag);
3186 __ Branch(Address(
THR, target::Thread::switchable_call_miss_entry_offset()),
3191static void CallSwitchableCallMissRuntimeEntry(Assembler* assembler,
3193 __ LoadImmediate(
IP, 0);
3196 __ Push(receiver_reg);
3197 __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
3205void StubCodeCompiler::GenerateSwitchableCallMissStub() {
3207 Address(
THR, target::Thread::switchable_call_miss_stub_offset()));
3208 __ EnterStubFrame();
3209 CallSwitchableCallMissRuntimeEntry(
assembler,
R0);
3210 __ LeaveStubFrame();
3212 __ Branch(FieldAddress(
3221void StubCodeCompiler::GenerateSingleTargetCallStub() {
3223 __ LoadClassIdMayBeSmi(
R1,
R0);
3225 FieldAddress(
R9, target::SingleTargetCache::lower_limit_offset()));
3227 FieldAddress(
R9, target::SingleTargetCache::upper_limit_offset()));
3235 FieldAddress(
R9, target::SingleTargetCache::target_offset()));
3236 __ Branch(FieldAddress(
R9, target::SingleTargetCache::entry_point_offset()));
3239 __ EnterStubFrame();
3240 CallSwitchableCallMissRuntimeEntry(
assembler,
R0);
3241 __ LeaveStubFrame();
3243 __ Branch(FieldAddress(
3247static int GetScaleFactor(intptr_t size) {
3264void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(intptr_t
cid) {
3267 const intptr_t scale_shift = GetScaleFactor(
element_size);
3272 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
3279 __ b(&call_runtime,
NE);
3283 __ CompareImmediate(
R2, max_len);
3284 __ b(&call_runtime,
HI);
3285 __ mov(
R2, Operand(
R2,
LSL, scale_shift));
3286 const intptr_t fixed_size_plus_alignment_padding =
3287 target::TypedData::HeaderSize() +
3289 __ AddImmediate(
R2, fixed_size_plus_alignment_padding);
3291 __ ldr(
R0, Address(
THR, target::Thread::top_offset()));
3295 __ b(&call_runtime,
CS);
3301 __ ldr(
IP, Address(
THR, target::Thread::end_offset()));
3303 __ b(&call_runtime,
CS);
3304 __ CheckAllocationCanary(
R0);
3306 __ str(
R1, Address(
THR, target::Thread::top_offset()));
3313 __ CompareImmediate(
R2, target::UntaggedObject::kSizeTagMaxSizeTag);
3316 target::UntaggedObject::kTagBitsSizeTagPos -
3319 __ mov(
R3, Operand(0),
HI);
3324 __ LoadImmediate(
TMP, tags);
3326 __ str(
R3, FieldAddress(
R0, target::Object::tags_offset()));
3334 __ StoreIntoObjectNoBarrier(
3335 R0, FieldAddress(
R0, target::TypedDataBase::length_offset()),
R3);
3343 __ LoadImmediate(
R8, 0);
3345 __ AddImmediate(
R3,
R0, target::TypedData::HeaderSize() - 1);
3346 __ StoreInternalPointer(
3347 R0, FieldAddress(
R0, target::PointerBase::data_offset()),
R3);
3349 __ Bind(&init_loop);
3350 __ AddImmediate(
R3, 2 * target::kWordSize);
3352 __ strd(
R8,
R9,
R3, -2 * target::kWordSize,
LS);
3353 __ b(&init_loop,
CC);
3354 __ str(
R8, Address(
R3, -2 * target::kWordSize),
HI);
3355 __ WriteAllocationCanary(
R1);
3359 __ Bind(&call_runtime);
3362 __ EnterStubFrame();
3363 __ PushObject(Object::null_object());
3366 __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
3369 __ LeaveStubFrame();
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static void async_callback(void *c, std::unique_ptr< const SkImage::AsyncReadResult > result)
static bool ok(int result)
static SkTileMode optimize(SkTileMode tm, int dimension)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define ASSERT_LESS_OR_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
#define COMPILE_ASSERT(expr)
virtual bool WillAllocateNewOrRemembered() const
static bool UseUnboxedRepresentation()
static intptr_t pointers_offset()
static intptr_t top_offset()
static intptr_t RawValue(intptr_t value)
static StaticTypeExactnessState HasExactSuperType()
static StaticTypeExactnessState NotExact()
static constexpr intptr_t kMaxInputs
void GenerateNArgsCheckInlineCacheStub(intptr_t num_args, const RuntimeEntry &handle_ic_miss, Token::Kind kind, Optimized optimized, CallType type, Exactness exactness)
void EnsureIsNewOrRemembered()
void GenerateUsageCounterIncrement(Register temp_reg)
void GenerateAllocationStubForClass(UnresolvedPcRelativeCalls *unresolved_calls, const Class &cls, const dart::Code &allocate_object, const dart::Code &allocat_object_parametrized)
void GenerateOptimizedUsageCounterIncrement()
static intptr_t WordOffsetFromFpToCpuRegister(Register cpu_register)
const uint8_t uint32_t uint32_t GError ** error
uword MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size)
bool CanLoadFromThread(const dart::Object &object, intptr_t *offset)
word ToRawSmi(const dart::Object &a)
bool SizeFitsInSizeTag(uword instance_size)
word TypedDataMaxNewSpaceElements(classid_t cid)
word TypedDataElementSizeInBytes(classid_t cid)
const Bool & TrueObject()
GrowableArray< UnresolvedPcRelativeCall * > UnresolvedPcRelativeCalls
bool IsSameObject(const Object &a, const Object &b)
const Bool & FalseObject()
const Object & NullObject()
const Code & StubCodeAllocateArray()
const Class & MintClass()
const Register kWriteBarrierSlotReg
constexpr bool IsAbiPreservedRegister(Register reg)
const Register kExceptionObjectReg
const Register kWriteBarrierObjectReg
const Register kWriteBarrierValueReg
static constexpr bool IsCalleeSavedRegister(Register reg)
static constexpr uword kZapReturnAddress
const Register ARGS_DESC_REG
const Register DISPATCH_TABLE_REG
static constexpr bool IsArgumentRegister(Register reg)
constexpr RegList kDartAvailableCpuRegs
const intptr_t kStoreBufferWrapperSize
const Register FUNCTION_REG
const Register IC_DATA_REG
static constexpr uword kZapCodeReg
const Register kStackTraceObjectReg
const int kFpuRegisterSize
static constexpr Register kResultReg
static constexpr Register kLengthReg
static constexpr Register kTypeArgumentsReg
static constexpr Register kResultReg
static constexpr Register kTempReg
static constexpr Register kTypeArgumentsReg
static constexpr Register kResultReg
static constexpr Register kTagsReg
static constexpr Register kLengthReg
static constexpr Register kResultReg
static constexpr Register kClassIdReg
static constexpr intptr_t kObjectAlignmentLog2
static constexpr intptr_t kObjectAlignment
static constexpr Register kLengthReg
static constexpr Register kIndexReg
static constexpr Register kInstanceCidOrSignatureReg
static constexpr Register kResultReg
static constexpr Register kSubtypeTestCacheReg
static constexpr Register kDstTypeReg
static constexpr Register kInstanceReg
static constexpr Register kSubtypeTestCacheResultReg
#define NOT_IN_PRODUCT(code)