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