Chromium Code Reviews| Index: src/deoptimizer.cc |
| diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
| index e7576562ba09c894f78809c0c4fdf09bf4a34ca0..aeec43665c54484159ead01261d30db1fcc81b9f 100644 |
| --- a/src/deoptimizer.cc |
| +++ b/src/deoptimizer.cc |
| @@ -41,8 +41,11 @@ namespace v8 { |
| namespace internal { |
| DeoptimizerData::DeoptimizerData() { |
| - eager_deoptimization_entry_code_ = NULL; |
| - lazy_deoptimization_entry_code_ = NULL; |
| + eager_deoptimization_entry_code_entries_ = -1; |
| + lazy_deoptimization_entry_code_entries_ = -1; |
| + size_t deopt_table_size = Deoptimizer::GetMaxDeoptTableSize(); |
| + eager_deoptimization_entry_code_ = new VirtualMemory(deopt_table_size); |
| + lazy_deoptimization_entry_code_ = new VirtualMemory(deopt_table_size); |
| current_ = NULL; |
| deoptimizing_code_list_ = NULL; |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| @@ -53,13 +56,11 @@ DeoptimizerData::DeoptimizerData() { |
| DeoptimizerData::~DeoptimizerData() { |
| if (eager_deoptimization_entry_code_ != NULL) { |
|
Jakob Kummerow
2012/11/06 11:40:50
nit: you can simplify this a bit by removing the c
danno
2012/11/06 11:59:03
Done.
|
| - Isolate::Current()->memory_allocator()->Free( |
| - eager_deoptimization_entry_code_); |
| + delete eager_deoptimization_entry_code_; |
| eager_deoptimization_entry_code_ = NULL; |
| } |
| if (lazy_deoptimization_entry_code_ != NULL) { |
| - Isolate::Current()->memory_allocator()->Free( |
| - lazy_deoptimization_entry_code_); |
| + delete lazy_deoptimization_entry_code_; |
| lazy_deoptimization_entry_code_ = NULL; |
| } |
| DeoptimizingCodeListNode* current = deoptimizing_code_list_; |
| @@ -103,6 +104,19 @@ Deoptimizer* Deoptimizer::New(JSFunction* function, |
| } |
| +// No larger than 2K on all platforms |
| +static const int kDeoptTableMaxEpilogueCodeSize = 2 * 1024; |
|
Jakob Kummerow
2012/11/06 11:40:50
nit: 2 * KB
|
| + |
| + |
| +size_t Deoptimizer::GetMaxDeoptTableSize() { |
| + size_t entries_size = |
| + Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; |
| + int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / |
| + OS::CommitPageSize()) + 1; |
| + return OS::CommitPageSize() * page_count; |
| +} |
| + |
| + |
| Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
| ASSERT(isolate == Isolate::Current()); |
| Deoptimizer* result = isolate->deoptimizer_data()->current_; |
| @@ -461,44 +475,44 @@ void Deoptimizer::DeleteFrameDescriptions() { |
| } |
| -Address Deoptimizer::GetDeoptimizationEntry(int id, BailoutType type) { |
| +Address Deoptimizer::GetDeoptimizationEntry(int id, BailoutType type, |
|
Jakob Kummerow
2012/11/06 11:40:50
nit: one line per argument
danno
2012/11/06 11:59:03
Done.
|
| + GetEntryMode mode) { |
| ASSERT(id >= 0); |
| - if (id >= kNumberOfEntries) return NULL; |
| - MemoryChunk* base = NULL; |
| + if (id >= kMaxNumberOfEntries) return NULL; |
| + VirtualMemory* base = NULL; |
| + if (mode == ENSURE_ENTRY_CODE) { |
| + EnsureCodeForDeoptimizationEntry(type, id); |
| + } else { |
| + ASSERT(mode == CALCULATE_ENTRY_ADDRESS); |
| + } |
| DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); |
| if (type == EAGER) { |
| - if (data->eager_deoptimization_entry_code_ == NULL) { |
| - data->eager_deoptimization_entry_code_ = CreateCode(type); |
| - } |
| base = data->eager_deoptimization_entry_code_; |
| } else { |
| - if (data->lazy_deoptimization_entry_code_ == NULL) { |
| - data->lazy_deoptimization_entry_code_ = CreateCode(type); |
| - } |
| base = data->lazy_deoptimization_entry_code_; |
| } |
| return |
| - static_cast<Address>(base->area_start()) + (id * table_entry_size_); |
| + static_cast<Address>(base->address()) + (id * table_entry_size_); |
| } |
| int Deoptimizer::GetDeoptimizationId(Address addr, BailoutType type) { |
| - MemoryChunk* base = NULL; |
| + VirtualMemory* base = NULL; |
| DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); |
| if (type == EAGER) { |
| base = data->eager_deoptimization_entry_code_; |
| } else { |
| base = data->lazy_deoptimization_entry_code_; |
| } |
| + Address base_casted = reinterpret_cast<Address>(base->address()); |
| if (base == NULL || |
| - addr < base->area_start() || |
| - addr >= base->area_start() + |
| - (kNumberOfEntries * table_entry_size_)) { |
| + addr < base->address() || |
| + addr >= base_casted + (kMaxNumberOfEntries * table_entry_size_)) { |
| return kNotDeoptimizationEntry; |
| } |
| ASSERT_EQ(0, |
| - static_cast<int>(addr - base->area_start()) % table_entry_size_); |
| - return static_cast<int>(addr - base->area_start()) / table_entry_size_; |
| + static_cast<int>(addr - base_casted) % table_entry_size_); |
| + return static_cast<int>(addr - base_casted) / table_entry_size_; |
| } |
| @@ -1384,31 +1398,44 @@ void Deoptimizer::AddDoubleValue(intptr_t slot_address, double value) { |
| } |
| -MemoryChunk* Deoptimizer::CreateCode(BailoutType type) { |
| +void Deoptimizer::EnsureCodeForDeoptimizationEntry(BailoutType type, |
| + int max_entry_id) { |
| // We cannot run this if the serializer is enabled because this will |
| // cause us to emit relocation information for the external |
| // references. This is fine because the deoptimizer's code section |
| // isn't meant to be serialized at all. |
| ASSERT(!Serializer::enabled()); |
| + ASSERT(type == EAGER || type == LAZY); |
| + DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); |
| + int entry_count = (type == EAGER) |
| + ? data->eager_deoptimization_entry_code_entries_ |
| + : data->lazy_deoptimization_entry_code_entries_; |
| + if (max_entry_id < entry_count) return; |
| + entry_count = Min(Max(entry_count * 2, Deoptimizer::kMinNumberOfEntries), |
| + Deoptimizer::kMaxNumberOfEntries); |
| + |
| MacroAssembler masm(Isolate::Current(), NULL, 16 * KB); |
| masm.set_emit_debug_code(false); |
| - GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type); |
| + GenerateDeoptimizationEntries(&masm, entry_count, type); |
| CodeDesc desc; |
| masm.GetCode(&desc); |
| ASSERT(desc.reloc_size == 0); |
| - MemoryChunk* chunk = |
| - Isolate::Current()->memory_allocator()->AllocateChunk(desc.instr_size, |
| - EXECUTABLE, |
| - NULL); |
| - ASSERT(chunk->area_size() >= desc.instr_size); |
| - if (chunk == NULL) { |
| - V8::FatalProcessOutOfMemory("Not enough memory for deoptimization table"); |
| + VirtualMemory* memory = type == EAGER |
| + ? data->eager_deoptimization_entry_code_ |
| + : data->lazy_deoptimization_entry_code_; |
| + size_t table_size = Deoptimizer::GetMaxDeoptTableSize(); |
| + ASSERT(static_cast<int>(table_size) >= desc.instr_size); |
| + memory->Commit(memory->address(), table_size, true); |
| + memcpy(memory->address(), desc.buffer, desc.instr_size); |
| + CPU::FlushICache(memory->address(), desc.instr_size); |
| + |
| + if (type == EAGER) { |
| + data->eager_deoptimization_entry_code_entries_ = entry_count; |
| + } else { |
| + data->lazy_deoptimization_entry_code_entries_ = entry_count; |
| } |
| - memcpy(chunk->area_start(), desc.buffer, desc.instr_size); |
| - CPU::FlushICache(chunk->area_start(), desc.instr_size); |
| - return chunk; |
| } |