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

Unified Diff: src/hydrogen.cc

Issue 5862002: Version 3.0.2. (Closed)
Patch Set: Created 10 years 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
« ChangeLog ('K') | « 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 bc49f06a20baf0980a6c5b1a62d90dda1742448d..0e8c4760dd353dd66a0adbf21138f253f56b8519 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1983,9 +1983,6 @@ void HGraph::InsertRepresentationChanges() {
AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
: owner_(owner), kind_(kind), outer_(owner->ast_context()) {
owner->set_ast_context(this); // Push.
-#ifdef DEBUG
- original_count_ = owner->environment()->total_count();
-#endif
}
@@ -1994,101 +1991,6 @@ AstContext::~AstContext() {
}
-EffectContext::~EffectContext() {
- ASSERT(owner()->HasStackOverflow() ||
- !owner()->subgraph()->HasExit() ||
- owner()->environment()->total_count() == original_count_);
-}
-
-
-ValueContext::~ValueContext() {
- ASSERT(owner()->HasStackOverflow() ||
- !owner()->subgraph()->HasExit() ||
- owner()->environment()->total_count() == original_count_ + 1);
-}
-
-
-void EffectContext::ReturnValue(HValue* value) {
- // The value is simply ignored.
-}
-
-
-void ValueContext::ReturnValue(HValue* value) {
- // The value is tracked in the bailout environment, and communicated
- // through the environment as the result of the expression.
- owner()->Push(value);
-}
-
-
-void TestContext::ReturnValue(HValue* value) {
- BuildBranch(value);
-}
-
-
-void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
- owner()->AddInstruction(instr);
- if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
-}
-
-
-void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
- owner()->AddInstruction(instr);
- owner()->Push(instr);
- if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
-}
-
-
-void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
- HGraphBuilder* builder = owner();
- builder->AddInstruction(instr);
- // We expect a simulate after every expression with side effects, though
- // this one isn't actually needed (and wouldn't work if it were targeted).
- if (instr->HasSideEffects()) {
- builder->Push(instr);
- builder->AddSimulate(ast_id);
- builder->Pop();
- }
- BuildBranch(instr);
-}
-
-
-void TestContext::BuildBranch(HValue* value) {
- HGraphBuilder* builder = owner();
- HBasicBlock* materialize_true = builder->graph()->CreateBasicBlock();
- HBasicBlock* materialize_false = builder->graph()->CreateBasicBlock();
- HBranch* branch = new HBranch(materialize_true, materialize_false, value);
- builder->CurrentBlock()->Finish(branch);
-
- HBasicBlock* true_block = if_true();
- HValue* true_value = invert_true()
- ? builder->graph()->GetConstantFalse()
- : builder->graph()->GetConstantTrue();
- materialize_true->set_inverted(invert_true());
- true_block->set_deopt_predecessor(materialize_true);
-
- if (true_block->IsInlineReturnTarget()) {
- materialize_true->AddLeaveInlined(true_value, true_block);
- } else {
- materialize_true->last_environment()->Push(true_value);
- materialize_true->Goto(true_block);
- }
-
- HBasicBlock* false_block = if_false();
- HValue* false_value = invert_false()
- ? builder->graph()->GetConstantTrue()
- : builder->graph()->GetConstantFalse();
- materialize_false->set_inverted(invert_false());
- false_block->set_deopt_predecessor(materialize_false);
-
- if (false_block->IsInlineReturnTarget()) {
- materialize_false->AddLeaveInlined(false_value, false_block);
- } else {
- materialize_false->last_environment()->Push(false_value);
- materialize_false->Goto(false_block);
- }
- builder->subgraph()->set_exit_block(NULL);
-}
-
// HGraphBuilder infrastructure for bailing out and checking bailouts.
#define BAILOUT(reason) \
@@ -2159,14 +2061,55 @@ void HGraphBuilder::Bailout(const char* reason) {
void HGraphBuilder::VisitForEffect(Expression* expr) {
- EffectContext for_effect(this);
- Visit(expr);
+#ifdef DEBUG
+ int original_count = environment()->total_count();
+#endif
+ BinaryOperation* binary_op = expr->AsBinaryOperation();
+
+ // We use special casing for expression types not handled properly by our
+ // usual trick of pretending they're in a value context and cleaning up
+ // later.
+ if (binary_op != NULL && binary_op->op() == Token::COMMA) {
+ VISIT_FOR_EFFECT(binary_op->left());
+ VISIT_FOR_EFFECT(binary_op->right());
+ } else {
+ { EffectContext for_effect(this);
+ Visit(expr);
+ }
+ if (HasStackOverflow() || !subgraph()->HasExit()) return;
+ // Discard return value.
+ Pop();
+ // TODO(kasperl): Try to improve the way we compute the last added
+ // instruction. The NULL check makes me uncomfortable.
+ HValue* last = subgraph()->exit_block()->GetLastInstruction();
+ // We need to ensure we emit a simulate after inlined functions in an
+ // effect context, to avoid having a bailout target the fictional
+ // environment with the return value on top.
+ if ((last != NULL && last->HasSideEffects()) ||
+ subgraph()->exit_block()->IsInlineReturnTarget()) {
+ AddSimulate(expr->id());
+ }
+ }
+
+ ASSERT(environment()->total_count() == original_count);
}
void HGraphBuilder::VisitForValue(Expression* expr) {
- ValueContext for_value(this);
- Visit(expr);
+#ifdef DEBUG
+ int original_height = environment()->values()->length();
+#endif
+ { ValueContext for_value(this);
+ Visit(expr);
+ }
+ if (HasStackOverflow() || !subgraph()->HasExit()) return;
+ // TODO(kasperl): Try to improve the way we compute the last added
+ // instruction. The NULL check makes me uncomfortable.
+ HValue* last = subgraph()->exit_block()->GetLastInstruction();
+ if (last != NULL && last->HasSideEffects()) {
+ AddSimulate(expr->id());
+ }
+ ASSERT(environment()->values()->length() == original_height + 1);
}
@@ -2301,7 +2244,99 @@ void HGraphBuilder::VisitForControl(Expression* expr,
bool invert_false) {
TestContext for_test(this, true_block, false_block,
invert_true, invert_false);
- Visit(expr);
+ BinaryOperation* binary_op = expr->AsBinaryOperation();
+ UnaryOperation* unary_op = expr->AsUnaryOperation();
+
+ if (unary_op != NULL && unary_op->op() == Token::NOT) {
+ VisitForControl(unary_op->expression(),
+ false_block,
+ true_block,
+ !invert_false,
+ !invert_true);
+ } else if (binary_op != NULL && binary_op->op() == Token::AND) {
+ // Translate left subexpression.
+ HBasicBlock* eval_right = graph()->CreateBasicBlock();
+ VisitForControl(binary_op->left(),
+ eval_right,
+ false_block,
+ false,
+ invert_false);
+ if (HasStackOverflow()) return;
+ eval_right->SetJoinId(binary_op->left()->id());
+
+ // Translate right subexpression.
+ eval_right->last_environment()->Pop();
+ subgraph()->set_exit_block(eval_right);
+ VisitForControl(binary_op->right(),
+ true_block,
+ false_block,
+ invert_true,
+ invert_false);
+ } else if (binary_op != NULL && binary_op->op() == Token::OR) {
+ // Translate left subexpression.
+ HBasicBlock* eval_right = graph()->CreateBasicBlock();
+ VisitForControl(binary_op->left(),
+ true_block,
+ eval_right,
+ invert_true,
+ false);
+ if (HasStackOverflow()) return;
+ eval_right->SetJoinId(binary_op->left()->id());
+
+ // Translate right subexpression
+ eval_right->last_environment()->Pop();
+ subgraph()->set_exit_block(eval_right);
+ VisitForControl(binary_op->right(),
+ true_block,
+ false_block,
+ invert_true,
+ invert_false);
+ } else {
+#ifdef DEBUG
+ int original_length = environment()->values()->length();
+#endif
+ // TODO(kmillikin): Refactor to avoid. This code is duplicated from
+ // VisitForValue, except without pushing a value context on the
+ // expression context stack.
+ Visit(expr);
+ if (HasStackOverflow() || !subgraph()->HasExit()) return;
+ HValue* last = subgraph()->exit_block()->GetLastInstruction();
+ if (last != NULL && last->HasSideEffects()) {
+ AddSimulate(expr->id());
+ }
+ ASSERT(environment()->values()->length() == original_length + 1);
+ HValue* value = Pop();
+ HBasicBlock* materialize_true = graph()->CreateBasicBlock();
+ HBasicBlock* materialize_false = graph()->CreateBasicBlock();
+ CurrentBlock()->Finish(new HBranch(materialize_true,
+ materialize_false,
+ value));
+ HValue* true_value = invert_true
+ ? graph()->GetConstantFalse()
+ : graph()->GetConstantTrue();
+ materialize_true->set_inverted(invert_true);
+ true_block->set_deopt_predecessor(materialize_true);
+
+ if (true_block->IsInlineReturnTarget()) {
+ materialize_true->AddLeaveInlined(true_value, true_block);
+ } else {
+ materialize_true->last_environment()->Push(true_value);
+ materialize_true->Goto(true_block);
+ }
+ HValue* false_value = invert_false
+ ? graph()->GetConstantTrue()
+ : graph()->GetConstantFalse();
+ materialize_false->set_inverted(invert_false);
+ false_block->set_deopt_predecessor(materialize_false);
+
+ if (false_block->IsInlineReturnTarget()) {
+ materialize_false->AddLeaveInlined(false_value, false_block);
+ } else {
+ materialize_false->last_environment()->Push(false_value);
+ materialize_false->Goto(false_block);
+ }
+ subgraph()->set_exit_block(NULL);
+ }
}
@@ -2337,6 +2372,12 @@ void HGraphBuilder::PushAndAdd(HInstruction* instr) {
}
+void HGraphBuilder::PushAndAdd(HInstruction* instr, int position) {
+ instr->set_position(position);
+ PushAndAdd(instr);
+}
+
+
void HGraphBuilder::PushArgumentsForStubCall(int argument_count) {
const int kMaxStubArguments = 4;
ASSERT_GE(kMaxStubArguments, argument_count);
@@ -2351,7 +2392,7 @@ void HGraphBuilder::PushArgumentsForStubCall(int argument_count) {
}
-void HGraphBuilder::ProcessCall(HCall* call) {
+void HGraphBuilder::ProcessCall(HCall* call, int source_position) {
for (int i = call->argument_count() - 1; i >= 0; --i) {
HValue* value = Pop();
HPushArgument* push = new HPushArgument(value);
@@ -2361,6 +2402,8 @@ void HGraphBuilder::ProcessCall(HCall* call) {
for (int i = 0; i < call->argument_count(); ++i) {
AddInstruction(call->PushArgumentAt(i));
}
+
+ PushAndAdd(call, source_position);
}
@@ -2871,9 +2914,7 @@ void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Handle<SharedFunctionInfo> shared_info =
Compiler::BuildFunctionInfo(expr, graph_->info()->script());
CHECK_BAILOUT;
- HFunctionLiteral* instr =
- new HFunctionLiteral(shared_info, expr->pretenure());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(new HFunctionLiteral(shared_info, expr->pretenure()));
}
@@ -2894,21 +2935,20 @@ void HGraphBuilder::VisitConditional(Conditional* expr) {
ADD_TO_SUBGRAPH(then_graph, expr->then_expression());
ADD_TO_SUBGRAPH(else_graph, expr->else_expression());
current_subgraph_->AppendJoin(then_graph, else_graph, expr);
- ast_context()->ReturnValue(Pop());
}
-void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
+void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr,
LookupResult* lookup,
bool is_store) {
- if (var->is_this()) {
+ if (expr->is_this()) {
BAILOUT("global this reference");
}
if (!graph()->info()->has_global_object()) {
BAILOUT("no global object to optimize VariableProxy");
}
Handle<GlobalObject> global(graph()->info()->global_object());
- global->Lookup(*var->name(), lookup);
+ global->Lookup(*expr->name(), lookup);
if (!lookup->IsProperty()) {
BAILOUT("global variable cell not yet introduced");
}
@@ -2921,6 +2961,23 @@ void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
}
+void HGraphBuilder::HandleGlobalVariableLoad(VariableProxy* expr) {
+ LookupResult lookup;
+ LookupGlobalPropertyCell(expr, &lookup, false);
+ CHECK_BAILOUT;
+
+ Handle<GlobalObject> global(graph()->info()->global_object());
+ // TODO(3039103): Handle global property load through an IC call when access
+ // checks are enabled.
+ if (global->IsAccessCheckNeeded()) {
+ BAILOUT("global object requires access check");
+ }
+ Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
+ bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
+ PushAndAdd(new HLoadGlobal(cell, check_hole));
+}
+
+
void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
Variable* variable = expr->AsVariable();
if (variable == NULL) {
@@ -2929,22 +2986,9 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) {
BAILOUT("unsupported context for arguments object");
}
- ast_context()->ReturnValue(environment()->Lookup(variable));
+ Push(environment()->Lookup(variable));
} else if (variable->is_global()) {
- LookupResult lookup;
- LookupGlobalPropertyCell(variable, &lookup, false);
- CHECK_BAILOUT;
-
- Handle<GlobalObject> global(graph()->info()->global_object());
- // TODO(3039103): Handle global property load through an IC call when access
- // checks are enabled.
- if (global->IsAccessCheckNeeded()) {
- BAILOUT("global object requires access check");
- }
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
- bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
- HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
- ast_context()->ReturnInstruction(instr, expr->id());
+ HandleGlobalVariableLoad(expr);
} else {
BAILOUT("reference to non-stack-allocated/non-global variable");
}
@@ -2952,16 +2996,14 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
void HGraphBuilder::VisitLiteral(Literal* expr) {
- HConstant* instr = new HConstant(expr->handle(), Representation::Tagged());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(new HConstant(expr->handle(), Representation::Tagged()));
}
void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
- HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(),
- expr->flags(),
- expr->literal_index());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(new HRegExpLiteral(expr->pattern(),
+ expr->flags(),
+ expr->literal_index()));
}
@@ -2970,8 +3012,6 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
expr->fast_elements(),
expr->literal_index(),
expr->depth()));
- // The object is expected in the bailout environment during computation
- // of the property values and is the value of the entire expression.
PushAndAdd(literal);
expr->CalculateEmitStore();
@@ -3008,7 +3048,6 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
default: UNREACHABLE();
}
}
- ast_context()->ReturnValue(Pop());
}
@@ -3020,8 +3059,6 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
length,
expr->literal_index(),
expr->depth());
- // The array is expected in the bailout environment during computation
- // of the property values and is the value of the entire expression.
PushAndAdd(literal);
HValue* elements = AddInstruction(new HLoadElements(literal));
@@ -3039,7 +3076,6 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
AddInstruction(new HStoreKeyedFastElement(elements, key, value));
AddSimulate(expr->GetIdForElement(i));
}
- ast_context()->ReturnValue(Pop());
}
@@ -3221,29 +3257,27 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
Push(value);
instr->set_position(expr->position());
AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->id());
- } else {
- // Build subgraph for generic store through IC.
- {
- HSubgraph* subgraph = CreateBranchSubgraph(environment());
- SubgraphScope scope(this, subgraph);
- if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
- subgraph->FinishExit(new HDeoptimize());
- } else {
- HInstruction* instr = new HStoreNamedGeneric(object, name, value);
- Push(value);
- instr->set_position(expr->position());
- AddInstruction(instr);
- }
- subgraphs.Add(subgraph);
- }
+ return;
+ }
- HBasicBlock* new_exit_block =
- BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
- subgraph()->set_exit_block(new_exit_block);
+ // Build subgraph for generic store through IC.
+ {
+ HSubgraph* subgraph = CreateBranchSubgraph(environment());
+ SubgraphScope scope(this, subgraph);
+ if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
+ subgraph->FinishExit(new HDeoptimize());
+ } else {
+ HInstruction* instr = new HStoreNamedGeneric(object, name, value);
+ Push(value);
+ instr->set_position(expr->position());
+ AddInstruction(instr);
+ }
+ subgraphs.Add(subgraph);
}
- if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
+ HBasicBlock* new_exit_block =
+ BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
+ current_subgraph_->set_exit_block(new_exit_block);
}
@@ -3299,20 +3333,14 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
Push(value);
instr->set_position(expr->position());
AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
- ast_context()->ReturnValue(Pop());
}
-// Because not every expression has a position and there is not common
-// superclass of Assignment and CountOperation, we cannot just pass the
-// owning expression instead of position and ast_id separately.
-void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
+void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy,
HValue* value,
- int position,
- int ast_id) {
+ int position) {
LookupResult lookup;
- LookupGlobalPropertyCell(var, &lookup, true);
+ LookupGlobalPropertyCell(proxy, &lookup, true);
CHECK_BAILOUT;
Handle<GlobalObject> global(graph()->info()->global_object());
@@ -3320,7 +3348,6 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
HInstruction* instr = new HStoreGlobal(value, cell);
instr->set_position(position);
AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(ast_id);
}
@@ -3344,15 +3371,10 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
VISIT_FOR_VALUE(operation);
if (var->is_global()) {
- HandleGlobalVariableAssignment(var,
- Top(),
- expr->position(),
- expr->AssignmentId());
+ HandleGlobalVariableAssignment(proxy, Top(), expr->position());
} else {
Bind(var, Top());
}
- ast_context()->ReturnValue(Pop());
-
} else if (prop != NULL) {
prop->RecordTypeFeedback(oracle());
@@ -3370,7 +3392,9 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
load = BuildLoadNamedGeneric(obj, prop);
}
PushAndAdd(load);
- if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
+ if (load->HasSideEffects()) {
+ AddSimulate(expr->compound_bailout_id());
+ }
VISIT_FOR_VALUE(expr->value());
HValue* right = Pop();
@@ -3382,11 +3406,10 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
HInstruction* store = BuildStoreNamed(obj, instr, prop);
AddInstruction(store);
- // Drop the simulated receiver and value. Return the value.
+
+ // Drop the simulated receiver and value and put back the value.
Drop(2);
Push(instr);
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
- ast_context()->ReturnValue(Pop());
} else {
// Keyed property.
@@ -3402,7 +3425,9 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
? BuildLoadKeyedFastElement(obj, key, prop)
: BuildLoadKeyedGeneric(obj, key);
PushAndAdd(load);
- if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
+ if (load->HasSideEffects()) {
+ AddSimulate(expr->compound_bailout_id());
+ }
VISIT_FOR_VALUE(expr->value());
HValue* right = Pop();
@@ -3416,13 +3441,11 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
? BuildStoreKeyedFastElement(obj, key, instr, prop)
: BuildStoreKeyedGeneric(obj, key, instr);
AddInstruction(store);
- // Drop the simulated receiver, key, and value. Return the value.
+
+ // Drop the simulated receiver, key and value and put back the value.
Drop(3);
Push(instr);
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
- ast_context()->ReturnValue(Pop());
}
-
} else {
BAILOUT("invalid lhs in compound assignment");
}
@@ -3442,14 +3465,9 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
if (var != NULL) {
if (proxy->IsArguments()) BAILOUT("assignment to arguments");
-
- // Handle the assignment.
if (var->is_global()) {
VISIT_FOR_VALUE(expr->value());
- HandleGlobalVariableAssignment(var,
- Top(),
- expr->position(),
- expr->AssignmentId());
+ HandleGlobalVariableAssignment(proxy, Top(), expr->position());
} else {
// We allow reference to the arguments object only in assignemtns
// to local variables to make sure that the arguments object does
@@ -3462,11 +3480,9 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
} else {
VISIT_FOR_VALUE(expr->value());
}
+
Bind(proxy->var(), Top());
}
- // Return the value.
- ast_context()->ReturnValue(Pop());
-
} else if (prop != NULL) {
HandlePropertyAssignment(expr);
} else {
@@ -3476,10 +3492,6 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
void HGraphBuilder::VisitThrow(Throw* expr) {
- // We don't optimize functions with invalid left-hand sides in
- // assignments, count operations, or for-in. Consequently throw can
- // currently only occur in an effect context.
- ASSERT(ast_context()->IsEffect());
VISIT_FOR_VALUE(expr->exception());
HValue* value = environment()->Pop();
@@ -3513,8 +3525,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
SubgraphScope scope(this, subgraph);
HInstruction* instr =
BuildLoadNamedField(object, expr, map, &lookup, false);
- instr->set_position(expr->position());
- PushAndAdd(instr);
+ PushAndAdd(instr, expr->position());
subgraphs.Add(subgraph);
} else {
needs_generic = true;
@@ -3525,30 +3536,26 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
// generic load.
if (maps.length() == 0) {
HInstruction* instr = BuildLoadNamedGeneric(object, expr);
- instr->set_position(expr->position());
- PushAndAdd(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->id());
- } else {
- // Build subgraph for generic load through IC.
- {
- HSubgraph* subgraph = CreateBranchSubgraph(environment());
- SubgraphScope scope(this, subgraph);
- if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
- subgraph->FinishExit(new HDeoptimize());
- } else {
- HInstruction* instr = BuildLoadNamedGeneric(object, expr);
- instr->set_position(expr->position());
- PushAndAdd(instr);
- }
- subgraphs.Add(subgraph);
- }
+ PushAndAdd(instr, expr->position());
+ return;
+ }
- HBasicBlock* new_exit_block =
- BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
- subgraph()->set_exit_block(new_exit_block);
+ // Build subgraph for generic load through IC.
+ {
+ HSubgraph* subgraph = CreateBranchSubgraph(environment());
+ SubgraphScope scope(this, subgraph);
+ if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
+ subgraph->FinishExit(new HDeoptimize());
+ } else {
+ HInstruction* instr = BuildLoadNamedGeneric(object, expr);
+ PushAndAdd(instr, expr->position());
+ }
+ subgraphs.Add(subgraph);
}
- if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
+ HBasicBlock* new_exit_block =
+ BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
+ current_subgraph_->set_exit_block(new_exit_block);
}
@@ -3661,12 +3668,11 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
return false;
}
- HInstruction* result = NULL;
if (expr->key()->IsPropertyName()) {
Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
if (!name->IsEqualTo(CStrVector("length"))) return false;
HInstruction* elements = AddInstruction(new HArgumentsElements);
- result = new HArgumentsLength(elements);
+ PushAndAdd(new HArgumentsLength(elements));
} else {
VisitForValue(expr->key());
if (HasStackOverflow()) return false;
@@ -3674,9 +3680,8 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
HInstruction* elements = AddInstruction(new HArgumentsElements);
HInstruction* length = AddInstruction(new HArgumentsLength(elements));
AddInstruction(new HBoundsCheck(key, length));
- result = new HAccessArgumentsAt(elements, length, key);
+ PushAndAdd(new HAccessArgumentsAt(elements, length, key));
}
- ast_context()->ReturnInstruction(result, expr->id());
return true;
}
@@ -3723,8 +3728,7 @@ void HGraphBuilder::VisitProperty(Property* expr) {
? BuildLoadKeyedFastElement(obj, key, expr)
: BuildLoadKeyedGeneric(obj, key);
}
- instr->set_position(expr->position());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(instr, expr->position());
}
@@ -3759,9 +3763,9 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
// Build subgraphs for each of the specific maps.
//
- // TODO(ager): We should recognize when the prototype chains for different
- // maps are identical. In that case we can avoid repeatedly generating the
- // same prototype map checks.
+ // TODO(ager): We should recognize when the prototype chains for
+ // different maps are identical. In that case we can avoid
+ // repeatedly generating the same prototype map checks.
for (int i = 0; i < number_of_types; ++i) {
Handle<Map> map = types->at(i);
if (expr->ComputeTarget(map, name)) {
@@ -3778,9 +3782,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
// during hydrogen processing.
CHECK_BAILOUT;
HCall* call = new HCallConstantFunction(expr->target(), argument_count);
- call->set_position(expr->position());
- ProcessCall(call);
- PushAndAdd(call);
+ ProcessCall(call, expr->position());
}
subgraphs.Add(subgraph);
} else {
@@ -3788,34 +3790,30 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
}
}
- // If we couldn't compute the target for any of the maps just perform an
- // IC call.
+ // If we couldn't compute the target for any of the maps just
+ // perform an IC call.
if (maps.length() == 0) {
HCall* call = new HCallNamed(name, argument_count);
- call->set_position(expr->position());
- ProcessCall(call);
- ast_context()->ReturnInstruction(call, expr->id());
- } else {
- // Build subgraph for generic call through IC.
- {
- HSubgraph* subgraph = CreateBranchSubgraph(environment());
- SubgraphScope scope(this, subgraph);
- if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
- subgraph->FinishExit(new HDeoptimize());
- } else {
- HCall* call = new HCallNamed(name, argument_count);
- call->set_position(expr->position());
- ProcessCall(call);
- PushAndAdd(call);
- }
- subgraphs.Add(subgraph);
- }
+ ProcessCall(call, expr->position());
+ return;
+ }
- HBasicBlock* new_exit_block =
- BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
- subgraph()->set_exit_block(new_exit_block);
- if (new_exit_block != NULL) ast_context()->ReturnValue(Pop());
+ // Build subgraph for generic call through IC.
+ {
+ HSubgraph* subgraph = CreateBranchSubgraph(environment());
+ SubgraphScope scope(this, subgraph);
+ if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
+ subgraph->FinishExit(new HDeoptimize());
+ } else {
+ HCall* call = new HCallNamed(name, argument_count);
+ ProcessCall(call, expr->position());
+ }
+ subgraphs.Add(subgraph);
}
+
+ HBasicBlock* new_exit_block =
+ BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
+ current_subgraph_->set_exit_block(new_exit_block);
}
@@ -4063,7 +4061,6 @@ bool HGraphBuilder::TryInline(Call* expr) {
function_return_ = saved_function_return;
oracle_ = saved_oracle;
graph()->info()->SetOsrAstId(saved_osr_ast_id);
-
return true;
}
@@ -4089,55 +4086,10 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
case kMathSqrt:
if (argument_count == 2) {
HValue* argument = Pop();
- Drop(1); // Receiver.
+ // Pop receiver.
+ Pop();
HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
- op->set_position(expr->position());
- ast_context()->ReturnInstruction(op, expr->id());
- return true;
- }
- break;
- case kMathPow:
- if (argument_count == 3) {
- HValue* right = Pop();
- HValue* left = Pop();
- Pop(); // Pop receiver.
- HInstruction* result = NULL;
- // Use sqrt() if exponent is 0.5 or -0.5.
- if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
- double exponent = HConstant::cast(right)->DoubleValue();
- if (exponent == 0.5) {
- result = new HUnaryMathOperation(left, kMathPowHalf);
- ast_context()->ReturnInstruction(result, expr->id());
- return true;
- } else if (exponent == -0.5) {
- HConstant* double_one =
- new HConstant(Handle<Object>(Smi::FromInt(1)),
- Representation::Double());
- AddInstruction(double_one);
- HUnaryMathOperation* square_root =
- new HUnaryMathOperation(left, kMathPowHalf);
- AddInstruction(square_root);
- // MathPowHalf doesn't have side effects so there's no need for
- // an environment simulation here.
- ASSERT(!square_root->HasSideEffects());
- result = new HDiv(double_one, square_root);
- ast_context()->ReturnInstruction(result, expr->id());
- return true;
- } else if (exponent == 2.0) {
- result = new HMul(left, left);
- ast_context()->ReturnInstruction(result, expr->id());
- return true;
- }
- } else if (right->IsConstant() &&
- HConstant::cast(right)->HasInteger32Value() &&
- HConstant::cast(right)->Integer32Value() == 2) {
- result = new HMul(left, left);
- ast_context()->ReturnInstruction(result, expr->id());
- return true;
- }
-
- result = new HPower(left, right);
- ast_context()->ReturnInstruction(result, expr->id());
+ PushAndAdd(op, expr->position());
return true;
}
break;
@@ -4182,10 +4134,8 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
function,
expr->GetReceiverTypes()->first(),
true);
- HInstruction* result =
- new HApplyArguments(function, receiver, length, elements);
- result->set_position(expr->position());
- ast_context()->ReturnInstruction(result, expr->id());
+ PushAndAdd(new HApplyArguments(function, receiver, length, elements),
+ expr->position());
return true;
}
@@ -4213,10 +4163,12 @@ void HGraphBuilder::VisitCall(Call* expr) {
CHECK_BAILOUT;
call = new HCallKeyed(key, argument_count);
- call->set_position(expr->position());
- ProcessCall(call);
- Drop(1); // Key.
- ast_context()->ReturnInstruction(call, expr->id());
+ ProcessCall(call, expr->position());
+ HValue* result = Pop();
+ // Drop the receiver from the environment and put back the result of
+ // the call.
+ Drop(1);
+ Push(result);
return;
}
@@ -4239,19 +4191,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
if (expr->IsMonomorphic()) {
AddCheckConstantFunction(expr, receiver, types->first(), true);
- if (TryMathFunctionInline(expr)) {
- return;
- } else if (TryInline(expr)) {
- if (subgraph()->HasExit()) {
- HValue* return_value = Pop();
- // If we inlined a function in a test context then we need to emit
- // a simulate here to shadow the ones at the end of the
- // predecessor blocks. Those environments contain the return
- // value on top and do not correspond to any actual state of the
- // unoptimized code.
- if (ast_context()->IsEffect()) AddSimulate(expr->id());
- ast_context()->ReturnValue(return_value);
- }
+ if (TryMathFunctionInline(expr) || TryInline(expr)) {
return;
} else {
// Check for bailout, as the TryInline call in the if condition above
@@ -4259,7 +4199,6 @@ void HGraphBuilder::VisitCall(Call* expr) {
CHECK_BAILOUT;
call = new HCallConstantFunction(expr->target(), argument_count);
}
-
} else if (types != NULL && types->length() > 1) {
HandlePolymorphicCallNamed(expr, receiver, types, name);
return;
@@ -4307,19 +4246,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
IsGlobalObject());
environment()->SetExpressionStackAt(receiver_index, global_receiver);
- if (TryInline(expr)) {
- if (subgraph()->HasExit()) {
- HValue* return_value = Pop();
- // If we inlined a function in a test context then we need to
- // emit a simulate here to shadow the ones at the end of the
- // predecessor blocks. Those environments contain the return
- // value on top and do not correspond to any actual state of the
- // unoptimized code.
- if (ast_context()->IsEffect()) AddSimulate(expr->id());
- ast_context()->ReturnValue(return_value);
- }
- return;
- }
+ if (TryInline(expr)) return;
// Check for bailout, as trying to inline might fail due to bailout
// during hydrogen processing.
CHECK_BAILOUT;
@@ -4342,9 +4269,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
}
}
- call->set_position(expr->position());
- ProcessCall(call);
- ast_context()->ReturnInstruction(call, expr->id());
+ ProcessCall(call, expr->position());
}
@@ -4358,9 +4283,8 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
int argument_count = expr->arguments()->length() + 1; // Plus constructor.
HCall* call = new HCallNew(argument_count);
- call->set_position(expr->position());
- ProcessCall(call);
- ast_context()->ReturnInstruction(call, expr->id());
+
+ ProcessCall(call, expr->position());
}
@@ -4368,7 +4292,7 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
// Lookup table for generators for runtime calls that are generated inline.
// Elements of the table are member pointers to functions of HGraphBuilder.
-#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
+#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
&HGraphBuilder::Generate##Name,
const HGraphBuilder::InlineFunctionGenerator
@@ -4382,7 +4306,7 @@ const HGraphBuilder::InlineFunctionGenerator
void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
Handle<String> name = expr->name();
if (name->IsEqualTo(CStrVector("_Log"))) {
- ast_context()->ReturnValue(graph()->GetConstantUndefined());
+ Push(graph()->GetConstantUndefined());
return;
}
@@ -4408,13 +4332,11 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
// Call the inline code generator using the pointer-to-member.
- (this->*generator)(argument_count, expr->id());
+ (this->*generator)(argument_count);
} else {
ASSERT(function->intrinsic_type == Runtime::RUNTIME);
HCall* call = new HCallRuntime(name, expr->function(), argument_count);
- call->set_position(RelocInfo::kNoPosition);
- ProcessCall(call);
- ast_context()->ReturnInstruction(call, expr->id());
+ ProcessCall(call, RelocInfo::kNoPosition);
}
}
@@ -4423,7 +4345,7 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
Token::Value op = expr->op();
if (op == Token::VOID) {
VISIT_FOR_EFFECT(expr->expression());
- ast_context()->ReturnValue(graph()->GetConstantUndefined());
+ Push(graph()->GetConstantUndefined());
} else if (op == Token::DELETE) {
Property* prop = expr->expression()->AsProperty();
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
@@ -4431,47 +4353,36 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
// Result of deleting non-property, non-variable reference is true.
// Evaluate the subexpression for side effects.
VISIT_FOR_EFFECT(expr->expression());
- ast_context()->ReturnValue(graph()->GetConstantTrue());
+ Push(graph_->GetConstantTrue());
} else if (var != NULL &&
!var->is_global() &&
var->AsSlot() != NULL &&
var->AsSlot()->type() != Slot::LOOKUP) {
// Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects.
- ast_context()->ReturnValue(graph()->GetConstantFalse());
+ Push(graph_->GetConstantFalse());
} else if (prop != NULL) {
VISIT_FOR_VALUE(prop->obj());
VISIT_FOR_VALUE(prop->key());
HValue* key = Pop();
HValue* obj = Pop();
- ast_context()->ReturnInstruction(new HDeleteProperty(obj, key),
- expr->id());
+ PushAndAdd(new HDeleteProperty(obj, key));
} else if (var->is_global()) {
BAILOUT("delete with global variable");
} else {
BAILOUT("delete with non-global variable");
}
} else if (op == Token::NOT) {
- if (ast_context()->IsTest()) {
- TestContext* context = TestContext::cast(ast_context());
- VisitForControl(expr->expression(),
- context->if_false(),
- context->if_true(),
- !context->invert_false(),
- !context->invert_true());
- } else {
- HSubgraph* true_graph = CreateEmptySubgraph();
- HSubgraph* false_graph = CreateEmptySubgraph();
- VisitCondition(expr->expression(),
- false_graph->entry_block(),
- true_graph->entry_block(),
- true, true);
- if (HasStackOverflow()) return;
- true_graph->environment()->Push(graph_->GetConstantTrue());
- false_graph->environment()->Push(graph_->GetConstantFalse());
- current_subgraph_->AppendJoin(true_graph, false_graph, expr);
- ast_context()->ReturnValue(Pop());
- }
+ HSubgraph* true_graph = CreateEmptySubgraph();
+ HSubgraph* false_graph = CreateEmptySubgraph();
+ VisitCondition(expr->expression(),
+ false_graph->entry_block(),
+ true_graph->entry_block(),
+ true, true);
+ if (HasStackOverflow()) return;
+ true_graph->environment()->Push(graph_->GetConstantTrue());
+ false_graph->environment()->Push(graph_->GetConstantFalse());
+ current_subgraph_->AppendJoin(true_graph, false_graph, expr);
} else if (op == Token::BIT_NOT || op == Token::SUB) {
VISIT_FOR_VALUE(expr->expression());
HValue* value = Pop();
@@ -4487,11 +4398,11 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
UNREACHABLE();
break;
}
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(instr);
} else if (op == Token::TYPEOF) {
VISIT_FOR_VALUE(expr->expression());
HValue* value = Pop();
- ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
+ PushAndAdd(new HTypeof(value));
} else {
BAILOUT("Value: unsupported unary operation");
}
@@ -4542,15 +4453,11 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
if (var->is_global()) {
- HandleGlobalVariableAssignment(var,
- instr,
- expr->position(),
- expr->AssignmentId());
+ HandleGlobalVariableAssignment(proxy, instr, expr->position());
} else {
ASSERT(var->IsStackAllocated());
Bind(var, instr);
}
- ast_context()->ReturnValue(Pop());
} else if (prop != NULL) {
prop->RecordTypeFeedback(oracle());
@@ -4558,10 +4465,11 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
if (prop->key()->IsPropertyName()) {
// Named property.
- // Match the full code generator stack by simulating an extra stack
- // element for postfix operations in a value context.
- bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
- if (has_extra) Push(graph_->GetConstantUndefined());
+ // Match the full code generator stack by simulate an extra stack element
+ // for postfix operations in a value context.
+ if (expr->is_postfix() && !ast_context()->IsEffect()) {
+ Push(graph_->GetConstantUndefined());
+ }
VISIT_FOR_VALUE(prop->obj());
HValue* obj = Top();
@@ -4577,35 +4485,37 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
PushAndAdd(load);
if (load->HasSideEffects()) AddSimulate(increment->id());
- HValue* before = Pop();
- // There is no deoptimization to after the increment, so we don't need
- // to simulate the expression stack after this instruction.
- HInstruction* after = BuildIncrement(before, inc);
- AddInstruction(after);
+ HValue* value = Pop();
- HInstruction* store = BuildStoreNamed(obj, after, prop);
- AddInstruction(store);
+ HInstruction* instr = BuildIncrement(value, inc);
+ AddInstruction(instr);
- // Overwrite the receiver in the bailout environment with the result
- // of the operation, and the placeholder with the original value if
- // necessary.
- environment()->SetExpressionStackAt(0, after);
- if (has_extra) environment()->SetExpressionStackAt(1, before);
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
- Drop(has_extra ? 2 : 1);
+ HInstruction* store = BuildStoreNamed(obj, instr, prop);
+ AddInstruction(store);
- ast_context()->ReturnValue(expr->is_postfix() ? before : after);
+ // Drop simulated receiver and push the result.
+ // There is no deoptimization to after the increment, so we can simulate
+ // the expression stack here.
+ Drop(1);
+ if (expr->is_prefix()) {
+ Push(instr);
+ } else {
+ if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero.
+ Push(value);
+ }
} else {
// Keyed property.
// Match the full code generator stack by simulate an extra stack element
// for postfix operations in a value context.
- bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
- if (has_extra) Push(graph_->GetConstantUndefined());
+ if (expr->is_postfix() && !ast_context()->IsEffect()) {
+ Push(graph_->GetConstantUndefined());
+ }
VISIT_FOR_VALUE(prop->obj());
VISIT_FOR_VALUE(prop->key());
+
HValue* obj = environment()->ExpressionStackAt(1);
HValue* key = environment()->ExpressionStackAt(0);
@@ -4618,29 +4528,27 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
PushAndAdd(load);
if (load->HasSideEffects()) AddSimulate(increment->id());
- HValue* before = Pop();
- // There is no deoptimization to after the increment, so we don't need
- // to simulate the expression stack after this instruction.
- HInstruction* after = BuildIncrement(before, inc);
- AddInstruction(after);
+ HValue* value = Pop();
+
+ HInstruction* instr = BuildIncrement(value, inc);
+ AddInstruction(instr);
HInstruction* store = is_fast_elements
- ? BuildStoreKeyedFastElement(obj, key, after, prop)
- : new HStoreKeyedGeneric(obj, key, after);
+ ? BuildStoreKeyedFastElement(obj, key, instr, prop)
+ : new HStoreKeyedGeneric(obj, key, instr);
AddInstruction(store);
- // Drop the key from the bailout environment. Overwrite the receiver
- // with the result of the operation, and the placeholder with the
- // original value if necessary.
- Drop(1);
- environment()->SetExpressionStackAt(0, after);
- if (has_extra) environment()->SetExpressionStackAt(1, before);
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
- Drop(has_extra ? 2 : 1);
-
- ast_context()->ReturnValue(expr->is_postfix() ? before : after);
+ // Drop simulated receiver and key and push the result.
+ // There is no deoptimization to after the increment, so we can simulate
+ // the expression stack here.
+ Drop(2);
+ if (expr->is_prefix()) {
+ Push(instr);
+ } else {
+ if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero.
+ Push(value);
+ }
}
-
} else {
BAILOUT("invalid lhs in count operation");
}
@@ -4722,47 +4630,21 @@ static bool IsClassOfTest(CompareOperation* expr) {
void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
if (expr->op() == Token::COMMA) {
VISIT_FOR_EFFECT(expr->left());
- // Visit the right subexpression in the same AST context as the entire
- // expression.
- Visit(expr->right());
-
+ VISIT_FOR_VALUE(expr->right());
} else if (expr->op() == Token::AND || expr->op() == Token::OR) {
- bool is_logical_and = (expr->op() == Token::AND);
- if (ast_context()->IsTest()) {
- TestContext* context = TestContext::cast(ast_context());
- // Translate left subexpression.
- HBasicBlock* eval_right = graph()->CreateBasicBlock();
- if (is_logical_and) {
- VisitForControl(expr->left(), eval_right, context->if_false(),
- false, context->invert_false());
- } else {
- VisitForControl(expr->left(), context->if_true(), eval_right,
- context->invert_true(), false);
- }
- if (HasStackOverflow()) return;
- eval_right->SetJoinId(expr->left()->id());
-
- // Translate right subexpression by visiting it in the same AST
- // context as the entire expression.
- eval_right->last_environment()->Pop();
- subgraph()->set_exit_block(eval_right);
- Visit(expr->right());
+ VISIT_FOR_VALUE(expr->left());
+ ASSERT(current_subgraph_->HasExit());
- } else {
- VISIT_FOR_VALUE(expr->left());
- ASSERT(current_subgraph_->HasExit());
-
- HValue* left = Top();
- HEnvironment* environment_copy = environment()->Copy();
- environment_copy->Pop();
- HSubgraph* right_subgraph;
- right_subgraph = CreateBranchSubgraph(environment_copy);
- ADD_TO_SUBGRAPH(right_subgraph, expr->right());
- current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left);
- current_subgraph_->exit_block()->SetJoinId(expr->id());
- ast_context()->ReturnValue(Pop());
- }
+ HValue* left = Top();
+ bool is_logical_and = (expr->op() == Token::AND);
+ HEnvironment* environment_copy = environment()->Copy();
+ environment_copy->Pop();
+ HSubgraph* right_subgraph;
+ right_subgraph = CreateBranchSubgraph(environment_copy);
+ ADD_TO_SUBGRAPH(right_subgraph, expr->right());
+ current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left);
+ current_subgraph_->exit_block()->SetJoinId(expr->id());
} else {
VISIT_FOR_VALUE(expr->left());
VISIT_FOR_VALUE(expr->right());
@@ -4770,8 +4652,7 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
HValue* right = Pop();
HValue* left = Pop();
HInstruction* instr = BuildBinaryOperation(expr, left, right);
- instr->set_position(expr->position());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(instr, expr->position());
}
}
@@ -4810,8 +4691,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Literal* literal = expr->right()->AsLiteral();
Handle<String> rhs = Handle<String>::cast(literal->handle());
HInstruction* instr = new HClassOfTest(value, rhs);
- instr->set_position(expr->position());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(instr, expr->position());
return;
}
@@ -4825,8 +4705,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
HValue* left = Pop();
HInstruction* instr = new HTypeofIs(left,
Handle<String>::cast(right_literal->handle()));
- instr->set_position(expr->position());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(instr, expr->position());
return;
}
@@ -4862,8 +4741,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
compare->SetInputRepresentation(r);
instr = compare;
}
- instr->set_position(expr->position());
- ast_context()->ReturnInstruction(instr, expr->id());
+ PushAndAdd(instr, expr->position());
}
@@ -4872,7 +4750,8 @@ void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
HValue* value = Pop();
HIsNull* compare = new HIsNull(value, expr->is_strict());
- ast_context()->ReturnInstruction(compare, expr->id());
+
+ PushAndAdd(compare);
}
@@ -4899,305 +4778,301 @@ void HGraphBuilder::VisitDeclaration(Declaration* decl) {
// Generators for inline runtime functions.
// Support for types.
-void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsSmi(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HIsSmi* result = new HIsSmi(value);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HIsSmi(value));
}
-void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsSpecObject(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HHasInstanceType* result =
+ HHasInstanceType* test =
new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(test);
}
-void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsFunction(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE);
- ast_context()->ReturnInstruction(result, ast_id);
+ HHasInstanceType* test =
+ new HHasInstanceType(value, JS_FUNCTION_TYPE);
+ PushAndAdd(test);
}
-void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value);
- ast_context()->ReturnInstruction(result, ast_id);
+ HHasCachedArrayIndex* spec_test = new HHasCachedArrayIndex(value);
+ PushAndAdd(spec_test);
}
-void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsArray(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE);
- ast_context()->ReturnInstruction(result, ast_id);
+ HHasInstanceType* test =
+ new HHasInstanceType(value, JS_ARRAY_TYPE);
+ PushAndAdd(test);
}
-void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsRegExp(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
- ast_context()->ReturnInstruction(result, ast_id);
+ HHasInstanceType* test =
+ new HHasInstanceType(value, JS_REGEXP_TYPE);
+ PushAndAdd(test);
}
-void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count) {
BAILOUT("inlined runtime function: IsNonNegativeSmi");
}
-void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsObject(int argument_count) {
BAILOUT("inlined runtime function: IsObject");
}
-void HGraphBuilder::GenerateIsUndetectableObject(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateIsUndetectableObject(int argument_count) {
BAILOUT("inlined runtime function: IsUndetectableObject");
}
void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
- int argument_count,
- int ast_id) {
+ int argument_count) {
BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
}
// Support for construct call checks.
-void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateIsConstructCall(int argument_count) {
BAILOUT("inlined runtime function: IsConstructCall");
}
// Support for arguments.length and arguments[?].
-void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateArgumentsLength(int argument_count) {
ASSERT(argument_count == 0);
HInstruction* elements = AddInstruction(new HArgumentsElements);
- HArgumentsLength* result = new HArgumentsLength(elements);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HArgumentsLength(elements));
}
-void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateArguments(int argument_count) {
ASSERT(argument_count == 1);
HValue* index = Pop();
HInstruction* elements = AddInstruction(new HArgumentsElements);
HInstruction* length = AddInstruction(new HArgumentsLength(elements));
- HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HAccessArgumentsAt(elements, length, index));
}
// Support for accessing the class and value fields of an object.
-void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateClassOf(int argument_count) {
// The special form detected by IsClassOfTest is detected before we get here
// and does not cause a bailout.
BAILOUT("inlined runtime function: ClassOf");
}
-void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateValueOf(int argument_count) {
ASSERT(argument_count == 1);
+
HValue* value = Pop();
- HValueOf* result = new HValueOf(value);
- ast_context()->ReturnInstruction(result, ast_id);
+ HValueOf* op = new HValueOf(value);
+ PushAndAdd(op);
}
-void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateSetValueOf(int argument_count) {
BAILOUT("inlined runtime function: SetValueOf");
}
// Fast support for charCodeAt(n).
-void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateStringCharCodeAt(int argument_count) {
BAILOUT("inlined runtime function: StringCharCodeAt");
}
// Fast support for string.charAt(n) and string[n].
-void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateStringCharFromCode(int argument_count) {
BAILOUT("inlined runtime function: StringCharFromCode");
}
// Fast support for string.charAt(n) and string[n].
-void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateStringCharAt(int argument_count) {
ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::StringCharAt, argument_count),
+ RelocInfo::kNoPosition);
}
// Fast support for object equality testing.
-void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateObjectEquals(int argument_count) {
ASSERT(argument_count == 2);
+
HValue* right = Pop();
HValue* left = Pop();
- HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCompareJSObjectEq(left, right));
}
-void HGraphBuilder::GenerateLog(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateLog(int argument_count) {
UNREACHABLE(); // We caught this in VisitCallRuntime.
}
// Fast support for Math.random().
-void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateRandomHeapNumber(int argument_count) {
BAILOUT("inlined runtime function: RandomHeapNumber");
}
// Fast support for StringAdd.
-void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateStringAdd(int argument_count) {
ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::StringAdd, argument_count),
+ RelocInfo::kNoPosition);
}
// Fast support for SubString.
-void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateSubString(int argument_count) {
ASSERT_EQ(3, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result = new HCallStub(CodeStub::SubString, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::SubString, argument_count),
+ RelocInfo::kNoPosition);
}
// Fast support for StringCompare.
-void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateStringCompare(int argument_count) {
ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::StringCompare, argument_count),
+ RelocInfo::kNoPosition);
}
// Support for direct calls from JavaScript to native RegExp code.
-void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateRegExpExec(int argument_count) {
ASSERT_EQ(4, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::RegExpExec, argument_count),
+ RelocInfo::kNoPosition);
}
// Construct a RegExp exec result with two in-object properties.
-void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateRegExpConstructResult(int argument_count) {
ASSERT_EQ(3, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result =
- new HCallStub(CodeStub::RegExpConstructResult, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::RegExpConstructResult, argument_count),
+ RelocInfo::kNoPosition);
}
// Support for fast native caches.
-void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateGetFromCache(int argument_count) {
BAILOUT("inlined runtime function: GetFromCache");
}
// Fast support for number to string.
-void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateNumberToString(int argument_count) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushAndAdd(new HCallStub(CodeStub::NumberToString, argument_count),
+ RelocInfo::kNoPosition);
}
// Fast swapping of elements. Takes three expressions, the object and two
// indices. This should only be used if the indices are known to be
// non-negative and within bounds of the elements array at the call site.
-void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateSwapElements(int argument_count) {
BAILOUT("inlined runtime function: SwapElements");
}
// Fast call for custom callbacks.
-void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateCallFunction(int argument_count) {
BAILOUT("inlined runtime function: CallFunction");
}
// Fast call to math functions.
-void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateMathPow(int argument_count) {
ASSERT_EQ(2, argument_count);
- HValue* right = Pop();
- HValue* left = Pop();
- HPower* result = new HPower(left, right);
- ast_context()->ReturnInstruction(result, ast_id);
+ PushArgumentsForStubCall(argument_count);
+ PushAndAdd(new HCallStub(CodeStub::MathPow, argument_count),
+ RelocInfo::kNoPosition);
}
-void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateMathSin(int argument_count) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result =
+ HCallStub* instr =
new HCallStub(CodeStub::TranscendentalCache, argument_count);
- result->set_transcendental_type(TranscendentalCache::SIN);
- ast_context()->ReturnInstruction(result, ast_id);
+ instr->set_transcendental_type(TranscendentalCache::SIN);
+ PushAndAdd(instr, RelocInfo::kNoPosition);
}
-void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateMathCos(int argument_count) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result =
+ HCallStub* instr =
new HCallStub(CodeStub::TranscendentalCache, argument_count);
- result->set_transcendental_type(TranscendentalCache::COS);
- ast_context()->ReturnInstruction(result, ast_id);
+ instr->set_transcendental_type(TranscendentalCache::COS);
+ PushAndAdd(instr, RelocInfo::kNoPosition);
}
-void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateMathLog(int argument_count) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
- HCallStub* result =
+ HCallStub* instr =
new HCallStub(CodeStub::TranscendentalCache, argument_count);
- result->set_transcendental_type(TranscendentalCache::LOG);
- ast_context()->ReturnInstruction(result, ast_id);
+ instr->set_transcendental_type(TranscendentalCache::LOG);
+ PushAndAdd(instr, RelocInfo::kNoPosition);
}
-void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateMathSqrt(int argument_count) {
BAILOUT("inlined runtime function: MathSqrt");
}
// Check whether two RegExps are equivalent
-void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count) {
BAILOUT("inlined runtime function: IsRegExpEquivalent");
}
-void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count) {
BAILOUT("inlined runtime function: GetCachedArrayIndex");
}
-void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count,
- int ast_id) {
+void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count) {
BAILOUT("inlined runtime function: FastAsciiArrayJoin");
}
« ChangeLog ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698