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 12385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12396 // static | 12396 // static |
12397 void SharedFunctionInfo::AddToOptimizedCodeMap( | 12397 void SharedFunctionInfo::AddToOptimizedCodeMap( |
12398 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 12398 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
12399 MaybeHandle<Code> code, Handle<LiteralsArray> literals, | 12399 MaybeHandle<Code> code, Handle<LiteralsArray> literals, |
12400 BailoutId osr_ast_id) { | 12400 BailoutId osr_ast_id) { |
12401 Isolate* isolate = shared->GetIsolate(); | 12401 Isolate* isolate = shared->GetIsolate(); |
12402 if (isolate->serializer_enabled()) return; | 12402 if (isolate->serializer_enabled()) return; |
12403 DCHECK(code.is_null() || | 12403 DCHECK(code.is_null() || |
12404 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | 12404 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); |
12405 DCHECK(native_context->IsNativeContext()); | 12405 DCHECK(native_context->IsNativeContext()); |
12406 STATIC_ASSERT(kEntryLength == 4); | 12406 STATIC_ASSERT(kEntryLength == 3); |
12407 Handle<FixedArray> new_code_map; | 12407 Handle<FixedArray> new_code_map; |
12408 int entry; | 12408 int entry; |
12409 | 12409 |
| 12410 if (!osr_ast_id.IsNone()) { |
| 12411 Context::AddToOptimizedCodeMap( |
| 12412 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); |
| 12413 return; |
| 12414 } |
| 12415 |
| 12416 DCHECK(osr_ast_id.IsNone()); |
12410 if (shared->OptimizedCodeMapIsCleared()) { | 12417 if (shared->OptimizedCodeMapIsCleared()) { |
12411 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12418 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
12412 entry = kEntriesStart; | 12419 entry = kEntriesStart; |
12413 } else { | 12420 } else { |
12414 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12421 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); |
12415 entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id); | 12422 entry = shared->SearchOptimizedCodeMapEntry(*native_context); |
12416 if (entry >= kEntriesStart) { | 12423 if (entry >= kEntriesStart) { |
12417 // Just set the code and literals of the entry. | 12424 // Just set the code and literals of the entry. |
12418 if (!code.is_null()) { | 12425 if (!code.is_null()) { |
12419 Handle<WeakCell> code_cell = | 12426 Handle<WeakCell> code_cell = |
12420 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12427 isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
12421 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12428 old_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12422 } | 12429 } |
12423 Handle<WeakCell> literals_cell = | 12430 Handle<WeakCell> literals_cell = |
12424 isolate->factory()->NewWeakCell(literals); | 12431 isolate->factory()->NewWeakCell(literals); |
12425 old_code_map->set(entry + kLiteralsOffset, *literals_cell); | 12432 old_code_map->set(entry + kLiteralsOffset, *literals_cell); |
(...skipping 26 matching lines...) Expand all Loading... |
12452 | 12459 |
12453 Handle<WeakCell> code_cell = | 12460 Handle<WeakCell> code_cell = |
12454 code.is_null() ? isolate->factory()->empty_weak_cell() | 12461 code.is_null() ? isolate->factory()->empty_weak_cell() |
12455 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12462 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); |
12456 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | 12463 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); |
12457 WeakCell* context_cell = native_context->self_weak_cell(); | 12464 WeakCell* context_cell = native_context->self_weak_cell(); |
12458 | 12465 |
12459 new_code_map->set(entry + kContextOffset, context_cell); | 12466 new_code_map->set(entry + kContextOffset, context_cell); |
12460 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12467 new_code_map->set(entry + kCachedCodeOffset, *code_cell); |
12461 new_code_map->set(entry + kLiteralsOffset, *literals_cell); | 12468 new_code_map->set(entry + kLiteralsOffset, *literals_cell); |
12462 new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt())); | |
12463 | 12469 |
12464 #ifdef DEBUG | 12470 #ifdef DEBUG |
12465 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12471 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
12466 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12472 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); |
12467 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12473 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); |
12468 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12474 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); |
12469 DCHECK(cell->cleared() || | 12475 DCHECK(cell->cleared() || |
12470 (cell->value()->IsCode() && | 12476 (cell->value()->IsCode() && |
12471 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12477 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); |
12472 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); | 12478 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); |
12473 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | 12479 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); |
12474 DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); | |
12475 } | 12480 } |
12476 #endif | 12481 #endif |
12477 | 12482 |
12478 FixedArray* old_code_map = shared->optimized_code_map(); | 12483 FixedArray* old_code_map = shared->optimized_code_map(); |
12479 if (old_code_map != *new_code_map) { | 12484 if (old_code_map != *new_code_map) { |
12480 shared->set_optimized_code_map(*new_code_map); | 12485 shared->set_optimized_code_map(*new_code_map); |
12481 } | 12486 } |
12482 } | 12487 } |
12483 | 12488 |
12484 | 12489 |
12485 void SharedFunctionInfo::ClearOptimizedCodeMap() { | 12490 void SharedFunctionInfo::ClearOptimizedCodeMap() { |
12486 FixedArray* empty_fixed_array = GetHeap()->empty_fixed_array(); | 12491 FixedArray* empty_fixed_array = GetHeap()->empty_fixed_array(); |
12487 set_optimized_code_map(empty_fixed_array, SKIP_WRITE_BARRIER); | 12492 set_optimized_code_map(empty_fixed_array, SKIP_WRITE_BARRIER); |
12488 } | 12493 } |
12489 | 12494 |
12490 | 12495 |
12491 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, | 12496 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, |
12492 const char* reason) { | 12497 const char* reason) { |
12493 DisallowHeapAllocation no_gc; | 12498 DisallowHeapAllocation no_gc; |
12494 if (OptimizedCodeMapIsCleared()) return; | 12499 if (OptimizedCodeMapIsCleared()) return; |
12495 | 12500 |
12496 Heap* heap = GetHeap(); | 12501 Isolate* isolate = GetIsolate(); |
| 12502 Heap* heap = isolate->heap(); |
12497 FixedArray* code_map = optimized_code_map(); | 12503 FixedArray* code_map = optimized_code_map(); |
12498 int dst = kEntriesStart; | |
12499 int length = code_map->length(); | 12504 int length = code_map->length(); |
| 12505 bool found = false; |
12500 for (int src = kEntriesStart; src < length; src += kEntryLength) { | 12506 for (int src = kEntriesStart; src < length; src += kEntryLength) { |
12501 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12507 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || |
12502 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12508 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); |
12503 if (WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12509 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == |
12504 optimized_code) { | 12510 optimized_code; |
12505 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); | 12511 if (found) { |
12506 if (FLAG_trace_opt) { | 12512 if (FLAG_trace_opt) { |
12507 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12513 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
12508 ShortPrint(); | 12514 ShortPrint(); |
12509 if (osr.IsNone()) { | 12515 PrintF("]\n"); |
12510 PrintF("]\n"); | |
12511 } else { | |
12512 PrintF(" (osr ast id %d)]\n", osr.ToInt()); | |
12513 } | |
12514 } | 12516 } |
12515 if (!osr.IsNone()) { | 12517 // Just clear the code in order to continue sharing literals. |
12516 // Evict the src entry by not copying it to the dst entry. | |
12517 continue; | |
12518 } | |
12519 // In case of non-OSR entry just clear the code in order to proceed | |
12520 // sharing literals. | |
12521 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12518 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), |
12522 SKIP_WRITE_BARRIER); | 12519 SKIP_WRITE_BARRIER); |
12523 } | 12520 } |
| 12521 } |
12524 | 12522 |
12525 // Keep the src entry by copying it to the dst entry. | 12523 if (!found) { |
12526 if (dst != src) { | 12524 // We didn't find the code in here. It must be osr'd code. |
12527 code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset)); | 12525 isolate->EvictOSROptimizedCode(optimized_code, reason); |
12528 code_map->set(dst + kCachedCodeOffset, | |
12529 code_map->get(src + kCachedCodeOffset)); | |
12530 code_map->set(dst + kLiteralsOffset, | |
12531 code_map->get(src + kLiteralsOffset)); | |
12532 code_map->set(dst + kOsrAstIdOffset, | |
12533 code_map->get(src + kOsrAstIdOffset)); | |
12534 } | |
12535 dst += kEntryLength; | |
12536 } | |
12537 if (dst != length) { | |
12538 // Always trim even when array is cleared because of heap verifier. | |
12539 heap->RightTrimFixedArray(code_map, length - dst); | |
12540 if (code_map->length() == kEntriesStart) { | |
12541 ClearOptimizedCodeMap(); | |
12542 } | |
12543 } | 12526 } |
12544 } | 12527 } |
12545 | 12528 |
12546 // static | 12529 // static |
12547 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { | 12530 void JSFunction::EnsureLiterals(Handle<JSFunction> function) { |
12548 Handle<SharedFunctionInfo> shared(function->shared()); | 12531 Handle<SharedFunctionInfo> shared(function->shared()); |
12549 Handle<Context> native_context(function->context()->native_context()); | 12532 Handle<Context> native_context(function->context()->native_context()); |
12550 if (function->literals() == | 12533 if (function->literals() == |
12551 function->GetIsolate()->heap()->empty_literals_array()) { | 12534 function->GetIsolate()->heap()->empty_literals_array()) { |
12552 Handle<LiteralsArray> literals = | 12535 Handle<LiteralsArray> literals = |
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14069 set_profiler_ticks(0); | 14052 set_profiler_ticks(0); |
14070 if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) { | 14053 if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) { |
14071 // Re-enable optimizations if they were disabled due to opt_count limit. | 14054 // Re-enable optimizations if they were disabled due to opt_count limit. |
14072 set_optimization_disabled(false); | 14055 set_optimization_disabled(false); |
14073 } | 14056 } |
14074 set_opt_count(0); | 14057 set_opt_count(0); |
14075 set_deopt_count(0); | 14058 set_deopt_count(0); |
14076 } | 14059 } |
14077 } | 14060 } |
14078 | 14061 |
14079 | 14062 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context) { |
14080 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context, | |
14081 BailoutId osr_ast_id) { | |
14082 DisallowHeapAllocation no_gc; | 14063 DisallowHeapAllocation no_gc; |
14083 DCHECK(native_context->IsNativeContext()); | 14064 DCHECK(native_context->IsNativeContext()); |
14084 if (!OptimizedCodeMapIsCleared()) { | 14065 if (!OptimizedCodeMapIsCleared()) { |
14085 FixedArray* optimized_code_map = this->optimized_code_map(); | 14066 FixedArray* optimized_code_map = this->optimized_code_map(); |
14086 int length = optimized_code_map->length(); | 14067 int length = optimized_code_map->length(); |
14087 Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt()); | |
14088 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 14068 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
14089 if (WeakCell::cast(optimized_code_map->get(i + kContextOffset)) | 14069 if (WeakCell::cast(optimized_code_map->get(i + kContextOffset)) |
14090 ->value() == native_context && | 14070 ->value() == native_context) { |
14091 optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { | |
14092 return i; | 14071 return i; |
14093 } | 14072 } |
14094 } | 14073 } |
14095 } | 14074 } |
14096 return -1; | 14075 return -1; |
14097 } | 14076 } |
14098 | 14077 |
14099 void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() { | 14078 void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() { |
14100 if (!OptimizedCodeMapIsCleared()) { | 14079 if (!OptimizedCodeMapIsCleared()) { |
14101 FixedArray* optimized_code_map = this->optimized_code_map(); | 14080 FixedArray* optimized_code_map = this->optimized_code_map(); |
14102 int length = optimized_code_map->length(); | 14081 int length = optimized_code_map->length(); |
14103 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 14082 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); |
14104 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 14083 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
14105 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 14084 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, |
14106 SKIP_WRITE_BARRIER); | 14085 SKIP_WRITE_BARRIER); |
14107 } | 14086 } |
14108 } | 14087 } |
14109 } | 14088 } |
14110 | 14089 |
14111 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 14090 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
14112 Context* native_context, BailoutId osr_ast_id) { | 14091 Context* native_context, BailoutId osr_ast_id) { |
14113 CodeAndLiterals result = {nullptr, nullptr}; | 14092 CodeAndLiterals result = {nullptr, nullptr}; |
14114 int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id); | 14093 if (!osr_ast_id.IsNone()) { |
| 14094 Code* code; |
| 14095 LiteralsArray* literals; |
| 14096 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); |
| 14097 result = {code, literals}; |
| 14098 return result; |
| 14099 } |
| 14100 |
| 14101 DCHECK(osr_ast_id.IsNone()); |
| 14102 int entry = SearchOptimizedCodeMapEntry(native_context); |
14115 if (entry != kNotFound) { | 14103 if (entry != kNotFound) { |
14116 FixedArray* code_map = optimized_code_map(); | 14104 FixedArray* code_map = optimized_code_map(); |
14117 DCHECK_LE(entry + kEntryLength, code_map->length()); | 14105 DCHECK_LE(entry + kEntryLength, code_map->length()); |
14118 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 14106 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); |
14119 WeakCell* literals_cell = | 14107 WeakCell* literals_cell = |
14120 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); | 14108 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); |
14121 | 14109 |
14122 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | 14110 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), |
14123 literals_cell->cleared() ? nullptr : LiteralsArray::cast( | 14111 literals_cell->cleared() ? nullptr : LiteralsArray::cast( |
14124 literals_cell->value())}; | 14112 literals_cell->value())}; |
(...skipping 6298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20423 // depend on this. | 20411 // depend on this. |
20424 return DICTIONARY_ELEMENTS; | 20412 return DICTIONARY_ELEMENTS; |
20425 } | 20413 } |
20426 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20414 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
20427 return kind; | 20415 return kind; |
20428 } | 20416 } |
20429 } | 20417 } |
20430 | 20418 |
20431 } // namespace internal | 20419 } // namespace internal |
20432 } // namespace v8 | 20420 } // namespace v8 |
OLD | NEW |