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

Side by Side Diff: src/hydrogen.cc

Issue 9643001: Inline functions that use arguments object in f.apply(o, arguments) pattern. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: regression test Created 8 years, 9 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 2621 matching lines...) Expand 10 before | Expand all | Expand 10 after
2632 ++i) { 2632 ++i) {
2633 environment()->Bind(i, undefined_constant); 2633 environment()->Bind(i, undefined_constant);
2634 } 2634 }
2635 2635
2636 // Handle the arguments and arguments shadow variables specially (they do 2636 // Handle the arguments and arguments shadow variables specially (they do
2637 // not have declarations). 2637 // not have declarations).
2638 if (scope->arguments() != NULL) { 2638 if (scope->arguments() != NULL) {
2639 if (!scope->arguments()->IsStackAllocated()) { 2639 if (!scope->arguments()->IsStackAllocated()) {
2640 return Bailout("context-allocated arguments"); 2640 return Bailout("context-allocated arguments");
2641 } 2641 }
2642 HArgumentsObject* object = new(zone()) HArgumentsObject; 2642
2643 AddInstruction(object); 2643 if (!graph()->HasArgumentsObject()) {
2644 graph()->SetArgumentsObject(object); 2644 HArgumentsObject* object = new(zone()) HArgumentsObject;
2645 environment()->Bind(scope->arguments(), object); 2645 AddInstruction(object);
2646 graph()->SetArgumentsObject(object);
2647 }
2648 environment()->Bind(scope->arguments(),
2649 graph()->GetArgumentsObject());
2646 } 2650 }
2647 } 2651 }
2648 2652
2649 2653
2650 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2654 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2651 for (int i = 0; i < statements->length(); i++) { 2655 for (int i = 0; i < statements->length(); i++) {
2652 CHECK_ALIVE(Visit(statements->at(i))); 2656 CHECK_ALIVE(Visit(statements->at(i)));
2653 } 2657 }
2654 } 2658 }
2655 2659
(...skipping 2563 matching lines...) Expand 10 before | Expand all | Expand 10 after
5219 nodes_added > kUnlimitedMaxInlinedSize) { 5223 nodes_added > kUnlimitedMaxInlinedSize) {
5220 TraceInline(target, caller, "target AST is too large [late]"); 5224 TraceInline(target, caller, "target AST is too large [late]");
5221 return false; 5225 return false;
5222 } 5226 }
5223 AstProperties::Flags* flags(function->flags()); 5227 AstProperties::Flags* flags(function->flags());
5224 if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) { 5228 if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
5225 TraceInline(target, caller, "target contains unsupported syntax [late]"); 5229 TraceInline(target, caller, "target contains unsupported syntax [late]");
5226 return false; 5230 return false;
5227 } 5231 }
5228 5232
5229 // Don't inline functions that uses the arguments object. 5233 // If the function uses arguments object check that inlining of functions
5234 // with arguments object is enabled and variable arguments is stack allocated.
5230 if (function->scope()->arguments() != NULL) { 5235 if (function->scope()->arguments() != NULL) {
5231 TraceInline(target, caller, "target requires special argument handling"); 5236 if (!FLAG_inline_arguments) {
5232 return false; 5237 TraceInline(target, caller, "target uses arguments object");
5238 return false;
5239 }
5240
5241 if (!function->scope()->arguments()->IsStackAllocated()) {
5242 TraceInline(target,
5243 caller,
5244 "target uses non-stackallocated arguments object");
5245 return false;
5246 }
5233 } 5247 }
5234 5248
5235 // All declarations must be inlineable. 5249 // All declarations must be inlineable.
5236 ZoneList<Declaration*>* decls = target_info.scope()->declarations(); 5250 ZoneList<Declaration*>* decls = target_info.scope()->declarations();
5237 int decl_count = decls->length(); 5251 int decl_count = decls->length();
5238 for (int i = 0; i < decl_count; ++i) { 5252 for (int i = 0; i < decl_count; ++i) {
5239 if (!decls->at(i)->IsInlineable()) { 5253 if (!decls->at(i)->IsInlineable()) {
5240 TraceInline(target, caller, "target has non-trivial declaration"); 5254 TraceInline(target, caller, "target has non-trivial declaration");
5241 return false; 5255 return false;
5242 } 5256 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5300 AddInstruction(context); 5314 AddInstruction(context);
5301 inner_env->BindContext(context); 5315 inner_env->BindContext(context);
5302 #endif 5316 #endif
5303 AddSimulate(return_id); 5317 AddSimulate(return_id);
5304 current_block()->UpdateEnvironment(inner_env); 5318 current_block()->UpdateEnvironment(inner_env);
5305 AddInstruction(new(zone()) HEnterInlined(target, 5319 AddInstruction(new(zone()) HEnterInlined(target,
5306 arguments->length(), 5320 arguments->length(),
5307 function, 5321 function,
5308 call_kind, 5322 call_kind,
5309 function_state()->is_construct())); 5323 function_state()->is_construct()));
5324 // If the function uses arguments object create and bind one.
5325 if (function->scope()->arguments() != NULL) {
5326 ASSERT(function->scope()->arguments()->IsStackAllocated());
5327 if (!graph()->HasArgumentsObject()) {
5328 HArgumentsObject* object = new(zone()) HArgumentsObject;
5329 AddInstruction(object);
5330 graph()->SetArgumentsObject(object);
5331 }
5332 environment()->Bind(function->scope()->arguments(),
5333 graph()->GetArgumentsObject());
5334 }
5310 VisitDeclarations(target_info.scope()->declarations()); 5335 VisitDeclarations(target_info.scope()->declarations());
5311 VisitStatements(function->body()); 5336 VisitStatements(function->body());
5312 if (HasStackOverflow()) { 5337 if (HasStackOverflow()) {
5313 // Bail out if the inline function did, as we cannot residualize a call 5338 // Bail out if the inline function did, as we cannot residualize a call
5314 // instead. 5339 // instead.
5315 TraceInline(target, caller, "inline graph construction failed"); 5340 TraceInline(target, caller, "inline graph construction failed");
5316 target_shared->DisableOptimization(); 5341 target_shared->DisableOptimization();
5317 inline_bailout_ = true; 5342 inline_bailout_ = true;
5318 delete target_state; 5343 delete target_state;
5319 return true; 5344 return true;
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
5638 if (info()->scope()->arguments() == NULL) return false; 5663 if (info()->scope()->arguments() == NULL) return false;
5639 5664
5640 ZoneList<Expression*>* args = expr->arguments(); 5665 ZoneList<Expression*>* args = expr->arguments();
5641 if (args->length() != 2) return false; 5666 if (args->length() != 2) return false;
5642 5667
5643 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 5668 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
5644 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 5669 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
5645 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 5670 HValue* arg_two_value = environment()->Lookup(arg_two->var());
5646 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 5671 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
5647 5672
5648 // Our implementation of arguments (based on this stack frame or an
5649 // adapter below it) does not work for inlined functions.
5650 if (function_state()->outer() != NULL) {
5651 Bailout("Function.prototype.apply optimization in inlined function");
5652 return true;
5653 }
5654
5655 // Found pattern f.apply(receiver, arguments). 5673 // Found pattern f.apply(receiver, arguments).
5656 VisitForValue(prop->obj()); 5674 VisitForValue(prop->obj());
5657 if (HasStackOverflow() || current_block() == NULL) return true; 5675 if (HasStackOverflow() || current_block() == NULL) return true;
5658 HValue* function = Top(); 5676 HValue* function = Top();
5659 AddCheckConstantFunction(expr, function, function_map, true); 5677 AddCheckConstantFunction(expr, function, function_map, true);
5660 Drop(1); 5678 Drop(1);
5661 5679
5662 VisitForValue(args->at(0)); 5680 VisitForValue(args->at(0));
5663 if (HasStackOverflow() || current_block() == NULL) return true; 5681 if (HasStackOverflow() || current_block() == NULL) return true;
5664 HValue* receiver = Pop(); 5682 HValue* receiver = Pop();
5665 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 5683
5666 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 5684 if (function_state()->outer() == NULL) {
5667 HInstruction* result = 5685 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
5668 new(zone()) HApplyArguments(function, receiver, length, elements); 5686 HInstruction* length =
5669 result->set_position(expr->position()); 5687 AddInstruction(new(zone()) HArgumentsLength(elements));
5670 ast_context()->ReturnInstruction(result, expr->id()); 5688 HValue* wrapped_receiver = receiver;
5671 return true; 5689 if (!receiver->IsAllocateObject()) {
5690 wrapped_receiver =
5691 AddInstruction(new(zone()) HWrapReceiver(receiver, function));
5692 }
5693 HInstruction* result =
5694 new(zone()) HApplyArguments(function,
5695 wrapped_receiver,
5696 length,
5697 elements);
5698 result->set_position(expr->position());
5699 ast_context()->ReturnInstruction(result, expr->id());
5700 return true;
5701 } else {
5702 // We are inside inlined function and we know exactly what is inside
5703 // arguments object.
5704 HValue* context = environment()->LookupContext();
5705
5706 HValue* wrapped_receiver = receiver;
5707 if (!receiver->IsAllocateObject()) {
5708 wrapped_receiver =
5709 AddInstruction(new(zone()) HWrapReceiver(receiver, function));
5710 }
5711 PushAndAdd(new(zone()) HPushArgument(wrapped_receiver));
5712
5713 int parameter_count = environment()->parameter_count();
5714 for (int i = 1; i < environment()->parameter_count(); i++) {
5715 PushAndAdd(new(zone()) HPushArgument(environment()->Lookup(i)));
5716 }
5717
5718 if (environment()->outer()->frame_type() == ARGUMENTS_ADAPTOR) {
5719 HEnvironment* adaptor = environment()->outer();
5720 parameter_count = adaptor->parameter_count();
5721
5722 for (int i = environment()->parameter_count();
5723 i < adaptor->parameter_count();
5724 i++) {
5725 PushAndAdd(new(zone()) HPushArgument(adaptor->Lookup(i)));
5726 }
5727 }
5728
5729 HInvokeFunction* call = new(zone()) HInvokeFunction(
5730 context,
5731 function,
5732 parameter_count);
5733 Drop(parameter_count);
5734 call->set_position(expr->position());
5735 ast_context()->ReturnInstruction(call, expr->id());
5736 return true;
5737 }
5672 } 5738 }
5673 5739
5674 5740
5675 void HGraphBuilder::VisitCall(Call* expr) { 5741 void HGraphBuilder::VisitCall(Call* expr) {
5676 ASSERT(!HasStackOverflow()); 5742 ASSERT(!HasStackOverflow());
5677 ASSERT(current_block() != NULL); 5743 ASSERT(current_block() != NULL);
5678 ASSERT(current_block()->HasPredecessor()); 5744 ASSERT(current_block()->HasPredecessor());
5679 Expression* callee = expr->expression(); 5745 Expression* callee = expr->expression();
5680 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5746 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
5681 HInstruction* call = NULL; 5747 HInstruction* call = NULL;
(...skipping 2367 matching lines...) Expand 10 before | Expand all | Expand 10 after
8049 } 8115 }
8050 } 8116 }
8051 8117
8052 #ifdef DEBUG 8118 #ifdef DEBUG
8053 if (graph_ != NULL) graph_->Verify(false); // No full verify. 8119 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8054 if (allocator_ != NULL) allocator_->Verify(); 8120 if (allocator_ != NULL) allocator_->Verify();
8055 #endif 8121 #endif
8056 } 8122 }
8057 8123
8058 } } // namespace v8::internal 8124 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698