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

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: Added comment. 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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()->arguments_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 HValue* rhs = environment()->arguments_environment()->Lookup(1);
3876 context->ReturnValue(rhs);
3877 } else if (context->IsEffect()) {
3878 current_block()->Goto(function_return(), state);
3879 } else {
3880 ASSERT(context->IsValue());
3881 HValue* rhs = environment()->arguments_environment()->Lookup(1);
3882 current_block()->AddLeaveInlined(rhs, state);
3871 } 3883 }
3872 } else { 3884 } else {
3873 // Return from an inlined function, visit the subexpression in the 3885 // Return from a normal inlined function. Visit the subexpression in the
3874 // expression context of the call. 3886 // expression context of the call.
3875 if (context->IsTest()) { 3887 if (context->IsTest()) {
3876 TestContext* test = TestContext::cast(context); 3888 TestContext* test = TestContext::cast(context);
3877 VisitForControl(stmt->expression(), 3889 VisitForControl(stmt->expression(), test->if_true(), test->if_false());
3878 test->if_true(),
3879 test->if_false());
3880 } else if (context->IsEffect()) { 3890 } else if (context->IsEffect()) {
3881 CHECK_ALIVE(VisitForEffect(stmt->expression())); 3891 CHECK_ALIVE(VisitForEffect(stmt->expression()));
3882 current_block()->Goto(function_return(), function_state()); 3892 current_block()->Goto(function_return(), state);
3883 } else { 3893 } else {
3884 ASSERT(context->IsValue()); 3894 ASSERT(context->IsValue());
3885 CHECK_ALIVE(VisitForValue(stmt->expression())); 3895 CHECK_ALIVE(VisitForValue(stmt->expression()));
3886 HValue* return_value = Pop(); 3896 current_block()->AddLeaveInlined(Pop(), state);
3887 current_block()->AddLeaveInlined(return_value,
3888 function_return(),
3889 function_state());
3890 } 3897 }
3891 } 3898 }
3892 set_current_block(NULL); 3899 set_current_block(NULL);
3893 } 3900 }
3894 3901
3895 3902
3896 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 3903 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
3897 ASSERT(!HasStackOverflow()); 3904 ASSERT(!HasStackOverflow());
3898 ASSERT(current_block() != NULL); 3905 ASSERT(current_block() != NULL);
3899 ASSERT(current_block()->HasPredecessor()); 3906 ASSERT(current_block()->HasPredecessor());
(...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after
5226 bool monomorphic = expr->IsMonomorphic(); 5233 bool monomorphic = expr->IsMonomorphic();
5227 Handle<Map> map; 5234 Handle<Map> map;
5228 if (monomorphic) { 5235 if (monomorphic) {
5229 map = types->first(); 5236 map = types->first();
5230 if (map->is_dictionary_map()) monomorphic = false; 5237 if (map->is_dictionary_map()) monomorphic = false;
5231 } 5238 }
5232 if (monomorphic) { 5239 if (monomorphic) {
5233 Handle<AccessorPair> accessors; 5240 Handle<AccessorPair> accessors;
5234 Handle<JSObject> holder; 5241 Handle<JSObject> holder;
5235 if (LookupAccessorPair(map, name, &accessors, &holder)) { 5242 if (LookupAccessorPair(map, name, &accessors, &holder)) {
5243 Handle<JSFunction> setter(JSFunction::cast(accessors->setter()));
5244 AddCheckConstantFunction(holder, object, map, true);
5245 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) {
5246 return;
5247 }
5236 Drop(2); 5248 Drop(2);
5237 instr = BuildCallSetter(object, value, map, accessors, holder); 5249 AddInstruction(new(zone()) HPushArgument(object));
5250 AddInstruction(new(zone()) HPushArgument(value));
5251 instr = new(zone()) HCallConstantFunction(setter, 2);
5238 } else { 5252 } else {
5239 Drop(2); 5253 Drop(2);
5240 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, 5254 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5241 name, 5255 name,
5242 value, 5256 value,
5243 map)); 5257 map));
5244 } 5258 }
5245 5259
5246 } else if (types != NULL && types->length() > 1) { 5260 } else if (types != NULL && types->length() > 1) {
5247 Drop(2); 5261 Drop(2);
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
6626 } 6640 }
6627 6641
6628 int nodes_added = target_shared->ast_node_count(); 6642 int nodes_added = target_shared->ast_node_count();
6629 return nodes_added; 6643 return nodes_added;
6630 } 6644 }
6631 6645
6632 6646
6633 bool HGraphBuilder::TryInline(CallKind call_kind, 6647 bool HGraphBuilder::TryInline(CallKind call_kind,
6634 Handle<JSFunction> target, 6648 Handle<JSFunction> target,
6635 int arguments_count, 6649 int arguments_count,
6636 HValue* receiver, 6650 HValue* implicit_return_value,
6637 BailoutId ast_id, 6651 BailoutId ast_id,
6638 BailoutId return_id, 6652 BailoutId return_id,
6639 ReturnHandlingFlag return_handling) { 6653 InliningKind inlining_kind) {
6640 int nodes_added = InliningAstSize(target); 6654 int nodes_added = InliningAstSize(target);
6641 if (nodes_added == kNotInlinable) return false; 6655 if (nodes_added == kNotInlinable) return false;
6642 6656
6643 Handle<JSFunction> caller = info()->closure(); 6657 Handle<JSFunction> caller = info()->closure();
6644 6658
6645 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 6659 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6646 TraceInline(target, caller, "target AST is too large [early]"); 6660 TraceInline(target, caller, "target AST is too large [early]");
6647 return false; 6661 return false;
6648 } 6662 }
6649 6663
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
6782 // for the inlined function. 6796 // for the inlined function.
6783 ASSERT(target_shared->has_deoptimization_support()); 6797 ASSERT(target_shared->has_deoptimization_support());
6784 TypeFeedbackOracle target_oracle( 6798 TypeFeedbackOracle target_oracle(
6785 Handle<Code>(target_shared->code()), 6799 Handle<Code>(target_shared->code()),
6786 Handle<Context>(target->context()->global_context()), 6800 Handle<Context>(target->context()->global_context()),
6787 isolate(), 6801 isolate(),
6788 zone()); 6802 zone());
6789 // The function state is new-allocated because we need to delete it 6803 // The function state is new-allocated because we need to delete it
6790 // in two different places. 6804 // in two different places.
6791 FunctionState* target_state = new FunctionState( 6805 FunctionState* target_state = new FunctionState(
6792 this, &target_info, &target_oracle, return_handling); 6806 this, &target_info, &target_oracle, inlining_kind);
6793 6807
6794 HConstant* undefined = graph()->GetConstantUndefined(); 6808 HConstant* undefined = graph()->GetConstantUndefined();
6795 HEnvironment* inner_env = 6809 HEnvironment* inner_env =
6796 environment()->CopyForInlining(target, 6810 environment()->CopyForInlining(target,
6797 arguments_count, 6811 arguments_count,
6798 function, 6812 function,
6799 undefined, 6813 undefined,
6800 call_kind, 6814 call_kind,
6801 function_state()->is_construct()); 6815 function_state()->inlining_kind());
6802 #ifdef V8_TARGET_ARCH_IA32 6816 #ifdef V8_TARGET_ARCH_IA32
6803 // IA32 only, overwrite the caller's context in the deoptimization 6817 // IA32 only, overwrite the caller's context in the deoptimization
6804 // environment with the correct one. 6818 // environment with the correct one.
6805 // 6819 //
6806 // TODO(kmillikin): implement the same inlining on other platforms so we 6820 // TODO(kmillikin): implement the same inlining on other platforms so we
6807 // can remove the unsightly ifdefs in this function. 6821 // can remove the unsightly ifdefs in this function.
6808 HConstant* context = 6822 HConstant* context =
6809 new(zone()) HConstant(Handle<Context>(target->context()), 6823 new(zone()) HConstant(Handle<Context>(target->context()),
6810 Representation::Tagged()); 6824 Representation::Tagged());
6811 AddInstruction(context); 6825 AddInstruction(context);
(...skipping 14 matching lines...) Expand all
6826 for (int i = 0; i < arguments_count; i++) { 6840 for (int i = 0; i < arguments_count; i++) {
6827 arguments_values->Add(arguments_env->Lookup(i), zone()); 6841 arguments_values->Add(arguments_env->Lookup(i), zone());
6828 } 6842 }
6829 } 6843 }
6830 6844
6831 HEnterInlined* enter_inlined = 6845 HEnterInlined* enter_inlined =
6832 new(zone()) HEnterInlined(target, 6846 new(zone()) HEnterInlined(target,
6833 arguments_count, 6847 arguments_count,
6834 function, 6848 function,
6835 call_kind, 6849 call_kind,
6836 function_state()->is_construct(), 6850 function_state()->inlining_kind(),
6837 function->scope()->arguments(), 6851 function->scope()->arguments(),
6838 arguments_values); 6852 arguments_values);
6839 function_state()->set_entry(enter_inlined); 6853 function_state()->set_entry(enter_inlined);
6840 AddInstruction(enter_inlined); 6854 AddInstruction(enter_inlined);
6841 6855
6842 // If the function uses arguments object create and bind one. 6856 // If the function uses arguments object create and bind one.
6843 if (function->scope()->arguments() != NULL) { 6857 if (function->scope()->arguments() != NULL) {
6844 ASSERT(function->scope()->arguments()->IsStackAllocated()); 6858 ASSERT(function->scope()->arguments()->IsStackAllocated());
6845 inner_env->Bind(function->scope()->arguments(), 6859 inner_env->Bind(function->scope()->arguments(),
6846 graph()->GetArgumentsObject()); 6860 graph()->GetArgumentsObject());
(...skipping 11 matching lines...) Expand all
6858 delete target_state; 6872 delete target_state;
6859 return true; 6873 return true;
6860 } 6874 }
6861 6875
6862 // Update inlined nodes count. 6876 // Update inlined nodes count.
6863 inlined_count_ += nodes_added; 6877 inlined_count_ += nodes_added;
6864 6878
6865 TraceInline(target, caller, NULL); 6879 TraceInline(target, caller, NULL);
6866 6880
6867 if (current_block() != NULL) { 6881 if (current_block() != NULL) {
6868 // Add default return value (i.e. undefined for normals calls or the newly 6882 FunctionState* state = function_state();
6869 // allocated receiver for construct calls) if control can fall off the 6883 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
6870 // body. In a test context, undefined is false and any JSObject is true. 6884 // Falling off the end of an inlined construct call. In a test context the
6871 if (call_context()->IsValue()) { 6885 // return value will always evaluate to true, in a value context the
6872 ASSERT(function_return() != NULL); 6886 // return value is the newly allocated receiver.
6873 HValue* return_value = function_state()->is_construct() 6887 if (call_context()->IsTest()) {
6874 ? receiver 6888 current_block()->Goto(inlined_test_context()->if_true(), state);
6875 : undefined; 6889 } else if (call_context()->IsEffect()) {
6876 current_block()->AddLeaveInlined(return_value, 6890 current_block()->Goto(function_return(), state);
6877 function_return(), 6891 } else {
6878 function_state()); 6892 ASSERT(call_context()->IsValue());
6879 } else if (call_context()->IsEffect()) { 6893 current_block()->AddLeaveInlined(implicit_return_value, state);
6880 ASSERT(function_return() != NULL); 6894 }
6881 current_block()->Goto(function_return(), function_state()); 6895 } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
6896 // Falling off the end of an inlined setter call. The returned value is
6897 // never used, the value of an assignment is always the value of the RHS
6898 // of the assignment.
6899 if (call_context()->IsTest()) {
6900 inlined_test_context()->ReturnValue(implicit_return_value);
6901 } else if (call_context()->IsEffect()) {
6902 current_block()->Goto(function_return(), state);
6903 } else {
6904 ASSERT(call_context()->IsValue());
6905 current_block()->AddLeaveInlined(implicit_return_value, state);
6906 }
6882 } else { 6907 } else {
6883 ASSERT(call_context()->IsTest()); 6908 // Falling off the end of a normal inlined function. This basically means
6884 ASSERT(inlined_test_context() != NULL); 6909 // returning undefined.
6885 HBasicBlock* target = function_state()->is_construct() 6910 if (call_context()->IsTest()) {
6886 ? inlined_test_context()->if_true() 6911 current_block()->Goto(inlined_test_context()->if_false(), state);
6887 : inlined_test_context()->if_false(); 6912 } else if (call_context()->IsEffect()) {
6888 current_block()->Goto(target, function_state()); 6913 current_block()->Goto(function_return(), state);
6914 } else {
6915 ASSERT(call_context()->IsValue());
6916 current_block()->AddLeaveInlined(undefined, state);
6917 }
6889 } 6918 }
6890 } 6919 }
6891 6920
6892 // Fix up the function exits. 6921 // Fix up the function exits.
6893 if (inlined_test_context() != NULL) { 6922 if (inlined_test_context() != NULL) {
6894 HBasicBlock* if_true = inlined_test_context()->if_true(); 6923 HBasicBlock* if_true = inlined_test_context()->if_true();
6895 HBasicBlock* if_false = inlined_test_context()->if_false(); 6924 HBasicBlock* if_false = inlined_test_context()->if_false();
6896 6925
6897 // Pop the return test context from the expression context stack. 6926 // Pop the return test context from the expression context stack.
6898 ASSERT(ast_context() == inlined_test_context()); 6927 ASSERT(ast_context() == inlined_test_context());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
6934 return TryInline(call_kind, 6963 return TryInline(call_kind,
6935 expr->target(), 6964 expr->target(),
6936 expr->arguments()->length(), 6965 expr->arguments()->length(),
6937 NULL, 6966 NULL,
6938 expr->id(), 6967 expr->id(),
6939 expr->ReturnId(), 6968 expr->ReturnId(),
6940 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); 6969 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN);
6941 } 6970 }
6942 6971
6943 6972
6944 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) { 6973 bool HGraphBuilder::TryInlineConstruct(CallNew* expr,
6974 HValue* implicit_return_value) {
6945 return TryInline(CALL_AS_FUNCTION, 6975 return TryInline(CALL_AS_FUNCTION,
6946 expr->target(), 6976 expr->target(),
6947 expr->arguments()->length(), 6977 expr->arguments()->length(),
6948 receiver, 6978 implicit_return_value,
6949 expr->id(), 6979 expr->id(),
6950 expr->ReturnId(), 6980 expr->ReturnId(),
6951 CONSTRUCT_CALL_RETURN); 6981 CONSTRUCT_CALL_RETURN);
6952 } 6982 }
6953 6983
6954 6984
6955 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, 6985 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
6956 Property* prop) { 6986 Property* prop) {
6957 return TryInline(CALL_AS_METHOD, 6987 return TryInline(CALL_AS_METHOD,
6958 getter, 6988 getter,
6959 0, 6989 0,
6960 NULL, 6990 NULL,
6961 prop->id(), 6991 prop->id(),
6962 prop->LoadId(), 6992 prop->LoadId(),
6963 NORMAL_RETURN); 6993 NORMAL_RETURN);
6964 } 6994 }
6965 6995
6966 6996
6997 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
6998 Assignment* assignment,
6999 HValue* implicit_return_value) {
7000 return TryInline(CALL_AS_METHOD,
7001 setter,
7002 1,
7003 implicit_return_value,
7004 assignment->id(),
7005 assignment->AssignmentId(),
7006 SETTER_CALL_RETURN);
7007 }
7008
7009
6967 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { 7010 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
6968 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7011 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
6969 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7012 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
6970 switch (id) { 7013 switch (id) {
6971 case kMathRound: 7014 case kMathRound:
6972 case kMathAbs: 7015 case kMathAbs:
6973 case kMathSqrt: 7016 case kMathSqrt:
6974 case kMathLog: 7017 case kMathLog:
6975 case kMathSin: 7018 case kMathSin:
6976 case kMathCos: 7019 case kMathCos:
(...skipping 1663 matching lines...) Expand 10 before | Expand all | Expand 10 after
8640 return Bailout( 8683 return Bailout(
8641 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 8684 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
8642 } 8685 }
8643 8686
8644 8687
8645 // Support for construct call checks. 8688 // Support for construct call checks.
8646 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 8689 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
8647 ASSERT(call->arguments()->length() == 0); 8690 ASSERT(call->arguments()->length() == 0);
8648 if (function_state()->outer() != NULL) { 8691 if (function_state()->outer() != NULL) {
8649 // We are generating graph for inlined function. 8692 // We are generating graph for inlined function.
8650 HValue* value = function_state()->is_construct() 8693 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
8651 ? graph()->GetConstantTrue() 8694 ? graph()->GetConstantTrue()
8652 : graph()->GetConstantFalse(); 8695 : graph()->GetConstantFalse();
8653 return ast_context()->ReturnValue(value); 8696 return ast_context()->ReturnValue(value);
8654 } else { 8697 } else {
8655 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 8698 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
8656 call->id()); 8699 call->id());
8657 } 8700 }
8658 } 8701 }
8659 8702
8660 8703
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
9230 return new_env; 9273 return new_env;
9231 } 9274 }
9232 9275
9233 9276
9234 HEnvironment* HEnvironment::CopyForInlining( 9277 HEnvironment* HEnvironment::CopyForInlining(
9235 Handle<JSFunction> target, 9278 Handle<JSFunction> target,
9236 int arguments, 9279 int arguments,
9237 FunctionLiteral* function, 9280 FunctionLiteral* function,
9238 HConstant* undefined, 9281 HConstant* undefined,
9239 CallKind call_kind, 9282 CallKind call_kind,
9240 bool is_construct) const { 9283 InliningKind inlining_kind) const {
9241 ASSERT(frame_type() == JS_FUNCTION); 9284 ASSERT(frame_type() == JS_FUNCTION);
9242 9285
9243 // Outer environment is a copy of this one without the arguments. 9286 // Outer environment is a copy of this one without the arguments.
9244 int arity = function->scope()->num_parameters(); 9287 int arity = function->scope()->num_parameters();
9245 9288
9246 HEnvironment* outer = Copy(); 9289 HEnvironment* outer = Copy();
9247 outer->Drop(arguments + 1); // Including receiver. 9290 outer->Drop(arguments + 1); // Including receiver.
9248 outer->ClearHistory(); 9291 outer->ClearHistory();
9249 9292
9250 if (is_construct) { 9293 if (inlining_kind == CONSTRUCT_CALL_RETURN) {
9251 // Create artificial constructor stub environment. The receiver should 9294 // Create artificial constructor stub environment. The receiver should
9252 // actually be the constructor function, but we pass the newly allocated 9295 // actually be the constructor function, but we pass the newly allocated
9253 // object instead, DoComputeConstructStubFrame() relies on that. 9296 // object instead, DoComputeConstructStubFrame() relies on that.
9254 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments); 9297 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
9298 } else if (inlining_kind == SETTER_CALL_RETURN) {
9299 // We need an additional StackFrame::INTERNAL frame for temporarily saving
9300 // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
9301 outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
9255 } 9302 }
9256 9303
9257 if (arity != arguments) { 9304 if (arity != arguments) {
9258 // Create artificial arguments adaptation environment. 9305 // Create artificial arguments adaptation environment.
9259 outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments); 9306 outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
9260 } 9307 }
9261 9308
9262 HEnvironment* inner = 9309 HEnvironment* inner =
9263 new(zone()) HEnvironment(outer, function->scope(), target, zone()); 9310 new(zone()) HEnvironment(outer, function->scope(), target, zone());
9264 // Get the argument values from the original environment. 9311 // Get the argument values from the original environment.
9265 for (int i = 0; i <= arity; ++i) { // Include receiver. 9312 for (int i = 0; i <= arity; ++i) { // Include receiver.
9266 HValue* push = (i <= arguments) ? 9313 HValue* push = (i <= arguments) ?
9267 ExpressionStackAt(arguments - i) : undefined; 9314 ExpressionStackAt(arguments - i) : undefined;
9268 inner->SetValueAt(i, push); 9315 inner->SetValueAt(i, push);
9269 } 9316 }
9270 // If the function we are inlining is a strict mode function or a 9317 // If the function we are inlining is a strict mode function or a
9271 // builtin function, pass undefined as the receiver for function 9318 // builtin function, pass undefined as the receiver for function
9272 // calls (instead of the global receiver). 9319 // calls (instead of the global receiver).
9273 if ((target->shared()->native() || !function->is_classic_mode()) && 9320 if ((target->shared()->native() || !function->is_classic_mode()) &&
9274 call_kind == CALL_AS_FUNCTION && !is_construct) { 9321 call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN) {
9275 inner->SetValueAt(0, undefined); 9322 inner->SetValueAt(0, undefined);
9276 } 9323 }
9277 inner->SetValueAt(arity + 1, LookupContext()); 9324 inner->SetValueAt(arity + 1, LookupContext());
9278 for (int i = arity + 2; i < inner->length(); ++i) { 9325 for (int i = arity + 2; i < inner->length(); ++i) {
9279 inner->SetValueAt(i, undefined); 9326 inner->SetValueAt(i, undefined);
9280 } 9327 }
9281 9328
9282 inner->set_ast_id(BailoutId::FunctionEntry()); 9329 inner->set_ast_id(BailoutId::FunctionEntry());
9283 return inner; 9330 return inner;
9284 } 9331 }
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
9626 } 9673 }
9627 } 9674 }
9628 9675
9629 #ifdef DEBUG 9676 #ifdef DEBUG
9630 if (graph_ != NULL) graph_->Verify(false); // No full verify. 9677 if (graph_ != NULL) graph_->Verify(false); // No full verify.
9631 if (allocator_ != NULL) allocator_->Verify(); 9678 if (allocator_ != NULL) allocator_->Verify();
9632 #endif 9679 #endif
9633 } 9680 }
9634 9681
9635 } } // namespace v8::internal 9682 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698