Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 003f4aefeee384ae8847cb3ece5576d56adce4ec..a015ab88b174247ca4735e81067eb712a7970f14 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -4074,8 +4074,12 @@ void EffectContext::ReturnValue(HValue* value) { |
void ValueContext::ReturnValue(HValue* value) { |
// The value is tracked in the bailout environment, and communicated |
// through the environment as the result of the expression. |
- if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { |
- owner()->Bailout(kBadValueContextForArgumentsValue); |
+ if (value->CheckFlag(HValue::kIsArguments)) { |
+ if (flag_ == ARGUMENTS_FAKED) { |
+ value = owner()->graph()->GetConstantUndefined(); |
+ } else if (!arguments_allowed()) { |
+ owner()->Bailout(kBadValueContextForArgumentsValue); |
+ } |
} |
owner()->Push(value); |
} |
@@ -4301,6 +4305,14 @@ void HOptimizedGraphBuilder::VisitExpressions( |
} |
+void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs, |
+ ArgumentsAllowedFlag flag) { |
+ for (int i = 0; i < exprs->length(); ++i) { |
+ CHECK_ALIVE(VisitForValue(exprs->at(i), flag)); |
+ } |
+} |
+ |
+ |
bool HOptimizedGraphBuilder::BuildGraph() { |
if (current_info()->function()->is_generator()) { |
Bailout(kFunctionIsAGenerator); |
@@ -8885,13 +8897,8 @@ bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { |
// is supported. |
if (current_info()->scope()->arguments() == NULL) return false; |
- ZoneList<Expression*>* args = expr->arguments(); |
- if (args->length() != 2) return false; |
+ if (!CanBeFunctionApplyArguments(expr)) return false; |
- VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
- if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
- HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
- if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
BuildFunctionApply(expr); |
return true; |
} |
@@ -9178,6 +9185,17 @@ bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr, |
} |
+bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) { |
+ ZoneList<Expression*>* args = expr->arguments(); |
+ if (args->length() != 2) return false; |
+ VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
+ if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
+ HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
+ if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
+ return true; |
+} |
+ |
+ |
void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
DCHECK(!HasStackOverflow()); |
DCHECK(current_block() != NULL); |
@@ -9214,13 +9232,14 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
- // Push the function under the receiver. |
- environment()->SetExpressionStackAt(0, function); |
- Push(receiver); |
if (function->IsConstant() && |
HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
+ // Push the function under the receiver. |
+ environment()->SetExpressionStackAt(0, function); |
+ Push(receiver); |
+ |
Handle<JSFunction> known_function = Handle<JSFunction>::cast( |
HConstant::cast(function)->handle(isolate())); |
expr->set_target(known_function); |
@@ -9256,7 +9275,20 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
} |
} else { |
- CHECK_ALIVE(VisitExpressions(expr->arguments())); |
+ ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
+ if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
+ // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
+ // gets ignored by the always-opt flag, which leads to incorrect code. |
+ Add<HDeoptimize>("Insufficient type feedback for call with arguments", |
+ Deoptimizer::EAGER); |
+ arguments_flag = ARGUMENTS_FAKED; |
+ } |
+ |
+ // Push the function under the receiver. |
+ environment()->SetExpressionStackAt(0, function); |
+ Push(receiver); |
+ |
+ CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
CallFunctionFlags flags = receiver->type().IsJSObject() |
? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
call = New<HCallFunction>(function, argument_count, flags); |