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" |
(...skipping 2366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2377 | 2377 |
2378 | 2378 |
2379 void Assembler::hlt() { | 2379 void Assembler::hlt() { |
2380 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2380 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2381 EmitUint8(0xF4); | 2381 EmitUint8(0xF4); |
2382 } | 2382 } |
2383 | 2383 |
2384 | 2384 |
2385 void Assembler::j(Condition condition, Label* label, bool near) { | 2385 void Assembler::j(Condition condition, Label* label, bool near) { |
2386 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2386 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2387 if (VerifiedMemory::enabled()) { | |
2388 near = Assembler::kFarJump; | |
2389 } | |
2387 if (label->IsBound()) { | 2390 if (label->IsBound()) { |
2388 static const int kShortSize = 2; | 2391 static const int kShortSize = 2; |
2389 static const int kLongSize = 6; | 2392 static const int kLongSize = 6; |
2390 intptr_t offset = label->Position() - buffer_.Size(); | 2393 intptr_t offset = label->Position() - buffer_.Size(); |
2391 ASSERT(offset <= 0); | 2394 ASSERT(offset <= 0); |
2392 if (Utils::IsInt(8, offset - kShortSize)) { | 2395 if (Utils::IsInt(8, offset - kShortSize)) { |
2393 EmitUint8(0x70 + condition); | 2396 EmitUint8(0x70 + condition); |
2394 EmitUint8((offset - kShortSize) & 0xFF); | 2397 EmitUint8((offset - kShortSize) & 0xFF); |
2395 } else { | 2398 } else { |
2396 EmitUint8(0x0F); | 2399 EmitUint8(0x0F); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2429 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2432 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2430 Operand operand(reg); | 2433 Operand operand(reg); |
2431 EmitOperandREX(4, operand, REX_NONE); | 2434 EmitOperandREX(4, operand, REX_NONE); |
2432 EmitUint8(0xFF); | 2435 EmitUint8(0xFF); |
2433 EmitOperand(4, operand); | 2436 EmitOperand(4, operand); |
2434 } | 2437 } |
2435 | 2438 |
2436 | 2439 |
2437 void Assembler::jmp(Label* label, bool near) { | 2440 void Assembler::jmp(Label* label, bool near) { |
2438 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2441 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2442 if (VerifiedMemory::enabled()) { | |
2443 near = Assembler::kFarJump; | |
2444 } | |
2439 if (label->IsBound()) { | 2445 if (label->IsBound()) { |
2440 static const int kShortSize = 2; | 2446 static const int kShortSize = 2; |
2441 static const int kLongSize = 5; | 2447 static const int kLongSize = 5; |
2442 intptr_t offset = label->Position() - buffer_.Size(); | 2448 intptr_t offset = label->Position() - buffer_.Size(); |
2443 ASSERT(offset <= 0); | 2449 ASSERT(offset <= 0); |
2444 if (Utils::IsInt(8, offset - kShortSize)) { | 2450 if (Utils::IsInt(8, offset - kShortSize)) { |
2445 EmitUint8(0xEB); | 2451 EmitUint8(0xEB); |
2446 EmitUint8((offset - kShortSize) & 0xFF); | 2452 EmitUint8((offset - kShortSize) & 0xFF); |
2447 } else { | 2453 } else { |
2448 EmitUint8(0xE9); | 2454 EmitUint8(0xE9); |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2864 // Mask out higher, uninteresting bits which were polluted by dest. | 2870 // Mask out higher, uninteresting bits which were polluted by dest. |
2865 andl(value, Immediate(kObjectAlignment - 1)); | 2871 andl(value, Immediate(kObjectAlignment - 1)); |
2866 // Compare with the expected bit pattern. | 2872 // Compare with the expected bit pattern. |
2867 cmpl(value, Immediate( | 2873 cmpl(value, Immediate( |
2868 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + | 2874 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + |
2869 kOldObjectAlignmentOffset + kHeapObjectTag)); | 2875 kOldObjectAlignmentOffset + kHeapObjectTag)); |
2870 j(NOT_ZERO, no_update, Assembler::kNearJump); | 2876 j(NOT_ZERO, no_update, Assembler::kNearJump); |
2871 } | 2877 } |
2872 | 2878 |
2873 | 2879 |
2880 void Assembler::Verify(const Address& dest) { | |
Ivan Posva
2014/11/14 22:16:06
ditto about the name.
koda
2014/11/17 17:08:59
Done, matching ia32.
| |
2881 if (VerifiedMemory::enabled()) { | |
2882 Register dest_addr = RDX; | |
2883 Register old_value = RBX; | |
2884 pushq(dest_addr); | |
2885 pushq(old_value); | |
2886 leaq(dest_addr, dest); | |
2887 movq(old_value, Address(dest_addr, 0)); | |
2888 cmpq(old_value, Address(dest_addr, VerifiedMemory::offset())); | |
2889 Label ok; | |
2890 j(EQUAL, &ok, Assembler::kNearJump); | |
Ivan Posva
2014/11/14 22:16:07
Will be a forced far jump.
koda
2014/11/17 17:09:00
Good point; removed hint.
| |
2891 Stop("Write barrier verification failed"); | |
2892 Bind(&ok); | |
2893 popq(old_value); | |
2894 popq(dest_addr); | |
2895 } | |
2896 } | |
2897 | |
2898 | |
2899 void Assembler::VerifiedWrite(const Address& dest, Register value) { | |
2900 Verify(dest); | |
2901 movq(dest, value); | |
2902 if (VerifiedMemory::enabled()) { | |
2903 Register temp = (value == RDX) ? RCX : RDX; | |
2904 pushq(temp); | |
2905 leaq(temp, dest); | |
2906 movq(Address(temp, VerifiedMemory::offset()), value); | |
2907 popq(temp); | |
2908 } | |
2909 } | |
2910 | |
2911 | |
2874 void Assembler::StoreIntoObject(Register object, | 2912 void Assembler::StoreIntoObject(Register object, |
2875 const Address& dest, | 2913 const Address& dest, |
2876 Register value, | 2914 Register value, |
2877 bool can_value_be_smi) { | 2915 bool can_value_be_smi) { |
2878 ASSERT(object != value); | 2916 ASSERT(object != value); |
2879 movq(dest, value); | 2917 VerifiedWrite(dest, value); |
2880 Label done; | 2918 Label done; |
2881 if (can_value_be_smi) { | 2919 if (can_value_be_smi) { |
2882 StoreIntoObjectFilter(object, value, &done); | 2920 StoreIntoObjectFilter(object, value, &done); |
2883 } else { | 2921 } else { |
2884 StoreIntoObjectFilterNoSmi(object, value, &done); | 2922 StoreIntoObjectFilterNoSmi(object, value, &done); |
2885 } | 2923 } |
2886 // A store buffer update is required. | 2924 // A store buffer update is required. |
2887 if (value != RAX) pushq(RAX); | 2925 if (value != RAX) pushq(RAX); |
2888 if (object != RAX) { | 2926 if (object != RAX) { |
2889 movq(RAX, object); | 2927 movq(RAX, object); |
2890 } | 2928 } |
2891 StubCode* stub_code = Isolate::Current()->stub_code(); | 2929 StubCode* stub_code = Isolate::Current()->stub_code(); |
2892 Call(&stub_code->UpdateStoreBufferLabel(), PP); | 2930 Call(&stub_code->UpdateStoreBufferLabel(), PP); |
2893 if (value != RAX) popq(RAX); | 2931 if (value != RAX) popq(RAX); |
2894 Bind(&done); | 2932 Bind(&done); |
2895 } | 2933 } |
2896 | 2934 |
2897 | 2935 |
2898 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2936 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2899 const Address& dest, | 2937 const Address& dest, |
2900 Register value) { | 2938 Register value) { |
2901 movq(dest, value); | 2939 VerifiedWrite(dest, value); |
2902 #if defined(DEBUG) | 2940 #if defined(DEBUG) |
2903 Label done; | 2941 Label done; |
2904 pushq(value); | 2942 pushq(value); |
2905 StoreIntoObjectFilter(object, value, &done); | 2943 StoreIntoObjectFilter(object, value, &done); |
2906 Stop("Store buffer update is required"); | 2944 Stop("Store buffer update is required"); |
2907 Bind(&done); | 2945 Bind(&done); |
2908 popq(value); | 2946 popq(value); |
2909 #endif // defined(DEBUG) | 2947 #endif // defined(DEBUG) |
2910 // No store buffer update. | 2948 // No store buffer update. |
2911 } | 2949 } |
2912 | 2950 |
2913 | 2951 |
2952 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { | |
2953 VerifiedWrite(dest, value); | |
2954 #if defined(DEBUG) | |
2955 Label done; | |
2956 testq(value, Immediate(kHeapObjectTag)); | |
2957 j(ZERO, &done); | |
2958 Stop("Smi expected"); | |
2959 Bind(&done); | |
2960 #endif // defined(DEBUG) | |
2961 } | |
2962 | |
2963 | |
2964 void Assembler::ZeroSmiField(const Address& dest) { | |
2965 Verify(dest); // TODO(koda): Add VerifySmi once we distinguish initalization. | |
2966 Immediate zero(Smi::RawValue(0)); | |
2967 movq(dest, zero); | |
2968 if (VerifiedMemory::enabled()) { | |
2969 Register temp = RCX; | |
2970 pushq(temp); | |
2971 leaq(temp, dest); | |
2972 movq(Address(temp, VerifiedMemory::offset()), zero); | |
2973 popq(temp); | |
2974 } | |
2975 } | |
2976 | |
2977 | |
2978 void Assembler::IncrementSmiField(const Address& dest, int64_t increment) { | |
2979 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on | |
2980 // the length of this instruction sequence. | |
2981 Verify(dest); // TODO(koda): Add VerifySmi once we distinguish initalization. | |
2982 Immediate inc_imm(Smi::RawValue(increment)); | |
2983 addq(dest, inc_imm); | |
2984 if (VerifiedMemory::enabled()) { | |
2985 Register temp = RCX; | |
2986 pushq(temp); | |
2987 leaq(temp, dest); | |
2988 addq(Address(temp, VerifiedMemory::offset()), inc_imm); | |
2989 popq(temp); | |
2990 } | |
2991 } | |
2992 | |
2993 | |
2914 void Assembler::DoubleNegate(XmmRegister d) { | 2994 void Assembler::DoubleNegate(XmmRegister d) { |
2915 static const struct ALIGN16 { | 2995 static const struct ALIGN16 { |
2916 uint64_t a; | 2996 uint64_t a; |
2917 uint64_t b; | 2997 uint64_t b; |
2918 } double_negate_constant = | 2998 } double_negate_constant = |
2919 {0x8000000000000000LL, 0x8000000000000000LL}; | 2999 {0x8000000000000000LL, 0x8000000000000000LL}; |
2920 LoadImmediate( | 3000 LoadImmediate( |
2921 TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); | 3001 TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); |
2922 xorpd(d, Address(TMP, 0)); | 3002 xorpd(d, Address(TMP, 0)); |
2923 } | 3003 } |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3663 | 3743 |
3664 | 3744 |
3665 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3745 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3666 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3746 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3667 return xmm_reg_names[reg]; | 3747 return xmm_reg_names[reg]; |
3668 } | 3748 } |
3669 | 3749 |
3670 } // namespace dart | 3750 } // namespace dart |
3671 | 3751 |
3672 #endif // defined TARGET_ARCH_X64 | 3752 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |