Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 47dcc805367757d890486768453fc3c0f273fd6a..2094acd0685a9db049e195151800c7b6ad1f44cd 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -167,8 +167,7 @@ void HBasicBlock::Finish(HControlInstruction* end) { |
| void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) { |
| if (block->IsInlineReturnTarget()) { |
| AddInstruction(new(zone()) HLeaveInlined); |
| - last_environment_ = last_environment()->outer(); |
| - if (drop_extra) last_environment_->Drop(1); |
| + last_environment_ = last_environment()->LeaveInlined(drop_extra); |
|
Kevin Millikin (Chromium)
2012/01/19 10:26:34
Maybe it's confusing to call the environment funct
|
| } |
| AddSimulate(AstNode::kNoNumber); |
| HGoto* instr = new(zone()) HGoto(block); |
| @@ -182,8 +181,7 @@ void HBasicBlock::AddLeaveInlined(HValue* return_value, |
| ASSERT(target->IsInlineReturnTarget()); |
| ASSERT(return_value != NULL); |
| AddInstruction(new(zone()) HLeaveInlined); |
| - last_environment_ = last_environment()->outer(); |
| - if (drop_extra) last_environment_->Drop(1); |
| + last_environment_ = last_environment()->LeaveInlined(drop_extra); |
| last_environment()->Push(return_value); |
| AddSimulate(AstNode::kNoNumber); |
| HGoto* instr = new(zone()) HGoto(target); |
| @@ -4867,11 +4865,8 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) { |
| return false; |
| } |
| - // Don't inline functions that uses the arguments object or that |
| - // have a mismatching number of parameters. |
| - int arity = expr->arguments()->length(); |
| - if (function->scope()->arguments() != NULL || |
| - arity != target_shared->formal_parameter_count()) { |
| + // Don't inline functions that uses the arguments object. |
| + if (function->scope()->arguments() != NULL) { |
| TraceInline(target, caller, "target requires special argument handling"); |
| return false; |
| } |
| @@ -4935,6 +4930,7 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) { |
| HConstant* undefined = graph()->GetConstantUndefined(); |
| HEnvironment* inner_env = |
| environment()->CopyForInlining(target, |
| + expr->arguments()->length(), |
| function, |
| undefined, |
| call_kind); |
| @@ -4954,6 +4950,7 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) { |
| body_entry->SetJoinId(expr->ReturnId()); |
| set_current_block(body_entry); |
| AddInstruction(new(zone()) HEnterInlined(target, |
| + expr->arguments()->length(), |
| function, |
| call_kind)); |
| VisitDeclarations(target_info.scope()->declarations()); |
| @@ -6878,7 +6875,8 @@ HEnvironment::HEnvironment(HEnvironment* outer, |
| outer_(outer), |
| pop_count_(0), |
| push_count_(0), |
| - ast_id_(AstNode::kNoNumber) { |
| + ast_id_(AstNode::kNoNumber), |
| + arguments_adaptor_(false) { |
| Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); |
| } |
| @@ -6892,11 +6890,28 @@ HEnvironment::HEnvironment(const HEnvironment* other) |
| outer_(NULL), |
| pop_count_(0), |
| push_count_(0), |
| - ast_id_(other->ast_id()) { |
| + ast_id_(other->ast_id()), |
| + arguments_adaptor_(false) { |
| Initialize(other); |
| } |
| +HEnvironment::HEnvironment(HEnvironment* outer, |
| + Handle<JSFunction> closure, |
| + int arguments) |
| + : closure_(closure), |
| + values_(arguments), |
| + assigned_variables_(0), |
| + parameter_count_(arguments), |
| + local_count_(0), |
| + outer_(outer), |
| + pop_count_(0), |
| + push_count_(0), |
| + ast_id_(AstNode::kNoNumber), |
| + arguments_adaptor_(true) { |
| +} |
| + |
| + |
| void HEnvironment::Initialize(int parameter_count, |
| int local_count, |
| int stack_height) { |
| @@ -7023,20 +7038,36 @@ HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { |
| HEnvironment* HEnvironment::CopyForInlining( |
| Handle<JSFunction> target, |
| + int arguments, |
| FunctionLiteral* function, |
| HConstant* undefined, |
| CallKind call_kind) const { |
| + ASSERT(!is_arguments_adaptor()); |
| + |
| + Zone* zone = closure()->GetIsolate()->zone(); |
| + |
| // Outer environment is a copy of this one without the arguments. |
| int arity = function->scope()->num_parameters(); |
| + |
| HEnvironment* outer = Copy(); |
| - outer->Drop(arity + 1); // Including receiver. |
| + outer->Drop(arguments + 1); // Including receiver. |
| outer->ClearHistory(); |
| - Zone* zone = closure()->GetIsolate()->zone(); |
| + |
| + if (arity != arguments) { |
| + // Create artificial arguments adaptation environment. |
| + outer = new(zone) HEnvironment(outer, target, arguments + 1); |
| + for (int i = 0; i <= arguments; ++i) { // Include receiver. |
| + outer->Push(ExpressionStackAt(arguments - i)); |
| + } |
| + outer->ClearHistory(); |
| + } |
| + |
| HEnvironment* inner = |
| new(zone) HEnvironment(outer, function->scope(), target); |
| // Get the argument values from the original environment. |
| for (int i = 0; i <= arity; ++i) { // Include receiver. |
| - HValue* push = ExpressionStackAt(arity - i); |
| + HValue* push = (arguments >= i) ? |
| + ExpressionStackAt(arguments - i) : undefined; |
| inner->SetValueAt(i, push); |
| } |
| // If the function we are inlining is a strict mode function or a |
| @@ -7046,7 +7077,7 @@ HEnvironment* HEnvironment::CopyForInlining( |
| call_kind == CALL_AS_FUNCTION) { |
| inner->SetValueAt(0, undefined); |
| } |
| - inner->SetValueAt(arity + 1, outer->LookupContext()); |
| + inner->SetValueAt(arity + 1, LookupContext()); |
| for (int i = arity + 2; i < inner->length(); ++i) { |
| inner->SetValueAt(i, undefined); |
| } |