Chromium Code Reviews| 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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
| 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/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 1507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1518 | 1518 |
| 1519 | 1519 |
| 1520 void Assembler::Drop(intptr_t stack_elements) { | 1520 void Assembler::Drop(intptr_t stack_elements) { |
| 1521 ASSERT(stack_elements >= 0); | 1521 ASSERT(stack_elements >= 0); |
| 1522 if (stack_elements > 0) { | 1522 if (stack_elements > 0) { |
| 1523 AddImmediate(SP, SP, stack_elements * kWordSize); | 1523 AddImmediate(SP, SP, stack_elements * kWordSize); |
| 1524 } | 1524 } |
| 1525 } | 1525 } |
| 1526 | 1526 |
| 1527 | 1527 |
| 1528 intptr_t Assembler::FindImmediate(int32_t imm) { | |
| 1529 ASSERT(Isolate::Current() != Dart::vm_isolate()); | |
| 1530 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); | |
| 1531 return object_pool_wrapper_.FindObject(smi); | |
|
zra
2015/07/23 22:45:59
Why not use ObjectPoolWrapper::FindImmediate() ? I
regis
2015/07/23 23:07:31
Because I forked the code in May, when arm64 was s
| |
| 1532 } | |
| 1533 | |
| 1534 | |
| 1528 // Uses a code sequence that can easily be decoded. | 1535 // Uses a code sequence that can easily be decoded. |
| 1529 void Assembler::LoadWordFromPoolOffset(Register rd, | 1536 void Assembler::LoadWordFromPoolOffset(Register rd, |
| 1530 int32_t offset, | 1537 int32_t offset, |
| 1531 Condition cond) { | 1538 Condition cond) { |
| 1532 ASSERT(constant_pool_allowed()); | 1539 ASSERT(constant_pool_allowed()); |
| 1533 ASSERT(rd != PP); | 1540 ASSERT(rd != PP); |
| 1534 int32_t offset_mask = 0; | 1541 int32_t offset_mask = 0; |
| 1535 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) { | 1542 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) { |
| 1536 ldr(rd, Address(PP, offset), cond); | 1543 ldr(rd, Address(PP, offset), cond); |
| 1537 } else { | 1544 } else { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1548 ldr(rd, Address(rd, offset_lo), cond); | 1555 ldr(rd, Address(rd, offset_lo), cond); |
| 1549 } | 1556 } |
| 1550 } | 1557 } |
| 1551 | 1558 |
| 1552 | 1559 |
| 1553 void Assembler::LoadPoolPointer() { | 1560 void Assembler::LoadPoolPointer() { |
| 1554 const intptr_t object_pool_pc_dist = | 1561 const intptr_t object_pool_pc_dist = |
| 1555 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 1562 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1556 CodeSize() + Instr::kPCReadOffset; | 1563 CodeSize() + Instr::kPCReadOffset; |
| 1557 LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist); | 1564 LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist); |
| 1565 set_constant_pool_allowed(true); | |
| 1558 } | 1566 } |
| 1559 | 1567 |
| 1560 | 1568 |
| 1561 void Assembler::LoadIsolate(Register rd) { | 1569 void Assembler::LoadIsolate(Register rd) { |
| 1562 ldr(rd, Address(THR, Thread::isolate_offset())); | 1570 ldr(rd, Address(THR, Thread::isolate_offset())); |
| 1563 } | 1571 } |
| 1564 | 1572 |
| 1565 | 1573 |
| 1566 void Assembler::LoadObjectHelper(Register rd, | 1574 void Assembler::LoadObjectHelper(Register rd, |
| 1567 const Object& object, | 1575 const Object& object, |
| (...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2739 movw(rd, value_low, cond); | 2747 movw(rd, value_low, cond); |
| 2740 movt(rd, value_high, cond); | 2748 movt(rd, value_high, cond); |
| 2741 } | 2749 } |
| 2742 } | 2750 } |
| 2743 | 2751 |
| 2744 | 2752 |
| 2745 void Assembler::LoadDecodableImmediate( | 2753 void Assembler::LoadDecodableImmediate( |
| 2746 Register rd, int32_t value, Condition cond) { | 2754 Register rd, int32_t value, Condition cond) { |
| 2747 const ARMVersion version = TargetCPUFeatures::arm_version(); | 2755 const ARMVersion version = TargetCPUFeatures::arm_version(); |
| 2748 if ((version == ARMv5TE) || (version == ARMv6)) { | 2756 if ((version == ARMv5TE) || (version == ARMv6)) { |
| 2749 LoadPatchableImmediate(rd, value, cond); | 2757 if (constant_pool_allowed() && |
|
zra
2015/07/23 22:45:59
Here: https://codereview.chromium.org//1249623004
regis
2015/07/23 23:07:31
Done.
| |
| 2758 // We *could* put constants in the pool in a VM isolate, but it is | |
| 2759 // simpler to maintain the invariant that the object pool is not used | |
| 2760 // in the VM isolate. | |
| 2761 (Isolate::Current() != Dart::vm_isolate())) { | |
| 2762 // Save the bit that must be masked-off for the SmiTag. | |
| 2763 int32_t val_smi_tag = value & kSmiTagMask; | |
| 2764 value &= ~kSmiTagMask; // Mask off the tag bit. | |
| 2765 const int32_t offset = Array::element_offset(FindImmediate(value)); | |
| 2766 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | |
| 2767 if (val_smi_tag != 0) { | |
| 2768 // Add back the tag bit. | |
| 2769 orr(rd, rd, Operand(val_smi_tag)); | |
| 2770 } | |
| 2771 } else { | |
| 2772 LoadPatchableImmediate(rd, value, cond); | |
| 2773 } | |
| 2750 } else { | 2774 } else { |
| 2751 ASSERT(version == ARMv7); | 2775 ASSERT(version == ARMv7); |
| 2752 movw(rd, Utils::Low16Bits(value), cond); | 2776 movw(rd, Utils::Low16Bits(value), cond); |
| 2753 const uint16_t value_high = Utils::High16Bits(value); | 2777 const uint16_t value_high = Utils::High16Bits(value); |
| 2754 if (value_high != 0) { | 2778 if (value_high != 0) { |
| 2755 movt(rd, value_high, cond); | 2779 movt(rd, value_high, cond); |
| 2756 } | 2780 } |
| 2757 } | 2781 } |
| 2758 } | 2782 } |
| 2759 | 2783 |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3266 } | 3290 } |
| 3267 | 3291 |
| 3268 | 3292 |
| 3269 void Assembler::CallRuntime(const RuntimeEntry& entry, | 3293 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 3270 intptr_t argument_count) { | 3294 intptr_t argument_count) { |
| 3271 entry.Call(this, argument_count); | 3295 entry.Call(this, argument_count); |
| 3272 } | 3296 } |
| 3273 | 3297 |
| 3274 | 3298 |
| 3275 void Assembler::EnterDartFrame(intptr_t frame_size) { | 3299 void Assembler::EnterDartFrame(intptr_t frame_size) { |
| 3300 ASSERT(!constant_pool_allowed()); | |
| 3276 const intptr_t offset = CodeSize(); | 3301 const intptr_t offset = CodeSize(); |
| 3277 | 3302 |
| 3278 // Save PC in frame for fast identification of corresponding code. | 3303 // Save PC in frame for fast identification of corresponding code. |
| 3279 // Note that callee-saved registers can be added to the register list. | 3304 // Note that callee-saved registers can be added to the register list. |
| 3280 EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); | 3305 EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); |
| 3281 | 3306 |
| 3282 if (offset != 0) { | 3307 if (offset != 0) { |
| 3283 // Adjust saved PC for any intrinsic code that could have been generated | 3308 // Adjust saved PC for any intrinsic code that could have been generated |
| 3284 // before a frame is created. Use PP as temp register. | 3309 // before a frame is created. Use PP as temp register. |
| 3285 ldr(PP, Address(FP, 2 * kWordSize)); | 3310 ldr(PP, Address(FP, 2 * kWordSize)); |
| 3286 AddImmediate(PP, PP, -offset); | 3311 AddImmediate(PP, PP, -offset); |
| 3287 str(PP, Address(FP, 2 * kWordSize)); | 3312 str(PP, Address(FP, 2 * kWordSize)); |
| 3288 } | 3313 } |
| 3289 | 3314 |
| 3290 // Setup pool pointer for this dart function. | 3315 // Setup pool pointer for this dart function. |
| 3291 LoadPoolPointer(); | 3316 LoadPoolPointer(); |
| 3292 | 3317 |
| 3293 // Reserve space for locals. | 3318 // Reserve space for locals. |
| 3294 AddImmediate(SP, -frame_size); | 3319 AddImmediate(SP, -frame_size); |
| 3295 } | 3320 } |
| 3296 | 3321 |
| 3297 | 3322 |
| 3298 // On entry to a function compiled for OSR, the caller's frame pointer, the | 3323 // On entry to a function compiled for OSR, the caller's frame pointer, the |
| 3299 // stack locals, and any copied parameters are already in place. The frame | 3324 // stack locals, and any copied parameters are already in place. The frame |
| 3300 // pointer is already set up. The PC marker is not correct for the | 3325 // pointer is already set up. The PC marker is not correct for the |
| 3301 // optimized function and there may be extra space for spill slots to | 3326 // optimized function and there may be extra space for spill slots to |
| 3302 // allocate. We must also set up the pool pointer for the function. | 3327 // allocate. We must also set up the pool pointer for the function. |
| 3303 void Assembler::EnterOsrFrame(intptr_t extra_size) { | 3328 void Assembler::EnterOsrFrame(intptr_t extra_size) { |
| 3329 ASSERT(!constant_pool_allowed()); | |
| 3304 // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be | 3330 // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be |
| 3305 // different from EntryPointToPcMarkerOffset(). | 3331 // different from EntryPointToPcMarkerOffset(). |
| 3306 const intptr_t offset = | 3332 const intptr_t offset = |
| 3307 CodeSize() + Instr::kPCReadOffset - EntryPointToPcMarkerOffset(); | 3333 CodeSize() + Instr::kPCReadOffset - EntryPointToPcMarkerOffset(); |
| 3308 | 3334 |
| 3309 Comment("EnterOsrFrame"); | 3335 Comment("EnterOsrFrame"); |
| 3310 mov(IP, Operand(PC)); | 3336 mov(IP, Operand(PC)); |
| 3311 | 3337 |
| 3312 AddImmediate(IP, -offset); | 3338 AddImmediate(IP, -offset); |
| 3313 str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); | 3339 str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); |
| 3314 | 3340 |
| 3315 // Setup pool pointer for this dart function. | 3341 // Setup pool pointer for this dart function. |
| 3316 LoadPoolPointer(); | 3342 LoadPoolPointer(); |
| 3317 | 3343 |
| 3318 AddImmediate(SP, -extra_size); | 3344 AddImmediate(SP, -extra_size); |
| 3319 } | 3345 } |
| 3320 | 3346 |
| 3321 | 3347 |
| 3322 void Assembler::LeaveDartFrame() { | 3348 void Assembler::LeaveDartFrame() { |
| 3349 // LeaveDartFrame is called from stubs (pp disallowed) and from Dart code (pp | |
| 3350 // allowed), so there is no point in checking the current value of | |
| 3351 // constant_pool_allowed(). | |
| 3352 set_constant_pool_allowed(false); | |
| 3323 LeaveFrame((1 << PP) | (1 << FP) | (1 << LR)); | 3353 LeaveFrame((1 << PP) | (1 << FP) | (1 << LR)); |
| 3324 // Adjust SP for PC pushed in EnterDartFrame. | 3354 // Adjust SP for PC pushed in EnterDartFrame. |
| 3325 AddImmediate(SP, kWordSize); | 3355 AddImmediate(SP, kWordSize); |
| 3326 } | 3356 } |
| 3327 | 3357 |
| 3328 | 3358 |
| 3329 void Assembler::EnterStubFrame() { | 3359 void Assembler::EnterStubFrame() { |
| 3360 set_constant_pool_allowed(false); | |
| 3330 // Push 0 as saved PC for stub frames. | 3361 // Push 0 as saved PC for stub frames. |
| 3331 mov(IP, Operand(LR)); | 3362 mov(IP, Operand(LR)); |
| 3332 mov(LR, Operand(0)); | 3363 mov(LR, Operand(0)); |
| 3333 RegList regs = (1 << PP) | (1 << FP) | (1 << IP) | (1 << LR); | 3364 RegList regs = (1 << PP) | (1 << FP) | (1 << IP) | (1 << LR); |
| 3334 EnterFrame(regs, 0); | 3365 EnterFrame(regs, 0); |
| 3335 // Setup pool pointer for this stub. | 3366 // Setup pool pointer for this stub. |
| 3336 LoadPoolPointer(); | 3367 LoadPoolPointer(); |
| 3337 } | 3368 } |
| 3338 | 3369 |
| 3339 | 3370 |
| 3340 void Assembler::LeaveStubFrame() { | 3371 void Assembler::LeaveStubFrame() { |
| 3341 LeaveFrame((1 << PP) | (1 << FP) | (1 << LR)); | 3372 LeaveFrame((1 << PP) | (1 << FP) | (1 << LR)); |
| 3373 set_constant_pool_allowed(false); | |
| 3342 // Adjust SP for null PC pushed in EnterStubFrame. | 3374 // Adjust SP for null PC pushed in EnterStubFrame. |
| 3343 AddImmediate(SP, kWordSize); | 3375 AddImmediate(SP, kWordSize); |
| 3344 } | 3376 } |
| 3345 | 3377 |
| 3346 | 3378 |
| 3347 void Assembler::LoadAllocationStatsAddress(Register dest, | 3379 void Assembler::LoadAllocationStatsAddress(Register dest, |
| 3348 intptr_t cid, | 3380 intptr_t cid, |
| 3349 bool inline_isolate) { | 3381 bool inline_isolate) { |
| 3350 ASSERT(dest != kNoRegister); | 3382 ASSERT(dest != kNoRegister); |
| 3351 ASSERT(dest != TMP); | 3383 ASSERT(dest != TMP); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3633 | 3665 |
| 3634 | 3666 |
| 3635 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3667 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 3636 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 3668 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 3637 return fpu_reg_names[reg]; | 3669 return fpu_reg_names[reg]; |
| 3638 } | 3670 } |
| 3639 | 3671 |
| 3640 } // namespace dart | 3672 } // namespace dart |
| 3641 | 3673 |
| 3642 #endif // defined TARGET_ARCH_ARM | 3674 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |