Chromium Code Reviews| 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 |