| 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;
|
| }
|
|
|
|
|
|
|