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 2621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |