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

Side by Side Diff: src/hydrogen.cc

Issue 10836133: Inline simple setter calls. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased. Extended unit tests. Created 8 years, 4 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 ASSERT(!IsFinished()); 159 ASSERT(!IsFinished());
160 AddInstruction(end); 160 AddInstruction(end);
161 end_ = end; 161 end_ = end;
162 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 162 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
163 it.Current()->RegisterPredecessor(this); 163 it.Current()->RegisterPredecessor(this);
164 } 164 }
165 } 165 }
166 166
167 167
168 void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) { 168 void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) {
169 bool drop_extra = state != NULL && state->drop_extra(); 169 bool drop_extra = state != NULL &&
170 state->inlining_kind() == DROP_EXTRA_ON_RETURN;
170 bool arguments_pushed = state != NULL && state->arguments_pushed(); 171 bool arguments_pushed = state != NULL && state->arguments_pushed();
171 172
172 if (block->IsInlineReturnTarget()) { 173 if (block->IsInlineReturnTarget()) {
173 AddInstruction(new(zone()) HLeaveInlined(arguments_pushed)); 174 AddInstruction(new(zone()) HLeaveInlined(arguments_pushed));
174 last_environment_ = last_environment()->DiscardInlined(drop_extra); 175 last_environment_ = last_environment()->DiscardInlined(drop_extra);
175 } 176 }
176 177
177 AddSimulate(BailoutId::None()); 178 AddSimulate(BailoutId::None());
178 HGoto* instr = new(zone()) HGoto(block); 179 HGoto* instr = new(zone()) HGoto(block);
179 Finish(instr); 180 Finish(instr);
180 } 181 }
181 182
182 183
183 void HBasicBlock::AddLeaveInlined(HValue* return_value, 184 void HBasicBlock::AddLeaveInlined(HValue* return_value,
184 HBasicBlock* target,
185 FunctionState* state) { 185 FunctionState* state) {
186 bool drop_extra = state != NULL && state->drop_extra(); 186 HBasicBlock* target = state->function_return();
187 bool arguments_pushed = state != NULL && state->arguments_pushed(); 187 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN;
188 bool arguments_pushed = state->arguments_pushed();
188 189
189 ASSERT(target->IsInlineReturnTarget()); 190 ASSERT(target->IsInlineReturnTarget());
190 ASSERT(return_value != NULL); 191 ASSERT(return_value != NULL);
191 AddInstruction(new(zone()) HLeaveInlined(arguments_pushed)); 192 AddInstruction(new(zone()) HLeaveInlined(arguments_pushed));
192 last_environment_ = last_environment()->DiscardInlined(drop_extra); 193 last_environment_ = last_environment()->DiscardInlined(drop_extra);
193 last_environment()->Push(return_value); 194 last_environment()->Push(return_value);
194 AddSimulate(BailoutId::None()); 195 AddSimulate(BailoutId::None());
195 HGoto* instr = new(zone()) HGoto(target); 196 HGoto* instr = new(zone()) HGoto(target);
196 Finish(instr); 197 Finish(instr);
197 } 198 }
(...skipping 2546 matching lines...) Expand 10 before | Expand all | Expand 10 after
2744 } 2745 }
2745 } 2746 }
2746 } 2747 }
2747 2748
2748 2749
2749 // Implementation of utility class to encapsulate the translation state for 2750 // Implementation of utility class to encapsulate the translation state for
2750 // a (possibly inlined) function. 2751 // a (possibly inlined) function.
2751 FunctionState::FunctionState(HGraphBuilder* owner, 2752 FunctionState::FunctionState(HGraphBuilder* owner,
2752 CompilationInfo* info, 2753 CompilationInfo* info,
2753 TypeFeedbackOracle* oracle, 2754 TypeFeedbackOracle* oracle,
2754 ReturnHandlingFlag return_handling) 2755 InliningKind inlining_kind)
2755 : owner_(owner), 2756 : owner_(owner),
2756 compilation_info_(info), 2757 compilation_info_(info),
2757 oracle_(oracle), 2758 oracle_(oracle),
2758 call_context_(NULL), 2759 call_context_(NULL),
2759 return_handling_(return_handling), 2760 inlining_kind_(inlining_kind),
2760 function_return_(NULL), 2761 function_return_(NULL),
2761 test_context_(NULL), 2762 test_context_(NULL),
2762 entry_(NULL), 2763 entry_(NULL),
2763 arguments_elements_(NULL), 2764 arguments_elements_(NULL),
2764 outer_(owner->function_state()) { 2765 outer_(owner->function_state()) {
2765 if (outer_ != NULL) { 2766 if (outer_ != NULL) {
2766 // State for an inline function. 2767 // State for an inline function.
2767 if (owner->ast_context()->IsTest()) { 2768 if (owner->ast_context()->IsTest()) {
2768 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2769 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2769 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2770 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after
3824 Drop(drop_extra); 3825 Drop(drop_extra);
3825 current_block()->Goto(break_block); 3826 current_block()->Goto(break_block);
3826 set_current_block(NULL); 3827 set_current_block(NULL);
3827 } 3828 }
3828 3829
3829 3830
3830 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 3831 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
3831 ASSERT(!HasStackOverflow()); 3832 ASSERT(!HasStackOverflow());
3832 ASSERT(current_block() != NULL); 3833 ASSERT(current_block() != NULL);
3833 ASSERT(current_block()->HasPredecessor()); 3834 ASSERT(current_block()->HasPredecessor());
3835 FunctionState* state = function_state();
3834 AstContext* context = call_context(); 3836 AstContext* context = call_context();
3835 if (context == NULL) { 3837 if (context == NULL) {
3836 // Not an inlined return, so an actual one. 3838 // Not an inlined return, so an actual one.
3837 CHECK_ALIVE(VisitForValue(stmt->expression())); 3839 CHECK_ALIVE(VisitForValue(stmt->expression()));
3838 HValue* result = environment()->Pop(); 3840 HValue* result = environment()->Pop();
3839 current_block()->FinishExit(new(zone()) HReturn(result)); 3841 current_block()->FinishExit(new(zone()) HReturn(result));
3840 } else if (function_state()->is_construct()) { 3842 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
3841 // Return from an inlined construct call. In a test context the return 3843 // Return from an inlined construct call. In a test context the return value
3842 // value will always evaluate to true, in a value context the return value 3844 // will always evaluate to true, in a value context the return value needs
3843 // needs to be a JSObject. 3845 // to be a JSObject.
3844 if (context->IsTest()) { 3846 if (context->IsTest()) {
3845 TestContext* test = TestContext::cast(context); 3847 TestContext* test = TestContext::cast(context);
3846 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3848 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3847 current_block()->Goto(test->if_true(), function_state()); 3849 current_block()->Goto(test->if_true(), state);
3848 } else if (context->IsEffect()) { 3850 } else if (context->IsEffect()) {
3849 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3851 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3850 current_block()->Goto(function_return(), function_state()); 3852 current_block()->Goto(function_return(), state);
3851 } else { 3853 } else {
3852 ASSERT(context->IsValue()); 3854 ASSERT(context->IsValue());
3853 CHECK_ALIVE(VisitForValue(stmt->expression())); 3855 CHECK_ALIVE(VisitForValue(stmt->expression()));
3854 HValue* return_value = Pop(); 3856 HValue* return_value = Pop();
3855 HValue* receiver = environment()->Lookup(0); 3857 HValue* receiver = environment()->Lookup(0);
3856 HHasInstanceTypeAndBranch* typecheck = 3858 HHasInstanceTypeAndBranch* typecheck =
3857 new(zone()) HHasInstanceTypeAndBranch(return_value, 3859 new(zone()) HHasInstanceTypeAndBranch(return_value,
3858 FIRST_SPEC_OBJECT_TYPE, 3860 FIRST_SPEC_OBJECT_TYPE,
3859 LAST_SPEC_OBJECT_TYPE); 3861 LAST_SPEC_OBJECT_TYPE);
3860 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); 3862 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
3861 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); 3863 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
3862 typecheck->SetSuccessorAt(0, if_spec_object); 3864 typecheck->SetSuccessorAt(0, if_spec_object);
3863 typecheck->SetSuccessorAt(1, not_spec_object); 3865 typecheck->SetSuccessorAt(1, not_spec_object);
3864 current_block()->Finish(typecheck); 3866 current_block()->Finish(typecheck);
3865 if_spec_object->AddLeaveInlined(return_value, 3867 if_spec_object->AddLeaveInlined(return_value, state);
3866 function_return(), 3868 not_spec_object->AddLeaveInlined(receiver, state);
3867 function_state()); 3869 }
3868 not_spec_object->AddLeaveInlined(receiver, 3870 } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
3869 function_return(), 3871 // Return from an inlined setter call. The returned value is never used, the
3870 function_state()); 3872 // value of an assignment is always the value of the RHS of the assignment.
3873 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3874 if (context->IsTest()) {
3875 context->ReturnValue(environment()->Lookup(1));
3876 } else if (context->IsEffect()) {
3877 current_block()->Goto(function_return(), state);
3878 } else {
3879 ASSERT(context->IsValue());
3880 current_block()->AddLeaveInlined(environment()->Lookup(1), state);
3871 } 3881 }
3872 } else { 3882 } else {
3873 // Return from an inlined function, visit the subexpression in the 3883 // Return from a normal inlined function. Visit the subexpression in the
3874 // expression context of the call. 3884 // expression context of the call.
3875 if (context->IsTest()) { 3885 if (context->IsTest()) {
3876 TestContext* test = TestContext::cast(context); 3886 TestContext* test = TestContext::cast(context);
3877 VisitForControl(stmt->expression(), 3887 VisitForControl(stmt->expression(), test->if_true(), test->if_false());
3878 test->if_true(),
3879 test->if_false());
3880 } else if (context->IsEffect()) { 3888 } else if (context->IsEffect()) {
3881 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3889 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3882 current_block()->Goto(function_return(), function_state()); 3890 current_block()->Goto(function_return(), state);
3883 } else { 3891 } else {
3884 ASSERT(context->IsValue()); 3892 ASSERT(context->IsValue());
3885 CHECK_ALIVE(VisitForValue(stmt->expression())); 3893 CHECK_ALIVE(VisitForValue(stmt->expression()));
3886 HValue* return_value = Pop(); 3894 current_block()->AddLeaveInlined(Pop(), state);
3887 current_block()->AddLeaveInlined(return_value,
3888 function_return(),
3889 function_state());
3890 } 3895 }
3891 } 3896 }
3892 set_current_block(NULL); 3897 set_current_block(NULL);
3893 } 3898 }
3894 3899
3895 3900
3896 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 3901 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
3897 ASSERT(!HasStackOverflow()); 3902 ASSERT(!HasStackOverflow());
3898 ASSERT(current_block() != NULL); 3903 ASSERT(current_block() != NULL);
3899 ASSERT(current_block()->HasPredecessor()); 3904 ASSERT(current_block()->HasPredecessor());
(...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after
5226 bool monomorphic = expr->IsMonomorphic(); 5231 bool monomorphic = expr->IsMonomorphic();
5227 Handle<Map> map; 5232 Handle<Map> map;
5228 if (monomorphic) { 5233 if (monomorphic) {
5229 map = types->first(); 5234 map = types->first();
5230 if (map->is_dictionary_map()) monomorphic = false; 5235 if (map->is_dictionary_map()) monomorphic = false;
5231 } 5236 }
5232 if (monomorphic) { 5237 if (monomorphic) {
5233 Handle<AccessorPair> accessors; 5238 Handle<AccessorPair> accessors;
5234 Handle<JSObject> holder; 5239 Handle<JSObject> holder;
5235 if (LookupAccessorPair(map, name, &accessors, &holder)) { 5240 if (LookupAccessorPair(map, name, &accessors, &holder)) {
5241 Handle<JSFunction> setter(JSFunction::cast(accessors->setter()));
5242 AddCheckConstantFunction(holder, object, map, true);
5243 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) {
5244 return;
5245 }
5236 Drop(2); 5246 Drop(2);
5237 instr = BuildCallSetter(object, value, map, accessors, holder); 5247 AddInstruction(new(zone()) HPushArgument(object));
5248 AddInstruction(new(zone()) HPushArgument(value));
5249 instr = new(zone()) HCallConstantFunction(setter, 2);
5238 } else { 5250 } else {
5239 Drop(2); 5251 Drop(2);
5240 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, 5252 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5241 name, 5253 name,
5242 value, 5254 value,
5243 map)); 5255 map));
5244 } 5256 }
5245 5257
5246 } else if (types != NULL && types->length() > 1) { 5258 } else if (types != NULL && types->length() > 1) {
5247 Drop(2); 5259 Drop(2);
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
6626 } 6638 }
6627 6639
6628 int nodes_added = target_shared->ast_node_count(); 6640 int nodes_added = target_shared->ast_node_count();
6629 return nodes_added; 6641 return nodes_added;
6630 } 6642 }
6631 6643
6632 6644
6633 bool HGraphBuilder::TryInline(CallKind call_kind, 6645 bool HGraphBuilder::TryInline(CallKind call_kind,
6634 Handle<JSFunction> target, 6646 Handle<JSFunction> target,
6635 int arguments_count, 6647 int arguments_count,
6636 HValue* receiver, 6648 HValue* implicit_return_value,
6637 BailoutId ast_id, 6649 BailoutId ast_id,
6638 BailoutId return_id, 6650 BailoutId return_id,
6639 ReturnHandlingFlag return_handling) { 6651 InliningKind inlining_kind) {
6640 int nodes_added = InliningAstSize(target); 6652 int nodes_added = InliningAstSize(target);
6641 if (nodes_added == kNotInlinable) return false; 6653 if (nodes_added == kNotInlinable) return false;
6642 6654
6643 Handle<JSFunction> caller = info()->closure(); 6655 Handle<JSFunction> caller = info()->closure();
6644 6656
6645 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 6657 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6646 TraceInline(target, caller, "target AST is too large [early]"); 6658 TraceInline(target, caller, "target AST is too large [early]");
6647 return false; 6659 return false;
6648 } 6660 }
6649 6661
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
6782 // for the inlined function. 6794 // for the inlined function.
6783 ASSERT(target_shared->has_deoptimization_support()); 6795 ASSERT(target_shared->has_deoptimization_support());
6784 TypeFeedbackOracle target_oracle( 6796 TypeFeedbackOracle target_oracle(
6785 Handle<Code>(target_shared->code()), 6797 Handle<Code>(target_shared->code()),
6786 Handle<Context>(target->context()->global_context()), 6798 Handle<Context>(target->context()->global_context()),
6787 isolate(), 6799 isolate(),
6788 zone()); 6800 zone());
6789 // The function state is new-allocated because we need to delete it 6801 // The function state is new-allocated because we need to delete it
6790 // in two different places. 6802 // in two different places.
6791 FunctionState* target_state = new FunctionState( 6803 FunctionState* target_state = new FunctionState(
6792 this, &target_info, &target_oracle, return_handling); 6804 this, &target_info, &target_oracle, inlining_kind);
6793 6805
6794 HConstant* undefined = graph()->GetConstantUndefined(); 6806 HConstant* undefined = graph()->GetConstantUndefined();
6795 HEnvironment* inner_env = 6807 HEnvironment* inner_env =
6796 environment()->CopyForInlining(target, 6808 environment()->CopyForInlining(target,
6797 arguments_count, 6809 arguments_count,
6798 function, 6810 function,
6799 undefined, 6811 undefined,
6800 call_kind, 6812 call_kind,
6801 function_state()->is_construct()); 6813 function_state()->inlining_kind());
6802 #ifdef V8_TARGET_ARCH_IA32 6814 #ifdef V8_TARGET_ARCH_IA32
6803 // IA32 only, overwrite the caller's context in the deoptimization 6815 // IA32 only, overwrite the caller's context in the deoptimization
6804 // environment with the correct one. 6816 // environment with the correct one.
6805 // 6817 //
6806 // TODO(kmillikin): implement the same inlining on other platforms so we 6818 // TODO(kmillikin): implement the same inlining on other platforms so we
6807 // can remove the unsightly ifdefs in this function. 6819 // can remove the unsightly ifdefs in this function.
6808 HConstant* context = 6820 HConstant* context =
6809 new(zone()) HConstant(Handle<Context>(target->context()), 6821 new(zone()) HConstant(Handle<Context>(target->context()),
6810 Representation::Tagged()); 6822 Representation::Tagged());
6811 AddInstruction(context); 6823 AddInstruction(context);
(...skipping 14 matching lines...) Expand all
6826 for (int i = 0; i < arguments_count; i++) { 6838 for (int i = 0; i < arguments_count; i++) {
6827 arguments_values->Add(arguments_env->Lookup(i), zone()); 6839 arguments_values->Add(arguments_env->Lookup(i), zone());
6828 } 6840 }
6829 } 6841 }
6830 6842
6831 HEnterInlined* enter_inlined = 6843 HEnterInlined* enter_inlined =
6832 new(zone()) HEnterInlined(target, 6844 new(zone()) HEnterInlined(target,
6833 arguments_count, 6845 arguments_count,
6834 function, 6846 function,
6835 call_kind, 6847 call_kind,
6836 function_state()->is_construct(), 6848 function_state()->inlining_kind(),
6837 function->scope()->arguments(), 6849 function->scope()->arguments(),
6838 arguments_values); 6850 arguments_values);
6839 function_state()->set_entry(enter_inlined); 6851 function_state()->set_entry(enter_inlined);
6840 AddInstruction(enter_inlined); 6852 AddInstruction(enter_inlined);
6841 6853
6842 // If the function uses arguments object create and bind one. 6854 // If the function uses arguments object create and bind one.
6843 if (function->scope()->arguments() != NULL) { 6855 if (function->scope()->arguments() != NULL) {
6844 ASSERT(function->scope()->arguments()->IsStackAllocated()); 6856 ASSERT(function->scope()->arguments()->IsStackAllocated());
6845 inner_env->Bind(function->scope()->arguments(), 6857 inner_env->Bind(function->scope()->arguments(),
6846 graph()->GetArgumentsObject()); 6858 graph()->GetArgumentsObject());
(...skipping 11 matching lines...) Expand all
6858 delete target_state; 6870 delete target_state;
6859 return true; 6871 return true;
6860 } 6872 }
6861 6873
6862 // Update inlined nodes count. 6874 // Update inlined nodes count.
6863 inlined_count_ += nodes_added; 6875 inlined_count_ += nodes_added;
6864 6876
6865 TraceInline(target, caller, NULL); 6877 TraceInline(target, caller, NULL);
6866 6878
6867 if (current_block() != NULL) { 6879 if (current_block() != NULL) {
6868 // Add default return value (i.e. undefined for normals calls or the newly 6880 FunctionState* state = function_state();
6869 // allocated receiver for construct calls) if control can fall off the 6881 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
6870 // body. In a test context, undefined is false and any JSObject is true. 6882 // Falling off the end of an inlined construct call. In a test context the
6871 if (call_context()->IsValue()) { 6883 // return value will always evaluate to true, in a value context the
6872 ASSERT(function_return() != NULL); 6884 // return value is the newly allocated receiver.
6873 HValue* return_value = function_state()->is_construct() 6885 if (call_context()->IsTest()) {
6874 ? receiver 6886 current_block()->Goto(inlined_test_context()->if_true(), state);
6875 : undefined; 6887 } else if (call_context()->IsEffect()) {
6876 current_block()->AddLeaveInlined(return_value, 6888 current_block()->Goto(function_return(), state);
6877 function_return(), 6889 } else {
6878 function_state()); 6890 ASSERT(call_context()->IsValue());
6879 } else if (call_context()->IsEffect()) { 6891 current_block()->AddLeaveInlined(implicit_return_value, state);
6880 ASSERT(function_return() != NULL); 6892 }
6881 current_block()->Goto(function_return(), function_state()); 6893 } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
6894 // Falling off the end of an inlined setter call. The returned value is
6895 // never used, the value of an assignment is always the value of the RHS
6896 // of the assignment.
6897 if (call_context()->IsTest()) {
6898 inlined_test_context()->ReturnValue(implicit_return_value);
6899 } else if (call_context()->IsEffect()) {
6900 current_block()->Goto(function_return(), state);
6901 } else {
6902 ASSERT(call_context()->IsValue());
6903 current_block()->AddLeaveInlined(implicit_return_value, state);
6904 }
6882 } else { 6905 } else {
6883 ASSERT(call_context()->IsTest()); 6906 // Falling off the end of a normal inlined function. This basically means
6884 ASSERT(inlined_test_context() != NULL); 6907 // returning undefined.
6885 HBasicBlock* target = function_state()->is_construct() 6908 if (call_context()->IsTest()) {
6886 ? inlined_test_context()->if_true() 6909 current_block()->Goto(inlined_test_context()->if_false(), state);
6887 : inlined_test_context()->if_false(); 6910 } else if (call_context()->IsEffect()) {
6888 current_block()->Goto(target, function_state()); 6911 current_block()->Goto(function_return(), state);
6912 } else {
6913 ASSERT(call_context()->IsValue());
6914 current_block()->AddLeaveInlined(undefined, state);
6915 }
6889 } 6916 }
6890 } 6917 }
6891 6918
6892 // Fix up the function exits. 6919 // Fix up the function exits.
6893 if (inlined_test_context() != NULL) { 6920 if (inlined_test_context() != NULL) {
6894 HBasicBlock* if_true = inlined_test_context()->if_true(); 6921 HBasicBlock* if_true = inlined_test_context()->if_true();
6895 HBasicBlock* if_false = inlined_test_context()->if_false(); 6922 HBasicBlock* if_false = inlined_test_context()->if_false();
6896 6923
6897 // Pop the return test context from the expression context stack. 6924 // Pop the return test context from the expression context stack.
6898 ASSERT(ast_context() == inlined_test_context()); 6925 ASSERT(ast_context() == inlined_test_context());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
6934 return TryInline(call_kind, 6961 return TryInline(call_kind,
6935 expr->target(), 6962 expr->target(),
6936 expr->arguments()->length(), 6963 expr->arguments()->length(),
6937 NULL, 6964 NULL,
6938 expr->id(), 6965 expr->id(),
6939 expr->ReturnId(), 6966 expr->ReturnId(),
6940 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); 6967 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN);
6941 } 6968 }
6942 6969
6943 6970
6944 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) { 6971 bool HGraphBuilder::TryInlineConstruct(CallNew* expr,
6972 HValue* implicit_return_value) {
6945 return TryInline(CALL_AS_FUNCTION, 6973 return TryInline(CALL_AS_FUNCTION,
6946 expr->target(), 6974 expr->target(),
6947 expr->arguments()->length(), 6975 expr->arguments()->length(),
6948 receiver, 6976 implicit_return_value,
6949 expr->id(), 6977 expr->id(),
6950 expr->ReturnId(), 6978 expr->ReturnId(),
6951 CONSTRUCT_CALL_RETURN); 6979 CONSTRUCT_CALL_RETURN);
6952 } 6980 }
6953 6981
6954 6982
6955 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, 6983 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
6956 Property* prop) { 6984 Property* prop) {
6957 return TryInline(CALL_AS_METHOD, 6985 return TryInline(CALL_AS_METHOD,
6958 getter, 6986 getter,
6959 0, 6987 0,
6960 NULL, 6988 NULL,
6961 prop->id(), 6989 prop->id(),
6962 prop->LoadId(), 6990 prop->LoadId(),
6963 NORMAL_RETURN); 6991 NORMAL_RETURN);
6964 } 6992 }
6965 6993
6966 6994
6995 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
6996 Assignment* assignment,
6997 HValue* implicit_return_value) {
6998 return TryInline(CALL_AS_METHOD,
6999 setter,
7000 1,
7001 implicit_return_value,
7002 assignment->id(),
7003 assignment->AssignmentId(),
7004 SETTER_CALL_RETURN);
7005 }
7006
7007
6967 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { 7008 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
6968 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7009 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
6969 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7010 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
6970 switch (id) { 7011 switch (id) {
6971 case kMathRound: 7012 case kMathRound:
6972 case kMathAbs: 7013 case kMathAbs:
6973 case kMathSqrt: 7014 case kMathSqrt:
6974 case kMathLog: 7015 case kMathLog:
6975 case kMathSin: 7016 case kMathSin:
6976 case kMathCos: 7017 case kMathCos:
(...skipping 1663 matching lines...) Expand 10 before | Expand all | Expand 10 after
8640 return Bailout( 8681 return Bailout(
8641 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 8682 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
8642 } 8683 }
8643 8684
8644 8685
8645 // Support for construct call checks. 8686 // Support for construct call checks.
8646 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 8687 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
8647 ASSERT(call->arguments()->length() == 0); 8688 ASSERT(call->arguments()->length() == 0);
8648 if (function_state()->outer() != NULL) { 8689 if (function_state()->outer() != NULL) {
8649 // We are generating graph for inlined function. 8690 // We are generating graph for inlined function.
8650 HValue* value = function_state()->is_construct() 8691 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
8651 ? graph()->GetConstantTrue() 8692 ? graph()->GetConstantTrue()
8652 : graph()->GetConstantFalse(); 8693 : graph()->GetConstantFalse();
8653 return ast_context()->ReturnValue(value); 8694 return ast_context()->ReturnValue(value);
8654 } else { 8695 } else {
8655 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 8696 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
8656 call->id()); 8697 call->id());
8657 } 8698 }
8658 } 8699 }
8659 8700
8660 8701
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
9230 return new_env; 9271 return new_env;
9231 } 9272 }
9232 9273
9233 9274
9234 HEnvironment* HEnvironment::CopyForInlining( 9275 HEnvironment* HEnvironment::CopyForInlining(
9235 Handle<JSFunction> target, 9276 Handle<JSFunction> target,
9236 int arguments, 9277 int arguments,
9237 FunctionLiteral* function, 9278 FunctionLiteral* function,
9238 HConstant* undefined, 9279 HConstant* undefined,
9239 CallKind call_kind, 9280 CallKind call_kind,
9240 bool is_construct) const { 9281 InliningKind inlining_kind) const {
9241 ASSERT(frame_type() == JS_FUNCTION); 9282 ASSERT(frame_type() == JS_FUNCTION);
9242 9283
9243 // Outer environment is a copy of this one without the arguments. 9284 // Outer environment is a copy of this one without the arguments.
9244 int arity = function->scope()->num_parameters(); 9285 int arity = function->scope()->num_parameters();
9245 9286
9246 HEnvironment* outer = Copy(); 9287 HEnvironment* outer = Copy();
9247 outer->Drop(arguments + 1); // Including receiver. 9288 outer->Drop(arguments + 1); // Including receiver.
9248 outer->ClearHistory(); 9289 outer->ClearHistory();
9249 9290
9250 if (is_construct) { 9291 if (inlining_kind == CONSTRUCT_CALL_RETURN) {
9251 // Create artificial constructor stub environment. The receiver should 9292 // Create artificial constructor stub environment. The receiver should
9252 // actually be the constructor function, but we pass the newly allocated 9293 // actually be the constructor function, but we pass the newly allocated
9253 // object instead, DoComputeConstructStubFrame() relies on that. 9294 // object instead, DoComputeConstructStubFrame() relies on that.
9254 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments); 9295 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
9255 } 9296 }
9256 9297
9257 if (arity != arguments) { 9298 if (arity != arguments) {
9258 // Create artificial arguments adaptation environment. 9299 // Create artificial arguments adaptation environment.
9259 outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments); 9300 outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
9260 } 9301 }
9261 9302
9262 HEnvironment* inner = 9303 HEnvironment* inner =
9263 new(zone()) HEnvironment(outer, function->scope(), target, zone()); 9304 new(zone()) HEnvironment(outer, function->scope(), target, zone());
9264 // Get the argument values from the original environment. 9305 // Get the argument values from the original environment.
9265 for (int i = 0; i <= arity; ++i) { // Include receiver. 9306 for (int i = 0; i <= arity; ++i) { // Include receiver.
9266 HValue* push = (i <= arguments) ? 9307 HValue* push = (i <= arguments) ?
9267 ExpressionStackAt(arguments - i) : undefined; 9308 ExpressionStackAt(arguments - i) : undefined;
9268 inner->SetValueAt(i, push); 9309 inner->SetValueAt(i, push);
9269 } 9310 }
9270 // If the function we are inlining is a strict mode function or a 9311 // If the function we are inlining is a strict mode function or a
9271 // builtin function, pass undefined as the receiver for function 9312 // builtin function, pass undefined as the receiver for function
9272 // calls (instead of the global receiver). 9313 // calls (instead of the global receiver).
9273 if ((target->shared()->native() || !function->is_classic_mode()) && 9314 if ((target->shared()->native() || !function->is_classic_mode()) &&
9274 call_kind == CALL_AS_FUNCTION && !is_construct) { 9315 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN) {
9275 inner->SetValueAt(0, undefined); 9316 inner->SetValueAt(0, undefined);
9276 } 9317 }
9277 inner->SetValueAt(arity + 1, LookupContext()); 9318 inner->SetValueAt(arity + 1, LookupContext());
9278 for (int i = arity + 2; i < inner->length(); ++i) { 9319 for (int i = arity + 2; i < inner->length(); ++i) {
9279 inner->SetValueAt(i, undefined); 9320 inner->SetValueAt(i, undefined);
9280 } 9321 }
9281 9322
9282 inner->set_ast_id(BailoutId::FunctionEntry()); 9323 inner->set_ast_id(BailoutId::FunctionEntry());
9283 return inner; 9324 return inner;
9284 } 9325 }
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
9626 } 9667 }
9627 } 9668 }
9628 9669
9629 #ifdef DEBUG 9670 #ifdef DEBUG
9630 if (graph_ != NULL) graph_->Verify(false); // No full verify. 9671 if (graph_ != NULL) graph_->Verify(false); // No full verify.
9631 if (allocator_ != NULL) allocator_->Verify(); 9672 if (allocator_ != NULL) allocator_->Verify();
9632 #endif 9673 #endif
9633 } 9674 }
9634 9675
9635 } } // namespace v8::internal 9676 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698