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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) { | 49 for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) { |
50 allocator_->Free<MemoryAllocator::kFull>(deopt_entry_code_[i]); | 50 allocator_->Free<MemoryAllocator::kFull>(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 Isolate* isolate = function_->GetIsolate(); |
59 Context* native_context = function_->context()->native_context(); | 60 Context* native_context = function_->context()->native_context(); |
60 Object* element = native_context->DeoptimizedCodeListHead(); | 61 Object* element = native_context->DeoptimizedCodeListHead(); |
61 while (!element->IsUndefined()) { | 62 while (!element->IsUndefined(isolate)) { |
62 Code* code = Code::cast(element); | 63 Code* code = Code::cast(element); |
63 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 64 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
64 if (code->contains(addr)) return code; | 65 if (code->contains(addr)) return code; |
65 element = code->next_code_link(); | 66 element = code->next_code_link(); |
66 } | 67 } |
67 } | 68 } |
68 return NULL; | 69 return NULL; |
69 } | 70 } |
70 | 71 |
71 | 72 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 DisallowHeapAllocation no_allocation; | 180 DisallowHeapAllocation no_allocation; |
180 | 181 |
181 CHECK(context->IsNativeContext()); | 182 CHECK(context->IsNativeContext()); |
182 | 183 |
183 visitor->EnterContext(context); | 184 visitor->EnterContext(context); |
184 | 185 |
185 // Visit the list of optimized functions, removing elements that | 186 // Visit the list of optimized functions, removing elements that |
186 // no longer refer to optimized code. | 187 // no longer refer to optimized code. |
187 JSFunction* prev = NULL; | 188 JSFunction* prev = NULL; |
188 Object* element = context->OptimizedFunctionsListHead(); | 189 Object* element = context->OptimizedFunctionsListHead(); |
189 while (!element->IsUndefined()) { | 190 Isolate* isolate = context->GetIsolate(); |
| 191 while (!element->IsUndefined(isolate)) { |
190 JSFunction* function = JSFunction::cast(element); | 192 JSFunction* function = JSFunction::cast(element); |
191 Object* next = function->next_function_link(); | 193 Object* next = function->next_function_link(); |
192 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION || | 194 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION || |
193 (visitor->VisitFunction(function), | 195 (visitor->VisitFunction(function), |
194 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) { | 196 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) { |
195 // The function no longer refers to optimized code, or the visitor | 197 // The function no longer refers to optimized code, or the visitor |
196 // changed the code to which it refers to no longer be optimized code. | 198 // changed the code to which it refers to no longer be optimized code. |
197 // Remove the function from this list. | 199 // Remove the function from this list. |
198 if (prev != NULL) { | 200 if (prev != NULL) { |
199 prev->set_next_function_link(next, UPDATE_WEAK_WRITE_BARRIER); | 201 prev->set_next_function_link(next, UPDATE_WEAK_WRITE_BARRIER); |
(...skipping 19 matching lines...) Expand all Loading... |
219 } | 221 } |
220 | 222 |
221 | 223 |
222 void Deoptimizer::VisitAllOptimizedFunctions( | 224 void Deoptimizer::VisitAllOptimizedFunctions( |
223 Isolate* isolate, | 225 Isolate* isolate, |
224 OptimizedFunctionVisitor* visitor) { | 226 OptimizedFunctionVisitor* visitor) { |
225 DisallowHeapAllocation no_allocation; | 227 DisallowHeapAllocation no_allocation; |
226 | 228 |
227 // Run through the list of all native contexts. | 229 // Run through the list of all native contexts. |
228 Object* context = isolate->heap()->native_contexts_list(); | 230 Object* context = isolate->heap()->native_contexts_list(); |
229 while (!context->IsUndefined()) { | 231 while (!context->IsUndefined(isolate)) { |
230 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); | 232 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); |
231 context = Context::cast(context)->next_context_link(); | 233 context = Context::cast(context)->next_context_link(); |
232 } | 234 } |
233 } | 235 } |
234 | 236 |
235 | 237 |
236 // Unlink functions referring to code marked for deoptimization, then move | 238 // Unlink functions referring to code marked for deoptimization, then move |
237 // marked code from the optimized code list to the deoptimized code list, | 239 // marked code from the optimized code list to the deoptimized code list, |
238 // and patch code for lazy deopt. | 240 // and patch code for lazy deopt. |
239 void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { | 241 void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 #endif | 310 #endif |
309 | 311 |
310 // Move marked code from the optimized code list to the deoptimized | 312 // Move marked code from the optimized code list to the deoptimized |
311 // code list, collecting them into a ZoneList. | 313 // code list, collecting them into a ZoneList. |
312 Zone zone(isolate->allocator()); | 314 Zone zone(isolate->allocator()); |
313 ZoneList<Code*> codes(10, &zone); | 315 ZoneList<Code*> codes(10, &zone); |
314 | 316 |
315 // Walk over all optimized code objects in this native context. | 317 // Walk over all optimized code objects in this native context. |
316 Code* prev = NULL; | 318 Code* prev = NULL; |
317 Object* element = context->OptimizedCodeListHead(); | 319 Object* element = context->OptimizedCodeListHead(); |
318 while (!element->IsUndefined()) { | 320 while (!element->IsUndefined(isolate)) { |
319 Code* code = Code::cast(element); | 321 Code* code = Code::cast(element); |
320 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); | 322 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); |
321 Object* next = code->next_code_link(); | 323 Object* next = code->next_code_link(); |
322 | 324 |
323 if (code->marked_for_deoptimization()) { | 325 if (code->marked_for_deoptimization()) { |
324 // Put the code into the list for later patching. | 326 // Put the code into the list for later patching. |
325 codes.Add(code, &zone); | 327 codes.Add(code, &zone); |
326 | 328 |
327 if (prev != NULL) { | 329 if (prev != NULL) { |
328 // Skip this code in the optimized code list. | 330 // Skip this code in the optimized code list. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 &RuntimeCallStats::DeoptimizeCode); | 380 &RuntimeCallStats::DeoptimizeCode); |
379 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate); | 381 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate); |
380 TRACE_EVENT0("v8", "V8.DeoptimizeCode"); | 382 TRACE_EVENT0("v8", "V8.DeoptimizeCode"); |
381 if (FLAG_trace_deopt) { | 383 if (FLAG_trace_deopt) { |
382 CodeTracer::Scope scope(isolate->GetCodeTracer()); | 384 CodeTracer::Scope scope(isolate->GetCodeTracer()); |
383 PrintF(scope.file(), "[deoptimize all code in all contexts]\n"); | 385 PrintF(scope.file(), "[deoptimize all code in all contexts]\n"); |
384 } | 386 } |
385 DisallowHeapAllocation no_allocation; | 387 DisallowHeapAllocation no_allocation; |
386 // For all contexts, mark all code, then deoptimize. | 388 // For all contexts, mark all code, then deoptimize. |
387 Object* context = isolate->heap()->native_contexts_list(); | 389 Object* context = isolate->heap()->native_contexts_list(); |
388 while (!context->IsUndefined()) { | 390 while (!context->IsUndefined(isolate)) { |
389 Context* native_context = Context::cast(context); | 391 Context* native_context = Context::cast(context); |
390 MarkAllCodeForContext(native_context); | 392 MarkAllCodeForContext(native_context); |
391 DeoptimizeMarkedCodeForContext(native_context); | 393 DeoptimizeMarkedCodeForContext(native_context); |
392 context = native_context->next_context_link(); | 394 context = native_context->next_context_link(); |
393 } | 395 } |
394 } | 396 } |
395 | 397 |
396 | 398 |
397 void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) { | 399 void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) { |
398 RuntimeCallTimerScope runtimeTimer(isolate, | 400 RuntimeCallTimerScope runtimeTimer(isolate, |
399 &RuntimeCallStats::DeoptimizeCode); | 401 &RuntimeCallStats::DeoptimizeCode); |
400 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate); | 402 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate); |
401 TRACE_EVENT0("v8", "V8.DeoptimizeCode"); | 403 TRACE_EVENT0("v8", "V8.DeoptimizeCode"); |
402 if (FLAG_trace_deopt) { | 404 if (FLAG_trace_deopt) { |
403 CodeTracer::Scope scope(isolate->GetCodeTracer()); | 405 CodeTracer::Scope scope(isolate->GetCodeTracer()); |
404 PrintF(scope.file(), "[deoptimize marked code in all contexts]\n"); | 406 PrintF(scope.file(), "[deoptimize marked code in all contexts]\n"); |
405 } | 407 } |
406 DisallowHeapAllocation no_allocation; | 408 DisallowHeapAllocation no_allocation; |
407 // For all contexts, deoptimize code already marked. | 409 // For all contexts, deoptimize code already marked. |
408 Object* context = isolate->heap()->native_contexts_list(); | 410 Object* context = isolate->heap()->native_contexts_list(); |
409 while (!context->IsUndefined()) { | 411 while (!context->IsUndefined(isolate)) { |
410 Context* native_context = Context::cast(context); | 412 Context* native_context = Context::cast(context); |
411 DeoptimizeMarkedCodeForContext(native_context); | 413 DeoptimizeMarkedCodeForContext(native_context); |
412 context = native_context->next_context_link(); | 414 context = native_context->next_context_link(); |
413 } | 415 } |
414 } | 416 } |
415 | 417 |
416 | 418 |
417 void Deoptimizer::MarkAllCodeForContext(Context* context) { | 419 void Deoptimizer::MarkAllCodeForContext(Context* context) { |
418 Object* element = context->OptimizedCodeListHead(); | 420 Object* element = context->OptimizedCodeListHead(); |
419 while (!element->IsUndefined()) { | 421 Isolate* isolate = context->GetIsolate(); |
| 422 while (!element->IsUndefined(isolate)) { |
420 Code* code = Code::cast(element); | 423 Code* code = Code::cast(element); |
421 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); | 424 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); |
422 code->set_marked_for_deoptimization(true); | 425 code->set_marked_for_deoptimization(true); |
423 element = code->next_code_link(); | 426 element = code->next_code_link(); |
424 } | 427 } |
425 } | 428 } |
426 | 429 |
427 | 430 |
428 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { | 431 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
429 Isolate* isolate = function->GetIsolate(); | 432 Isolate* isolate = function->GetIsolate(); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 0xfefefeff); | 656 0xfefefeff); |
654 FATAL("unable to find pc offset during deoptimization"); | 657 FATAL("unable to find pc offset during deoptimization"); |
655 return -1; | 658 return -1; |
656 } | 659 } |
657 | 660 |
658 | 661 |
659 int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) { | 662 int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) { |
660 int length = 0; | 663 int length = 0; |
661 // Count all entries in the deoptimizing code list of every context. | 664 // Count all entries in the deoptimizing code list of every context. |
662 Object* context = isolate->heap()->native_contexts_list(); | 665 Object* context = isolate->heap()->native_contexts_list(); |
663 while (!context->IsUndefined()) { | 666 while (!context->IsUndefined(isolate)) { |
664 Context* native_context = Context::cast(context); | 667 Context* native_context = Context::cast(context); |
665 Object* element = native_context->DeoptimizedCodeListHead(); | 668 Object* element = native_context->DeoptimizedCodeListHead(); |
666 while (!element->IsUndefined()) { | 669 while (!element->IsUndefined(isolate)) { |
667 Code* code = Code::cast(element); | 670 Code* code = Code::cast(element); |
668 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 671 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
669 length++; | 672 length++; |
670 element = code->next_code_link(); | 673 element = code->next_code_link(); |
671 } | 674 } |
672 context = Context::cast(context)->next_context_link(); | 675 context = Context::cast(context)->next_context_link(); |
673 } | 676 } |
674 return length; | 677 return length; |
675 } | 678 } |
676 | 679 |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 // from just above the top of the operand stack (we push the context | 985 // from just above the top of the operand stack (we push the context |
983 // at the entry of the try block). | 986 // at the entry of the try block). |
984 if (goto_catch_handler) { | 987 if (goto_catch_handler) { |
985 for (unsigned i = 0; i < height + 1; ++i) { | 988 for (unsigned i = 0; i < height + 1; ++i) { |
986 context_pos++; | 989 context_pos++; |
987 context_input_index++; | 990 context_input_index++; |
988 } | 991 } |
989 } | 992 } |
990 // Read the context from the translations. | 993 // Read the context from the translations. |
991 Object* context = context_pos->GetRawValue(); | 994 Object* context = context_pos->GetRawValue(); |
992 if (context == isolate_->heap()->undefined_value()) { | 995 if (context->IsUndefined(isolate_)) { |
993 // If the context was optimized away, just use the context from | 996 // If the context was optimized away, just use the context from |
994 // the activation. This should only apply to Crankshaft code. | 997 // the activation. This should only apply to Crankshaft code. |
995 CHECK(!compiled_code_->is_turbofanned()); | 998 CHECK(!compiled_code_->is_turbofanned()); |
996 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_) | 999 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_) |
997 : function->context(); | 1000 : function->context(); |
998 } | 1001 } |
999 value = reinterpret_cast<intptr_t>(context); | 1002 value = reinterpret_cast<intptr_t>(context); |
1000 output_frame->SetContext(value); | 1003 output_frame->SetContext(value); |
1001 if (is_topmost) { | 1004 if (is_topmost) { |
1002 Register context_reg = JavaScriptFrame::context_register(); | 1005 Register context_reg = JavaScriptFrame::context_register(); |
(...skipping 2779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3782 Handle<Object> next_link = MaterializeAt(frame_index, value_index); | 3785 Handle<Object> next_link = MaterializeAt(frame_index, value_index); |
3783 object->ReplaceCode(*isolate_->builtins()->CompileLazy()); | 3786 object->ReplaceCode(*isolate_->builtins()->CompileLazy()); |
3784 object->set_map(*map); | 3787 object->set_map(*map); |
3785 object->set_properties(FixedArray::cast(*properties)); | 3788 object->set_properties(FixedArray::cast(*properties)); |
3786 object->set_elements(FixedArrayBase::cast(*elements)); | 3789 object->set_elements(FixedArrayBase::cast(*elements)); |
3787 object->set_prototype_or_initial_map(*prototype); | 3790 object->set_prototype_or_initial_map(*prototype); |
3788 object->set_shared(SharedFunctionInfo::cast(*shared)); | 3791 object->set_shared(SharedFunctionInfo::cast(*shared)); |
3789 object->set_context(Context::cast(*context)); | 3792 object->set_context(Context::cast(*context)); |
3790 object->set_literals(LiteralsArray::cast(*literals)); | 3793 object->set_literals(LiteralsArray::cast(*literals)); |
3791 CHECK(entry->IsNumber()); // Entry to compile lazy stub. | 3794 CHECK(entry->IsNumber()); // Entry to compile lazy stub. |
3792 CHECK(next_link->IsUndefined()); | 3795 CHECK(next_link->IsUndefined(isolate_)); |
3793 return object; | 3796 return object; |
3794 } | 3797 } |
3795 case FIXED_ARRAY_TYPE: { | 3798 case FIXED_ARRAY_TYPE: { |
3796 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index); | 3799 Handle<Object> lengthObject = MaterializeAt(frame_index, value_index); |
3797 int32_t length = 0; | 3800 int32_t length = 0; |
3798 CHECK(lengthObject->ToInt32(&length)); | 3801 CHECK(lengthObject->ToInt32(&length)); |
3799 Handle<FixedArray> object = | 3802 Handle<FixedArray> object = |
3800 isolate_->factory()->NewFixedArray(length); | 3803 isolate_->factory()->NewFixedArray(length); |
3801 // We need to set the map, because the fixed array we are | 3804 // We need to set the map, because the fixed array we are |
3802 // materializing could be a context or an arguments object, | 3805 // materializing could be a context or an arguments object, |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4014 CHECK(value_info->IsMaterializedObject()); | 4017 CHECK(value_info->IsMaterializedObject()); |
4015 | 4018 |
4016 value_info->value_ = | 4019 value_info->value_ = |
4017 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 4020 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
4018 } | 4021 } |
4019 } | 4022 } |
4020 } | 4023 } |
4021 | 4024 |
4022 } // namespace internal | 4025 } // namespace internal |
4023 } // namespace v8 | 4026 } // namespace v8 |
OLD | NEW |