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

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: Remove Lookup 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
« src/ast.h ('K') | « src/hydrogen.h ('k') | src/type-info.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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)) 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(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
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
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
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
OLDNEW
« src/ast.h ('K') | « src/hydrogen.h ('k') | src/type-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698