| 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 3285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3962 CHECK(value_info->IsMaterializedObject()); | 3965 CHECK(value_info->IsMaterializedObject()); |
| 3963 | 3966 |
| 3964 value_info->value_ = | 3967 value_info->value_ = |
| 3965 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3968 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
| 3966 } | 3969 } |
| 3967 } | 3970 } |
| 3968 } | 3971 } |
| 3969 | 3972 |
| 3970 } // namespace internal | 3973 } // namespace internal |
| 3971 } // namespace v8 | 3974 } // namespace v8 |
| OLD | NEW |