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

Side by Side Diff: src/hydrogen.cc

Issue 9837002: Support arguments object access from inlined functions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: revert heap.cc Created 8 years, 9 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 void HBasicBlock::AddInstruction(HInstruction* instr) { 106 void HBasicBlock::AddInstruction(HInstruction* instr) {
107 ASSERT(!IsStartBlock() || !IsFinished()); 107 ASSERT(!IsStartBlock() || !IsFinished());
108 ASSERT(!instr->IsLinked()); 108 ASSERT(!instr->IsLinked());
109 ASSERT(!IsFinished()); 109 ASSERT(!IsFinished());
110 if (first_ == NULL) { 110 if (first_ == NULL) {
111 HBlockEntry* entry = new(zone()) HBlockEntry(); 111 HBlockEntry* entry = new(zone()) HBlockEntry();
112 entry->InitializeAsFirst(this); 112 entry->InitializeAsFirst(this);
113 first_ = last_ = entry; 113 first_ = last_ = entry;
114 } 114 }
115 instr->InsertAfter(last_); 115 instr->InsertAfter(last_);
116 last_ = instr;
117 } 116 }
118 117
119 118
120 HDeoptimize* HBasicBlock::CreateDeoptimize( 119 HDeoptimize* HBasicBlock::CreateDeoptimize(
121 HDeoptimize::UseEnvironment has_uses) { 120 HDeoptimize::UseEnvironment has_uses) {
122 ASSERT(HasEnvironment()); 121 ASSERT(HasEnvironment());
123 if (has_uses == HDeoptimize::kNoUses) return new(zone()) HDeoptimize(0); 122 if (has_uses == HDeoptimize::kNoUses) return new(zone()) HDeoptimize(0);
124 123
125 HEnvironment* environment = last_environment(); 124 HEnvironment* environment = last_environment();
126 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length()); 125 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 void HBasicBlock::Finish(HControlInstruction* end) { 157 void HBasicBlock::Finish(HControlInstruction* end) {
159 ASSERT(!IsFinished()); 158 ASSERT(!IsFinished());
160 AddInstruction(end); 159 AddInstruction(end);
161 end_ = end; 160 end_ = end;
162 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
163 it.Current()->RegisterPredecessor(this); 162 it.Current()->RegisterPredecessor(this);
164 } 163 }
165 } 164 }
166 165
167 166
168 void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) { 167 void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) {
168 bool drop_extra = state != NULL && state->drop_extra();
169 bool arguments_pushed = state != NULL && state->arguments_pushed();
170
169 if (block->IsInlineReturnTarget()) { 171 if (block->IsInlineReturnTarget()) {
170 AddInstruction(new(zone()) HLeaveInlined); 172 AddInstruction(new(zone()) HLeaveInlined(arguments_pushed));
171 last_environment_ = last_environment()->DiscardInlined(drop_extra); 173 last_environment_ = last_environment()->DiscardInlined(drop_extra);
172 } 174 }
175
173 AddSimulate(AstNode::kNoNumber); 176 AddSimulate(AstNode::kNoNumber);
174 HGoto* instr = new(zone()) HGoto(block); 177 HGoto* instr = new(zone()) HGoto(block);
175 Finish(instr); 178 Finish(instr);
176 } 179 }
177 180
178 181
179 void HBasicBlock::AddLeaveInlined(HValue* return_value, 182 void HBasicBlock::AddLeaveInlined(HValue* return_value,
180 HBasicBlock* target, 183 HBasicBlock* target,
181 bool drop_extra) { 184 FunctionState* state) {
185 bool drop_extra = state != NULL && state->drop_extra();
186 bool arguments_pushed = state != NULL && state->arguments_pushed();
187
182 ASSERT(target->IsInlineReturnTarget()); 188 ASSERT(target->IsInlineReturnTarget());
183 ASSERT(return_value != NULL); 189 ASSERT(return_value != NULL);
184 AddInstruction(new(zone()) HLeaveInlined); 190 AddInstruction(new(zone()) HLeaveInlined(arguments_pushed));
185 last_environment_ = last_environment()->DiscardInlined(drop_extra); 191 last_environment_ = last_environment()->DiscardInlined(drop_extra);
186 last_environment()->Push(return_value); 192 last_environment()->Push(return_value);
187 AddSimulate(AstNode::kNoNumber); 193 AddSimulate(AstNode::kNoNumber);
188 HGoto* instr = new(zone()) HGoto(target); 194 HGoto* instr = new(zone()) HGoto(target);
189 Finish(instr); 195 Finish(instr);
190 } 196 }
191 197
192 198
193 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 199 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
194 ASSERT(!HasEnvironment()); 200 ASSERT(!HasEnvironment());
(...skipping 1976 matching lines...) Expand 10 before | Expand all | Expand 10 after
2171 CompilationInfo* info, 2177 CompilationInfo* info,
2172 TypeFeedbackOracle* oracle, 2178 TypeFeedbackOracle* oracle,
2173 ReturnHandlingFlag return_handling) 2179 ReturnHandlingFlag return_handling)
2174 : owner_(owner), 2180 : owner_(owner),
2175 compilation_info_(info), 2181 compilation_info_(info),
2176 oracle_(oracle), 2182 oracle_(oracle),
2177 call_context_(NULL), 2183 call_context_(NULL),
2178 return_handling_(return_handling), 2184 return_handling_(return_handling),
2179 function_return_(NULL), 2185 function_return_(NULL),
2180 test_context_(NULL), 2186 test_context_(NULL),
2187 entry_(NULL),
2188 arguments_elements_(NULL),
2181 outer_(owner->function_state()) { 2189 outer_(owner->function_state()) {
2182 if (outer_ != NULL) { 2190 if (outer_ != NULL) {
2183 // State for an inline function. 2191 // State for an inline function.
2184 if (owner->ast_context()->IsTest()) { 2192 if (owner->ast_context()->IsTest()) {
2185 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2193 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2186 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2194 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2187 if_true->MarkAsInlineReturnTarget(); 2195 if_true->MarkAsInlineReturnTarget();
2188 if_false->MarkAsInlineReturnTarget(); 2196 if_false->MarkAsInlineReturnTarget();
2189 Expression* cond = TestContext::cast(owner->ast_context())->condition(); 2197 Expression* cond = TestContext::cast(owner->ast_context())->condition();
2190 // The AstContext constructor pushed on the context stack. This newed 2198 // The AstContext constructor pushed on the context stack. This newed
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2330 } 2338 }
2331 2339
2332 2340
2333 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { 2341 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2334 ASSERT(!instr->HasObservableSideEffects()); 2342 ASSERT(!instr->HasObservableSideEffects());
2335 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 2343 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2336 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 2344 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2337 instr->SetSuccessorAt(0, empty_true); 2345 instr->SetSuccessorAt(0, empty_true);
2338 instr->SetSuccessorAt(1, empty_false); 2346 instr->SetSuccessorAt(1, empty_false);
2339 owner()->current_block()->Finish(instr); 2347 owner()->current_block()->Finish(instr);
2340 empty_true->Goto(if_true(), owner()->function_state()->drop_extra()); 2348 empty_true->Goto(if_true(), owner()->function_state());
2341 empty_false->Goto(if_false(), owner()->function_state()->drop_extra()); 2349 empty_false->Goto(if_false(), owner()->function_state());
2342 owner()->set_current_block(NULL); 2350 owner()->set_current_block(NULL);
2343 } 2351 }
2344 2352
2345 2353
2346 void TestContext::BuildBranch(HValue* value) { 2354 void TestContext::BuildBranch(HValue* value) {
2347 // We expect the graph to be in edge-split form: there is no edge that 2355 // We expect the graph to be in edge-split form: there is no edge that
2348 // connects a branch node to a join node. We conservatively ensure that 2356 // connects a branch node to a join node. We conservatively ensure that
2349 // property by always adding an empty block on the outgoing edges of this 2357 // property by always adding an empty block on the outgoing edges of this
2350 // branch. 2358 // branch.
2351 HGraphBuilder* builder = owner(); 2359 HGraphBuilder* builder = owner();
2352 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2360 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2353 builder->Bailout("arguments object value in a test context"); 2361 builder->Bailout("arguments object value in a test context");
2354 } 2362 }
2355 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2363 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2356 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2364 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2357 unsigned test_id = condition()->test_id(); 2365 unsigned test_id = condition()->test_id();
2358 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id)); 2366 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
2359 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); 2367 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2360 builder->current_block()->Finish(test); 2368 builder->current_block()->Finish(test);
2361 2369
2362 empty_true->Goto(if_true(), owner()->function_state()->drop_extra()); 2370 empty_true->Goto(if_true(), owner()->function_state());
2363 empty_false->Goto(if_false(), owner()->function_state()->drop_extra()); 2371 empty_false->Goto(if_false(), owner()->function_state());
2364 builder->set_current_block(NULL); 2372 builder->set_current_block(NULL);
2365 } 2373 }
2366 2374
2367 2375
2368 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2376 // HGraphBuilder infrastructure for bailing out and checking bailouts.
2369 #define CHECK_BAILOUT(call) \ 2377 #define CHECK_BAILOUT(call) \
2370 do { \ 2378 do { \
2371 call; \ 2379 call; \
2372 if (HasStackOverflow()) return; \ 2380 if (HasStackOverflow()) return; \
2373 } while (false) 2381 } while (false)
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
2844 CHECK_ALIVE(VisitForValue(stmt->expression())); 2852 CHECK_ALIVE(VisitForValue(stmt->expression()));
2845 HValue* result = environment()->Pop(); 2853 HValue* result = environment()->Pop();
2846 current_block()->FinishExit(new(zone()) HReturn(result)); 2854 current_block()->FinishExit(new(zone()) HReturn(result));
2847 } else if (function_state()->is_construct()) { 2855 } else if (function_state()->is_construct()) {
2848 // Return from an inlined construct call. In a test context the return 2856 // Return from an inlined construct call. In a test context the return
2849 // value will always evaluate to true, in a value context the return value 2857 // value will always evaluate to true, in a value context the return value
2850 // needs to be a JSObject. 2858 // needs to be a JSObject.
2851 if (context->IsTest()) { 2859 if (context->IsTest()) {
2852 TestContext* test = TestContext::cast(context); 2860 TestContext* test = TestContext::cast(context);
2853 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2861 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2854 current_block()->Goto(test->if_true(), function_state()->drop_extra()); 2862 current_block()->Goto(test->if_true(), function_state());
2855 } else if (context->IsEffect()) { 2863 } else if (context->IsEffect()) {
2856 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2864 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2857 current_block()->Goto(function_return(), function_state()->drop_extra()); 2865 current_block()->Goto(function_return(), function_state());
2858 } else { 2866 } else {
2859 ASSERT(context->IsValue()); 2867 ASSERT(context->IsValue());
2860 CHECK_ALIVE(VisitForValue(stmt->expression())); 2868 CHECK_ALIVE(VisitForValue(stmt->expression()));
2861 HValue* return_value = Pop(); 2869 HValue* return_value = Pop();
2862 HValue* receiver = environment()->Lookup(0); 2870 HValue* receiver = environment()->Lookup(0);
2863 HHasInstanceTypeAndBranch* typecheck = 2871 HHasInstanceTypeAndBranch* typecheck =
2864 new(zone()) HHasInstanceTypeAndBranch(return_value, 2872 new(zone()) HHasInstanceTypeAndBranch(return_value,
2865 FIRST_SPEC_OBJECT_TYPE, 2873 FIRST_SPEC_OBJECT_TYPE,
2866 LAST_SPEC_OBJECT_TYPE); 2874 LAST_SPEC_OBJECT_TYPE);
2867 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); 2875 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
2868 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); 2876 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
2869 typecheck->SetSuccessorAt(0, if_spec_object); 2877 typecheck->SetSuccessorAt(0, if_spec_object);
2870 typecheck->SetSuccessorAt(1, not_spec_object); 2878 typecheck->SetSuccessorAt(1, not_spec_object);
2871 current_block()->Finish(typecheck); 2879 current_block()->Finish(typecheck);
2872 if_spec_object->AddLeaveInlined(return_value, 2880 if_spec_object->AddLeaveInlined(return_value,
2873 function_return(), 2881 function_return(),
2874 function_state()->drop_extra()); 2882 function_state());
2875 not_spec_object->AddLeaveInlined(receiver, 2883 not_spec_object->AddLeaveInlined(receiver,
2876 function_return(), 2884 function_return(),
2877 function_state()->drop_extra()); 2885 function_state());
2878 } 2886 }
2879 } else { 2887 } else {
2880 // Return from an inlined function, visit the subexpression in the 2888 // Return from an inlined function, visit the subexpression in the
2881 // expression context of the call. 2889 // expression context of the call.
2882 if (context->IsTest()) { 2890 if (context->IsTest()) {
2883 TestContext* test = TestContext::cast(context); 2891 TestContext* test = TestContext::cast(context);
2884 VisitForControl(stmt->expression(), 2892 VisitForControl(stmt->expression(),
2885 test->if_true(), 2893 test->if_true(),
2886 test->if_false()); 2894 test->if_false());
2887 } else if (context->IsEffect()) { 2895 } else if (context->IsEffect()) {
2888 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2896 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2889 current_block()->Goto(function_return(), function_state()->drop_extra()); 2897 current_block()->Goto(function_return(), function_state());
2890 } else { 2898 } else {
2891 ASSERT(context->IsValue()); 2899 ASSERT(context->IsValue());
2892 CHECK_ALIVE(VisitForValue(stmt->expression())); 2900 CHECK_ALIVE(VisitForValue(stmt->expression()));
2893 HValue* return_value = Pop(); 2901 HValue* return_value = Pop();
2894 current_block()->AddLeaveInlined(return_value, 2902 current_block()->AddLeaveInlined(return_value,
2895 function_return(), 2903 function_return(),
2896 function_state()->drop_extra()); 2904 function_state());
2897 } 2905 }
2898 } 2906 }
2899 set_current_block(NULL); 2907 set_current_block(NULL);
2900 } 2908 }
2901 2909
2902 2910
2903 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2911 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2904 ASSERT(!HasStackOverflow()); 2912 ASSERT(!HasStackOverflow());
2905 ASSERT(current_block() != NULL); 2913 ASSERT(current_block() != NULL);
2906 ASSERT(current_block()->HasPredecessor()); 2914 ASSERT(current_block()->HasPredecessor());
(...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after
4925 } 4933 }
4926 4934
4927 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 4935 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
4928 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 4936 VariableProxy* proxy = expr->obj()->AsVariableProxy();
4929 if (proxy == NULL) return false; 4937 if (proxy == NULL) return false;
4930 if (!proxy->var()->IsStackAllocated()) return false; 4938 if (!proxy->var()->IsStackAllocated()) return false;
4931 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 4939 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
4932 return false; 4940 return false;
4933 } 4941 }
4934 4942
4935 // Our implementation of arguments (based on this stack frame or an
4936 // adapter below it) does not work for inlined functions.
4937 if (function_state()->outer() != NULL) { 4943 if (function_state()->outer() != NULL) {
4938 Bailout("arguments access in inlined function"); 4944 // Push arguments when entering inlined function.
4939 return true; 4945 if (!function_state()->arguments_pushed()) {
4946 HEnvironment* arguments_env = environment()->arguments_environment();
4947
4948 HInstruction* insert_after = function_state()->entry();
4949 ASSERT(insert_after->IsEnterInlined());
4950 HEnterInlined::cast(insert_after)->set_materializes_arguments(true);
4951
4952 for (int i = 0; i < arguments_env->parameter_count(); i++) {
4953 HValue* argument = arguments_env->Lookup(i);
4954 HInstruction* push_argument = new(zone()) HPushArgument(argument);
4955 push_argument->InsertAfter(insert_after);
4956 insert_after = push_argument;
4957 }
4958
4959 HInstruction* arguments_elements = new(zone()) HArgumentsElements();
4960 arguments_elements->ClearFlag(HValue::kUseGVN);
4961 arguments_elements->InsertAfter(insert_after);
4962 function_state()->set_arguments_elements(arguments_elements);
4963 }
4940 } 4964 }
4941 4965
4942 HInstruction* result = NULL; 4966 HInstruction* result = NULL;
4943 if (expr->key()->IsPropertyName()) { 4967 if (expr->key()->IsPropertyName()) {
4944 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 4968 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
4945 if (!name->IsEqualTo(CStrVector("length"))) return false; 4969 if (!name->IsEqualTo(CStrVector("length"))) return false;
4946 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 4970
4947 result = new(zone()) HArgumentsLength(elements); 4971 if (function_state()->outer() == NULL) {
4972 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
4973 result = new(zone()) HArgumentsLength(elements);
4974 } else {
4975 // Number of arguments without receiver.
4976 int argument_count = environment()->
4977 arguments_environment()->parameter_count() - 1;
4978 result = new(zone()) HConstant(
4979 Handle<Object>(Smi::FromInt(argument_count)),
4980 Representation::Integer32());
4981 }
4948 } else { 4982 } else {
4949 Push(graph()->GetArgumentsObject()); 4983 Push(graph()->GetArgumentsObject());
4950 VisitForValue(expr->key()); 4984 VisitForValue(expr->key());
4951 if (HasStackOverflow() || current_block() == NULL) return true; 4985 if (HasStackOverflow() || current_block() == NULL) return true;
4952 HValue* key = Pop(); 4986 HValue* key = Pop();
4953 Drop(1); // Arguments object. 4987 Drop(1); // Arguments object.
4954 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 4988 if (function_state()->outer() == NULL) {
4955 HInstruction* length = AddInstruction( 4989 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
4956 new(zone()) HArgumentsLength(elements)); 4990 HInstruction* length = AddInstruction(
4957 HInstruction* checked_key = 4991 new(zone()) HArgumentsLength(elements));
4958 AddInstruction(new(zone()) HBoundsCheck(key, length)); 4992 HInstruction* checked_key =
4959 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 4993 AddInstruction(new(zone()) HBoundsCheck(key, length));
4994 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
4995 } else {
4996 // Number of arguments without receiver.
4997 HInstruction* elements = function_state()->arguments_elements();
4998 int argument_count = environment()->
4999 arguments_environment()->parameter_count() - 1;
5000 HInstruction* length = AddInstruction(new(zone()) HConstant(
5001 Handle<Object>(Smi::FromInt(argument_count)),
5002 Representation::Integer32()));
5003 HInstruction* checked_key =
5004 AddInstruction(new(zone()) HBoundsCheck(key, length));
5005 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5006 }
4960 } 5007 }
4961 ast_context()->ReturnInstruction(result, expr->id()); 5008 ast_context()->ReturnInstruction(result, expr->id());
4962 return true; 5009 return true;
4963 } 5010 }
4964 5011
4965 5012
4966 void HGraphBuilder::VisitProperty(Property* expr) { 5013 void HGraphBuilder::VisitProperty(Property* expr) {
4967 ASSERT(!HasStackOverflow()); 5014 ASSERT(!HasStackOverflow());
4968 ASSERT(current_block() != NULL); 5015 ASSERT(current_block() != NULL);
4969 ASSERT(current_block()->HasPredecessor()); 5016 ASSERT(current_block()->HasPredecessor());
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
5357 // IA32 only, overwrite the caller's context in the deoptimization 5404 // IA32 only, overwrite the caller's context in the deoptimization
5358 // environment with the correct one. 5405 // environment with the correct one.
5359 // 5406 //
5360 // TODO(kmillikin): implement the same inlining on other platforms so we 5407 // TODO(kmillikin): implement the same inlining on other platforms so we
5361 // can remove the unsightly ifdefs in this function. 5408 // can remove the unsightly ifdefs in this function.
5362 HConstant* context = new HConstant(Handle<Context>(target->context()), 5409 HConstant* context = new HConstant(Handle<Context>(target->context()),
5363 Representation::Tagged()); 5410 Representation::Tagged());
5364 AddInstruction(context); 5411 AddInstruction(context);
5365 inner_env->BindContext(context); 5412 inner_env->BindContext(context);
5366 #endif 5413 #endif
5367 AddSimulate(return_id);
5368 current_block()->UpdateEnvironment(inner_env);
5369 AddInstruction(new(zone()) HEnterInlined(target,
5370 arguments->length(),
5371 function,
5372 call_kind,
5373 function_state()->is_construct()));
5374 // If the function uses arguments object create and bind one. 5414 // If the function uses arguments object create and bind one.
5375 if (function->scope()->arguments() != NULL) { 5415 if (function->scope()->arguments() != NULL) {
5376 ASSERT(function->scope()->arguments()->IsStackAllocated()); 5416 ASSERT(function->scope()->arguments()->IsStackAllocated());
5377 environment()->Bind(function->scope()->arguments(), 5417 inner_env->Bind(function->scope()->arguments(),
5378 graph()->GetArgumentsObject()); 5418 graph()->GetArgumentsObject());
5379 } 5419 }
5420
5421 AddSimulate(return_id);
5422 current_block()->UpdateEnvironment(inner_env);
5423
5424 HInstruction* enter_inlined =
5425 AddInstruction(new(zone()) HEnterInlined(target,
5426 arguments->length(),
5427 function,
5428 call_kind,
5429 function_state()->is_construct(),
5430 function->scope()->arguments()));
5431 function_state()->set_entry(enter_inlined);
5380 VisitDeclarations(target_info.scope()->declarations()); 5432 VisitDeclarations(target_info.scope()->declarations());
5381 VisitStatements(function->body()); 5433 VisitStatements(function->body());
5382 if (HasStackOverflow()) { 5434 if (HasStackOverflow()) {
5383 // Bail out if the inline function did, as we cannot residualize a call 5435 // Bail out if the inline function did, as we cannot residualize a call
5384 // instead. 5436 // instead.
5385 TraceInline(target, caller, "inline graph construction failed"); 5437 TraceInline(target, caller, "inline graph construction failed");
5386 target_shared->DisableOptimization(); 5438 target_shared->DisableOptimization();
5387 inline_bailout_ = true; 5439 inline_bailout_ = true;
5388 delete target_state; 5440 delete target_state;
5389 return true; 5441 return true;
5390 } 5442 }
5391 5443
5392 // Update inlined nodes count. 5444 // Update inlined nodes count.
5393 inlined_count_ += nodes_added; 5445 inlined_count_ += nodes_added;
5394 5446
5395 TraceInline(target, caller, NULL); 5447 TraceInline(target, caller, NULL);
5396 5448
5397 if (current_block() != NULL) { 5449 if (current_block() != NULL) {
5398 // Add default return value (i.e. undefined for normals calls or the newly 5450 // Add default return value (i.e. undefined for normals calls or the newly
5399 // allocated receiver for construct calls) if control can fall off the 5451 // allocated receiver for construct calls) if control can fall off the
5400 // body. In a test context, undefined is false and any JSObject is true. 5452 // body. In a test context, undefined is false and any JSObject is true.
5401 if (call_context()->IsValue()) { 5453 if (call_context()->IsValue()) {
5402 ASSERT(function_return() != NULL); 5454 ASSERT(function_return() != NULL);
5403 HValue* return_value = function_state()->is_construct() 5455 HValue* return_value = function_state()->is_construct()
5404 ? receiver 5456 ? receiver
5405 : undefined; 5457 : undefined;
5406 current_block()->AddLeaveInlined(return_value, 5458 current_block()->AddLeaveInlined(return_value,
5407 function_return(), 5459 function_return(),
5408 function_state()->drop_extra()); 5460 function_state());
5409 } else if (call_context()->IsEffect()) { 5461 } else if (call_context()->IsEffect()) {
5410 ASSERT(function_return() != NULL); 5462 ASSERT(function_return() != NULL);
5411 current_block()->Goto(function_return(), function_state()->drop_extra()); 5463 current_block()->Goto(function_return(), function_state());
5412 } else { 5464 } else {
5413 ASSERT(call_context()->IsTest()); 5465 ASSERT(call_context()->IsTest());
5414 ASSERT(inlined_test_context() != NULL); 5466 ASSERT(inlined_test_context() != NULL);
5415 HBasicBlock* target = function_state()->is_construct() 5467 HBasicBlock* target = function_state()->is_construct()
5416 ? inlined_test_context()->if_true() 5468 ? inlined_test_context()->if_true()
5417 : inlined_test_context()->if_false(); 5469 : inlined_test_context()->if_false();
5418 current_block()->Goto(target, function_state()->drop_extra()); 5470 current_block()->Goto(target, function_state());
5419 } 5471 }
5420 } 5472 }
5421 5473
5422 // Fix up the function exits. 5474 // Fix up the function exits.
5423 if (inlined_test_context() != NULL) { 5475 if (inlined_test_context() != NULL) {
5424 HBasicBlock* if_true = inlined_test_context()->if_true(); 5476 HBasicBlock* if_true = inlined_test_context()->if_true();
5425 HBasicBlock* if_false = inlined_test_context()->if_false(); 5477 HBasicBlock* if_false = inlined_test_context()->if_false();
5426 5478
5427 // Pop the return test context from the expression context stack. 5479 // Pop the return test context from the expression context stack.
5428 ASSERT(ast_context() == inlined_test_context()); 5480 ASSERT(ast_context() == inlined_test_context());
5429 ClearInlinedTestContext(); 5481 ClearInlinedTestContext();
5430 delete target_state; 5482 delete target_state;
5431 5483
5432 // Forward to the real test context. 5484 // Forward to the real test context.
5433 if (if_true->HasPredecessor()) { 5485 if (if_true->HasPredecessor()) {
5434 if_true->SetJoinId(ast_id); 5486 if_true->SetJoinId(ast_id);
5435 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 5487 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
5436 if_true->Goto(true_target, function_state()->drop_extra()); 5488 if_true->Goto(true_target, function_state());
5437 } 5489 }
5438 if (if_false->HasPredecessor()) { 5490 if (if_false->HasPredecessor()) {
5439 if_false->SetJoinId(ast_id); 5491 if_false->SetJoinId(ast_id);
5440 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 5492 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
5441 if_false->Goto(false_target, function_state()->drop_extra()); 5493 if_false->Goto(false_target, function_state());
5442 } 5494 }
5443 set_current_block(NULL); 5495 set_current_block(NULL);
5444 return true; 5496 return true;
5445 5497
5446 } else if (function_return()->HasPredecessor()) { 5498 } else if (function_return()->HasPredecessor()) {
5447 function_return()->SetJoinId(ast_id); 5499 function_return()->SetJoinId(ast_id);
5448 set_current_block(function_return()); 5500 set_current_block(function_return());
5449 } else { 5501 } else {
5450 set_current_block(NULL); 5502 set_current_block(NULL);
5451 } 5503 }
(...skipping 2704 matching lines...) Expand 10 before | Expand all | Expand 10 after
8156 } 8208 }
8157 } 8209 }
8158 8210
8159 #ifdef DEBUG 8211 #ifdef DEBUG
8160 if (graph_ != NULL) graph_->Verify(false); // No full verify. 8212 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8161 if (allocator_ != NULL) allocator_->Verify(); 8213 if (allocator_ != NULL) allocator_->Verify();
8162 #endif 8214 #endif
8163 } 8215 }
8164 8216
8165 } } // namespace v8::internal 8217 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/ia32/lithium-codegen-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698