| 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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 __ EnterStubFrame(); | 304 __ EnterStubFrame(); |
| 305 // Setup space on stack for return value and preserve arguments descriptor. | 305 // Setup space on stack for return value and preserve arguments descriptor. |
| 306 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 306 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 307 __ PushList((1 << R0) | (1 << R4)); | 307 __ PushList((1 << R0) | (1 << R4)); |
| 308 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 308 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
| 309 // Get Code object result and restore arguments descriptor array. | 309 // Get Code object result and restore arguments descriptor array. |
| 310 __ PopList((1 << R0) | (1 << R4)); | 310 __ PopList((1 << R0) | (1 << R4)); |
| 311 // Remove the stub frame. | 311 // Remove the stub frame. |
| 312 __ LeaveStubFrame(); | 312 __ LeaveStubFrame(); |
| 313 // Jump to the dart function. | 313 // Jump to the dart function. |
| 314 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 314 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 315 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 316 __ bx(R0); | 315 __ bx(R0); |
| 317 } | 316 } |
| 318 | 317 |
| 319 | 318 |
| 320 // Called from a static call only when an invalid code has been entered | 319 // Called from a static call only when an invalid code has been entered |
| 321 // (invalid because its function was optimized or deoptimized). | 320 // (invalid because its function was optimized or deoptimized). |
| 322 // R4: arguments descriptor array. | 321 // R4: arguments descriptor array. |
| 323 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 322 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 324 // Create a stub frame as we are pushing some objects on the stack before | 323 // Create a stub frame as we are pushing some objects on the stack before |
| 325 // calling into the runtime. | 324 // calling into the runtime. |
| 326 __ EnterStubFrame(); | 325 __ EnterStubFrame(); |
| 327 // Setup space on stack for return value and preserve arguments descriptor. | 326 // Setup space on stack for return value and preserve arguments descriptor. |
| 328 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 327 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 329 __ PushList((1 << R0) | (1 << R4)); | 328 __ PushList((1 << R0) | (1 << R4)); |
| 330 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 329 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
| 331 // Get Code object result and restore arguments descriptor array. | 330 // Get Code object result and restore arguments descriptor array. |
| 332 __ PopList((1 << R0) | (1 << R4)); | 331 __ PopList((1 << R0) | (1 << R4)); |
| 333 // Remove the stub frame. | 332 // Remove the stub frame. |
| 334 __ LeaveStubFrame(); | 333 __ LeaveStubFrame(); |
| 335 // Jump to the dart function. | 334 // Jump to the dart function. |
| 336 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 335 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 337 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 338 __ bx(R0); | 336 __ bx(R0); |
| 339 } | 337 } |
| 340 | 338 |
| 341 | 339 |
| 342 // Called from object allocate instruction when the allocation stub has been | 340 // Called from object allocate instruction when the allocation stub has been |
| 343 // disabled. | 341 // disabled. |
| 344 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { | 342 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
| 345 __ EnterStubFrame(); | 343 __ EnterStubFrame(); |
| 346 // Setup space on stack for return value. | 344 // Setup space on stack for return value. |
| 347 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 345 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 348 __ Push(R0); | 346 __ Push(R0); |
| 349 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 347 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
| 350 // Get Code object result. | 348 // Get Code object result. |
| 351 __ Pop(R0); | 349 __ Pop(R0); |
| 352 // Remove the stub frame. | 350 // Remove the stub frame. |
| 353 __ LeaveStubFrame(); | 351 __ LeaveStubFrame(); |
| 354 // Jump to the dart function. | 352 // Jump to the dart function. |
| 355 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 353 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 356 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 357 __ bx(R0); | 354 __ bx(R0); |
| 358 } | 355 } |
| 359 | 356 |
| 360 | 357 |
| 361 // Input parameters: | 358 // Input parameters: |
| 362 // R2: smi-tagged argument count, may be zero. | 359 // R2: smi-tagged argument count, may be zero. |
| 363 // FP[kParamEndSlotFromFp + 1]: last argument. | 360 // FP[kParamEndSlotFromFp + 1]: last argument. |
| 364 static void PushArgumentsArray(Assembler* assembler) { | 361 static void PushArgumentsArray(Assembler* assembler) { |
| 365 // Allocate array to store arguments of caller. | 362 // Allocate array to store arguments of caller. |
| 366 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 363 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 | 575 |
| 579 __ LeaveStubFrame(); | 576 __ LeaveStubFrame(); |
| 580 | 577 |
| 581 if (!FLAG_lazy_dispatchers) { | 578 if (!FLAG_lazy_dispatchers) { |
| 582 Label call_target_function; | 579 Label call_target_function; |
| 583 GenerateDispatcherCode(assembler, &call_target_function); | 580 GenerateDispatcherCode(assembler, &call_target_function); |
| 584 __ Bind(&call_target_function); | 581 __ Bind(&call_target_function); |
| 585 } | 582 } |
| 586 | 583 |
| 587 // Tail-call to target function. | 584 // Tail-call to target function. |
| 588 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 585 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 589 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | |
| 590 __ bx(R2); | 586 __ bx(R2); |
| 591 } | 587 } |
| 592 | 588 |
| 593 | 589 |
| 594 // Called for inline allocation of arrays. | 590 // Called for inline allocation of arrays. |
| 595 // Input parameters: | 591 // Input parameters: |
| 596 // LR: return address. | 592 // LR: return address. |
| 597 // R1: array element type (either NULL or an instantiated type). | 593 // R1: array element type (either NULL or an instantiated type). |
| 598 // R2: array length as Smi (must be preserved). | 594 // R2: array length as Smi (must be preserved). |
| 599 // The newly allocated object is returned in R0. | 595 // The newly allocated object is returned in R0. |
| (...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1463 __ Comment("Update caller's counter"); | 1459 __ Comment("Update caller's counter"); |
| 1464 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1460 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1465 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1461 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1466 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1462 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
| 1467 __ StoreIntoSmiField(Address(R6, count_offset), R1); | 1463 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
| 1468 } | 1464 } |
| 1469 | 1465 |
| 1470 __ Comment("Call target"); | 1466 __ Comment("Call target"); |
| 1471 __ Bind(&call_target_function); | 1467 __ Bind(&call_target_function); |
| 1472 // R0: target function. | 1468 // R0: target function. |
| 1473 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1469 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 1474 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1475 if (range_collection_mode == kCollectRanges) { | 1470 if (range_collection_mode == kCollectRanges) { |
| 1476 __ ldr(R1, Address(SP, 0 * kWordSize)); | 1471 __ ldr(R1, Address(SP, 0 * kWordSize)); |
| 1477 if (num_args == 2) { | 1472 if (num_args == 2) { |
| 1478 __ ldr(R3, Address(SP, 1 * kWordSize)); | 1473 __ ldr(R3, Address(SP, 1 * kWordSize)); |
| 1479 } | 1474 } |
| 1480 __ EnterStubFrame(); | 1475 __ EnterStubFrame(); |
| 1481 if (num_args == 2) { | 1476 if (num_args == 2) { |
| 1482 __ PushList((1 << R1) | (1 << R3) | (1 << R5)); | 1477 __ PushList((1 << R1) | (1 << R3) | (1 << R5)); |
| 1483 } else { | 1478 } else { |
| 1484 __ PushList((1 << R1) | (1 << R5)); | 1479 __ PushList((1 << R1) | (1 << R5)); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1644 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1639 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1645 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1640 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
| 1646 __ StoreIntoSmiField(Address(R6, count_offset), R1); | 1641 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
| 1647 } | 1642 } |
| 1648 | 1643 |
| 1649 // Load arguments descriptor into R4. | 1644 // Load arguments descriptor into R4. |
| 1650 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1645 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1651 | 1646 |
| 1652 // Get function and call it, if possible. | 1647 // Get function and call it, if possible. |
| 1653 __ LoadFromOffset(kWord, R0, R6, target_offset); | 1648 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1654 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1649 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 1655 | |
| 1656 // R0: function. | |
| 1657 // R2: target instructions. | |
| 1658 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1659 __ bx(R2); | 1650 __ bx(R2); |
| 1660 | 1651 |
| 1661 if (FLAG_support_debugger) { | 1652 if (FLAG_support_debugger) { |
| 1662 __ Bind(&stepping); | 1653 __ Bind(&stepping); |
| 1663 __ EnterStubFrame(); | 1654 __ EnterStubFrame(); |
| 1664 __ Push(R5); // Preserve IC data. | 1655 __ Push(R5); // Preserve IC data. |
| 1665 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1656 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1666 __ Pop(R5); | 1657 __ Pop(R5); |
| 1667 __ LeaveStubFrame(); | 1658 __ LeaveStubFrame(); |
| 1668 __ b(&done_stepping); | 1659 __ b(&done_stepping); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1693 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1684 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
| 1694 // Preserve arg desc. and IC data object. | 1685 // Preserve arg desc. and IC data object. |
| 1695 __ EnterStubFrame(); | 1686 __ EnterStubFrame(); |
| 1696 __ PushList((1 << R4) | (1 << R5)); | 1687 __ PushList((1 << R4) | (1 << R5)); |
| 1697 __ Push(R0); // Pass function. | 1688 __ Push(R0); // Pass function. |
| 1698 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1689 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1699 __ Pop(R0); // Restore argument. | 1690 __ Pop(R0); // Restore argument. |
| 1700 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. | 1691 __ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. |
| 1701 __ LeaveStubFrame(); | 1692 __ LeaveStubFrame(); |
| 1702 | 1693 |
| 1703 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1694 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 1704 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1705 __ bx(R2); | 1695 __ bx(R2); |
| 1706 } | 1696 } |
| 1707 | 1697 |
| 1708 | 1698 |
| 1709 // R5: Contains an ICData. | 1699 // R5: Contains an ICData. |
| 1710 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1700 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
| 1711 __ EnterStubFrame(); | 1701 __ EnterStubFrame(); |
| 1712 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1702 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1713 // Preserve arguments descriptor and make room for result. | 1703 // Preserve arguments descriptor and make room for result. |
| 1714 __ PushList((1 << R0) | (1 << R5)); | 1704 __ PushList((1 << R0) | (1 << R5)); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1899 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1889 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
| 1900 __ EnterStubFrame(); | 1890 __ EnterStubFrame(); |
| 1901 __ Push(R4); | 1891 __ Push(R4); |
| 1902 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 1892 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 1903 __ Push(IP); // Setup space on stack for return value. | 1893 __ Push(IP); // Setup space on stack for return value. |
| 1904 __ Push(R6); | 1894 __ Push(R6); |
| 1905 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 1895 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
| 1906 __ Pop(R0); // Discard argument. | 1896 __ Pop(R0); // Discard argument. |
| 1907 __ Pop(R0); // Get Code object | 1897 __ Pop(R0); // Get Code object |
| 1908 __ Pop(R4); // Restore argument descriptor. | 1898 __ Pop(R4); // Restore argument descriptor. |
| 1909 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 1899 __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
| 1910 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 1911 __ LeaveStubFrame(); | 1900 __ LeaveStubFrame(); |
| 1912 __ bx(R0); | 1901 __ bx(R0); |
| 1913 __ bkpt(0); | 1902 __ bkpt(0); |
| 1914 } | 1903 } |
| 1915 | 1904 |
| 1916 | 1905 |
| 1917 // Does identical check (object references are equal or not equal) with special | 1906 // Does identical check (object references are equal or not equal) with special |
| 1918 // checks for boxed numbers. | 1907 // checks for boxed numbers. |
| 1919 // LR: return address. | 1908 // LR: return address. |
| 1920 // Return Zero condition flag set if equal. | 1909 // Return Zero condition flag set if equal. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2062 __ cmp(R4, Operand(R0)); | 2051 __ cmp(R4, Operand(R0)); |
| 2063 __ b(&update, NE); | 2052 __ b(&update, NE); |
| 2064 | 2053 |
| 2065 __ Bind(&call_target_function); | 2054 __ Bind(&call_target_function); |
| 2066 // Call the target found in the cache. For a class id match, this is a | 2055 // Call the target found in the cache. For a class id match, this is a |
| 2067 // proper target for the given name and arguments descriptor. If the | 2056 // proper target for the given name and arguments descriptor. If the |
| 2068 // illegal class id was found, the target is a cache miss handler that can | 2057 // illegal class id was found, the target is a cache miss handler that can |
| 2069 // be invoked as a normal Dart function. | 2058 // be invoked as a normal Dart function. |
| 2070 __ add(IP, R2, Operand(R3, LSL, 2)); | 2059 __ add(IP, R2, Operand(R3, LSL, 2)); |
| 2071 __ ldr(R0, FieldAddress(IP, base + kWordSize)); | 2060 __ ldr(R0, FieldAddress(IP, base + kWordSize)); |
| 2072 __ ldr(target, FieldAddress(R0, Function::instructions_offset())); | 2061 __ ldr(target, FieldAddress(R0, Function::entry_point_offset())); |
| 2073 // TODO(srdjan): Evaluate performance impact of moving the instruction below | |
| 2074 // to the call site, instead of having it here. | |
| 2075 __ AddImmediate(target, Instructions::HeaderSize() - kHeapObjectTag); | |
| 2076 } | 2062 } |
| 2077 | 2063 |
| 2078 | 2064 |
| 2079 // Called from megamorphic calls. | 2065 // Called from megamorphic calls. |
| 2080 // R0: receiver. | 2066 // R0: receiver. |
| 2081 // R1: lookup cache. | 2067 // R1: lookup cache. |
| 2082 // Result: | 2068 // Result: |
| 2083 // R1: entry point. | 2069 // R1: entry point. |
| 2084 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2070 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 2085 EmitMegamorphicLookup(assembler, R0, R1, R1); | 2071 EmitMegamorphicLookup(assembler, R0, R1, R1); |
| 2086 __ Ret(); | 2072 __ Ret(); |
| 2087 } | 2073 } |
| 2088 | 2074 |
| 2089 } // namespace dart | 2075 } // namespace dart |
| 2090 | 2076 |
| 2091 #endif // defined TARGET_ARCH_ARM | 2077 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |