Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 8121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8132 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) { | 8132 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) { |
| 8133 HandleScope scope(isolate); | 8133 HandleScope scope(isolate); |
| 8134 ASSERT(args.length() == 1); | 8134 ASSERT(args.length() == 1); |
| 8135 Handle<JSFunction> function = args.at<JSFunction>(0); | 8135 Handle<JSFunction> function = args.at<JSFunction>(0); |
| 8136 | 8136 |
| 8137 if (!AllowOptimization(isolate, function)) { | 8137 if (!AllowOptimization(isolate, function)) { |
| 8138 function->ReplaceCode(function->shared()->code()); | 8138 function->ReplaceCode(function->shared()->code()); |
| 8139 return function->code(); | 8139 return function->code(); |
| 8140 } | 8140 } |
| 8141 function->shared()->code()->set_profiler_ticks(0); | 8141 function->shared()->code()->set_profiler_ticks(0); |
| 8142 if (JSFunction::CompileOptimized(function, | 8142 if (JSFunction::CompileOptimized(function, CLEAR_EXCEPTION)) { |
| 8143 BailoutId::None(), | |
| 8144 CLEAR_EXCEPTION)) { | |
| 8145 return function->code(); | 8143 return function->code(); |
| 8146 } | 8144 } |
| 8147 if (FLAG_trace_opt) { | 8145 if (FLAG_trace_opt) { |
| 8148 PrintF("[failed to optimize "); | 8146 PrintF("[failed to optimize "); |
| 8149 function->PrintName(); | 8147 function->PrintName(); |
| 8150 PrintF(": optimized compilation failed]\n"); | 8148 PrintF(": optimized compilation failed]\n"); |
| 8151 } | 8149 } |
| 8152 function->ReplaceCode(function->shared()->code()); | 8150 function->ReplaceCode(function->shared()->code()); |
| 8153 return function->code(); | 8151 return function->code(); |
| 8154 } | 8152 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8216 | 8214 |
| 8217 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) { | 8215 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) { |
| 8218 HandleScope scope(isolate); | 8216 HandleScope scope(isolate); |
| 8219 ASSERT(args.length() == 1); | 8217 ASSERT(args.length() == 1); |
| 8220 RUNTIME_ASSERT(args[0]->IsSmi()); | 8218 RUNTIME_ASSERT(args[0]->IsSmi()); |
| 8221 Deoptimizer::BailoutType type = | 8219 Deoptimizer::BailoutType type = |
| 8222 static_cast<Deoptimizer::BailoutType>(args.smi_at(0)); | 8220 static_cast<Deoptimizer::BailoutType>(args.smi_at(0)); |
| 8223 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); | 8221 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); |
| 8224 ASSERT(AllowHeapAllocation::IsAllowed()); | 8222 ASSERT(AllowHeapAllocation::IsAllowed()); |
| 8225 | 8223 |
| 8226 ASSERT(deoptimizer->compiled_code_kind() == Code::OPTIMIZED_FUNCTION); | 8224 Handle<Code> optimized_code(deoptimizer->compiled_code()); |
| 8225 ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION); | |
| 8226 | |
| 8227 Handle<JSFunction> function(deoptimizer->function()); | |
| 8228 ASSERT(!function.is_null()); | |
| 8227 | 8229 |
| 8228 // Make sure to materialize objects before causing any allocation. | 8230 // Make sure to materialize objects before causing any allocation. |
| 8229 JavaScriptFrameIterator it(isolate); | 8231 JavaScriptFrameIterator it(isolate); |
| 8230 deoptimizer->MaterializeHeapObjects(&it); | 8232 deoptimizer->MaterializeHeapObjects(&it); |
| 8231 delete deoptimizer; | 8233 delete deoptimizer; |
| 8232 | 8234 |
| 8233 JavaScriptFrame* frame = it.frame(); | 8235 JavaScriptFrame* frame = it.frame(); |
| 8234 RUNTIME_ASSERT(frame->function()->IsJSFunction()); | |
| 8235 Handle<JSFunction> function(frame->function(), isolate); | |
| 8236 Handle<Code> optimized_code(function->code()); | |
| 8237 RUNTIME_ASSERT((type != Deoptimizer::EAGER && | |
| 8238 type != Deoptimizer::SOFT) || function->IsOptimized()); | |
| 8239 | 8236 |
| 8237 ASSERT(frame->function() == *function); | |
| 8240 // Avoid doing too much work when running with --always-opt and keep | 8238 // Avoid doing too much work when running with --always-opt and keep |
| 8241 // the optimized code around. | 8239 // the optimized code around. |
| 8242 if (FLAG_always_opt || type == Deoptimizer::LAZY) { | 8240 if (FLAG_always_opt || type == Deoptimizer::LAZY) { |
| 8243 return isolate->heap()->undefined_value(); | 8241 return isolate->heap()->undefined_value(); |
| 8244 } | 8242 } |
| 8245 | 8243 |
| 8246 // Find other optimized activations of the function or functions that | 8244 // Find other activations of the optimized code. |
| 8247 // share the same optimized code. | |
| 8248 bool has_other_activations = false; | 8245 bool has_other_activations = false; |
| 8249 while (!it.done()) { | 8246 while (!it.done()) { |
| 8250 JavaScriptFrame* frame = it.frame(); | 8247 if (it.frame()->function()->code() == *optimized_code) { |
|
Michael Starzinger
2013/08/01 09:25:30
Yep, this method is looking good to me now.
| |
| 8251 JSFunction* other_function = frame->function(); | |
| 8252 if (frame->is_optimized() && other_function->code() == function->code()) { | |
| 8253 has_other_activations = true; | 8248 has_other_activations = true; |
| 8254 break; | 8249 break; |
| 8255 } | 8250 } |
| 8256 it.Advance(); | 8251 it.Advance(); |
| 8257 } | 8252 } |
| 8258 | 8253 |
| 8259 if (!has_other_activations) { | 8254 if (!has_other_activations) { |
| 8260 ActivationsFinder activations_finder(*function); | 8255 ActivationsFinder activations_finder(*function); |
| 8261 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); | 8256 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); |
| 8262 has_other_activations = activations_finder.has_activations(); | 8257 has_other_activations = activations_finder.has_activations(); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8432 // Check for optimized activations of this function. | 8427 // Check for optimized activations of this function. |
| 8433 JavaScriptFrameIterator it(isolate); | 8428 JavaScriptFrameIterator it(isolate); |
| 8434 while (succeeded && !it.done()) { | 8429 while (succeeded && !it.done()) { |
| 8435 JavaScriptFrame* frame = it.frame(); | 8430 JavaScriptFrame* frame = it.frame(); |
| 8436 succeeded = !frame->is_optimized() || frame->function() != *function; | 8431 succeeded = !frame->is_optimized() || frame->function() != *function; |
| 8437 it.Advance(); | 8432 it.Advance(); |
| 8438 } | 8433 } |
| 8439 } | 8434 } |
| 8440 | 8435 |
| 8441 BailoutId ast_id = BailoutId::None(); | 8436 BailoutId ast_id = BailoutId::None(); |
| 8437 Handle<Code> osr_code = Handle<Code>::null(); | |
| 8442 if (succeeded) { | 8438 if (succeeded) { |
| 8443 // The top JS function is this one, the PC is somewhere in the | 8439 // The top JS function is this one, the PC is somewhere in the |
| 8444 // unoptimized code. | 8440 // unoptimized code. |
| 8445 JavaScriptFrameIterator it(isolate); | 8441 JavaScriptFrameIterator it(isolate); |
| 8446 JavaScriptFrame* frame = it.frame(); | 8442 JavaScriptFrame* frame = it.frame(); |
| 8447 ASSERT(frame->function() == *function); | 8443 ASSERT(frame->function() == *function); |
| 8448 ASSERT(frame->LookupCode() == *unoptimized); | 8444 ASSERT(frame->LookupCode() == *unoptimized); |
| 8449 ASSERT(unoptimized->contains(frame->pc())); | 8445 ASSERT(unoptimized->contains(frame->pc())); |
| 8450 | 8446 |
| 8451 // Use linear search of the unoptimized code's back edge table to find | 8447 // Use linear search of the unoptimized code's back edge table to find |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 8467 table_cursor += FullCodeGenerator::kBackEdgeEntrySize; | 8463 table_cursor += FullCodeGenerator::kBackEdgeEntrySize; |
| 8468 } | 8464 } |
| 8469 ASSERT(!ast_id.IsNone()); | 8465 ASSERT(!ast_id.IsNone()); |
| 8470 if (FLAG_trace_osr) { | 8466 if (FLAG_trace_osr) { |
| 8471 PrintF("[replacing on-stack at AST id %d, loop depth %d in ", | 8467 PrintF("[replacing on-stack at AST id %d, loop depth %d in ", |
| 8472 ast_id.ToInt(), loop_depth); | 8468 ast_id.ToInt(), loop_depth); |
| 8473 function->PrintName(); | 8469 function->PrintName(); |
| 8474 PrintF("]\n"); | 8470 PrintF("]\n"); |
| 8475 } | 8471 } |
| 8476 | 8472 |
| 8477 // Try to compile the optimized code. A true return value from | 8473 // Try to compile the function for OSR. A non-null return value indicates |
| 8478 // CompileOptimized means that compilation succeeded, not necessarily | 8474 // the compilation succeeded for the given AST id. |
| 8479 // that optimization succeeded. | 8475 osr_code = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION); |
| 8480 if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) && | 8476 |
| 8481 function->IsOptimized()) { | 8477 if (!osr_code.is_null() && |
| 8478 osr_code->kind() == Code::OPTIMIZED_FUNCTION) { | |
| 8482 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 8479 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 8483 function->code()->deoptimization_data()); | 8480 osr_code->deoptimization_data()); |
| 8484 if (data->OsrPcOffset()->value() >= 0) { | 8481 if (data->OsrPcOffset()->value() >= 0 |
| 8482 && BailoutId(data->OsrAstId()->value()) == ast_id) { | |
| 8485 if (FLAG_trace_osr) { | 8483 if (FLAG_trace_osr) { |
| 8486 PrintF("[on-stack replacement offset %d in optimized code]\n", | 8484 PrintF("[on-stack replacement offset %d in optimized code]\n", |
| 8487 data->OsrPcOffset()->value()); | 8485 data->OsrPcOffset()->value()); |
| 8488 } | 8486 } |
| 8489 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); | |
| 8490 } else { | 8487 } else { |
| 8491 // We may never generate the desired OSR entry if we emit an | 8488 // The code we got back did not match our OSR compile request. |
| 8492 // early deoptimize. | 8489 osr_code = Handle<Code>::null(); |
| 8493 succeeded = false; | |
| 8494 } | 8490 } |
| 8495 } else { | 8491 } else { |
| 8496 succeeded = false; | 8492 osr_code = Handle<Code>::null(); |
| 8497 } | 8493 } |
| 8498 } | 8494 } |
| 8499 | 8495 |
| 8500 // Revert to the original interrupt calls in the original unoptimized code. | 8496 // Revert to the original interrupt calls in the original unoptimized code. |
| 8501 if (FLAG_trace_osr) { | 8497 if (FLAG_trace_osr) { |
| 8502 PrintF("[restoring original interrupt calls in "); | 8498 PrintF("[restoring original interrupt calls in "); |
| 8503 function->PrintName(); | 8499 function->PrintName(); |
| 8504 PrintF("]\n"); | 8500 PrintF("]\n"); |
| 8505 } | 8501 } |
| 8506 InterruptStub interrupt_stub; | 8502 InterruptStub interrupt_stub; |
| 8507 Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate); | 8503 Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate); |
| 8508 Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement(); | 8504 Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement(); |
| 8509 Deoptimizer::RevertInterruptCode(*unoptimized, | 8505 Deoptimizer::RevertInterruptCode(*unoptimized, |
| 8510 *interrupt_code, | 8506 *interrupt_code, |
| 8511 *replacement_code); | 8507 *replacement_code); |
| 8512 | 8508 |
| 8513 // If the optimization attempt succeeded, return the AST id tagged as a | 8509 // Return the code object to the calling builtin. If non-null, the builtin |
| 8514 // smi. This tells the builtin that we need to translate the unoptimized | 8510 // will jump directly to its OSR entrypoint. |
| 8515 // frame to an optimized one. | 8511 return osr_code.is_null() ? NULL : *osr_code; |
| 8516 if (succeeded) { | |
| 8517 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); | |
| 8518 return Smi::FromInt(ast_id.ToInt()); | |
| 8519 } else { | |
| 8520 if (function->IsMarkedForLazyRecompilation()) { | |
| 8521 function->ReplaceCode(function->shared()->code()); | |
| 8522 } | |
| 8523 return Smi::FromInt(-1); | |
| 8524 } | |
| 8525 } | 8512 } |
| 8526 | 8513 |
| 8527 | 8514 |
| 8528 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) { | 8515 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) { |
| 8529 SealHandleScope shs(isolate); | 8516 SealHandleScope shs(isolate); |
| 8530 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); | 8517 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); |
| 8531 return isolate->heap()->undefined_value(); | 8518 return isolate->heap()->undefined_value(); |
| 8532 } | 8519 } |
| 8533 | 8520 |
| 8534 | 8521 |
| (...skipping 5323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13858 // Handle last resort GC and make sure to allow future allocations | 13845 // Handle last resort GC and make sure to allow future allocations |
| 13859 // to grow the heap without causing GCs (if possible). | 13846 // to grow the heap without causing GCs (if possible). |
| 13860 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13847 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13861 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13848 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 13862 "Runtime::PerformGC"); | 13849 "Runtime::PerformGC"); |
| 13863 } | 13850 } |
| 13864 } | 13851 } |
| 13865 | 13852 |
| 13866 | 13853 |
| 13867 } } // namespace v8::internal | 13854 } } // namespace v8::internal |
| OLD | NEW |