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 10245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10256 } | 10256 } |
10257 | 10257 |
10258 SharedFunctionInfo* DeoptimizationInputData::GetInlinedFunction(int index) { | 10258 SharedFunctionInfo* DeoptimizationInputData::GetInlinedFunction(int index) { |
10259 if (index == -1) { | 10259 if (index == -1) { |
10260 return SharedFunctionInfo::cast(SharedFunctionInfo()); | 10260 return SharedFunctionInfo::cast(SharedFunctionInfo()); |
10261 } else { | 10261 } else { |
10262 return SharedFunctionInfo::cast(LiteralArray()->get(index)); | 10262 return SharedFunctionInfo::cast(LiteralArray()->get(index)); |
10263 } | 10263 } |
10264 } | 10264 } |
10265 | 10265 |
10266 const int LiteralsArray::kFeedbackVectorOffset = | |
10267 LiteralsArray::OffsetOfElementAt(LiteralsArray::kVectorIndex); | |
10268 | |
10269 const int LiteralsArray::kOffsetToFirstLiteral = | |
10270 LiteralsArray::OffsetOfElementAt(LiteralsArray::kFirstLiteralIndex); | |
10271 | |
10272 // static | |
10273 Handle<LiteralsArray> LiteralsArray::New(Isolate* isolate, | |
10274 Handle<TypeFeedbackVector> vector, | |
10275 int number_of_literals, | |
10276 PretenureFlag pretenure) { | |
10277 if (vector->is_empty() && number_of_literals == 0) { | |
10278 return Handle<LiteralsArray>::cast( | |
10279 isolate->factory()->empty_literals_array()); | |
10280 } | |
10281 Handle<FixedArray> literals = isolate->factory()->NewFixedArray( | |
10282 number_of_literals + kFirstLiteralIndex, pretenure); | |
10283 Handle<LiteralsArray> casted_literals = Handle<LiteralsArray>::cast(literals); | |
10284 casted_literals->set_feedback_vector(*vector); | |
10285 return casted_literals; | |
10286 } | |
10287 | |
10288 int HandlerTable::LookupRange(int pc_offset, int* data_out, | 10266 int HandlerTable::LookupRange(int pc_offset, int* data_out, |
10289 CatchPrediction* prediction_out) { | 10267 CatchPrediction* prediction_out) { |
10290 int innermost_handler = -1; | 10268 int innermost_handler = -1; |
10291 #ifdef DEBUG | 10269 #ifdef DEBUG |
10292 // Assuming that ranges are well nested, we don't need to track the innermost | 10270 // Assuming that ranges are well nested, we don't need to track the innermost |
10293 // offsets. This is just to verify that the table is actually well nested. | 10271 // offsets. This is just to verify that the table is actually well nested. |
10294 int innermost_start = std::numeric_limits<int>::min(); | 10272 int innermost_start = std::numeric_limits<int>::min(); |
10295 int innermost_end = std::numeric_limits<int>::max(); | 10273 int innermost_end = std::numeric_limits<int>::max(); |
10296 #endif | 10274 #endif |
10297 for (int i = 0; i < length(); i += kRangeEntrySize) { | 10275 for (int i = 0; i < length(); i += kRangeEntrySize) { |
(...skipping 1704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12002 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 11980 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
12003 // 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. |
12004 if (FLAG_mark_shared_functions_for_tier_up) { | 11982 if (FLAG_mark_shared_functions_for_tier_up) { |
12005 // 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 |
12006 // this bit. | 11984 // this bit. |
12007 shared()->set_marked_for_tier_up(true); | 11985 shared()->set_marked_for_tier_up(true); |
12008 } | 11986 } |
12009 } | 11987 } |
12010 | 11988 |
12011 // static | 11989 // static |
12012 Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals( | 11990 Handle<TypeFeedbackVector> SharedFunctionInfo::FindOrCreateVector( |
12013 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { | 11991 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { |
12014 Isolate* isolate = shared->GetIsolate(); | 11992 Isolate* isolate = shared->GetIsolate(); |
12015 CodeAndLiterals result = | 11993 CodeAndVector result = |
12016 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); | 11994 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); |
12017 if (result.literals != nullptr) { | 11995 if (result.vector != nullptr) { |
12018 DCHECK(shared->feedback_metadata()->is_empty() || | 11996 DCHECK(shared->feedback_metadata()->is_empty() || |
12019 !result.literals->feedback_vector()->is_empty()); | 11997 !result.vector->is_empty()); |
12020 return handle(result.literals, isolate); | 11998 return handle(result.vector, isolate); |
12021 } | 11999 } |
12022 | 12000 |
12023 Handle<TypeFeedbackVector> feedback_vector = | 12001 Handle<TypeFeedbackVector> vector = |
12024 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | 12002 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); |
12025 Handle<LiteralsArray> literals = | |
12026 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); | |
12027 Handle<Code> code; | 12003 Handle<Code> code; |
12028 if (result.code != nullptr) { | 12004 if (result.code != nullptr) { |
12029 code = Handle<Code>(result.code, isolate); | 12005 code = Handle<Code>(result.code, isolate); |
12030 } | 12006 } |
12031 AddToOptimizedCodeMap(shared, native_context, code, literals, | 12007 AddToOptimizedCodeMap(shared, native_context, code, vector, |
12032 BailoutId::None()); | 12008 BailoutId::None()); |
12033 return literals; | 12009 return vector; |
12034 } | 12010 } |
12035 | 12011 |
12036 // static | 12012 // static |
12037 void SharedFunctionInfo::AddToOptimizedCodeMap( | 12013 void SharedFunctionInfo::AddToOptimizedCodeMap( |
12038 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 12014 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
12039 MaybeHandle<Code> code, Handle<LiteralsArray> literals, | 12015 MaybeHandle<Code> code, Handle<TypeFeedbackVector> vector, |
12040 BailoutId osr_ast_id) { | 12016 BailoutId osr_ast_id) { |
12041 Isolate* isolate = shared->GetIsolate(); | 12017 Isolate* isolate = shared->GetIsolate(); |
12042 if (isolate->serializer_enabled()) return; | 12018 if (isolate->serializer_enabled()) return; |
12043 DCHECK(code.is_null() || | 12019 DCHECK(code.is_null() || |
12044 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | 12020 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); |
12045 DCHECK(native_context->IsNativeContext()); | 12021 DCHECK(native_context->IsNativeContext()); |
12046 STATIC_ASSERT(kEntryLength == 3); | 12022 STATIC_ASSERT(kEntryLength == 3); |
12047 Handle<FixedArray> new_code_map; | 12023 Handle<FixedArray> new_code_map; |
12048 int entry; | 12024 int entry; |
12049 | 12025 |
12050 if (!osr_ast_id.IsNone()) { | 12026 if (!osr_ast_id.IsNone()) { |
12051 Context::AddToOptimizedCodeMap( | 12027 Context::AddToOptimizedCodeMap(native_context, shared, |
12052 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); | 12028 code.ToHandleChecked(), vector, osr_ast_id); |
12053 return; | 12029 return; |
12054 } | 12030 } |
12055 | 12031 |
12056 DCHECK(osr_ast_id.IsNone()); | 12032 DCHECK(osr_ast_id.IsNone()); |
12057 if (shared->OptimizedCodeMapIsCleared()) { | 12033 if (shared->OptimizedCodeMapIsCleared()) { |
12058 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12034 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
12059 entry = kEntriesStart; | 12035 entry = kEntriesStart; |
12060 } else { | 12036 } else { |
12061 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12037 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
12062 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 12038 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
12063 if (entry >= kEntriesStart) { | 12039 if (entry >= kEntriesStart) { |
12064 // Just set the code and literals of the entry. | 12040 // Just set the code and vector of the entry. |
12065 if (!code.is_null()) { | 12041 if (!code.is_null()) { |
12066 Handle<WeakCell> code_cell = | 12042 Handle<WeakCell> code_cell = |
12067 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12043 isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
12068 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12044 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12069 } | 12045 } |
12070 Handle<WeakCell> literals_cell = | 12046 Handle<WeakCell> vector_cell = isolate->factory()->NewWeakCell(vector); |
12071 isolate->factory()->NewWeakCell(literals); | 12047 old_code_map->set(entry + kFeedbackVectorOffset, *vector_cell); |
12072 old_code_map->set(entry + kLiteralsOffset, *literals_cell); | |
12073 return; | 12048 return; |
12074 } | 12049 } |
12075 | 12050 |
12076 // Can we reuse an entry? | 12051 // Can we reuse an entry? |
12077 DCHECK(entry < kEntriesStart); | 12052 DCHECK(entry < kEntriesStart); |
12078 int length = old_code_map->length(); | 12053 int length = old_code_map->length(); |
12079 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 12054 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
12080 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { | 12055 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { |
12081 new_code_map = old_code_map; | 12056 new_code_map = old_code_map; |
12082 entry = i; | 12057 entry = i; |
(...skipping 10 matching lines...) Expand all Loading... |
12093 // holes. For now we just give up on adding the entry and pretend it got | 12068 // holes. For now we just give up on adding the entry and pretend it got |
12094 // flushed. | 12069 // flushed. |
12095 if (shared->OptimizedCodeMapIsCleared()) return; | 12070 if (shared->OptimizedCodeMapIsCleared()) return; |
12096 entry = old_code_map->length(); | 12071 entry = old_code_map->length(); |
12097 } | 12072 } |
12098 } | 12073 } |
12099 | 12074 |
12100 Handle<WeakCell> code_cell = | 12075 Handle<WeakCell> code_cell = |
12101 code.is_null() ? isolate->factory()->empty_weak_cell() | 12076 code.is_null() ? isolate->factory()->empty_weak_cell() |
12102 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12077 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
12103 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | 12078 Handle<WeakCell> vector_cell = isolate->factory()->NewWeakCell(vector); |
12104 WeakCell* context_cell = native_context->self_weak_cell(); | 12079 WeakCell* context_cell = native_context->self_weak_cell(); |
12105 | 12080 |
12106 new_code_map->set(entry + kContextOffset, context_cell); | 12081 new_code_map->set(entry + kContextOffset, context_cell); |
12107 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12082 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12108 new_code_map->set(entry + kLiteralsOffset, *literals_cell); | 12083 new_code_map->set(entry + kFeedbackVectorOffset, *vector_cell); |
12109 | 12084 |
12110 #ifdef DEBUG | 12085 #ifdef DEBUG |
12111 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12086 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
12112 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12087 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
12113 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12088 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
12114 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12089 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
12115 DCHECK(cell->cleared() || | 12090 DCHECK(cell->cleared() || |
12116 (cell->value()->IsCode() && | 12091 (cell->value()->IsCode() && |
12117 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12092 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
12118 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); | 12093 cell = WeakCell::cast(new_code_map->get(i + kFeedbackVectorOffset)); |
12119 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | 12094 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); |
12120 } | 12095 } |
12121 #endif | 12096 #endif |
12122 | 12097 |
12123 FixedArray* old_code_map = shared->optimized_code_map(); | 12098 FixedArray* old_code_map = shared->optimized_code_map(); |
12124 if (old_code_map != *new_code_map) { | 12099 if (old_code_map != *new_code_map) { |
12125 shared->set_optimized_code_map(*new_code_map); | 12100 shared->set_optimized_code_map(*new_code_map); |
12126 } | 12101 } |
12127 } | 12102 } |
12128 | 12103 |
(...skipping 18 matching lines...) Expand all Loading... |
12147 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12122 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
12148 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12123 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
12149 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12124 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
12150 optimized_code; | 12125 optimized_code; |
12151 if (found) { | 12126 if (found) { |
12152 if (FLAG_trace_opt) { | 12127 if (FLAG_trace_opt) { |
12153 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12128 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
12154 ShortPrint(); | 12129 ShortPrint(); |
12155 PrintF("]\n"); | 12130 PrintF("]\n"); |
12156 } | 12131 } |
12157 // Just clear the code in order to continue sharing literals. | 12132 // Just clear the code in order to continue sharing a feedback vector. |
12158 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12133 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
12159 SKIP_WRITE_BARRIER); | 12134 SKIP_WRITE_BARRIER); |
12160 } | 12135 } |
12161 } | 12136 } |
12162 } | 12137 } |
12163 | 12138 |
12164 if (!found) { | 12139 if (!found) { |
12165 // We didn't find the code in here. It must be osr'd code. | 12140 // We didn't find the code in here. It must be osr'd code. |
12166 isolate->EvictOSROptimizedCode(optimized_code, reason); | 12141 isolate->EvictOSROptimizedCode(optimized_code, reason); |
12167 } | 12142 } |
12168 } | 12143 } |
12169 | 12144 |
12170 // static | 12145 // static |
12171 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12146 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
12172 Handle<SharedFunctionInfo> shared(function->shared()); | 12147 Handle<SharedFunctionInfo> shared(function->shared()); |
12173 Handle<Context> native_context(function->context()->native_context()); | 12148 Handle<Context> native_context(function->context()->native_context()); |
12174 if (function->literals() == | 12149 if (function->feedback_vector() == |
12175 function->GetIsolate()->heap()->empty_literals_array()) { | 12150 function->GetIsolate()->heap()->empty_type_feedback_vector()) { |
12176 Handle<LiteralsArray> literals = | 12151 Handle<TypeFeedbackVector> vector = |
12177 SharedFunctionInfo::FindOrCreateLiterals(shared, native_context); | 12152 SharedFunctionInfo::FindOrCreateVector(shared, native_context); |
12178 function->set_literals(*literals); | 12153 function->set_feedback_vector(*vector); |
12179 } | 12154 } |
12180 } | 12155 } |
12181 | 12156 |
12182 static void GetMinInobjectSlack(Map* map, void* data) { | 12157 static void GetMinInobjectSlack(Map* map, void* data) { |
12183 int slack = map->unused_property_fields(); | 12158 int slack = map->unused_property_fields(); |
12184 if (*reinterpret_cast<int*>(data) > slack) { | 12159 if (*reinterpret_cast<int*>(data) > slack) { |
12185 *reinterpret_cast<int*>(data) = slack; | 12160 *reinterpret_cast<int*>(data) = slack; |
12186 } | 12161 } |
12187 } | 12162 } |
12188 | 12163 |
(...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13748 FixedArray* optimized_code_map = this->optimized_code_map(); | 13723 FixedArray* optimized_code_map = this->optimized_code_map(); |
13749 int length = optimized_code_map->length(); | 13724 int length = optimized_code_map->length(); |
13750 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 13725 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
13751 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 13726 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
13752 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 13727 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
13753 SKIP_WRITE_BARRIER); | 13728 SKIP_WRITE_BARRIER); |
13754 } | 13729 } |
13755 } | 13730 } |
13756 } | 13731 } |
13757 | 13732 |
13758 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 13733 CodeAndVector SharedFunctionInfo::SearchOptimizedCodeMap( |
13759 Context* native_context, BailoutId osr_ast_id) { | 13734 Context* native_context, BailoutId osr_ast_id) { |
13760 CodeAndLiterals result = {nullptr, nullptr}; | 13735 CodeAndVector result = {nullptr, nullptr}; |
13761 if (!osr_ast_id.IsNone()) { | 13736 if (!osr_ast_id.IsNone()) { |
13762 Code* code; | 13737 Code* code; |
13763 LiteralsArray* literals; | 13738 TypeFeedbackVector* vector; |
13764 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); | 13739 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &vector); |
13765 result = {code, literals}; | 13740 result = {code, vector}; |
13766 return result; | 13741 return result; |
13767 } | 13742 } |
13768 | 13743 |
13769 DCHECK(osr_ast_id.IsNone()); | 13744 DCHECK(osr_ast_id.IsNone()); |
13770 int entry = SearchOptimizedCodeMapEntry(native_context); | 13745 int entry = SearchOptimizedCodeMapEntry(native_context); |
13771 if (entry != kNotFound) { | 13746 if (entry != kNotFound) { |
13772 FixedArray* code_map = optimized_code_map(); | 13747 FixedArray* code_map = optimized_code_map(); |
13773 DCHECK_LE(entry + kEntryLength, code_map->length()); | 13748 DCHECK_LE(entry + kEntryLength, code_map->length()); |
13774 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 13749 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
13775 WeakCell* literals_cell = | 13750 WeakCell* vector_cell = |
13776 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); | 13751 WeakCell::cast(code_map->get(entry + kFeedbackVectorOffset)); |
13777 | 13752 |
13778 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | 13753 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), |
13779 literals_cell->cleared() ? nullptr : LiteralsArray::cast( | 13754 vector_cell->cleared() ? nullptr : TypeFeedbackVector::cast( |
13780 literals_cell->value())}; | 13755 vector_cell->value())}; |
13781 } | 13756 } |
13782 return result; | 13757 return result; |
13783 } | 13758 } |
13784 | 13759 |
13785 | 13760 |
13786 #define DECLARE_TAG(ignore1, name, ignore2) name, | 13761 #define DECLARE_TAG(ignore1, name, ignore2) name, |
13787 const char* const VisitorSynchronization::kTags[ | 13762 const char* const VisitorSynchronization::kTags[ |
13788 VisitorSynchronization::kNumberOfSyncTags] = { | 13763 VisitorSynchronization::kNumberOfSyncTags] = { |
13789 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 13764 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
13790 }; | 13765 }; |
(...skipping 6235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20026 // depend on this. | 20001 // depend on this. |
20027 return DICTIONARY_ELEMENTS; | 20002 return DICTIONARY_ELEMENTS; |
20028 } | 20003 } |
20029 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20004 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
20030 return kind; | 20005 return kind; |
20031 } | 20006 } |
20032 } | 20007 } |
20033 | 20008 |
20034 } // namespace internal | 20009 } // namespace internal |
20035 } // namespace v8 | 20010 } // namespace v8 |
OLD | NEW |