| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 091fcf7d17fc361951c46267fcf278ffa0dccd03..a858a407add6b8e947279bf2a75e92988a6029ea 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -3950,9 +3950,7 @@ void HGraph::RestoreActualValues() {
|
| }
|
|
|
|
|
| -template <class Instruction>
|
| -HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
|
| - int count = call->argument_count();
|
| +void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
|
| ZoneList<HValue*> arguments(count, zone());
|
| for (int i = 0; i < count; ++i) {
|
| arguments.Add(Pop(), zone());
|
| @@ -3961,6 +3959,12 @@ HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
|
| while (!arguments.is_empty()) {
|
| Add<HPushArgument>(arguments.RemoveLast());
|
| }
|
| +}
|
| +
|
| +
|
| +template <class Instruction>
|
| +HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
|
| + PushArgumentsFromEnvironment(call->argument_count());
|
| return call;
|
| }
|
|
|
| @@ -5532,7 +5536,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
|
| return NULL;
|
| }
|
| Add<HPushArgument>(Pop());
|
| - return New<HCallConstantFunction>(info->accessor(), 1);
|
| + return BuildCallConstantFunction(info->accessor(), 1);
|
| }
|
|
|
| ASSERT(info->lookup()->IsConstant());
|
| @@ -5817,7 +5821,7 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr,
|
| Drop(2);
|
| Add<HPushArgument>(object);
|
| Add<HPushArgument>(value);
|
| - instr = New<HCallConstantFunction>(setter, 2);
|
| + instr = BuildCallConstantFunction(setter, 2);
|
| } else {
|
| Drop(2);
|
| CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
|
| @@ -6779,6 +6783,86 @@ void HOptimizedGraphBuilder::AddCheckConstantFunction(
|
| }
|
|
|
|
|
| +HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
|
| + HValue* fun, int argument_count, bool pass_argument_count) {
|
| + return New<HCallJSFunction>(
|
| + fun, argument_count, pass_argument_count);
|
| +}
|
| +
|
| +
|
| +HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
|
| + HValue* fun, HValue* context,
|
| + int argument_count, HValue* expected_param_count) {
|
| + CallInterfaceDescriptor* descriptor =
|
| + isolate()->call_descriptor(Isolate::ArgumentAdaptorCall);
|
| +
|
| + HValue* arity = Add<HConstant>(argument_count - 1);
|
| +
|
| + HValue* op_vals[] = { fun, context, arity, expected_param_count };
|
| +
|
| + Handle<Code> adaptor =
|
| + isolate()->builtins()->ArgumentsAdaptorTrampoline();
|
| + HConstant* adaptor_value = Add<HConstant>(adaptor);
|
| +
|
| + return New<HCallWithDescriptor>(
|
| + adaptor_value, argument_count, descriptor,
|
| + Vector<HValue*>(op_vals, descriptor->environment_length()));
|
| +}
|
| +
|
| +
|
| +HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
|
| + Handle<JSFunction> jsfun, int argument_count) {
|
| + HValue* target = Add<HConstant>(jsfun);
|
| + // For constant functions, we try to avoid calling the
|
| + // argument adaptor and instead call the function directly
|
| + int formal_parameter_count = jsfun->shared()->formal_parameter_count();
|
| + bool dont_adapt_arguments =
|
| + (formal_parameter_count ==
|
| + SharedFunctionInfo::kDontAdaptArgumentsSentinel);
|
| + int arity = argument_count - 1;
|
| + bool can_invoke_directly =
|
| + dont_adapt_arguments || formal_parameter_count == arity;
|
| + if (can_invoke_directly) {
|
| + return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
|
| + } else {
|
| + HValue* param_count_value = Add<HConstant>(formal_parameter_count);
|
| + HValue* context = Add<HLoadNamedField>(target,
|
| + HObjectAccess::ForFunctionContextPointer());
|
| + return NewArgumentAdaptorCall(target, context,
|
| + argument_count, param_count_value);
|
| + }
|
| + UNREACHABLE();
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| +HInstruction* HOptimizedGraphBuilder::NewCallNamed(
|
| + Handle<String> name, int argument_count) {
|
| + CallInterfaceDescriptor* descriptor =
|
| + isolate()->call_descriptor(Isolate::NamedCall);
|
| + HValue* op_vals[] = { context(), Add<HConstant>(name) };
|
| + int arity = argument_count - 1;
|
| + Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity);
|
| +
|
| + return New<HCallWithDescriptor>(
|
| + Add<HConstant>(ic), argument_count, descriptor,
|
| + Vector<HValue*>(op_vals, descriptor->environment_length()));
|
| +}
|
| +
|
| +
|
| +HInstruction* HOptimizedGraphBuilder::NewCallKeyed(
|
| + HValue* key, int argument_count) {
|
| + CallInterfaceDescriptor* descriptor =
|
| + isolate()->call_descriptor(Isolate::KeyedCall);
|
| + HValue* op_vals[] = { context(), key };
|
| + int arity = argument_count - 1;
|
| + Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
|
| +
|
| + return New<HCallWithDescriptor>(
|
| + Add<HConstant>(ic), argument_count, descriptor,
|
| + Vector<HValue*>(op_vals, descriptor->environment_length()));
|
| +}
|
| +
|
| class FunctionSorter {
|
| public:
|
| FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
|
| @@ -6834,9 +6918,9 @@ bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
|
|
|
| if (!TryInlineCall(expr)) {
|
| int argument_count = expr->arguments()->length() + 1; // Includes receiver.
|
| - HCallConstantFunction* call =
|
| - New<HCallConstantFunction>(expr->target(), argument_count);
|
| - PreProcessCall(call);
|
| + HInstruction* call = BuildCallConstantFunction(
|
| + expr->target(), argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| AddInstruction(call);
|
| if (!ast_context()->IsEffect()) Push(call);
|
| Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
|
| @@ -6996,9 +7080,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
| // entire compilation by setting stack overflow on the visitor.
|
| if (HasStackOverflow()) return;
|
| } else {
|
| - HCallConstantFunction* call =
|
| - New<HCallConstantFunction>(expr->target(), argument_count);
|
| - PreProcessCall(call);
|
| + HInstruction* call = BuildCallConstantFunction(
|
| + expr->target(), argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| AddInstruction(call);
|
| if (!ast_context()->IsEffect()) Push(call);
|
| }
|
| @@ -7018,8 +7102,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
| if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
|
| FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
|
| } else {
|
| - HCallNamed* call = New<HCallNamed>(name, argument_count);
|
| - PreProcessCall(call);
|
| + HInstruction* call = NewCallNamed(name, argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
|
|
| if (join != NULL) {
|
| AddInstruction(call);
|
| @@ -7743,7 +7827,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
|
|
| call = New<HCallFunction>(function, argument_count);
|
| } else {
|
| - call = New<HCallKeyed>(key, argument_count);
|
| + call = NewCallKeyed(key, argument_count);
|
| }
|
| Drop(argument_count + 1); // 1 is the key.
|
| return ast_context()->ReturnInstruction(call, expr->id());
|
| @@ -7782,13 +7866,14 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| // When the target has a custom call IC generator, use the IC,
|
| // because it is likely to generate better code. Also use the IC
|
| // when a primitive receiver check is required.
|
| - call = PreProcessCall(New<HCallNamed>(name, argument_count));
|
| + call = NewCallNamed(name, argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| } else {
|
| AddCheckConstantFunction(expr->holder(), receiver, map);
|
|
|
| if (TryInlineCall(expr)) return;
|
| - call = PreProcessCall(
|
| - New<HCallConstantFunction>(expr->target(), argument_count));
|
| + call = BuildCallConstantFunction(expr->target(), argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| }
|
| } else if (types != NULL && types->length() > 1) {
|
| ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
|
| @@ -7796,7 +7881,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| return;
|
|
|
| } else {
|
| - call = PreProcessCall(New<HCallNamed>(name, argument_count));
|
| + call = NewCallNamed(name, argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| }
|
| } else {
|
| VariableProxy* proxy = expr->expression()->AsVariableProxy();
|
| @@ -7857,17 +7943,18 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
|
| environment()->SetExpressionStackAt(receiver_index, global_object);
|
| // When the target has a custom call IC generator, use the IC,
|
| // because it is likely to generate better code.
|
| - call = PreProcessCall(New<HCallNamed>(var->name(), argument_count));
|
| + call = NewCallNamed(var->name(), argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| } else {
|
| - call = PreProcessCall(New<HCallKnownGlobal>(
|
| - expr->target(), argument_count));
|
| + call = BuildCallConstantFunction(expr->target(), argument_count);
|
| + PushArgumentsFromEnvironment(argument_count);
|
| }
|
| } else {
|
| HGlobalObject* receiver = Add<HGlobalObject>();
|
| Push(Add<HPushArgument>(receiver));
|
| CHECK_ALIVE(VisitArgumentList(expr->arguments()));
|
|
|
| - call = New<HCallNamed>(var->name(), argument_count);
|
| + call = NewCallNamed(var->name(), argument_count);
|
| Drop(argument_count);
|
| }
|
|
|
|
|