| 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::VerifyHeapWord(const Address& address) { |
| 2881 if (VerifiedMemory::enabled()) { |
| 2882 Register addr_reg = RDX; |
| 2883 Register value = RBX; |
| 2884 // Preserve registers. |
| 2885 pushq(addr_reg); |
| 2886 pushq(value); |
| 2887 leaq(addr_reg, address); |
| 2888 // ASSERT(*address == *(address + offset)) |
| 2889 movq(value, Address(addr_reg, 0)); |
| 2890 cmpq(value, Address(addr_reg, VerifiedMemory::offset())); |
| 2891 Label ok; |
| 2892 j(EQUAL, &ok); |
| 2893 Stop("Write barrier verification failed"); |
| 2894 Bind(&ok); |
| 2895 popq(value); |
| 2896 popq(addr_reg); |
| 2897 } |
| 2898 } |
| 2899 |
| 2900 |
| 2901 void Assembler::VerifiedWrite(const Address& dest, Register value) { |
| 2902 VerifyHeapWord(dest); |
| 2903 movq(dest, value); |
| 2904 if (VerifiedMemory::enabled()) { |
| 2905 Register temp = (value == RDX) ? RCX : RDX; |
| 2906 pushq(temp); |
| 2907 leaq(temp, dest); |
| 2908 movq(Address(temp, VerifiedMemory::offset()), value); |
| 2909 popq(temp); |
| 2910 } |
| 2911 } |
| 2912 |
| 2913 |
| 2874 void Assembler::StoreIntoObject(Register object, | 2914 void Assembler::StoreIntoObject(Register object, |
| 2875 const Address& dest, | 2915 const Address& dest, |
| 2876 Register value, | 2916 Register value, |
| 2877 bool can_value_be_smi) { | 2917 bool can_value_be_smi) { |
| 2878 ASSERT(object != value); | 2918 ASSERT(object != value); |
| 2879 movq(dest, value); | 2919 VerifiedWrite(dest, value); |
| 2880 Label done; | 2920 Label done; |
| 2881 if (can_value_be_smi) { | 2921 if (can_value_be_smi) { |
| 2882 StoreIntoObjectFilter(object, value, &done); | 2922 StoreIntoObjectFilter(object, value, &done); |
| 2883 } else { | 2923 } else { |
| 2884 StoreIntoObjectFilterNoSmi(object, value, &done); | 2924 StoreIntoObjectFilterNoSmi(object, value, &done); |
| 2885 } | 2925 } |
| 2886 // A store buffer update is required. | 2926 // A store buffer update is required. |
| 2887 if (value != RDX) pushq(RDX); | 2927 if (value != RDX) pushq(RDX); |
| 2888 if (object != RDX) { | 2928 if (object != RDX) { |
| 2889 movq(RDX, object); | 2929 movq(RDX, object); |
| 2890 } | 2930 } |
| 2891 StubCode* stub_code = Isolate::Current()->stub_code(); | 2931 StubCode* stub_code = Isolate::Current()->stub_code(); |
| 2892 Call(&stub_code->UpdateStoreBufferLabel(), PP); | 2932 Call(&stub_code->UpdateStoreBufferLabel(), PP); |
| 2893 if (value != RDX) popq(RDX); | 2933 if (value != RDX) popq(RDX); |
| 2894 Bind(&done); | 2934 Bind(&done); |
| 2895 } | 2935 } |
| 2896 | 2936 |
| 2897 | 2937 |
| 2898 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2938 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 2899 const Address& dest, | 2939 const Address& dest, |
| 2900 Register value) { | 2940 Register value) { |
| 2901 movq(dest, value); | 2941 VerifiedWrite(dest, value); |
| 2902 #if defined(DEBUG) | 2942 #if defined(DEBUG) |
| 2903 Label done; | 2943 Label done; |
| 2904 pushq(value); | 2944 pushq(value); |
| 2905 StoreIntoObjectFilter(object, value, &done); | 2945 StoreIntoObjectFilter(object, value, &done); |
| 2906 Stop("Store buffer update is required"); | 2946 Stop("Store buffer update is required"); |
| 2907 Bind(&done); | 2947 Bind(&done); |
| 2908 popq(value); | 2948 popq(value); |
| 2909 #endif // defined(DEBUG) | 2949 #endif // defined(DEBUG) |
| 2910 // No store buffer update. | 2950 // No store buffer update. |
| 2911 } | 2951 } |
| 2912 | 2952 |
| 2913 | 2953 |
| 2954 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
| 2955 VerifiedWrite(dest, value); |
| 2956 #if defined(DEBUG) |
| 2957 Label done; |
| 2958 testq(value, Immediate(kHeapObjectTag)); |
| 2959 j(ZERO, &done); |
| 2960 Stop("Smi expected"); |
| 2961 Bind(&done); |
| 2962 #endif // defined(DEBUG) |
| 2963 } |
| 2964 |
| 2965 |
| 2966 void Assembler::ZeroSmiField(const Address& dest) { |
| 2967 // TODO(koda): Add VerifySmi once we distinguish initalization. |
| 2968 VerifyHeapWord(dest); |
| 2969 Immediate zero(Smi::RawValue(0)); |
| 2970 movq(dest, zero); |
| 2971 if (VerifiedMemory::enabled()) { |
| 2972 Register temp = RCX; |
| 2973 pushq(temp); |
| 2974 leaq(temp, dest); |
| 2975 movq(Address(temp, VerifiedMemory::offset()), zero); |
| 2976 popq(temp); |
| 2977 } |
| 2978 } |
| 2979 |
| 2980 |
| 2981 void Assembler::IncrementSmiField(const Address& dest, int64_t increment) { |
| 2982 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on |
| 2983 // the length of this instruction sequence. |
| 2984 // TODO(koda): Add VerifySmi once we distinguish initalization. |
| 2985 VerifyHeapWord(dest); |
| 2986 Immediate inc_imm(Smi::RawValue(increment)); |
| 2987 addq(dest, inc_imm); |
| 2988 if (VerifiedMemory::enabled()) { |
| 2989 Register temp = RCX; |
| 2990 pushq(temp); |
| 2991 leaq(temp, dest); |
| 2992 addq(Address(temp, VerifiedMemory::offset()), inc_imm); |
| 2993 popq(temp); |
| 2994 } |
| 2995 } |
| 2996 |
| 2997 |
| 2914 void Assembler::DoubleNegate(XmmRegister d) { | 2998 void Assembler::DoubleNegate(XmmRegister d) { |
| 2915 static const struct ALIGN16 { | 2999 static const struct ALIGN16 { |
| 2916 uint64_t a; | 3000 uint64_t a; |
| 2917 uint64_t b; | 3001 uint64_t b; |
| 2918 } double_negate_constant = | 3002 } double_negate_constant = |
| 2919 {0x8000000000000000LL, 0x8000000000000000LL}; | 3003 {0x8000000000000000LL, 0x8000000000000000LL}; |
| 2920 LoadImmediate( | 3004 LoadImmediate( |
| 2921 TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); | 3005 TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); |
| 2922 xorpd(d, Address(TMP, 0)); | 3006 xorpd(d, Address(TMP, 0)); |
| 2923 } | 3007 } |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3663 | 3747 |
| 3664 | 3748 |
| 3665 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3749 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 3666 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3750 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
| 3667 return xmm_reg_names[reg]; | 3751 return xmm_reg_names[reg]; |
| 3668 } | 3752 } |
| 3669 | 3753 |
| 3670 } // namespace dart | 3754 } // namespace dart |
| 3671 | 3755 |
| 3672 #endif // defined TARGET_ARCH_X64 | 3756 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |