OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments))); | 73 __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments))); |
74 if (OS::ActivationFrameAlignment() > 1) { | 74 if (OS::ActivationFrameAlignment() > 1) { |
75 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); | 75 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
76 } | 76 } |
77 | 77 |
78 // Pass NativeArguments structure by value and call runtime. | 78 // Pass NativeArguments structure by value and call runtime. |
79 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs. | 79 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs. |
80 // There are no runtime calls to closures, so we do not need to set the tag | 80 // There are no runtime calls to closures, so we do not need to set the tag |
81 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. | 81 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. |
82 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments. | 82 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments. |
83 __ leal(EAX, Address(EBP, EDX, TIMES_4, 1 * kWordSize)); // Compute argv. | 83 // Compute argv. |
| 84 __ leal(EAX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
84 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. | 85 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. |
85 __ addl(EAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument. | 86 __ addl(EAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument. |
86 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. | 87 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. |
87 __ call(ECX); | 88 __ call(ECX); |
88 | 89 |
89 // Mark that the isolate is executing Dart code. EDI is callee saved. | 90 // Mark that the isolate is executing Dart code. EDI is callee saved. |
90 __ movl(Address(EDI, Isolate::vm_tag_offset()), | 91 __ movl(Address(EDI, Isolate::vm_tag_offset()), |
91 Immediate(VMTag::kDartTagId)); | 92 Immediate(VMTag::kDartTagId)); |
92 | 93 |
93 // Reset exit frame information in Isolate structure. | 94 // Reset exit frame information in Isolate structure. |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 // - Materialize objects that require allocation (e.g. Double instances). | 363 // - Materialize objects that require allocation (e.g. Double instances). |
363 // GC can occur only after frame is fully rewritten. | 364 // GC can occur only after frame is fully rewritten. |
364 // Stack after EnterDartFrame(0) below: | 365 // Stack after EnterDartFrame(0) below: |
365 // +------------------+ | 366 // +------------------+ |
366 // | PC marker | <- TOS | 367 // | PC marker | <- TOS |
367 // +------------------+ | 368 // +------------------+ |
368 // | Saved FP | <- FP of stub | 369 // | Saved FP | <- FP of stub |
369 // +------------------+ | 370 // +------------------+ |
370 // | return-address | (deoptimization point) | 371 // | return-address | (deoptimization point) |
371 // +------------------+ | 372 // +------------------+ |
| 373 // | Saved CODE_REG | |
| 374 // +------------------+ |
372 // | ... | <- SP of optimized frame | 375 // | ... | <- SP of optimized frame |
373 // | 376 // |
374 // Parts of the code cannot GC, part of the code can GC. | 377 // Parts of the code cannot GC, part of the code can GC. |
375 static void GenerateDeoptimizationSequence(Assembler* assembler, | 378 static void GenerateDeoptimizationSequence(Assembler* assembler, |
376 bool preserve_result) { | 379 DeoptStubKind kind) { |
377 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. | 380 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. |
378 __ EnterDartFrame(0); | 381 __ EnterDartFrame(0); |
379 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 382 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
380 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 383 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
381 const intptr_t saved_result_slot_from_fp = | 384 const intptr_t saved_result_slot_from_fp = |
382 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - EAX); | 385 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - EAX); |
383 // Result in EAX is preserved as part of pushing all registers below. | 386 // Result in EAX is preserved as part of pushing all registers below. |
384 | 387 |
385 // Push registers in their enumeration order: lowest register number at | 388 // Push registers in their enumeration order: lowest register number at |
386 // lowest address. | 389 // lowest address. |
387 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { | 390 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
388 __ pushl(static_cast<Register>(i)); | 391 if (i == CODE_REG) { |
| 392 // Save the original value of CODE_REG pushed before invoking this stub |
| 393 // instead of the value used to call this stub. |
| 394 __ pushl(Address(EBP, 2 * kWordSize)); |
| 395 } else { |
| 396 __ pushl(static_cast<Register>(i)); |
| 397 } |
389 } | 398 } |
390 __ subl(ESP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); | 399 __ subl(ESP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); |
391 intptr_t offset = 0; | 400 intptr_t offset = 0; |
392 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 401 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
393 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 402 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
394 __ movups(Address(ESP, offset), xmm_reg); | 403 __ movups(Address(ESP, offset), xmm_reg); |
395 offset += kFpuRegisterSize; | 404 offset += kFpuRegisterSize; |
396 } | 405 } |
397 | 406 |
398 __ movl(ECX, ESP); // Preserve saved registers block. | 407 __ movl(ECX, ESP); // Preserve saved registers block. |
399 __ ReserveAlignedFrameSpace(1 * kWordSize); | 408 __ ReserveAlignedFrameSpace(2 * kWordSize); |
400 __ movl(Address(ESP, 0), ECX); // Start of register block. | 409 __ movl(Address(ESP, 0 * kWordSize), ECX); // Start of register block. |
401 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); | 410 __ movl(Address(ESP, 1 * kWordSize), Immediate(kind == kLazyDeopt ? 1 : 0)); |
| 411 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); |
402 // Result (EAX) is stack-size (FP - SP) in bytes. | 412 // Result (EAX) is stack-size (FP - SP) in bytes. |
403 | 413 |
| 414 const bool preserve_result = (kind == kLazyDeopt); |
404 if (preserve_result) { | 415 if (preserve_result) { |
405 // Restore result into EBX temporarily. | 416 // Restore result into EBX temporarily. |
406 __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize)); | 417 __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize)); |
407 } | 418 } |
408 | 419 |
409 __ LeaveFrame(); | 420 __ LeaveFrame(); |
410 __ popl(EDX); // Preserve return address. | 421 __ popl(EDX); // Preserve return address. |
411 __ movl(ESP, EBP); // Discard optimized frame. | 422 __ movl(ESP, EBP); // Discard optimized frame. |
412 __ subl(ESP, EAX); // Reserve space for deoptimized frame. | 423 __ subl(ESP, EAX); // Reserve space for deoptimized frame. |
413 __ pushl(EDX); // Restore return address. | 424 __ pushl(EDX); // Restore return address. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 | 464 |
454 | 465 |
455 // TOS: return address + call-instruction-size (5 bytes). | 466 // TOS: return address + call-instruction-size (5 bytes). |
456 // EAX: result, must be preserved | 467 // EAX: result, must be preserved |
457 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { | 468 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { |
458 // Correct return address to point just after the call that is being | 469 // Correct return address to point just after the call that is being |
459 // deoptimized. | 470 // deoptimized. |
460 __ popl(EBX); | 471 __ popl(EBX); |
461 __ subl(EBX, Immediate(CallPattern::pattern_length_in_bytes())); | 472 __ subl(EBX, Immediate(CallPattern::pattern_length_in_bytes())); |
462 __ pushl(EBX); | 473 __ pushl(EBX); |
463 GenerateDeoptimizationSequence(assembler, true); // Preserve EAX. | 474 GenerateDeoptimizationSequence(assembler, kLazyDeopt); |
464 } | 475 } |
465 | 476 |
466 | 477 |
467 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 478 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
468 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX. | 479 GenerateDeoptimizationSequence(assembler, kEagerDeopt); |
469 } | 480 } |
470 | 481 |
471 | 482 |
472 static void GenerateDispatcherCode(Assembler* assembler, | 483 static void GenerateDispatcherCode(Assembler* assembler, |
473 Label* call_target_function) { | 484 Label* call_target_function) { |
474 __ Comment("NoSuchMethodDispatch"); | 485 __ Comment("NoSuchMethodDispatch"); |
475 // When lazily generated invocation dispatchers are disabled, the | 486 // When lazily generated invocation dispatchers are disabled, the |
476 // miss-handler may return null. | 487 // miss-handler may return null. |
477 const Immediate& raw_null = | 488 const Immediate& raw_null = |
478 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 489 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 __ popl(EDX); // Pop array length argument (preserved). | 688 __ popl(EDX); // Pop array length argument (preserved). |
678 __ popl(EAX); // Pop return value from return slot. | 689 __ popl(EAX); // Pop return value from return slot. |
679 __ LeaveFrame(); | 690 __ LeaveFrame(); |
680 __ ret(); | 691 __ ret(); |
681 } | 692 } |
682 | 693 |
683 | 694 |
684 // Called when invoking dart code from C++ (VM code). | 695 // Called when invoking dart code from C++ (VM code). |
685 // Input parameters: | 696 // Input parameters: |
686 // ESP : points to return address. | 697 // ESP : points to return address. |
687 // ESP + 4 : entrypoint of the dart function to call. | 698 // ESP + 4 : code object of the dart function to call. |
688 // ESP + 8 : arguments descriptor array. | 699 // ESP + 8 : arguments descriptor array. |
689 // ESP + 12 : arguments array. | 700 // ESP + 12 : arguments array. |
690 // ESP + 16 : current thread. | 701 // ESP + 16 : current thread. |
691 // Uses EAX, EDX, ECX, EDI as temporary registers. | 702 // Uses EAX, EDX, ECX, EDI as temporary registers. |
692 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 703 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
693 const intptr_t kEntryPointOffset = 2 * kWordSize; | 704 const intptr_t kTargetCodeOffset = 2 * kWordSize; |
694 const intptr_t kArgumentsDescOffset = 3 * kWordSize; | 705 const intptr_t kArgumentsDescOffset = 3 * kWordSize; |
695 const intptr_t kArgumentsOffset = 4 * kWordSize; | 706 const intptr_t kArgumentsOffset = 4 * kWordSize; |
696 const intptr_t kThreadOffset = 5 * kWordSize; | 707 const intptr_t kThreadOffset = 5 * kWordSize; |
697 | 708 |
698 // Save frame pointer coming in. | 709 // Save frame pointer coming in. |
699 __ EnterFrame(0); | 710 __ EnterFrame(0); |
700 | 711 |
| 712 // Push code object to PC marker slot. |
| 713 __ movl(EAX, Address(EBP, kThreadOffset)); |
| 714 __ pushl(Address(EAX, Thread::invoke_dart_code_stub_offset())); |
| 715 |
701 // Save C++ ABI callee-saved registers. | 716 // Save C++ ABI callee-saved registers. |
702 __ pushl(EBX); | 717 __ pushl(EBX); |
703 __ pushl(ESI); | 718 __ pushl(ESI); |
704 __ pushl(EDI); | 719 __ pushl(EDI); |
705 | 720 |
706 // Set up THR, which caches the current thread in Dart code. | 721 // Set up THR, which caches the current thread in Dart code. |
707 __ movl(THR, Address(EBP, kThreadOffset)); | 722 __ movl(THR, EAX); |
708 __ LoadIsolate(EDI); | 723 __ LoadIsolate(EDI); |
709 | 724 |
710 // Save the current VMTag on the stack. | 725 // Save the current VMTag on the stack. |
711 __ movl(ECX, Address(EDI, Isolate::vm_tag_offset())); | 726 __ movl(ECX, Address(EDI, Isolate::vm_tag_offset())); |
712 __ pushl(ECX); | 727 __ pushl(ECX); |
713 | 728 |
714 // Mark that the isolate is executing Dart code. | 729 // Mark that the isolate is executing Dart code. |
715 __ movl(Address(EDI, Isolate::vm_tag_offset()), | 730 __ movl(Address(EDI, Isolate::vm_tag_offset()), |
716 Immediate(VMTag::kDartTagId)); | 731 Immediate(VMTag::kDartTagId)); |
717 | 732 |
718 // Save top resource and top exit frame info. Use EDX as a temporary register. | 733 // Save top resource and top exit frame info. Use EDX as a temporary register. |
719 // StackFrameIterator reads the top exit frame info saved in this frame. | 734 // StackFrameIterator reads the top exit frame info saved in this frame. |
720 __ movl(EDX, Address(THR, Thread::top_resource_offset())); | 735 __ movl(EDX, Address(THR, Thread::top_resource_offset())); |
721 __ pushl(EDX); | 736 __ pushl(EDX); |
722 __ movl(Address(THR, Thread::top_resource_offset()), Immediate(0)); | 737 __ movl(Address(THR, Thread::top_resource_offset()), Immediate(0)); |
723 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the | 738 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the |
724 // code below. | 739 // code below. |
725 ASSERT(kExitLinkSlotFromEntryFp == -6); | 740 ASSERT(kExitLinkSlotFromEntryFp == -7); |
726 __ movl(EDX, Address(THR, Thread::top_exit_frame_info_offset())); | 741 __ movl(EDX, Address(THR, Thread::top_exit_frame_info_offset())); |
727 __ pushl(EDX); | 742 __ pushl(EDX); |
728 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); | 743 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); |
729 | 744 |
730 // Load arguments descriptor array into EDX. | 745 // Load arguments descriptor array into EDX. |
731 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); | 746 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); |
732 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); | 747 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); |
733 | 748 |
734 // Load number of arguments into EBX. | 749 // Load number of arguments into EBX. |
735 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 750 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
(...skipping 13 matching lines...) Expand all Loading... |
749 | 764 |
750 __ Bind(&push_arguments); | 765 __ Bind(&push_arguments); |
751 __ movl(ECX, Address(EDI, EAX, TIMES_4, 0)); | 766 __ movl(ECX, Address(EDI, EAX, TIMES_4, 0)); |
752 __ pushl(ECX); | 767 __ pushl(ECX); |
753 __ incl(EAX); | 768 __ incl(EAX); |
754 __ cmpl(EAX, EBX); | 769 __ cmpl(EAX, EBX); |
755 __ j(LESS, &push_arguments, Assembler::kNearJump); | 770 __ j(LESS, &push_arguments, Assembler::kNearJump); |
756 __ Bind(&done_push_arguments); | 771 __ Bind(&done_push_arguments); |
757 | 772 |
758 // Call the dart code entrypoint. | 773 // Call the dart code entrypoint. |
759 __ call(Address(EBP, kEntryPointOffset)); | 774 __ movl(EAX, Address(EBP, kTargetCodeOffset)); |
| 775 __ movl(EAX, Address(EAX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 776 __ call(FieldAddress(EAX, Code::entry_point_offset())); |
760 | 777 |
761 // Reread the arguments descriptor array to obtain the number of passed | 778 // Reread the arguments descriptor array to obtain the number of passed |
762 // arguments. | 779 // arguments. |
763 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); | 780 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); |
764 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); | 781 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); |
765 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 782 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
766 // Get rid of arguments pushed on the stack. | 783 // Get rid of arguments pushed on the stack. |
767 __ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi. | 784 __ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi. |
768 | 785 |
769 // Restore the saved top exit frame info and top resource back into the | 786 // Restore the saved top exit frame info and top resource back into the |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 | 1011 |
995 | 1012 |
996 // Called for inline allocation of objects. | 1013 // Called for inline allocation of objects. |
997 // Input parameters: | 1014 // Input parameters: |
998 // ESP + 4 : type arguments object (only if class is parameterized). | 1015 // ESP + 4 : type arguments object (only if class is parameterized). |
999 // ESP : points to return address. | 1016 // ESP : points to return address. |
1000 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers. | 1017 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers. |
1001 // Returns patch_code_pc offset where patching code for disabling the stub | 1018 // Returns patch_code_pc offset where patching code for disabling the stub |
1002 // has been generated (similar to regularly generated Dart code). | 1019 // has been generated (similar to regularly generated Dart code). |
1003 void StubCode::GenerateAllocationStubForClass( | 1020 void StubCode::GenerateAllocationStubForClass( |
1004 Assembler* assembler, const Class& cls, | 1021 Assembler* assembler, const Class& cls) { |
1005 uword* entry_patch_offset, uword* patch_code_pc_offset) { | |
1006 *entry_patch_offset = assembler->CodeSize(); | |
1007 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; | 1022 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; |
1008 const Immediate& raw_null = | 1023 const Immediate& raw_null = |
1009 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1024 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1010 // The generated code is different if the class is parameterized. | 1025 // The generated code is different if the class is parameterized. |
1011 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1026 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
1012 ASSERT(!is_cls_parameterized || | 1027 ASSERT(!is_cls_parameterized || |
1013 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1028 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
1014 // kInlineInstanceSize is a constant used as a threshold for determining | 1029 // kInlineInstanceSize is a constant used as a threshold for determining |
1015 // when the object initialization should be done as a loop or as | 1030 // when the object initialization should be done as a loop or as |
1016 // straight line code. | 1031 // straight line code. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 __ pushl(raw_null); // Push null type arguments. | 1133 __ pushl(raw_null); // Push null type arguments. |
1119 } | 1134 } |
1120 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1135 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
1121 __ popl(EAX); // Pop argument (type arguments of object). | 1136 __ popl(EAX); // Pop argument (type arguments of object). |
1122 __ popl(EAX); // Pop argument (class of object). | 1137 __ popl(EAX); // Pop argument (class of object). |
1123 __ popl(EAX); // Pop result (newly allocated object). | 1138 __ popl(EAX); // Pop result (newly allocated object). |
1124 // EAX: new object | 1139 // EAX: new object |
1125 // Restore the frame pointer. | 1140 // Restore the frame pointer. |
1126 __ LeaveFrame(); | 1141 __ LeaveFrame(); |
1127 __ ret(); | 1142 __ ret(); |
1128 // Emit function patching code. This will be swapped with the first 5 bytes | |
1129 // at entry point. | |
1130 *patch_code_pc_offset = assembler->CodeSize(); | |
1131 __ Jmp(*StubCode::FixAllocationStubTarget_entry()); | |
1132 } | 1143 } |
1133 | 1144 |
1134 | 1145 |
1135 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1146 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1136 // from the entry code of a dart function after an error in passed argument | 1147 // from the entry code of a dart function after an error in passed argument |
1137 // name or number is detected. | 1148 // name or number is detected. |
1138 // Input parameters: | 1149 // Input parameters: |
1139 // ESP : points to return address. | 1150 // ESP : points to return address. |
1140 // ESP + 4 : address of last argument. | 1151 // ESP + 4 : address of last argument. |
1141 // EDX : arguments descriptor array. | 1152 // EDX : arguments descriptor array. |
(...skipping 19 matching lines...) Expand all Loading... |
1161 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); | 1172 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); |
1162 // noSuchMethod on closures always throws an error, so it will never return. | 1173 // noSuchMethod on closures always throws an error, so it will never return. |
1163 __ int3(); | 1174 __ int3(); |
1164 } | 1175 } |
1165 | 1176 |
1166 | 1177 |
1167 // Cannot use function object from ICData as it may be the inlined | 1178 // Cannot use function object from ICData as it may be the inlined |
1168 // function and not the top-scope function. | 1179 // function and not the top-scope function. |
1169 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1180 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
1170 Register ic_reg = ECX; | 1181 Register ic_reg = ECX; |
1171 Register func_reg = EDI; | 1182 Register func_reg = EBX; |
1172 if (FLAG_trace_optimized_ic_calls) { | 1183 if (FLAG_trace_optimized_ic_calls) { |
1173 __ EnterStubFrame(); | 1184 __ EnterStubFrame(); |
1174 __ pushl(func_reg); // Preserve | 1185 __ pushl(func_reg); // Preserve |
1175 __ pushl(ic_reg); // Preserve. | 1186 __ pushl(ic_reg); // Preserve. |
1176 __ pushl(ic_reg); // Argument. | 1187 __ pushl(ic_reg); // Argument. |
1177 __ pushl(func_reg); // Argument. | 1188 __ pushl(func_reg); // Argument. |
1178 __ CallRuntime(kTraceICCallRuntimeEntry, 2); | 1189 __ CallRuntime(kTraceICCallRuntimeEntry, 2); |
1179 __ popl(EAX); // Discard argument; | 1190 __ popl(EAX); // Discard argument; |
1180 __ popl(EAX); // Discard argument; | 1191 __ popl(EAX); // Discard argument; |
1181 __ popl(ic_reg); // Restore. | 1192 __ popl(ic_reg); // Restore. |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1697 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1708 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
1698 __ EnterStubFrame(); | 1709 __ EnterStubFrame(); |
1699 // Save IC data. | 1710 // Save IC data. |
1700 __ pushl(ECX); | 1711 __ pushl(ECX); |
1701 // Room for result. Debugger stub returns address of the | 1712 // Room for result. Debugger stub returns address of the |
1702 // unpatched runtime stub. | 1713 // unpatched runtime stub. |
1703 const Immediate& raw_null = | 1714 const Immediate& raw_null = |
1704 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1715 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1705 __ pushl(raw_null); // Room for result. | 1716 __ pushl(raw_null); // Room for result. |
1706 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1717 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1707 __ popl(EAX); // Address of original stub. | 1718 __ popl(EAX); // Code of original stub. |
1708 __ popl(ECX); // Restore IC data. | 1719 __ popl(ECX); // Restore IC data. |
1709 __ LeaveFrame(); | 1720 __ LeaveFrame(); |
1710 __ jmp(EAX); // Jump to original stub. | 1721 // Jump to original stub. |
| 1722 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); |
| 1723 __ jmp(EAX); |
1711 } | 1724 } |
1712 | 1725 |
1713 | 1726 |
1714 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { | 1727 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { |
1715 __ EnterStubFrame(); | 1728 __ EnterStubFrame(); |
1716 // Room for result. Debugger stub returns address of the | 1729 // Room for result. Debugger stub returns address of the |
1717 // unpatched runtime stub. | 1730 // unpatched runtime stub. |
1718 const Immediate& raw_null = | 1731 const Immediate& raw_null = |
1719 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1732 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1720 __ pushl(raw_null); // Room for result. | 1733 __ pushl(raw_null); // Room for result. |
1721 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1734 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1722 __ popl(EAX); // Address of original stub. | 1735 __ popl(EAX); // Code of the original stub |
1723 __ LeaveFrame(); | 1736 __ LeaveFrame(); |
1724 __ jmp(EAX); // Jump to original stub. | 1737 // Jump to original stub. |
| 1738 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); |
| 1739 __ jmp(EAX); |
1725 } | 1740 } |
1726 | 1741 |
1727 | 1742 |
1728 // Called only from unoptimized code. | 1743 // Called only from unoptimized code. |
1729 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1744 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
1730 // Check single stepping. | 1745 // Check single stepping. |
1731 Label stepping, done_stepping; | 1746 Label stepping, done_stepping; |
1732 __ LoadIsolate(EAX); | 1747 __ LoadIsolate(EAX); |
1733 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); | 1748 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); |
1734 __ cmpl(EAX, Immediate(0)); | 1749 __ cmpl(EAX, Immediate(0)); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1886 // Set tag. | 1901 // Set tag. |
1887 __ movl(Address(EDI, Isolate::vm_tag_offset()), | 1902 __ movl(Address(EDI, Isolate::vm_tag_offset()), |
1888 Immediate(VMTag::kDartTagId)); | 1903 Immediate(VMTag::kDartTagId)); |
1889 // Clear top exit frame. | 1904 // Clear top exit frame. |
1890 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); | 1905 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); |
1891 __ jmp(EBX); // Jump to the exception handler code. | 1906 __ jmp(EBX); // Jump to the exception handler code. |
1892 } | 1907 } |
1893 | 1908 |
1894 | 1909 |
1895 // Calls to the runtime to optimize the given function. | 1910 // Calls to the runtime to optimize the given function. |
1896 // EDI: function to be reoptimized. | 1911 // EBX: function to be reoptimized. |
1897 // EDX: argument descriptor (preserved). | 1912 // EDX: argument descriptor (preserved). |
1898 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1913 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
1899 const Immediate& raw_null = | 1914 const Immediate& raw_null = |
1900 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1915 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1901 __ EnterStubFrame(); | 1916 __ EnterStubFrame(); |
1902 __ pushl(EDX); | 1917 __ pushl(EDX); |
1903 __ pushl(raw_null); // Setup space on stack for return value. | 1918 __ pushl(raw_null); // Setup space on stack for return value. |
1904 __ pushl(EDI); | 1919 __ pushl(EBX); |
1905 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 1920 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
1906 __ popl(EAX); // Discard argument. | 1921 __ popl(EAX); // Discard argument. |
1907 __ popl(EAX); // Get Code object | 1922 __ popl(EAX); // Get Code object |
1908 __ popl(EDX); // Restore argument descriptor. | 1923 __ popl(EDX); // Restore argument descriptor. |
1909 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); | 1924 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); |
1910 __ LeaveFrame(); | 1925 __ LeaveFrame(); |
1911 __ jmp(EAX); | 1926 __ jmp(EAX); |
1912 __ int3(); | 1927 __ int3(); |
1913 } | 1928 } |
1914 | 1929 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 // Call the target found in the cache. For a class id match, this is a | 2076 // Call the target found in the cache. For a class id match, this is a |
2062 // proper target for the given name and arguments descriptor. If the | 2077 // proper target for the given name and arguments descriptor. If the |
2063 // illegal class id was found, the target is a cache miss handler that can | 2078 // illegal class id was found, the target is a cache miss handler that can |
2064 // be invoked as a normal Dart function. | 2079 // be invoked as a normal Dart function. |
2065 __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize)); | 2080 __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize)); |
2066 __ movl(target, FieldAddress(EAX, Function::entry_point_offset())); | 2081 __ movl(target, FieldAddress(EAX, Function::entry_point_offset())); |
2067 } | 2082 } |
2068 | 2083 |
2069 | 2084 |
2070 // Called from megamorphic calls. | 2085 // Called from megamorphic calls. |
2071 // EDI: receiver. | 2086 // ECX: receiver. |
2072 // EBX: lookup cache. | 2087 // EBX: lookup cache. |
2073 // Result: | 2088 // Result: |
2074 // EBX: entry point. | 2089 // EBX: entry point. |
2075 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2090 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2076 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); | 2091 EmitMegamorphicLookup(assembler, ECX, EBX, EBX); |
2077 __ ret(); | 2092 __ ret(); |
2078 } | 2093 } |
2079 | 2094 |
2080 | 2095 |
2081 } // namespace dart | 2096 } // namespace dart |
2082 | 2097 |
2083 #endif // defined TARGET_ARCH_IA32 | 2098 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |