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