| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include "disassembler.h" | 39 #include "disassembler.h" |
| 40 #include "macro-assembler.h" | 40 #include "macro-assembler.h" |
| 41 #include "serialize.h" | 41 #include "serialize.h" |
| 42 | 42 |
| 43 namespace v8 { | 43 namespace v8 { |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 // ----------------------------------------------------------------------------- | 46 // ----------------------------------------------------------------------------- |
| 47 // Implementation of CpuFeatures | 47 // Implementation of CpuFeatures |
| 48 | 48 |
| 49 // Safe default is no features. | |
| 50 uint64_t CpuFeatures::supported_ = 0; | |
| 51 uint64_t CpuFeatures::enabled_ = 0; | |
| 52 uint64_t CpuFeatures::found_by_runtime_probing_ = 0; | |
| 53 | |
| 54 | |
| 55 // The Probe method needs executable memory, so it uses Heap::CreateCode. | 49 // The Probe method needs executable memory, so it uses Heap::CreateCode. |
| 56 // Allocation failure is silent and leads to safe default. | 50 // Allocation failure is silent and leads to safe default. |
| 57 void CpuFeatures::Probe() { | 51 void CpuFeatures::Probe() { |
| 52 AssemblerData* data = v8_context()->assembler_data_; |
| 58 ASSERT(Heap::HasBeenSetup()); | 53 ASSERT(Heap::HasBeenSetup()); |
| 59 ASSERT(supported_ == 0); | 54 ASSERT(data->supported_ == 0); |
| 60 if (Serializer::enabled()) { | 55 if (Serializer::enabled()) { |
| 61 supported_ |= OS::CpuFeaturesImpliedByPlatform(); | 56 data->supported_ |= OS::CpuFeaturesImpliedByPlatform(); |
| 62 return; // No features if we might serialize. | 57 return; // No features if we might serialize. |
| 63 } | 58 } |
| 64 | 59 |
| 65 Assembler assm(NULL, 0); | 60 Assembler assm(NULL, 0); |
| 66 Label cpuid, done; | 61 Label cpuid, done; |
| 67 #define __ assm. | 62 #define __ assm. |
| 68 // Save old esp, since we are going to modify the stack. | 63 // Save old esp, since we are going to modify the stack. |
| 69 __ push(ebp); | 64 __ push(ebp); |
| 70 __ pushfd(); | 65 __ pushfd(); |
| 71 __ push(ecx); | 66 __ push(ecx); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 87 // CPUID not supported. Clear the supported features in edx:eax. | 82 // CPUID not supported. Clear the supported features in edx:eax. |
| 88 __ xor_(eax, Operand(eax)); | 83 __ xor_(eax, Operand(eax)); |
| 89 __ xor_(edx, Operand(edx)); | 84 __ xor_(edx, Operand(edx)); |
| 90 __ jmp(&done); | 85 __ jmp(&done); |
| 91 | 86 |
| 92 // Invoke CPUID with 1 in eax to get feature information in | 87 // Invoke CPUID with 1 in eax to get feature information in |
| 93 // ecx:edx. Temporarily enable CPUID support because we know it's | 88 // ecx:edx. Temporarily enable CPUID support because we know it's |
| 94 // safe here. | 89 // safe here. |
| 95 __ bind(&cpuid); | 90 __ bind(&cpuid); |
| 96 __ mov(eax, 1); | 91 __ mov(eax, 1); |
| 97 supported_ = (1 << CPUID); | 92 data->supported_ = (1 << CPUID); |
| 98 { Scope fscope(CPUID); | 93 { Scope fscope(CPUID); |
| 99 __ cpuid(); | 94 __ cpuid(); |
| 100 } | 95 } |
| 101 supported_ = 0; | 96 data->supported_ = 0; |
| 102 | 97 |
| 103 // Move the result from ecx:edx to edx:eax and make sure to mark the | 98 // Move the result from ecx:edx to edx:eax and make sure to mark the |
| 104 // CPUID feature as supported. | 99 // CPUID feature as supported. |
| 105 __ mov(eax, Operand(edx)); | 100 __ mov(eax, Operand(edx)); |
| 106 __ or_(eax, 1 << CPUID); | 101 __ or_(eax, 1 << CPUID); |
| 107 __ mov(edx, Operand(ecx)); | 102 __ mov(edx, Operand(ecx)); |
| 108 | 103 |
| 109 // Done. | 104 // Done. |
| 110 __ bind(&done); | 105 __ bind(&done); |
| 111 __ mov(esp, Operand(ebp)); | 106 __ mov(esp, Operand(ebp)); |
| 112 __ pop(ebx); | 107 __ pop(ebx); |
| 113 __ pop(ecx); | 108 __ pop(ecx); |
| 114 __ popfd(); | 109 __ popfd(); |
| 115 __ pop(ebp); | 110 __ pop(ebp); |
| 116 __ ret(0); | 111 __ ret(0); |
| 117 #undef __ | 112 #undef __ |
| 118 | 113 |
| 119 CodeDesc desc; | 114 CodeDesc desc; |
| 120 assm.GetCode(&desc); | 115 assm.GetCode(&desc); |
| 121 Object* code = Heap::CreateCode(desc, | 116 Object* code = Heap::CreateCode(desc, |
| 122 NULL, | 117 NULL, |
| 123 Code::ComputeFlags(Code::STUB), | 118 Code::ComputeFlags(Code::STUB), |
| 124 Handle<Code>::null()); | 119 Handle<Code>::null()); |
| 125 if (!code->IsCode()) return; | 120 if (!code->IsCode()) return; |
| 126 LOG(CodeCreateEvent(Logger::BUILTIN_TAG, | 121 LOG(CodeCreateEvent(Logger::BUILTIN_TAG, |
| 127 Code::cast(code), "CpuFeatures::Probe")); | 122 Code::cast(code), "CpuFeatures::Probe")); |
| 128 typedef uint64_t (*F0)(); | 123 typedef uint64_t (*F0)(); |
| 129 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry()); | 124 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry()); |
| 130 supported_ = probe(); | 125 data->supported_ = probe(); |
| 131 found_by_runtime_probing_ = supported_; | 126 data->found_by_runtime_probing_ = data->supported_; |
| 132 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform(); | 127 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform(); |
| 133 supported_ |= os_guarantees; | 128 data->supported_ |= os_guarantees; |
| 134 found_by_runtime_probing_ &= ~os_guarantees; | 129 data->found_by_runtime_probing_ &= ~os_guarantees; |
| 135 } | 130 } |
| 136 | 131 |
| 137 | 132 |
| 138 // ----------------------------------------------------------------------------- | 133 // ----------------------------------------------------------------------------- |
| 139 // Implementation of Displacement | 134 // Implementation of Displacement |
| 140 | 135 |
| 141 void Displacement::init(Label* L, Type type) { | 136 void Displacement::init(Label* L, Type type) { |
| 142 ASSERT(!L->is_bound()); | 137 ASSERT(!L->is_bound()); |
| 143 int next = 0; | 138 int next = 0; |
| 144 if (L->is_linked()) { | 139 if (L->is_linked()) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 | 266 |
| 272 // Emit a single byte. Must always be inlined. | 267 // Emit a single byte. Must always be inlined. |
| 273 #define EMIT(x) \ | 268 #define EMIT(x) \ |
| 274 *pc_++ = (x) | 269 *pc_++ = (x) |
| 275 | 270 |
| 276 | 271 |
| 277 #ifdef GENERATED_CODE_COVERAGE | 272 #ifdef GENERATED_CODE_COVERAGE |
| 278 static void InitCoverageLog(); | 273 static void InitCoverageLog(); |
| 279 #endif | 274 #endif |
| 280 | 275 |
| 281 // spare_buffer_ | |
| 282 byte* Assembler::spare_buffer_ = NULL; | |
| 283 | 276 |
| 284 Assembler::Assembler(void* buffer, int buffer_size) { | 277 Assembler::Assembler(void* buffer, int buffer_size) { |
| 285 if (buffer == NULL) { | 278 if (buffer == NULL) { |
| 286 // do our own buffer management | 279 // do our own buffer management |
| 287 if (buffer_size <= kMinimalBufferSize) { | 280 if (buffer_size <= kMinimalBufferSize) { |
| 288 buffer_size = kMinimalBufferSize; | 281 buffer_size = kMinimalBufferSize; |
| 289 | 282 AssemblerData* const data = v8_context()->assembler_data_; |
| 290 if (spare_buffer_ != NULL) { | 283 if (data->spare_buffer_ != NULL) { |
| 291 buffer = spare_buffer_; | 284 buffer = data->spare_buffer_; |
| 292 spare_buffer_ = NULL; | 285 data->spare_buffer_ = NULL; |
| 293 } | 286 } |
| 294 } | 287 } |
| 295 if (buffer == NULL) { | 288 if (buffer == NULL) { |
| 296 buffer_ = NewArray<byte>(buffer_size); | 289 buffer_ = NewArray<byte>(buffer_size); |
| 297 } else { | 290 } else { |
| 298 buffer_ = static_cast<byte*>(buffer); | 291 buffer_ = static_cast<byte*>(buffer); |
| 299 } | 292 } |
| 300 buffer_size_ = buffer_size; | 293 buffer_size_ = buffer_size; |
| 301 own_buffer_ = true; | 294 own_buffer_ = true; |
| 302 } else { | 295 } else { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 327 written_statement_position_ = current_statement_position_; | 320 written_statement_position_ = current_statement_position_; |
| 328 written_position_ = current_position_; | 321 written_position_ = current_position_; |
| 329 #ifdef GENERATED_CODE_COVERAGE | 322 #ifdef GENERATED_CODE_COVERAGE |
| 330 InitCoverageLog(); | 323 InitCoverageLog(); |
| 331 #endif | 324 #endif |
| 332 } | 325 } |
| 333 | 326 |
| 334 | 327 |
| 335 Assembler::~Assembler() { | 328 Assembler::~Assembler() { |
| 336 if (own_buffer_) { | 329 if (own_buffer_) { |
| 337 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 330 AssemblerData* const data = v8_context()->assembler_data_; |
| 338 spare_buffer_ = buffer_; | 331 if (data->spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 332 data->spare_buffer_ = buffer_; |
| 339 } else { | 333 } else { |
| 340 DeleteArray(buffer_); | 334 DeleteArray(buffer_); |
| 341 } | 335 } |
| 342 } | 336 } |
| 343 } | 337 } |
| 344 | 338 |
| 345 | 339 |
| 346 void Assembler::GetCode(CodeDesc* desc) { | 340 void Assembler::GetCode(CodeDesc* desc) { |
| 347 // finalize code | 341 // finalize code |
| 348 // (at this point overflow() may be true, but the gap ensures that | 342 // (at this point overflow() may be true, but the gap ensures that |
| 349 // we are still not overlapping instructions and relocation info) | 343 // we are still not overlapping instructions and relocation info) |
| 350 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap | 344 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap |
| 351 // setup desc | 345 // setup desc |
| 352 desc->buffer = buffer_; | 346 desc->buffer = buffer_; |
| 353 desc->buffer_size = buffer_size_; | 347 desc->buffer_size = buffer_size_; |
| 354 desc->instr_size = pc_offset(); | 348 desc->instr_size = pc_offset(); |
| 355 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 349 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 356 desc->origin = this; | 350 desc->origin = this; |
| 357 | 351 |
| 358 Counters::reloc_info_size.Increment(desc->reloc_size); | 352 INCREMENT_COUNTER(reloc_info_size, desc->reloc_size); |
| 359 } | 353 } |
| 360 | 354 |
| 361 | 355 |
| 362 void Assembler::Align(int m) { | 356 void Assembler::Align(int m) { |
| 363 ASSERT(IsPowerOf2(m)); | 357 ASSERT(IsPowerOf2(m)); |
| 364 while ((pc_offset() & (m - 1)) != 0) { | 358 while ((pc_offset() & (m - 1)) != 0) { |
| 365 nop(); | 359 nop(); |
| 366 } | 360 } |
| 367 } | 361 } |
| 368 | 362 |
| (...skipping 1776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 memset(desc.buffer, 0xCC, desc.buffer_size); | 2139 memset(desc.buffer, 0xCC, desc.buffer_size); |
| 2146 #endif | 2140 #endif |
| 2147 | 2141 |
| 2148 // copy the data | 2142 // copy the data |
| 2149 int pc_delta = desc.buffer - buffer_; | 2143 int pc_delta = desc.buffer - buffer_; |
| 2150 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); | 2144 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); |
| 2151 memmove(desc.buffer, buffer_, desc.instr_size); | 2145 memmove(desc.buffer, buffer_, desc.instr_size); |
| 2152 memmove(rc_delta + reloc_info_writer.pos(), | 2146 memmove(rc_delta + reloc_info_writer.pos(), |
| 2153 reloc_info_writer.pos(), desc.reloc_size); | 2147 reloc_info_writer.pos(), desc.reloc_size); |
| 2154 | 2148 |
| 2149 AssemblerData* const data = v8_context()->assembler_data_; |
| 2155 // switch buffers | 2150 // switch buffers |
| 2156 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 2151 if (data->spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 2157 spare_buffer_ = buffer_; | 2152 data->spare_buffer_ = buffer_; |
| 2158 } else { | 2153 } else { |
| 2159 DeleteArray(buffer_); | 2154 DeleteArray(buffer_); |
| 2160 } | 2155 } |
| 2161 buffer_ = desc.buffer; | 2156 buffer_ = desc.buffer; |
| 2162 buffer_size_ = desc.buffer_size; | 2157 buffer_size_ = desc.buffer_size; |
| 2163 pc_ += pc_delta; | 2158 pc_ += pc_delta; |
| 2164 if (last_pc_ != NULL) { | 2159 if (last_pc_ != NULL) { |
| 2165 last_pc_ += pc_delta; | 2160 last_pc_ += pc_delta; |
| 2166 } | 2161 } |
| 2167 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 2162 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2257 } | 2252 } |
| 2258 #endif | 2253 #endif |
| 2259 if (!Serializer::enabled() && !FLAG_debug_code) { | 2254 if (!Serializer::enabled() && !FLAG_debug_code) { |
| 2260 return; | 2255 return; |
| 2261 } | 2256 } |
| 2262 } | 2257 } |
| 2263 RelocInfo rinfo(pc_, rmode, data); | 2258 RelocInfo rinfo(pc_, rmode, data); |
| 2264 reloc_info_writer.Write(&rinfo); | 2259 reloc_info_writer.Write(&rinfo); |
| 2265 } | 2260 } |
| 2266 | 2261 |
| 2262 void Assembler::PostConstruct() { |
| 2263 v8_context()->assembler_data_ = new AssemblerData(); |
| 2264 } |
| 2265 |
| 2266 void Assembler::PreDestroy() { |
| 2267 delete v8_context()->assembler_data_; |
| 2268 } |
| 2267 | 2269 |
| 2268 #ifdef GENERATED_CODE_COVERAGE | 2270 #ifdef GENERATED_CODE_COVERAGE |
| 2269 static FILE* coverage_log = NULL; | 2271 static FILE* coverage_log = NULL; |
| 2270 | 2272 |
| 2271 | 2273 |
| 2272 static void InitCoverageLog() { | 2274 static void InitCoverageLog() { |
| 2273 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | 2275 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
| 2274 if (file_name != NULL) { | 2276 if (file_name != NULL) { |
| 2275 coverage_log = fopen(file_name, "aw+"); | 2277 coverage_log = fopen(file_name, "aw+"); |
| 2276 } | 2278 } |
| 2277 } | 2279 } |
| 2278 | 2280 |
| 2279 | 2281 |
| 2280 void LogGeneratedCodeCoverage(const char* file_line) { | 2282 void LogGeneratedCodeCoverage(const char* file_line) { |
| 2281 const char* return_address = (&file_line)[-1]; | 2283 const char* return_address = (&file_line)[-1]; |
| 2282 char* push_insn = const_cast<char*>(return_address - 12); | 2284 char* push_insn = const_cast<char*>(return_address - 12); |
| 2283 push_insn[0] = 0xeb; // Relative branch insn. | 2285 push_insn[0] = 0xeb; // Relative branch insn. |
| 2284 push_insn[1] = 13; // Skip over coverage insns. | 2286 push_insn[1] = 13; // Skip over coverage insns. |
| 2285 if (coverage_log != NULL) { | 2287 if (coverage_log != NULL) { |
| 2286 fprintf(coverage_log, "%s\n", file_line); | 2288 fprintf(coverage_log, "%s\n", file_line); |
| 2287 fflush(coverage_log); | 2289 fflush(coverage_log); |
| 2288 } | 2290 } |
| 2289 } | 2291 } |
| 2290 | 2292 |
| 2291 #endif | 2293 #endif |
| 2292 | 2294 |
| 2293 } } // namespace v8::internal | 2295 } } // namespace v8::internal |
| OLD | NEW |