| 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) {
|
|
|