Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(450)

Unified Diff: src/hydrogen.cc

Issue 132623005: A64: Synchronize with r18642. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 24a07d41c66198a7decbb8d86478d4c1101fc9bd..cefabe225dc816d0ee1ef0d8ad7833819696d632 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3919,9 +3919,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());
@@ -3930,6 +3928,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;
}
@@ -5501,7 +5505,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
return NULL;
}
Add<HPushArgument>(Pop());
- return New<HCallConstantFunction>(info->accessor(), 1);
+ return BuildCallConstantFunction(info->accessor(), 1);
}
ASSERT(info->lookup()->IsConstant());
@@ -5786,7 +5790,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,
@@ -6748,6 +6752,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) { }
@@ -6803,9 +6887,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);
@@ -6824,6 +6908,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
+ HBasicBlock* join = NULL;
+ FunctionSorter order[kMaxCallPolymorphism];
+ int ordered_functions = 0;
Handle<Map> initial_string_map(
isolate()->native_context()->string_function()->initial_map());
@@ -6837,121 +6924,72 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
bool handle_smi = false;
- // A map from functions to a set of receivers' maps.
- struct FuncMapEntry {
- Handle<JSFunction> func;
- SmallMapList maps;
- };
- FuncMapEntry func_map[kMaxCallPolymorphism];
- FunctionSorter order[kMaxCallPolymorphism];
- int func_count = 0;
- int maps_count = 0;
-
for (int i = 0;
- i < types->length() && func_count < kMaxCallPolymorphism;
+ i < types->length() && ordered_functions < kMaxCallPolymorphism;
++i) {
Handle<Map> map = types->at(i);
if (expr->ComputeTarget(map, name)) {
if (map.is_identical_to(number_marker_map)) handle_smi = true;
-
- // Try to find the target function among known targets.
- int func_index = 0;
- for (; func_index < func_count; ++func_index) {
- if (*func_map[func_index].func == *expr->target()) {
- break;
- }
- }
- FuncMapEntry* entry = &func_map[func_index];
- if (func_index == func_count) {
- // Entry not found, "allocate" it.
- entry->func = expr->target();
- entry->maps.Reserve(types->length() - maps_count, zone());
- order[func_index] =
- FunctionSorter(func_index,
- entry->func->shared()->profiler_ticks(),
- InliningAstSize(entry->func),
- entry->func->shared()->SourceSize());
- ++func_count;
- }
- entry->maps.Add(map, zone());
- ++maps_count;
+ order[ordered_functions++] =
+ FunctionSorter(i,
+ expr->target()->shared()->profiler_ticks(),
+ InliningAstSize(expr->target()),
+ expr->target()->shared()->SourceSize());
}
}
- std::sort(order, order + func_count);
+ std::sort(order, order + ordered_functions);
HBasicBlock* number_block = NULL;
- HBasicBlock* join = NULL;
- if (func_count > 0) {
- // Only needed once.
- join = graph()->CreateBasicBlock();
- if (handle_smi) {
- HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
- HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
- number_block = graph()->CreateBasicBlock();
- FinishCurrentBlock(
- New<HIsSmiAndBranch>(receiver, empty_smi_block, not_smi_block));
- Goto(empty_smi_block, number_block);
- set_current_block(not_smi_block);
- } else {
- BuildCheckHeapObject(receiver);
- }
- }
-
- for (int fn = 0; fn < func_count; ++fn) {
+ for (int fn = 0; fn < ordered_functions; ++fn) {
int i = order[fn].index();
- FuncMapEntry* func_map_entry = &func_map[i];
-
- HBasicBlock* call_block = graph()->CreateBasicBlock();
- HBasicBlock* if_false = NULL;
-
- int maps_count = func_map_entry->maps.length();
- for (int m = 0; m < maps_count; ++m) {
- Handle<Map> map = func_map_entry->maps.at(m);
- HBasicBlock* if_true = graph()->CreateBasicBlock();
- if_false = graph()->CreateBasicBlock();
- HUnaryControlInstruction* compare;
-
- if (handle_smi && map.is_identical_to(number_marker_map)) {
- compare =
- New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
- map = initial_number_map;
- expr->set_number_check(
- Handle<JSObject>(JSObject::cast(map->prototype())));
- } else if (map.is_identical_to(string_marker_map)) {
- compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
- map = initial_string_map;
- expr->set_string_check(
- Handle<JSObject>(JSObject::cast(map->prototype())));
+ Handle<Map> map = types->at(i);
+ if (fn == 0) {
+ // Only needed once.
+ join = graph()->CreateBasicBlock();
+ if (handle_smi) {
+ HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
+ HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
+ number_block = graph()->CreateBasicBlock();
+ FinishCurrentBlock(New<HIsSmiAndBranch>(
+ receiver, empty_smi_block, not_smi_block));
+ Goto(empty_smi_block, number_block);
+ set_current_block(not_smi_block);
} else {
- compare = New<HCompareMap>(receiver, map, if_true, if_false);
- expr->set_map_check();
- }
-
- FinishCurrentBlock(compare);
-
- if (expr->check_type() == NUMBER_CHECK) {
- Goto(if_true, number_block);
- if_true = number_block;
- number_block->SetJoinId(expr->id());
+ BuildCheckHeapObject(receiver);
}
- set_current_block(if_true);
-
- expr->ComputeTarget(map, name);
- ASSERT(*expr->target() == *func_map_entry->func);
-
- AddCheckPrototypeMaps(expr->holder(), map);
+ }
+ HBasicBlock* if_true = graph()->CreateBasicBlock();
+ HBasicBlock* if_false = graph()->CreateBasicBlock();
+ HUnaryControlInstruction* compare;
+
+ if (handle_smi && map.is_identical_to(number_marker_map)) {
+ compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
+ map = initial_number_map;
+ expr->set_number_check(
+ Handle<JSObject>(JSObject::cast(map->prototype())));
+ } else if (map.is_identical_to(string_marker_map)) {
+ compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
+ map = initial_string_map;
+ expr->set_string_check(
+ Handle<JSObject>(JSObject::cast(map->prototype())));
+ } else {
+ compare = New<HCompareMap>(receiver, map, if_true, if_false);
+ expr->set_map_check();
+ }
- Goto(if_true, call_block);
+ FinishCurrentBlock(compare);
- set_current_block(if_false);
+ if (expr->check_type() == NUMBER_CHECK) {
+ Goto(if_true, number_block);
+ if_true = number_block;
+ number_block->SetJoinId(expr->id());
}
+ set_current_block(if_true);
- // Generate call once for all corresponding maps.
- call_block->SetJoinId(expr->id());
- set_current_block(call_block);
-
+ expr->ComputeTarget(map, name);
+ AddCheckPrototypeMaps(expr->holder(), map);
if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
Handle<JSFunction> caller = current_info()->closure();
SmartArrayPointer<char> caller_name =
@@ -6965,21 +7003,21 @@ 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);
}
- if (current_block() != NULL) Goto(join);
+ if (current_block() != NULL) Goto(join);
set_current_block(if_false);
}
// Finish up. Unconditionally deoptimize if we've handled all the maps we
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
- if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) {
+ if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
// Because the deopt may be the only path in the polymorphic call, make sure
// that the environment stack matches the depth on deopt that it otherwise
// would have had after a successful call.
@@ -6987,8 +7025,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);
@@ -7071,8 +7109,7 @@ int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
}
-bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
- Handle<JSFunction> target,
+bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
int arguments_count,
HValue* implicit_return_value,
BailoutId ast_id,
@@ -7372,14 +7409,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) {
- // The function call we are inlining is a method call if the call
- // is a property call.
- CallKind call_kind = (expr->expression()->AsProperty() == NULL)
- ? CALL_AS_FUNCTION
- : CALL_AS_METHOD;
-
- return TryInline(call_kind,
- expr->target(),
+ return TryInline(expr->target(),
expr->arguments()->length(),
NULL,
expr->id(),
@@ -7390,8 +7420,7 @@ bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) {
bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
HValue* implicit_return_value) {
- return TryInline(CALL_AS_FUNCTION,
- expr->target(),
+ return TryInline(expr->target(),
expr->arguments()->length(),
implicit_return_value,
expr->id(),
@@ -7403,8 +7432,7 @@ bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
BailoutId ast_id,
BailoutId return_id) {
- return TryInline(CALL_AS_METHOD,
- getter,
+ return TryInline(getter,
0,
NULL,
ast_id,
@@ -7417,8 +7445,7 @@ bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
BailoutId id,
BailoutId assignment_id,
HValue* implicit_return_value) {
- return TryInline(CALL_AS_METHOD,
- setter,
+ return TryInline(setter,
1,
implicit_return_value,
id, assignment_id,
@@ -7429,8 +7456,7 @@ bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
Call* expr,
int arguments_count) {
- return TryInline(CALL_AS_METHOD,
- function,
+ return TryInline(function,
arguments_count,
NULL,
expr->id(),
@@ -7741,7 +7767,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());
@@ -7780,13 +7806,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);
@@ -7794,7 +7821,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();
@@ -7855,17 +7883,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<HCallGlobal>(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<HCallGlobal>(var->name(), argument_count);
+ call = NewCallNamed(var->name(), argument_count);
Drop(argument_count);
}
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698