 Chromium Code Reviews
 Chromium Code Reviews Issue 2549753002:
  Store OSR'd optimized code on the native context.  (Closed)
    
  
    Issue 2549753002:
  Store OSR'd optimized code on the native context.  (Closed) 
  | 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 12356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12367 // static | 12367 // static | 
| 12368 void SharedFunctionInfo::AddToOptimizedCodeMap( | 12368 void SharedFunctionInfo::AddToOptimizedCodeMap( | 
| 12369 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 12369 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, | 
| 12370 MaybeHandle<Code> code, Handle<LiteralsArray> literals, | 12370 MaybeHandle<Code> code, Handle<LiteralsArray> literals, | 
| 12371 BailoutId osr_ast_id) { | 12371 BailoutId osr_ast_id) { | 
| 12372 Isolate* isolate = shared->GetIsolate(); | 12372 Isolate* isolate = shared->GetIsolate(); | 
| 12373 if (isolate->serializer_enabled()) return; | 12373 if (isolate->serializer_enabled()) return; | 
| 12374 DCHECK(code.is_null() || | 12374 DCHECK(code.is_null() || | 
| 12375 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | 12375 code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION); | 
| 12376 DCHECK(native_context->IsNativeContext()); | 12376 DCHECK(native_context->IsNativeContext()); | 
| 12377 STATIC_ASSERT(kEntryLength == 4); | 12377 STATIC_ASSERT(kEntryLength == 3); | 
| 12378 Handle<FixedArray> new_code_map; | 12378 Handle<FixedArray> new_code_map; | 
| 12379 int entry; | 12379 int entry; | 
| 12380 | 12380 | 
| 12381 if (!osr_ast_id.IsNone()) { | |
| 12382 Context::AddToOptimizedCodeMap( | |
| 12383 native_context, shared, code.ToHandleChecked(), literals, osr_ast_id); | |
| 12384 return; | |
| 12385 } | |
| 12386 | |
| 12387 DCHECK(osr_ast_id.IsNone()); | |
| 12381 if (shared->OptimizedCodeMapIsCleared()) { | 12388 if (shared->OptimizedCodeMapIsCleared()) { | 
| 12382 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 12389 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 
| 12383 entry = kEntriesStart; | 12390 entry = kEntriesStart; | 
| 12384 } else { | 12391 } else { | 
| 12385 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 12392 Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate); | 
| 12386 entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id); | 12393 entry = shared->SearchOptimizedCodeMapEntry(*native_context); | 
| 12387 if (entry >= kEntriesStart) { | 12394 if (entry >= kEntriesStart) { | 
| 12388 // Just set the code and literals of the entry. | 12395 // Just set the code and literals of the entry. | 
| 12389 if (!code.is_null()) { | 12396 if (!code.is_null()) { | 
| 12390 Handle<WeakCell> code_cell = | 12397 Handle<WeakCell> code_cell = | 
| 12391 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12398 isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 
| 12392 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12399 old_code_map->set(entry + kCachedCodeOffset, *code_cell); | 
| 12393 } | 12400 } | 
| 12394 Handle<WeakCell> literals_cell = | 12401 Handle<WeakCell> literals_cell = | 
| 12395 isolate->factory()->NewWeakCell(literals); | 12402 isolate->factory()->NewWeakCell(literals); | 
| 12396 old_code_map->set(entry + kLiteralsOffset, *literals_cell); | 12403 old_code_map->set(entry + kLiteralsOffset, *literals_cell); | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 12423 | 12430 | 
| 12424 Handle<WeakCell> code_cell = | 12431 Handle<WeakCell> code_cell = | 
| 12425 code.is_null() ? isolate->factory()->empty_weak_cell() | 12432 code.is_null() ? isolate->factory()->empty_weak_cell() | 
| 12426 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 12433 : isolate->factory()->NewWeakCell(code.ToHandleChecked()); | 
| 12427 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | 12434 Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals); | 
| 12428 WeakCell* context_cell = native_context->self_weak_cell(); | 12435 WeakCell* context_cell = native_context->self_weak_cell(); | 
| 12429 | 12436 | 
| 12430 new_code_map->set(entry + kContextOffset, context_cell); | 12437 new_code_map->set(entry + kContextOffset, context_cell); | 
| 12431 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 12438 new_code_map->set(entry + kCachedCodeOffset, *code_cell); | 
| 12432 new_code_map->set(entry + kLiteralsOffset, *literals_cell); | 12439 new_code_map->set(entry + kLiteralsOffset, *literals_cell); | 
| 12433 new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt())); | |
| 12434 | 12440 | 
| 12435 #ifdef DEBUG | 12441 #ifdef DEBUG | 
| 12436 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 12442 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 
| 12437 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 12443 WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset)); | 
| 12438 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 12444 DCHECK(cell->cleared() || cell->value()->IsNativeContext()); | 
| 12439 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 12445 cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset)); | 
| 12440 DCHECK(cell->cleared() || | 12446 DCHECK(cell->cleared() || | 
| 12441 (cell->value()->IsCode() && | 12447 (cell->value()->IsCode() && | 
| 12442 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 12448 Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION)); | 
| 12443 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); | 12449 cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset)); | 
| 12444 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | 12450 DCHECK(cell->cleared() || cell->value()->IsFixedArray()); | 
| 12445 DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); | |
| 12446 } | 12451 } | 
| 12447 #endif | 12452 #endif | 
| 12448 | 12453 | 
| 12449 FixedArray* old_code_map = shared->optimized_code_map(); | 12454 FixedArray* old_code_map = shared->optimized_code_map(); | 
| 12450 if (old_code_map != *new_code_map) { | 12455 if (old_code_map != *new_code_map) { | 
| 12451 shared->set_optimized_code_map(*new_code_map); | 12456 shared->set_optimized_code_map(*new_code_map); | 
| 12452 } | 12457 } | 
| 12453 } | 12458 } | 
| 12454 | 12459 | 
| 12455 | 12460 | 
| 12456 void SharedFunctionInfo::ClearOptimizedCodeMap() { | 12461 void SharedFunctionInfo::ClearOptimizedCodeMap() { | 
| 12457 FixedArray* empty_fixed_array = GetHeap()->empty_fixed_array(); | 12462 FixedArray* empty_fixed_array = GetHeap()->empty_fixed_array(); | 
| 12458 set_optimized_code_map(empty_fixed_array, SKIP_WRITE_BARRIER); | 12463 set_optimized_code_map(empty_fixed_array, SKIP_WRITE_BARRIER); | 
| 12459 } | 12464 } | 
| 12460 | 12465 | 
| 12461 | 12466 | 
| 12462 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, | 12467 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, | 
| 12463 const char* reason) { | 12468 const char* reason) { | 
| 12464 DisallowHeapAllocation no_gc; | 12469 DisallowHeapAllocation no_gc; | 
| 12465 if (OptimizedCodeMapIsCleared()) return; | 12470 if (OptimizedCodeMapIsCleared()) return; | 
| 12466 | 12471 | 
| 12467 Heap* heap = GetHeap(); | 12472 Isolate* isolate = GetIsolate(); | 
| 12473 Heap* heap = isolate->heap(); | |
| 12468 FixedArray* code_map = optimized_code_map(); | 12474 FixedArray* code_map = optimized_code_map(); | 
| 12469 int dst = kEntriesStart; | |
| 12470 int length = code_map->length(); | 12475 int length = code_map->length(); | 
| 12476 bool found = false; | |
| 12471 for (int src = kEntriesStart; src < length; src += kEntryLength) { | 12477 for (int src = kEntriesStart; src < length; src += kEntryLength) { | 
| 12472 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 12478 DCHECK(WeakCell::cast(code_map->get(src))->cleared() || | 
| 12473 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 12479 WeakCell::cast(code_map->get(src))->value()->IsNativeContext()); | 
| 12474 if (WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 12480 found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() == | 
| 
ulan
2016/12/07 14:54:57
I think we need two flags here: found and match.
 | |
| 12475 optimized_code) { | 12481 optimized_code; | 
| 12476 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); | 12482 if (found) { | 
| 12477 if (FLAG_trace_opt) { | 12483 if (FLAG_trace_opt) { | 
| 12478 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 12484 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 
| 12479 ShortPrint(); | 12485 ShortPrint(); | 
| 12480 if (osr.IsNone()) { | 12486 PrintF("]\n"); | 
| 12481 PrintF("]\n"); | |
| 12482 } else { | |
| 12483 PrintF(" (osr ast id %d)]\n", osr.ToInt()); | |
| 12484 } | |
| 12485 } | 12487 } | 
| 12486 if (!osr.IsNone()) { | 12488 // Just clear the code in order to continue sharing literals. | 
| 12487 // Evict the src entry by not copying it to the dst entry. | |
| 12488 continue; | |
| 12489 } | |
| 12490 // In case of non-OSR entry just clear the code in order to proceed | |
| 12491 // sharing literals. | |
| 12492 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 12489 code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(), | 
| 12493 SKIP_WRITE_BARRIER); | 12490 SKIP_WRITE_BARRIER); | 
| 12494 } | 12491 } | 
| 12492 } | |
| 12495 | 12493 | 
| 12496 // Keep the src entry by copying it to the dst entry. | 12494 if (!found) { | 
| 12497 if (dst != src) { | 12495 // We didn't find the code in here. It must be osr'd code. | 
| 12498 code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset)); | 12496 isolate->EvictOSROptimizedCode(optimized_code, reason); | 
| 12499 code_map->set(dst + kCachedCodeOffset, | |
| 12500 code_map->get(src + kCachedCodeOffset)); | |
| 12501 code_map->set(dst + kLiteralsOffset, | |
| 12502 code_map->get(src + kLiteralsOffset)); | |
| 12503 code_map->set(dst + kOsrAstIdOffset, | |
| 12504 code_map->get(src + kOsrAstIdOffset)); | |
| 12505 } | |
| 12506 dst += kEntryLength; | |
| 12507 } | |
| 12508 if (dst != length) { | |
| 12509 // Always trim even when array is cleared because of heap verifier. | |
| 12510 heap->RightTrimFixedArray(code_map, length - dst); | |
| 12511 if (code_map->length() == kEntriesStart) { | |
| 12512 ClearOptimizedCodeMap(); | |
| 12513 } | |
| 12514 } | 12497 } | 
| 12515 } | 12498 } | 
| 12516 | 12499 | 
| 12517 | 12500 | 
| 12518 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { | 12501 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { | 
| 12519 FixedArray* code_map = optimized_code_map(); | 12502 FixedArray* code_map = optimized_code_map(); | 
| 12520 DCHECK(shrink_by % kEntryLength == 0); | 12503 DCHECK(shrink_by % kEntryLength == 0); | 
| 12521 DCHECK(shrink_by <= code_map->length() - kEntriesStart); | 12504 DCHECK(shrink_by <= code_map->length() - kEntriesStart); | 
| 12522 // Always trim even when array is cleared because of heap verifier. | 12505 // Always trim even when array is cleared because of heap verifier. | 
| 12523 GetHeap()->RightTrimFixedArray(code_map, shrink_by); | 12506 GetHeap()->RightTrimFixedArray(code_map, shrink_by); | 
| (...skipping 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14052 set_profiler_ticks(0); | 14035 set_profiler_ticks(0); | 
| 14053 if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) { | 14036 if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) { | 
| 14054 // Re-enable optimizations if they were disabled due to opt_count limit. | 14037 // Re-enable optimizations if they were disabled due to opt_count limit. | 
| 14055 set_optimization_disabled(false); | 14038 set_optimization_disabled(false); | 
| 14056 } | 14039 } | 
| 14057 set_opt_count(0); | 14040 set_opt_count(0); | 
| 14058 set_deopt_count(0); | 14041 set_deopt_count(0); | 
| 14059 } | 14042 } | 
| 14060 } | 14043 } | 
| 14061 | 14044 | 
| 14062 | 14045 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context) { | 
| 14063 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context, | |
| 14064 BailoutId osr_ast_id) { | |
| 14065 DisallowHeapAllocation no_gc; | 14046 DisallowHeapAllocation no_gc; | 
| 14066 DCHECK(native_context->IsNativeContext()); | 14047 DCHECK(native_context->IsNativeContext()); | 
| 14067 if (!OptimizedCodeMapIsCleared()) { | 14048 if (!OptimizedCodeMapIsCleared()) { | 
| 14068 FixedArray* optimized_code_map = this->optimized_code_map(); | 14049 FixedArray* optimized_code_map = this->optimized_code_map(); | 
| 14069 int length = optimized_code_map->length(); | 14050 int length = optimized_code_map->length(); | 
| 14070 Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt()); | |
| 14071 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 14051 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 
| 14072 if (WeakCell::cast(optimized_code_map->get(i + kContextOffset)) | 14052 if (WeakCell::cast(optimized_code_map->get(i + kContextOffset)) | 
| 14073 ->value() == native_context && | 14053 ->value() == native_context) { | 
| 14074 optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { | |
| 14075 return i; | 14054 return i; | 
| 14076 } | 14055 } | 
| 14077 } | 14056 } | 
| 14078 } | 14057 } | 
| 14079 return -1; | 14058 return -1; | 
| 14080 } | 14059 } | 
| 14081 | 14060 | 
| 14082 void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() { | 14061 void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() { | 
| 14083 if (!OptimizedCodeMapIsCleared()) { | 14062 if (!OptimizedCodeMapIsCleared()) { | 
| 14084 FixedArray* optimized_code_map = this->optimized_code_map(); | 14063 FixedArray* optimized_code_map = this->optimized_code_map(); | 
| 14085 int length = optimized_code_map->length(); | 14064 int length = optimized_code_map->length(); | 
| 14086 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 14065 WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell(); | 
| 14087 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 14066 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 
| 14088 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 14067 optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell, | 
| 14089 SKIP_WRITE_BARRIER); | 14068 SKIP_WRITE_BARRIER); | 
| 14090 } | 14069 } | 
| 14091 } | 14070 } | 
| 14092 } | 14071 } | 
| 14093 | 14072 | 
| 14094 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 14073 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 
| 14095 Context* native_context, BailoutId osr_ast_id) { | 14074 Context* native_context, BailoutId osr_ast_id) { | 
| 14096 CodeAndLiterals result = {nullptr, nullptr}; | 14075 CodeAndLiterals result = {nullptr, nullptr}; | 
| 14097 int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id); | 14076 if (!osr_ast_id.IsNone()) { | 
| 14077 Code* code; | |
| 14078 LiteralsArray* literals; | |
| 14079 native_context->SearchOptimizedCodeMap(this, osr_ast_id, &code, &literals); | |
| 14080 result = {code, literals}; | |
| 14081 return result; | |
| 14082 } | |
| 14083 | |
| 14084 DCHECK(osr_ast_id.IsNone()); | |
| 14085 int entry = SearchOptimizedCodeMapEntry(native_context); | |
| 14098 if (entry != kNotFound) { | 14086 if (entry != kNotFound) { | 
| 14099 FixedArray* code_map = optimized_code_map(); | 14087 FixedArray* code_map = optimized_code_map(); | 
| 14100 DCHECK_LE(entry + kEntryLength, code_map->length()); | 14088 DCHECK_LE(entry + kEntryLength, code_map->length()); | 
| 14101 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 14089 WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset)); | 
| 14102 WeakCell* literals_cell = | 14090 WeakCell* literals_cell = | 
| 14103 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); | 14091 WeakCell::cast(code_map->get(entry + kLiteralsOffset)); | 
| 14104 | 14092 | 
| 14105 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | 14093 result = {cell->cleared() ? nullptr : Code::cast(cell->value()), | 
| 14106 literals_cell->cleared() ? nullptr : LiteralsArray::cast( | 14094 literals_cell->cleared() ? nullptr : LiteralsArray::cast( | 
| 14107 literals_cell->value())}; | 14095 literals_cell->value())}; | 
| (...skipping 6298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 20406 // depend on this. | 20394 // depend on this. | 
| 20407 return DICTIONARY_ELEMENTS; | 20395 return DICTIONARY_ELEMENTS; | 
| 20408 } | 20396 } | 
| 20409 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20397 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 
| 20410 return kind; | 20398 return kind; | 
| 20411 } | 20399 } | 
| 20412 } | 20400 } | 
| 20413 | 20401 | 
| 20414 } // namespace internal | 20402 } // namespace internal | 
| 20415 } // namespace v8 | 20403 } // namespace v8 | 
| OLD | NEW |