OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 4056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4067 | 4067 |
4068 | 4068 |
4069 void EffectContext::ReturnValue(HValue* value) { | 4069 void EffectContext::ReturnValue(HValue* value) { |
4070 // The value is simply ignored. | 4070 // The value is simply ignored. |
4071 } | 4071 } |
4072 | 4072 |
4073 | 4073 |
4074 void ValueContext::ReturnValue(HValue* value) { | 4074 void ValueContext::ReturnValue(HValue* value) { |
4075 // The value is tracked in the bailout environment, and communicated | 4075 // The value is tracked in the bailout environment, and communicated |
4076 // through the environment as the result of the expression. | 4076 // through the environment as the result of the expression. |
4077 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { | 4077 if (value->CheckFlag(HValue::kIsArguments)) { |
4078 owner()->Bailout(kBadValueContextForArgumentsValue); | 4078 if (flag_ == ARGUMENTS_FAKED) { |
| 4079 value = owner()->graph()->GetConstantUndefined(); |
| 4080 } else if (!arguments_allowed()) { |
| 4081 owner()->Bailout(kBadValueContextForArgumentsValue); |
| 4082 } |
4079 } | 4083 } |
4080 owner()->Push(value); | 4084 owner()->Push(value); |
4081 } | 4085 } |
4082 | 4086 |
4083 | 4087 |
4084 void TestContext::ReturnValue(HValue* value) { | 4088 void TestContext::ReturnValue(HValue* value) { |
4085 BuildBranch(value); | 4089 BuildBranch(value); |
4086 } | 4090 } |
4087 | 4091 |
4088 | 4092 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4294 | 4298 |
4295 | 4299 |
4296 void HOptimizedGraphBuilder::VisitExpressions( | 4300 void HOptimizedGraphBuilder::VisitExpressions( |
4297 ZoneList<Expression*>* exprs) { | 4301 ZoneList<Expression*>* exprs) { |
4298 for (int i = 0; i < exprs->length(); ++i) { | 4302 for (int i = 0; i < exprs->length(); ++i) { |
4299 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 4303 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
4300 } | 4304 } |
4301 } | 4305 } |
4302 | 4306 |
4303 | 4307 |
| 4308 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs, |
| 4309 ArgumentsAllowedFlag flag) { |
| 4310 for (int i = 0; i < exprs->length(); ++i) { |
| 4311 CHECK_ALIVE(VisitForValue(exprs->at(i), flag)); |
| 4312 } |
| 4313 } |
| 4314 |
| 4315 |
4304 bool HOptimizedGraphBuilder::BuildGraph() { | 4316 bool HOptimizedGraphBuilder::BuildGraph() { |
4305 if (current_info()->function()->is_generator()) { | 4317 if (current_info()->function()->is_generator()) { |
4306 Bailout(kFunctionIsAGenerator); | 4318 Bailout(kFunctionIsAGenerator); |
4307 return false; | 4319 return false; |
4308 } | 4320 } |
4309 Scope* scope = current_info()->scope(); | 4321 Scope* scope = current_info()->scope(); |
4310 if (scope->HasIllegalRedeclaration()) { | 4322 if (scope->HasIllegalRedeclaration()) { |
4311 Bailout(kFunctionWithIllegalRedeclaration); | 4323 Bailout(kFunctionWithIllegalRedeclaration); |
4312 return false; | 4324 return false; |
4313 } | 4325 } |
(...skipping 4564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8878 case kFunctionCall: { | 8890 case kFunctionCall: { |
8879 if (expr->arguments()->length() == 0) return false; | 8891 if (expr->arguments()->length() == 0) return false; |
8880 BuildFunctionCall(expr); | 8892 BuildFunctionCall(expr); |
8881 return true; | 8893 return true; |
8882 } | 8894 } |
8883 case kFunctionApply: { | 8895 case kFunctionApply: { |
8884 // For .apply, only the pattern f.apply(receiver, arguments) | 8896 // For .apply, only the pattern f.apply(receiver, arguments) |
8885 // is supported. | 8897 // is supported. |
8886 if (current_info()->scope()->arguments() == NULL) return false; | 8898 if (current_info()->scope()->arguments() == NULL) return false; |
8887 | 8899 |
8888 ZoneList<Expression*>* args = expr->arguments(); | 8900 if (!CanBeFunctionApplyArguments(expr)) return false; |
8889 if (args->length() != 2) return false; | |
8890 | 8901 |
8891 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | |
8892 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | |
8893 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | |
8894 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | |
8895 BuildFunctionApply(expr); | 8902 BuildFunctionApply(expr); |
8896 return true; | 8903 return true; |
8897 } | 8904 } |
8898 default: { return false; } | 8905 default: { return false; } |
8899 } | 8906 } |
8900 UNREACHABLE(); | 8907 UNREACHABLE(); |
8901 } | 8908 } |
8902 | 8909 |
8903 | 8910 |
8904 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) { | 8911 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) { |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9171 } | 9178 } |
9172 | 9179 |
9173 BuildArrayCall(expr, | 9180 BuildArrayCall(expr, |
9174 expr->arguments()->length(), | 9181 expr->arguments()->length(), |
9175 function, | 9182 function, |
9176 expr->allocation_site()); | 9183 expr->allocation_site()); |
9177 return true; | 9184 return true; |
9178 } | 9185 } |
9179 | 9186 |
9180 | 9187 |
| 9188 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) { |
| 9189 ZoneList<Expression*>* args = expr->arguments(); |
| 9190 if (args->length() != 2) return false; |
| 9191 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 9192 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 9193 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 9194 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 9195 return true; |
| 9196 } |
| 9197 |
| 9198 |
9181 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 9199 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
9182 DCHECK(!HasStackOverflow()); | 9200 DCHECK(!HasStackOverflow()); |
9183 DCHECK(current_block() != NULL); | 9201 DCHECK(current_block() != NULL); |
9184 DCHECK(current_block()->HasPredecessor()); | 9202 DCHECK(current_block()->HasPredecessor()); |
9185 Expression* callee = expr->expression(); | 9203 Expression* callee = expr->expression(); |
9186 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 9204 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
9187 HInstruction* call = NULL; | 9205 HInstruction* call = NULL; |
9188 | 9206 |
9189 Property* prop = callee->AsProperty(); | 9207 Property* prop = callee->AsProperty(); |
9190 if (prop != NULL) { | 9208 if (prop != NULL) { |
(...skipping 16 matching lines...) Expand all Loading... |
9207 if (!prop->key()->IsPropertyName()) { | 9225 if (!prop->key()->IsPropertyName()) { |
9208 CHECK_ALIVE(VisitForValue(prop->key())); | 9226 CHECK_ALIVE(VisitForValue(prop->key())); |
9209 key = Pop(); | 9227 key = Pop(); |
9210 } | 9228 } |
9211 | 9229 |
9212 CHECK_ALIVE(PushLoad(prop, receiver, key)); | 9230 CHECK_ALIVE(PushLoad(prop, receiver, key)); |
9213 HValue* function = Pop(); | 9231 HValue* function = Pop(); |
9214 | 9232 |
9215 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 9233 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
9216 | 9234 |
9217 // Push the function under the receiver. | |
9218 environment()->SetExpressionStackAt(0, function); | |
9219 | 9235 |
9220 Push(receiver); | |
9221 | 9236 |
9222 if (function->IsConstant() && | 9237 if (function->IsConstant() && |
9223 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 9238 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 9239 // Push the function under the receiver. |
| 9240 environment()->SetExpressionStackAt(0, function); |
| 9241 Push(receiver); |
| 9242 |
9224 Handle<JSFunction> known_function = Handle<JSFunction>::cast( | 9243 Handle<JSFunction> known_function = Handle<JSFunction>::cast( |
9225 HConstant::cast(function)->handle(isolate())); | 9244 HConstant::cast(function)->handle(isolate())); |
9226 expr->set_target(known_function); | 9245 expr->set_target(known_function); |
9227 | 9246 |
9228 if (TryIndirectCall(expr)) return; | 9247 if (TryIndirectCall(expr)) return; |
9229 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9248 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
9230 | 9249 |
9231 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); | 9250 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); |
9232 if (TryInlineBuiltinMethodCall(expr, known_function, map, | 9251 if (TryInlineBuiltinMethodCall(expr, known_function, map, |
9233 expr->arguments()->length())) { | 9252 expr->arguments()->length())) { |
(...skipping 15 matching lines...) Expand all Loading... |
9249 // HWrapReceiver. | 9268 // HWrapReceiver. |
9250 call = New<HCallFunction>( | 9269 call = New<HCallFunction>( |
9251 function, argument_count, WRAP_AND_CALL); | 9270 function, argument_count, WRAP_AND_CALL); |
9252 } else if (TryInlineCall(expr)) { | 9271 } else if (TryInlineCall(expr)) { |
9253 return; | 9272 return; |
9254 } else { | 9273 } else { |
9255 call = BuildCallConstantFunction(known_function, argument_count); | 9274 call = BuildCallConstantFunction(known_function, argument_count); |
9256 } | 9275 } |
9257 | 9276 |
9258 } else { | 9277 } else { |
9259 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9278 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
| 9279 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
| 9280 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
| 9281 // gets ignored by the always-opt flag, which leads to incorrect code. |
| 9282 Add<HDeoptimize>("Insufficient type feedback for call with arguments", |
| 9283 Deoptimizer::EAGER); |
| 9284 arguments_flag = ARGUMENTS_FAKED; |
| 9285 } |
| 9286 |
| 9287 // Push the function under the receiver. |
| 9288 environment()->SetExpressionStackAt(0, function); |
| 9289 Push(receiver); |
| 9290 |
| 9291 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9260 CallFunctionFlags flags = receiver->type().IsJSObject() | 9292 CallFunctionFlags flags = receiver->type().IsJSObject() |
9261 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 9293 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
9262 call = New<HCallFunction>(function, argument_count, flags); | 9294 call = New<HCallFunction>(function, argument_count, flags); |
9263 } | 9295 } |
9264 PushArgumentsFromEnvironment(argument_count); | 9296 PushArgumentsFromEnvironment(argument_count); |
9265 | 9297 |
9266 } else { | 9298 } else { |
9267 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9299 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
9268 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 9300 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
9269 return Bailout(kPossibleDirectCallToEval); | 9301 return Bailout(kPossibleDirectCallToEval); |
(...skipping 3487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12757 if (ShouldProduceTraceOutput()) { | 12789 if (ShouldProduceTraceOutput()) { |
12758 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12790 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12759 } | 12791 } |
12760 | 12792 |
12761 #ifdef DEBUG | 12793 #ifdef DEBUG |
12762 graph_->Verify(false); // No full verify. | 12794 graph_->Verify(false); // No full verify. |
12763 #endif | 12795 #endif |
12764 } | 12796 } |
12765 | 12797 |
12766 } } // namespace v8::internal | 12798 } } // namespace v8::internal |
OLD | NEW |