Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 11969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11980 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 11980 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
| 11981 // No write barrier required, since the builtin is part of the root set. | 11981 // No write barrier required, since the builtin is part of the root set. |
| 11982 if (FLAG_mark_shared_functions_for_tier_up) { | 11982 if (FLAG_mark_shared_functions_for_tier_up) { |
| 11983 // TODO(leszeks): The compilation isn't concurrent if we trigger it using | 11983 // TODO(leszeks): The compilation isn't concurrent if we trigger it using |
| 11984 // this bit. | 11984 // this bit. |
| 11985 shared()->set_marked_for_tier_up(true); | 11985 shared()->set_marked_for_tier_up(true); |
| 11986 } | 11986 } |
| 11987 } | 11987 } |
| 11988 | 11988 |
| 11989 // static | 11989 // static |
| 11990 Handle<TypeFeedbackVector> SharedFunctionInfo::FindOrCreateVector( | |
| 11991 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { | |
| 11992 Isolate* isolate = shared->GetIsolate(); | |
| 11993 CodeAndVector result = | |
| 11994 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); | |
| 11995 if (result.vector != nullptr) { | |
| 11996 DCHECK(shared->feedback_metadata()->is_empty() || | |
| 11997 !result.vector->is_empty()); | |
| 11998 return handle(result.vector, isolate); | |
| 11999 } | |
| 12000 | |
| 12001 Handle<TypeFeedbackVector> vector = | |
| 12002 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
| 12003 Handle<Code> code; | |
| 12004 if (result.code != nullptr) { | |
| 12005 code = Handle<Code>(result.code, isolate); | |
| 12006 } | |
| 12007 AddToOptimizedCodeMap(shared, native_context, code, vector, | |
| 12008 BailoutId::None()); | |
| 12009 return vector; | |
| 12010 } | |
| 12011 | |
| 12012 // static | |
| 12013 void SharedFunctionInfo::AddToOptimizedCodeMap( | 11990 void SharedFunctionInfo::AddToOptimizedCodeMap( |
| 12014 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 11991 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
| 12015 MaybeHandle<Code> code, Handle<TypeFeedbackVector> vector, | 11992 Handle<Code> code, BailoutId osr_ast_id) { |
| 12016 BailoutId osr_ast_id) { | |
| 12017 Isolate* isolate = shared->GetIsolate(); | 11993 Isolate* isolate = shared->GetIsolate(); |
| 12018 if (isolate->serializer_enabled()) return; | 11994 if (isolate->serializer_enabled()) return; |
| 12019 DCHECK(code.is_null() || | 11995 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
| 12020 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | |
| 12021 DCHECK(native_context->IsNativeContext()); | 11996 DCHECK(native_context->IsNativeContext()); |
| 12022 STATIC_ASSERT(kEntryLength == 3); | 11997 STATIC_ASSERT(kEntryLength == 2); |
| 12023 Handle<FixedArray> new_code_map; | 11998 Handle<FixedArray> new_code_map; |
| 12024 int entry; | 11999 int entry; |
| 12025 | 12000 |
| 12026 if (!osr_ast_id.IsNone()) { | 12001 if (!osr_ast_id.IsNone()) { |
| 12027 Context::AddToOptimizedCodeMap(native_context, shared, | 12002 Context::AddToOptimizedCodeMap(native_context, shared, code, osr_ast_id); |
| 12028 code.ToHandleChecked(), vector, osr_ast_id); | |
| 12029 return; | 12003 return; |
| 12030 } | 12004 } |
| 12031 | 12005 |
| 12032 DCHECK(osr_ast_id.IsNone()); | 12006 DCHECK(osr_ast_id.IsNone()); |
| 12033 if (shared->OptimizedCodeMapIsCleared()) { | 12007 if (shared->OptimizedCodeMapIsCleared()) { |
| 12034 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12008 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
| 12035 entry = kEntriesStart; | 12009 entry = kEntriesStart; |
| 12036 } else { | 12010 } else { |
| 12037 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12011 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
| 12038 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 12012 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
| 12039 if (entry >= kEntriesStart) { | 12013 if (entry >= kEntriesStart) { |
| 12040 // Just set the code and vector of the entry. | 12014 // Just set the code of the entry. |
| 12041 if (!code.is_null()) { | 12015 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); |
| 12042 Handle<WeakCell> code_cell = | 12016 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12043 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | |
| 12044 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | |
| 12045 } | |
| 12046 Handle<WeakCell> vector_cell = isolate->factory()->NewWeakCell(vector); | |
| 12047 old_code_map->set(entry + kFeedbackVectorOffset, *vector_cell); | |
| 12048 return; | 12017 return; |
| 12049 } | 12018 } |
| 12050 | 12019 |
| 12051 // Can we reuse an entry? | 12020 // Can we reuse an entry? |
| 12052 DCHECK(entry < kEntriesStart); | 12021 DCHECK(entry < kEntriesStart); |
| 12053 int length = old_code_map->length(); | 12022 int length = old_code_map->length(); |
| 12054 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 12023 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
| 12055 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { | 12024 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { |
| 12056 new_code_map = old_code_map; | 12025 new_code_map = old_code_map; |
| 12057 entry = i; | 12026 entry = i; |
| 12058 break; | 12027 break; |
| 12059 } | 12028 } |
| 12060 } | 12029 } |
| 12061 | 12030 |
| 12062 if (entry < kEntriesStart) { | 12031 if (entry < kEntriesStart) { |
| 12063 // Copy old optimized code map and append one new entry. | 12032 // Copy old optimized code map and append one new entry. |
| 12064 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( | 12033 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( |
| 12065 old_code_map, kEntryLength, TENURED); | 12034 old_code_map, kEntryLength, TENURED); |
| 12066 // TODO(mstarzinger): Temporary workaround. The allocation above might | 12035 // TODO(mstarzinger): Temporary workaround. The allocation above might |
| 12067 // have flushed the optimized code map and the copy we created is full of | 12036 // have flushed the optimized code map and the copy we created is full of |
| 12068 // holes. For now we just give up on adding the entry and pretend it got | 12037 // holes. For now we just give up on adding the entry and pretend it got |
| 12069 // flushed. | 12038 // flushed. |
| 12070 if (shared->OptimizedCodeMapIsCleared()) return; | 12039 if (shared->OptimizedCodeMapIsCleared()) return; |
| 12071 entry = old_code_map->length(); | 12040 entry = old_code_map->length(); |
| 12072 } | 12041 } |
| 12073 } | 12042 } |
| 12074 | 12043 |
| 12075 Handle<WeakCell> code_cell = | 12044 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); |
| 12076 code.is_null() ? isolate->factory()->empty_weak_cell() | |
| 12077 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | |
| 12078 Handle<WeakCell> vector_cell = isolate->factory()->NewWeakCell(vector); | |
| 12079 WeakCell* context_cell = native_context->self_weak_cell(); | 12045 WeakCell* context_cell = native_context->self_weak_cell(); |
| 12080 | 12046 |
| 12081 new_code_map->set(entry + kContextOffset, context_cell); | 12047 new_code_map->set(entry + kContextOffset, context_cell); |
| 12082 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12048 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12083 new_code_map->set(entry + kFeedbackVectorOffset, *vector_cell); | |
| 12084 | 12049 |
| 12085 #ifdef DEBUG | 12050 #ifdef DEBUG |
| 12086 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12051 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
| 12087 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12052 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
| 12088 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12053 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
| 12089 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12054 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
| 12090 DCHECK(cell->cleared() || | 12055 DCHECK(cell->cleared() || |
| 12091 (cell->value()->IsCode() && | 12056 (cell->value()->IsCode() && |
| 12092 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12057 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
| 12093 cell = WeakCell::cast(new_code_map->get(i + kFeedbackVectorOffset)); | |
| 12094 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | |
| 12095 } | 12058 } |
| 12096 #endif | 12059 #endif |
| 12097 | 12060 |
| 12098 FixedArray* old_code_map = shared->optimized_code_map(); | 12061 FixedArray* old_code_map = shared->optimized_code_map(); |
| 12099 if (old_code_map != *new_code_map) { | 12062 if (old_code_map != *new_code_map) { |
| 12100 shared->set_optimized_code_map(*new_code_map); | 12063 shared->set_optimized_code_map(*new_code_map); |
| 12101 } | 12064 } |
| 12102 } | 12065 } |
| 12103 | 12066 |
| 12104 | 12067 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 12122 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12085 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
| 12123 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12086 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
| 12124 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12087 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
| 12125 optimized_code; | 12088 optimized_code; |
| 12126 if (found) { | 12089 if (found) { |
| 12127 if (FLAG_trace_opt) { | 12090 if (FLAG_trace_opt) { |
| 12128 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12091 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
| 12129 ShortPrint(); | 12092 ShortPrint(); |
| 12130 PrintF("]\n"); | 12093 PrintF("]\n"); |
| 12131 } | 12094 } |
| 12132 // Just clear the code in order to continue sharing a feedback vector. | 12095 // Just clear the code. |
| 12133 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12096 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
| 12134 SKIP_WRITE_BARRIER); | 12097 SKIP_WRITE_BARRIER); |
| 12135 } | 12098 } |
| 12136 } | 12099 } |
| 12137 } | 12100 } |
| 12138 | 12101 |
| 12139 if (!found) { | 12102 if (!found) { |
| 12140 // We didn't find the code in here. It must be osr'd code. | 12103 // We didn't find the code in here. It must be osr'd code. |
| 12141 isolate->EvictOSROptimizedCode(optimized_code, reason); | 12104 isolate->EvictOSROptimizedCode(optimized_code, reason); |
| 12142 } | 12105 } |
| 12143 } | 12106 } |
| 12144 | 12107 |
| 12145 // static | 12108 // static |
| 12146 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12109 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
| 12147 Handle<SharedFunctionInfo> shared(function->shared()); | 12110 Handle<SharedFunctionInfo> shared(function->shared()); |
| 12148 Handle<Context> native_context(function->context()->native_context()); | 12111 Handle<Context> native_context(function->context()->native_context()); |
| 12149 if (function->feedback_vector() == | 12112 Isolate* isolate = shared->GetIsolate(); |
| 12150 function->GetIsolate()->heap()->empty_type_feedback_vector()) { | 12113 |
| 12151 Handle<TypeFeedbackVector> vector = | 12114 Cell* cell = function->feedback_vector_cell(); |
| 12152 SharedFunctionInfo::FindOrCreateVector(shared, native_context); | 12115 if (cell == isolate->heap()->undefined_cell()) { |
| 12153 function->set_feedback_vector(*vector); | 12116 if (FLAG_trace_strong_rooted_literals) { |
| 12117 PrintF("EnsureLiterals: Installing literals cell in %s %p\n", | |
| 12118 shared->DebugName()->ToCString().get(), | |
| 12119 reinterpret_cast<void*>(*function)); | |
| 12120 } | |
| 12121 // Top level code didn't get it's literals installed. | |
| 12122 Handle<TypeFeedbackVector> feedback_vector = | |
| 12123 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
| 12124 Handle<Cell> new_cell = isolate->factory()->NewCell(feedback_vector); | |
| 12125 function->set_feedback_vector_cell(*new_cell); | |
| 12126 } else if (!cell->value()->IsTypeFeedbackVector() || | |
| 12127 !function->has_feedback_vector()) { | |
| 12128 DCHECK(cell != isolate->heap()->undefined_cell()); | |
| 12129 if (FLAG_trace_strong_rooted_literals) { | |
| 12130 PrintF("EnsureLiterals: Update literals cell in %s %p\n", | |
| 12131 shared->DebugName()->ToCString().get(), | |
| 12132 reinterpret_cast<void*>(*function)); | |
| 12133 } | |
| 12134 Handle<TypeFeedbackVector> feedback_vector = | |
| 12135 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
| 12136 // Re-get the feedback_vector() value as GC may have occurred. | |
| 12137 function->feedback_vector_cell()->set_value(*feedback_vector); | |
| 12138 } else { | |
| 12139 if (FLAG_trace_strong_rooted_literals) { | |
| 12140 PrintF("EnsureLiterals: did nothing for %s %p\n", | |
| 12141 shared->DebugName()->ToCString().get(), | |
| 12142 reinterpret_cast<void*>(*function)); | |
| 12143 } | |
| 12154 } | 12144 } |
| 12145 | |
| 12146 // No matter what, ensure some post-conditions. | |
| 12147 DCHECK(shared->feedback_metadata()->slot_count() != 0 || | |
| 12148 function->feedback_vector() == | |
| 12149 shared->GetIsolate()->heap()->empty_type_feedback_vector()); | |
| 12155 } | 12150 } |
| 12156 | 12151 |
| 12157 static void GetMinInobjectSlack(Map* map, void* data) { | 12152 static void GetMinInobjectSlack(Map* map, void* data) { |
| 12158 int slack = map->unused_property_fields(); | 12153 int slack = map->unused_property_fields(); |
| 12159 if (*reinterpret_cast<int*>(data) > slack) { | 12154 if (*reinterpret_cast<int*>(data) > slack) { |
| 12160 *reinterpret_cast<int*>(data) = slack; | 12155 *reinterpret_cast<int*>(data) = slack; |
| 12161 } | 12156 } |
| 12162 } | 12157 } |
| 12163 | 12158 |
| 12164 | 12159 |
| (...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13723 FixedArray* optimized_code_map = this->optimized_code_map(); | 13718 FixedArray* optimized_code_map = this->optimized_code_map(); |
| 13724 int length = optimized_code_map->length(); | 13719 int length = optimized_code_map->length(); |
| 13725 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 13720 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
| 13726 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 13721 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
| 13727 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 13722 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
| 13728 SKIP_WRITE_BARRIER); | 13723 SKIP_WRITE_BARRIER); |
| 13729 } | 13724 } |
| 13730 } | 13725 } |
| 13731 } | 13726 } |
| 13732 | 13727 |
| 13733 CodeAndVector SharedFunctionInfo::SearchOptimizedCodeMap( | 13728 Code* SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
| 13734 Context* native_context, BailoutId osr_ast_id) { | 13729 BailoutId osr_ast_id) { |
| 13735 CodeAndVector result = {nullptr, nullptr}; | 13730 Code* result = nullptr; |
| 13736 if (!osr_ast_id.IsNone()) { | 13731 if (!osr_ast_id.IsNone()) { |
| 13737 Code* code; | 13732 return native_context->SearchOptimizedCodeMap(this, osr_ast_id); |
| 13738 TypeFeedbackVector* vector; | |
| 13739 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &vector); | |
| 13740 result = {code, vector}; | |
| 13741 return result; | |
| 13742 } | 13733 } |
| 13743 | 13734 |
| 13744 DCHECK(osr_ast_id.IsNone()); | 13735 DCHECK(osr_ast_id.IsNone()); |
| 13745 int entry = SearchOptimizedCodeMapEntry(native_context); | 13736 int entry = SearchOptimizedCodeMapEntry(native_context); |
| 13746 if (entry != kNotFound) { | 13737 if (entry != kNotFound) { |
| 13747 FixedArray* code_map = optimized_code_map(); | 13738 FixedArray* code_map = optimized_code_map(); |
| 13748 DCHECK_LE(entry + kEntryLength, code_map->length()); | 13739 DCHECK_LE(entry + kEntryLength, code_map->length()); |
| 13749 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 13740 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
| 13750 WeakCell* vector_cell = | 13741 result = cell->cleared() ? nullptr : Code::cast(cell->value()); |
| 13751 WeakCell::cast(code_map->get(entry + kFeedbackVectorOffset)); | |
| 13752 | |
| 13753 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | |
| 13754 vector_cell->cleared() ? nullptr : TypeFeedbackVector::cast( | |
| 13755 vector_cell->value())}; | |
| 13756 } | 13742 } |
| 13757 return result; | 13743 return result; |
| 13758 } | 13744 } |
| 13759 | 13745 |
| 13760 | 13746 |
| 13761 #define DECLARE_TAG(ignore1, name, ignore2) name, | 13747 #define DECLARE_TAG(ignore1, name, ignore2) name, |
| 13762 const char* const VisitorSynchronization::kTags[ | 13748 const char* const VisitorSynchronization::kTags[ |
| 13763 VisitorSynchronization::kNumberOfSyncTags] = { | 13749 VisitorSynchronization::kNumberOfSyncTags] = { |
| 13764 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 13750 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
| 13765 }; | 13751 }; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14025 int p = it.source_position().ScriptOffset(); | 14011 int p = it.source_position().ScriptOffset(); |
| 14026 if (statement_position < p && p <= position) { | 14012 if (statement_position < p && p <= position) { |
| 14027 statement_position = p; | 14013 statement_position = p; |
| 14028 } | 14014 } |
| 14029 } | 14015 } |
| 14030 } | 14016 } |
| 14031 return statement_position; | 14017 return statement_position; |
| 14032 } | 14018 } |
| 14033 | 14019 |
| 14034 void JSFunction::ClearTypeFeedbackInfo() { | 14020 void JSFunction::ClearTypeFeedbackInfo() { |
| 14035 feedback_vector()->ClearSlots(shared()); | 14021 if (feedback_vector_cell()->value()->IsTypeFeedbackVector()) { |
| 14022 TypeFeedbackVector* vector = feedback_vector(); | |
| 14023 vector->ClearSlots(shared()); | |
| 14024 } | |
| 14036 } | 14025 } |
| 14037 | 14026 |
| 14038 void JSFunction::ClearTypeFeedbackInfoAtGCTime() { | 14027 void JSFunction::ClearTypeFeedbackInfoAtGCTime() { |
| 14039 feedback_vector()->ClearSlotsAtGCTime(shared()); | 14028 if (feedback_vector_cell()->value()->IsTypeFeedbackVector()) { |
| 14029 TypeFeedbackVector* vector = feedback_vector(); | |
| 14030 vector->ClearSlotsAtGCTime(shared()); | |
| 14031 } | |
| 14040 } | 14032 } |
| 14041 | 14033 |
| 14042 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { | 14034 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { |
| 14043 DisallowHeapAllocation no_gc; | 14035 DisallowHeapAllocation no_gc; |
| 14044 DCHECK(kind() == FUNCTION); | 14036 DCHECK(kind() == FUNCTION); |
| 14045 BackEdgeTable back_edges(this, &no_gc); | 14037 BackEdgeTable back_edges(this, &no_gc); |
| 14046 for (uint32_t i = 0; i < back_edges.length(); i++) { | 14038 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 14047 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); | 14039 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); |
| 14048 } | 14040 } |
| 14049 return BailoutId::None(); | 14041 return BailoutId::None(); |
| (...skipping 3418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17468 Isolate* isolate = GetIsolate(); | 17460 Isolate* isolate = GetIsolate(); |
| 17469 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | 17461 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
| 17470 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); | 17462 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); |
| 17471 int entry = FindEntry(&key); | 17463 int entry = FindEntry(&key); |
| 17472 if (entry == kNotFound) return isolate->factory()->undefined_value(); | 17464 if (entry == kNotFound) return isolate->factory()->undefined_value(); |
| 17473 int index = EntryToIndex(entry); | 17465 int index = EntryToIndex(entry); |
| 17474 if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value(); | 17466 if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value(); |
| 17475 return Handle<Object>(get(index + 1), isolate); | 17467 return Handle<Object>(get(index + 1), isolate); |
| 17476 } | 17468 } |
| 17477 | 17469 |
| 17470 static Cell* SearchLiteralsMap(CompilationCacheTable* cache, int cache_entry, | |
| 17471 Context* native_context); | |
| 17472 static void AddToLiteralsMap(Handle<CompilationCacheTable> cache, | |
| 17473 int cache_entry, Handle<Context> native_context, | |
| 17474 Handle<Cell> literals); | |
| 17478 | 17475 |
| 17479 Handle<Object> CompilationCacheTable::LookupEval( | 17476 InfoVectorPair CompilationCacheTable::LookupScript(Handle<String> src, |
| 17477 Handle<Context> context, | |
| 17478 LanguageMode language_mode) { | |
| 17479 InfoVectorPair empty_result; | |
| 17480 Isolate* isolate = GetIsolate(); | |
| 17481 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | |
| 17482 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); | |
| 17483 int entry = FindEntry(&key); | |
| 17484 if (entry == kNotFound) return empty_result; | |
| 17485 int index = EntryToIndex(entry); | |
| 17486 if (!get(index)->IsFixedArray()) return empty_result; | |
| 17487 Object* obj = get(index + 1); | |
| 17488 if (obj->IsSharedFunctionInfo()) { | |
| 17489 Cell* literals = | |
| 17490 SearchLiteralsMap(this, index + 2, context->native_context()); | |
| 17491 return InfoVectorPair(SharedFunctionInfo::cast(obj), literals); | |
| 17492 } | |
| 17493 return empty_result; | |
| 17494 } | |
| 17495 | |
| 17496 InfoVectorPair CompilationCacheTable::LookupEval( | |
| 17480 Handle<String> src, Handle<SharedFunctionInfo> outer_info, | 17497 Handle<String> src, Handle<SharedFunctionInfo> outer_info, |
| 17481 LanguageMode language_mode, int scope_position) { | 17498 Handle<Context> native_context, LanguageMode language_mode, |
| 17482 Isolate* isolate = GetIsolate(); | 17499 int scope_position) { |
| 17500 InfoVectorPair empty_result; | |
| 17483 // Cache key is the tuple (source, outer shared function info, scope position) | 17501 // Cache key is the tuple (source, outer shared function info, scope position) |
| 17484 // to unambiguously identify the context chain the cached eval code assumes. | 17502 // to unambiguously identify the context chain the cached eval code assumes. |
| 17485 StringSharedKey key(src, outer_info, language_mode, scope_position); | 17503 StringSharedKey key(src, outer_info, language_mode, scope_position); |
| 17486 int entry = FindEntry(&key); | 17504 int entry = FindEntry(&key); |
| 17487 if (entry == kNotFound) return isolate->factory()->undefined_value(); | 17505 if (entry == kNotFound) return empty_result; |
| 17488 int index = EntryToIndex(entry); | 17506 int index = EntryToIndex(entry); |
| 17489 if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value(); | 17507 if (!get(index)->IsFixedArray()) return empty_result; |
| 17490 return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); | 17508 Object* obj = get(EntryToIndex(entry) + 1); |
| 17509 if (obj->IsSharedFunctionInfo()) { | |
| 17510 Cell* literals = | |
| 17511 SearchLiteralsMap(this, EntryToIndex(entry) + 2, *native_context); | |
| 17512 return InfoVectorPair(SharedFunctionInfo::cast(obj), literals); | |
| 17513 } | |
| 17514 return empty_result; | |
| 17491 } | 17515 } |
| 17492 | 17516 |
| 17493 | |
| 17494 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src, | 17517 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src, |
| 17495 JSRegExp::Flags flags) { | 17518 JSRegExp::Flags flags) { |
| 17496 Isolate* isolate = GetIsolate(); | 17519 Isolate* isolate = GetIsolate(); |
| 17497 DisallowHeapAllocation no_allocation; | 17520 DisallowHeapAllocation no_allocation; |
| 17498 RegExpKey key(src, flags); | 17521 RegExpKey key(src, flags); |
| 17499 int entry = FindEntry(&key); | 17522 int entry = FindEntry(&key); |
| 17500 if (entry == kNotFound) return isolate->factory()->undefined_value(); | 17523 if (entry == kNotFound) return isolate->factory()->undefined_value(); |
| 17501 return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); | 17524 return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); |
| 17502 } | 17525 } |
| 17503 | 17526 |
| 17504 | 17527 |
| 17505 Handle<CompilationCacheTable> CompilationCacheTable::Put( | 17528 Handle<CompilationCacheTable> CompilationCacheTable::Put( |
| 17506 Handle<CompilationCacheTable> cache, Handle<String> src, | 17529 Handle<CompilationCacheTable> cache, Handle<String> src, |
| 17507 Handle<Context> context, LanguageMode language_mode, Handle<Object> value) { | 17530 Handle<Context> context, LanguageMode language_mode, Handle<Object> value) { |
| 17508 Isolate* isolate = cache->GetIsolate(); | 17531 Isolate* isolate = cache->GetIsolate(); |
| 17509 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | 17532 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
| 17510 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); | 17533 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); |
| 17511 Handle<Object> k = key.AsHandle(isolate); | 17534 Handle<Object> k = key.AsHandle(isolate); |
| 17512 cache = EnsureCapacity(cache, 1, &key); | 17535 cache = EnsureCapacity(cache, 1, &key); |
| 17513 int entry = cache->FindInsertionEntry(key.Hash()); | 17536 int entry = cache->FindInsertionEntry(key.Hash()); |
| 17514 cache->set(EntryToIndex(entry), *k); | 17537 cache->set(EntryToIndex(entry), *k); |
| 17515 cache->set(EntryToIndex(entry) + 1, *value); | 17538 cache->set(EntryToIndex(entry) + 1, *value); |
| 17516 cache->ElementAdded(); | 17539 cache->ElementAdded(); |
| 17517 return cache; | 17540 return cache; |
| 17518 } | 17541 } |
| 17519 | 17542 |
| 17543 Handle<CompilationCacheTable> CompilationCacheTable::PutScript( | |
| 17544 Handle<CompilationCacheTable> cache, Handle<String> src, | |
| 17545 Handle<Context> context, LanguageMode language_mode, | |
| 17546 Handle<SharedFunctionInfo> value, Handle<Cell> literals) { | |
| 17547 Isolate* isolate = cache->GetIsolate(); | |
| 17548 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | |
| 17549 // TODO(mvstanton): is the context always a native context already? | |
| 17550 Handle<Context> native_context(context->native_context()); | |
| 17551 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); | |
| 17552 Handle<Object> k = key.AsHandle(isolate); | |
| 17553 cache = EnsureCapacity(cache, 1, &key); | |
| 17554 int entry = cache->FindInsertionEntry(key.Hash()); | |
| 17555 cache->set(EntryToIndex(entry), *k); | |
| 17556 cache->set(EntryToIndex(entry) + 1, *value); | |
| 17557 AddToLiteralsMap(cache, EntryToIndex(entry) + 2, native_context, literals); | |
| 17558 cache->ElementAdded(); | |
| 17559 return cache; | |
| 17560 } | |
| 17561 | |
| 17562 const int kLiteralEntryLength = 2; | |
| 17563 const int kLiteralInitialLength = 2; | |
| 17564 const int kLiteralContextOffset = 0; | |
| 17565 const int kLiteralLiteralsOffset = 1; | |
| 17566 | |
| 17567 static int SearchLiteralsMapEntry(CompilationCacheTable* cache, int cache_entry, | |
|
Michael Starzinger
2017/02/02 13:42:07
nit: Use anonymous namespace instead of static. I
mvstanton
2017/02/03 12:16:37
Excellent, I did both.
| |
| 17568 Context* native_context) { | |
| 17569 DisallowHeapAllocation no_gc; | |
| 17570 DCHECK(native_context->IsNativeContext()); | |
| 17571 Object* obj = cache->get(cache_entry); | |
| 17572 | |
| 17573 if (obj->IsFixedArray()) { | |
| 17574 FixedArray* literals_map = FixedArray::cast(obj); | |
| 17575 int length = literals_map->length(); | |
| 17576 for (int i = 0; i < length; i += kLiteralEntryLength) { | |
| 17577 if (WeakCell::cast(literals_map->get(i + kLiteralContextOffset)) | |
| 17578 ->value() == native_context) { | |
| 17579 return i; | |
| 17580 } | |
| 17581 } | |
| 17582 } | |
| 17583 return -1; | |
| 17584 } | |
| 17585 | |
| 17586 static void AddToLiteralsMap(Handle<CompilationCacheTable> cache, | |
| 17587 int cache_entry, Handle<Context> native_context, | |
| 17588 Handle<Cell> literals) { | |
| 17589 Isolate* isolate = native_context->GetIsolate(); | |
| 17590 DCHECK(native_context->IsNativeContext()); | |
| 17591 STATIC_ASSERT(kLiteralEntryLength == 2); | |
| 17592 Handle<FixedArray> new_literals_map; | |
| 17593 int entry; | |
| 17594 | |
| 17595 Object* obj = cache->get(cache_entry); | |
| 17596 | |
| 17597 if (!obj->IsFixedArray() || FixedArray::cast(obj)->length() == 0) { | |
| 17598 new_literals_map = | |
| 17599 isolate->factory()->NewFixedArray(kLiteralInitialLength, TENURED); | |
| 17600 entry = 0; | |
| 17601 } else { | |
| 17602 Handle<FixedArray> old_literals_map(FixedArray::cast(obj), isolate); | |
| 17603 entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context); | |
| 17604 if (entry >= 0) { | |
| 17605 // Just set the code of the entry. | |
| 17606 Handle<WeakCell> literals_cell = | |
| 17607 isolate->factory()->NewWeakCell(literals); | |
| 17608 old_literals_map->set(entry + kLiteralLiteralsOffset, *literals_cell); | |
| 17609 return; | |
| 17610 } | |
| 17611 | |
| 17612 // Can we reuse an entry? | |
| 17613 DCHECK(entry < 0); | |
| 17614 int length = old_literals_map->length(); | |
| 17615 for (int i = 0; i < length; i += kLiteralEntryLength) { | |
| 17616 if (WeakCell::cast(old_literals_map->get(i + kLiteralContextOffset)) | |
| 17617 ->cleared()) { | |
| 17618 new_literals_map = old_literals_map; | |
| 17619 entry = i; | |
| 17620 break; | |
| 17621 } | |
| 17622 } | |
| 17623 | |
| 17624 if (entry < 0) { | |
| 17625 // Copy old optimized code map and append one new entry. | |
| 17626 new_literals_map = isolate->factory()->CopyFixedArrayAndGrow( | |
| 17627 old_literals_map, kLiteralEntryLength, TENURED); | |
| 17628 entry = old_literals_map->length(); | |
| 17629 } | |
| 17630 } | |
| 17631 | |
| 17632 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | |
| 17633 WeakCell* context_cell = native_context->self_weak_cell(); | |
| 17634 | |
| 17635 new_literals_map->set(entry + kLiteralContextOffset, context_cell); | |
| 17636 new_literals_map->set(entry + kLiteralLiteralsOffset, *literals_cell); | |
| 17637 | |
| 17638 #ifdef DEBUG | |
| 17639 for (int i = 0; i < new_literals_map->length(); i += kLiteralEntryLength) { | |
| 17640 WeakCell* cell = | |
| 17641 WeakCell::cast(new_literals_map->get(i + kLiteralContextOffset)); | |
| 17642 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | |
| 17643 cell = WeakCell::cast(new_literals_map->get(i + kLiteralLiteralsOffset)); | |
| 17644 DCHECK(cell->cleared() || (cell->value()->IsCell())); | |
| 17645 } | |
| 17646 #endif | |
| 17647 | |
| 17648 Object* old_literals_map = cache->get(cache_entry); | |
| 17649 if (old_literals_map != *new_literals_map) { | |
| 17650 cache->set(cache_entry, *new_literals_map); | |
| 17651 } | |
| 17652 } | |
| 17653 | |
| 17654 static Cell* SearchLiteralsMap(CompilationCacheTable* cache, int cache_entry, | |
| 17655 Context* native_context) { | |
| 17656 Cell* result = nullptr; | |
| 17657 int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context); | |
| 17658 if (entry >= 0) { | |
| 17659 FixedArray* literals_map = FixedArray::cast(cache->get(cache_entry)); | |
| 17660 DCHECK_LE(entry + kLiteralEntryLength, literals_map->length()); | |
| 17661 WeakCell* cell = | |
| 17662 WeakCell::cast(literals_map->get(entry + kLiteralLiteralsOffset)); | |
| 17663 | |
| 17664 result = cell->cleared() ? nullptr : Cell::cast(cell->value()); | |
| 17665 } | |
| 17666 DCHECK(result == nullptr || result->IsCell()); | |
| 17667 return result; | |
| 17668 } | |
| 17520 | 17669 |
| 17521 Handle<CompilationCacheTable> CompilationCacheTable::PutEval( | 17670 Handle<CompilationCacheTable> CompilationCacheTable::PutEval( |
| 17522 Handle<CompilationCacheTable> cache, Handle<String> src, | 17671 Handle<CompilationCacheTable> cache, Handle<String> src, |
| 17523 Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value, | 17672 Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value, |
| 17524 int scope_position) { | 17673 Handle<Context> native_context, Handle<Cell> literals, int scope_position) { |
| 17525 Isolate* isolate = cache->GetIsolate(); | 17674 Isolate* isolate = cache->GetIsolate(); |
| 17526 StringSharedKey key(src, outer_info, value->language_mode(), scope_position); | 17675 StringSharedKey key(src, outer_info, value->language_mode(), scope_position); |
| 17527 { | 17676 { |
| 17528 Handle<Object> k = key.AsHandle(isolate); | 17677 Handle<Object> k = key.AsHandle(isolate); |
| 17529 DisallowHeapAllocation no_allocation_scope; | 17678 // DisallowHeapAllocation no_allocation_scope; |
|
Michael Starzinger
2017/02/02 13:42:07
Looks like a left-over. As discussed offline, the
mvstanton
2017/02/03 12:16:37
Thanks, I've added a comment about this - good poi
| |
| 17530 int entry = cache->FindEntry(&key); | 17679 int entry = cache->FindEntry(&key); |
| 17531 if (entry != kNotFound) { | 17680 if (entry != kNotFound) { |
| 17532 cache->set(EntryToIndex(entry), *k); | 17681 cache->set(EntryToIndex(entry), *k); |
| 17533 cache->set(EntryToIndex(entry) + 1, *value); | 17682 cache->set(EntryToIndex(entry) + 1, *value); |
| 17683 AddToLiteralsMap(cache, EntryToIndex(entry) + 2, native_context, | |
| 17684 literals); | |
| 17534 return cache; | 17685 return cache; |
| 17535 } | 17686 } |
| 17536 } | 17687 } |
| 17537 | 17688 |
| 17538 cache = EnsureCapacity(cache, 1, &key); | 17689 cache = EnsureCapacity(cache, 1, &key); |
| 17539 int entry = cache->FindInsertionEntry(key.Hash()); | 17690 int entry = cache->FindInsertionEntry(key.Hash()); |
| 17540 Handle<Object> k = | 17691 Handle<Object> k = |
| 17541 isolate->factory()->NewNumber(static_cast<double>(key.Hash())); | 17692 isolate->factory()->NewNumber(static_cast<double>(key.Hash())); |
| 17542 cache->set(EntryToIndex(entry), *k); | 17693 cache->set(EntryToIndex(entry), *k); |
| 17543 cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations)); | 17694 cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17578 } else { | 17729 } else { |
| 17579 NoWriteBarrierSet(this, value_index, count); | 17730 NoWriteBarrierSet(this, value_index, count); |
| 17580 } | 17731 } |
| 17581 } else if (get(entry_index)->IsFixedArray()) { | 17732 } else if (get(entry_index)->IsFixedArray()) { |
| 17582 SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index)); | 17733 SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index)); |
| 17583 bool is_old = | 17734 bool is_old = |
| 17584 info->IsInterpreted() | 17735 info->IsInterpreted() |
| 17585 ? info->bytecode_array()->IsOld() | 17736 ? info->bytecode_array()->IsOld() |
| 17586 : info->code()->kind() != Code::FUNCTION || info->code()->IsOld(); | 17737 : info->code()->kind() != Code::FUNCTION || info->code()->IsOld(); |
| 17587 if (is_old) { | 17738 if (is_old) { |
| 17588 NoWriteBarrierSet(this, entry_index, the_hole_value); | 17739 for (int i = 0; i < kEntrySize; i++) { |
| 17589 NoWriteBarrierSet(this, value_index, the_hole_value); | 17740 NoWriteBarrierSet(this, entry_index + i, the_hole_value); |
| 17741 } | |
| 17590 ElementRemoved(); | 17742 ElementRemoved(); |
| 17591 } | 17743 } |
| 17592 } | 17744 } |
| 17593 } | 17745 } |
| 17594 } | 17746 } |
| 17595 | 17747 |
| 17596 | 17748 |
| 17597 void CompilationCacheTable::Remove(Object* value) { | 17749 void CompilationCacheTable::Remove(Object* value) { |
| 17598 DisallowHeapAllocation no_allocation; | 17750 DisallowHeapAllocation no_allocation; |
| 17599 Object* the_hole_value = GetHeap()->the_hole_value(); | 17751 Object* the_hole_value = GetHeap()->the_hole_value(); |
| 17600 for (int entry = 0, size = Capacity(); entry < size; entry++) { | 17752 for (int entry = 0, size = Capacity(); entry < size; entry++) { |
| 17601 int entry_index = EntryToIndex(entry); | 17753 int entry_index = EntryToIndex(entry); |
| 17602 int value_index = entry_index + 1; | 17754 int value_index = entry_index + 1; |
| 17603 if (get(value_index) == value) { | 17755 if (get(value_index) == value) { |
| 17604 NoWriteBarrierSet(this, entry_index, the_hole_value); | 17756 for (int i = 0; i < kEntrySize; i++) { |
| 17605 NoWriteBarrierSet(this, value_index, the_hole_value); | 17757 NoWriteBarrierSet(this, entry_index + i, the_hole_value); |
| 17758 } | |
| 17606 ElementRemoved(); | 17759 ElementRemoved(); |
| 17607 } | 17760 } |
| 17608 } | 17761 } |
| 17609 return; | 17762 return; |
| 17610 } | 17763 } |
| 17611 | 17764 |
| 17612 template <typename Derived, typename Shape, typename Key> | 17765 template <typename Derived, typename Shape, typename Key> |
| 17613 Handle<Derived> Dictionary<Derived, Shape, Key>::New( | 17766 Handle<Derived> Dictionary<Derived, Shape, Key>::New( |
| 17614 Isolate* isolate, int at_least_space_for, PretenureFlag pretenure, | 17767 Isolate* isolate, int at_least_space_for, PretenureFlag pretenure, |
| 17615 MinimumCapacity capacity_option) { | 17768 MinimumCapacity capacity_option) { |
| (...skipping 2409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 20025 // depend on this. | 20178 // depend on this. |
| 20026 return DICTIONARY_ELEMENTS; | 20179 return DICTIONARY_ELEMENTS; |
| 20027 } | 20180 } |
| 20028 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20181 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20029 return kind; | 20182 return kind; |
| 20030 } | 20183 } |
| 20031 } | 20184 } |
| 20032 | 20185 |
| 20033 } // namespace internal | 20186 } // namespace internal |
| 20034 } // namespace v8 | 20187 } // namespace v8 |
| OLD | NEW |