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