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