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 11990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12001 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 12001 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
12002 // No write barrier required, since the builtin is part of the root set. | 12002 // No write barrier required, since the builtin is part of the root set. |
12003 if (FLAG_mark_shared_functions_for_tier_up) { | 12003 if (FLAG_mark_shared_functions_for_tier_up) { |
12004 // TODO(leszeks): The compilation isn't concurrent if we trigger it using | 12004 // TODO(leszeks): The compilation isn't concurrent if we trigger it using |
12005 // this bit. | 12005 // this bit. |
12006 shared()->set_marked_for_tier_up(true); | 12006 shared()->set_marked_for_tier_up(true); |
12007 } | 12007 } |
12008 } | 12008 } |
12009 | 12009 |
12010 // static | 12010 // static |
| 12011 Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals( |
| 12012 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { |
| 12013 Isolate* isolate = shared->GetIsolate(); |
| 12014 CodeAndLiterals result = |
| 12015 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); |
| 12016 if (result.literals != nullptr) { |
| 12017 DCHECK(shared->feedback_metadata()->is_empty() || |
| 12018 !result.literals->feedback_vector()->is_empty()); |
| 12019 return handle(result.literals, isolate); |
| 12020 } |
| 12021 |
| 12022 Handle<TypeFeedbackVector> feedback_vector = |
| 12023 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); |
| 12024 Handle<LiteralsArray> literals = |
| 12025 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); |
| 12026 Handle<Code> code; |
| 12027 if (result.code != nullptr) { |
| 12028 code = Handle<Code>(result.code, isolate); |
| 12029 } |
| 12030 AddToOptimizedCodeMap(shared, native_context, code, literals, |
| 12031 BailoutId::None()); |
| 12032 return literals; |
| 12033 } |
| 12034 |
| 12035 // static |
12011 void SharedFunctionInfo::AddToOptimizedCodeMap( | 12036 void SharedFunctionInfo::AddToOptimizedCodeMap( |
12012 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 12037 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
12013 Handle<Code> code, BailoutId osr_ast_id) { | 12038 MaybeHandle<Code> code, Handle<LiteralsArray> literals, |
| 12039 BailoutId osr_ast_id) { |
12014 Isolate* isolate = shared->GetIsolate(); | 12040 Isolate* isolate = shared->GetIsolate(); |
12015 if (isolate->serializer_enabled()) return; | 12041 if (isolate->serializer_enabled()) return; |
12016 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 12042 DCHECK(code.is_null() || |
| 12043 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); |
12017 DCHECK(native_context->IsNativeContext()); | 12044 DCHECK(native_context->IsNativeContext()); |
12018 STATIC_ASSERT(kEntryLength == 2); | 12045 STATIC_ASSERT(kEntryLength == 3); |
12019 Handle<FixedArray> new_code_map; | 12046 Handle<FixedArray> new_code_map; |
12020 int entry; | 12047 int entry; |
12021 | 12048 |
12022 if (!osr_ast_id.IsNone()) { | 12049 if (!osr_ast_id.IsNone()) { |
12023 Context::AddToOptimizedCodeMap(native_context, shared, code, osr_ast_id); | 12050 Context::AddToOptimizedCodeMap( |
| 12051 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); |
12024 return; | 12052 return; |
12025 } | 12053 } |
12026 | 12054 |
12027 DCHECK(osr_ast_id.IsNone()); | 12055 DCHECK(osr_ast_id.IsNone()); |
12028 if (shared->OptimizedCodeMapIsCleared()) { | 12056 if (shared->OptimizedCodeMapIsCleared()) { |
12029 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12057 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
12030 entry = kEntriesStart; | 12058 entry = kEntriesStart; |
12031 } else { | 12059 } else { |
12032 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12060 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
12033 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 12061 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
12034 if (entry >= kEntriesStart) { | 12062 if (entry >= kEntriesStart) { |
12035 // Just set the code of the entry. | 12063 // Just set the code and literals of the entry. |
12036 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); | 12064 if (!code.is_null()) { |
12037 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12065 Handle<WeakCell> code_cell = |
| 12066 isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
| 12067 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12068 } |
| 12069 Handle<WeakCell> literals_cell = |
| 12070 isolate->factory()->NewWeakCell(literals); |
| 12071 old_code_map->set(entry + kLiteralsOffset, *literals_cell); |
12038 return; | 12072 return; |
12039 } | 12073 } |
12040 | 12074 |
12041 // Can we reuse an entry? | 12075 // Can we reuse an entry? |
12042 DCHECK(entry < kEntriesStart); | 12076 DCHECK(entry < kEntriesStart); |
12043 int length = old_code_map->length(); | 12077 int length = old_code_map->length(); |
12044 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 12078 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
12045 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { | 12079 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { |
12046 new_code_map = old_code_map; | 12080 new_code_map = old_code_map; |
12047 entry = i; | 12081 entry = i; |
12048 break; | 12082 break; |
12049 } | 12083 } |
12050 } | 12084 } |
12051 | 12085 |
12052 if (entry < kEntriesStart) { | 12086 if (entry < kEntriesStart) { |
12053 // Copy old optimized code map and append one new entry. | 12087 // Copy old optimized code map and append one new entry. |
12054 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( | 12088 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( |
12055 old_code_map, kEntryLength, TENURED); | 12089 old_code_map, kEntryLength, TENURED); |
12056 // TODO(mstarzinger): Temporary workaround. The allocation above might | 12090 // TODO(mstarzinger): Temporary workaround. The allocation above might |
12057 // have flushed the optimized code map and the copy we created is full of | 12091 // have flushed the optimized code map and the copy we created is full of |
12058 // holes. For now we just give up on adding the entry and pretend it got | 12092 // holes. For now we just give up on adding the entry and pretend it got |
12059 // flushed. | 12093 // flushed. |
12060 if (shared->OptimizedCodeMapIsCleared()) return; | 12094 if (shared->OptimizedCodeMapIsCleared()) return; |
12061 entry = old_code_map->length(); | 12095 entry = old_code_map->length(); |
12062 } | 12096 } |
12063 } | 12097 } |
12064 | 12098 |
12065 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); | 12099 Handle<WeakCell> code_cell = |
| 12100 code.is_null() ? isolate->factory()->empty_weak_cell() |
| 12101 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
| 12102 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); |
12066 WeakCell* context_cell = native_context->self_weak_cell(); | 12103 WeakCell* context_cell = native_context->self_weak_cell(); |
12067 | 12104 |
12068 new_code_map->set(entry + kContextOffset, context_cell); | 12105 new_code_map->set(entry + kContextOffset, context_cell); |
12069 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12106 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12107 new_code_map->set(entry + kLiteralsOffset, *literals_cell); |
12070 | 12108 |
12071 #ifdef DEBUG | 12109 #ifdef DEBUG |
12072 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12110 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
12073 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12111 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
12074 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12112 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
12075 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12113 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
12076 DCHECK(cell->cleared() || | 12114 DCHECK(cell->cleared() || |
12077 (cell->value()->IsCode() && | 12115 (cell->value()->IsCode() && |
12078 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12116 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
| 12117 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); |
| 12118 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); |
12079 } | 12119 } |
12080 #endif | 12120 #endif |
12081 | 12121 |
12082 FixedArray* old_code_map = shared->optimized_code_map(); | 12122 FixedArray* old_code_map = shared->optimized_code_map(); |
12083 if (old_code_map != *new_code_map) { | 12123 if (old_code_map != *new_code_map) { |
12084 shared->set_optimized_code_map(*new_code_map); | 12124 shared->set_optimized_code_map(*new_code_map); |
12085 } | 12125 } |
12086 } | 12126 } |
12087 | 12127 |
12088 | 12128 |
(...skipping 17 matching lines...) Expand all Loading... |
12106 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12146 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
12107 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12147 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
12108 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12148 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
12109 optimized_code; | 12149 optimized_code; |
12110 if (found) { | 12150 if (found) { |
12111 if (FLAG_trace_opt) { | 12151 if (FLAG_trace_opt) { |
12112 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12152 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
12113 ShortPrint(); | 12153 ShortPrint(); |
12114 PrintF("]\n"); | 12154 PrintF("]\n"); |
12115 } | 12155 } |
12116 // Just clear the code. | 12156 // Just clear the code in order to continue sharing literals. |
12117 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12157 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
12118 SKIP_WRITE_BARRIER); | 12158 SKIP_WRITE_BARRIER); |
12119 } | 12159 } |
12120 } | 12160 } |
12121 } | 12161 } |
12122 | 12162 |
12123 if (!found) { | 12163 if (!found) { |
12124 // We didn't find the code in here. It must be osr'd code. | 12164 // We didn't find the code in here. It must be osr'd code. |
12125 isolate->EvictOSROptimizedCode(optimized_code, reason); | 12165 isolate->EvictOSROptimizedCode(optimized_code, reason); |
12126 } | 12166 } |
12127 } | 12167 } |
12128 | 12168 |
12129 // static | 12169 // static |
12130 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12170 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
12131 Handle<SharedFunctionInfo> shared(function->shared()); | 12171 Handle<SharedFunctionInfo> shared(function->shared()); |
12132 Handle<Context> native_context(function->context()->native_context()); | 12172 Handle<Context> native_context(function->context()->native_context()); |
12133 Isolate* isolate = shared->GetIsolate(); | 12173 if (function->literals() == |
12134 | 12174 function->GetIsolate()->heap()->empty_literals_array()) { |
12135 if (!function->has_literals_array()) { | 12175 Handle<LiteralsArray> literals = |
12136 if (FLAG_trace_strong_rooted_literals) { | 12176 SharedFunctionInfo::FindOrCreateLiterals(shared, native_context); |
12137 PrintF("EnsureLiterals: Installing literals array in %s %p\n", | 12177 function->set_literals(*literals); |
12138 shared->DebugName()->ToCString().get(), | |
12139 reinterpret_cast<void*>(*function)); | |
12140 } | |
12141 // Top level code didn't get it's literals installed. | |
12142 Handle<TypeFeedbackVector> feedback_vector = | |
12143 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
12144 Handle<LiteralsArray> new_literals = | |
12145 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); | |
12146 function->set_literals(*new_literals); | |
12147 } else if (!function->literals()->has_feedback_vector()) { | |
12148 if (FLAG_trace_strong_rooted_literals) { | |
12149 PrintF("EnsureLiterals: Installing feedback vector in %s %p\n", | |
12150 shared->DebugName()->ToCString().get(), | |
12151 reinterpret_cast<void*>(*function)); | |
12152 } | |
12153 // If the feedback vector hasn't been installed, do that. | |
12154 Handle<TypeFeedbackVector> feedback_vector = TypeFeedbackVector::New( | |
12155 shared->GetIsolate(), handle(shared->feedback_metadata())); | |
12156 function->literals()->set_feedback_vector(*feedback_vector); | |
12157 } else { | |
12158 if (FLAG_trace_strong_rooted_literals) { | |
12159 PrintF("EnsureLiterals: did nothing for %s %p\n", | |
12160 shared->DebugName()->ToCString().get(), | |
12161 reinterpret_cast<void*>(*function)); | |
12162 } | |
12163 } | 12178 } |
12164 | |
12165 // No matter what, ensure some post-conditions. | |
12166 DCHECK(shared->feedback_metadata()->slot_count() != 0 || | |
12167 function->feedback_vector() == | |
12168 shared->GetIsolate()->heap()->empty_type_feedback_vector()); | |
12169 DCHECK(shared->num_literals() == 0 || | |
12170 function->literals() != | |
12171 shared->GetIsolate()->heap()->empty_literals_array()); | |
12172 } | 12179 } |
12173 | 12180 |
12174 static void GetMinInobjectSlack(Map* map, void* data) { | 12181 static void GetMinInobjectSlack(Map* map, void* data) { |
12175 int slack = map->unused_property_fields(); | 12182 int slack = map->unused_property_fields(); |
12176 if (*reinterpret_cast<int*>(data) > slack) { | 12183 if (*reinterpret_cast<int*>(data) > slack) { |
12177 *reinterpret_cast<int*>(data) = slack; | 12184 *reinterpret_cast<int*>(data) = slack; |
12178 } | 12185 } |
12179 } | 12186 } |
12180 | 12187 |
12181 | 12188 |
(...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13740 FixedArray* optimized_code_map = this->optimized_code_map(); | 13747 FixedArray* optimized_code_map = this->optimized_code_map(); |
13741 int length = optimized_code_map->length(); | 13748 int length = optimized_code_map->length(); |
13742 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 13749 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
13743 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 13750 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
13744 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 13751 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
13745 SKIP_WRITE_BARRIER); | 13752 SKIP_WRITE_BARRIER); |
13746 } | 13753 } |
13747 } | 13754 } |
13748 } | 13755 } |
13749 | 13756 |
13750 Code* SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, | 13757 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
13751 BailoutId osr_ast_id) { | 13758 Context* native_context, BailoutId osr_ast_id) { |
13752 Code* result = nullptr; | 13759 CodeAndLiterals result = {nullptr, nullptr}; |
13753 if (!osr_ast_id.IsNone()) { | 13760 if (!osr_ast_id.IsNone()) { |
13754 return native_context->SearchOptimizedCodeMap(this, osr_ast_id); | 13761 Code* code; |
| 13762 LiteralsArray* literals; |
| 13763 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); |
| 13764 result = {code, literals}; |
| 13765 return result; |
13755 } | 13766 } |
13756 | 13767 |
13757 DCHECK(osr_ast_id.IsNone()); | 13768 DCHECK(osr_ast_id.IsNone()); |
13758 int entry = SearchOptimizedCodeMapEntry(native_context); | 13769 int entry = SearchOptimizedCodeMapEntry(native_context); |
13759 if (entry != kNotFound) { | 13770 if (entry != kNotFound) { |
13760 FixedArray* code_map = optimized_code_map(); | 13771 FixedArray* code_map = optimized_code_map(); |
13761 DCHECK_LE(entry + kEntryLength, code_map->length()); | 13772 DCHECK_LE(entry + kEntryLength, code_map->length()); |
13762 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 13773 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
| 13774 WeakCell* literals_cell = |
| 13775 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); |
13763 | 13776 |
13764 result = cell->cleared() ? nullptr : Code::cast(cell->value()); | 13777 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), |
| 13778 literals_cell->cleared() ? nullptr : LiteralsArray::cast( |
| 13779 literals_cell->value())}; |
13765 } | 13780 } |
13766 return result; | 13781 return result; |
13767 } | 13782 } |
13768 | 13783 |
13769 | 13784 |
13770 #define DECLARE_TAG(ignore1, name, ignore2) name, | 13785 #define DECLARE_TAG(ignore1, name, ignore2) name, |
13771 const char* const VisitorSynchronization::kTags[ | 13786 const char* const VisitorSynchronization::kTags[ |
13772 VisitorSynchronization::kNumberOfSyncTags] = { | 13787 VisitorSynchronization::kNumberOfSyncTags] = { |
13773 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 13788 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
13774 }; | 13789 }; |
(...skipping 6235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20010 // depend on this. | 20025 // depend on this. |
20011 return DICTIONARY_ELEMENTS; | 20026 return DICTIONARY_ELEMENTS; |
20012 } | 20027 } |
20013 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20028 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
20014 return kind; | 20029 return kind; |
20015 } | 20030 } |
20016 } | 20031 } |
20017 | 20032 |
20018 } // namespace internal | 20033 } // namespace internal |
20019 } // namespace v8 | 20034 } // namespace v8 |
OLD | NEW |