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

Side by Side Diff: src/hydrogen.cc

Issue 9265004: Support inlining at call-sites with mismatched number of arguments. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 end_ = end; 160 end_ = end;
161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
162 it.Current()->RegisterPredecessor(this); 162 it.Current()->RegisterPredecessor(this);
163 } 163 }
164 } 164 }
165 165
166 166
167 void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) { 167 void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
168 if (block->IsInlineReturnTarget()) { 168 if (block->IsInlineReturnTarget()) {
169 AddInstruction(new(zone()) HLeaveInlined); 169 AddInstruction(new(zone()) HLeaveInlined);
170 last_environment_ = last_environment()->outer(); 170 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
171 if (drop_extra) last_environment_->Drop(1);
172 } 171 }
173 AddSimulate(AstNode::kNoNumber); 172 AddSimulate(AstNode::kNoNumber);
174 HGoto* instr = new(zone()) HGoto(block); 173 HGoto* instr = new(zone()) HGoto(block);
175 Finish(instr); 174 Finish(instr);
176 } 175 }
177 176
178 177
179 void HBasicBlock::AddLeaveInlined(HValue* return_value, 178 void HBasicBlock::AddLeaveInlined(HValue* return_value,
180 HBasicBlock* target, 179 HBasicBlock* target,
181 bool drop_extra) { 180 bool drop_extra) {
182 ASSERT(target->IsInlineReturnTarget()); 181 ASSERT(target->IsInlineReturnTarget());
183 ASSERT(return_value != NULL); 182 ASSERT(return_value != NULL);
184 AddInstruction(new(zone()) HLeaveInlined); 183 AddInstruction(new(zone()) HLeaveInlined);
185 last_environment_ = last_environment()->outer(); 184 last_environment_ = last_environment()->LeaveInlined(drop_extra);
186 if (drop_extra) last_environment_->Drop(1);
187 last_environment()->Push(return_value); 185 last_environment()->Push(return_value);
188 AddSimulate(AstNode::kNoNumber); 186 AddSimulate(AstNode::kNoNumber);
189 HGoto* instr = new(zone()) HGoto(target); 187 HGoto* instr = new(zone()) HGoto(target);
190 Finish(instr); 188 Finish(instr);
191 } 189 }
192 190
193 191
194 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 192 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
195 ASSERT(!HasEnvironment()); 193 ASSERT(!HasEnvironment());
196 ASSERT(first() == NULL); 194 ASSERT(first() == NULL);
(...skipping 4663 matching lines...) Expand 10 before | Expand all | Expand 10 after
4860 } 4858 }
4861 FunctionLiteral* function = target_info.function(); 4859 FunctionLiteral* function = target_info.function();
4862 4860
4863 // Count the number of AST nodes added by inlining this call. 4861 // Count the number of AST nodes added by inlining this call.
4864 int nodes_added = AstNode::Count() - count_before; 4862 int nodes_added = AstNode::Count() - count_before;
4865 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 4863 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
4866 TraceInline(target, caller, "target AST is too large"); 4864 TraceInline(target, caller, "target AST is too large");
4867 return false; 4865 return false;
4868 } 4866 }
4869 4867
4870 // Don't inline functions that uses the arguments object or that 4868 // Don't inline functions that uses the arguments object.
4871 // have a mismatching number of parameters. 4869 if (function->scope()->arguments() != NULL) {
4872 int arity = expr->arguments()->length();
4873 if (function->scope()->arguments() != NULL ||
4874 arity != target_shared->formal_parameter_count()) {
4875 TraceInline(target, caller, "target requires special argument handling"); 4870 TraceInline(target, caller, "target requires special argument handling");
4876 return false; 4871 return false;
4877 } 4872 }
4878 4873
4879 // All declarations must be inlineable. 4874 // All declarations must be inlineable.
4880 ZoneList<Declaration*>* decls = target_info.scope()->declarations(); 4875 ZoneList<Declaration*>* decls = target_info.scope()->declarations();
4881 int decl_count = decls->length(); 4876 int decl_count = decls->length();
4882 for (int i = 0; i < decl_count; ++i) { 4877 for (int i = 0; i < decl_count; ++i) {
4883 if (!decls->at(i)->IsInlineable()) { 4878 if (!decls->at(i)->IsInlineable()) {
4884 TraceInline(target, caller, "target has non-trivial declaration"); 4879 TraceInline(target, caller, "target has non-trivial declaration");
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4928 Handle<Context>(target->context()->global_context()), 4923 Handle<Context>(target->context()->global_context()),
4929 isolate()); 4924 isolate());
4930 // The function state is new-allocated because we need to delete it 4925 // The function state is new-allocated because we need to delete it
4931 // in two different places. 4926 // in two different places.
4932 FunctionState* target_state = 4927 FunctionState* target_state =
4933 new FunctionState(this, &target_info, &target_oracle, drop_extra); 4928 new FunctionState(this, &target_info, &target_oracle, drop_extra);
4934 4929
4935 HConstant* undefined = graph()->GetConstantUndefined(); 4930 HConstant* undefined = graph()->GetConstantUndefined();
4936 HEnvironment* inner_env = 4931 HEnvironment* inner_env =
4937 environment()->CopyForInlining(target, 4932 environment()->CopyForInlining(target,
4933 expr->arguments()->length(),
4938 function, 4934 function,
4939 undefined, 4935 undefined,
4940 call_kind); 4936 call_kind);
4941 #ifdef V8_TARGET_ARCH_IA32 4937 #ifdef V8_TARGET_ARCH_IA32
4942 // IA32 only, overwrite the caller's context in the deoptimization 4938 // IA32 only, overwrite the caller's context in the deoptimization
4943 // environment with the correct one. 4939 // environment with the correct one.
4944 // 4940 //
4945 // TODO(kmillikin): implement the same inlining on other platforms so we 4941 // TODO(kmillikin): implement the same inlining on other platforms so we
4946 // can remove the unsightly ifdefs in this function. 4942 // can remove the unsightly ifdefs in this function.
4947 HConstant* context = new HConstant(Handle<Context>(target->context()), 4943 HConstant* context = new HConstant(Handle<Context>(target->context()),
4948 Representation::Tagged()); 4944 Representation::Tagged());
4949 AddInstruction(context); 4945 AddInstruction(context);
4950 inner_env->BindContext(context); 4946 inner_env->BindContext(context);
4951 #endif 4947 #endif
4952 HBasicBlock* body_entry = CreateBasicBlock(inner_env); 4948 HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4953 current_block()->Goto(body_entry); 4949 current_block()->Goto(body_entry);
4954 body_entry->SetJoinId(expr->ReturnId()); 4950 body_entry->SetJoinId(expr->ReturnId());
4955 set_current_block(body_entry); 4951 set_current_block(body_entry);
4956 AddInstruction(new(zone()) HEnterInlined(target, 4952 AddInstruction(new(zone()) HEnterInlined(target,
4953 expr->arguments()->length(),
4957 function, 4954 function,
4958 call_kind)); 4955 call_kind));
4959 VisitDeclarations(target_info.scope()->declarations()); 4956 VisitDeclarations(target_info.scope()->declarations());
4960 VisitStatements(function->body()); 4957 VisitStatements(function->body());
4961 if (HasStackOverflow()) { 4958 if (HasStackOverflow()) {
4962 // Bail out if the inline function did, as we cannot residualize a call 4959 // Bail out if the inline function did, as we cannot residualize a call
4963 // instead. 4960 // instead.
4964 TraceInline(target, caller, "inline graph construction failed"); 4961 TraceInline(target, caller, "inline graph construction failed");
4965 target_shared->DisableOptimization(*target); 4962 target_shared->DisableOptimization(*target);
4966 inline_bailout_ = true; 4963 inline_bailout_ = true;
(...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after
6871 Handle<JSFunction> closure) 6868 Handle<JSFunction> closure)
6872 : closure_(closure), 6869 : closure_(closure),
6873 values_(0), 6870 values_(0),
6874 assigned_variables_(4), 6871 assigned_variables_(4),
6875 parameter_count_(0), 6872 parameter_count_(0),
6876 specials_count_(1), 6873 specials_count_(1),
6877 local_count_(0), 6874 local_count_(0),
6878 outer_(outer), 6875 outer_(outer),
6879 pop_count_(0), 6876 pop_count_(0),
6880 push_count_(0), 6877 push_count_(0),
6881 ast_id_(AstNode::kNoNumber) { 6878 ast_id_(AstNode::kNoNumber),
6879 arguments_adaptor_(false) {
6882 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 6880 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
6883 } 6881 }
6884 6882
6885 6883
6886 HEnvironment::HEnvironment(const HEnvironment* other) 6884 HEnvironment::HEnvironment(const HEnvironment* other)
6887 : values_(0), 6885 : values_(0),
6888 assigned_variables_(0), 6886 assigned_variables_(0),
6889 parameter_count_(0), 6887 parameter_count_(0),
6890 specials_count_(1), 6888 specials_count_(1),
6891 local_count_(0), 6889 local_count_(0),
6892 outer_(NULL), 6890 outer_(NULL),
6893 pop_count_(0), 6891 pop_count_(0),
6894 push_count_(0), 6892 push_count_(0),
6895 ast_id_(other->ast_id()) { 6893 ast_id_(other->ast_id()),
6894 arguments_adaptor_(false) {
6896 Initialize(other); 6895 Initialize(other);
6897 } 6896 }
6898 6897
6899 6898
6899 HEnvironment::HEnvironment(HEnvironment* outer,
6900 Handle<JSFunction> closure,
6901 int arguments)
6902 : closure_(closure),
6903 values_(arguments),
6904 assigned_variables_(0),
6905 parameter_count_(arguments),
6906 local_count_(0),
6907 outer_(outer),
6908 pop_count_(0),
6909 push_count_(0),
6910 ast_id_(AstNode::kNoNumber),
6911 arguments_adaptor_(true) {
6912 }
6913
6914
6900 void HEnvironment::Initialize(int parameter_count, 6915 void HEnvironment::Initialize(int parameter_count,
6901 int local_count, 6916 int local_count,
6902 int stack_height) { 6917 int stack_height) {
6903 parameter_count_ = parameter_count; 6918 parameter_count_ = parameter_count;
6904 local_count_ = local_count; 6919 local_count_ = local_count;
6905 6920
6906 // Avoid reallocating the temporaries' backing store on the first Push. 6921 // Avoid reallocating the temporaries' backing store on the first Push.
6907 int total = parameter_count + specials_count_ + local_count + stack_height; 6922 int total = parameter_count + specials_count_ + local_count + stack_height;
6908 values_.Initialize(total + 4); 6923 values_.Initialize(total + 4);
6909 for (int i = 0; i < total; ++i) values_.Add(NULL); 6924 for (int i = 0; i < total; ++i) values_.Add(NULL);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
7016 new_env->values_[i] = phi; 7031 new_env->values_[i] = phi;
7017 loop_header->AddPhi(phi); 7032 loop_header->AddPhi(phi);
7018 } 7033 }
7019 new_env->ClearHistory(); 7034 new_env->ClearHistory();
7020 return new_env; 7035 return new_env;
7021 } 7036 }
7022 7037
7023 7038
7024 HEnvironment* HEnvironment::CopyForInlining( 7039 HEnvironment* HEnvironment::CopyForInlining(
7025 Handle<JSFunction> target, 7040 Handle<JSFunction> target,
7041 int arguments,
7026 FunctionLiteral* function, 7042 FunctionLiteral* function,
7027 HConstant* undefined, 7043 HConstant* undefined,
7028 CallKind call_kind) const { 7044 CallKind call_kind) const {
7045 ASSERT(!is_arguments_adaptor());
7046
7047 Zone* zone = closure()->GetIsolate()->zone();
7048
7029 // Outer environment is a copy of this one without the arguments. 7049 // Outer environment is a copy of this one without the arguments.
7030 int arity = function->scope()->num_parameters(); 7050 int arity = function->scope()->num_parameters();
7051
7031 HEnvironment* outer = Copy(); 7052 HEnvironment* outer = Copy();
7032 outer->Drop(arity + 1); // Including receiver. 7053 outer->Drop(arguments + 1); // Including receiver.
7033 outer->ClearHistory(); 7054 outer->ClearHistory();
7034 Zone* zone = closure()->GetIsolate()->zone(); 7055
7056 if (arity != arguments) {
7057 // Create artificial arguments adaptation environment.
7058 outer = new(zone) HEnvironment(outer, target, arguments + 1);
7059 for (int i = 0; i <= arguments; ++i) { // Include receiver.
7060 outer->Push(ExpressionStackAt(arguments - i));
7061 }
7062 outer->ClearHistory();
7063 }
7064
7035 HEnvironment* inner = 7065 HEnvironment* inner =
7036 new(zone) HEnvironment(outer, function->scope(), target); 7066 new(zone) HEnvironment(outer, function->scope(), target);
7037 // Get the argument values from the original environment. 7067 // Get the argument values from the original environment.
7038 for (int i = 0; i <= arity; ++i) { // Include receiver. 7068 for (int i = 0; i <= arity; ++i) { // Include receiver.
7039 HValue* push = ExpressionStackAt(arity - i); 7069 HValue* push = (arguments >= i) ?
7070 ExpressionStackAt(arguments - i) : undefined;
7040 inner->SetValueAt(i, push); 7071 inner->SetValueAt(i, push);
7041 } 7072 }
7042 // If the function we are inlining is a strict mode function or a 7073 // If the function we are inlining is a strict mode function or a
7043 // builtin function, pass undefined as the receiver for function 7074 // builtin function, pass undefined as the receiver for function
7044 // calls (instead of the global receiver). 7075 // calls (instead of the global receiver).
7045 if ((target->shared()->native() || !function->is_classic_mode()) && 7076 if ((target->shared()->native() || !function->is_classic_mode()) &&
7046 call_kind == CALL_AS_FUNCTION) { 7077 call_kind == CALL_AS_FUNCTION) {
7047 inner->SetValueAt(0, undefined); 7078 inner->SetValueAt(0, undefined);
7048 } 7079 }
7049 inner->SetValueAt(arity + 1, outer->LookupContext()); 7080 inner->SetValueAt(arity + 1, LookupContext());
7050 for (int i = arity + 2; i < inner->length(); ++i) { 7081 for (int i = arity + 2; i < inner->length(); ++i) {
7051 inner->SetValueAt(i, undefined); 7082 inner->SetValueAt(i, undefined);
7052 } 7083 }
7053 7084
7054 inner->set_ast_id(AstNode::kFunctionEntryId); 7085 inner->set_ast_id(AstNode::kFunctionEntryId);
7055 return inner; 7086 return inner;
7056 } 7087 }
7057 7088
7058 7089
7059 void HEnvironment::PrintTo(StringStream* stream) { 7090 void HEnvironment::PrintTo(StringStream* stream) {
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
7388 } 7419 }
7389 } 7420 }
7390 7421
7391 #ifdef DEBUG 7422 #ifdef DEBUG
7392 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7423 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7393 if (allocator_ != NULL) allocator_->Verify(); 7424 if (allocator_ != NULL) allocator_->Verify();
7394 #endif 7425 #endif
7395 } 7426 }
7396 7427
7397 } } // namespace v8::internal 7428 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698