Chromium Code Reviews| 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 12521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12532 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); | 12532 isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent)); |
| 12533 // No write barrier required, since the builtin is part of the root set. | 12533 // No write barrier required, since the builtin is part of the root set. |
| 12534 if (FLAG_mark_shared_functions_for_tier_up) { | 12534 if (FLAG_mark_shared_functions_for_tier_up) { |
| 12535 // TODO(leszeks): The compilation isn't concurrent if we trigger it using | 12535 // TODO(leszeks): The compilation isn't concurrent if we trigger it using |
| 12536 // this bit. | 12536 // this bit. |
| 12537 shared()->set_marked_for_tier_up(true); | 12537 shared()->set_marked_for_tier_up(true); |
| 12538 } | 12538 } |
| 12539 } | 12539 } |
| 12540 | 12540 |
| 12541 // static | 12541 // static |
| 12542 Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals( | |
| 12543 Handle<SharedFunctionInfo> shared, Handle<Context> native_context) { | |
| 12544 Isolate* isolate = shared->GetIsolate(); | |
| 12545 CodeAndLiterals result = | |
| 12546 shared->SearchOptimizedCodeMap(*native_context, BailoutId::None()); | |
| 12547 if (result.literals != nullptr) { | |
| 12548 DCHECK(shared->feedback_metadata()->is_empty() || | |
| 12549 !result.literals->feedback_vector()->is_empty()); | |
| 12550 return handle(result.literals, isolate); | |
| 12551 } | |
| 12552 | |
| 12553 Handle<TypeFeedbackVector> feedback_vector = | |
| 12554 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
| 12555 Handle<LiteralsArray> literals = | |
| 12556 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); | |
| 12557 Handle<Code> code; | |
| 12558 if (result.code != nullptr) { | |
| 12559 code = Handle<Code>(result.code, isolate); | |
| 12560 } | |
| 12561 AddToOptimizedCodeMap(shared, native_context, code, literals, | |
| 12562 BailoutId::None()); | |
| 12563 return literals; | |
| 12564 } | |
| 12565 | |
| 12566 // static | |
| 12567 void SharedFunctionInfo::AddToOptimizedCodeMap( | 12542 void SharedFunctionInfo::AddToOptimizedCodeMap( |
| 12568 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 12543 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
| 12569 MaybeHandle<Code> code, Handle<LiteralsArray> literals, | 12544 Handle<Code> code, BailoutId osr_ast_id) { |
| 12570 BailoutId osr_ast_id) { | |
| 12571 Isolate* isolate = shared->GetIsolate(); | 12545 Isolate* isolate = shared->GetIsolate(); |
| 12572 if (isolate->serializer_enabled()) return; | 12546 if (isolate->serializer_enabled()) return; |
| 12573 DCHECK(code.is_null() || | 12547 DCHECK(code.is_null() || code->kind() == Code::OPTIMIZED_FUNCTION); |
|
Michael Starzinger
2017/01/11 13:22:44
nit: First half of the predicate should always hol
mvstanton
2017/01/11 14:52:06
Done.
| |
| 12574 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | |
| 12575 DCHECK(native_context->IsNativeContext()); | 12548 DCHECK(native_context->IsNativeContext()); |
| 12576 STATIC_ASSERT(kEntryLength == 3); | 12549 STATIC_ASSERT(kEntryLength == 2); |
| 12577 Handle<FixedArray> new_code_map; | 12550 Handle<FixedArray> new_code_map; |
| 12578 int entry; | 12551 int entry; |
| 12579 | 12552 |
| 12580 if (!osr_ast_id.IsNone()) { | 12553 if (!osr_ast_id.IsNone()) { |
| 12581 Context::AddToOptimizedCodeMap( | 12554 Context::AddToOptimizedCodeMap(native_context, shared, code, osr_ast_id); |
| 12582 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); | |
| 12583 return; | 12555 return; |
| 12584 } | 12556 } |
| 12585 | 12557 |
| 12586 DCHECK(osr_ast_id.IsNone()); | 12558 DCHECK(osr_ast_id.IsNone()); |
| 12587 if (shared->OptimizedCodeMapIsCleared()) { | 12559 if (shared->OptimizedCodeMapIsCleared()) { |
| 12588 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12560 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
| 12589 entry = kEntriesStart; | 12561 entry = kEntriesStart; |
| 12590 } else { | 12562 } else { |
| 12591 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12563 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
| 12592 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 12564 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
| 12593 if (entry >= kEntriesStart) { | 12565 if (entry >= kEntriesStart) { |
| 12594 // Just set the code and literals of the entry. | 12566 // Just set the code of the entry. |
| 12595 if (!code.is_null()) { | 12567 if (!code.is_null()) { |
|
Michael Starzinger
2017/01/11 13:22:44
nit: Should always hold now AFAICT.
mvstanton
2017/01/11 14:52:06
Done.
| |
| 12596 Handle<WeakCell> code_cell = | 12568 Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code); |
| 12597 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | |
| 12598 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12569 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12599 } | 12570 } |
| 12600 Handle<WeakCell> literals_cell = | |
| 12601 isolate->factory()->NewWeakCell(literals); | |
| 12602 old_code_map->set(entry + kLiteralsOffset, *literals_cell); | |
| 12603 return; | 12571 return; |
| 12604 } | 12572 } |
| 12605 | 12573 |
| 12606 // Can we reuse an entry? | 12574 // Can we reuse an entry? |
| 12607 DCHECK(entry < kEntriesStart); | 12575 DCHECK(entry < kEntriesStart); |
| 12608 int length = old_code_map->length(); | 12576 int length = old_code_map->length(); |
| 12609 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 12577 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
| 12610 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { | 12578 if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) { |
| 12611 new_code_map = old_code_map; | 12579 new_code_map = old_code_map; |
| 12612 entry = i; | 12580 entry = i; |
| 12613 break; | 12581 break; |
| 12614 } | 12582 } |
| 12615 } | 12583 } |
| 12616 | 12584 |
| 12617 if (entry < kEntriesStart) { | 12585 if (entry < kEntriesStart) { |
| 12618 // Copy old optimized code map and append one new entry. | 12586 // Copy old optimized code map and append one new entry. |
| 12619 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( | 12587 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( |
| 12620 old_code_map, kEntryLength, TENURED); | 12588 old_code_map, kEntryLength, TENURED); |
| 12621 // TODO(mstarzinger): Temporary workaround. The allocation above might | 12589 // TODO(mstarzinger): Temporary workaround. The allocation above might |
| 12622 // have flushed the optimized code map and the copy we created is full of | 12590 // have flushed the optimized code map and the copy we created is full of |
| 12623 // holes. For now we just give up on adding the entry and pretend it got | 12591 // holes. For now we just give up on adding the entry and pretend it got |
| 12624 // flushed. | 12592 // flushed. |
| 12625 if (shared->OptimizedCodeMapIsCleared()) return; | 12593 if (shared->OptimizedCodeMapIsCleared()) return; |
| 12626 entry = old_code_map->length(); | 12594 entry = old_code_map->length(); |
| 12627 } | 12595 } |
| 12628 } | 12596 } |
| 12629 | 12597 |
| 12630 Handle<WeakCell> code_cell = | 12598 Handle<WeakCell> code_cell = code.is_null() |
|
Michael Starzinger
2017/01/11 13:22:44
nit: Should always hold now AFAICT.
mvstanton
2017/01/11 14:52:06
Done.
| |
| 12631 code.is_null() ? isolate->factory()->empty_weak_cell() | 12599 ? isolate->factory()->empty_weak_cell() |
| 12632 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12600 : isolate->factory()->NewWeakCell(code); |
| 12633 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | |
| 12634 WeakCell* context_cell = native_context->self_weak_cell(); | 12601 WeakCell* context_cell = native_context->self_weak_cell(); |
| 12635 | 12602 |
| 12636 new_code_map->set(entry + kContextOffset, context_cell); | 12603 new_code_map->set(entry + kContextOffset, context_cell); |
| 12637 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12604 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
| 12638 new_code_map->set(entry + kLiteralsOffset, *literals_cell); | |
| 12639 | 12605 |
| 12640 #ifdef DEBUG | 12606 #ifdef DEBUG |
| 12641 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12607 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
| 12642 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12608 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
| 12643 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12609 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
| 12644 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12610 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
| 12645 DCHECK(cell->cleared() || | 12611 DCHECK(cell->cleared() || |
| 12646 (cell->value()->IsCode() && | 12612 (cell->value()->IsCode() && |
| 12647 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12613 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
| 12648 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); | |
| 12649 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | |
| 12650 } | 12614 } |
| 12651 #endif | 12615 #endif |
| 12652 | 12616 |
| 12653 FixedArray* old_code_map = shared->optimized_code_map(); | 12617 FixedArray* old_code_map = shared->optimized_code_map(); |
| 12654 if (old_code_map != *new_code_map) { | 12618 if (old_code_map != *new_code_map) { |
| 12655 shared->set_optimized_code_map(*new_code_map); | 12619 shared->set_optimized_code_map(*new_code_map); |
| 12656 } | 12620 } |
| 12657 } | 12621 } |
| 12658 | 12622 |
| 12659 | 12623 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 12677 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12641 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
| 12678 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12642 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
| 12679 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12643 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
| 12680 optimized_code; | 12644 optimized_code; |
| 12681 if (found) { | 12645 if (found) { |
| 12682 if (FLAG_trace_opt) { | 12646 if (FLAG_trace_opt) { |
| 12683 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12647 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
| 12684 ShortPrint(); | 12648 ShortPrint(); |
| 12685 PrintF("]\n"); | 12649 PrintF("]\n"); |
| 12686 } | 12650 } |
| 12687 // Just clear the code in order to continue sharing literals. | 12651 // Just clear the code. |
| 12688 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12652 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
| 12689 SKIP_WRITE_BARRIER); | 12653 SKIP_WRITE_BARRIER); |
| 12690 } | 12654 } |
| 12691 } | 12655 } |
| 12692 } | 12656 } |
| 12693 | 12657 |
| 12694 if (!found) { | 12658 if (!found) { |
| 12695 // We didn't find the code in here. It must be osr'd code. | 12659 // We didn't find the code in here. It must be osr'd code. |
| 12696 isolate->EvictOSROptimizedCode(optimized_code, reason); | 12660 isolate->EvictOSROptimizedCode(optimized_code, reason); |
| 12697 } | 12661 } |
| 12698 } | 12662 } |
| 12699 | 12663 |
| 12700 // static | 12664 // static |
| 12701 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12665 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
| 12702 Handle<SharedFunctionInfo> shared(function->shared()); | 12666 Handle<SharedFunctionInfo> shared(function->shared()); |
| 12703 Handle<Context> native_context(function->context()->native_context()); | 12667 Handle<Context> native_context(function->context()->native_context()); |
| 12704 if (function->literals() == | 12668 Isolate* isolate = shared->GetIsolate(); |
| 12705 function->GetIsolate()->heap()->empty_literals_array()) { | 12669 |
| 12706 Handle<LiteralsArray> literals = | 12670 if (!function->has_literals_array()) { |
| 12707 SharedFunctionInfo::FindOrCreateLiterals(shared, native_context); | 12671 if (FLAG_trace_strong_rooted_literals) { |
| 12708 function->set_literals(*literals); | 12672 PrintF("EnsureLiterals: Installing literals array in %s %p\n", |
| 12673 shared->DebugName()->ToCString().get(), | |
| 12674 reinterpret_cast<void*>(*function)); | |
| 12675 } | |
| 12676 // Top level code didn't get it's literals installed. | |
| 12677 Handle<TypeFeedbackVector> feedback_vector = | |
| 12678 TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata())); | |
| 12679 Handle<LiteralsArray> new_literals = | |
| 12680 LiteralsArray::New(isolate, feedback_vector, shared->num_literals()); | |
| 12681 function->set_literals(*new_literals); | |
| 12682 } else if (!function->literals()->has_feedback_vector()) { | |
| 12683 if (FLAG_trace_strong_rooted_literals) { | |
| 12684 PrintF("EnsureLiterals: Installing feedback vector in %s %p\n", | |
| 12685 shared->DebugName()->ToCString().get(), | |
| 12686 reinterpret_cast<void*>(*function)); | |
| 12687 } | |
| 12688 // If the feedback vector hasn't been installed, do that. | |
| 12689 Handle<TypeFeedbackVector> feedback_vector = TypeFeedbackVector::New( | |
| 12690 shared->GetIsolate(), handle(shared->feedback_metadata())); | |
| 12691 function->literals()->set_feedback_vector(*feedback_vector); | |
| 12692 } else { | |
| 12693 if (FLAG_trace_strong_rooted_literals) { | |
| 12694 PrintF("EnsureLiterals: did nothing for %s %p\n", | |
| 12695 shared->DebugName()->ToCString().get(), | |
| 12696 reinterpret_cast<void*>(*function)); | |
| 12697 } | |
| 12709 } | 12698 } |
| 12699 | |
| 12700 // No matter what, ensure some post-conditions. | |
| 12701 DCHECK(shared->feedback_metadata()->slot_count() != 0 || | |
| 12702 function->feedback_vector() == | |
| 12703 shared->GetIsolate()->heap()->empty_type_feedback_vector()); | |
| 12704 DCHECK(shared->num_literals() == 0 || | |
| 12705 function->literals() != | |
| 12706 shared->GetIsolate()->heap()->empty_literals_array()); | |
| 12710 } | 12707 } |
| 12711 | 12708 |
| 12712 static void GetMinInobjectSlack(Map* map, void* data) { | 12709 static void GetMinInobjectSlack(Map* map, void* data) { |
| 12713 int slack = map->unused_property_fields(); | 12710 int slack = map->unused_property_fields(); |
| 12714 if (*reinterpret_cast<int*>(data) > slack) { | 12711 if (*reinterpret_cast<int*>(data) > slack) { |
| 12715 *reinterpret_cast<int*>(data) = slack; | 12712 *reinterpret_cast<int*>(data) = slack; |
| 12716 } | 12713 } |
| 12717 } | 12714 } |
| 12718 | 12715 |
| 12719 | 12716 |
| (...skipping 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14269 FixedArray* optimized_code_map = this->optimized_code_map(); | 14266 FixedArray* optimized_code_map = this->optimized_code_map(); |
| 14270 int length = optimized_code_map->length(); | 14267 int length = optimized_code_map->length(); |
| 14271 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 14268 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
| 14272 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 14269 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
| 14273 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 14270 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
| 14274 SKIP_WRITE_BARRIER); | 14271 SKIP_WRITE_BARRIER); |
| 14275 } | 14272 } |
| 14276 } | 14273 } |
| 14277 } | 14274 } |
| 14278 | 14275 |
| 14279 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 14276 Code* SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context, |
| 14280 Context* native_context, BailoutId osr_ast_id) { | 14277 BailoutId osr_ast_id) { |
| 14281 CodeAndLiterals result = {nullptr, nullptr}; | 14278 Code* result = nullptr; |
| 14282 if (!osr_ast_id.IsNone()) { | 14279 if (!osr_ast_id.IsNone()) { |
| 14283 Code* code; | 14280 return native_context->SearchOptimizedCodeMap(this, osr_ast_id); |
| 14284 LiteralsArray* literals; | |
| 14285 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); | |
| 14286 result = {code, literals}; | |
| 14287 return result; | |
| 14288 } | 14281 } |
| 14289 | 14282 |
| 14290 DCHECK(osr_ast_id.IsNone()); | 14283 DCHECK(osr_ast_id.IsNone()); |
| 14291 int entry = SearchOptimizedCodeMapEntry(native_context); | 14284 int entry = SearchOptimizedCodeMapEntry(native_context); |
| 14292 if (entry != kNotFound) { | 14285 if (entry != kNotFound) { |
| 14293 FixedArray* code_map = optimized_code_map(); | 14286 FixedArray* code_map = optimized_code_map(); |
| 14294 DCHECK_LE(entry + kEntryLength, code_map->length()); | 14287 DCHECK_LE(entry + kEntryLength, code_map->length()); |
| 14295 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 14288 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
| 14296 WeakCell* literals_cell = | |
| 14297 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); | |
| 14298 | 14289 |
| 14299 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | 14290 result = cell->cleared() ? nullptr : Code::cast(cell->value()); |
| 14300 literals_cell->cleared() ? nullptr : LiteralsArray::cast( | |
| 14301 literals_cell->value())}; | |
| 14302 } | 14291 } |
| 14303 return result; | 14292 return result; |
| 14304 } | 14293 } |
| 14305 | 14294 |
| 14306 | 14295 |
| 14307 #define DECLARE_TAG(ignore1, name, ignore2) name, | 14296 #define DECLARE_TAG(ignore1, name, ignore2) name, |
| 14308 const char* const VisitorSynchronization::kTags[ | 14297 const char* const VisitorSynchronization::kTags[ |
| 14309 VisitorSynchronization::kNumberOfSyncTags] = { | 14298 VisitorSynchronization::kNumberOfSyncTags] = { |
| 14310 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 14299 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
| 14311 }; | 14300 }; |
| (...skipping 6179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 20491 // depend on this. | 20480 // depend on this. |
| 20492 return DICTIONARY_ELEMENTS; | 20481 return DICTIONARY_ELEMENTS; |
| 20493 } | 20482 } |
| 20494 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20483 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20495 return kind; | 20484 return kind; |
| 20496 } | 20485 } |
| 20497 } | 20486 } |
| 20498 | 20487 |
| 20499 } // namespace internal | 20488 } // namespace internal |
| 20500 } // namespace v8 | 20489 } // namespace v8 |
| OLD | NEW |