| 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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 269 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 270 __ EnterStubFrame(); | 270 __ EnterStubFrame(); |
| 271 __ pushl(EDX); // Preserve arguments descriptor array. | 271 __ pushl(EDX); // Preserve arguments descriptor array. |
| 272 __ pushl(raw_null); // Setup space on stack for return value. | 272 __ pushl(raw_null); // Setup space on stack for return value. |
| 273 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 273 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
| 274 __ popl(EAX); // Get Code object result. | 274 __ popl(EAX); // Get Code object result. |
| 275 __ popl(EDX); // Restore arguments descriptor array. | 275 __ popl(EDX); // Restore arguments descriptor array. |
| 276 // Remove the stub frame as we are about to jump to the dart function. | 276 // Remove the stub frame as we are about to jump to the dart function. |
| 277 __ LeaveFrame(); | 277 __ LeaveFrame(); |
| 278 | 278 |
| 279 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 279 __ movl(ECX, FieldAddress(EAX, Code::entry_point_offset())); |
| 280 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 281 __ jmp(ECX); | 280 __ jmp(ECX); |
| 282 } | 281 } |
| 283 | 282 |
| 284 | 283 |
| 285 // Called from a static call only when an invalid code has been entered | 284 // Called from a static call only when an invalid code has been entered |
| 286 // (invalid because its function was optimized or deoptimized). | 285 // (invalid because its function was optimized or deoptimized). |
| 287 // EDX: arguments descriptor array. | 286 // EDX: arguments descriptor array. |
| 288 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 287 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 289 const Immediate& raw_null = | 288 const Immediate& raw_null = |
| 290 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 289 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 291 // Create a stub frame as we are pushing some objects on the stack before | 290 // Create a stub frame as we are pushing some objects on the stack before |
| 292 // calling into the runtime. | 291 // calling into the runtime. |
| 293 __ EnterStubFrame(); | 292 __ EnterStubFrame(); |
| 294 __ pushl(EDX); // Preserve arguments descriptor array. | 293 __ pushl(EDX); // Preserve arguments descriptor array. |
| 295 __ pushl(raw_null); // Setup space on stack for return value. | 294 __ pushl(raw_null); // Setup space on stack for return value. |
| 296 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 295 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
| 297 __ popl(EAX); // Get Code object. | 296 __ popl(EAX); // Get Code object. |
| 298 __ popl(EDX); // Restore arguments descriptor array. | 297 __ popl(EDX); // Restore arguments descriptor array. |
| 299 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 298 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); |
| 300 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 301 __ LeaveFrame(); | 299 __ LeaveFrame(); |
| 302 __ jmp(EAX); | 300 __ jmp(EAX); |
| 303 __ int3(); | 301 __ int3(); |
| 304 } | 302 } |
| 305 | 303 |
| 306 | 304 |
| 307 // Called from object allocate instruction when the allocation stub has been | 305 // Called from object allocate instruction when the allocation stub has been |
| 308 // disabled. | 306 // disabled. |
| 309 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { | 307 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
| 310 const Immediate& raw_null = | 308 const Immediate& raw_null = |
| 311 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 309 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 312 __ EnterStubFrame(); | 310 __ EnterStubFrame(); |
| 313 __ pushl(raw_null); // Setup space on stack for return value. | 311 __ pushl(raw_null); // Setup space on stack for return value. |
| 314 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 312 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
| 315 __ popl(EAX); // Get Code object. | 313 __ popl(EAX); // Get Code object. |
| 316 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 314 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); |
| 317 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 318 __ LeaveFrame(); | 315 __ LeaveFrame(); |
| 319 __ jmp(EAX); | 316 __ jmp(EAX); |
| 320 __ int3(); | 317 __ int3(); |
| 321 } | 318 } |
| 322 | 319 |
| 323 | 320 |
| 324 // Input parameters: | 321 // Input parameters: |
| 325 // EDX: smi-tagged argument count, may be zero. | 322 // EDX: smi-tagged argument count, may be zero. |
| 326 // EBP[kParamEndSlotFromFp + 1]: last argument. | 323 // EBP[kParamEndSlotFromFp + 1]: last argument. |
| 327 // Uses EAX, EBX, ECX, EDX, EDI. | 324 // Uses EAX, EBX, ECX, EDX, EDI. |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 __ popl(EDX); // Restore arguments descriptor. | 526 __ popl(EDX); // Restore arguments descriptor. |
| 530 __ popl(ECX); // Restore IC data. | 527 __ popl(ECX); // Restore IC data. |
| 531 __ LeaveFrame(); | 528 __ LeaveFrame(); |
| 532 | 529 |
| 533 if (!FLAG_lazy_dispatchers) { | 530 if (!FLAG_lazy_dispatchers) { |
| 534 Label call_target_function; | 531 Label call_target_function; |
| 535 GenerateDispatcherCode(assembler, &call_target_function); | 532 GenerateDispatcherCode(assembler, &call_target_function); |
| 536 __ Bind(&call_target_function); | 533 __ Bind(&call_target_function); |
| 537 } | 534 } |
| 538 | 535 |
| 539 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 536 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| 540 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 541 __ jmp(EBX); | 537 __ jmp(EBX); |
| 542 } | 538 } |
| 543 | 539 |
| 544 | 540 |
| 545 // Called for inline allocation of arrays. | 541 // Called for inline allocation of arrays. |
| 546 // Input parameters: | 542 // Input parameters: |
| 547 // EDX : Array length as Smi (must be preserved). | 543 // EDX : Array length as Smi (must be preserved). |
| 548 // ECX : array element type (either NULL or an instantiated type). | 544 // ECX : array element type (either NULL or an instantiated type). |
| 549 // Uses EAX, EBX, ECX, EDI as temporary registers. | 545 // Uses EAX, EBX, ECX, EDI as temporary registers. |
| 550 // The newly allocated object is returned in EAX. | 546 // The newly allocated object is returned in EAX. |
| (...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1444 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1440 __ addl(EAX, Immediate(Smi::RawValue(1))); |
| 1445 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1441 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1446 __ cmovno(EDI, EAX); | 1442 __ cmovno(EDI, EAX); |
| 1447 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1443 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1448 } | 1444 } |
| 1449 | 1445 |
| 1450 __ movl(EAX, Address(EBX, target_offset)); | 1446 __ movl(EAX, Address(EBX, target_offset)); |
| 1451 __ Bind(&call_target_function); | 1447 __ Bind(&call_target_function); |
| 1452 __ Comment("Call target"); | 1448 __ Comment("Call target"); |
| 1453 // EAX: Target function. | 1449 // EAX: Target function. |
| 1454 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1450 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| 1455 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 1456 if (range_collection_mode == kCollectRanges) { | 1451 if (range_collection_mode == kCollectRanges) { |
| 1457 __ EnterStubFrame(); | 1452 __ EnterStubFrame(); |
| 1458 __ pushl(ECX); | 1453 __ pushl(ECX); |
| 1459 const intptr_t arg_offset_words = num_args + | 1454 const intptr_t arg_offset_words = num_args + |
| 1460 Assembler::kEnterStubFramePushedWords + | 1455 Assembler::kEnterStubFramePushedWords + |
| 1461 1; // ECX | 1456 1; // ECX |
| 1462 for (intptr_t i = 0; i < num_args; i++) { | 1457 for (intptr_t i = 0; i < num_args; i++) { |
| 1463 __ movl(EDI, Address(ESP, arg_offset_words * kWordSize)); | 1458 __ movl(EDI, Address(ESP, arg_offset_words * kWordSize)); |
| 1464 __ pushl(EDI); | 1459 __ pushl(EDI); |
| 1465 } | 1460 } |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1633 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1639 __ cmovno(EDI, EAX); | 1634 __ cmovno(EDI, EAX); |
| 1640 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1635 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1641 } | 1636 } |
| 1642 | 1637 |
| 1643 // Load arguments descriptor into EDX. | 1638 // Load arguments descriptor into EDX. |
| 1644 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1639 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| 1645 | 1640 |
| 1646 // Get function and call it, if possible. | 1641 // Get function and call it, if possible. |
| 1647 __ movl(EAX, Address(EBX, target_offset)); | 1642 __ movl(EAX, Address(EBX, target_offset)); |
| 1648 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1643 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| 1649 | |
| 1650 // EBX: Target instructions. | |
| 1651 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 1652 __ jmp(EBX); | 1644 __ jmp(EBX); |
| 1653 | 1645 |
| 1654 if (FLAG_support_debugger) { | 1646 if (FLAG_support_debugger) { |
| 1655 __ Bind(&stepping); | 1647 __ Bind(&stepping); |
| 1656 __ EnterStubFrame(); | 1648 __ EnterStubFrame(); |
| 1657 __ pushl(ECX); | 1649 __ pushl(ECX); |
| 1658 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1650 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1659 __ popl(ECX); | 1651 __ popl(ECX); |
| 1660 __ LeaveFrame(); | 1652 __ LeaveFrame(); |
| 1661 __ jmp(&done_stepping, Assembler::kNearJump); | 1653 __ jmp(&done_stepping, Assembler::kNearJump); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1689 __ EnterStubFrame(); | 1681 __ EnterStubFrame(); |
| 1690 __ pushl(EDX); // Preserve arguments descriptor array. | 1682 __ pushl(EDX); // Preserve arguments descriptor array. |
| 1691 __ pushl(ECX); // Preserve IC data object. | 1683 __ pushl(ECX); // Preserve IC data object. |
| 1692 __ pushl(EAX); // Pass function. | 1684 __ pushl(EAX); // Pass function. |
| 1693 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1685 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1694 __ popl(EAX); // Restore function. | 1686 __ popl(EAX); // Restore function. |
| 1695 __ popl(ECX); // Restore IC data array. | 1687 __ popl(ECX); // Restore IC data array. |
| 1696 __ popl(EDX); // Restore arguments descriptor array. | 1688 __ popl(EDX); // Restore arguments descriptor array. |
| 1697 __ LeaveFrame(); | 1689 __ LeaveFrame(); |
| 1698 | 1690 |
| 1699 __ movl(EAX, FieldAddress(EAX, Function::instructions_offset())); | 1691 __ movl(EAX, FieldAddress(EAX, Function::entry_point_offset())); |
| 1700 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 1701 __ jmp(EAX); | 1692 __ jmp(EAX); |
| 1702 } | 1693 } |
| 1703 | 1694 |
| 1704 | 1695 |
| 1705 // ECX: Contains an ICData. | 1696 // ECX: Contains an ICData. |
| 1706 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1697 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
| 1707 __ EnterStubFrame(); | 1698 __ EnterStubFrame(); |
| 1708 // Save IC data. | 1699 // Save IC data. |
| 1709 __ pushl(ECX); | 1700 __ pushl(ECX); |
| 1710 // Room for result. Debugger stub returns address of the | 1701 // Room for result. Debugger stub returns address of the |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1908 const Immediate& raw_null = | 1899 const Immediate& raw_null = |
| 1909 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1900 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1910 __ EnterStubFrame(); | 1901 __ EnterStubFrame(); |
| 1911 __ pushl(EDX); | 1902 __ pushl(EDX); |
| 1912 __ pushl(raw_null); // Setup space on stack for return value. | 1903 __ pushl(raw_null); // Setup space on stack for return value. |
| 1913 __ pushl(EDI); | 1904 __ pushl(EDI); |
| 1914 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 1905 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
| 1915 __ popl(EAX); // Discard argument. | 1906 __ popl(EAX); // Discard argument. |
| 1916 __ popl(EAX); // Get Code object | 1907 __ popl(EAX); // Get Code object |
| 1917 __ popl(EDX); // Restore argument descriptor. | 1908 __ popl(EDX); // Restore argument descriptor. |
| 1918 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 1909 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); |
| 1919 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 1920 __ LeaveFrame(); | 1910 __ LeaveFrame(); |
| 1921 __ jmp(EAX); | 1911 __ jmp(EAX); |
| 1922 __ int3(); | 1912 __ int3(); |
| 1923 } | 1913 } |
| 1924 | 1914 |
| 1925 | 1915 |
| 1926 // Does identical check (object references are equal or not equal) with special | 1916 // Does identical check (object references are equal or not equal) with special |
| 1927 // checks for boxed numbers. | 1917 // checks for boxed numbers. |
| 1928 // Return ZF set. | 1918 // Return ZF set. |
| 1929 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint | 1919 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2066 __ j(ZERO, &call_target_function, Assembler::kNearJump); | 2056 __ j(ZERO, &call_target_function, Assembler::kNearJump); |
| 2067 __ cmpl(EDX, EAX); | 2057 __ cmpl(EDX, EAX); |
| 2068 __ j(NOT_EQUAL, &update, Assembler::kNearJump); | 2058 __ j(NOT_EQUAL, &update, Assembler::kNearJump); |
| 2069 | 2059 |
| 2070 __ Bind(&call_target_function); | 2060 __ Bind(&call_target_function); |
| 2071 // 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 |
| 2072 // proper target for the given name and arguments descriptor. If the | 2062 // proper target for the given name and arguments descriptor. If the |
| 2073 // 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 |
| 2074 // be invoked as a normal Dart function. | 2064 // be invoked as a normal Dart function. |
| 2075 __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize)); | 2065 __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize)); |
| 2076 __ movl(target, FieldAddress(EAX, Function::instructions_offset())); | 2066 __ movl(target, FieldAddress(EAX, Function::entry_point_offset())); |
| 2077 // TODO(srdjan): Evaluate performance impact of moving the instruction below | |
| 2078 // to the call site, instead of having it here. | |
| 2079 __ addl(target, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
| 2080 } | 2067 } |
| 2081 | 2068 |
| 2082 | 2069 |
| 2083 // Called from megamorphic calls. | 2070 // Called from megamorphic calls. |
| 2084 // EDI: receiver. | 2071 // EDI: receiver. |
| 2085 // EBX: lookup cache. | 2072 // EBX: lookup cache. |
| 2086 // Result: | 2073 // Result: |
| 2087 // EBX: entry point. | 2074 // EBX: entry point. |
| 2088 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2075 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 2089 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); | 2076 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); |
| 2090 __ ret(); | 2077 __ ret(); |
| 2091 } | 2078 } |
| 2092 | 2079 |
| 2093 | 2080 |
| 2094 } // namespace dart | 2081 } // namespace dart |
| 2095 | 2082 |
| 2096 #endif // defined TARGET_ARCH_IA32 | 2083 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |