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_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/instructions.h" | 11 #include "vm/instructions.h" |
12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
13 #include "vm/memory_region.h" | 13 #include "vm/memory_region.h" |
14 #include "vm/runtime_entry.h" | 14 #include "vm/runtime_entry.h" |
15 #include "vm/stack_frame.h" | 15 #include "vm/stack_frame.h" |
16 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
17 | 17 |
18 namespace dart { | 18 namespace dart { |
19 | 19 |
20 DECLARE_FLAG(bool, allow_absolute_addresses); | |
20 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); | 21 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
21 DECLARE_FLAG(bool, inline_alloc); | 22 DECLARE_FLAG(bool, inline_alloc); |
22 | 23 |
23 | 24 |
24 Assembler::Assembler(bool use_far_branches) | 25 Assembler::Assembler(bool use_far_branches) |
25 : buffer_(), | 26 : buffer_(), |
26 prologue_offset_(-1), | 27 prologue_offset_(-1), |
27 comments_(), | 28 comments_(), |
28 constant_pool_allowed_(false) { | 29 constant_pool_allowed_(false) { |
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. |
(...skipping 2781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2811 bool is_unique) { | 2812 bool is_unique) { |
2812 if (Thread::CanLoadFromThread(object)) { | 2813 if (Thread::CanLoadFromThread(object)) { |
2813 movq(dst, Address(THR, Thread::OffsetFromThread(object))); | 2814 movq(dst, Address(THR, Thread::OffsetFromThread(object))); |
2814 } else if (CanLoadFromObjectPool(object)) { | 2815 } else if (CanLoadFromObjectPool(object)) { |
2815 const int32_t offset = ObjectPool::element_offset( | 2816 const int32_t offset = ObjectPool::element_offset( |
2816 is_unique ? object_pool_wrapper_.AddObject(object) | 2817 is_unique ? object_pool_wrapper_.AddObject(object) |
2817 : object_pool_wrapper_.FindObject(object)); | 2818 : object_pool_wrapper_.FindObject(object)); |
2818 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag); | 2819 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag); |
2819 } else { | 2820 } else { |
2820 ASSERT(object.IsSmi() || object.InVMHeap()); | 2821 ASSERT(object.IsSmi() || object.InVMHeap()); |
2822 ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses); | |
2821 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2823 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
2822 } | 2824 } |
2823 } | 2825 } |
2824 | 2826 |
2825 | 2827 |
2826 void Assembler::LoadFunctionFromCalleePool(Register dst, | 2828 void Assembler::LoadFunctionFromCalleePool(Register dst, |
2827 const Function& function, | 2829 const Function& function, |
2828 Register new_pp) { | 2830 Register new_pp) { |
2829 ASSERT(!constant_pool_allowed()); | 2831 ASSERT(!constant_pool_allowed()); |
2830 ASSERT(new_pp != PP); | 2832 ASSERT(new_pp != PP); |
(...skipping 14 matching lines...) Expand all Loading... | |
2845 | 2847 |
2846 | 2848 |
2847 void Assembler::StoreObject(const Address& dst, const Object& object) { | 2849 void Assembler::StoreObject(const Address& dst, const Object& object) { |
2848 if (Thread::CanLoadFromThread(object)) { | 2850 if (Thread::CanLoadFromThread(object)) { |
2849 movq(TMP, Address(THR, Thread::OffsetFromThread(object))); | 2851 movq(TMP, Address(THR, Thread::OffsetFromThread(object))); |
2850 movq(dst, TMP); | 2852 movq(dst, TMP); |
2851 } else if (CanLoadFromObjectPool(object)) { | 2853 } else if (CanLoadFromObjectPool(object)) { |
2852 LoadObject(TMP, object); | 2854 LoadObject(TMP, object); |
2853 movq(dst, TMP); | 2855 movq(dst, TMP); |
2854 } else { | 2856 } else { |
2857 ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses); | |
2855 MoveImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2858 MoveImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
2856 } | 2859 } |
2857 } | 2860 } |
2858 | 2861 |
2859 | 2862 |
2860 void Assembler::PushObject(const Object& object) { | 2863 void Assembler::PushObject(const Object& object) { |
2861 if (Thread::CanLoadFromThread(object)) { | 2864 if (Thread::CanLoadFromThread(object)) { |
2862 pushq(Address(THR, Thread::OffsetFromThread(object))); | 2865 pushq(Address(THR, Thread::OffsetFromThread(object))); |
2863 } else if (CanLoadFromObjectPool(object)) { | 2866 } else if (CanLoadFromObjectPool(object)) { |
2864 LoadObject(TMP, object); | 2867 LoadObject(TMP, object); |
2865 pushq(TMP); | 2868 pushq(TMP); |
2866 } else { | 2869 } else { |
2870 ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses); | |
2867 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2871 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw()))); |
2868 } | 2872 } |
2869 } | 2873 } |
2870 | 2874 |
2871 | 2875 |
2872 void Assembler::CompareObject(Register reg, const Object& object) { | 2876 void Assembler::CompareObject(Register reg, const Object& object) { |
2873 if (Thread::CanLoadFromThread(object)) { | 2877 if (Thread::CanLoadFromThread(object)) { |
2874 cmpq(reg, Address(THR, Thread::OffsetFromThread(object))); | 2878 cmpq(reg, Address(THR, Thread::OffsetFromThread(object))); |
2875 } else if (CanLoadFromObjectPool(object)) { | 2879 } else if (CanLoadFromObjectPool(object)) { |
2876 const int32_t offset = | 2880 const int32_t offset = |
2877 ObjectPool::element_offset(object_pool_wrapper_.FindObject(object)); | 2881 ObjectPool::element_offset(object_pool_wrapper_.FindObject(object)); |
2878 cmpq(reg, Address(PP, offset-kHeapObjectTag)); | 2882 cmpq(reg, Address(PP, offset-kHeapObjectTag)); |
2879 } else { | 2883 } else { |
2884 ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses); | |
2880 CompareImmediate( | 2885 CompareImmediate( |
2881 reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2886 reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
2882 } | 2887 } |
2883 } | 2888 } |
2884 | 2889 |
2885 | 2890 |
2886 intptr_t Assembler::FindImmediate(int64_t imm) { | 2891 intptr_t Assembler::FindImmediate(int64_t imm) { |
2887 return object_pool_wrapper_.FindImmediate(imm); | 2892 return object_pool_wrapper_.FindImmediate(imm); |
2888 } | 2893 } |
2889 | 2894 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3019 Label ok; | 3024 Label ok; |
3020 testb(dest, Immediate(kHeapObjectTag)); | 3025 testb(dest, Immediate(kHeapObjectTag)); |
3021 j(ZERO, &ok, Assembler::kNearJump); | 3026 j(ZERO, &ok, Assembler::kNearJump); |
3022 // Non-smi case: Check for the special zap word or null. | 3027 // Non-smi case: Check for the special zap word or null. |
3023 #if defined(DEBUG) | 3028 #if defined(DEBUG) |
3024 cmpq(dest, Immediate(Heap::kZap64Bits)); | 3029 cmpq(dest, Immediate(Heap::kZap64Bits)); |
3025 j(EQUAL, &ok, Assembler::kNearJump); | 3030 j(EQUAL, &ok, Assembler::kNearJump); |
3026 #else | 3031 #else |
3027 #error Only supported in DEBUG mode | 3032 #error Only supported in DEBUG mode |
3028 #endif | 3033 #endif |
3029 cmpq(dest, Immediate(reinterpret_cast<uint64_t>(Object::null()))); | 3034 // Is TMP available here or do we need a memory-memory comparison? |
3035 LoadObject(TMP, Object::null_object()); | |
Florian Schneider
2015/09/11 13:42:40
TMP should be only used inside the Assembler, so I
| |
3036 cmpq(dest, TMP); | |
3030 j(EQUAL, &ok, Assembler::kNearJump); | 3037 j(EQUAL, &ok, Assembler::kNearJump); |
3031 static const bool kFixedLengthEncoding = true; | 3038 static const bool kFixedLengthEncoding = true; |
3032 Stop("Expected zapped, Smi or null", kFixedLengthEncoding); | 3039 Stop("Expected zapped, Smi or null", kFixedLengthEncoding); |
3033 Bind(&ok); | 3040 Bind(&ok); |
3034 } | 3041 } |
3035 | 3042 |
3036 | 3043 |
3037 void Assembler::VerifySmi(const Address& dest, const char* stop_msg) { | 3044 void Assembler::VerifySmi(const Address& dest, const char* stop_msg) { |
3038 Label done; | 3045 Label done; |
3039 testb(dest, Immediate(kHeapObjectTag)); | 3046 testb(dest, Immediate(kHeapObjectTag)); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3437 | 3444 |
3438 | 3445 |
3439 void Assembler::MaybeTraceAllocation(intptr_t cid, | 3446 void Assembler::MaybeTraceAllocation(intptr_t cid, |
3440 Label* trace, | 3447 Label* trace, |
3441 bool near_jump, | 3448 bool near_jump, |
3442 bool inline_isolate) { | 3449 bool inline_isolate) { |
3443 ASSERT(cid > 0); | 3450 ASSERT(cid > 0); |
3444 intptr_t state_offset = ClassTable::StateOffsetFor(cid); | 3451 intptr_t state_offset = ClassTable::StateOffsetFor(cid); |
3445 Register temp_reg = TMP; | 3452 Register temp_reg = TMP; |
3446 if (inline_isolate) { | 3453 if (inline_isolate) { |
3454 ASSERT(FLAG_allow_absolute_addresses); | |
3447 ClassTable* class_table = Isolate::Current()->class_table(); | 3455 ClassTable* class_table = Isolate::Current()->class_table(); |
3448 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); | 3456 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); |
3449 if (cid < kNumPredefinedCids) { | 3457 if (cid < kNumPredefinedCids) { |
3450 movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr))); | 3458 movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr))); |
3451 } else { | 3459 } else { |
3452 movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr))); | 3460 movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr))); |
3453 movq(temp_reg, Address(temp_reg, 0)); | 3461 movq(temp_reg, Address(temp_reg, 0)); |
3454 } | 3462 } |
3455 } else { | 3463 } else { |
3456 LoadIsolate(temp_reg); | 3464 LoadIsolate(temp_reg); |
(...skipping 10 matching lines...) Expand all Loading... | |
3467 | 3475 |
3468 | 3476 |
3469 void Assembler::UpdateAllocationStats(intptr_t cid, | 3477 void Assembler::UpdateAllocationStats(intptr_t cid, |
3470 Heap::Space space, | 3478 Heap::Space space, |
3471 bool inline_isolate) { | 3479 bool inline_isolate) { |
3472 ASSERT(cid > 0); | 3480 ASSERT(cid > 0); |
3473 intptr_t counter_offset = | 3481 intptr_t counter_offset = |
3474 ClassTable::CounterOffsetFor(cid, space == Heap::kNew); | 3482 ClassTable::CounterOffsetFor(cid, space == Heap::kNew); |
3475 Register temp_reg = TMP; | 3483 Register temp_reg = TMP; |
3476 if (inline_isolate) { | 3484 if (inline_isolate) { |
3485 ASSERT(FLAG_allow_absolute_addresses); | |
3477 ClassTable* class_table = Isolate::Current()->class_table(); | 3486 ClassTable* class_table = Isolate::Current()->class_table(); |
3478 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); | 3487 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); |
3479 if (cid < kNumPredefinedCids) { | 3488 if (cid < kNumPredefinedCids) { |
3480 movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr))); | 3489 movq(temp_reg, Immediate(reinterpret_cast<uword>(*table_ptr))); |
3481 } else { | 3490 } else { |
3482 movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr))); | 3491 movq(temp_reg, Immediate(reinterpret_cast<uword>(table_ptr))); |
3483 movq(temp_reg, Address(temp_reg, 0)); | 3492 movq(temp_reg, Address(temp_reg, 0)); |
3484 } | 3493 } |
3485 } else { | 3494 } else { |
3486 LoadIsolate(temp_reg); | 3495 LoadIsolate(temp_reg); |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3927 | 3936 |
3928 | 3937 |
3929 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3938 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3930 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3939 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3931 return xmm_reg_names[reg]; | 3940 return xmm_reg_names[reg]; |
3932 } | 3941 } |
3933 | 3942 |
3934 } // namespace dart | 3943 } // namespace dart |
3935 | 3944 |
3936 #endif // defined TARGET_ARCH_X64 | 3945 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |