OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |