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 namespace { |
17478 | 17471 |
17479 Handle<Object> CompilationCacheTable::LookupEval( | 17472 const int kLiteralEntryLength = 2; |
| 17473 const int kLiteralInitialLength = 2; |
| 17474 const int kLiteralContextOffset = 0; |
| 17475 const int kLiteralLiteralsOffset = 1; |
| 17476 |
| 17477 int SearchLiteralsMapEntry(CompilationCacheTable* cache, int cache_entry, |
| 17478 Context* native_context) { |
| 17479 DisallowHeapAllocation no_gc; |
| 17480 DCHECK(native_context->IsNativeContext()); |
| 17481 Object* obj = cache->get(cache_entry); |
| 17482 |
| 17483 if (obj->IsFixedArray()) { |
| 17484 FixedArray* literals_map = FixedArray::cast(obj); |
| 17485 int length = literals_map->length(); |
| 17486 for (int i = 0; i < length; i += kLiteralEntryLength) { |
| 17487 if (WeakCell::cast(literals_map->get(i + kLiteralContextOffset)) |
| 17488 ->value() == native_context) { |
| 17489 return i; |
| 17490 } |
| 17491 } |
| 17492 } |
| 17493 return -1; |
| 17494 } |
| 17495 |
| 17496 void AddToLiteralsMap(Handle<CompilationCacheTable> cache, int cache_entry, |
| 17497 Handle<Context> native_context, Handle<Cell> literals) { |
| 17498 Isolate* isolate = native_context->GetIsolate(); |
| 17499 DCHECK(native_context->IsNativeContext()); |
| 17500 STATIC_ASSERT(kLiteralEntryLength == 2); |
| 17501 Handle<FixedArray> new_literals_map; |
| 17502 int entry; |
| 17503 |
| 17504 Object* obj = cache->get(cache_entry); |
| 17505 |
| 17506 if (!obj->IsFixedArray() || FixedArray::cast(obj)->length() == 0) { |
| 17507 new_literals_map = |
| 17508 isolate->factory()->NewFixedArray(kLiteralInitialLength, TENURED); |
| 17509 entry = 0; |
| 17510 } else { |
| 17511 Handle<FixedArray> old_literals_map(FixedArray::cast(obj), isolate); |
| 17512 entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context); |
| 17513 if (entry >= 0) { |
| 17514 // Just set the code of the entry. |
| 17515 Handle<WeakCell> literals_cell = |
| 17516 isolate->factory()->NewWeakCell(literals); |
| 17517 old_literals_map->set(entry + kLiteralLiteralsOffset, *literals_cell); |
| 17518 return; |
| 17519 } |
| 17520 |
| 17521 // Can we reuse an entry? |
| 17522 DCHECK(entry < 0); |
| 17523 int length = old_literals_map->length(); |
| 17524 for (int i = 0; i < length; i += kLiteralEntryLength) { |
| 17525 if (WeakCell::cast(old_literals_map->get(i + kLiteralContextOffset)) |
| 17526 ->cleared()) { |
| 17527 new_literals_map = old_literals_map; |
| 17528 entry = i; |
| 17529 break; |
| 17530 } |
| 17531 } |
| 17532 |
| 17533 if (entry < 0) { |
| 17534 // Copy old optimized code map and append one new entry. |
| 17535 new_literals_map = isolate->factory()->CopyFixedArrayAndGrow( |
| 17536 old_literals_map, kLiteralEntryLength, TENURED); |
| 17537 entry = old_literals_map->length(); |
| 17538 } |
| 17539 } |
| 17540 |
| 17541 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); |
| 17542 WeakCell* context_cell = native_context->self_weak_cell(); |
| 17543 |
| 17544 new_literals_map->set(entry + kLiteralContextOffset, context_cell); |
| 17545 new_literals_map->set(entry + kLiteralLiteralsOffset, *literals_cell); |
| 17546 |
| 17547 #ifdef DEBUG |
| 17548 for (int i = 0; i < new_literals_map->length(); i += kLiteralEntryLength) { |
| 17549 WeakCell* cell = |
| 17550 WeakCell::cast(new_literals_map->get(i + kLiteralContextOffset)); |
| 17551 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
| 17552 cell = WeakCell::cast(new_literals_map->get(i + kLiteralLiteralsOffset)); |
| 17553 DCHECK(cell->cleared() || (cell->value()->IsCell())); |
| 17554 } |
| 17555 #endif |
| 17556 |
| 17557 Object* old_literals_map = cache->get(cache_entry); |
| 17558 if (old_literals_map != *new_literals_map) { |
| 17559 cache->set(cache_entry, *new_literals_map); |
| 17560 } |
| 17561 } |
| 17562 |
| 17563 Cell* SearchLiteralsMap(CompilationCacheTable* cache, int cache_entry, |
| 17564 Context* native_context) { |
| 17565 Cell* result = nullptr; |
| 17566 int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context); |
| 17567 if (entry >= 0) { |
| 17568 FixedArray* literals_map = FixedArray::cast(cache->get(cache_entry)); |
| 17569 DCHECK_LE(entry + kLiteralEntryLength, literals_map->length()); |
| 17570 WeakCell* cell = |
| 17571 WeakCell::cast(literals_map->get(entry + kLiteralLiteralsOffset)); |
| 17572 |
| 17573 result = cell->cleared() ? nullptr : Cell::cast(cell->value()); |
| 17574 } |
| 17575 DCHECK(result == nullptr || result->IsCell()); |
| 17576 return result; |
| 17577 } |
| 17578 |
| 17579 } // namespace |
| 17580 |
| 17581 InfoVectorPair CompilationCacheTable::LookupScript(Handle<String> src, |
| 17582 Handle<Context> context, |
| 17583 LanguageMode language_mode) { |
| 17584 InfoVectorPair empty_result; |
| 17585 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
| 17586 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); |
| 17587 int entry = FindEntry(&key); |
| 17588 if (entry == kNotFound) return empty_result; |
| 17589 int index = EntryToIndex(entry); |
| 17590 if (!get(index)->IsFixedArray()) return empty_result; |
| 17591 Object* obj = get(index + 1); |
| 17592 if (obj->IsSharedFunctionInfo()) { |
| 17593 Cell* literals = |
| 17594 SearchLiteralsMap(this, index + 2, context->native_context()); |
| 17595 return InfoVectorPair(SharedFunctionInfo::cast(obj), literals); |
| 17596 } |
| 17597 return empty_result; |
| 17598 } |
| 17599 |
| 17600 InfoVectorPair CompilationCacheTable::LookupEval( |
17480 Handle<String> src, Handle<SharedFunctionInfo> outer_info, | 17601 Handle<String> src, Handle<SharedFunctionInfo> outer_info, |
17481 LanguageMode language_mode, int scope_position) { | 17602 Handle<Context> native_context, LanguageMode language_mode, |
17482 Isolate* isolate = GetIsolate(); | 17603 int scope_position) { |
| 17604 InfoVectorPair empty_result; |
17483 // Cache key is the tuple (source, outer shared function info, scope position) | 17605 // Cache key is the tuple (source, outer shared function info, scope position) |
17484 // to unambiguously identify the context chain the cached eval code assumes. | 17606 // to unambiguously identify the context chain the cached eval code assumes. |
17485 StringSharedKey key(src, outer_info, language_mode, scope_position); | 17607 StringSharedKey key(src, outer_info, language_mode, scope_position); |
17486 int entry = FindEntry(&key); | 17608 int entry = FindEntry(&key); |
17487 if (entry == kNotFound) return isolate->factory()->undefined_value(); | 17609 if (entry == kNotFound) return empty_result; |
17488 int index = EntryToIndex(entry); | 17610 int index = EntryToIndex(entry); |
17489 if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value(); | 17611 if (!get(index)->IsFixedArray()) return empty_result; |
17490 return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); | 17612 Object* obj = get(EntryToIndex(entry) + 1); |
| 17613 if (obj->IsSharedFunctionInfo()) { |
| 17614 Cell* literals = |
| 17615 SearchLiteralsMap(this, EntryToIndex(entry) + 2, *native_context); |
| 17616 return InfoVectorPair(SharedFunctionInfo::cast(obj), literals); |
| 17617 } |
| 17618 return empty_result; |
17491 } | 17619 } |
17492 | 17620 |
17493 | |
17494 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src, | 17621 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src, |
17495 JSRegExp::Flags flags) { | 17622 JSRegExp::Flags flags) { |
17496 Isolate* isolate = GetIsolate(); | 17623 Isolate* isolate = GetIsolate(); |
17497 DisallowHeapAllocation no_allocation; | 17624 DisallowHeapAllocation no_allocation; |
17498 RegExpKey key(src, flags); | 17625 RegExpKey key(src, flags); |
17499 int entry = FindEntry(&key); | 17626 int entry = FindEntry(&key); |
17500 if (entry == kNotFound) return isolate->factory()->undefined_value(); | 17627 if (entry == kNotFound) return isolate->factory()->undefined_value(); |
17501 return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); | 17628 return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); |
17502 } | 17629 } |
17503 | 17630 |
17504 | 17631 |
17505 Handle<CompilationCacheTable> CompilationCacheTable::Put( | 17632 Handle<CompilationCacheTable> CompilationCacheTable::Put( |
17506 Handle<CompilationCacheTable> cache, Handle<String> src, | 17633 Handle<CompilationCacheTable> cache, Handle<String> src, |
17507 Handle<Context> context, LanguageMode language_mode, Handle<Object> value) { | 17634 Handle<Context> context, LanguageMode language_mode, Handle<Object> value) { |
17508 Isolate* isolate = cache->GetIsolate(); | 17635 Isolate* isolate = cache->GetIsolate(); |
17509 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | 17636 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
17510 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); | 17637 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); |
17511 Handle<Object> k = key.AsHandle(isolate); | 17638 Handle<Object> k = key.AsHandle(isolate); |
17512 cache = EnsureCapacity(cache, 1, &key); | 17639 cache = EnsureCapacity(cache, 1, &key); |
17513 int entry = cache->FindInsertionEntry(key.Hash()); | 17640 int entry = cache->FindInsertionEntry(key.Hash()); |
17514 cache->set(EntryToIndex(entry), *k); | 17641 cache->set(EntryToIndex(entry), *k); |
17515 cache->set(EntryToIndex(entry) + 1, *value); | 17642 cache->set(EntryToIndex(entry) + 1, *value); |
17516 cache->ElementAdded(); | 17643 cache->ElementAdded(); |
17517 return cache; | 17644 return cache; |
17518 } | 17645 } |
17519 | 17646 |
| 17647 Handle<CompilationCacheTable> CompilationCacheTable::PutScript( |
| 17648 Handle<CompilationCacheTable> cache, Handle<String> src, |
| 17649 Handle<Context> context, LanguageMode language_mode, |
| 17650 Handle<SharedFunctionInfo> value, Handle<Cell> literals) { |
| 17651 Isolate* isolate = cache->GetIsolate(); |
| 17652 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
| 17653 Handle<Context> native_context(context->native_context()); |
| 17654 StringSharedKey key(src, shared, language_mode, kNoSourcePosition); |
| 17655 Handle<Object> k = key.AsHandle(isolate); |
| 17656 cache = EnsureCapacity(cache, 1, &key); |
| 17657 int entry = cache->FindInsertionEntry(key.Hash()); |
| 17658 cache->set(EntryToIndex(entry), *k); |
| 17659 cache->set(EntryToIndex(entry) + 1, *value); |
| 17660 AddToLiteralsMap(cache, EntryToIndex(entry) + 2, native_context, literals); |
| 17661 cache->ElementAdded(); |
| 17662 return cache; |
| 17663 } |
17520 | 17664 |
17521 Handle<CompilationCacheTable> CompilationCacheTable::PutEval( | 17665 Handle<CompilationCacheTable> CompilationCacheTable::PutEval( |
17522 Handle<CompilationCacheTable> cache, Handle<String> src, | 17666 Handle<CompilationCacheTable> cache, Handle<String> src, |
17523 Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value, | 17667 Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value, |
17524 int scope_position) { | 17668 Handle<Context> native_context, Handle<Cell> literals, int scope_position) { |
17525 Isolate* isolate = cache->GetIsolate(); | 17669 Isolate* isolate = cache->GetIsolate(); |
17526 StringSharedKey key(src, outer_info, value->language_mode(), scope_position); | 17670 StringSharedKey key(src, outer_info, value->language_mode(), scope_position); |
17527 { | 17671 { |
17528 Handle<Object> k = key.AsHandle(isolate); | 17672 Handle<Object> k = key.AsHandle(isolate); |
17529 DisallowHeapAllocation no_allocation_scope; | |
17530 int entry = cache->FindEntry(&key); | 17673 int entry = cache->FindEntry(&key); |
17531 if (entry != kNotFound) { | 17674 if (entry != kNotFound) { |
17532 cache->set(EntryToIndex(entry), *k); | 17675 cache->set(EntryToIndex(entry), *k); |
17533 cache->set(EntryToIndex(entry) + 1, *value); | 17676 cache->set(EntryToIndex(entry) + 1, *value); |
| 17677 // AddToLiteralsMap may allocate a new sub-array to live in the entry, |
| 17678 // but it won't change the cache array. Therefore EntryToIndex and |
| 17679 // entry remains correct. |
| 17680 AddToLiteralsMap(cache, EntryToIndex(entry) + 2, native_context, |
| 17681 literals); |
17534 return cache; | 17682 return cache; |
17535 } | 17683 } |
17536 } | 17684 } |
17537 | 17685 |
17538 cache = EnsureCapacity(cache, 1, &key); | 17686 cache = EnsureCapacity(cache, 1, &key); |
17539 int entry = cache->FindInsertionEntry(key.Hash()); | 17687 int entry = cache->FindInsertionEntry(key.Hash()); |
17540 Handle<Object> k = | 17688 Handle<Object> k = |
17541 isolate->factory()->NewNumber(static_cast<double>(key.Hash())); | 17689 isolate->factory()->NewNumber(static_cast<double>(key.Hash())); |
17542 cache->set(EntryToIndex(entry), *k); | 17690 cache->set(EntryToIndex(entry), *k); |
17543 cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations)); | 17691 cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17578 } else { | 17726 } else { |
17579 NoWriteBarrierSet(this, value_index, count); | 17727 NoWriteBarrierSet(this, value_index, count); |
17580 } | 17728 } |
17581 } else if (get(entry_index)->IsFixedArray()) { | 17729 } else if (get(entry_index)->IsFixedArray()) { |
17582 SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index)); | 17730 SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index)); |
17583 bool is_old = | 17731 bool is_old = |
17584 info->IsInterpreted() | 17732 info->IsInterpreted() |
17585 ? info->bytecode_array()->IsOld() | 17733 ? info->bytecode_array()->IsOld() |
17586 : info->code()->kind() != Code::FUNCTION || info->code()->IsOld(); | 17734 : info->code()->kind() != Code::FUNCTION || info->code()->IsOld(); |
17587 if (is_old) { | 17735 if (is_old) { |
17588 NoWriteBarrierSet(this, entry_index, the_hole_value); | 17736 for (int i = 0; i < kEntrySize; i++) { |
17589 NoWriteBarrierSet(this, value_index, the_hole_value); | 17737 NoWriteBarrierSet(this, entry_index + i, the_hole_value); |
| 17738 } |
17590 ElementRemoved(); | 17739 ElementRemoved(); |
17591 } | 17740 } |
17592 } | 17741 } |
17593 } | 17742 } |
17594 } | 17743 } |
17595 | 17744 |
17596 | 17745 |
17597 void CompilationCacheTable::Remove(Object* value) { | 17746 void CompilationCacheTable::Remove(Object* value) { |
17598 DisallowHeapAllocation no_allocation; | 17747 DisallowHeapAllocation no_allocation; |
17599 Object* the_hole_value = GetHeap()->the_hole_value(); | 17748 Object* the_hole_value = GetHeap()->the_hole_value(); |
17600 for (int entry = 0, size = Capacity(); entry < size; entry++) { | 17749 for (int entry = 0, size = Capacity(); entry < size; entry++) { |
17601 int entry_index = EntryToIndex(entry); | 17750 int entry_index = EntryToIndex(entry); |
17602 int value_index = entry_index + 1; | 17751 int value_index = entry_index + 1; |
17603 if (get(value_index) == value) { | 17752 if (get(value_index) == value) { |
17604 NoWriteBarrierSet(this, entry_index, the_hole_value); | 17753 for (int i = 0; i < kEntrySize; i++) { |
17605 NoWriteBarrierSet(this, value_index, the_hole_value); | 17754 NoWriteBarrierSet(this, entry_index + i, the_hole_value); |
| 17755 } |
17606 ElementRemoved(); | 17756 ElementRemoved(); |
17607 } | 17757 } |
17608 } | 17758 } |
17609 return; | 17759 return; |
17610 } | 17760 } |
17611 | 17761 |
17612 template <typename Derived, typename Shape, typename Key> | 17762 template <typename Derived, typename Shape, typename Key> |
17613 Handle<Derived> Dictionary<Derived, Shape, Key>::New( | 17763 Handle<Derived> Dictionary<Derived, Shape, Key>::New( |
17614 Isolate* isolate, int at_least_space_for, PretenureFlag pretenure, | 17764 Isolate* isolate, int at_least_space_for, PretenureFlag pretenure, |
17615 MinimumCapacity capacity_option) { | 17765 MinimumCapacity capacity_option) { |
(...skipping 2409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20025 // depend on this. | 20175 // depend on this. |
20026 return DICTIONARY_ELEMENTS; | 20176 return DICTIONARY_ELEMENTS; |
20027 } | 20177 } |
20028 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20178 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
20029 return kind; | 20179 return kind; |
20030 } | 20180 } |
20031 } | 20181 } |
20032 | 20182 |
20033 } // namespace internal | 20183 } // namespace internal |
20034 } // namespace v8 | 20184 } // namespace v8 |
OLD | NEW |