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