Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index cccfa5b041ee7ee3cf12f747f69dea295f0fcd32..74a535b7891b7135fde18d55eaa4b7936e5ac29d 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -3858,9 +3858,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()); |
| @@ -3869,6 +3867,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; |
| } |
| @@ -5451,7 +5455,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( |
| return NULL; |
| } |
| Add<HPushArgument>(Pop()); |
| - return New<HCallConstantFunction>(info->accessor(), 1); |
| + return BuildCallConstantFunction(info->accessor(), 1, CALL_AS_METHOD); |
| } |
| ASSERT(info->lookup()->IsConstant()); |
| @@ -5736,7 +5740,7 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr, |
| Drop(2); |
| Add<HPushArgument>(object); |
| Add<HPushArgument>(value); |
| - instr = New<HCallConstantFunction>(setter, 2); |
| + instr = BuildCallConstantFunction(setter, 2, CALL_AS_METHOD); |
| } else { |
| Drop(2); |
| CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| @@ -6686,6 +6690,100 @@ void HOptimizedGraphBuilder::AddCheckConstantFunction( |
| } |
| +HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall( |
| + HValue* fun, HValue* call_kind_value, |
| + int argument_count, bool pass_argument_count) { |
| + return New<HCallJSFunction>( |
| + fun, call_kind_value, argument_count, pass_argument_count); |
| +} |
| + |
| + |
| +HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( |
| + HValue* fun, HValue* context, HValue* call_kind_value, |
| + 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, call_kind_value, arity, |
|
Toon Verwaest
2014/01/14 15:33:50
HValue* op_vals
Jarin
2014/01/14 19:08:08
Done.
|
| + 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, CallKind call_kind) { |
| + HValue* target = Add<HConstant>(jsfun); |
| + HValue* call_kind_value = Add<HConstant>(static_cast<int>(call_kind)); |
| + // 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, call_kind_value, |
| + 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, call_kind_value, |
| + 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* name_val = Add<HConstant>(name); |
| + HValue* op_vals[] = { context(), name_val }; |
| + |
| + int arity = argument_count - 1; |
| + Handle<Code> ic = |
| + isolate()->stub_cache()->ComputeCallInitialize(arity, |
| + RelocInfo::CODE_TARGET); |
| + HConstant* ic_value = Add<HConstant>(ic); |
| + |
| + return New<HCallWithDescriptor>( |
| + ic_value, 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); |
| + HConstant* ic_value = Add<HConstant>(ic); |
| + |
| + return New<HCallWithDescriptor>( |
| + ic_value, argument_count, descriptor, |
| + Vector<HValue*>(op_vals, descriptor->environment_length())); |
| +} |
|
Toon Verwaest
2014/01/14 15:33:50
This code looks almost exactly the same as the cod
Jarin
2014/01/14 19:08:08
I tried this, but it seems to add about as much co
|
| + |
| class FunctionSorter { |
| public: |
| FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } |
| @@ -6741,9 +6839,11 @@ 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(), |
|
Toon Verwaest
2014/01/14 15:33:50
4-space indent.
Jarin
2014/01/14 19:08:08
Done.
|
| + argument_count, |
| + CALL_AS_METHOD); |
| + PushArgumentsFromEnvironment(argument_count); |
| AddInstruction(call); |
| if (!ast_context()->IsEffect()) Push(call); |
| Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| @@ -6857,9 +6957,11 @@ 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(), |
|
Toon Verwaest
2014/01/14 15:33:50
4-space indent.
Jarin
2014/01/14 19:08:08
Done.
|
| + argument_count, |
| + CALL_AS_METHOD); |
| + PushArgumentsFromEnvironment(argument_count); |
| AddInstruction(call); |
| if (!ast_context()->IsEffect()) Push(call); |
| } |
| @@ -6879,8 +6981,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); |
| @@ -7598,7 +7700,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()); |
| @@ -7637,13 +7739,16 @@ 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, |
| + CALL_AS_METHOD); |
| + PushArgumentsFromEnvironment(argument_count); |
| } |
| } else if (types != NULL && types->length() > 1) { |
| ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
| @@ -7651,7 +7756,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(); |
| @@ -7709,10 +7815,12 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
| if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
| // 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, CALL_AS_FUNCTION); |
| + PushArgumentsFromEnvironment(argument_count); |
| } |
| } else { |
| HGlobalObject* receiver = Add<HGlobalObject>(); |