// from https://raw.githubusercontent.com/v8/v8/master/src/objects.cc void SharedFunctionInfo::AddToOptimizedCodeMapInternal( Handle shared, Handle native_context, Handle code, Handle literals, BailoutId osr_ast_id) { Isolate* isolate = shared->GetIsolate(); if (isolate->serializer_enabled()) return; 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 new_code_map; int entry; if (shared->OptimizedCodeMapIsCleared()) { new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); new_code_map->set(kSharedCodeIndex, *isolate->factory()->empty_weak_cell(), SKIP_WRITE_BARRIER); entry = kEntriesStart; } else { Handle old_code_map(shared->optimized_code_map(), isolate); entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id); if (entry > kSharedCodeIndex) { // Found an existing context-specific entry. If the user provided valid // code, it must not contain any code. DCHECK(code->IsUndefined() || WeakCell::cast(old_code_map->get(entry + kCachedCodeOffset)) ->cleared()); // Just set the code and literals to the entry. if (!code->IsUndefined()) { Handle code_cell = isolate->factory()->NewWeakCell(code); old_code_map->set(entry + kCachedCodeOffset, *code_cell); } Handle literals_cell = isolate->factory()->NewWeakCell(literals); old_code_map->set(entry + kLiteralsOffset, *literals_cell); return; } // Can we reuse an entry? DCHECK(entry < kEntriesStart); int length = old_code_map->length(); for (int i = kEntriesStart; i < length; i += kEntryLength) { if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { new_code_map = old_code_map; entry = i; break; } } if (entry < kEntriesStart) { // Copy old optimized code map and append one new entry. new_code_map = isolate->factory()->CopyFixedArrayAndGrow( old_code_map, kEntryLength, TENURED); // TODO(mstarzinger): Temporary workaround. The allocation above might // have flushed the optimized code map and the copy we created is full of // holes. For now we just give up on adding the entry and pretend it got // flushed. if (shared->OptimizedCodeMapIsCleared()) return; entry = old_code_map->length(); } } Handle code_cell = code->IsUndefined() ? isolate->factory()->empty_weak_cell() : isolate->factory()->NewWeakCell(code); Handle literals_cell = isolate->factory()->NewWeakCell(literals); WeakCell* context_cell = native_context->self_weak_cell(); new_code_map->set(entry + kContextOffset, context_cell); new_code_map->set(entry + kCachedCodeOffset, *code_cell); new_code_map->set(entry + kLiteralsOffset, *literals_cell); 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) { WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); DCHECK(cell->cleared() || cell->value()->IsNativeContext()); cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); DCHECK(cell->cleared() || (cell->value()->IsCode() && Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); DCHECK(cell->cleared() || cell->value()->IsFixedArray()); DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); } #endif FixedArray* old_code_map = shared->optimized_code_map(); if (old_code_map != *new_code_map) { shared->set_optimized_code_map(*new_code_map); } }