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); |
} |