| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 #include "macro-assembler.h" | 32 #include "macro-assembler.h" |
| 33 #include "serialize.h" | 33 #include "serialize.h" |
| 34 | 34 |
| 35 namespace v8 { | 35 namespace v8 { |
| 36 namespace internal { | 36 namespace internal { |
| 37 | 37 |
| 38 // ----------------------------------------------------------------------------- | 38 // ----------------------------------------------------------------------------- |
| 39 // Implementation of CpuFeatures | 39 // Implementation of CpuFeatures |
| 40 | 40 |
| 41 CpuFeatures::CpuFeatures() | 41 |
| 42 : supported_(kDefaultCpuFeatures), | 42 #ifdef DEBUG |
| 43 enabled_(0), | 43 bool CpuFeatures::initialized_ = false; |
| 44 found_by_runtime_probing_(0) { | 44 #endif |
| 45 } | 45 uint64_t CpuFeatures::supported_ = CpuFeatures::kDefaultCpuFeatures; |
| 46 uint64_t CpuFeatures::found_by_runtime_probing_ = 0; |
| 46 | 47 |
| 47 | 48 |
| 48 void CpuFeatures::Probe(bool portable) { | 49 void CpuFeatures::Probe() { |
| 49 ASSERT(HEAP->HasBeenSetup()); | 50 ASSERT(!initialized_); |
| 51 #ifdef DEBUG |
| 52 initialized_ = true; |
| 53 #endif |
| 50 supported_ = kDefaultCpuFeatures; | 54 supported_ = kDefaultCpuFeatures; |
| 51 if (portable && Serializer::enabled()) { | 55 if (Serializer::enabled()) { |
| 52 supported_ |= OS::CpuFeaturesImpliedByPlatform(); | 56 supported_ |= OS::CpuFeaturesImpliedByPlatform(); |
| 53 return; // No features if we might serialize. | 57 return; // No features if we might serialize. |
| 54 } | 58 } |
| 55 | 59 |
| 56 Assembler assm(NULL, 0); | 60 const int kBufferSize = 4 * KB; |
| 61 VirtualMemory* memory = new VirtualMemory(kBufferSize); |
| 62 if (!memory->IsReserved()) { |
| 63 delete memory; |
| 64 return; |
| 65 } |
| 66 ASSERT(memory->size() >= static_cast<size_t>(kBufferSize)); |
| 67 if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) { |
| 68 delete memory; |
| 69 return; |
| 70 } |
| 71 |
| 72 Assembler assm(NULL, memory->address(), kBufferSize); |
| 57 Label cpuid, done; | 73 Label cpuid, done; |
| 58 #define __ assm. | 74 #define __ assm. |
| 59 // Save old rsp, since we are going to modify the stack. | 75 // Save old rsp, since we are going to modify the stack. |
| 60 __ push(rbp); | 76 __ push(rbp); |
| 61 __ pushfq(); | 77 __ pushfq(); |
| 62 __ push(rcx); | 78 __ push(rcx); |
| 63 __ push(rbx); | 79 __ push(rbx); |
| 64 __ movq(rbp, rsp); | 80 __ movq(rbp, rsp); |
| 65 | 81 |
| 66 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. | 82 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 // Done. | 126 // Done. |
| 111 __ bind(&done); | 127 __ bind(&done); |
| 112 __ movq(rsp, rbp); | 128 __ movq(rsp, rbp); |
| 113 __ pop(rbx); | 129 __ pop(rbx); |
| 114 __ pop(rcx); | 130 __ pop(rcx); |
| 115 __ popfq(); | 131 __ popfq(); |
| 116 __ pop(rbp); | 132 __ pop(rbp); |
| 117 __ ret(0); | 133 __ ret(0); |
| 118 #undef __ | 134 #undef __ |
| 119 | 135 |
| 120 CodeDesc desc; | |
| 121 assm.GetCode(&desc); | |
| 122 Isolate* isolate = Isolate::Current(); | |
| 123 MaybeObject* maybe_code = | |
| 124 isolate->heap()->CreateCode(desc, | |
| 125 Code::ComputeFlags(Code::STUB), | |
| 126 Handle<Object>()); | |
| 127 Object* code; | |
| 128 if (!maybe_code->ToObject(&code)) return; | |
| 129 if (!code->IsCode()) return; | |
| 130 PROFILE(isolate, | |
| 131 CodeCreateEvent(Logger::BUILTIN_TAG, | |
| 132 Code::cast(code), "CpuFeatures::Probe")); | |
| 133 typedef uint64_t (*F0)(); | 136 typedef uint64_t (*F0)(); |
| 134 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry()); | 137 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address())); |
| 135 supported_ = probe(); | 138 supported_ = probe(); |
| 136 found_by_runtime_probing_ = supported_; | 139 found_by_runtime_probing_ = supported_; |
| 137 found_by_runtime_probing_ &= ~kDefaultCpuFeatures; | 140 found_by_runtime_probing_ &= ~kDefaultCpuFeatures; |
| 138 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform(); | 141 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform(); |
| 139 supported_ |= os_guarantees; | 142 supported_ |= os_guarantees; |
| 140 found_by_runtime_probing_ &= portable ? ~os_guarantees : 0; | 143 found_by_runtime_probing_ &= ~os_guarantees; |
| 141 // SSE2 and CMOV must be available on an X64 CPU. | 144 // SSE2 and CMOV must be available on an X64 CPU. |
| 142 ASSERT(IsSupported(CPUID)); | 145 ASSERT(IsSupported(CPUID)); |
| 143 ASSERT(IsSupported(SSE2)); | 146 ASSERT(IsSupported(SSE2)); |
| 144 ASSERT(IsSupported(CMOV)); | 147 ASSERT(IsSupported(CMOV)); |
| 148 |
| 149 delete memory; |
| 145 } | 150 } |
| 146 | 151 |
| 147 | 152 |
| 148 // ----------------------------------------------------------------------------- | 153 // ----------------------------------------------------------------------------- |
| 149 // Implementation of RelocInfo | 154 // Implementation of RelocInfo |
| 150 | 155 |
| 151 // Patch the code at the current PC with a call to the target address. | 156 // Patch the code at the current PC with a call to the target address. |
| 152 // Additional guard int3 instructions can be added if required. | 157 // Additional guard int3 instructions can be added if required. |
| 153 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { | 158 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { |
| 154 // Load register with immediate 64 and call through a register instructions | 159 // Load register with immediate 64 and call through a register instructions |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 } | 337 } |
| 333 | 338 |
| 334 | 339 |
| 335 // ----------------------------------------------------------------------------- | 340 // ----------------------------------------------------------------------------- |
| 336 // Implementation of Assembler. | 341 // Implementation of Assembler. |
| 337 | 342 |
| 338 #ifdef GENERATED_CODE_COVERAGE | 343 #ifdef GENERATED_CODE_COVERAGE |
| 339 static void InitCoverageLog(); | 344 static void InitCoverageLog(); |
| 340 #endif | 345 #endif |
| 341 | 346 |
| 342 Assembler::Assembler(void* buffer, int buffer_size) | 347 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) |
| 343 : AssemblerBase(Isolate::Current()), | 348 : AssemblerBase(arg_isolate), |
| 344 code_targets_(100), | 349 code_targets_(100), |
| 345 positions_recorder_(this), | 350 positions_recorder_(this), |
| 346 emit_debug_code_(FLAG_debug_code) { | 351 emit_debug_code_(FLAG_debug_code) { |
| 347 if (buffer == NULL) { | 352 if (buffer == NULL) { |
| 348 // Do our own buffer management. | 353 // Do our own buffer management. |
| 349 if (buffer_size <= kMinimalBufferSize) { | 354 if (buffer_size <= kMinimalBufferSize) { |
| 350 buffer_size = kMinimalBufferSize; | 355 buffer_size = kMinimalBufferSize; |
| 351 | 356 |
| 352 if (isolate()->assembler_spare_buffer() != NULL) { | 357 if (isolate() != NULL && isolate()->assembler_spare_buffer() != NULL) { |
| 353 buffer = isolate()->assembler_spare_buffer(); | 358 buffer = isolate()->assembler_spare_buffer(); |
| 354 isolate()->set_assembler_spare_buffer(NULL); | 359 isolate()->set_assembler_spare_buffer(NULL); |
| 355 } | 360 } |
| 356 } | 361 } |
| 357 if (buffer == NULL) { | 362 if (buffer == NULL) { |
| 358 buffer_ = NewArray<byte>(buffer_size); | 363 buffer_ = NewArray<byte>(buffer_size); |
| 359 } else { | 364 } else { |
| 360 buffer_ = static_cast<byte*>(buffer); | 365 buffer_ = static_cast<byte*>(buffer); |
| 361 } | 366 } |
| 362 buffer_size_ = buffer_size; | 367 buffer_size_ = buffer_size; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 386 last_pc_ = NULL; | 391 last_pc_ = NULL; |
| 387 | 392 |
| 388 #ifdef GENERATED_CODE_COVERAGE | 393 #ifdef GENERATED_CODE_COVERAGE |
| 389 InitCoverageLog(); | 394 InitCoverageLog(); |
| 390 #endif | 395 #endif |
| 391 } | 396 } |
| 392 | 397 |
| 393 | 398 |
| 394 Assembler::~Assembler() { | 399 Assembler::~Assembler() { |
| 395 if (own_buffer_) { | 400 if (own_buffer_) { |
| 396 if (isolate()->assembler_spare_buffer() == NULL && | 401 if (isolate() != NULL && |
| 402 isolate()->assembler_spare_buffer() == NULL && |
| 397 buffer_size_ == kMinimalBufferSize) { | 403 buffer_size_ == kMinimalBufferSize) { |
| 398 isolate()->set_assembler_spare_buffer(buffer_); | 404 isolate()->set_assembler_spare_buffer(buffer_); |
| 399 } else { | 405 } else { |
| 400 DeleteArray(buffer_); | 406 DeleteArray(buffer_); |
| 401 } | 407 } |
| 402 } | 408 } |
| 403 } | 409 } |
| 404 | 410 |
| 405 | 411 |
| 406 void Assembler::GetCode(CodeDesc* desc) { | 412 void Assembler::GetCode(CodeDesc* desc) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 | 515 |
| 510 // Copy the data. | 516 // Copy the data. |
| 511 intptr_t pc_delta = desc.buffer - buffer_; | 517 intptr_t pc_delta = desc.buffer - buffer_; |
| 512 intptr_t rc_delta = (desc.buffer + desc.buffer_size) - | 518 intptr_t rc_delta = (desc.buffer + desc.buffer_size) - |
| 513 (buffer_ + buffer_size_); | 519 (buffer_ + buffer_size_); |
| 514 memmove(desc.buffer, buffer_, desc.instr_size); | 520 memmove(desc.buffer, buffer_, desc.instr_size); |
| 515 memmove(rc_delta + reloc_info_writer.pos(), | 521 memmove(rc_delta + reloc_info_writer.pos(), |
| 516 reloc_info_writer.pos(), desc.reloc_size); | 522 reloc_info_writer.pos(), desc.reloc_size); |
| 517 | 523 |
| 518 // Switch buffers. | 524 // Switch buffers. |
| 519 if (isolate()->assembler_spare_buffer() == NULL && | 525 if (isolate() != NULL && |
| 526 isolate()->assembler_spare_buffer() == NULL && |
| 520 buffer_size_ == kMinimalBufferSize) { | 527 buffer_size_ == kMinimalBufferSize) { |
| 521 isolate()->set_assembler_spare_buffer(buffer_); | 528 isolate()->set_assembler_spare_buffer(buffer_); |
| 522 } else { | 529 } else { |
| 523 DeleteArray(buffer_); | 530 DeleteArray(buffer_); |
| 524 } | 531 } |
| 525 buffer_ = desc.buffer; | 532 buffer_ = desc.buffer; |
| 526 buffer_size_ = desc.buffer_size; | 533 buffer_size_ = desc.buffer_size; |
| 527 pc_ += pc_delta; | 534 pc_ += pc_delta; |
| 528 if (last_pc_ != NULL) { | 535 if (last_pc_ != NULL) { |
| 529 last_pc_ += pc_delta; | 536 last_pc_ += pc_delta; |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 void Assembler::cmpb_al(Immediate imm8) { | 1037 void Assembler::cmpb_al(Immediate imm8) { |
| 1031 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_)); | 1038 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_)); |
| 1032 EnsureSpace ensure_space(this); | 1039 EnsureSpace ensure_space(this); |
| 1033 last_pc_ = pc_; | 1040 last_pc_ = pc_; |
| 1034 emit(0x3c); | 1041 emit(0x3c); |
| 1035 emit(imm8.value_); | 1042 emit(imm8.value_); |
| 1036 } | 1043 } |
| 1037 | 1044 |
| 1038 | 1045 |
| 1039 void Assembler::cpuid() { | 1046 void Assembler::cpuid() { |
| 1040 ASSERT(isolate()->cpu_features()->IsEnabled(CPUID)); | 1047 ASSERT(CpuFeatures::IsEnabled(CPUID)); |
| 1041 EnsureSpace ensure_space(this); | 1048 EnsureSpace ensure_space(this); |
| 1042 last_pc_ = pc_; | 1049 last_pc_ = pc_; |
| 1043 emit(0x0F); | 1050 emit(0x0F); |
| 1044 emit(0xA2); | 1051 emit(0xA2); |
| 1045 } | 1052 } |
| 1046 | 1053 |
| 1047 | 1054 |
| 1048 void Assembler::cqo() { | 1055 void Assembler::cqo() { |
| 1049 EnsureSpace ensure_space(this); | 1056 EnsureSpace ensure_space(this); |
| 1050 last_pc_ = pc_; | 1057 last_pc_ = pc_; |
| (...skipping 1330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2381 void Assembler::fistp_s(const Operand& adr) { | 2388 void Assembler::fistp_s(const Operand& adr) { |
| 2382 EnsureSpace ensure_space(this); | 2389 EnsureSpace ensure_space(this); |
| 2383 last_pc_ = pc_; | 2390 last_pc_ = pc_; |
| 2384 emit_optional_rex_32(adr); | 2391 emit_optional_rex_32(adr); |
| 2385 emit(0xDB); | 2392 emit(0xDB); |
| 2386 emit_operand(3, adr); | 2393 emit_operand(3, adr); |
| 2387 } | 2394 } |
| 2388 | 2395 |
| 2389 | 2396 |
| 2390 void Assembler::fisttp_s(const Operand& adr) { | 2397 void Assembler::fisttp_s(const Operand& adr) { |
| 2391 ASSERT(isolate()->cpu_features()->IsEnabled(SSE3)); | 2398 ASSERT(CpuFeatures::IsEnabled(SSE3)); |
| 2392 EnsureSpace ensure_space(this); | 2399 EnsureSpace ensure_space(this); |
| 2393 last_pc_ = pc_; | 2400 last_pc_ = pc_; |
| 2394 emit_optional_rex_32(adr); | 2401 emit_optional_rex_32(adr); |
| 2395 emit(0xDB); | 2402 emit(0xDB); |
| 2396 emit_operand(1, adr); | 2403 emit_operand(1, adr); |
| 2397 } | 2404 } |
| 2398 | 2405 |
| 2399 | 2406 |
| 2400 void Assembler::fisttp_d(const Operand& adr) { | 2407 void Assembler::fisttp_d(const Operand& adr) { |
| 2401 ASSERT(isolate()->cpu_features()->IsEnabled(SSE3)); | 2408 ASSERT(CpuFeatures::IsEnabled(SSE3)); |
| 2402 EnsureSpace ensure_space(this); | 2409 EnsureSpace ensure_space(this); |
| 2403 last_pc_ = pc_; | 2410 last_pc_ = pc_; |
| 2404 emit_optional_rex_32(adr); | 2411 emit_optional_rex_32(adr); |
| 2405 emit(0xDD); | 2412 emit(0xDD); |
| 2406 emit_operand(1, adr); | 2413 emit_operand(1, adr); |
| 2407 } | 2414 } |
| 2408 | 2415 |
| 2409 | 2416 |
| 2410 void Assembler::fist_s(const Operand& adr) { | 2417 void Assembler::fist_s(const Operand& adr) { |
| 2411 EnsureSpace ensure_space(this); | 2418 EnsureSpace ensure_space(this); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2709 last_pc_ = pc_; | 2716 last_pc_ = pc_; |
| 2710 emit(0x66); | 2717 emit(0x66); |
| 2711 emit_rex_64(src, dst); | 2718 emit_rex_64(src, dst); |
| 2712 emit(0x0F); | 2719 emit(0x0F); |
| 2713 emit(0x7E); | 2720 emit(0x7E); |
| 2714 emit_sse_operand(src, dst); | 2721 emit_sse_operand(src, dst); |
| 2715 } | 2722 } |
| 2716 | 2723 |
| 2717 | 2724 |
| 2718 void Assembler::movdqa(const Operand& dst, XMMRegister src) { | 2725 void Assembler::movdqa(const Operand& dst, XMMRegister src) { |
| 2719 ASSERT(isolate()->cpu_features()->IsEnabled(SSE2)); | 2726 ASSERT(CpuFeatures::IsEnabled(SSE2)); |
| 2720 EnsureSpace ensure_space(this); | 2727 EnsureSpace ensure_space(this); |
| 2721 last_pc_ = pc_; | 2728 last_pc_ = pc_; |
| 2722 emit(0x66); | 2729 emit(0x66); |
| 2723 emit_rex_64(src, dst); | 2730 emit_rex_64(src, dst); |
| 2724 emit(0x0F); | 2731 emit(0x0F); |
| 2725 emit(0x7F); | 2732 emit(0x7F); |
| 2726 emit_sse_operand(src, dst); | 2733 emit_sse_operand(src, dst); |
| 2727 } | 2734 } |
| 2728 | 2735 |
| 2729 | 2736 |
| 2730 void Assembler::movdqa(XMMRegister dst, const Operand& src) { | 2737 void Assembler::movdqa(XMMRegister dst, const Operand& src) { |
| 2731 ASSERT(isolate()->cpu_features()->IsEnabled(SSE2)); | 2738 ASSERT(CpuFeatures::IsEnabled(SSE2)); |
| 2732 EnsureSpace ensure_space(this); | 2739 EnsureSpace ensure_space(this); |
| 2733 last_pc_ = pc_; | 2740 last_pc_ = pc_; |
| 2734 emit(0x66); | 2741 emit(0x66); |
| 2735 emit_rex_64(dst, src); | 2742 emit_rex_64(dst, src); |
| 2736 emit(0x0F); | 2743 emit(0x0F); |
| 2737 emit(0x6F); | 2744 emit(0x6F); |
| 2738 emit_sse_operand(dst, src); | 2745 emit_sse_operand(dst, src); |
| 2739 } | 2746 } |
| 2740 | 2747 |
| 2741 | 2748 |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3164 // specially coded on x64 means that it is a relative 32 bit address, as used | 3171 // specially coded on x64 means that it is a relative 32 bit address, as used |
| 3165 // by branch instructions. | 3172 // by branch instructions. |
| 3166 return (1 << rmode_) & kApplyMask; | 3173 return (1 << rmode_) & kApplyMask; |
| 3167 } | 3174 } |
| 3168 | 3175 |
| 3169 | 3176 |
| 3170 | 3177 |
| 3171 } } // namespace v8::internal | 3178 } } // namespace v8::internal |
| 3172 | 3179 |
| 3173 #endif // V8_TARGET_ARCH_X64 | 3180 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |