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 |