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 |