Decouple allocation and creation of deopt tables

This makes it possible to calculate the future address of a deopt entry before it is possible to generate the deopt table.

Review URL: https://codereview.chromium.org/11275145

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12877 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2012-11-07 08:49:17 +00:00
parent 85ac311a6e
commit 0fc9527abe
3 changed files with 87 additions and 45 deletions

View File

@ -6501,6 +6501,7 @@ void Testing::PrepareStressRun(int run) {
void Testing::DeoptimizeAll() {
i::HandleScope scope;
internal::Deoptimizer::DeoptimizeAll();
}

View File

@ -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
@ -52,16 +55,11 @@ DeoptimizerData::DeoptimizerData() {
DeoptimizerData::~DeoptimizerData() {
if (eager_deoptimization_entry_code_ != NULL) {
Isolate::Current()->memory_allocator()->Free(
eager_deoptimization_entry_code_);
eager_deoptimization_entry_code_ = NULL;
}
if (lazy_deoptimization_entry_code_ != NULL) {
Isolate::Current()->memory_allocator()->Free(
lazy_deoptimization_entry_code_);
lazy_deoptimization_entry_code_ = NULL;
}
delete eager_deoptimization_entry_code_;
eager_deoptimization_entry_code_ = NULL;
delete lazy_deoptimization_entry_code_;
lazy_deoptimization_entry_code_ = NULL;
DeoptimizingCodeListNode* current = deoptimizing_code_list_;
while (current != NULL) {
DeoptimizingCodeListNode* prev = current;
@ -103,6 +101,19 @@ Deoptimizer* Deoptimizer::New(JSFunction* function,
}
// No larger than 2K on all platforms
static const int kDeoptTableMaxEpilogueCodeSize = 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 +472,45 @@ void Deoptimizer::DeleteFrameDescriptions() {
}
Address Deoptimizer::GetDeoptimizationEntry(int id, BailoutType type) {
Address Deoptimizer::GetDeoptimizationEntry(int id,
BailoutType type,
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 +1396,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;
}

View File

@ -100,8 +100,10 @@ class DeoptimizerData {
#endif
private:
MemoryChunk* eager_deoptimization_entry_code_;
MemoryChunk* lazy_deoptimization_entry_code_;
int eager_deoptimization_entry_code_entries_;
int lazy_deoptimization_entry_code_entries_;
VirtualMemory* eager_deoptimization_entry_code_;
VirtualMemory* lazy_deoptimization_entry_code_;
Deoptimizer* current_;
#ifdef ENABLE_DEBUGGER_SUPPORT
@ -226,7 +228,17 @@ class Deoptimizer : public Malloced {
static void ComputeOutputFrames(Deoptimizer* deoptimizer);
static Address GetDeoptimizationEntry(int id, BailoutType type);
enum GetEntryMode {
CALCULATE_ENTRY_ADDRESS,
ENSURE_ENTRY_CODE
};
static Address GetDeoptimizationEntry(
int id,
BailoutType type,
GetEntryMode mode = ENSURE_ENTRY_CODE);
static int GetDeoptimizationId(Address addr, BailoutType type);
static int GetOutputInfo(DeoptimizationOutputData* data,
BailoutId node_id,
@ -283,8 +295,11 @@ class Deoptimizer : public Malloced {
int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
static size_t GetMaxDeoptTableSize();
private:
static const int kNumberOfEntries = 16384;
static const int kMinNumberOfEntries = 64;
static const int kMaxNumberOfEntries = 16384;
Deoptimizer(Isolate* isolate,
JSFunction* function,
@ -327,7 +342,8 @@ class Deoptimizer : public Malloced {
void AddArgumentsObjectValue(intptr_t value);
void AddDoubleValue(intptr_t slot_address, double value);
static MemoryChunk* CreateCode(BailoutType type);
static void EnsureCodeForDeoptimizationEntry(BailoutType type,
int max_entry_id);
static void GenerateDeoptimizationEntries(
MacroAssembler* masm, int count, BailoutType type);