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 11930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11941 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 11941 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
11942 // No write barrier required, since the builtin is part of the root set. | 11942 // No write barrier required, since the builtin is part of the root set. |
11943 if (FLAG_mark_shared_functions_for_tier_up) { | 11943 if (FLAG_mark_shared_functions_for_tier_up) { |
11944 // TODO(leszeks): The compilation isn't concurrent if we trigger it using | 11944 // TODO(leszeks): The compilation isn't concurrent if we trigger it using |
11945 // this bit. | 11945 // this bit. |
11946 shared()->set_marked_for_tier_up(true); | 11946 shared()->set_marked_for_tier_up(true); |
11947 } | 11947 } |
11948 } | 11948 } |
11949 | 11949 |
11950 // static | 11950 // static |
11951 Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals( | |
11952 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { | |
11953 Isolate* isolate = shared->GetIsolate(); | |
11954 CodeAndLiterals result = | |
11955 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); | |
11956 if (result.literals != nullptr) { | |
11957 DCHECK(shared->feedback_metadata()->is_empty() || | |
11958 !result.literals->feedback_vector()->is_empty()); | |
11959 return handle(result.literals, isolate); | |
11960 } | |
11961 | |
11962 Handle<TypeFeedbackVector> feedback_vector = | |
11963 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
11964 Handle<LiteralsArray> literals = | |
11965 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); | |
11966 Handle<Code> code; | |
11967 if (result.code != nullptr) { | |
11968 code = Handle<Code>(result.code, isolate); | |
11969 } | |
11970 AddToOptimizedCodeMap(shared, native_context, code, literals, | |
11971 BailoutId::None()); | |
11972 return literals; | |
11973 } | |
11974 | |
11975 // static | |
11976 void SharedFunctionInfo::AddToOptimizedCodeMap( | 11951 void SharedFunctionInfo::AddToOptimizedCodeMap( |
11977 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 11952 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
11978 MaybeHandle<Code> code, Handle<LiteralsArray> literals, | 11953 Handle<Code> code, BailoutId osr_ast_id) { |
11979 BailoutId osr_ast_id) { | |
11980 Isolate* isolate = shared->GetIsolate(); | 11954 Isolate* isolate = shared->GetIsolate(); |
11981 if (isolate->serializer_enabled()) return; | 11955 if (isolate->serializer_enabled()) return; |
11982 DCHECK(code.is_null() || | 11956 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
11983 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | |
11984 DCHECK(native_context->IsNativeContext()); | 11957 DCHECK(native_context->IsNativeContext()); |
11985 STATIC_ASSERT(kEntryLength == 3); | 11958 STATIC_ASSERT(kEntryLength == 2); |
11986 Handle<FixedArray> new_code_map; | 11959 Handle<FixedArray> new_code_map; |
11987 int entry; | 11960 int entry; |
11988 | 11961 |
11989 if (!osr_ast_id.IsNone()) { | 11962 if (!osr_ast_id.IsNone()) { |
11990 Context::AddToOptimizedCodeMap( | 11963 Context::AddToOptimizedCodeMap(native_context, shared, code, osr_ast_id); |
11991 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); | |
11992 return; | 11964 return; |
11993 } | 11965 } |
11994 | 11966 |
11995 DCHECK(osr_ast_id.IsNone()); | 11967 DCHECK(osr_ast_id.IsNone()); |
11996 if (shared->OptimizedCodeMapIsCleared()) { | 11968 if (shared->OptimizedCodeMapIsCleared()) { |
11997 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 11969 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
11998 entry = kEntriesStart; | 11970 entry = kEntriesStart; |
11999 } else { | 11971 } else { |
12000 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 11972 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
12001 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 11973 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
12002 if (entry >= kEntriesStart) { | 11974 if (entry >= kEntriesStart) { |
12003 // Just set the code and literals of the entry. | 11975 // Just set the code of the entry. |
12004 if (!code.is_null()) { | 11976 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); |
12005 Handle<WeakCell> code_cell = | 11977 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12006 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | |
12007 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | |
12008 } | |
12009 Handle<WeakCell> literals_cell = | |
12010 isolate->factory()->NewWeakCell(literals); | |
12011 old_code_map->set(entry + kLiteralsOffset, *literals_cell); | |
12012 return; | 11978 return; |
12013 } | 11979 } |
12014 | 11980 |
12015 // Can we reuse an entry? | 11981 // Can we reuse an entry? |
12016 DCHECK(entry < kEntriesStart); | 11982 DCHECK(entry < kEntriesStart); |
12017 int length = old_code_map->length(); | 11983 int length = old_code_map->length(); |
12018 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 11984 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
12019 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { | 11985 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { |
12020 new_code_map = old_code_map; | 11986 new_code_map = old_code_map; |
12021 entry = i; | 11987 entry = i; |
12022 break; | 11988 break; |
12023 } | 11989 } |
12024 } | 11990 } |
12025 | 11991 |
12026 if (entry < kEntriesStart) { | 11992 if (entry < kEntriesStart) { |
12027 // Copy old optimized code map and append one new entry. | 11993 // Copy old optimized code map and append one new entry. |
12028 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( | 11994 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( |
12029 old_code_map, kEntryLength, TENURED); | 11995 old_code_map, kEntryLength, TENURED); |
12030 // TODO(mstarzinger): Temporary workaround. The allocation above might | 11996 // TODO(mstarzinger): Temporary workaround. The allocation above might |
12031 // have flushed the optimized code map and the copy we created is full of | 11997 // have flushed the optimized code map and the copy we created is full of |
12032 // holes. For now we just give up on adding the entry and pretend it got | 11998 // holes. For now we just give up on adding the entry and pretend it got |
12033 // flushed. | 11999 // flushed. |
12034 if (shared->OptimizedCodeMapIsCleared()) return; | 12000 if (shared->OptimizedCodeMapIsCleared()) return; |
12035 entry = old_code_map->length(); | 12001 entry = old_code_map->length(); |
12036 } | 12002 } |
12037 } | 12003 } |
12038 | 12004 |
12039 Handle<WeakCell> code_cell = | 12005 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); |
12040 code.is_null() ? isolate->factory()->empty_weak_cell() | |
12041 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | |
12042 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | |
12043 WeakCell* context_cell = native_context->self_weak_cell(); | 12006 WeakCell* context_cell = native_context->self_weak_cell(); |
12044 | 12007 |
12045 new_code_map->set(entry + kContextOffset, context_cell); | 12008 new_code_map->set(entry + kContextOffset, context_cell); |
12046 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12009 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12047 new_code_map->set(entry + kLiteralsOffset, *literals_cell); | |
12048 | 12010 |
12049 #ifdef DEBUG | 12011 #ifdef DEBUG |
12050 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12012 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
12051 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12013 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
12052 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12014 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
12053 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12015 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
12054 DCHECK(cell->cleared() || | 12016 DCHECK(cell->cleared() || |
12055 (cell->value()->IsCode() && | 12017 (cell->value()->IsCode() && |
12056 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12018 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
12057 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); | |
12058 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | |
12059 } | 12019 } |
12060 #endif | 12020 #endif |
12061 | 12021 |
12062 FixedArray* old_code_map = shared->optimized_code_map(); | 12022 FixedArray* old_code_map = shared->optimized_code_map(); |
12063 if (old_code_map != *new_code_map) { | 12023 if (old_code_map != *new_code_map) { |
12064 shared->set_optimized_code_map(*new_code_map); | 12024 shared->set_optimized_code_map(*new_code_map); |
12065 } | 12025 } |
12066 } | 12026 } |
12067 | 12027 |
12068 | 12028 |
(...skipping 17 matching lines...) Expand all Loading... |
12086 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12046 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
12087 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12047 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
12088 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12048 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
12089 optimized_code; | 12049 optimized_code; |
12090 if (found) { | 12050 if (found) { |
12091 if (FLAG_trace_opt) { | 12051 if (FLAG_trace_opt) { |
12092 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12052 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
12093 ShortPrint(); | 12053 ShortPrint(); |
12094 PrintF("]\n"); | 12054 PrintF("]\n"); |
12095 } | 12055 } |
12096 // Just clear the code in order to continue sharing literals. | 12056 // Just clear the code. |
12097 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12057 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
12098 SKIP_WRITE_BARRIER); | 12058 SKIP_WRITE_BARRIER); |
12099 } | 12059 } |
12100 } | 12060 } |
12101 } | 12061 } |
12102 | 12062 |
12103 if (!found) { | 12063 if (!found) { |
12104 // We didn't find the code in here. It must be osr'd code. | 12064 // We didn't find the code in here. It must be osr'd code. |
12105 isolate->EvictOSROptimizedCode(optimized_code, reason); | 12065 isolate->EvictOSROptimizedCode(optimized_code, reason); |
12106 } | 12066 } |
12107 } | 12067 } |
12108 | 12068 |
12109 // static | 12069 // static |
12110 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12070 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
12111 Handle<SharedFunctionInfo> shared(function->shared()); | 12071 Handle<SharedFunctionInfo> shared(function->shared()); |
12112 Handle<Context> native_context(function->context()->native_context()); | 12072 Handle<Context> native_context(function->context()->native_context()); |
12113 if (function->literals() == | 12073 Isolate* isolate = shared->GetIsolate(); |
12114 function->GetIsolate()->heap()->empty_literals_array()) { | 12074 |
12115 Handle<LiteralsArray> literals = | 12075 if (!function->has_literals_array()) { |
12116 SharedFunctionInfo::FindOrCreateLiterals(shared, native_context); | 12076 if (FLAG_trace_strong_rooted_literals) { |
12117 function->set_literals(*literals); | 12077 PrintF("EnsureLiterals: Installing literals array in %s %p\n", |
| 12078 shared->DebugName()->ToCString().get(), |
| 12079 reinterpret_cast<void*>(*function)); |
| 12080 } |
| 12081 // Top level code didn't get it's literals installed. |
| 12082 Handle<TypeFeedbackVector> feedback_vector = |
| 12083 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); |
| 12084 Handle<LiteralsArray> new_literals = |
| 12085 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); |
| 12086 function->set_literals(*new_literals); |
| 12087 } else if (!function->literals()->has_feedback_vector()) { |
| 12088 if (FLAG_trace_strong_rooted_literals) { |
| 12089 PrintF("EnsureLiterals: Installing feedback vector in %s %p\n", |
| 12090 shared->DebugName()->ToCString().get(), |
| 12091 reinterpret_cast<void*>(*function)); |
| 12092 } |
| 12093 // If the feedback vector hasn't been installed, do that. |
| 12094 Handle<TypeFeedbackVector> feedback_vector = TypeFeedbackVector::New( |
| 12095 shared->GetIsolate(), handle(shared->feedback_metadata())); |
| 12096 function->literals()->set_feedback_vector(*feedback_vector); |
| 12097 } else { |
| 12098 if (FLAG_trace_strong_rooted_literals) { |
| 12099 PrintF("EnsureLiterals: did nothing for %s %p\n", |
| 12100 shared->DebugName()->ToCString().get(), |
| 12101 reinterpret_cast<void*>(*function)); |
| 12102 } |
12118 } | 12103 } |
| 12104 |
| 12105 // No matter what, ensure some post-conditions. |
| 12106 DCHECK(shared->feedback_metadata()->slot_count() != 0 || |
| 12107 function->feedback_vector() == |
| 12108 shared->GetIsolate()->heap()->empty_type_feedback_vector()); |
| 12109 DCHECK(shared->num_literals() == 0 || |
| 12110 function->literals() != |
| 12111 shared->GetIsolate()->heap()->empty_literals_array()); |
12119 } | 12112 } |
12120 | 12113 |
12121 static void GetMinInobjectSlack(Map* map, void* data) { | 12114 static void GetMinInobjectSlack(Map* map, void* data) { |
12122 int slack = map->unused_property_fields(); | 12115 int slack = map->unused_property_fields(); |
12123 if (*reinterpret_cast<int*>(data) > slack) { | 12116 if (*reinterpret_cast<int*>(data) > slack) { |
12124 *reinterpret_cast<int*>(data) = slack; | 12117 *reinterpret_cast<int*>(data) = slack; |
12125 } | 12118 } |
12126 } | 12119 } |
12127 | 12120 |
12128 | 12121 |
(...skipping 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13678 FixedArray* optimized_code_map = this->optimized_code_map(); | 13671 FixedArray* optimized_code_map = this->optimized_code_map(); |
13679 int length = optimized_code_map->length(); | 13672 int length = optimized_code_map->length(); |
13680 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 13673 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
13681 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 13674 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
13682 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 13675 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
13683 SKIP_WRITE_BARRIER); | 13676 SKIP_WRITE_BARRIER); |
13684 } | 13677 } |
13685 } | 13678 } |
13686 } | 13679 } |
13687 | 13680 |
13688 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 13681 Code* SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
13689 Context* native_context, BailoutId osr_ast_id) { | 13682 BailoutId osr_ast_id) { |
13690 CodeAndLiterals result = {nullptr, nullptr}; | 13683 Code* result = nullptr; |
13691 if (!osr_ast_id.IsNone()) { | 13684 if (!osr_ast_id.IsNone()) { |
13692 Code* code; | 13685 return native_context->SearchOptimizedCodeMap(this, osr_ast_id); |
13693 LiteralsArray* literals; | |
13694 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); | |
13695 result = {code, literals}; | |
13696 return result; | |
13697 } | 13686 } |
13698 | 13687 |
13699 DCHECK(osr_ast_id.IsNone()); | 13688 DCHECK(osr_ast_id.IsNone()); |
13700 int entry = SearchOptimizedCodeMapEntry(native_context); | 13689 int entry = SearchOptimizedCodeMapEntry(native_context); |
13701 if (entry != kNotFound) { | 13690 if (entry != kNotFound) { |
13702 FixedArray* code_map = optimized_code_map(); | 13691 FixedArray* code_map = optimized_code_map(); |
13703 DCHECK_LE(entry + kEntryLength, code_map->length()); | 13692 DCHECK_LE(entry + kEntryLength, code_map->length()); |
13704 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 13693 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
13705 WeakCell* literals_cell = | |
13706 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); | |
13707 | 13694 |
13708 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | 13695 result = cell->cleared() ? nullptr : Code::cast(cell->value()); |
13709 literals_cell->cleared() ? nullptr : LiteralsArray::cast( | |
13710 literals_cell->value())}; | |
13711 } | 13696 } |
13712 return result; | 13697 return result; |
13713 } | 13698 } |
13714 | 13699 |
13715 | 13700 |
13716 #define DECLARE_TAG(ignore1, name, ignore2) name, | 13701 #define DECLARE_TAG(ignore1, name, ignore2) name, |
13717 const char* const VisitorSynchronization::kTags[ | 13702 const char* const VisitorSynchronization::kTags[ |
13718 VisitorSynchronization::kNumberOfSyncTags] = { | 13703 VisitorSynchronization::kNumberOfSyncTags] = { |
13719 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 13704 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
13720 }; | 13705 }; |
(...skipping 6232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19953 // depend on this. | 19938 // depend on this. |
19954 return DICTIONARY_ELEMENTS; | 19939 return DICTIONARY_ELEMENTS; |
19955 } | 19940 } |
19956 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 19941 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
19957 return kind; | 19942 return kind; |
19958 } | 19943 } |
19959 } | 19944 } |
19960 | 19945 |
19961 } // namespace internal | 19946 } // namespace internal |
19962 } // namespace v8 | 19947 } // namespace v8 |
OLD | NEW |