Commit 6ba6d0b4 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Cache optimized code for OSR.

BUG=v8:2637
LOG=N
R=titzer@chromium.org, verwaest@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18410 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2a4be706
...@@ -1194,9 +1194,14 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( ...@@ -1194,9 +1194,14 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
Label install_optimized; Label install_optimized;
HValue* first_context_slot = Add<HLoadNamedField>(optimized_map, HValue* first_context_slot = Add<HLoadNamedField>(optimized_map,
HObjectAccess::ForFirstContextSlot()); HObjectAccess::ForFirstContextSlot());
HValue* first_osr_ast_slot = Add<HLoadNamedField>(optimized_map,
HObjectAccess::ForFirstOsrAstIdSlot());
HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt());
IfBuilder already_in(this); IfBuilder already_in(this);
already_in.If<HCompareObjectEqAndBranch>(native_context, already_in.If<HCompareObjectEqAndBranch>(native_context,
first_context_slot); first_context_slot);
already_in.AndIf<HCompareObjectEqAndBranch>(first_osr_ast_slot,
osr_ast_id_none);
already_in.Then(); already_in.Then();
{ {
HValue* code_object = Add<HLoadNamedField>(optimized_map, HValue* code_object = Add<HLoadNamedField>(optimized_map,
...@@ -1213,7 +1218,7 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( ...@@ -1213,7 +1218,7 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
shared_function_entry_length); shared_function_entry_length);
HValue* array_length = Add<HLoadNamedField>(optimized_map, HValue* array_length = Add<HLoadNamedField>(optimized_map,
HObjectAccess::ForFixedArrayLength()); HObjectAccess::ForFixedArrayLength());
HValue* key = loop_builder.BeginBody(array_length, HValue* slot_iterator = loop_builder.BeginBody(array_length,
graph()->GetConstant0(), graph()->GetConstant0(),
Token::GT); Token::GT);
{ {
...@@ -1222,8 +1227,8 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( ...@@ -1222,8 +1227,8 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
HValue* second_entry_index = HValue* second_entry_index =
Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex); Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex);
IfBuilder restore_check(this); IfBuilder restore_check(this);
restore_check.If<HCompareNumericAndBranch>(key, second_entry_index, restore_check.If<HCompareNumericAndBranch>(
Token::EQ); slot_iterator, second_entry_index, Token::EQ);
restore_check.Then(); restore_check.Then();
{ {
// Store the unoptimized code // Store the unoptimized code
...@@ -1232,20 +1237,29 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( ...@@ -1232,20 +1237,29 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
} }
restore_check.Else(); restore_check.Else();
{ {
HValue* keyed_minus = AddUncasted<HSub>( STATIC_ASSERT(SharedFunctionInfo::kContextOffset == 0);
key, shared_function_entry_length); STATIC_ASSERT(SharedFunctionInfo::kEntryLength -
HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map, SharedFunctionInfo::kOsrAstIdOffset == 1);
keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS); HValue* native_context_slot = AddUncasted<HSub>(
slot_iterator, shared_function_entry_length);
HValue* osr_ast_id_slot = AddUncasted<HSub>(
slot_iterator, graph()->GetConstant1());
HInstruction* native_context_entry = Add<HLoadKeyed>(optimized_map,
native_context_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
HInstruction* osr_ast_id_entry = Add<HLoadKeyed>(optimized_map,
osr_ast_id_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
IfBuilder done_check(this); IfBuilder done_check(this);
done_check.If<HCompareObjectEqAndBranch>(native_context, done_check.If<HCompareObjectEqAndBranch>(native_context,
keyed_lookup); native_context_entry);
done_check.AndIf<HCompareObjectEqAndBranch>(osr_ast_id_entry,
osr_ast_id_none);
done_check.Then(); done_check.Then();
{ {
// Hit: fetch the optimized code. // Hit: fetch the optimized code.
HValue* keyed_plus = AddUncasted<HAdd>( HValue* code_slot = AddUncasted<HAdd>(
keyed_minus, graph()->GetConstant1()); native_context_slot, graph()->GetConstant1());
HValue* code_object = Add<HLoadKeyed>(optimized_map, HValue* code_object = Add<HLoadKeyed>(optimized_map,
keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS); code_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
BuildInstallOptimizedCode(js_function, native_context, code_object); BuildInstallOptimizedCode(js_function, native_context, code_object);
// Fall out of the loop // Fall out of the loop
......
...@@ -1028,16 +1028,20 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, ...@@ -1028,16 +1028,20 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
} }
static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function) { static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function,
BailoutId osr_ast_id) {
if (FLAG_cache_optimized_code) { if (FLAG_cache_optimized_code) {
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
int index = shared->SearchOptimizedCodeMap( int index = shared->SearchOptimizedCodeMap(
function->context()->native_context()); function->context()->native_context(), osr_ast_id);
if (index > 0) { if (index > 0) {
if (FLAG_trace_opt) { if (FLAG_trace_opt) {
PrintF("[found optimized code for "); PrintF("[found optimized code for ");
function->ShortPrint(); function->ShortPrint();
if (!osr_ast_id.IsNone()) {
PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
}
PrintF("]\n"); PrintF("]\n");
} }
FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index); FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index);
...@@ -1053,14 +1057,14 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { ...@@ -1053,14 +1057,14 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Handle<Code> code = info->code(); Handle<Code> code = info->code();
if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
// Cache non-OSR optimized code. // Cache optimized code.
if (FLAG_cache_optimized_code && !info->is_osr()) { if (FLAG_cache_optimized_code) {
Handle<JSFunction> function = info->closure(); Handle<JSFunction> function = info->closure();
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
Handle<FixedArray> literals(function->literals()); Handle<FixedArray> literals(function->literals());
Handle<Context> native_context(function->context()->native_context()); Handle<Context> native_context(function->context()->native_context());
SharedFunctionInfo::AddToOptimizedCodeMap( SharedFunctionInfo::AddToOptimizedCodeMap(
shared, native_context, code, literals); shared, native_context, code, literals, info->osr_ast_id());
} }
} }
...@@ -1137,10 +1141,8 @@ Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, ...@@ -1137,10 +1141,8 @@ Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
Handle<Code> current_code, Handle<Code> current_code,
ConcurrencyMode mode, ConcurrencyMode mode,
BailoutId osr_ast_id) { BailoutId osr_ast_id) {
if (osr_ast_id.IsNone()) { // No cache for OSR. Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function, osr_ast_id);
Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function);
if (!cached_code.is_null()) return cached_code; if (!cached_code.is_null()) return cached_code;
}
SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function)); SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function));
Isolate* isolate = info->isolate(); Isolate* isolate = info->isolate();
...@@ -1210,7 +1212,7 @@ Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) { ...@@ -1210,7 +1212,7 @@ Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) {
Compiler::RecordFunctionCompilation( Compiler::RecordFunctionCompilation(
Logger::LAZY_COMPILE_TAG, info.get(), shared); Logger::LAZY_COMPILE_TAG, info.get(), shared);
if (info->shared_info()->SearchOptimizedCodeMap( if (info->shared_info()->SearchOptimizedCodeMap(
info->context()->native_context()) == -1) { info->context()->native_context(), info->osr_ast_id()) == -1) {
InsertCodeIntoOptimizedCodeMap(info.get()); InsertCodeIntoOptimizedCodeMap(info.get());
} }
......
...@@ -924,7 +924,8 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo( ...@@ -924,7 +924,8 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
result->set_context(*context); result->set_context(*context);
int index = function_info->SearchOptimizedCodeMap(context->native_context()); int index = function_info->SearchOptimizedCodeMap(context->native_context(),
BailoutId::None());
if (!function_info->bound() && index < 0) { if (!function_info->bound() && index < 0) {
int number_of_literals = function_info->num_literals(); int number_of_literals = function_info->num_literals();
Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure); Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
......
...@@ -6028,6 +6028,10 @@ class HObjectAccess V8_FINAL { ...@@ -6028,6 +6028,10 @@ class HObjectAccess V8_FINAL {
return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot); return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot);
} }
static HObjectAccess ForFirstOsrAstIdSlot() {
return HObjectAccess(kInobject, SharedFunctionInfo::kFirstOsrAstIdSlot);
}
static HObjectAccess ForOptimizedCodeMap() { static HObjectAccess ForOptimizedCodeMap() {
return HObjectAccess(kInobject, return HObjectAccess(kInobject,
SharedFunctionInfo::kOptimizedCodeMapOffset); SharedFunctionInfo::kOptimizedCodeMapOffset);
......
...@@ -1065,55 +1065,40 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() { ...@@ -1065,55 +1065,40 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() {
void CodeFlusher::ProcessOptimizedCodeMaps() { void CodeFlusher::ProcessOptimizedCodeMaps() {
static const int kEntriesStart = SharedFunctionInfo::kEntriesStart; STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4);
static const int kEntryLength = SharedFunctionInfo::kEntryLength;
static const int kContextOffset = 0;
static const int kCodeOffset = 1;
static const int kLiteralsOffset = 2;
STATIC_ASSERT(kEntryLength == 3);
SharedFunctionInfo* holder = optimized_code_map_holder_head_; SharedFunctionInfo* holder = optimized_code_map_holder_head_;
SharedFunctionInfo* next_holder; SharedFunctionInfo* next_holder;
while (holder != NULL) { while (holder != NULL) {
next_holder = GetNextCodeMap(holder); next_holder = GetNextCodeMap(holder);
ClearNextCodeMap(holder); ClearNextCodeMap(holder);
FixedArray* code_map = FixedArray::cast(holder->optimized_code_map()); FixedArray* code_map = FixedArray::cast(holder->optimized_code_map());
int new_length = kEntriesStart; int new_length = SharedFunctionInfo::kEntriesStart;
int old_length = code_map->length(); int old_length = code_map->length();
for (int i = kEntriesStart; i < old_length; i += kEntryLength) { for (int i = SharedFunctionInfo::kEntriesStart;
Code* code = Code::cast(code_map->get(i + kCodeOffset)); i < old_length;
MarkBit code_mark = Marking::MarkBitFrom(code); i += SharedFunctionInfo::kEntryLength) {
if (!code_mark.Get()) { Code* code =
continue; Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset));
} if (!Marking::MarkBitFrom(code).Get()) continue;
// Update and record the context slot in the optimized code map. // Move every slot in the entry.
Object** context_slot = HeapObject::RawField(code_map, for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) {
FixedArray::OffsetOfElementAt(new_length)); int dst_index = new_length++;
code_map->set(new_length++, code_map->get(i + kContextOffset)); Object** slot = code_map->RawFieldOfElementAt(dst_index);
ASSERT(Marking::IsBlack( Object* object = code_map->get(i + j);
Marking::MarkBitFrom(HeapObject::cast(*context_slot)))); code_map->set(dst_index, object);
isolate_->heap()->mark_compact_collector()-> if (j == SharedFunctionInfo::kOsrAstIdOffset) {
RecordSlot(context_slot, context_slot, *context_slot); ASSERT(object->IsSmi());
} else {
// Update and record the code slot in the optimized code map.
Object** code_slot = HeapObject::RawField(code_map,
FixedArray::OffsetOfElementAt(new_length));
code_map->set(new_length++, code_map->get(i + kCodeOffset));
ASSERT(Marking::IsBlack(
Marking::MarkBitFrom(HeapObject::cast(*code_slot))));
isolate_->heap()->mark_compact_collector()->
RecordSlot(code_slot, code_slot, *code_slot);
// Update and record the literals slot in the optimized code map.
Object** literals_slot = HeapObject::RawField(code_map,
FixedArray::OffsetOfElementAt(new_length));
code_map->set(new_length++, code_map->get(i + kLiteralsOffset));
ASSERT(Marking::IsBlack( ASSERT(Marking::IsBlack(
Marking::MarkBitFrom(HeapObject::cast(*literals_slot)))); Marking::MarkBitFrom(HeapObject::cast(*slot))));
isolate_->heap()->mark_compact_collector()-> isolate_->heap()->mark_compact_collector()->
RecordSlot(literals_slot, literals_slot, *literals_slot); RecordSlot(slot, slot, *slot);
}
}
} }
// Trim the optimized code map if entries have been removed. // Trim the optimized code map if entries have been removed.
...@@ -2608,9 +2593,7 @@ void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { ...@@ -2608,9 +2593,7 @@ void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
cached_map, cached_map,
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
} }
Object** slot = Object** slot = prototype_transitions->RawFieldOfElementAt(proto_index);
HeapObject::RawField(prototype_transitions,
FixedArray::OffsetOfElementAt(proto_index));
RecordSlot(slot, slot, prototype); RecordSlot(slot, slot, prototype);
new_number_of_transitions++; new_number_of_transitions++;
} }
...@@ -2715,12 +2698,10 @@ void MarkCompactCollector::ProcessWeakCollections() { ...@@ -2715,12 +2698,10 @@ void MarkCompactCollector::ProcessWeakCollections() {
for (int i = 0; i < table->Capacity(); i++) { for (int i = 0; i < table->Capacity(); i++) {
if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) {
Object** key_slot = Object** key_slot =
HeapObject::RawField(table, FixedArray::OffsetOfElementAt( table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i));
ObjectHashTable::EntryToIndex(i)));
RecordSlot(anchor, key_slot, *key_slot); RecordSlot(anchor, key_slot, *key_slot);
Object** value_slot = Object** value_slot =
HeapObject::RawField(table, FixedArray::OffsetOfElementAt( table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i));
ObjectHashTable::EntryToValueIndex(i)));
MarkCompactMarkingVisitor::MarkObjectByPointer( MarkCompactMarkingVisitor::MarkObjectByPointer(
this, anchor, value_slot); this, anchor, value_slot);
} }
......
...@@ -2364,9 +2364,7 @@ void Map::LookupTransition(JSObject* holder, ...@@ -2364,9 +2364,7 @@ void Map::LookupTransition(JSObject* holder,
Object** DescriptorArray::GetKeySlot(int descriptor_number) { Object** DescriptorArray::GetKeySlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors()); ASSERT(descriptor_number < number_of_descriptors());
return HeapObject::RawField( return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
reinterpret_cast<HeapObject*>(this),
OffsetOfElementAt(ToKeyIndex(descriptor_number)));
} }
...@@ -2421,9 +2419,7 @@ void DescriptorArray::InitializeRepresentations(Representation representation) { ...@@ -2421,9 +2419,7 @@ void DescriptorArray::InitializeRepresentations(Representation representation) {
Object** DescriptorArray::GetValueSlot(int descriptor_number) { Object** DescriptorArray::GetValueSlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors()); ASSERT(descriptor_number < number_of_descriptors());
return HeapObject::RawField( return RawFieldOfElementAt(ToValueIndex(descriptor_number));
reinterpret_cast<HeapObject*>(this),
OffsetOfElementAt(ToValueIndex(descriptor_number)));
} }
...@@ -3224,7 +3220,7 @@ void JSFunctionResultCache::MakeZeroSize() { ...@@ -3224,7 +3220,7 @@ void JSFunctionResultCache::MakeZeroSize() {
void JSFunctionResultCache::Clear() { void JSFunctionResultCache::Clear() {
int cache_size = size(); int cache_size = size();
Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex)); Object** entries_start = RawFieldOfElementAt(kEntriesIndex);
MemsetPointer(entries_start, MemsetPointer(entries_start,
GetHeap()->the_hole_value(), GetHeap()->the_hole_value(),
cache_size - kEntriesIndex); cache_size - kEntriesIndex);
...@@ -3830,8 +3826,7 @@ Object* DependentCode::object_at(int i) { ...@@ -3830,8 +3826,7 @@ Object* DependentCode::object_at(int i) {
Object** DependentCode::slot_at(int i) { Object** DependentCode::slot_at(int i) {
return HeapObject::RawField( return RawFieldOfElementAt(kCodesStartIndex + i);
this, FixedArray::OffsetOfElementAt(kCodesStartIndex + i));
} }
......
...@@ -331,8 +331,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitNativeContext( ...@@ -331,8 +331,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitNativeContext(
for (int idx = Context::FIRST_WEAK_SLOT; for (int idx = Context::FIRST_WEAK_SLOT;
idx < Context::NATIVE_CONTEXT_SLOTS; idx < Context::NATIVE_CONTEXT_SLOTS;
++idx) { ++idx) {
Object** slot = Object** slot = Context::cast(object)->RawFieldOfElementAt(idx);
HeapObject::RawField(object, FixedArray::OffsetOfElementAt(idx));
collector->RecordSlot(slot, slot, *slot); collector->RecordSlot(slot, slot, *slot);
} }
} }
......
...@@ -9526,42 +9526,48 @@ void SharedFunctionInfo::AddToOptimizedCodeMap( ...@@ -9526,42 +9526,48 @@ void SharedFunctionInfo::AddToOptimizedCodeMap(
Handle<SharedFunctionInfo> shared, Handle<SharedFunctionInfo> shared,
Handle<Context> native_context, Handle<Context> native_context,
Handle<Code> code, Handle<Code> code,
Handle<FixedArray> literals) { Handle<FixedArray> literals,
BailoutId osr_ast_id) {
CALL_HEAP_FUNCTION_VOID( CALL_HEAP_FUNCTION_VOID(
shared->GetIsolate(), shared->GetIsolate(),
shared->AddToOptimizedCodeMap(*native_context, *code, *literals)); shared->AddToOptimizedCodeMap(
*native_context, *code, *literals, osr_ast_id));
} }
MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context, MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
Code* code, Code* code,
FixedArray* literals) { FixedArray* literals,
BailoutId osr_ast_id) {
ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
ASSERT(native_context->IsNativeContext()); ASSERT(native_context->IsNativeContext());
STATIC_ASSERT(kEntryLength == 3); STATIC_ASSERT(kEntryLength == 4);
Heap* heap = GetHeap(); Heap* heap = GetHeap();
FixedArray* new_code_map; FixedArray* new_code_map;
Object* value = optimized_code_map(); Object* value = optimized_code_map();
Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
if (value->IsSmi()) { if (value->IsSmi()) {
// No optimized code map. // No optimized code map.
ASSERT_EQ(0, Smi::cast(value)->value()); ASSERT_EQ(0, Smi::cast(value)->value());
// Create 3 entries per context {context, code, literals}. // Create 3 entries per context {context, code, literals}.
MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength); MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength);
if (!maybe->To(&new_code_map)) return maybe; if (!maybe->To(&new_code_map)) return maybe;
new_code_map->set(kEntriesStart + 0, native_context); new_code_map->set(kEntriesStart + kContextOffset, native_context);
new_code_map->set(kEntriesStart + 1, code); new_code_map->set(kEntriesStart + kCachedCodeOffset, code);
new_code_map->set(kEntriesStart + 2, literals); new_code_map->set(kEntriesStart + kLiteralsOffset, literals);
new_code_map->set(kEntriesStart + kOsrAstIdOffset, osr_ast_id_smi);
} else { } else {
// Copy old map and append one new entry. // Copy old map and append one new entry.
FixedArray* old_code_map = FixedArray::cast(value); FixedArray* old_code_map = FixedArray::cast(value);
ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context)); ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context, osr_ast_id));
int old_length = old_code_map->length(); int old_length = old_code_map->length();
int new_length = old_length + kEntryLength; int new_length = old_length + kEntryLength;
MaybeObject* maybe = old_code_map->CopySize(new_length); MaybeObject* maybe = old_code_map->CopySize(new_length);
if (!maybe->To(&new_code_map)) return maybe; if (!maybe->To(&new_code_map)) return maybe;
new_code_map->set(old_length + 0, native_context); new_code_map->set(old_length + kContextOffset, native_context);
new_code_map->set(old_length + 1, code); new_code_map->set(old_length + kCachedCodeOffset, code);
new_code_map->set(old_length + 2, literals); new_code_map->set(old_length + kLiteralsOffset, literals);
new_code_map->set(old_length + kOsrAstIdOffset, osr_ast_id_smi);
// Zap the old map for the sake of the heap verifier. // Zap the old map for the sake of the heap verifier.
if (Heap::ShouldZapGarbage()) { if (Heap::ShouldZapGarbage()) {
Object** data = old_code_map->data_start(); Object** data = old_code_map->data_start();
...@@ -9570,11 +9576,12 @@ MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context, ...@@ -9570,11 +9576,12 @@ MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
} }
#ifdef DEBUG #ifdef DEBUG
for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
ASSERT(new_code_map->get(i)->IsNativeContext()); ASSERT(new_code_map->get(i + kContextOffset)->IsNativeContext());
ASSERT(new_code_map->get(i + 1)->IsCode()); ASSERT(new_code_map->get(i + kCachedCodeOffset)->IsCode());
ASSERT(Code::cast(new_code_map->get(i + 1))->kind() == ASSERT(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
Code::OPTIMIZED_FUNCTION); Code::OPTIMIZED_FUNCTION);
ASSERT(new_code_map->get(i + 2)->IsFixedArray()); ASSERT(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
ASSERT(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
} }
#endif #endif
set_optimized_code_map(new_code_map); set_optimized_code_map(new_code_map);
...@@ -9594,7 +9601,6 @@ FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) { ...@@ -9594,7 +9601,6 @@ FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
} }
Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) { Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
ASSERT(index > kEntriesStart); ASSERT(index > kEntriesStart);
FixedArray* code_map = FixedArray::cast(optimized_code_map()); FixedArray* code_map = FixedArray::cast(optimized_code_map());
...@@ -9639,9 +9645,14 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, ...@@ -9639,9 +9645,14 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
} }
} }
while (i < (code_map->length() - kEntryLength)) { while (i < (code_map->length() - kEntryLength)) {
code_map->set(i, code_map->get(i + kEntryLength)); code_map->set(i + kContextOffset,
code_map->set(i + 1, code_map->get(i + 1 + kEntryLength)); code_map->get(i + kContextOffset + kEntryLength));
code_map->set(i + 2, code_map->get(i + 2 + kEntryLength)); code_map->set(i + kCachedCodeOffset,
code_map->get(i + kCachedCodeOffset + kEntryLength));
code_map->set(i + kLiteralsOffset,
code_map->get(i + kLiteralsOffset + kEntryLength));
code_map->set(i + kOsrAstIdOffset,
code_map->get(i + kOsrAstIdOffset + kEntryLength));
i += kEntryLength; i += kEntryLength;
} }
if (removed_entry) { if (removed_entry) {
...@@ -10203,16 +10214,19 @@ void SharedFunctionInfo::CompleteInobjectSlackTracking() { ...@@ -10203,16 +10214,19 @@ void SharedFunctionInfo::CompleteInobjectSlackTracking() {
} }
int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context) { int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
BailoutId osr_ast_id) {
ASSERT(native_context->IsNativeContext()); ASSERT(native_context->IsNativeContext());
if (!FLAG_cache_optimized_code) return -1; if (!FLAG_cache_optimized_code) return -1;
Object* value = optimized_code_map(); Object* value = optimized_code_map();
if (!value->IsSmi()) { if (!value->IsSmi()) {
FixedArray* optimized_code_map = FixedArray::cast(value); FixedArray* optimized_code_map = FixedArray::cast(value);
int length = optimized_code_map->length(); int length = optimized_code_map->length();
Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
for (int i = kEntriesStart; i < length; i += kEntryLength) { for (int i = kEntriesStart; i < length; i += kEntryLength) {
if (optimized_code_map->get(i) == native_context) { if (optimized_code_map->get(i + kContextOffset) == native_context &&
return i + 1; optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
return i + kCachedCodeOffset;
} }
} }
if (FLAG_trace_opt) { if (FLAG_trace_opt) {
......
...@@ -2957,6 +2957,11 @@ class FixedArray: public FixedArrayBase { ...@@ -2957,6 +2957,11 @@ class FixedArray: public FixedArrayBase {
// Code Generation support. // Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); } static int OffsetOfElementAt(int index) { return SizeFor(index); }
// Garbage collection support.
Object** RawFieldOfElementAt(int index) {
return HeapObject::RawField(this, OffsetOfElementAt(index));
}
// Casting. // Casting.
static inline FixedArray* cast(Object* obj); static inline FixedArray* cast(Object* obj);
...@@ -6536,10 +6541,10 @@ class SharedFunctionInfo: public HeapObject { ...@@ -6536,10 +6541,10 @@ class SharedFunctionInfo: public HeapObject {
// and a shared literals array or Smi(0) if none. // and a shared literals array or Smi(0) if none.
DECL_ACCESSORS(optimized_code_map, Object) DECL_ACCESSORS(optimized_code_map, Object)
// Returns index i of the entry with the specified context. At position // Returns index i of the entry with the specified context and OSR entry.
// i - 1 is the context, position i the code, and i + 1 the literals array. // At position i - 1 is the context, position i the code, and i + 1 the
// Returns -1 when no matching entry is found. // literals array. Returns -1 when no matching entry is found.
int SearchOptimizedCodeMap(Context* native_context); int SearchOptimizedCodeMap(Context* native_context, BailoutId osr_ast_id);
// Installs optimized code from the code map on the given closure. The // Installs optimized code from the code map on the given closure. The
// index has to be consistent with a search result as defined above. // index has to be consistent with a search result as defined above.
...@@ -6559,18 +6564,28 @@ class SharedFunctionInfo: public HeapObject { ...@@ -6559,18 +6564,28 @@ class SharedFunctionInfo: public HeapObject {
// Add a new entry to the optimized code map. // Add a new entry to the optimized code map.
MUST_USE_RESULT MaybeObject* AddToOptimizedCodeMap(Context* native_context, MUST_USE_RESULT MaybeObject* AddToOptimizedCodeMap(Context* native_context,
Code* code, Code* code,
FixedArray* literals); FixedArray* literals,
BailoutId osr_ast_id);
static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared, static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared,
Handle<Context> native_context, Handle<Context> native_context,
Handle<Code> code, Handle<Code> code,
Handle<FixedArray> literals); Handle<FixedArray> literals,
BailoutId osr_ast_id);
// Layout description of the optimized code map. // Layout description of the optimized code map.
static const int kNextMapIndex = 0; static const int kNextMapIndex = 0;
static const int kEntriesStart = 1; static const int kEntriesStart = 1;
static const int kEntryLength = 3; static const int kContextOffset = 0;
static const int kFirstContextSlot = FixedArray::kHeaderSize + kPointerSize; static const int kCachedCodeOffset = 1;
static const int kFirstCodeSlot = FixedArray::kHeaderSize + 2 * kPointerSize; static const int kLiteralsOffset = 2;
static const int kOsrAstIdOffset = 3;
static const int kEntryLength = 4;
static const int kFirstContextSlot = FixedArray::kHeaderSize +
(kEntriesStart + kContextOffset) * kPointerSize;
static const int kFirstCodeSlot = FixedArray::kHeaderSize +
(kEntriesStart + kCachedCodeOffset) * kPointerSize;
static const int kFirstOsrAstIdSlot = FixedArray::kHeaderSize +
(kEntriesStart + kOsrAstIdOffset) * kPointerSize;
static const int kSecondEntryIndex = kEntryLength + kEntriesStart; static const int kSecondEntryIndex = kEntryLength + kEntriesStart;
static const int kInitialLength = kEntriesStart + kEntryLength; static const int kInitialLength = kEntriesStart + kEntryLength;
......
...@@ -115,9 +115,7 @@ Object** TransitionArray::GetPrototypeTransitionsSlot() { ...@@ -115,9 +115,7 @@ Object** TransitionArray::GetPrototypeTransitionsSlot() {
Object** TransitionArray::GetKeySlot(int transition_number) { Object** TransitionArray::GetKeySlot(int transition_number) {
ASSERT(!IsSimpleTransition()); ASSERT(!IsSimpleTransition());
ASSERT(transition_number < number_of_transitions()); ASSERT(transition_number < number_of_transitions());
return HeapObject::RawField( return RawFieldOfElementAt(ToKeyIndex(transition_number));
reinterpret_cast<HeapObject*>(this),
OffsetOfElementAt(ToKeyIndex(transition_number)));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment