Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 658cc5c2f92edeaf2fb44dc30bc3ec3aa2edd30c..a26d4d126383da97a64b7e05794ab7a9b293c01d 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -4173,6 +4173,33 @@ void HOptimizedGraphBuilder::VisitExpressions( |
} |
+void HOptimizedGraphBuilder::VisitCallArguments(ZoneList<Expression*>* args, |
+ HValue* function, |
+ bool* args_contain_arguments) { |
+ Handle<JSFunction> known_function; |
+ ArgumentsAllowedFlag is_arguments_allowed = ARGUMENTS_NOT_ALLOWED; |
+ if (function->IsConstant() && |
+ HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
+ known_function = Handle<JSFunction>::cast( |
+ HConstant::cast(function)->handle(isolate())); |
+ |
+ if (known_function->shared()->CanHandleArgumentsSafely()) { |
+ ASSERT(known_function->shared()->HasBuiltinFunctionId()); |
+ is_arguments_allowed = ARGUMENTS_ALLOWED; |
+ } |
+ } |
+ |
+ bool found_arguments = false; |
+ for (int i = 0; i < args->length(); i++) { |
+ CHECK_ALIVE(VisitForValue(args->at(i), is_arguments_allowed)); |
+ if (!found_arguments) |
+ found_arguments = Top()->CheckFlag(HValue::kIsArguments); |
+ } |
+ *args_contain_arguments = found_arguments; |
+ if (found_arguments) ASSERT(is_arguments_allowed == ARGUMENTS_ALLOWED); |
+} |
+ |
+ |
bool HOptimizedGraphBuilder::BuildGraph() { |
if (current_info()->function()->is_generator()) { |
Bailout(kFunctionIsAGenerator); |
@@ -8367,6 +8394,30 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
} |
+void HOptimizedGraphBuilder::InlineBuiltinWithArguments( |
+ Call* expr, |
+ HValue* function, |
+ Handle<Map> receiver_map, |
+ int args_count_no_receiver) { |
+ ASSERT(function->IsConstant() && |
+ HConstant::cast(function)->handle(isolate())->IsJSFunction()); |
+ Handle<JSFunction> known_function = Handle<JSFunction>::cast( |
+ HConstant::cast(function)->handle(isolate())); |
+ ASSERT(known_function->shared()->CanHandleArgumentsSafely()); |
+ ASSERT(known_function->shared()->HasBuiltinFunctionId()); |
+ if (TryInlineBuiltinMethodCall(expr, known_function, receiver_map, |
+ args_count_no_receiver)) { |
+ if (FLAG_trace_inlining) { |
+ PrintF("Inlining builtin "); |
+ known_function->ShortPrint(); |
+ PrintF("\n"); |
+ } |
+ } else { |
+ Bailout(kBadValueContextForArgumentsValue); |
+ } |
+} |
+ |
+ |
bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, |
HValue* receiver) { |
Handle<JSFunction> function = expr->target(); |
@@ -8660,20 +8711,25 @@ void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) { |
int args_length = args->length(); |
Drop(1); // call |
+ Push(function); |
+ bool have_arguments = false; |
if (args_length == 0) { |
- receiver = graph()->GetConstantUndefined(); |
+ receiver = BuildWrapReceiver(graph()->GetConstantUndefined(), function); |
args_length = 1; |
+ Push(receiver); |
} else { |
- CHECK_ALIVE(VisitForValue(args->at(0))); |
- receiver = Pop(); |
+ CHECK_ALIVE(VisitCallArguments(args, function, &have_arguments)); |
+ receiver = BuildWrapReceiver( |
+ environment()->ExpressionStackAt(args_length - 1), function); |
+ environment()->SetExpressionStackAt(args_length - 1, receiver); |
} |
- receiver = BuildWrapReceiver(receiver, function); |
- Push(function); |
- Push(receiver); |
- for (int i = 1; i < args_length; i++) { |
- CHECK_ALIVE(VisitForValue(args->at(i))); |
+ if (have_arguments) { |
+ Handle<Map> map; |
+ CHECK_BAILOUT(InlineBuiltinWithArguments(expr, function, map, |
+ args_length - 1)); |
} |
+ ASSERT(!have_arguments); |
HandleIndirectCall(expr, function, args_length); |
} |
@@ -8940,9 +8996,18 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
expr->set_target(known_function); |
if (TryIndirectCall(expr)) return; |
- CHECK_ALIVE(VisitExpressions(expr->arguments())); |
+ bool have_arguments = false; |
+ CHECK_ALIVE(VisitCallArguments(expr->arguments(), function, |
+ &have_arguments)); |
Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); |
+ if (have_arguments) { |
+ CHECK_BAILOUT(InlineBuiltinWithArguments(expr, |
+ function, |
+ map, |
+ expr->arguments()->length())); |
+ } |
+ ASSERT(!have_arguments); |
if (TryInlineBuiltinMethodCall(expr, known_function, map, |
expr->arguments()->length())) { |
if (FLAG_trace_inlining) { |