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

Side by Side Diff: src/hydrogen.cc

Issue 736043002: Do not bailout from optimizing functions that use f(x, arguments) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years, 1 month 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
OLDNEW
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
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
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
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, true)) 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
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(
9189 Call* expr, bool mark_arguments_as_live) {
9190 ZoneList<Expression*>* args = expr->arguments();
9191 if (args->length() != 2) return false;
9192 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
9193 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
9194 HValue* arg_two_value = mark_arguments_as_live
9195 ? LookupAndMakeLive(arg_two->var())
9196 : Lookup(arg_two->var());
9197 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
9198 return true;
9199 }
9200
9201
9181 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 9202 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
9182 DCHECK(!HasStackOverflow()); 9203 DCHECK(!HasStackOverflow());
9183 DCHECK(current_block() != NULL); 9204 DCHECK(current_block() != NULL);
9184 DCHECK(current_block()->HasPredecessor()); 9205 DCHECK(current_block()->HasPredecessor());
9185 Expression* callee = expr->expression(); 9206 Expression* callee = expr->expression();
9186 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 9207 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
9187 HInstruction* call = NULL; 9208 HInstruction* call = NULL;
9188 9209
9189 Property* prop = callee->AsProperty(); 9210 Property* prop = callee->AsProperty();
9190 if (prop != NULL) { 9211 if (prop != NULL) {
(...skipping 16 matching lines...) Expand all
9207 if (!prop->key()->IsPropertyName()) { 9228 if (!prop->key()->IsPropertyName()) {
9208 CHECK_ALIVE(VisitForValue(prop->key())); 9229 CHECK_ALIVE(VisitForValue(prop->key()));
9209 key = Pop(); 9230 key = Pop();
9210 } 9231 }
9211 9232
9212 CHECK_ALIVE(PushLoad(prop, receiver, key)); 9233 CHECK_ALIVE(PushLoad(prop, receiver, key));
9213 HValue* function = Pop(); 9234 HValue* function = Pop();
9214 9235
9215 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 9236 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
9216 9237
9217 // Push the function under the receiver.
9218 environment()->SetExpressionStackAt(0, function);
9219 9238
9220 Push(receiver);
9221 9239
9222 if (function->IsConstant() && 9240 if (function->IsConstant() &&
9223 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 9241 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9242 // Push the function under the receiver.
9243 environment()->SetExpressionStackAt(0, function);
9244 Push(receiver);
9245
9224 Handle<JSFunction> known_function = Handle<JSFunction>::cast( 9246 Handle<JSFunction> known_function = Handle<JSFunction>::cast(
9225 HConstant::cast(function)->handle(isolate())); 9247 HConstant::cast(function)->handle(isolate()));
9226 expr->set_target(known_function); 9248 expr->set_target(known_function);
9227 9249
9228 if (TryIndirectCall(expr)) return; 9250 if (TryIndirectCall(expr)) return;
9229 CHECK_ALIVE(VisitExpressions(expr->arguments())); 9251 CHECK_ALIVE(VisitExpressions(expr->arguments()));
9230 9252
9231 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); 9253 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
9232 if (TryInlineBuiltinMethodCall(expr, known_function, map, 9254 if (TryInlineBuiltinMethodCall(expr, known_function, map,
9233 expr->arguments()->length())) { 9255 expr->arguments()->length())) {
(...skipping 15 matching lines...) Expand all
9249 // HWrapReceiver. 9271 // HWrapReceiver.
9250 call = New<HCallFunction>( 9272 call = New<HCallFunction>(
9251 function, argument_count, WRAP_AND_CALL); 9273 function, argument_count, WRAP_AND_CALL);
9252 } else if (TryInlineCall(expr)) { 9274 } else if (TryInlineCall(expr)) {
9253 return; 9275 return;
9254 } else { 9276 } else {
9255 call = BuildCallConstantFunction(known_function, argument_count); 9277 call = BuildCallConstantFunction(known_function, argument_count);
9256 } 9278 }
9257 9279
9258 } else { 9280 } else {
9259 CHECK_ALIVE(VisitExpressions(expr->arguments())); 9281 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
9282 if (CanBeFunctionApplyArguments(expr, false)) {
Jakob Kummerow 2014/11/19 20:46:16 I'm not too happy with this condition. It lacks a
Jakob Kummerow 2014/11/20 09:59:15 I've talked to mvstanton@, he suggested to impleme
ulan 2014/11/20 15:23:29 Done.
ulan 2014/11/20 15:23:29 Acknowledged.
9283 Add<HDeoptimize>("Insufficient type feedback for call with arguments",
9284 Deoptimizer::EAGER);
Jakob Kummerow 2014/11/19 20:46:16 If we find an appropriate check for "no type feedb
ulan 2014/11/20 15:23:29 Done.
9285 arguments_flag = ARGUMENTS_FAKED;
9286 }
9287
9288 // Push the function under the receiver.
9289 environment()->SetExpressionStackAt(0, function);
9290 Push(receiver);
9291
9292 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
9260 CallFunctionFlags flags = receiver->type().IsJSObject() 9293 CallFunctionFlags flags = receiver->type().IsJSObject()
9261 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; 9294 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
9262 call = New<HCallFunction>(function, argument_count, flags); 9295 call = New<HCallFunction>(function, argument_count, flags);
9263 } 9296 }
9264 PushArgumentsFromEnvironment(argument_count); 9297 PushArgumentsFromEnvironment(argument_count);
9265 9298
9266 } else { 9299 } else {
9267 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 9300 VariableProxy* proxy = expr->expression()->AsVariableProxy();
9268 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 9301 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
9269 return Bailout(kPossibleDirectCallToEval); 9302 return Bailout(kPossibleDirectCallToEval);
(...skipping 3487 matching lines...) Expand 10 before | Expand all | Expand 10 after
12757 if (ShouldProduceTraceOutput()) { 12790 if (ShouldProduceTraceOutput()) {
12758 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 12791 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
12759 } 12792 }
12760 12793
12761 #ifdef DEBUG 12794 #ifdef DEBUG
12762 graph_->Verify(false); // No full verify. 12795 graph_->Verify(false); // No full verify.
12763 #endif 12796 #endif
12764 } 12797 }
12765 12798
12766 } } // namespace v8::internal 12799 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698