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