OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/deoptimizer.h" | 5 #include "src/deoptimizer.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/ast/prettyprinter.h" | 8 #include "src/ast/prettyprinter.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 #else | 31 #else |
32 EXECUTABLE, | 32 EXECUTABLE, |
33 #endif | 33 #endif |
34 NULL); | 34 NULL); |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator) | 38 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator) |
39 : allocator_(allocator), | 39 : allocator_(allocator), |
40 current_(NULL) { | 40 current_(NULL) { |
41 for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) { | 41 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) { |
42 deopt_entry_code_entries_[i] = -1; | 42 deopt_entry_code_entries_[i] = -1; |
43 deopt_entry_code_[i] = AllocateCodeChunk(allocator); | 43 deopt_entry_code_[i] = AllocateCodeChunk(allocator); |
44 } | 44 } |
45 } | 45 } |
46 | 46 |
47 | 47 |
48 DeoptimizerData::~DeoptimizerData() { | 48 DeoptimizerData::~DeoptimizerData() { |
49 for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) { | 49 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) { |
50 allocator_->Free(deopt_entry_code_[i]); | 50 allocator_->Free(deopt_entry_code_[i]); |
51 deopt_entry_code_[i] = NULL; | 51 deopt_entry_code_[i] = NULL; |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 | 55 |
56 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { | 56 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { |
57 if (function_->IsHeapObject()) { | 57 if (function_->IsHeapObject()) { |
58 // Search all deoptimizing code in the native context of the function. | 58 // Search all deoptimizing code in the native context of the function. |
59 Context* native_context = function_->context()->native_context(); | 59 Context* native_context = function_->context()->native_context(); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 deoptimizer->DoComputeOutputFrames(); | 437 deoptimizer->DoComputeOutputFrames(); |
438 } | 438 } |
439 | 439 |
440 | 440 |
441 bool Deoptimizer::TraceEnabledFor(BailoutType deopt_type, | 441 bool Deoptimizer::TraceEnabledFor(BailoutType deopt_type, |
442 StackFrame::Type frame_type) { | 442 StackFrame::Type frame_type) { |
443 switch (deopt_type) { | 443 switch (deopt_type) { |
444 case EAGER: | 444 case EAGER: |
445 case SOFT: | 445 case SOFT: |
446 case LAZY: | 446 case LAZY: |
447 case DEBUGGER: | |
448 return (frame_type == StackFrame::STUB) | 447 return (frame_type == StackFrame::STUB) |
449 ? FLAG_trace_stub_failures | 448 ? FLAG_trace_stub_failures |
450 : FLAG_trace_deopt; | 449 : FLAG_trace_deopt; |
451 } | 450 } |
452 FATAL("Unsupported deopt type"); | 451 FATAL("Unsupported deopt type"); |
453 return false; | 452 return false; |
454 } | 453 } |
455 | 454 |
456 | 455 |
457 const char* Deoptimizer::MessageFor(BailoutType type) { | 456 const char* Deoptimizer::MessageFor(BailoutType type) { |
458 switch (type) { | 457 switch (type) { |
459 case EAGER: return "eager"; | 458 case EAGER: return "eager"; |
460 case SOFT: return "soft"; | 459 case SOFT: return "soft"; |
461 case LAZY: return "lazy"; | 460 case LAZY: return "lazy"; |
462 case DEBUGGER: return "debugger"; | |
463 } | 461 } |
464 FATAL("Unsupported deopt type"); | 462 FATAL("Unsupported deopt type"); |
465 return NULL; | 463 return NULL; |
466 } | 464 } |
467 | 465 |
468 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, | 466 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, |
469 BailoutType type, unsigned bailout_id, Address from, | 467 BailoutType type, unsigned bailout_id, Address from, |
470 int fp_to_sp_delta, Code* optimized_code) | 468 int fp_to_sp_delta, Code* optimized_code) |
471 : isolate_(isolate), | 469 : isolate_(isolate), |
472 function_(function), | 470 function_(function), |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 Code* optimized_code) { | 536 Code* optimized_code) { |
539 switch (bailout_type_) { | 537 switch (bailout_type_) { |
540 case Deoptimizer::SOFT: | 538 case Deoptimizer::SOFT: |
541 case Deoptimizer::EAGER: | 539 case Deoptimizer::EAGER: |
542 case Deoptimizer::LAZY: { | 540 case Deoptimizer::LAZY: { |
543 Code* compiled_code = FindDeoptimizingCode(from_); | 541 Code* compiled_code = FindDeoptimizingCode(from_); |
544 return (compiled_code == NULL) | 542 return (compiled_code == NULL) |
545 ? static_cast<Code*>(isolate_->FindCodeObject(from_)) | 543 ? static_cast<Code*>(isolate_->FindCodeObject(from_)) |
546 : compiled_code; | 544 : compiled_code; |
547 } | 545 } |
548 case Deoptimizer::DEBUGGER: | |
549 DCHECK(optimized_code->contains(from_)); | |
550 return optimized_code; | |
551 } | 546 } |
552 FATAL("Could not find code for optimized function"); | 547 FATAL("Could not find code for optimized function"); |
553 return NULL; | 548 return NULL; |
554 } | 549 } |
555 | 550 |
556 | 551 |
557 void Deoptimizer::PrintFunctionName() { | 552 void Deoptimizer::PrintFunctionName() { |
558 if (function_->IsJSFunction()) { | 553 if (function_->IsJSFunction()) { |
559 function_->ShortPrint(trace_scope_->file()); | 554 function_->ShortPrint(trace_scope_->file()); |
560 } else { | 555 } else { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 BailoutType type, | 588 BailoutType type, |
594 GetEntryMode mode) { | 589 GetEntryMode mode) { |
595 CHECK_GE(id, 0); | 590 CHECK_GE(id, 0); |
596 if (id >= kMaxNumberOfEntries) return NULL; | 591 if (id >= kMaxNumberOfEntries) return NULL; |
597 if (mode == ENSURE_ENTRY_CODE) { | 592 if (mode == ENSURE_ENTRY_CODE) { |
598 EnsureCodeForDeoptimizationEntry(isolate, type, id); | 593 EnsureCodeForDeoptimizationEntry(isolate, type, id); |
599 } else { | 594 } else { |
600 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS); | 595 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS); |
601 } | 596 } |
602 DeoptimizerData* data = isolate->deoptimizer_data(); | 597 DeoptimizerData* data = isolate->deoptimizer_data(); |
603 CHECK_LT(type, kBailoutTypesWithCodeEntry); | 598 CHECK_LE(type, kLastBailoutType); |
604 MemoryChunk* base = data->deopt_entry_code_[type]; | 599 MemoryChunk* base = data->deopt_entry_code_[type]; |
605 return base->area_start() + (id * table_entry_size_); | 600 return base->area_start() + (id * table_entry_size_); |
606 } | 601 } |
607 | 602 |
608 | 603 |
609 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, | 604 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, |
610 Address addr, | 605 Address addr, |
611 BailoutType type) { | 606 BailoutType type) { |
612 DeoptimizerData* data = isolate->deoptimizer_data(); | 607 DeoptimizerData* data = isolate->deoptimizer_data(); |
613 MemoryChunk* base = data->deopt_entry_code_[type]; | 608 MemoryChunk* base = data->deopt_entry_code_[type]; |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 output_frame->SetPc(pc_value); | 1039 output_frame->SetPc(pc_value); |
1045 | 1040 |
1046 // If we are going to the catch handler, then the exception lives in | 1041 // If we are going to the catch handler, then the exception lives in |
1047 // the accumulator. | 1042 // the accumulator. |
1048 FullCodeGenerator::State state = | 1043 FullCodeGenerator::State state = |
1049 goto_catch_handler ? FullCodeGenerator::TOS_REG | 1044 goto_catch_handler ? FullCodeGenerator::TOS_REG |
1050 : FullCodeGenerator::StateField::decode(pc_and_state); | 1045 : FullCodeGenerator::StateField::decode(pc_and_state); |
1051 output_frame->SetState(Smi::FromInt(state)); | 1046 output_frame->SetState(Smi::FromInt(state)); |
1052 | 1047 |
1053 // Set the continuation for the topmost frame. | 1048 // Set the continuation for the topmost frame. |
1054 if (is_topmost && bailout_type_ != DEBUGGER) { | 1049 if (is_topmost) { |
1055 Builtins* builtins = isolate_->builtins(); | 1050 Builtins* builtins = isolate_->builtins(); |
1056 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1051 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
1057 if (bailout_type_ == LAZY) { | 1052 if (bailout_type_ == LAZY) { |
1058 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1053 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
1059 } else if (bailout_type_ == SOFT) { | 1054 } else if (bailout_type_ == SOFT) { |
1060 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); | 1055 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
1061 } else { | 1056 } else { |
1062 CHECK_EQ(bailout_type_, EAGER); | 1057 CHECK_EQ(bailout_type_, EAGER); |
1063 } | 1058 } |
1064 output_frame->SetContinuation( | 1059 output_frame->SetContinuation( |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool()); | 1287 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool()); |
1293 output_frame->SetConstantPool(constant_pool_value); | 1288 output_frame->SetConstantPool(constant_pool_value); |
1294 if (is_topmost) { | 1289 if (is_topmost) { |
1295 Register constant_pool_reg = | 1290 Register constant_pool_reg = |
1296 InterpretedFrame::constant_pool_pointer_register(); | 1291 InterpretedFrame::constant_pool_pointer_register(); |
1297 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); | 1292 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
1298 } | 1293 } |
1299 } | 1294 } |
1300 | 1295 |
1301 // Set the continuation for the topmost frame. | 1296 // Set the continuation for the topmost frame. |
1302 if (is_topmost && bailout_type_ != DEBUGGER) { | 1297 if (is_topmost) { |
1303 Code* continuation = | 1298 Code* continuation = |
1304 builtins->builtin(Builtins::kInterpreterNotifyDeoptimized); | 1299 builtins->builtin(Builtins::kInterpreterNotifyDeoptimized); |
1305 if (bailout_type_ == LAZY) { | 1300 if (bailout_type_ == LAZY) { |
1306 continuation = | 1301 continuation = |
1307 builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized); | 1302 builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized); |
1308 } else if (bailout_type_ == SOFT) { | 1303 } else if (bailout_type_ == SOFT) { |
1309 continuation = | 1304 continuation = |
1310 builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized); | 1305 builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized); |
1311 } else { | 1306 } else { |
1312 CHECK_EQ(bailout_type_, EAGER); | 1307 CHECK_EQ(bailout_type_, EAGER); |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1917 } | 1912 } |
1918 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | 1913 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
1919 Code* notify_failure = | 1914 Code* notify_failure = |
1920 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); | 1915 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); |
1921 output_frame->SetContinuation( | 1916 output_frame->SetContinuation( |
1922 reinterpret_cast<intptr_t>(notify_failure->entry())); | 1917 reinterpret_cast<intptr_t>(notify_failure->entry())); |
1923 } | 1918 } |
1924 | 1919 |
1925 | 1920 |
1926 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { | 1921 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { |
1927 DCHECK_NE(DEBUGGER, bailout_type_); | |
1928 | |
1929 // Walk to the last JavaScript output frame to find out if it has | 1922 // Walk to the last JavaScript output frame to find out if it has |
1930 // adapted arguments. | 1923 // adapted arguments. |
1931 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { | 1924 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { |
1932 if (frame_index != 0) it->Advance(); | 1925 if (frame_index != 0) it->Advance(); |
1933 } | 1926 } |
1934 translated_state_.Prepare(it->frame()->has_adapted_arguments(), stack_fp_); | 1927 translated_state_.Prepare(it->frame()->has_adapted_arguments(), stack_fp_); |
1935 | 1928 |
1936 for (auto& materialization : values_to_materialize_) { | 1929 for (auto& materialization : values_to_materialize_) { |
1937 Handle<Object> value = materialization.value_->GetValue(); | 1930 Handle<Object> value = materialization.value_->GetValue(); |
1938 | 1931 |
(...skipping 1799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3738 CHECK(value_info->IsMaterializedObject()); | 3731 CHECK(value_info->IsMaterializedObject()); |
3739 | 3732 |
3740 value_info->value_ = | 3733 value_info->value_ = |
3741 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3734 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3742 } | 3735 } |
3743 } | 3736 } |
3744 } | 3737 } |
3745 | 3738 |
3746 } // namespace internal | 3739 } // namespace internal |
3747 } // namespace v8 | 3740 } // namespace v8 |
OLD | NEW |