| 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_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 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/heap.h" | 10 #include "vm/heap.h" |
| 11 #include "vm/locations.h" | 11 #include "vm/locations.h" |
| 12 #include "vm/memory_region.h" | 12 #include "vm/memory_region.h" |
| 13 #include "vm/runtime_entry.h" | 13 #include "vm/runtime_entry.h" |
| 14 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
| 15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); | 19 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
| 20 DECLARE_FLAG(bool, inline_alloc); | 20 DECLARE_FLAG(bool, inline_alloc); |
| 21 | 21 |
| 22 | 22 |
| 23 Assembler::Assembler(bool use_far_branches) | 23 Assembler::Assembler(bool use_far_branches) |
| 24 : buffer_(), | 24 : buffer_(), |
| 25 object_pool_(GrowableObjectArray::Handle()), | 25 object_pool_(GrowableObjectArray::Handle()), |
| 26 patchable_pool_entries_(), | 26 patchable_pool_entries_(), |
| 27 prologue_offset_(-1), | 27 prologue_offset_(-1), |
| 28 comments_() { | 28 comments_(), |
| 29 allow_constant_pool_(true) { |
| 29 // Far branching mode is only needed and implemented for MIPS and ARM. | 30 // Far branching mode is only needed and implemented for MIPS and ARM. |
| 30 ASSERT(!use_far_branches); | 31 ASSERT(!use_far_branches); |
| 31 Isolate* isolate = Isolate::Current(); | 32 Isolate* isolate = Isolate::Current(); |
| 32 if (isolate != Dart::vm_isolate()) { | 33 if (isolate != Dart::vm_isolate()) { |
| 33 object_pool_ = GrowableObjectArray::New(Heap::kOld); | 34 object_pool_ = GrowableObjectArray::New(Heap::kOld); |
| 34 | 35 |
| 35 // These objects and labels need to be accessible through every pool-pointer | 36 // These objects and labels need to be accessible through every pool-pointer |
| 36 // at the same index. | 37 // at the same index. |
| 37 object_pool_.Add(Object::null_object(), Heap::kOld); | 38 object_pool_.Add(Object::null_object(), Heap::kOld); |
| 38 patchable_pool_entries_.Add(kNotPatchable); | 39 patchable_pool_entries_.Add(kNotPatchable); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 142 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 142 EmitRegisterREX(TMP, REX_W); | 143 EmitRegisterREX(TMP, REX_W); |
| 143 EmitUint8(0xB8 | (TMP & 7)); | 144 EmitUint8(0xB8 | (TMP & 7)); |
| 144 EmitInt64(label->address()); | 145 EmitInt64(label->address()); |
| 145 } | 146 } |
| 146 call(TMP); | 147 call(TMP); |
| 147 } | 148 } |
| 148 | 149 |
| 149 | 150 |
| 150 void Assembler::CallPatchable(const ExternalLabel* label) { | 151 void Assembler::CallPatchable(const ExternalLabel* label) { |
| 152 ASSERT(allow_constant_pool()); |
| 151 intptr_t call_start = buffer_.GetPosition(); | 153 intptr_t call_start = buffer_.GetPosition(); |
| 152 LoadExternalLabel(TMP, label, kPatchable, PP); | 154 LoadExternalLabel(TMP, label, kPatchable, PP); |
| 153 call(TMP); | 155 call(TMP); |
| 154 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | 156 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
| 155 } | 157 } |
| 156 | 158 |
| 157 | 159 |
| 158 void Assembler::Call(const ExternalLabel* label, Register pp) { | 160 void Assembler::Call(const ExternalLabel* label, Register pp) { |
| 159 if (Isolate::Current() == Dart::vm_isolate()) { | 161 if (Isolate::Current() == Dart::vm_isolate()) { |
| 160 call(label); | 162 call(label); |
| (...skipping 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2361 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2363 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 2362 EmitRegisterREX(TMP, REX_W); | 2364 EmitRegisterREX(TMP, REX_W); |
| 2363 EmitUint8(0xB8 | (TMP & 7)); | 2365 EmitUint8(0xB8 | (TMP & 7)); |
| 2364 EmitInt64(label->address()); | 2366 EmitInt64(label->address()); |
| 2365 } | 2367 } |
| 2366 jmp(TMP); | 2368 jmp(TMP); |
| 2367 } | 2369 } |
| 2368 | 2370 |
| 2369 | 2371 |
| 2370 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { | 2372 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { |
| 2373 ASSERT(allow_constant_pool()); |
| 2371 intptr_t call_start = buffer_.GetPosition(); | 2374 intptr_t call_start = buffer_.GetPosition(); |
| 2372 LoadExternalLabel(TMP, label, kPatchable, pp); | 2375 LoadExternalLabel(TMP, label, kPatchable, pp); |
| 2373 jmp(TMP); | 2376 jmp(TMP); |
| 2374 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | 2377 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
| 2375 } | 2378 } |
| 2376 | 2379 |
| 2377 | 2380 |
| 2378 void Assembler::Jmp(const ExternalLabel* label, Register pp) { | 2381 void Assembler::Jmp(const ExternalLabel* label, Register pp) { |
| 2379 LoadExternalLabel(TMP, label, kNotPatchable, pp); | 2382 LoadExternalLabel(TMP, label, kNotPatchable, pp); |
| 2380 jmp(TMP); | 2383 jmp(TMP); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2581 return FindObject(smi, kNotPatchable); | 2584 return FindObject(smi, kNotPatchable); |
| 2582 } | 2585 } |
| 2583 // If the call is patchable, do not reuse an existing entry since each | 2586 // If the call is patchable, do not reuse an existing entry since each |
| 2584 // reference may be patched independently. | 2587 // reference may be patched independently. |
| 2585 object_pool_.Add(smi, Heap::kOld); | 2588 object_pool_.Add(smi, Heap::kOld); |
| 2586 patchable_pool_entries_.Add(patchable); | 2589 patchable_pool_entries_.Add(patchable); |
| 2587 return object_pool_.Length() - 1; | 2590 return object_pool_.Length() - 1; |
| 2588 } | 2591 } |
| 2589 | 2592 |
| 2590 | 2593 |
| 2594 // A set of VM objects that are present in every constant pool. |
| 2595 static bool IsAlwaysInConstantPool(const Object& object) { |
| 2596 // TODO(zra): Evaluate putting all VM heap objects into the pool. |
| 2597 return (object.raw() == Object::null()) |
| 2598 || (object.raw() == Bool::True().raw()) |
| 2599 || (object.raw() == Bool::False().raw()); |
| 2600 } |
| 2601 |
| 2602 |
| 2591 bool Assembler::CanLoadFromObjectPool(const Object& object) { | 2603 bool Assembler::CanLoadFromObjectPool(const Object& object) { |
| 2604 if (!allow_constant_pool()) { |
| 2605 return IsAlwaysInConstantPool(object); |
| 2606 } |
| 2607 |
| 2592 // TODO(zra, kmillikin): Also load other large immediates from the object | 2608 // TODO(zra, kmillikin): Also load other large immediates from the object |
| 2593 // pool | 2609 // pool |
| 2594 if (object.IsSmi()) { | 2610 if (object.IsSmi()) { |
| 2595 // If the raw smi does not fit into a 32-bit signed int, then we'll keep | 2611 // If the raw smi does not fit into a 32-bit signed int, then we'll keep |
| 2596 // the raw value in the object pool. | 2612 // the raw value in the object pool. |
| 2597 return !Utils::IsInt(32, reinterpret_cast<int64_t>(object.raw())); | 2613 return !Utils::IsInt(32, reinterpret_cast<int64_t>(object.raw())); |
| 2598 } | 2614 } |
| 2599 ASSERT(object.IsNotTemporaryScopedHandle()); | 2615 ASSERT(object.IsNotTemporaryScopedHandle()); |
| 2600 ASSERT(object.IsOld()); | 2616 ASSERT(object.IsOld()); |
| 2601 return (Isolate::Current() != Dart::vm_isolate()) && | 2617 return (Isolate::Current() != Dart::vm_isolate()) && |
| 2602 // Not in the VMHeap, OR is one of the VMHeap objects we put in every | 2618 // Not in the VMHeap, OR is one of the VMHeap objects we put in every |
| 2603 // object pool. | 2619 // object pool. |
| 2604 // TODO(zra): Evaluate putting all VM heap objects into the pool. | 2620 (!object.InVMHeap() || IsAlwaysInConstantPool(object)); |
| 2605 (!object.InVMHeap() || (object.raw() == Object::null()) || | |
| 2606 (object.raw() == Bool::True().raw()) || | |
| 2607 (object.raw() == Bool::False().raw())); | |
| 2608 } | 2621 } |
| 2609 | 2622 |
| 2610 | 2623 |
| 2611 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, | 2624 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, |
| 2612 int32_t offset) { | 2625 int32_t offset) { |
| 2613 // This sequence must be of fixed size. AddressBaseImm32 | 2626 // This sequence must be of fixed size. AddressBaseImm32 |
| 2614 // forces the address operand to use a fixed-size imm32 encoding. | 2627 // forces the address operand to use a fixed-size imm32 encoding. |
| 2615 movq(dst, Address::AddressBaseImm32(pp, offset)); | 2628 movq(dst, Address::AddressBaseImm32(pp, offset)); |
| 2616 } | 2629 } |
| 2617 | 2630 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2665 | 2678 |
| 2666 intptr_t Assembler::FindImmediate(int64_t imm) { | 2679 intptr_t Assembler::FindImmediate(int64_t imm) { |
| 2667 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 2680 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 2668 ASSERT(!object_pool_.IsNull()); | 2681 ASSERT(!object_pool_.IsNull()); |
| 2669 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); | 2682 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); |
| 2670 return FindObject(smi, kNotPatchable); | 2683 return FindObject(smi, kNotPatchable); |
| 2671 } | 2684 } |
| 2672 | 2685 |
| 2673 | 2686 |
| 2674 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { | 2687 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { |
| 2688 if (!allow_constant_pool()) { |
| 2689 return false; |
| 2690 } |
| 2675 return !imm.is_int32() && | 2691 return !imm.is_int32() && |
| 2676 (pp != kNoRegister) && | 2692 (pp != kNoRegister) && |
| 2677 (Isolate::Current() != Dart::vm_isolate()); | 2693 (Isolate::Current() != Dart::vm_isolate()); |
| 2678 } | 2694 } |
| 2679 | 2695 |
| 2680 | 2696 |
| 2681 void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { | 2697 void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { |
| 2682 if (CanLoadImmediateFromPool(imm, pp)) { | 2698 if (CanLoadImmediateFromPool(imm, pp)) { |
| 2683 // It's a 64-bit constant and we're not in the VM isolate, so load from | 2699 // It's a 64-bit constant and we're not in the VM isolate, so load from |
| 2684 // object pool. | 2700 // object pool. |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3523 | 3539 |
| 3524 | 3540 |
| 3525 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3541 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 3526 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3542 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
| 3527 return xmm_reg_names[reg]; | 3543 return xmm_reg_names[reg]; |
| 3528 } | 3544 } |
| 3529 | 3545 |
| 3530 } // namespace dart | 3546 } // namespace dart |
| 3531 | 3547 |
| 3532 #endif // defined TARGET_ARCH_X64 | 3548 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |