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

Side by Side Diff: src/hydrogen.cc

Issue 10033028: Reland arguments access support for inlined functions (r11109,r11118). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix Kevin's comments Created 8 years, 8 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 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
2848 CHECK_ALIVE(VisitForValue(stmt->expression())); 2856 CHECK_ALIVE(VisitForValue(stmt->expression()));
2849 HValue* result = environment()->Pop(); 2857 HValue* result = environment()->Pop();
2850 current_block()->FinishExit(new(zone()) HReturn(result)); 2858 current_block()->FinishExit(new(zone()) HReturn(result));
2851 } else if (function_state()->is_construct()) { 2859 } else if (function_state()->is_construct()) {
2852 // Return from an inlined construct call. In a test context the return 2860 // Return from an inlined construct call. In a test context the return
2853 // value will always evaluate to true, in a value context the return value 2861 // value will always evaluate to true, in a value context the return value
2854 // needs to be a JSObject. 2862 // needs to be a JSObject.
2855 if (context->IsTest()) { 2863 if (context->IsTest()) {
2856 TestContext* test = TestContext::cast(context); 2864 TestContext* test = TestContext::cast(context);
2857 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2865 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2858 current_block()->Goto(test->if_true(), function_state()->drop_extra()); 2866 current_block()->Goto(test->if_true(), function_state());
2859 } else if (context->IsEffect()) { 2867 } else if (context->IsEffect()) {
2860 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2868 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2861 current_block()->Goto(function_return(), function_state()->drop_extra()); 2869 current_block()->Goto(function_return(), function_state());
2862 } else { 2870 } else {
2863 ASSERT(context->IsValue()); 2871 ASSERT(context->IsValue());
2864 CHECK_ALIVE(VisitForValue(stmt->expression())); 2872 CHECK_ALIVE(VisitForValue(stmt->expression()));
2865 HValue* return_value = Pop(); 2873 HValue* return_value = Pop();
2866 HValue* receiver = environment()->Lookup(0); 2874 HValue* receiver = environment()->Lookup(0);
2867 HHasInstanceTypeAndBranch* typecheck = 2875 HHasInstanceTypeAndBranch* typecheck =
2868 new(zone()) HHasInstanceTypeAndBranch(return_value, 2876 new(zone()) HHasInstanceTypeAndBranch(return_value,
2869 FIRST_SPEC_OBJECT_TYPE, 2877 FIRST_SPEC_OBJECT_TYPE,
2870 LAST_SPEC_OBJECT_TYPE); 2878 LAST_SPEC_OBJECT_TYPE);
2871 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); 2879 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
2872 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); 2880 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
2873 typecheck->SetSuccessorAt(0, if_spec_object); 2881 typecheck->SetSuccessorAt(0, if_spec_object);
2874 typecheck->SetSuccessorAt(1, not_spec_object); 2882 typecheck->SetSuccessorAt(1, not_spec_object);
2875 current_block()->Finish(typecheck); 2883 current_block()->Finish(typecheck);
2876 if_spec_object->AddLeaveInlined(return_value, 2884 if_spec_object->AddLeaveInlined(return_value,
2877 function_return(), 2885 function_return(),
2878 function_state()->drop_extra()); 2886 function_state());
2879 not_spec_object->AddLeaveInlined(receiver, 2887 not_spec_object->AddLeaveInlined(receiver,
2880 function_return(), 2888 function_return(),
2881 function_state()->drop_extra()); 2889 function_state());
2882 } 2890 }
2883 } else { 2891 } else {
2884 // Return from an inlined function, visit the subexpression in the 2892 // Return from an inlined function, visit the subexpression in the
2885 // expression context of the call. 2893 // expression context of the call.
2886 if (context->IsTest()) { 2894 if (context->IsTest()) {
2887 TestContext* test = TestContext::cast(context); 2895 TestContext* test = TestContext::cast(context);
2888 VisitForControl(stmt->expression(), 2896 VisitForControl(stmt->expression(),
2889 test->if_true(), 2897 test->if_true(),
2890 test->if_false()); 2898 test->if_false());
2891 } else if (context->IsEffect()) { 2899 } else if (context->IsEffect()) {
2892 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2900 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2893 current_block()->Goto(function_return(), function_state()->drop_extra()); 2901 current_block()->Goto(function_return(), function_state());
2894 } else { 2902 } else {
2895 ASSERT(context->IsValue()); 2903 ASSERT(context->IsValue());
2896 CHECK_ALIVE(VisitForValue(stmt->expression())); 2904 CHECK_ALIVE(VisitForValue(stmt->expression()));
2897 HValue* return_value = Pop(); 2905 HValue* return_value = Pop();
2898 current_block()->AddLeaveInlined(return_value, 2906 current_block()->AddLeaveInlined(return_value,
2899 function_return(), 2907 function_return(),
2900 function_state()->drop_extra()); 2908 function_state());
2901 } 2909 }
2902 } 2910 }
2903 set_current_block(NULL); 2911 set_current_block(NULL);
2904 } 2912 }
2905 2913
2906 2914
2907 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2915 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2908 ASSERT(!HasStackOverflow()); 2916 ASSERT(!HasStackOverflow());
2909 ASSERT(current_block() != NULL); 2917 ASSERT(current_block() != NULL);
2910 ASSERT(current_block()->HasPredecessor()); 2918 ASSERT(current_block()->HasPredecessor());
(...skipping 2066 matching lines...) Expand 10 before | Expand all | Expand 10 after
4977 HValue* value) { 4985 HValue* value) {
4978 HValue* context = environment()->LookupContext(); 4986 HValue* context = environment()->LookupContext();
4979 return new(zone()) HStoreKeyedGeneric( 4987 return new(zone()) HStoreKeyedGeneric(
4980 context, 4988 context,
4981 object, 4989 object,
4982 key, 4990 key,
4983 value, 4991 value,
4984 function_strict_mode_flag()); 4992 function_strict_mode_flag());
4985 } 4993 }
4986 4994
4995
4996 void HGraphBuilder::EnsureArgumentsArePushedForAccess() {
4997 // Outermost function already has arguments on the stack.
4998 if (function_state()->outer() == NULL) return;
4999
5000 if (function_state()->arguments_pushed()) return;
5001
5002 // Push arguments when entering inlined function.
5003 HEnterInlined* entry = function_state()->entry();
5004
5005 ZoneList<HValue*>* arguments_values = entry->arguments_values();
5006
5007 HInstruction* insert_after = entry;
5008 for (int i = 0; i < arguments_values->length(); i++) {
5009 HValue* argument = arguments_values->at(i);
5010 HInstruction* push_argument = new(zone()) HPushArgument(argument);
5011 push_argument->InsertAfter(insert_after);
5012 insert_after = push_argument;
5013 }
5014
5015 HArgumentsElements* arguments_elements =
5016 new(zone()) HArgumentsElements(true);
5017 arguments_elements->ClearFlag(HValue::kUseGVN);
5018 arguments_elements->InsertAfter(insert_after);
5019 function_state()->set_arguments_elements(arguments_elements);
5020 }
5021
5022
4987 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 5023 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
4988 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 5024 VariableProxy* proxy = expr->obj()->AsVariableProxy();
4989 if (proxy == NULL) return false; 5025 if (proxy == NULL) return false;
4990 if (!proxy->var()->IsStackAllocated()) return false; 5026 if (!proxy->var()->IsStackAllocated()) return false;
4991 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 5027 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
4992 return false; 5028 return false;
4993 } 5029 }
4994 5030
4995 // Our implementation of arguments (based on this stack frame or an
4996 // adapter below it) does not work for inlined functions.
4997 if (function_state()->outer() != NULL) {
4998 Bailout("arguments access in inlined function");
4999 return true;
5000 }
5001
5002 HInstruction* result = NULL; 5031 HInstruction* result = NULL;
5003 if (expr->key()->IsPropertyName()) { 5032 if (expr->key()->IsPropertyName()) {
5004 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5033 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5005 if (!name->IsEqualTo(CStrVector("length"))) return false; 5034 if (!name->IsEqualTo(CStrVector("length"))) return false;
5006 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 5035
5007 result = new(zone()) HArgumentsLength(elements); 5036 if (function_state()->outer() == NULL) {
5037 HInstruction* elements = AddInstruction(
5038 new(zone()) HArgumentsElements(false));
5039 result = new(zone()) HArgumentsLength(elements);
5040 } else {
5041 // Number of arguments without receiver.
5042 int argument_count = environment()->
5043 arguments_environment()->parameter_count() - 1;
5044 result = new(zone()) HConstant(
5045 Handle<Object>(Smi::FromInt(argument_count)),
5046 Representation::Integer32());
5047 }
5008 } else { 5048 } else {
5009 Push(graph()->GetArgumentsObject()); 5049 Push(graph()->GetArgumentsObject());
5010 VisitForValue(expr->key()); 5050 VisitForValue(expr->key());
5011 if (HasStackOverflow() || current_block() == NULL) return true; 5051 if (HasStackOverflow() || current_block() == NULL) return true;
5012 HValue* key = Pop(); 5052 HValue* key = Pop();
5013 Drop(1); // Arguments object. 5053 Drop(1); // Arguments object.
5014 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 5054 if (function_state()->outer() == NULL) {
5015 HInstruction* length = AddInstruction( 5055 HInstruction* elements = AddInstruction(
5016 new(zone()) HArgumentsLength(elements)); 5056 new(zone()) HArgumentsElements(false));
5017 HInstruction* checked_key = 5057 HInstruction* length = AddInstruction(
5018 AddInstruction(new(zone()) HBoundsCheck(key, length)); 5058 new(zone()) HArgumentsLength(elements));
5019 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 5059 HInstruction* checked_key =
5060 AddInstruction(new(zone()) HBoundsCheck(key, length));
5061 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5062 } else {
5063 EnsureArgumentsArePushedForAccess();
5064
5065 // Number of arguments without receiver.
5066 HInstruction* elements = function_state()->arguments_elements();
5067 int argument_count = environment()->
5068 arguments_environment()->parameter_count() - 1;
5069 HInstruction* length = AddInstruction(new(zone()) HConstant(
5070 Handle<Object>(Smi::FromInt(argument_count)),
5071 Representation::Integer32()));
5072 HInstruction* checked_key =
5073 AddInstruction(new(zone()) HBoundsCheck(key, length));
5074 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5075 }
5020 } 5076 }
5021 ast_context()->ReturnInstruction(result, expr->id()); 5077 ast_context()->ReturnInstruction(result, expr->id());
5022 return true; 5078 return true;
5023 } 5079 }
5024 5080
5025 5081
5026 void HGraphBuilder::VisitProperty(Property* expr) { 5082 void HGraphBuilder::VisitProperty(Property* expr) {
5027 ASSERT(!HasStackOverflow()); 5083 ASSERT(!HasStackOverflow());
5028 ASSERT(current_block() != NULL); 5084 ASSERT(current_block() != NULL);
5029 ASSERT(current_block()->HasPredecessor()); 5085 ASSERT(current_block()->HasPredecessor());
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
5416 // IA32 only, overwrite the caller's context in the deoptimization 5472 // IA32 only, overwrite the caller's context in the deoptimization
5417 // environment with the correct one. 5473 // environment with the correct one.
5418 // 5474 //
5419 // TODO(kmillikin): implement the same inlining on other platforms so we 5475 // TODO(kmillikin): implement the same inlining on other platforms so we
5420 // can remove the unsightly ifdefs in this function. 5476 // can remove the unsightly ifdefs in this function.
5421 HConstant* context = new HConstant(Handle<Context>(target->context()), 5477 HConstant* context = new HConstant(Handle<Context>(target->context()),
5422 Representation::Tagged()); 5478 Representation::Tagged());
5423 AddInstruction(context); 5479 AddInstruction(context);
5424 inner_env->BindContext(context); 5480 inner_env->BindContext(context);
5425 #endif 5481 #endif
5482
5426 AddSimulate(return_id); 5483 AddSimulate(return_id);
5427 current_block()->UpdateEnvironment(inner_env); 5484 current_block()->UpdateEnvironment(inner_env);
5428 AddInstruction(new(zone()) HEnterInlined(target, 5485
5429 arguments->length(), 5486 ZoneList<HValue*>* arguments_values = NULL;
5430 function, 5487
5431 call_kind, 5488 // If the function uses arguments copy current arguments values
5432 function_state()->is_construct(), 5489 // to use them for materialization.
5433 function->scope()->arguments())); 5490 if (function->scope()->arguments() != NULL) {
5491 HEnvironment* arguments_env = inner_env->arguments_environment();
5492 int arguments_count = arguments_env->parameter_count();
5493 arguments_values = new(zone()) ZoneList<HValue*>(arguments_count);
5494 for (int i = 0; i < arguments_count; i++) {
5495 arguments_values->Add(arguments_env->Lookup(i));
5496 }
5497 }
5498
5499 HEnterInlined* enter_inlined =
5500 new(zone()) HEnterInlined(target,
5501 arguments->length(),
5502 function,
5503 call_kind,
5504 function_state()->is_construct(),
5505 function->scope()->arguments(),
5506 arguments_values);
5507 function_state()->set_entry(enter_inlined);
5508 AddInstruction(enter_inlined);
5509
5434 // If the function uses arguments object create and bind one. 5510 // If the function uses arguments object create and bind one.
5435 if (function->scope()->arguments() != NULL) { 5511 if (function->scope()->arguments() != NULL) {
5436 ASSERT(function->scope()->arguments()->IsStackAllocated()); 5512 ASSERT(function->scope()->arguments()->IsStackAllocated());
5437 environment()->Bind(function->scope()->arguments(), 5513 inner_env->Bind(function->scope()->arguments(),
5438 graph()->GetArgumentsObject()); 5514 graph()->GetArgumentsObject());
5439 } 5515 }
5516
5517
5440 VisitDeclarations(target_info.scope()->declarations()); 5518 VisitDeclarations(target_info.scope()->declarations());
5441 VisitStatements(function->body()); 5519 VisitStatements(function->body());
5442 if (HasStackOverflow()) { 5520 if (HasStackOverflow()) {
5443 // Bail out if the inline function did, as we cannot residualize a call 5521 // Bail out if the inline function did, as we cannot residualize a call
5444 // instead. 5522 // instead.
5445 TraceInline(target, caller, "inline graph construction failed"); 5523 TraceInline(target, caller, "inline graph construction failed");
5446 target_shared->DisableOptimization(); 5524 target_shared->DisableOptimization();
5447 inline_bailout_ = true; 5525 inline_bailout_ = true;
5448 delete target_state; 5526 delete target_state;
5449 return true; 5527 return true;
5450 } 5528 }
5451 5529
5452 // Update inlined nodes count. 5530 // Update inlined nodes count.
5453 inlined_count_ += nodes_added; 5531 inlined_count_ += nodes_added;
5454 5532
5455 TraceInline(target, caller, NULL); 5533 TraceInline(target, caller, NULL);
5456 5534
5457 if (current_block() != NULL) { 5535 if (current_block() != NULL) {
5458 // Add default return value (i.e. undefined for normals calls or the newly 5536 // Add default return value (i.e. undefined for normals calls or the newly
5459 // allocated receiver for construct calls) if control can fall off the 5537 // allocated receiver for construct calls) if control can fall off the
5460 // body. In a test context, undefined is false and any JSObject is true. 5538 // body. In a test context, undefined is false and any JSObject is true.
5461 if (call_context()->IsValue()) { 5539 if (call_context()->IsValue()) {
5462 ASSERT(function_return() != NULL); 5540 ASSERT(function_return() != NULL);
5463 HValue* return_value = function_state()->is_construct() 5541 HValue* return_value = function_state()->is_construct()
5464 ? receiver 5542 ? receiver
5465 : undefined; 5543 : undefined;
5466 current_block()->AddLeaveInlined(return_value, 5544 current_block()->AddLeaveInlined(return_value,
5467 function_return(), 5545 function_return(),
5468 function_state()->drop_extra()); 5546 function_state());
5469 } else if (call_context()->IsEffect()) { 5547 } else if (call_context()->IsEffect()) {
5470 ASSERT(function_return() != NULL); 5548 ASSERT(function_return() != NULL);
5471 current_block()->Goto(function_return(), function_state()->drop_extra()); 5549 current_block()->Goto(function_return(), function_state());
5472 } else { 5550 } else {
5473 ASSERT(call_context()->IsTest()); 5551 ASSERT(call_context()->IsTest());
5474 ASSERT(inlined_test_context() != NULL); 5552 ASSERT(inlined_test_context() != NULL);
5475 HBasicBlock* target = function_state()->is_construct() 5553 HBasicBlock* target = function_state()->is_construct()
5476 ? inlined_test_context()->if_true() 5554 ? inlined_test_context()->if_true()
5477 : inlined_test_context()->if_false(); 5555 : inlined_test_context()->if_false();
5478 current_block()->Goto(target, function_state()->drop_extra()); 5556 current_block()->Goto(target, function_state());
5479 } 5557 }
5480 } 5558 }
5481 5559
5482 // Fix up the function exits. 5560 // Fix up the function exits.
5483 if (inlined_test_context() != NULL) { 5561 if (inlined_test_context() != NULL) {
5484 HBasicBlock* if_true = inlined_test_context()->if_true(); 5562 HBasicBlock* if_true = inlined_test_context()->if_true();
5485 HBasicBlock* if_false = inlined_test_context()->if_false(); 5563 HBasicBlock* if_false = inlined_test_context()->if_false();
5486 5564
5487 // Pop the return test context from the expression context stack. 5565 // Pop the return test context from the expression context stack.
5488 ASSERT(ast_context() == inlined_test_context()); 5566 ASSERT(ast_context() == inlined_test_context());
5489 ClearInlinedTestContext(); 5567 ClearInlinedTestContext();
5490 delete target_state; 5568 delete target_state;
5491 5569
5492 // Forward to the real test context. 5570 // Forward to the real test context.
5493 if (if_true->HasPredecessor()) { 5571 if (if_true->HasPredecessor()) {
5494 if_true->SetJoinId(ast_id); 5572 if_true->SetJoinId(ast_id);
5495 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 5573 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
5496 if_true->Goto(true_target, function_state()->drop_extra()); 5574 if_true->Goto(true_target, function_state());
5497 } 5575 }
5498 if (if_false->HasPredecessor()) { 5576 if (if_false->HasPredecessor()) {
5499 if_false->SetJoinId(ast_id); 5577 if_false->SetJoinId(ast_id);
5500 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 5578 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
5501 if_false->Goto(false_target, function_state()->drop_extra()); 5579 if_false->Goto(false_target, function_state());
5502 } 5580 }
5503 set_current_block(NULL); 5581 set_current_block(NULL);
5504 return true; 5582 return true;
5505 5583
5506 } else if (function_return()->HasPredecessor()) { 5584 } else if (function_return()->HasPredecessor()) {
5507 function_return()->SetJoinId(ast_id); 5585 function_return()->SetJoinId(ast_id);
5508 set_current_block(function_return()); 5586 set_current_block(function_return());
5509 } else { 5587 } else {
5510 set_current_block(NULL); 5588 set_current_block(NULL);
5511 } 5589 }
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
5800 if (HasStackOverflow() || current_block() == NULL) return true; 5878 if (HasStackOverflow() || current_block() == NULL) return true;
5801 HValue* function = Top(); 5879 HValue* function = Top();
5802 AddCheckConstantFunction(expr, function, function_map, true); 5880 AddCheckConstantFunction(expr, function, function_map, true);
5803 Drop(1); 5881 Drop(1);
5804 5882
5805 VisitForValue(args->at(0)); 5883 VisitForValue(args->at(0));
5806 if (HasStackOverflow() || current_block() == NULL) return true; 5884 if (HasStackOverflow() || current_block() == NULL) return true;
5807 HValue* receiver = Pop(); 5885 HValue* receiver = Pop();
5808 5886
5809 if (function_state()->outer() == NULL) { 5887 if (function_state()->outer() == NULL) {
5810 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 5888 HInstruction* elements = AddInstruction(
5889 new(zone()) HArgumentsElements(false));
5811 HInstruction* length = 5890 HInstruction* length =
5812 AddInstruction(new(zone()) HArgumentsLength(elements)); 5891 AddInstruction(new(zone()) HArgumentsLength(elements));
5813 HValue* wrapped_receiver = 5892 HValue* wrapped_receiver =
5814 AddInstruction(new(zone()) HWrapReceiver(receiver, function)); 5893 AddInstruction(new(zone()) HWrapReceiver(receiver, function));
5815 HInstruction* result = 5894 HInstruction* result =
5816 new(zone()) HApplyArguments(function, 5895 new(zone()) HApplyArguments(function,
5817 wrapped_receiver, 5896 wrapped_receiver,
5818 length, 5897 length,
5819 elements); 5898 elements);
5820 result->set_position(expr->position()); 5899 result->set_position(expr->position());
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after
7270 } 7349 }
7271 7350
7272 7351
7273 // Support for arguments.length and arguments[?]. 7352 // Support for arguments.length and arguments[?].
7274 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 7353 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
7275 // Our implementation of arguments (based on this stack frame or an 7354 // Our implementation of arguments (based on this stack frame or an
7276 // adapter below it) does not work for inlined functions. This runtime 7355 // adapter below it) does not work for inlined functions. This runtime
7277 // function is blacklisted by AstNode::IsInlineable. 7356 // function is blacklisted by AstNode::IsInlineable.
7278 ASSERT(function_state()->outer() == NULL); 7357 ASSERT(function_state()->outer() == NULL);
7279 ASSERT(call->arguments()->length() == 0); 7358 ASSERT(call->arguments()->length() == 0);
7280 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 7359 HInstruction* elements = AddInstruction(
7360 new(zone()) HArgumentsElements(false));
7281 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 7361 HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
7282 return ast_context()->ReturnInstruction(result, call->id()); 7362 return ast_context()->ReturnInstruction(result, call->id());
7283 } 7363 }
7284 7364
7285 7365
7286 void HGraphBuilder::GenerateArguments(CallRuntime* call) { 7366 void HGraphBuilder::GenerateArguments(CallRuntime* call) {
7287 // Our implementation of arguments (based on this stack frame or an 7367 // Our implementation of arguments (based on this stack frame or an
7288 // adapter below it) does not work for inlined functions. This runtime 7368 // adapter below it) does not work for inlined functions. This runtime
7289 // function is blacklisted by AstNode::IsInlineable. 7369 // function is blacklisted by AstNode::IsInlineable.
7290 ASSERT(function_state()->outer() == NULL); 7370 ASSERT(function_state()->outer() == NULL);
7291 ASSERT(call->arguments()->length() == 1); 7371 ASSERT(call->arguments()->length() == 1);
7292 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7372 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7293 HValue* index = Pop(); 7373 HValue* index = Pop();
7294 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 7374 HInstruction* elements = AddInstruction(
7375 new(zone()) HArgumentsElements(false));
7295 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 7376 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
7296 HAccessArgumentsAt* result = 7377 HAccessArgumentsAt* result =
7297 new(zone()) HAccessArgumentsAt(elements, length, index); 7378 new(zone()) HAccessArgumentsAt(elements, length, index);
7298 return ast_context()->ReturnInstruction(result, call->id()); 7379 return ast_context()->ReturnInstruction(result, call->id());
7299 } 7380 }
7300 7381
7301 7382
7302 // Support for accessing the class and value fields of an object. 7383 // Support for accessing the class and value fields of an object.
7303 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { 7384 void HGraphBuilder::GenerateClassOf(CallRuntime* call) {
7304 // The special form detected by IsClassOfTest is detected before we get here 7385 // The special form detected by IsClassOfTest is detected before we get here
(...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after
8239 } 8320 }
8240 } 8321 }
8241 8322
8242 #ifdef DEBUG 8323 #ifdef DEBUG
8243 if (graph_ != NULL) graph_->Verify(false); // No full verify. 8324 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8244 if (allocator_ != NULL) allocator_->Verify(); 8325 if (allocator_ != NULL) allocator_->Verify();
8245 #endif 8326 #endif
8246 } 8327 }
8247 8328
8248 } } // namespace v8::internal 8329 } } // namespace v8::internal
OLDNEW
« src/arm/lithium-arm.h ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698