Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 7db54aa811e7ce2ed260f4ec729675231fd830bd..1262b521a7d5dc8b9515d489db077e0315f799ca 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -10137,47 +10137,60 @@ void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap( |
void SharedFunctionInfo::AddToOptimizedCodeMap( |
- Handle<SharedFunctionInfo> shared, |
- Handle<Context> native_context, |
- Handle<Code> code, |
- Handle<FixedArray> literals, |
+ Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
+ Handle<HeapObject> code, Handle<FixedArray> literals, |
BailoutId osr_ast_id) { |
Isolate* isolate = shared->GetIsolate(); |
- DCHECK(!shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code); |
- DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
+ DCHECK(*code == isolate->heap()->undefined_value() || |
+ !shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code); |
+ DCHECK(*code == isolate->heap()->undefined_value() || |
+ Code::cast(*code)->kind() == Code::OPTIMIZED_FUNCTION); |
DCHECK(native_context->IsNativeContext()); |
STATIC_ASSERT(kEntryLength == 4); |
Handle<FixedArray> new_code_map; |
Handle<Object> value(shared->optimized_code_map(), isolate); |
- int old_length; |
+ int entry; |
if (value->IsSmi()) { |
// No optimized code map. |
DCHECK_EQ(0, Smi::cast(*value)->value()); |
new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
- old_length = kEntriesStart; |
+ entry = kEntriesStart; |
} else { |
- // Copy old optimized code map and append one new entry. |
Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value); |
+ entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id); |
+ if (entry > kSharedCodeIndex) { |
+ // Found an existing context-specific entry, it must not contain any code. |
+ DCHECK_EQ(isolate->heap()->undefined_value(), |
+ old_code_map->get(entry + kCachedCodeOffset)); |
+ // Just set the code and literals to the entry. |
+ old_code_map->set(entry + kCachedCodeOffset, *code); |
+ old_code_map->set(entry + kLiteralsOffset, *literals); |
+ return; |
+ } |
+ |
+ // Copy old optimized code map and append one new entry. |
new_code_map = isolate->factory()->CopyFixedArrayAndGrow( |
old_code_map, kEntryLength, TENURED); |
- old_length = old_code_map->length(); |
+ int old_length = old_code_map->length(); |
// Zap the old map to avoid any stale entries. Note that this is required |
// for correctness because entries are being treated weakly by the GC. |
MemsetPointer(old_code_map->data_start(), isolate->heap()->the_hole_value(), |
old_length); |
+ entry = old_length; |
} |
- new_code_map->set(old_length + kContextOffset, *native_context); |
- new_code_map->set(old_length + kCachedCodeOffset, *code); |
- new_code_map->set(old_length + kLiteralsOffset, *literals); |
- new_code_map->set(old_length + kOsrAstIdOffset, |
- Smi::FromInt(osr_ast_id.ToInt())); |
+ new_code_map->set(entry + kContextOffset, *native_context); |
+ new_code_map->set(entry + kCachedCodeOffset, *code); |
+ new_code_map->set(entry + kLiteralsOffset, *literals); |
+ new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt())); |
#ifdef DEBUG |
for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext()); |
- DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode()); |
- DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() == |
- Code::OPTIMIZED_FUNCTION); |
+ Object* code = new_code_map->get(i + kCachedCodeOffset); |
+ if (code != isolate->heap()->undefined_value()) { |
+ DCHECK(code->IsCode()); |
+ DCHECK(Code::cast(code)->kind() == Code::OPTIMIZED_FUNCTION); |
+ } |
DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray()); |
DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); |
} |
@@ -10206,37 +10219,43 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, |
DisallowHeapAllocation no_gc; |
if (optimized_code_map()->IsSmi()) return; |
+ Heap* heap = GetHeap(); |
FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
int dst = kEntriesStart; |
int length = code_map->length(); |
for (int src = kEntriesStart; src < length; src += kEntryLength) { |
DCHECK(code_map->get(src)->IsNativeContext()); |
- if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) { |
- // Evict the src entry by not copying it to the dst entry. |
+ if (code_map->get(src + kCachedCodeOffset) == optimized_code) { |
+ BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); |
if (FLAG_trace_opt) { |
PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
ShortPrint(); |
- BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); |
if (osr.IsNone()) { |
PrintF("]\n"); |
} else { |
PrintF(" (osr ast id %d)]\n", osr.ToInt()); |
} |
} |
- } else { |
- // Keep the src entry by copying it to the dst entry. |
- if (dst != src) { |
- code_map->set(dst + kContextOffset, |
- code_map->get(src + kContextOffset)); |
- code_map->set(dst + kCachedCodeOffset, |
- code_map->get(src + kCachedCodeOffset)); |
- code_map->set(dst + kLiteralsOffset, |
- code_map->get(src + kLiteralsOffset)); |
- code_map->set(dst + kOsrAstIdOffset, |
- code_map->get(src + kOsrAstIdOffset)); |
+ if (!osr.IsNone()) { |
+ // Evict the src entry by not copying it to the dst entry. |
+ continue; |
} |
- dst += kEntryLength; |
+ // In case of non-OSR entry just clear the code in order to proceed |
+ // sharing literals. |
+ code_map->set_undefined(src + kCachedCodeOffset); |
+ } |
+ |
+ // Keep the src entry by copying it to the dst entry. |
+ if (dst != src) { |
+ code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset)); |
+ code_map->set(dst + kCachedCodeOffset, |
+ code_map->get(src + kCachedCodeOffset)); |
+ code_map->set(dst + kLiteralsOffset, |
+ code_map->get(src + kLiteralsOffset)); |
+ code_map->set(dst + kOsrAstIdOffset, |
+ code_map->get(src + kOsrAstIdOffset)); |
} |
+ dst += kEntryLength; |
} |
if (code_map->get(kSharedCodeIndex) == optimized_code) { |
// Evict context-independent code as well. |
@@ -10249,8 +10268,8 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, |
} |
if (dst != length) { |
// Always trim even when array is cleared because of heap verifier. |
- GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map, |
- length - dst); |
+ heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map, |
+ length - dst); |
if (code_map->length() == kEntriesStart && |
code_map->get(kSharedCodeIndex)->IsUndefined()) { |
ClearOptimizedCodeMap(); |
@@ -11265,8 +11284,8 @@ void SharedFunctionInfo::ResetForNewContext(int new_ic_age) { |
} |
-CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
- Context* native_context, BailoutId osr_ast_id) { |
+int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context, |
+ BailoutId osr_ast_id) { |
DisallowHeapAllocation no_gc; |
DCHECK(native_context->IsNativeContext()); |
Object* value = optimized_code_map(); |
@@ -11277,21 +11296,41 @@ CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
for (int i = kEntriesStart; i < length; i += kEntryLength) { |
if (optimized_code_map->get(i + kContextOffset) == native_context && |
optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { |
- return {Code::cast(optimized_code_map->get(i + kCachedCodeOffset)), |
- FixedArray::cast(optimized_code_map->get(i + kLiteralsOffset))}; |
+ return i; |
} |
} |
Object* shared_code = optimized_code_map->get(kSharedCodeIndex); |
if (shared_code->IsCode() && osr_ast_id.IsNone()) { |
- return {Code::cast(shared_code), nullptr}; |
+ return kSharedCodeIndex; |
} |
- if (FLAG_trace_opt) { |
- PrintF("[didn't find optimized code in optimized code map for "); |
- ShortPrint(); |
- PrintF("]\n"); |
+ } |
+ return -1; |
+} |
+ |
+ |
+CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
+ Context* native_context, BailoutId osr_ast_id) { |
+ CodeAndLiterals result = {nullptr, nullptr}; |
+ int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id); |
+ if (entry != kNotFound) { |
+ FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
+ if (entry == kSharedCodeIndex) { |
+ result = {Code::cast(code_map->get(kSharedCodeIndex)), nullptr}; |
+ |
+ } else { |
+ DCHECK_LE(entry + kEntryLength, code_map->length()); |
+ Object* code = code_map->get(entry + kCachedCodeOffset); |
+ result = {code->IsUndefined() ? nullptr : Code::cast(code), |
+ FixedArray::cast(code_map->get(entry + kLiteralsOffset))}; |
} |
} |
- return {nullptr, nullptr}; |
+ if (FLAG_trace_opt && !optimized_code_map()->IsSmi() && |
+ result.code == nullptr) { |
+ PrintF("[didn't find optimized code in optimized code map for "); |
+ ShortPrint(); |
+ PrintF("]\n"); |
+ } |
+ return result; |
} |