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 12366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12377 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 12377 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
12378 // No write barrier required, since the builtin is part of the root set. | 12378 // No write barrier required, since the builtin is part of the root set. |
12379 if (FLAG_mark_shared_functions_for_tier_up) { | 12379 if (FLAG_mark_shared_functions_for_tier_up) { |
12380 // TODO(leszeks): The compilation isn't concurrent if we trigger it using | 12380 // TODO(leszeks): The compilation isn't concurrent if we trigger it using |
12381 // this bit. | 12381 // this bit. |
12382 shared()->set_marked_for_tier_up(true); | 12382 shared()->set_marked_for_tier_up(true); |
12383 } | 12383 } |
12384 } | 12384 } |
12385 | 12385 |
12386 // static | 12386 // static |
| 12387 Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals( |
| 12388 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { |
| 12389 Isolate* isolate = shared->GetIsolate(); |
| 12390 CodeAndLiterals result = |
| 12391 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); |
| 12392 if (result.literals != nullptr) { |
| 12393 DCHECK(shared->feedback_metadata()->is_empty() || |
| 12394 !result.literals->feedback_vector()->is_empty()); |
| 12395 return handle(result.literals, isolate); |
| 12396 } |
| 12397 |
| 12398 Handle<TypeFeedbackVector> feedback_vector = |
| 12399 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); |
| 12400 Handle<LiteralsArray> literals = |
| 12401 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); |
| 12402 Handle<Code> code; |
| 12403 if (result.code != nullptr) { |
| 12404 code = Handle<Code>(result.code, isolate); |
| 12405 } |
| 12406 AddToOptimizedCodeMap(shared, native_context, code, literals, |
| 12407 BailoutId::None()); |
| 12408 return literals; |
| 12409 } |
| 12410 |
| 12411 // static |
12387 void SharedFunctionInfo::AddToOptimizedCodeMap( | 12412 void SharedFunctionInfo::AddToOptimizedCodeMap( |
12388 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 12413 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
12389 MaybeHandle<Code> code, BailoutId osr_ast_id) { | 12414 MaybeHandle<Code> code, Handle<LiteralsArray> literals, |
| 12415 BailoutId osr_ast_id) { |
12390 Isolate* isolate = shared->GetIsolate(); | 12416 Isolate* isolate = shared->GetIsolate(); |
12391 if (isolate->serializer_enabled()) return; | 12417 if (isolate->serializer_enabled()) return; |
12392 DCHECK(code.is_null() || | 12418 DCHECK(code.is_null() || |
12393 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | 12419 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); |
12394 DCHECK(native_context->IsNativeContext()); | 12420 DCHECK(native_context->IsNativeContext()); |
12395 STATIC_ASSERT(kEntryLength == 2); | 12421 STATIC_ASSERT(kEntryLength == 3); |
12396 Handle<FixedArray> new_code_map; | 12422 Handle<FixedArray> new_code_map; |
12397 int entry; | 12423 int entry; |
12398 | 12424 |
12399 if (!osr_ast_id.IsNone()) { | 12425 if (!osr_ast_id.IsNone()) { |
12400 Context::AddToOptimizedCodeMap(native_context, shared, | 12426 Context::AddToOptimizedCodeMap( |
12401 code.ToHandleChecked(), osr_ast_id); | 12427 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); |
12402 return; | 12428 return; |
12403 } | 12429 } |
12404 | 12430 |
12405 DCHECK(osr_ast_id.IsNone()); | 12431 DCHECK(osr_ast_id.IsNone()); |
12406 if (shared->OptimizedCodeMapIsCleared()) { | 12432 if (shared->OptimizedCodeMapIsCleared()) { |
12407 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12433 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
12408 entry = kEntriesStart; | 12434 entry = kEntriesStart; |
12409 } else { | 12435 } else { |
12410 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12436 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
12411 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 12437 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
12412 if (entry >= kEntriesStart) { | 12438 if (entry >= kEntriesStart) { |
12413 // Just set the code of the entry. | 12439 // Just set the code and literals of the entry. |
12414 if (!code.is_null()) { | 12440 if (!code.is_null()) { |
12415 Handle<WeakCell> code_cell = | 12441 Handle<WeakCell> code_cell = |
12416 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12442 isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
12417 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12443 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12418 } | 12444 } |
| 12445 Handle<WeakCell> literals_cell = |
| 12446 isolate->factory()->NewWeakCell(literals); |
| 12447 old_code_map->set(entry + kLiteralsOffset, *literals_cell); |
12419 return; | 12448 return; |
12420 } | 12449 } |
12421 | 12450 |
12422 // Can we reuse an entry? | 12451 // Can we reuse an entry? |
12423 DCHECK(entry < kEntriesStart); | 12452 DCHECK(entry < kEntriesStart); |
12424 int length = old_code_map->length(); | 12453 int length = old_code_map->length(); |
12425 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 12454 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
12426 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { | 12455 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { |
12427 new_code_map = old_code_map; | 12456 new_code_map = old_code_map; |
12428 entry = i; | 12457 entry = i; |
(...skipping 10 matching lines...) Expand all Loading... |
12439 // holes. For now we just give up on adding the entry and pretend it got | 12468 // holes. For now we just give up on adding the entry and pretend it got |
12440 // flushed. | 12469 // flushed. |
12441 if (shared->OptimizedCodeMapIsCleared()) return; | 12470 if (shared->OptimizedCodeMapIsCleared()) return; |
12442 entry = old_code_map->length(); | 12471 entry = old_code_map->length(); |
12443 } | 12472 } |
12444 } | 12473 } |
12445 | 12474 |
12446 Handle<WeakCell> code_cell = | 12475 Handle<WeakCell> code_cell = |
12447 code.is_null() ? isolate->factory()->empty_weak_cell() | 12476 code.is_null() ? isolate->factory()->empty_weak_cell() |
12448 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12477 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
| 12478 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); |
12449 WeakCell* context_cell = native_context->self_weak_cell(); | 12479 WeakCell* context_cell = native_context->self_weak_cell(); |
12450 | 12480 |
12451 new_code_map->set(entry + kContextOffset, context_cell); | 12481 new_code_map->set(entry + kContextOffset, context_cell); |
12452 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12482 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12483 new_code_map->set(entry + kLiteralsOffset, *literals_cell); |
12453 | 12484 |
12454 #ifdef DEBUG | 12485 #ifdef DEBUG |
12455 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12486 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
12456 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12487 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
12457 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12488 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
12458 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12489 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
12459 DCHECK(cell->cleared() || | 12490 DCHECK(cell->cleared() || |
12460 (cell->value()->IsCode() && | 12491 (cell->value()->IsCode() && |
12461 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12492 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
| 12493 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); |
| 12494 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); |
12462 } | 12495 } |
12463 #endif | 12496 #endif |
12464 | 12497 |
12465 FixedArray* old_code_map = shared->optimized_code_map(); | 12498 FixedArray* old_code_map = shared->optimized_code_map(); |
12466 if (old_code_map != *new_code_map) { | 12499 if (old_code_map != *new_code_map) { |
12467 shared->set_optimized_code_map(*new_code_map); | 12500 shared->set_optimized_code_map(*new_code_map); |
12468 } | 12501 } |
12469 } | 12502 } |
12470 | 12503 |
12471 | 12504 |
(...skipping 17 matching lines...) Expand all Loading... |
12489 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12522 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
12490 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12523 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
12491 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12524 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
12492 optimized_code; | 12525 optimized_code; |
12493 if (found) { | 12526 if (found) { |
12494 if (FLAG_trace_opt) { | 12527 if (FLAG_trace_opt) { |
12495 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12528 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
12496 ShortPrint(); | 12529 ShortPrint(); |
12497 PrintF("]\n"); | 12530 PrintF("]\n"); |
12498 } | 12531 } |
12499 // Just clear the code. | 12532 // Just clear the code in order to continue sharing literals. |
12500 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12533 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
12501 SKIP_WRITE_BARRIER); | 12534 SKIP_WRITE_BARRIER); |
12502 } | 12535 } |
12503 } | 12536 } |
12504 } | 12537 } |
12505 | 12538 |
12506 if (!found) { | 12539 if (!found) { |
12507 // We didn't find the code in here. It must be osr'd code. | 12540 // We didn't find the code in here. It must be osr'd code. |
12508 isolate->EvictOSROptimizedCode(optimized_code, reason); | 12541 isolate->EvictOSROptimizedCode(optimized_code, reason); |
12509 } | 12542 } |
12510 } | 12543 } |
12511 | 12544 |
12512 // static | 12545 // static |
12513 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12546 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
12514 Handle<SharedFunctionInfo> shared(function->shared()); | 12547 Handle<SharedFunctionInfo> shared(function->shared()); |
12515 Handle<Context> native_context(function->context()->native_context()); | 12548 Handle<Context> native_context(function->context()->native_context()); |
12516 Isolate* isolate = shared->GetIsolate(); | 12549 if (function->literals() == |
12517 | 12550 function->GetIsolate()->heap()->empty_literals_array()) { |
12518 if (function->needs_literals_array()) { | 12551 Handle<LiteralsArray> literals = |
12519 if (FLAG_trace_strong_rooted_literals) { | 12552 SharedFunctionInfo::FindOrCreateLiterals(shared, native_context); |
12520 PrintF("EnsureLiterals: Installing literals array in %s %p\n", | 12553 function->set_literals(*literals); |
12521 shared->DebugName()->ToCString().get(), | |
12522 reinterpret_cast<void*>(*function)); | |
12523 } | |
12524 // Top level code didn't get it's literals installed. | |
12525 Handle<TypeFeedbackVector> feedback_vector = | |
12526 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
12527 Handle<LiteralsArray> new_literals = | |
12528 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); | |
12529 function->set_literals(*new_literals); | |
12530 } else if (function->literals()->needs_feedback_vector()) { | |
12531 if (FLAG_trace_strong_rooted_literals) { | |
12532 PrintF("EnsureLiterals: Installing feedback vector in %s %p\n", | |
12533 shared->DebugName()->ToCString().get(), | |
12534 reinterpret_cast<void*>(*function)); | |
12535 } | |
12536 // If the feedback vector hasn't been installed, do that. | |
12537 Handle<TypeFeedbackVector> feedback_vector = TypeFeedbackVector::New( | |
12538 shared->GetIsolate(), handle(shared->feedback_metadata())); | |
12539 function->literals()->set_feedback_vector(*feedback_vector); | |
12540 } else { | |
12541 if (FLAG_trace_strong_rooted_literals) { | |
12542 PrintF("EnsureLiterals: did nothing for %s %p\n", | |
12543 shared->DebugName()->ToCString().get(), | |
12544 reinterpret_cast<void*>(*function)); | |
12545 } | |
12546 } | 12554 } |
12547 | |
12548 // No matter what, ensure some post-conditions. | |
12549 DCHECK(shared->feedback_metadata()->slot_count() != 0 || | |
12550 function->feedback_vector() == | |
12551 shared->GetIsolate()->heap()->empty_type_feedback_vector()); | |
12552 DCHECK(shared->num_literals() == 0 || | |
12553 function->literals() != | |
12554 shared->GetIsolate()->heap()->empty_literals_array()); | |
12555 } | 12555 } |
12556 | 12556 |
12557 static void GetMinInobjectSlack(Map* map, void* data) { | 12557 static void GetMinInobjectSlack(Map* map, void* data) { |
12558 int slack = map->unused_property_fields(); | 12558 int slack = map->unused_property_fields(); |
12559 if (*reinterpret_cast<int*>(data) > slack) { | 12559 if (*reinterpret_cast<int*>(data) > slack) { |
12560 *reinterpret_cast<int*>(data) = slack; | 12560 *reinterpret_cast<int*>(data) = slack; |
12561 } | 12561 } |
12562 } | 12562 } |
12563 | 12563 |
12564 | 12564 |
(...skipping 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14114 FixedArray* optimized_code_map = this->optimized_code_map(); | 14114 FixedArray* optimized_code_map = this->optimized_code_map(); |
14115 int length = optimized_code_map->length(); | 14115 int length = optimized_code_map->length(); |
14116 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 14116 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
14117 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 14117 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
14118 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 14118 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
14119 SKIP_WRITE_BARRIER); | 14119 SKIP_WRITE_BARRIER); |
14120 } | 14120 } |
14121 } | 14121 } |
14122 } | 14122 } |
14123 | 14123 |
14124 Code* SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, | 14124 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
14125 BailoutId osr_ast_id) { | 14125 Context* native_context, BailoutId osr_ast_id) { |
14126 Code* result = nullptr; | 14126 CodeAndLiterals result = {nullptr, nullptr}; |
14127 if (!osr_ast_id.IsNone()) { | 14127 if (!osr_ast_id.IsNone()) { |
14128 return native_context->SearchOptimizedCodeMap(this, osr_ast_id); | 14128 Code* code; |
| 14129 LiteralsArray* literals; |
| 14130 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); |
| 14131 result = {code, literals}; |
| 14132 return result; |
14129 } | 14133 } |
14130 | 14134 |
14131 DCHECK(osr_ast_id.IsNone()); | 14135 DCHECK(osr_ast_id.IsNone()); |
14132 int entry = SearchOptimizedCodeMapEntry(native_context); | 14136 int entry = SearchOptimizedCodeMapEntry(native_context); |
14133 if (entry != kNotFound) { | 14137 if (entry != kNotFound) { |
14134 FixedArray* code_map = optimized_code_map(); | 14138 FixedArray* code_map = optimized_code_map(); |
14135 DCHECK_LE(entry + kEntryLength, code_map->length()); | 14139 DCHECK_LE(entry + kEntryLength, code_map->length()); |
14136 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 14140 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
| 14141 WeakCell* literals_cell = |
| 14142 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); |
14137 | 14143 |
14138 result = cell->cleared() ? nullptr : Code::cast(cell->value()); | 14144 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), |
| 14145 literals_cell->cleared() ? nullptr : LiteralsArray::cast( |
| 14146 literals_cell->value())}; |
14139 } | 14147 } |
14140 return result; | 14148 return result; |
14141 } | 14149 } |
14142 | 14150 |
14143 | 14151 |
14144 #define DECLARE_TAG(ignore1, name, ignore2) name, | 14152 #define DECLARE_TAG(ignore1, name, ignore2) name, |
14145 const char* const VisitorSynchronization::kTags[ | 14153 const char* const VisitorSynchronization::kTags[ |
14146 VisitorSynchronization::kNumberOfSyncTags] = { | 14154 VisitorSynchronization::kNumberOfSyncTags] = { |
14147 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 14155 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
14148 }; | 14156 }; |
(...skipping 6288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20437 // depend on this. | 20445 // depend on this. |
20438 return DICTIONARY_ELEMENTS; | 20446 return DICTIONARY_ELEMENTS; |
20439 } | 20447 } |
20440 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20448 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
20441 return kind; | 20449 return kind; |
20442 } | 20450 } |
20443 } | 20451 } |
20444 | 20452 |
20445 } // namespace internal | 20453 } // namespace internal |
20446 } // namespace v8 | 20454 } // namespace v8 |
OLD | NEW |