}
+// Disable optimization for the rest of the compilation pipeline.
void CompilationInfo::DisableOptimization() {
bool is_optimizable_closure =
FLAG_optimize_closures &&
}
+void CompilationInfo::AbortOptimization() {
+ Handle<Code> code(shared_info()->code());
+ SetCode(code);
+ Isolate* isolate = code->GetIsolate();
+ isolate->compilation_cache()->MarkForLazyOptimizing(closure());
+}
+
+
// Determine whether to use the full compiler for all code. If the flag
// --always-full-compiler is specified this is the case. For the virtual frame
// based compiler the full compiler is also used if a debugger is connected, as
}
-static void AbortAndDisable(CompilationInfo* info) {
- // Disable optimization for the shared function info and mark the
- // code as non-optimizable. The marker on the shared function info
- // is there because we flush non-optimized code thereby loosing the
- // non-optimizable information for the code. When the code is
- // regenerated and set on the shared function info it is marked as
- // non-optimizable if optimization is disabled for the shared
- // function info.
- Handle<SharedFunctionInfo> shared = info->shared_info();
- shared->set_optimization_disabled(true);
- Handle<Code> code = Handle<Code>(shared->code());
- ASSERT(code->kind() == Code::FUNCTION);
- code->set_optimizable(false);
- info->SetCode(code);
- Isolate* isolate = code->GetIsolate();
- isolate->compilation_cache()->MarkForLazyOptimizing(info->closure());
- if (FLAG_trace_opt) {
- PrintF("[disabled optimization for: ");
- info->closure()->PrintName();
- PrintF(" / %" V8PRIxPTR "]\n",
- reinterpret_cast<intptr_t>(*info->closure()));
- }
-}
-
-
static bool MakeCrankshaftCode(CompilationInfo* info) {
// Test if we can optimize this function when asked to. We can only
// do this after the scopes are computed.
const int kMaxOptCount =
FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
if (info->shared_info()->opt_count() > kMaxOptCount) {
- AbortAndDisable(info);
+ info->AbortOptimization();
+ Handle<JSFunction> closure = info->closure();
+ info->shared_info()->DisableOptimization(*closure);
// True indicates the compilation pipeline is still going, not
// necessarily that we optimized the code.
return true;
Scope* scope = info->scope();
if ((scope->num_parameters() + 1) > limit ||
scope->num_stack_slots() > limit) {
- AbortAndDisable(info);
+ info->AbortOptimization();
+ Handle<JSFunction> closure = info->closure();
+ info->shared_info()->DisableOptimization(*closure);
// True indicates the compilation pipeline is still going, not
// necessarily that we optimized the code.
return true;
}
}
- // Compilation with the Hydrogen compiler failed. Keep using the
- // shared code but mark it as unoptimizable.
- AbortAndDisable(info);
+ // Keep using the shared code.
+ info->AbortOptimization();
+ if (!builder.inline_bailout()) {
+ // Mark the shared code as unoptimizable unless it was an inlined
+ // function that bailed out.
+ Handle<JSFunction> closure = info->closure();
+ info->shared_info()->DisableOptimization(*closure);
+ }
// True indicates the compilation pipeline is still going, not necessarily
// that we optimized the code.
return true;
return V8::UseCrankshaft() && !closure_.is_null();
}
+ // Disable all optimization attempts of this info for the rest of the
+ // current compilation pipeline.
+ void AbortOptimization();
+
private:
Isolate* isolate_;
return GetConstant(&constant_false_, isolate()->heap()->false_value());
}
+HGraphBuilder::HGraphBuilder(CompilationInfo* info,
+ TypeFeedbackOracle* oracle)
+ : function_state_(NULL),
+ initial_function_state_(this, info, oracle),
+ ast_context_(NULL),
+ break_scope_(NULL),
+ graph_(NULL),
+ current_block_(NULL),
+ inlined_count_(0),
+ zone_(info->isolate()->zone()),
+ inline_bailout_(false) {
+ // This is not initialized in the initializer list because the
+ // constructor for the initial state relies on function_state_ == NULL
+ // to know it's the initial state.
+ function_state_= &initial_function_state_;
+}
HBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
HBasicBlock* second,
// Precondition: call is monomorphic and we have found a target with the
// appropriate arity.
- Handle<JSFunction> target = expr->target();
Handle<JSFunction> caller = info()->closure();
+ Handle<JSFunction> target = expr->target();
+ Handle<SharedFunctionInfo> target_shared(target->shared());
// Do a quick check on source code length to avoid parsing large
// inlining candidates.
}
// Don't inline recursive functions.
- if (target->shared() == outer_info->closure()->shared()) {
+ if (*target_shared == outer_info->closure()->shared()) {
TraceInline(target, caller, "target is recursive");
return false;
}
if (target_info.isolate()->has_pending_exception()) {
// Parse or scope error, never optimize this function.
SetStackOverflow();
- target->shared()->set_optimization_disabled(true);
+ target_shared->DisableOptimization(*target);
}
TraceInline(target, caller, "parse failure");
return false;
// Don't inline functions that uses the arguments object or that
// have a mismatching number of parameters.
- Handle<SharedFunctionInfo> target_shared(target->shared());
int arity = expr->arguments()->length();
if (function->scope()->arguments() != NULL ||
arity != target_shared->formal_parameter_count()) {
// Bail out if the inline function did, as we cannot residualize a call
// instead.
TraceInline(target, caller, "inline graph construction failed");
+ target_shared->DisableOptimization(*target);
+ inline_bailout_ = true;
return true;
}
BreakAndContinueScope* next_;
};
- HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle)
- : function_state_(NULL),
- initial_function_state_(this, info, oracle),
- ast_context_(NULL),
- break_scope_(NULL),
- graph_(NULL),
- current_block_(NULL),
- inlined_count_(0),
- zone_(info->isolate()->zone()) {
- // This is not initialized in the initializer list because the
- // constructor for the initial state relies on function_state_ == NULL
- // to know it's the initial state.
- function_state_= &initial_function_state_;
- }
+ HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle);
HGraph* CreateGraph();
return current_block()->last_environment();
}
+ bool inline_bailout() { return inline_bailout_; }
+
// Adding instructions.
HInstruction* AddInstruction(HInstruction* instr);
void AddSimulate(int id);
Zone* zone_;
+ bool inline_bailout_;
+
friend class FunctionState; // Pushes and pops the state stack.
friend class AstContext; // Pushes and pops the AST context stack.
}
+void SharedFunctionInfo::DisableOptimization(JSFunction* function) {
+ // Disable optimization for the shared function info and mark the
+ // code as non-optimizable. The marker on the shared function info
+ // is there because we flush non-optimized code thereby loosing the
+ // non-optimizable information for the code. When the code is
+ // regenerated and set on the shared function info it is marked as
+ // non-optimizable if optimization is disabled for the shared
+ // function info.
+ set_optimization_disabled(true);
+ // Code should be the lazy compilation stub or else unoptimized. If the
+ // latter, disable optimization for the code too.
+ ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
+ if (code()->kind() == Code::FUNCTION) {
+ code()->set_optimizable(false);
+ }
+ if (FLAG_trace_opt) {
+ PrintF("[disabled optimization for: ");
+ function->PrintName();
+ PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
+ }
+}
+
+
bool SharedFunctionInfo::VerifyBailoutId(int id) {
// TODO(srdjan): debugging ARM crashes in hydrogen. OK to disable while
// we are always bailing out on ARM.
// Enable deoptimization support through recompiled code.
void EnableDeoptimizationSupport(Code* recompiled);
+ // Disable (further) attempted optimization of all functions sharing this
+ // shared function info. The function is the one we actually tried to
+ // optimize.
+ void DisableOptimization(JSFunction* function);
+
// Lookup the bailout ID and ASSERT that it exists in the non-optimized
// code, returns whether it asserted (i.e., always true if assertions are
// disabled).