10#define SHOULD_NOT_INCLUDE_RUNTIME
14#if defined(TARGET_ARCH_IA32)
43 __ LoadFromOffset(
ECX,
ECX, target::Page::original_top_offset());
49 2 * target::kWordSize,
51 __ movl(Address(
ESP, 1 * target::kWordSize),
THR);
52 __ movl(Address(
ESP, 0 * target::kWordSize),
EAX);
53 rt.Call(kEnsureRememberedAndMarkingDeferredRuntimeEntry, 2);
67void StubCodeCompiler::GenerateCallToRuntimeStub() {
68 const intptr_t thread_offset = target::NativeArguments::thread_offset();
69 const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
70 const intptr_t argv_offset = target::NativeArguments::argv_offset();
71 const intptr_t retval_offset = target::NativeArguments::retval_offset();
74 Address(
THR, target::Thread::call_to_runtime_stub_offset()));
79 __ movl(Address(
THR, target::Thread::top_exit_frame_info_offset()),
EBP);
82 __ movl(Address(
THR, target::Thread::exit_through_ffi_offset()),
83 Immediate(target::Thread::exit_through_runtime_call()));
91 __ Stop(
"Not coming from Dart code.");
102 Immediate(-
static_cast<int32_t
>(target::NativeArguments::StructSize())));
108 __ movl(Address(
ESP, thread_offset),
THR);
109 __ movl(Address(
ESP, argc_tag_offset),
EDX);
113 target::frame_layout.param_end_from_fp * target::kWordSize));
114 __ movl(Address(
ESP, argv_offset),
EAX);
116 Immediate(1 * target::kWordSize));
117 __ movl(Address(
ESP, retval_offset),
EAX);
123 __ movl(Address(
THR, target::Thread::exit_through_ffi_offset()),
127 __ movl(Address(
THR, target::Thread::top_exit_frame_info_offset()),
141void StubCodeCompiler::GenerateEnterSafepointStub() {
147 __ ReserveAlignedFrameSpace(0);
148 __ movl(
EAX, Address(
THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
158static void GenerateExitSafepointStubCommon(Assembler* assembler,
159 uword runtime_entry_offset) {
165 __ ReserveAlignedFrameSpace(0);
170 __ movl(Address(
THR, target::Thread::execution_state_offset()),
171 Immediate(target::Thread::vm_execution_state()));
173 __ movl(
EAX, Address(
THR, runtime_entry_offset));
183void StubCodeCompiler::GenerateExitSafepointStub() {
184 GenerateExitSafepointStubCommon(
185 assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
188void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub() {
189 GenerateExitSafepointStubCommon(
191 kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
210void StubCodeCompiler::GenerateCallNativeThroughSafepointStub() {
213 __ movl(
ECX, compiler::Immediate(target::Thread::exit_through_ffi()));
217 __ TransitionNativeToGenerated(
ECX ,
true);
222void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
228 Label body, load_tramp_addr;
229 const intptr_t kCallLength = 5;
237 const intptr_t size_before =
__ CodeSize();
238 __ call(&load_tramp_addr);
239 const intptr_t size_after =
__ CodeSize();
245 FfiCallbackMetadata::kNativeCallbackTrampolineSize *
248 const intptr_t shared_stub_start =
__ CodeSize();
250 __ Bind(&load_tramp_addr);
254 __ subl(
EAX, Immediate(kCallLength));
264 COMPILE_ASSERT(FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta == 4);
274 __ ReserveAlignedFrameSpace(5 * target::kWordSize);
277 __ movl(Address(
SPREG, 0 * target::kWordSize),
EAX);
281 __ addl(
EAX, Immediate(3 * target::kWordSize));
282 __ movl(Address(
SPREG, 2 * target::kWordSize),
EAX);
285 __ addl(
EAX, Immediate(target::kWordSize));
286 __ movl(Address(
SPREG, 1 * target::kWordSize),
EAX);
294 __ movl(
EBX, Address(
SPREG, 3 * target::kWordSize));
295 __ movl(
ECX, Address(
SPREG, 4 * target::kWordSize));
312 __ cmpl(
THR, Immediate(0));
329 __ EnterFullSafepoint(
ECX);
344 __ ret(Immediate(4));
359 __ ReserveAlignedFrameSpace(0);
363 __ CallCFunction(
EAX);
383 FfiCallbackMetadata::kNativeCallbackSharedStubSize);
393void StubCodeCompiler::GenerateSharedStubGeneric(
394 bool save_fpu_registers,
395 intptr_t self_code_stub_offset_from_thread,
397 std::function<
void()> perform_runtime_call) {
402void StubCodeCompiler::GenerateSharedStub(
403 bool save_fpu_registers,
404 const RuntimeEntry*
target,
405 intptr_t self_code_stub_offset_from_thread,
407 bool store_runtime_result_in_result_register) {
412void StubCodeCompiler::GenerateRangeError(
bool with_fpu_regs) {
417void StubCodeCompiler::GenerateWriteError(
bool with_fpu_regs) {
422void StubCodeCompiler::GenerateDispatchTableNullErrorStub() {
433static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
434 Address wrapper_address) {
435 const intptr_t native_args_struct_offset =
436 target::NativeEntry::kNumCallWrapperArguments * target::kWordSize;
437 const intptr_t thread_offset =
438 target::NativeArguments::thread_offset() + native_args_struct_offset;
439 const intptr_t argc_tag_offset =
440 target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
441 const intptr_t argv_offset =
442 target::NativeArguments::argv_offset() + native_args_struct_offset;
443 const intptr_t retval_offset =
444 target::NativeArguments::retval_offset() + native_args_struct_offset;
450 __ movl(Address(
THR, target::Thread::top_exit_frame_info_offset()),
EBP);
453 __ movl(Address(
THR, target::Thread::exit_through_ffi_offset()),
454 Immediate(target::Thread::exit_through_runtime_call()));
462 __ Stop(
"Not coming from Dart code.");
475 Immediate(-
static_cast<int32_t
>(target::NativeArguments::StructSize()) -
476 (2 * target::kWordSize)));
483 __ movl(Address(
ESP, thread_offset),
THR);
485 __ movl(Address(
ESP, argc_tag_offset),
EDX);
487 __ movl(Address(
ESP, argv_offset),
EAX);
489 __ leal(
EAX, Address(
EBP, (target::frame_layout.param_end_from_fp + 1) *
492 __ movl(Address(
ESP, retval_offset),
EAX);
494 __ leal(
EAX, Address(
ESP, 2 * target::kWordSize));
498 __ movl(Address(
ESP, target::kWordSize),
ECX);
499 __ call(wrapper_address);
504 __ movl(Address(
THR, target::Thread::exit_through_ffi_offset()),
508 __ movl(Address(
THR, target::Thread::top_exit_frame_info_offset()),
515void StubCodeCompiler::GenerateCallNoScopeNativeStub() {
516 GenerateCallNativeWithWrapperStub(
519 target::Thread::no_scope_native_wrapper_entry_point_offset()));
522void StubCodeCompiler::GenerateCallAutoScopeNativeStub() {
523 GenerateCallNativeWithWrapperStub(
526 target::Thread::auto_scope_native_wrapper_entry_point_offset()));
535void StubCodeCompiler::GenerateCallBootstrapNativeStub() {
536 GenerateCallNativeWithWrapperStub(
539 target::Thread::bootstrap_native_wrapper_entry_point_offset()));
544void StubCodeCompiler::GenerateCallStaticFunctionStub() {
547 __ pushl(Immediate(0));
548 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
554 __ jmp(FieldAddress(
EAX, target::Code::entry_point_offset()));
560void StubCodeCompiler::GenerateFixCallersTargetStub() {
562 __ BranchOnMonomorphicCheckedEntryJIT(&monomorphic);
567 __ pushl(Immediate(0));
568 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
571 __ movl(
EAX, FieldAddress(
EAX, target::Code::entry_point_offset()));
576 __ Bind(&monomorphic);
579 __ pushl(Immediate(0));
582 __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
586 __ movl(
EAX, FieldAddress(
CODE_REG, target::Code::entry_point_offset(
595void StubCodeCompiler::GenerateFixAllocationStubTargetStub() {
597 __ pushl(Immediate(0));
598 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
600 __ movl(
EAX, FieldAddress(
EAX, target::Code::entry_point_offset()));
608void StubCodeCompiler::GenerateFixParameterizedAllocationStubTargetStub() {
612 __ pushl(Immediate(0));
613 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
617 __ movl(
EAX, FieldAddress(
EAX, target::Code::entry_point_offset()));
627static void PushArrayOfArguments(Assembler* assembler) {
629 const Immediate& raw_null = Immediate(target::ToRawPointer(
NullObject()));
630 __ movl(
ECX, raw_null);
638 target::frame_layout.param_end_from_fp * target::kWordSize));
639 __ leal(
ECX, FieldAddress(
EAX, target::Array::data_offset()));
642 Label loop, loop_condition;
648 __ AddImmediate(
ECX, Immediate(target::kWordSize));
649 __ AddImmediate(
EBX, Immediate(-target::kWordSize));
650 __ Bind(&loop_condition);
677static void GenerateDeoptimizationSequence(Assembler* assembler,
680 __ EnterDartFrame(0);
683 const intptr_t saved_result_slot_from_fp =
684 target::frame_layout.first_local_from_fp + 1 -
686 const intptr_t saved_exception_slot_from_fp =
687 target::frame_layout.first_local_from_fp + 1 -
689 const intptr_t saved_stacktrace_slot_from_fp =
690 target::frame_layout.first_local_from_fp + 1 -
700 __ pushl(Address(
EBP, 2 * target::kWordSize));
715 LeafRuntimeScope rt(assembler,
716 2 * target::kWordSize,
720 __ movl(Address(
ESP, 0 * target::kWordSize),
722 __ movl(Address(
ESP, 1 * target::kWordSize), Immediate(is_lazy ? 1 : 0));
723 rt.Call(kDeoptimizeCopyFrameRuntimeEntry, 2);
729 __ movl(
EBX, Address(
EBP, saved_result_slot_from_fp * target::kWordSize));
733 Address(
EBP, saved_exception_slot_from_fp * target::kWordSize));
735 Address(
EBP, saved_stacktrace_slot_from_fp * target::kWordSize));
745 __ EnterDartFrame(0);
753 LeafRuntimeScope rt(assembler,
754 1 * target::kWordSize,
757 rt.Call(kDeoptimizeFillFrameRuntimeEntry, 1);
761 __ movl(
EBX, Address(
EBP, target::frame_layout.first_local_from_fp *
765 __ movl(
EBX, Address(
EBP, target::frame_layout.first_local_from_fp *
767 __ movl(
ECX, Address(
EBP, (target::frame_layout.first_local_from_fp - 1) *
786 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
814 __ CallRuntime(kReThrowRuntimeEntry, 3);
820void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub() {
829void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub() {
836void StubCodeCompiler::GenerateDeoptimizeStub() {
841static void GenerateNoSuchMethodDispatcherCode(Assembler* assembler) {
843 __ movl(
EDX, FieldAddress(
844 ECX, target::CallSiteData::arguments_descriptor_offset()));
847 __ movl(
EDI, FieldAddress(
EDX, target::ArgumentsDescriptor::size_offset()));
849 Address(
EBP,
EDI, TIMES_HALF_WORD_SIZE,
850 target::frame_layout.param_end_from_fp * target::kWordSize));
851 __ pushl(Immediate(0));
858 FieldAddress(
EDX, target::ArgumentsDescriptor::type_args_len_offset()),
864 __ Bind(&args_count_ok);
867 PushArrayOfArguments(assembler);
868 const intptr_t kNumArgs = 4;
869 __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
876static void GenerateDispatcherCode(Assembler* assembler,
877 Label* call_target_function) {
878 __ Comment(
"NoSuchMethodDispatch");
881 const Immediate& raw_null = Immediate(target::ToRawPointer(
NullObject()));
882 __ cmpl(
EAX, raw_null);
884 GenerateNoSuchMethodDispatcherCode(assembler);
887void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub() {
888 GenerateNoSuchMethodDispatcherCode(
assembler);
899void StubCodeCompiler::GenerateAllocateArrayStub() {
900 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
911 const Immediate& max_len =
919 const intptr_t fixed_size_plus_alignment_padding =
920 target::Array::header_size() +
924 fixed_size_plus_alignment_padding));
932 const intptr_t
cid = kArrayCid;
934 Address(
THR, target::Thread::top_offset()));
943 __ cmpl(
EBX, Address(
THR, target::Thread::end_offset()));
949 __ movl(Address(
THR, target::Thread::top_offset()),
EBX);
959 Label size_tag_overflow,
done;
961 __ cmpl(
EDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
963 __ shll(
EDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
967 __ Bind(&size_tag_overflow);
968 __ movl(
EDI, Immediate(0));
973 __ orl(
EDI, Immediate(tags));
975 target::Object::tags_offset()),
984 __ StoreIntoObjectNoBarrier(
987 target::Array::type_arguments_offset()),
993 target::Array::length_offset()),
1005 target::Array::header_size()));
1008 for (intptr_t
offset = 0;
offset < target::kObjectAlignment;
1009 offset += target::kWordSize) {
1016 __ addl(
EDI, Immediate(target::kObjectAlignment));
1019 __ WriteAllocationCanary(
EBX);
1024 __ Bind(&slow_case);
1028 __ EnterStubFrame();
1029 __ pushl(Immediate(0));
1032 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
1055void StubCodeCompiler::GenerateInvokeDartCodeStub() {
1056 const intptr_t kTargetCodeOffset = 2 * target::kWordSize;
1057 const intptr_t kArgumentsDescOffset = 3 * target::kWordSize;
1058 const intptr_t kArgumentsOffset = 4 * target::kWordSize;
1059 const intptr_t kThreadOffset = 5 * target::kWordSize;
1063 __ movl(
EAX, Address(
EBP, kThreadOffset));
1064 __ pushl(Address(
EAX, target::Thread::invoke_dart_code_stub_offset()));
1074#if defined(USING_SHADOW_CALL_STACK)
1084 __ movl(
EDX, Address(
THR, target::Thread::top_resource_offset()));
1086 __ movl(Address(
THR, target::Thread::top_resource_offset()), Immediate(0));
1087 __ movl(
EAX, Address(
THR, target::Thread::exit_through_ffi_offset()));
1089 __ movl(Address(
THR, target::Thread::exit_through_ffi_offset()),
1093 ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -8);
1094 __ movl(
EDX, Address(
THR, target::Thread::top_exit_frame_info_offset()));
1096 __ movl(Address(
THR, target::Thread::top_exit_frame_info_offset()),
1101 __ EmitEntryFrameVerification();
1108 __ movl(
EDX, Address(
EBP, kArgumentsDescOffset));
1111 __ movl(
EBX, FieldAddress(
EDX, target::ArgumentsDescriptor::count_offset()));
1113 FieldAddress(
EDX, target::ArgumentsDescriptor::type_args_len_offset()),
1115 Label args_count_ok;
1118 __ Bind(&args_count_ok);
1120 __ movl(Address(
EBP, kArgumentsDescOffset),
EBX);
1124 Label push_arguments;
1125 Label done_push_arguments;
1128 __ movl(
EAX, Immediate(0));
1131 __ movl(
EDI, Address(
EBP, kArgumentsOffset));
1132 __ leal(
EDI, FieldAddress(
EDI, target::Array::data_offset()));
1134 __ Bind(&push_arguments);
1140 __ Bind(&done_push_arguments);
1143 __ movl(
EAX, Address(
EBP, kTargetCodeOffset));
1144 __ call(FieldAddress(
EAX, target::Code::entry_point_offset()));
1147 __ movl(
EDX, Address(
EBP, kArgumentsDescOffset));
1153 __ popl(Address(
THR, target::Thread::top_exit_frame_info_offset()));
1154 __ popl(Address(
THR, target::Thread::exit_through_ffi_offset()));
1155 __ popl(Address(
THR, target::Thread::top_resource_offset()));
1160#if defined(USING_SHADOW_CALL_STACK)
1183static void GenerateAllocateContextSpaceStub(Assembler* assembler,
1187 intptr_t fixed_size_plus_alignment_padding =
1188 (target::Context::header_size() +
1190 __ leal(
EBX, Address(
EDX,
TIMES_4, fixed_size_plus_alignment_padding));
1197 __ movl(
EAX, Address(
THR, target::Thread::top_offset()));
1203 __ cmpl(
EBX, Address(
THR, target::Thread::end_offset()));
1210 __ CheckAllocationCanary(
EAX);
1217 __ movl(Address(
THR, target::Thread::top_offset()),
EBX);
1227 Label size_tag_overflow,
done;
1228 __ leal(
EBX, Address(
EDX,
TIMES_4, fixed_size_plus_alignment_padding));
1230 __ cmpl(
EBX, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
1232 __ shll(
EBX, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
1236 __ Bind(&size_tag_overflow);
1238 __ movl(
EBX, Immediate(0));
1245 __ orl(
EBX, Immediate(tags));
1246 __ movl(FieldAddress(
EAX, target::Object::tags_offset()),
EBX);
1252 __ movl(FieldAddress(
EAX, target::Context::num_variables_offset()),
EDX);
1262void StubCodeCompiler::GenerateAllocateContextStub() {
1263 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1266 GenerateAllocateContextSpaceStub(
assembler, &slow_case);
1272 __ StoreObjectIntoObjectNoBarrier(
1280 __ leal(
EBX, FieldAddress(
EAX, target::Context::variable_offset(0)));
1289 __ cmpl(
EDX, Immediate(0));
1297 __ Bind(&slow_case);
1301 __ EnterStubFrame();
1302 __ pushl(Immediate(0));
1305 __ CallRuntime(kAllocateContextRuntimeEntry, 1);
1328void StubCodeCompiler::GenerateCloneContextStub() {
1329 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
1333 __ movl(
EDX, FieldAddress(
ECX, target::Context::num_variables_offset()));
1335 GenerateAllocateContextSpaceStub(
assembler, &slow_case);
1340 __ movl(
EBX, FieldAddress(
ECX, target::Context::parent_offset()));
1341 __ StoreIntoObjectNoBarrier(
1342 EAX, FieldAddress(
EAX, target::Context::parent_offset()),
EBX);
1356 target::Context::variable_offset(0)));
1357 __ StoreIntoObjectNoBarrier(
1359 FieldAddress(
EAX,
EDX,
TIMES_4, target::Context::variable_offset(0)),
1363 __ cmpl(
EDX, Immediate(0));
1371 __ Bind(&slow_case);
1376 __ EnterStubFrame();
1377 __ pushl(Immediate(0));
1379 __ CallRuntime(kCloneContextRuntimeEntry, 1);
1394void StubCodeCompiler::GenerateWriteBarrierWrappersStub() {
1399 intptr_t
start =
__ CodeSize();
1402 __ call(Address(
THR, target::Thread::write_barrier_entry_point_offset()));
1405 intptr_t
end =
__ CodeSize();
1422static void GenerateWriteBarrierStubHelper(Assembler* assembler,
bool cards) {
1428 __ movl(
EAX, FieldAddress(
EBX, target::Object::tags_offset()));
1429 __ andl(
EAX, Address(
THR, target::Thread::write_barrier_mask_offset()));
1430 __ testl(
EAX, Immediate(target::UntaggedObject::kIncrementalBarrierMask));
1431 __ j(
ZERO, &skip_marking);
1436 __ movl(
EAX, FieldAddress(
EBX, target::Object::tags_offset()));
1439 __ testl(
ECX, Immediate(1 << target::UntaggedObject::kNotMarkedBit));
1441 __ andl(
ECX, Immediate(~(1 << target::UntaggedObject::kNotMarkedBit)));
1444 __ LockCmpxchgl(FieldAddress(
EBX, target::Object::tags_offset()),
ECX);
1447 __ movl(
EAX, Address(
THR, target::Thread::marking_stack_block_offset()));
1458 LeafRuntimeScope rt(assembler,
1459 1 * target::kWordSize,
1462 rt.Call(kMarkingStackBlockProcessRuntimeEntry, 1);
1468 Label add_to_remembered_set, remember_card;
1469 __ Bind(&skip_marking);
1470 __ movl(
EAX, FieldAddress(
EDX, target::Object::tags_offset()));
1471 __ shrl(
EAX, Immediate(target::UntaggedObject::kBarrierOverlapShift));
1472 __ andl(
EAX, FieldAddress(
EBX, target::Object::tags_offset()));
1473 __ testl(
EAX, Immediate(target::UntaggedObject::kGenerationalBarrierMask));
1479 __ Bind(&add_to_remembered_set);
1481 __ testl(FieldAddress(
EDX, target::Object::tags_offset()),
1482 Immediate(1 << target::UntaggedObject::kCardRememberedBit));
1487 __ testl(FieldAddress(
EDX, target::Object::tags_offset()),
1488 Immediate(1 << target::UntaggedObject::kCardRememberedBit));
1490 __ Stop(
"Wrong barrier");
1498 __ movl(
EAX, FieldAddress(
EDX, target::Object::tags_offset()));
1502 Immediate(1 << target::UntaggedObject::kOldAndNotRememberedBit));
1505 Immediate(~(1 << target::UntaggedObject::kOldAndNotRememberedBit)));
1508 __ LockCmpxchgl(FieldAddress(
EDX, target::Object::tags_offset()),
ECX);
1515 __ movl(
EAX, Address(
THR, target::Thread::store_buffer_block_offset()));
1531 LeafRuntimeScope rt(assembler,
1532 1 * target::kWordSize,
1535 rt.Call(kStoreBufferBlockProcessRuntimeEntry, 1);
1544 Label remember_card_slow;
1547 __ Bind(&remember_card);
1550 __ cmpl(Address(
EAX, target::Page::card_table_offset()), Immediate(0));
1558 Address(
EAX, target::Page::card_table_offset()));
1561 Immediate(target::Page::kBytesPerCardLog2 +
1562 target::kBitsPerWordLog2));
1563 __ shrl(
ECX, Immediate(target::Page::kBytesPerCardLog2));
1564 __ movl(
EBX, Immediate(1));
1573 __ Bind(&remember_card_slow);
1576 LeafRuntimeScope rt(assembler,
1577 2 * target::kWordSize,
1579 __ movl(Address(
ESP, 0 * target::kWordSize),
EDX);
1580 __ movl(Address(
ESP, 1 * target::kWordSize),
EDI);
1581 rt.Call(kRememberCardRuntimeEntry, 2);
1589void StubCodeCompiler::GenerateWriteBarrierStub() {
1590 GenerateWriteBarrierStubHelper(
assembler,
false);
1593void StubCodeCompiler::GenerateArrayWriteBarrierStub() {
1594 GenerateWriteBarrierStubHelper(
assembler,
true);
1597void StubCodeCompiler::GenerateAllocateObjectStub() {
1601void StubCodeCompiler::GenerateAllocateObjectParameterizedStub() {
1605void StubCodeCompiler::GenerateAllocateObjectSlowStub() {
1620 const Code& allocate_object,
1621 const Code& allocat_object_parametrized) {
1622 const Immediate& raw_null = Immediate(target::ToRawPointer(
NullObject()));
1624 const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
1625 ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
1626 cls) != target::Class::kNoTypeArguments);
1630 const int kInlineInstanceSize = 12;
1631 const intptr_t instance_size = target::Class::GetInstanceSize(cls);
1632 ASSERT(instance_size > 0);
1636 if (!FLAG_use_slow_path && FLAG_inline_alloc &&
1637 target::Heap::IsAllocatableInNewSpace(instance_size) &&
1638 !target::Class::TraceAllocation(cls)) {
1645 Address(
THR, target::Thread::top_offset()));
1650 __ cmpl(
EBX, Address(
THR, target::Thread::end_offset()));
1653 __ movl(Address(
THR, target::Thread::top_offset()),
EBX);
1675 if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
1678 for (intptr_t current_offset = target::Instance::first_field_offset();
1679 current_offset < instance_size;
1680 current_offset += target::kWordSize) {
1681 __ StoreObjectIntoObjectNoBarrier(
1688 target::Instance::first_field_offset()));
1697 for (intptr_t
offset = 0;
offset < target::kObjectAlignment;
1698 offset += target::kWordSize) {
1704 __ addl(
ECX, Immediate(target::kObjectAlignment));
1707 __ WriteAllocationCanary(
EBX);
1709 if (is_cls_parameterized) {
1713 const intptr_t
offset = target::Class::TypeArgumentsFieldOffset(cls);
1714 __ StoreIntoObjectNoBarrier(
1723 __ Bind(&slow_case);
1729 __ EnterStubFrame();
1732 CastHandle<Object>(cls));
1733 if (is_cls_parameterized) {
1739 __ CallRuntime(kAllocateObjectRuntimeEntry, 2);
1764void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub() {
1765 __ EnterStubFrame();
1768 __ movl(
EDI, FieldAddress(
EDX, target::ArgumentsDescriptor::size_offset()));
1771 target::frame_layout.param_end_from_fp * target::kWordSize));
1774 __ movl(
EBX, FieldAddress(
EAX, target::Closure::function_offset()));
1776 __ pushl(Immediate(0));
1783 FieldAddress(
EDX, target::ArgumentsDescriptor::type_args_len_offset()),
1786 Label args_count_ok;
1789 __ Bind(&args_count_ok);
1794 const intptr_t kNumArgs = 4;
1795 __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
1805 if (FLAG_trace_optimized_ic_calls) {
1806 __ EnterStubFrame();
1811 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1818 __ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
1823 if (FLAG_optimization_counter_threshold >= 0) {
1826 __ Comment(
"Increment function counter");
1828 FieldAddress(
IC_DATA_REG, target::ICData::owner_offset()));
1829 __ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
1837static void EmitFastSmiOp(Assembler* assembler,
1840 Label* not_smi_or_overflow) {
1841 __ Comment(
"Fast Smi op");
1843 __ movl(
EAX, Address(
ESP, +2 * target::kWordSize));
1844 __ movl(
EDI, Address(
ESP, +1 * target::kWordSize));
1856 Label
done, is_true;
1861 Address(
THR,
EAX,
TIMES_4, target::Thread::bool_true_offset()));
1862 ASSERT(target::Thread::bool_true_offset() + 4 ==
1863 target::Thread::bool_false_offset());
1867 Label
done, is_true;
1872 Address(
THR,
EAX,
TIMES_4, target::Thread::bool_true_offset()));
1873 ASSERT(target::Thread::bool_true_offset() + 4 ==
1874 target::Thread::bool_false_offset());
1882 __ movl(
EBX, FieldAddress(
ECX, target::ICData::entries_offset()));
1884 __ leal(
EBX, FieldAddress(
EBX, target::Array::data_offset()));
1889 __ cmpl(Address(
EBX, 0 * target::kWordSize), imm_smi_cid);
1891 __ cmpl(Address(
EBX, 1 * target::kWordSize), imm_smi_cid);
1894 __ Stop(
"Incorrect IC data");
1897 if (FLAG_optimization_counter_threshold >= 0) {
1898 const intptr_t count_offset =
1899 target::ICData::CountIndexFor(num_args) * target::kWordSize;
1919 const RuntimeEntry& handle_ic_miss,
1921 Optimized optimized,
1923 Exactness exactness) {
1925 optimized,
type, exactness,
1927 __ BindUncheckedEntryPoint();
1929 optimized,
type, exactness,
1935 const RuntimeEntry& handle_ic_miss,
1937 Optimized optimized,
1939 Exactness exactness,
1947 ASSERT(num_args == 1 || num_args == 2);
1953 __ movl(
EAX, FieldAddress(
ECX, target::ICData::state_bits_offset()));
1954 ASSERT(target::ICData::NumArgsTestedShift() == 0);
1955 __ andl(
EAX, Immediate(target::ICData::NumArgsTestedMask()));
1956 __ cmpl(
EAX, Immediate(num_args));
1958 __ Stop(
"Incorrect stub for IC data");
1963#if !defined(PRODUCT)
1964 Label stepping, done_stepping;
1966 __ Comment(
"Check single stepping");
1967 __ LoadIsolate(
EAX);
1968 __ cmpb(Address(
EAX, target::Isolate::single_step_offset()), Immediate(0));
1970 __ Bind(&done_stepping);
1973 Label not_smi_or_overflow;
1974 if (kind != Token::kILLEGAL) {
1975 EmitFastSmiOp(
assembler, kind, num_args, ¬_smi_or_overflow);
1977 __ Bind(¬_smi_or_overflow);
1979 __ Comment(
"Extract ICData initial values and receiver cid");
1984 FieldAddress(
ECX, target::CallSiteData::arguments_descriptor_offset()));
1986 Label loop, found, miss;
1988 __ movl(
EBX, FieldAddress(
ECX, target::ICData::entries_offset()));
1990 __ leal(
EBX, FieldAddress(
EBX, target::Array::data_offset()));
1998 target::ArgumentsDescriptor::count_offset()));
1999 if (num_args == 1) {
2003 __ LoadTaggedClassIdMayBeSmi(
EAX,
EDI);
2007 __ Comment(
"ICData loop");
2010 bool optimize = kind == Token::kILLEGAL;
2011 const intptr_t target_offset =
2012 target::ICData::TargetIndexFor(num_args) * target::kWordSize;
2013 const intptr_t count_offset =
2014 target::ICData::CountIndexFor(num_args) * target::kWordSize;
2015 const intptr_t exactness_offset =
2016 target::ICData::ExactnessIndexFor(num_args) * target::kWordSize;
2017 const intptr_t entry_size = target::ICData::TestEntryLengthFor(
2022 for (
int unroll =
optimize ? 4 : 2; unroll >= 0; unroll--) {
2024 if (num_args == 1) {
2028 __ addl(
EBX, Immediate(entry_size));
2034 __ LoadTaggedClassIdMayBeSmi(
EDI,
EDI);
2040 __ LoadTaggedClassIdMayBeSmi(
EDI,
EDI);
2041 __ cmpl(
EDI, Address(
EBX, target::kWordSize));
2045 __ addl(
EBX, Immediate(entry_size));
2046 __ cmpl(Address(
EBX, -entry_size),
2058 __ Comment(
"IC miss");
2062 target::ArgumentsDescriptor::count_offset()));
2066 __ EnterStubFrame();
2069 __ pushl(Immediate(0));
2071 for (intptr_t i = 0; i < num_args; i++) {
2072 __ movl(
EBX, Address(
EAX, -target::kWordSize * i));
2076 __ CallRuntime(handle_ic_miss, num_args + 1);
2078 for (intptr_t i = 0; i < num_args + 1; i++) {
2085 Label call_target_function;
2086 if (!FLAG_lazy_dispatchers) {
2087 GenerateDispatcherCode(
assembler, &call_target_function);
2089 __ jmp(&call_target_function);
2094 Label call_target_function_through_unchecked_entry;
2098 __ movl(
EDI, Address(
EBX, exactness_offset));
2101 __ j(
LESS, &exactness_ok);
2102 __ j(
EQUAL, &call_target_function_through_unchecked_entry);
2108 target::ArgumentsDescriptor::count_offset()));
2116 FieldAddress(
ECX, target::ICData::receivers_static_type_offset()));
2117 __ cmpl(
EDI, FieldAddress(
EAX, target::Type::arguments_offset()));
2118 __ j(
EQUAL, &call_target_function_through_unchecked_entry);
2121 __ movl(Address(
EBX, exactness_offset),
2124 __ Bind(&exactness_ok);
2127 if (FLAG_optimization_counter_threshold >= 0) {
2128 __ Comment(
"Update caller's counter");
2134 __ Bind(&call_target_function);
2135 __ Comment(
"Call target");
2138 target::Function::entry_point_offset(entry_kind)));
2141 __ Bind(&call_target_function_through_unchecked_entry);
2142 if (FLAG_optimization_counter_threshold >= 0) {
2143 __ Comment(
"Update ICData counter");
2147 __ Comment(
"Call target (via unchecked entry point)");
2149 __ jmp(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset(
2153#if !defined(PRODUCT)
2156 __ EnterStubFrame();
2159 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2163 __ jmp(&done_stepping);
2171void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub() {
2173 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
2180void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub() {
2182 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
2186void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub() {
2187 __ Stop(
"Unimplemented");
2190void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub() {
2191 __ Stop(
"Unimplemented");
2197void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub() {
2199 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2206void StubCodeCompiler::GenerateSmiAddInlineCacheStub() {
2208 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
kUnoptimized,
2215void StubCodeCompiler::GenerateSmiLessInlineCacheStub() {
2217 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
kUnoptimized,
2224void StubCodeCompiler::GenerateSmiEqualInlineCacheStub() {
2226 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
kUnoptimized,
2234void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub() {
2236 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
kOptimized,
2244void StubCodeCompiler::
2245 GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub() {
2247 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
kOptimized,
2255void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub() {
2257 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2263static void GenerateZeroArgsUnoptimizedStaticCallForEntryKind(
2264 StubCodeCompiler* stub_code_compiler,
2266 stub_code_compiler->GenerateUsageCounterIncrement(
EAX);
2267 auto*
const assembler = stub_code_compiler->assembler;
2274 __ movl(
EBX, FieldAddress(
ECX, target::ICData::state_bits_offset()));
2275 ASSERT(target::ICData::NumArgsTestedShift() == 0);
2276 __ andl(
EBX, Immediate(target::ICData::NumArgsTestedMask()));
2277 __ cmpl(
EBX, Immediate(0));
2279 __ Stop(
"Incorrect IC data for unoptimized static call");
2284#if !defined(PRODUCT)
2286 Label stepping, done_stepping;
2287 __ LoadIsolate(
EAX);
2288 __ cmpb(Address(
EAX, target::Isolate::single_step_offset()), Immediate(0));
2290 __ Bind(&done_stepping);
2294 __ movl(
EBX, FieldAddress(
ECX, target::ICData::entries_offset()));
2296 __ leal(
EBX, FieldAddress(
EBX, target::Array::data_offset()));
2298 const intptr_t target_offset =
2299 target::ICData::TargetIndexFor(0) * target::kWordSize;
2300 const intptr_t count_offset =
2301 target::ICData::CountIndexFor(0) * target::kWordSize;
2303 if (FLAG_optimization_counter_threshold >= 0) {
2311 FieldAddress(
ECX, target::CallSiteData::arguments_descriptor_offset()));
2316 target::Function::entry_point_offset(entry_kind)));
2318#if !defined(PRODUCT)
2320 __ EnterStubFrame();
2322 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2329void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub() {
2330 GenerateZeroArgsUnoptimizedStaticCallForEntryKind(
this,
2332 __ BindUncheckedEntryPoint();
2333 GenerateZeroArgsUnoptimizedStaticCallForEntryKind(
this,
2339void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub() {
2341 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2347void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub() {
2349 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
2356void StubCodeCompiler::GenerateLazyCompileStub() {
2357 __ EnterStubFrame();
2360 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
2365 __ jmp(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
2369void StubCodeCompiler::GenerateICCallBreakpointStub() {
2371 __ Stop(
"No debugging in PRODUCT mode");
2373 __ EnterStubFrame();
2376 __ pushl(Immediate(0));
2377 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
2383 __ jmp(FieldAddress(
EAX, target::Code::entry_point_offset()));
2387void StubCodeCompiler::GenerateUnoptStaticCallBreakpointStub() {
2389 __ Stop(
"No debugging in PRODUCT mode");
2391 __ EnterStubFrame();
2393 __ pushl(Immediate(0));
2394 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
2399 __ jmp(FieldAddress(
EAX, target::Code::entry_point_offset()));
2403void StubCodeCompiler::GenerateRuntimeCallBreakpointStub() {
2405 __ Stop(
"No debugging in PRODUCT mode");
2407 __ EnterStubFrame();
2410 __ pushl(Immediate(0));
2411 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
2415 __ jmp(FieldAddress(
EAX, target::Code::entry_point_offset()));
2420void StubCodeCompiler::GenerateDebugStepCheckStub() {
2422 __ Stop(
"No debugging in PRODUCT mode");
2425 Label stepping, done_stepping;
2426 __ LoadIsolate(
EAX);
2427 __ movzxb(
EAX, Address(
EAX, target::Isolate::single_step_offset()));
2428 __ cmpl(
EAX, Immediate(0));
2430 __ Bind(&done_stepping);
2434 __ EnterStubFrame();
2435 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2446struct STCInternal : AllStatic {
2448 static constexpr intptr_t kNoDepth = kIntptrMin;
2453 static constexpr intptr_t kFunctionTypeArgumentsDepth = 1;
2454 static constexpr intptr_t kInstantiatorTypeArgumentsDepth = 2;
2455 static constexpr intptr_t kDestinationTypeDepth = 3;
2456 static constexpr intptr_t kInstanceDepth = 4;
2457 static constexpr intptr_t kCacheDepth = 5;
2460 static constexpr Register kCacheArrayReg =
2461 TypeTestABI::kInstantiatorTypeArgumentsReg;
2462 static constexpr Register kScratchReg = TypeTestABI::kSubtypeTestCacheReg;
2463 static constexpr Register kInstanceCidOrSignatureReg =
2464 TypeTestABI::kFunctionTypeArgumentsReg;
2465 static constexpr Register kInstanceInstantiatorTypeArgumentsReg =
2466 TypeTestABI::kDstTypeReg;
2469static void GenerateSubtypeTestCacheLoop(
2470 Assembler* assembler,
2472 intptr_t original_tos_offset,
2473 intptr_t parent_function_type_args_depth,
2474 intptr_t delayed_type_args_depth,
2477 Label* next_iteration) {
2478 const auto& raw_null = Immediate(target::ToRawPointer(
NullObject()));
2481 auto compare_to_stack = [&](
Register src, intptr_t depth) {
2482 ASSERT(original_tos_offset + depth >= 0);
2483 __ CompareToStack(src, original_tos_offset + depth);
2486 __ LoadAcquireCompressedFromOffset(
2487 STCInternal::kScratchReg, STCInternal::kCacheArrayReg,
2488 target::kCompressedWordSize *
2489 target::SubtypeTestCache::kInstanceCidOrSignature);
2490 __ cmpl(STCInternal::kScratchReg, raw_null);
2492 __ cmpl(STCInternal::kScratchReg, STCInternal::kInstanceCidOrSignatureReg);
2498 __ cmpl(STCInternal::kInstanceInstantiatorTypeArgumentsReg,
2499 Address(STCInternal::kCacheArrayReg,
2501 target::SubtypeTestCache::kInstanceTypeArguments));
2507 __ movl(STCInternal::kScratchReg,
2508 Address(STCInternal::kCacheArrayReg,
2510 target::SubtypeTestCache::kInstantiatorTypeArguments));
2511 compare_to_stack(STCInternal::kScratchReg,
2512 STCInternal::kInstantiatorTypeArgumentsDepth);
2518 __ movl(STCInternal::kScratchReg,
2519 Address(STCInternal::kCacheArrayReg,
2521 target::SubtypeTestCache::kFunctionTypeArguments));
2522 compare_to_stack(STCInternal::kScratchReg,
2523 STCInternal::kFunctionTypeArgumentsDepth);
2530 STCInternal::kScratchReg,
2532 STCInternal::kCacheArrayReg,
2534 target::SubtypeTestCache::kInstanceParentFunctionTypeArguments));
2535 compare_to_stack(STCInternal::kScratchReg, parent_function_type_args_depth);
2542 STCInternal::kScratchReg,
2544 STCInternal::kCacheArrayReg,
2546 target::SubtypeTestCache::kInstanceDelayedFunctionTypeArguments));
2547 compare_to_stack(STCInternal::kScratchReg, delayed_type_args_depth);
2554 STCInternal::kScratchReg,
2555 Address(STCInternal::kCacheArrayReg,
2556 target::kWordSize * target::SubtypeTestCache::kDestinationType));
2557 compare_to_stack(STCInternal::kScratchReg,
2558 STCInternal::kDestinationTypeDepth);
2574void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler,
2582 const auto& raw_null = Immediate(target::ToRawPointer(
NullObject()));
2588 __ LoadFromStack(STCInternal::kCacheArrayReg, STCInternal::kCacheDepth);
2592 __ LoadFromSlot(STCInternal::kScratchReg, STCInternal::kCacheArrayReg,
2593 Slot::SubtypeTestCache_num_inputs());
2594 __ CompareImmediate(STCInternal::kScratchReg, n);
2597 __ Bind(&search_stc);
2601 __ movl(STCInternal::kCacheArrayReg,
2602 FieldAddress(STCInternal::kCacheArrayReg,
2603 target::SubtypeTestCache::cache_offset()));
2608 __ LoadFromSlot(STCInternal::kScratchReg, STCInternal::kCacheArrayReg,
2609 Slot::Array_length());
2610 __ CompareImmediate(STCInternal::kScratchReg,
2619 __ Bind(&is_linear);
2620 __ AddImmediate(STCInternal::kCacheArrayReg,
2623 Label loop, not_closure;
2625 __ LoadClassIdMayBeSmi(STCInternal::kInstanceCidOrSignatureReg,
2628 __ LoadClassId(STCInternal::kInstanceCidOrSignatureReg,
2631 __ cmpl(STCInternal::kInstanceCidOrSignatureReg, Immediate(kClosureCid));
2636 __ movl(STCInternal::kInstanceCidOrSignatureReg,
2638 target::Closure::function_offset()));
2639 __ movl(STCInternal::kInstanceCidOrSignatureReg,
2640 FieldAddress(STCInternal::kInstanceCidOrSignatureReg,
2641 target::Function::signature_offset()));
2644 STCInternal::kInstanceInstantiatorTypeArgumentsReg,
2646 target::Closure::instantiator_type_arguments_offset()));
2650 target::Closure::function_type_arguments_offset()));
2654 target::Closure::delayed_type_arguments_offset()));
2661 __ Bind(¬_closure);
2663 Label has_no_type_arguments;
2664 __ LoadClassById(STCInternal::kScratchReg,
2665 STCInternal::kInstanceCidOrSignatureReg);
2666 __ movl(STCInternal::kInstanceInstantiatorTypeArgumentsReg, raw_null);
2668 STCInternal::kScratchReg,
2669 FieldAddress(STCInternal::kScratchReg,
2671 host_type_arguments_field_offset_in_words_offset()));
2672 __ cmpl(STCInternal::kScratchReg,
2673 Immediate(target::Class::kNoTypeArguments));
2675 __ movl(STCInternal::kInstanceInstantiatorTypeArgumentsReg,
2678 __ Bind(&has_no_type_arguments);
2680 __ SmiTag(STCInternal::kInstanceCidOrSignatureReg);
2690 intptr_t original_tos_offset = 0;
2695 intptr_t kInstanceParentFunctionTypeArgumentsDepth = STCInternal::kNoDepth;
2696 intptr_t kInstanceDelayedFunctionTypeArgumentsDepth = STCInternal::kNoDepth;
2703 original_tos_offset++;
2704 kInstanceParentFunctionTypeArgumentsDepth = -original_tos_offset;
2707 original_tos_offset++;
2708 kInstanceDelayedFunctionTypeArgumentsDepth = -original_tos_offset;
2711 Label found, not_found,
done, next_iteration;
2715 GenerateSubtypeTestCacheLoop(
assembler, n, original_tos_offset,
2716 kInstanceParentFunctionTypeArgumentsDepth,
2717 kInstanceDelayedFunctionTypeArgumentsDepth,
2718 &found, ¬_found, &next_iteration);
2719 __ Bind(&next_iteration);
2720 __ addl(STCInternal::kCacheArrayReg,
2721 Immediate(target::kWordSize *
2722 target::SubtypeTestCache::kTestEntryLength));
2727 __ Drop(original_tos_offset);
2730 Address(STCInternal::kCacheArrayReg,
2731 target::kWordSize * target::SubtypeTestCache::kTestResult));
2734 __ Bind(¬_found);
2736 __ Drop(original_tos_offset);
2749void StubCodeCompiler::GenerateGetCStackPointerStub() {
2750 __ leal(
EAX, Address(
ESP, target::kWordSize));
2761void StubCodeCompiler::GenerateJumpToFrameStub() {
2762 __ movl(
THR, Address(
ESP, 4 * target::kWordSize));
2764 Address(
ESP, 3 * target::kWordSize));
2766 Address(
ESP, 1 * target::kWordSize));
2768 Address(
ESP, 2 * target::kWordSize));
2769#if defined(USING_SHADOW_CALL_STACK)
2773 Label exit_through_non_ffi;
2780 __ cmpl(compiler::Address(
2781 THR, compiler::target::Thread::exit_through_ffi_offset()),
2782 compiler::Immediate(target::Thread::exit_through_ffi()));
2784 __ TransitionNativeToGenerated(
ECX,
true,
2786 __ Bind(&exit_through_non_ffi);
2791 __ movl(Address(
THR, target::Thread::top_exit_frame_info_offset()),
2800void StubCodeCompiler::GenerateRunExceptionHandlerStub() {
2803 __ movl(
EBX, Address(
THR, target::Thread::resume_pc_offset()));
2809 Address exception_addr(
THR, target::Thread::active_exception_offset());
2811 __ movl(exception_addr,
ECX);
2814 Address stacktrace_addr(
THR, target::Thread::active_stacktrace_offset());
2816 __ movl(stacktrace_addr,
ECX);
2824void StubCodeCompiler::GenerateDeoptForRewindStub() {
2826 __ pushl(Address(
THR, target::Thread::resume_pc_offset()));
2830 __ EnterStubFrame();
2831 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0);
2839void StubCodeCompiler::GenerateOptimizeFunctionStub() {
2840 __ movl(
CODE_REG, Address(
THR, target::Thread::optimize_stub_offset()));
2841 __ EnterStubFrame();
2843 __ pushl(Immediate(0));
2845 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
2851 FieldAddress(
FUNCTION_REG, target::Function::code_offset()));
2852 __ jmp(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
2860static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
2864 Label reference_compare,
done, check_mint;
2872 __ CompareClassId(
left, kDoubleCid, temp);
2874 __ CompareClassId(
right, kDoubleCid, temp);
2878 __ movl(temp, FieldAddress(
left, target::Double::value_offset() +
2879 0 * target::kWordSize));
2880 __ cmpl(temp, FieldAddress(
right, target::Double::value_offset() +
2881 0 * target::kWordSize));
2883 __ movl(temp, FieldAddress(
left, target::Double::value_offset() +
2884 1 * target::kWordSize));
2885 __ cmpl(temp, FieldAddress(
right, target::Double::value_offset() +
2886 1 * target::kWordSize));
2889 __ Bind(&check_mint);
2890 __ CompareClassId(
left, kMintCid, temp);
2892 __ CompareClassId(
right, kMintCid, temp);
2894 __ movl(temp, FieldAddress(
left, target::Mint::value_offset() +
2895 0 * target::kWordSize));
2896 __ cmpl(temp, FieldAddress(
right, target::Mint::value_offset() +
2897 0 * target::kWordSize));
2899 __ movl(temp, FieldAddress(
left, target::Mint::value_offset() +
2900 1 * target::kWordSize));
2901 __ cmpl(temp, FieldAddress(
right, target::Mint::value_offset() +
2902 1 * target::kWordSize));
2905 __ Bind(&reference_compare);
2915void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub() {
2916#if !defined(PRODUCT)
2918 Label stepping, done_stepping;
2919 __ LoadIsolate(
EAX);
2920 __ movzxb(
EAX, Address(
EAX, target::Isolate::single_step_offset()));
2921 __ cmpl(
EAX, Immediate(0));
2923 __ Bind(&done_stepping);
2929 __ movl(
left, Address(
ESP, 2 * target::kWordSize));
2930 __ movl(
right, Address(
ESP, 1 * target::kWordSize));
2934#if !defined(PRODUCT)
2936 __ EnterStubFrame();
2937 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2939 __ jmp(&done_stepping);
2948void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub() {
2952 __ movl(
left, Address(
ESP, 2 * target::kWordSize));
2953 __ movl(
right, Address(
ESP, 1 * target::kWordSize));
2965void StubCodeCompiler::GenerateMegamorphicCallStub() {
2977 __ Bind(&cid_loaded);
2980 FieldAddress(
IC_DATA_REG, target::MegamorphicCache::mask_offset()));
2982 target::MegamorphicCache::buckets_offset()));
2990 ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
2999 const intptr_t
base = target::Array::data_offset();
3006 __ Bind(&load_target);
3015 target::CallSiteData::arguments_descriptor_offset()));
3017 __ jmp(FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
3019 __ Bind(&probe_failed);
3032 __ movl(
EAX, Immediate(kSmiCid));
3033 __ jmp(&cid_loaded);
3037 GenerateSwitchableCallMissStub();
3040void StubCodeCompiler::GenerateICCallThroughCodeStub() {
3044void StubCodeCompiler::GenerateMonomorphicSmiableCheckStub() {
3050void StubCodeCompiler::GenerateSwitchableCallMissStub() {
3052 Address(
THR, target::Thread::switchable_call_miss_stub_offset()));
3053 __ EnterStubFrame();
3056 __ pushl(Immediate(0));
3057 __ pushl(Immediate(0));
3059 __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
3067 __ movl(
EAX, FieldAddress(
CODE_REG, target::Code::entry_point_offset(
3072void StubCodeCompiler::GenerateSingleTargetCallStub() {
3093void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(intptr_t
cid) {
3101 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
3116 __ cmpl(
EDI, Immediate(max_len));
3126 const intptr_t fixed_size_plus_alignment_padding =
3127 target::TypedData::HeaderSize() +
3129 __ leal(
EDI, Address(
EDI, scale_factor, fixed_size_plus_alignment_padding));
3131 __ movl(
EAX, Address(
THR, target::Thread::top_offset()));
3141 __ cmpl(
EBX, Address(
THR, target::Thread::end_offset()));
3143 __ CheckAllocationCanary(
EAX);
3147 __ movl(Address(
THR, target::Thread::top_offset()),
EBX);
3155 Label size_tag_overflow,
done;
3156 __ cmpl(
EDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
3158 __ shll(
EDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
3161 __ Bind(&size_tag_overflow);
3162 __ movl(
EDI, Immediate(0));
3167 __ orl(
EDI, Immediate(tags));
3168 __ movl(FieldAddress(
EAX, target::Object::tags_offset()),
3176 __ StoreIntoObjectNoBarrier(
3177 EAX, FieldAddress(
EAX, target::TypedDataBase::length_offset()),
EDI);
3186 __ leal(
EDI, FieldAddress(
EAX, target::TypedData::HeaderSize()));
3187 __ StoreInternalPointer(
3188 EAX, FieldAddress(
EAX, target::PointerBase::data_offset()),
EDI);
3191 for (intptr_t
offset = 0;
offset < target::kObjectAlignment;
3192 offset += target::kWordSize) {
3197 __ addl(
EDI, Immediate(target::kObjectAlignment));
3200 __ WriteAllocationCanary(
EBX);
3204 __ Bind(&call_runtime);
3208 __ EnterStubFrame();
3209 __ PushObject(Object::null_object());
3212 __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
3215 __ 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 ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
#define COMPILE_ASSERT(expr)
virtual bool WillAllocateNewOrRemembered() const
static intptr_t ActivationFrameAlignment()
static intptr_t pointers_offset()
static intptr_t top_offset()
static StaticTypeExactnessState HasExactSuperType()
static StaticTypeExactnessState NotExact()
static constexpr intptr_t kMaxLinearCacheSize
static constexpr intptr_t kMaxInputs
static Address VMTagAddress()
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 GenerateNArgsCheckInlineCacheStubForEntryKind(intptr_t num_args, const RuntimeEntry &handle_ic_miss, Token::Kind kind, Optimized optimized, CallType type, Exactness exactness, CodeEntryKind entry_kind)
void GenerateOptimizedUsageCounterIncrement()
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)
word TypedDataMaxNewSpaceElements(classid_t cid)
word TypedDataElementSizeInBytes(classid_t cid)
GrowableArray< UnresolvedPcRelativeCall * > UnresolvedPcRelativeCalls
const Object & NullObject()
const Code & StubCodeAllocateArray()
const Register kWriteBarrierSlotReg
const Register kExceptionObjectReg
const Register kWriteBarrierObjectReg
Thread * DLRT_GetFfiCallbackMetadata(FfiCallbackMetadata::Trampoline trampoline, uword *out_entry_point, uword *out_trampoline_type)
const Register kWriteBarrierValueReg
static constexpr bool IsCalleeSavedRegister(Register reg)
static constexpr uword kZapReturnAddress
void DLRT_ExitTemporaryIsolate()
const Register ARGS_DESC_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 intptr_t kAllocationRedZoneSize
const Register kStackTraceObjectReg
const int kFpuRegisterSize
static constexpr Register kResultReg
static constexpr Register kLengthReg
static constexpr Register kTypeArgumentsReg
static constexpr Register kTypeArgumentsReg
static constexpr Register kResultReg
static constexpr Register kLengthReg
static constexpr Register kResultReg
static constexpr intptr_t kObjectAlignmentLog2
static constexpr intptr_t kObjectAlignment
static constexpr Register kInstanceReg
static constexpr Register kSubtypeTestCacheResultReg
#define NOT_IN_PRODUCT(code)