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

Side by Side Diff: src/hydrogen.cc

Issue 9304001: Implement inlining of constructor calls. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed moar comments by Vyacheslav Egorov. 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.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 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 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 536
537 537
538 HConstant* HGraph::GetConstantHole() { 538 HConstant* HGraph::GetConstantHole() {
539 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value()); 539 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
540 } 540 }
541 541
542 542
543 HGraphBuilder::HGraphBuilder(CompilationInfo* info, 543 HGraphBuilder::HGraphBuilder(CompilationInfo* info,
544 TypeFeedbackOracle* oracle) 544 TypeFeedbackOracle* oracle)
545 : function_state_(NULL), 545 : function_state_(NULL),
546 initial_function_state_(this, info, oracle, false), 546 initial_function_state_(this, info, oracle, NORMAL_RETURN),
547 ast_context_(NULL), 547 ast_context_(NULL),
548 break_scope_(NULL), 548 break_scope_(NULL),
549 graph_(NULL), 549 graph_(NULL),
550 current_block_(NULL), 550 current_block_(NULL),
551 inlined_count_(0), 551 inlined_count_(0),
552 zone_(info->isolate()->zone()), 552 zone_(info->isolate()->zone()),
553 inline_bailout_(false) { 553 inline_bailout_(false) {
554 // This is not initialized in the initializer list because the 554 // This is not initialized in the initializer list because the
555 // constructor for the initial state relies on function_state_ == NULL 555 // constructor for the initial state relies on function_state_ == NULL
556 // to know it's the initial state. 556 // to know it's the initial state.
(...skipping 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 } 2019 }
2020 } 2020 }
2021 } 2021 }
2022 2022
2023 2023
2024 // Implementation of utility class to encapsulate the translation state for 2024 // Implementation of utility class to encapsulate the translation state for
2025 // a (possibly inlined) function. 2025 // a (possibly inlined) function.
2026 FunctionState::FunctionState(HGraphBuilder* owner, 2026 FunctionState::FunctionState(HGraphBuilder* owner,
2027 CompilationInfo* info, 2027 CompilationInfo* info,
2028 TypeFeedbackOracle* oracle, 2028 TypeFeedbackOracle* oracle,
2029 bool drop_extra) 2029 ReturnHandlingFlag return_handling)
2030 : owner_(owner), 2030 : owner_(owner),
2031 compilation_info_(info), 2031 compilation_info_(info),
2032 oracle_(oracle), 2032 oracle_(oracle),
2033 call_context_(NULL), 2033 call_context_(NULL),
2034 drop_extra_(drop_extra), 2034 return_handling_(return_handling),
2035 function_return_(NULL), 2035 function_return_(NULL),
2036 test_context_(NULL), 2036 test_context_(NULL),
2037 outer_(owner->function_state()) { 2037 outer_(owner->function_state()) {
2038 if (outer_ != NULL) { 2038 if (outer_ != NULL) {
2039 // State for an inline function. 2039 // State for an inline function.
2040 if (owner->ast_context()->IsTest()) { 2040 if (owner->ast_context()->IsTest()) {
2041 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2041 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2042 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2042 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2043 if_true->MarkAsInlineReturnTarget(); 2043 if_true->MarkAsInlineReturnTarget();
2044 if_false->MarkAsInlineReturnTarget(); 2044 if_false->MarkAsInlineReturnTarget();
(...skipping 22 matching lines...) Expand all
2067 2067
2068 // Implementation of utility classes to represent an expression's context in 2068 // Implementation of utility classes to represent an expression's context in
2069 // the AST. 2069 // the AST.
2070 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 2070 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
2071 : owner_(owner), 2071 : owner_(owner),
2072 kind_(kind), 2072 kind_(kind),
2073 outer_(owner->ast_context()), 2073 outer_(owner->ast_context()),
2074 for_typeof_(false) { 2074 for_typeof_(false) {
2075 owner->set_ast_context(this); // Push. 2075 owner->set_ast_context(this); // Push.
2076 #ifdef DEBUG 2076 #ifdef DEBUG
2077 ASSERT(!owner->environment()->is_arguments_adaptor()); 2077 ASSERT(owner->environment()->frame_type() == JS_FUNCTION);
2078 original_length_ = owner->environment()->length(); 2078 original_length_ = owner->environment()->length();
2079 #endif 2079 #endif
2080 } 2080 }
2081 2081
2082 2082
2083 AstContext::~AstContext() { 2083 AstContext::~AstContext() {
2084 owner_->set_ast_context(outer_); // Pop. 2084 owner_->set_ast_context(outer_); // Pop.
2085 } 2085 }
2086 2086
2087 2087
2088 EffectContext::~EffectContext() { 2088 EffectContext::~EffectContext() {
2089 ASSERT(owner()->HasStackOverflow() || 2089 ASSERT(owner()->HasStackOverflow() ||
2090 owner()->current_block() == NULL || 2090 owner()->current_block() == NULL ||
2091 (owner()->environment()->length() == original_length_ && 2091 (owner()->environment()->length() == original_length_ &&
2092 !owner()->environment()->is_arguments_adaptor())); 2092 owner()->environment()->frame_type() == JS_FUNCTION));
2093 } 2093 }
2094 2094
2095 2095
2096 ValueContext::~ValueContext() { 2096 ValueContext::~ValueContext() {
2097 ASSERT(owner()->HasStackOverflow() || 2097 ASSERT(owner()->HasStackOverflow() ||
2098 owner()->current_block() == NULL || 2098 owner()->current_block() == NULL ||
2099 (owner()->environment()->length() == original_length_ + 1 && 2099 (owner()->environment()->length() == original_length_ + 1 &&
2100 !owner()->environment()->is_arguments_adaptor())); 2100 owner()->environment()->frame_type() == JS_FUNCTION));
2101 } 2101 }
2102 2102
2103 2103
2104 void EffectContext::ReturnValue(HValue* value) { 2104 void EffectContext::ReturnValue(HValue* value) {
2105 // The value is simply ignored. 2105 // The value is simply ignored.
2106 } 2106 }
2107 2107
2108 2108
2109 void ValueContext::ReturnValue(HValue* value) { 2109 void ValueContext::ReturnValue(HValue* value) {
2110 // The value is tracked in the bailout environment, and communicated 2110 // The value is tracked in the bailout environment, and communicated
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
2452 current_block()->AddPhi(instr); 2452 current_block()->AddPhi(instr);
2453 } 2453 }
2454 2454
2455 2455
2456 void HGraphBuilder::PushAndAdd(HInstruction* instr) { 2456 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
2457 Push(instr); 2457 Push(instr);
2458 AddInstruction(instr); 2458 AddInstruction(instr);
2459 } 2459 }
2460 2460
2461 2461
2462 template <int V> 2462 template <class Instruction>
2463 HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { 2463 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) {
2464 int count = call->argument_count(); 2464 int count = call->argument_count();
2465 ZoneList<HValue*> arguments(count); 2465 ZoneList<HValue*> arguments(count);
2466 for (int i = 0; i < count; ++i) { 2466 for (int i = 0; i < count; ++i) {
2467 arguments.Add(Pop()); 2467 arguments.Add(Pop());
2468 } 2468 }
2469 2469
2470 while (!arguments.is_empty()) { 2470 while (!arguments.is_empty()) {
2471 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 2471 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
2472 } 2472 }
2473 return call; 2473 return call;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2665 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 2665 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2666 ASSERT(!HasStackOverflow()); 2666 ASSERT(!HasStackOverflow());
2667 ASSERT(current_block() != NULL); 2667 ASSERT(current_block() != NULL);
2668 ASSERT(current_block()->HasPredecessor()); 2668 ASSERT(current_block()->HasPredecessor());
2669 AstContext* context = call_context(); 2669 AstContext* context = call_context();
2670 if (context == NULL) { 2670 if (context == NULL) {
2671 // Not an inlined return, so an actual one. 2671 // Not an inlined return, so an actual one.
2672 CHECK_ALIVE(VisitForValue(stmt->expression())); 2672 CHECK_ALIVE(VisitForValue(stmt->expression()));
2673 HValue* result = environment()->Pop(); 2673 HValue* result = environment()->Pop();
2674 current_block()->FinishExit(new(zone()) HReturn(result)); 2674 current_block()->FinishExit(new(zone()) HReturn(result));
2675 set_current_block(NULL); 2675 } else if (function_state()->is_construct()) {
2676 // Return from an inlined construct call. In a test context the return
2677 // value will always evaluate to true, in a value context the return value
2678 // needs to be a JSObject.
2679 if (context->IsTest()) {
2680 TestContext* test = TestContext::cast(context);
2681 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2682 current_block()->Goto(test->if_true(), function_state()->drop_extra());
2683 } else if (context->IsEffect()) {
2684 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2685 current_block()->Goto(function_return(), function_state()->drop_extra());
2686 } else {
2687 ASSERT(context->IsValue());
2688 CHECK_ALIVE(VisitForValue(stmt->expression()));
2689 HValue* return_value = Pop();
2690 HValue* receiver = environment()->Lookup(0);
2691 HHasInstanceTypeAndBranch* typecheck =
2692 new(zone()) HHasInstanceTypeAndBranch(return_value,
2693 FIRST_SPEC_OBJECT_TYPE,
2694 LAST_SPEC_OBJECT_TYPE);
2695 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
2696 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
2697 typecheck->SetSuccessorAt(0, if_spec_object);
2698 typecheck->SetSuccessorAt(1, not_spec_object);
2699 current_block()->Finish(typecheck);
2700 if_spec_object->AddLeaveInlined(return_value,
2701 function_return(),
2702 function_state()->drop_extra());
2703 not_spec_object->AddLeaveInlined(receiver,
2704 function_return(),
2705 function_state()->drop_extra());
2706 }
2676 } else { 2707 } else {
2677 // Return from an inlined function, visit the subexpression in the 2708 // Return from an inlined function, visit the subexpression in the
2678 // expression context of the call. 2709 // expression context of the call.
2679 if (context->IsTest()) { 2710 if (context->IsTest()) {
2680 TestContext* test = TestContext::cast(context); 2711 TestContext* test = TestContext::cast(context);
2681 VisitForControl(stmt->expression(), 2712 VisitForControl(stmt->expression(),
2682 test->if_true(), 2713 test->if_true(),
2683 test->if_false()); 2714 test->if_false());
2684 } else if (context->IsEffect()) { 2715 } else if (context->IsEffect()) {
2685 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2716 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2686 current_block()->Goto(function_return(), function_state()->drop_extra()); 2717 current_block()->Goto(function_return(), function_state()->drop_extra());
2687 } else { 2718 } else {
2688 ASSERT(context->IsValue()); 2719 ASSERT(context->IsValue());
2689 CHECK_ALIVE(VisitForValue(stmt->expression())); 2720 CHECK_ALIVE(VisitForValue(stmt->expression()));
2690 HValue* return_value = environment()->Pop(); 2721 HValue* return_value = Pop();
2691 current_block()->AddLeaveInlined(return_value, 2722 current_block()->AddLeaveInlined(return_value,
2692 function_return(), 2723 function_return(),
2693 function_state()->drop_extra()); 2724 function_state()->drop_extra());
2694 } 2725 }
2695 set_current_block(NULL);
2696 } 2726 }
2727 set_current_block(NULL);
2697 } 2728 }
2698 2729
2699 2730
2700 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2731 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2701 ASSERT(!HasStackOverflow()); 2732 ASSERT(!HasStackOverflow());
2702 ASSERT(current_block() != NULL); 2733 ASSERT(current_block() != NULL);
2703 ASSERT(current_block()->HasPredecessor()); 2734 ASSERT(current_block()->HasPredecessor());
2704 return Bailout("WithStatement"); 2735 return Bailout("WithStatement");
2705 } 2736 }
2706 2737
(...skipping 1997 matching lines...) Expand 10 before | Expand all | Expand 10 after
4704 HCompareMap* compare = 4735 HCompareMap* compare =
4705 new(zone()) HCompareMap(receiver, map, if_true, if_false); 4736 new(zone()) HCompareMap(receiver, map, if_true, if_false);
4706 current_block()->Finish(compare); 4737 current_block()->Finish(compare);
4707 4738
4708 set_current_block(if_true); 4739 set_current_block(if_true);
4709 AddCheckConstantFunction(expr, receiver, map, false); 4740 AddCheckConstantFunction(expr, receiver, map, false);
4710 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 4741 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
4711 PrintF("Trying to inline the polymorphic call to %s\n", 4742 PrintF("Trying to inline the polymorphic call to %s\n",
4712 *name->ToCString()); 4743 *name->ToCString());
4713 } 4744 }
4714 if (FLAG_polymorphic_inlining && TryInline(expr)) { 4745 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
4715 // Trying to inline will signal that we should bailout from the 4746 // Trying to inline will signal that we should bailout from the
4716 // entire compilation by setting stack overflow on the visitor. 4747 // entire compilation by setting stack overflow on the visitor.
4717 if (HasStackOverflow()) return; 4748 if (HasStackOverflow()) return;
4718 } else { 4749 } else {
4719 HCallConstantFunction* call = 4750 HCallConstantFunction* call =
4720 new(zone()) HCallConstantFunction(expr->target(), argument_count); 4751 new(zone()) HCallConstantFunction(expr->target(), argument_count);
4721 call->set_position(expr->position()); 4752 call->set_position(expr->position());
4722 PreProcessCall(call); 4753 PreProcessCall(call);
4723 AddInstruction(call); 4754 AddInstruction(call);
4724 if (!ast_context()->IsEffect()) Push(call); 4755 if (!ast_context()->IsEffect()) Push(call);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4774 if (reason == NULL) { 4805 if (reason == NULL) {
4775 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 4806 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
4776 } else { 4807 } else {
4777 PrintF("Did not inline %s called from %s (%s).\n", 4808 PrintF("Did not inline %s called from %s (%s).\n",
4778 *target_name, *caller_name, reason); 4809 *target_name, *caller_name, reason);
4779 } 4810 }
4780 } 4811 }
4781 } 4812 }
4782 4813
4783 4814
4784 bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) { 4815 bool HGraphBuilder::TryInline(CallKind call_kind,
4816 Handle<JSFunction> target,
4817 ZoneList<Expression*>* arguments,
4818 HValue* receiver,
4819 int ast_id,
4820 int return_id,
4821 ReturnHandlingFlag return_handling) {
4785 if (!FLAG_use_inlining) return false; 4822 if (!FLAG_use_inlining) return false;
4786 4823
4787 // The function call we are inlining is a method call if the call
4788 // is a property call.
4789 CallKind call_kind = (expr->expression()->AsProperty() == NULL)
4790 ? CALL_AS_FUNCTION
4791 : CALL_AS_METHOD;
4792
4793 // Precondition: call is monomorphic and we have found a target with the 4824 // Precondition: call is monomorphic and we have found a target with the
4794 // appropriate arity. 4825 // appropriate arity.
4795 Handle<JSFunction> caller = info()->closure(); 4826 Handle<JSFunction> caller = info()->closure();
4796 Handle<JSFunction> target = expr->target();
4797 Handle<SharedFunctionInfo> target_shared(target->shared()); 4827 Handle<SharedFunctionInfo> target_shared(target->shared());
4798 4828
4799 // Do a quick check on source code length to avoid parsing large 4829 // Do a quick check on source code length to avoid parsing large
4800 // inlining candidates. 4830 // inlining candidates.
4801 if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) 4831 if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize)
4802 || target->shared()->SourceSize() > kUnlimitedMaxSourceSize) { 4832 || target->shared()->SourceSize() > kUnlimitedMaxSourceSize) {
4803 TraceInline(target, caller, "target text too big"); 4833 TraceInline(target, caller, "target text too big");
4804 return false; 4834 return false;
4805 } 4835 }
4806 4836
(...skipping 16 matching lines...) Expand all
4823 4853
4824 4854
4825 // Don't inline deeper than kMaxInliningLevels calls. 4855 // Don't inline deeper than kMaxInliningLevels calls.
4826 HEnvironment* env = environment(); 4856 HEnvironment* env = environment();
4827 int current_level = 1; 4857 int current_level = 1;
4828 while (env->outer() != NULL) { 4858 while (env->outer() != NULL) {
4829 if (current_level == Compiler::kMaxInliningLevels) { 4859 if (current_level == Compiler::kMaxInliningLevels) {
4830 TraceInline(target, caller, "inline depth limit reached"); 4860 TraceInline(target, caller, "inline depth limit reached");
4831 return false; 4861 return false;
4832 } 4862 }
4833 if (!env->outer()->is_arguments_adaptor()) { 4863 if (env->outer()->frame_type() == JS_FUNCTION) {
4834 current_level++; 4864 current_level++;
4835 } 4865 }
4836 env = env->outer(); 4866 env = env->outer();
4837 } 4867 }
4838 4868
4839 // Don't inline recursive functions. 4869 // Don't inline recursive functions.
4840 for (FunctionState* state = function_state(); 4870 for (FunctionState* state = function_state();
4841 state != NULL; 4871 state != NULL;
4842 state = state->outer()) { 4872 state = state->outer()) {
4843 if (state->compilation_info()->closure()->shared() == *target_shared) { 4873 if (state->compilation_info()->closure()->shared() == *target_shared) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
4934 4964
4935 // Save the pending call context and type feedback oracle. Set up new ones 4965 // Save the pending call context and type feedback oracle. Set up new ones
4936 // for the inlined function. 4966 // for the inlined function.
4937 ASSERT(target_shared->has_deoptimization_support()); 4967 ASSERT(target_shared->has_deoptimization_support());
4938 TypeFeedbackOracle target_oracle( 4968 TypeFeedbackOracle target_oracle(
4939 Handle<Code>(target_shared->code()), 4969 Handle<Code>(target_shared->code()),
4940 Handle<Context>(target->context()->global_context()), 4970 Handle<Context>(target->context()->global_context()),
4941 isolate()); 4971 isolate());
4942 // The function state is new-allocated because we need to delete it 4972 // The function state is new-allocated because we need to delete it
4943 // in two different places. 4973 // in two different places.
4944 FunctionState* target_state = 4974 FunctionState* target_state = new FunctionState(
4945 new FunctionState(this, &target_info, &target_oracle, drop_extra); 4975 this, &target_info, &target_oracle, return_handling);
4946 4976
4947 HConstant* undefined = graph()->GetConstantUndefined(); 4977 HConstant* undefined = graph()->GetConstantUndefined();
4948 HEnvironment* inner_env = 4978 HEnvironment* inner_env =
4949 environment()->CopyForInlining(target, 4979 environment()->CopyForInlining(target,
4950 expr->arguments()->length(), 4980 arguments->length(),
4951 function, 4981 function,
4952 undefined, 4982 undefined,
4953 call_kind); 4983 call_kind,
4984 function_state()->is_construct());
4954 #ifdef V8_TARGET_ARCH_IA32 4985 #ifdef V8_TARGET_ARCH_IA32
4955 // IA32 only, overwrite the caller's context in the deoptimization 4986 // IA32 only, overwrite the caller's context in the deoptimization
4956 // environment with the correct one. 4987 // environment with the correct one.
4957 // 4988 //
4958 // TODO(kmillikin): implement the same inlining on other platforms so we 4989 // TODO(kmillikin): implement the same inlining on other platforms so we
4959 // can remove the unsightly ifdefs in this function. 4990 // can remove the unsightly ifdefs in this function.
4960 HConstant* context = new HConstant(Handle<Context>(target->context()), 4991 HConstant* context = new HConstant(Handle<Context>(target->context()),
4961 Representation::Tagged()); 4992 Representation::Tagged());
4962 AddInstruction(context); 4993 AddInstruction(context);
4963 inner_env->BindContext(context); 4994 inner_env->BindContext(context);
4964 #endif 4995 #endif
4965 HBasicBlock* body_entry = CreateBasicBlock(inner_env); 4996 HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4966 current_block()->Goto(body_entry); 4997 current_block()->Goto(body_entry);
4967 body_entry->SetJoinId(expr->ReturnId()); 4998 body_entry->SetJoinId(return_id);
4968 set_current_block(body_entry); 4999 set_current_block(body_entry);
4969 AddInstruction(new(zone()) HEnterInlined(target, 5000 AddInstruction(new(zone()) HEnterInlined(target,
4970 expr->arguments()->length(), 5001 arguments->length(),
4971 function, 5002 function,
4972 call_kind)); 5003 call_kind,
5004 function_state()->is_construct()));
4973 VisitDeclarations(target_info.scope()->declarations()); 5005 VisitDeclarations(target_info.scope()->declarations());
4974 VisitStatements(function->body()); 5006 VisitStatements(function->body());
4975 if (HasStackOverflow()) { 5007 if (HasStackOverflow()) {
4976 // Bail out if the inline function did, as we cannot residualize a call 5008 // Bail out if the inline function did, as we cannot residualize a call
4977 // instead. 5009 // instead.
4978 TraceInline(target, caller, "inline graph construction failed"); 5010 TraceInline(target, caller, "inline graph construction failed");
4979 target_shared->DisableOptimization(*target); 5011 target_shared->DisableOptimization(*target);
4980 inline_bailout_ = true; 5012 inline_bailout_ = true;
4981 delete target_state; 5013 delete target_state;
4982 return true; 5014 return true;
4983 } 5015 }
4984 5016
4985 // Update inlined nodes count. 5017 // Update inlined nodes count.
4986 inlined_count_ += nodes_added; 5018 inlined_count_ += nodes_added;
4987 5019
4988 TraceInline(target, caller, NULL); 5020 TraceInline(target, caller, NULL);
4989 5021
4990 if (current_block() != NULL) { 5022 if (current_block() != NULL) {
4991 // Add a return of undefined if control can fall off the body. In a 5023 // Add default return value (i.e. undefined for normals calls or the newly
4992 // test context, undefined is false. 5024 // allocated receiver for construct calls) if control can fall off the
4993 if (inlined_test_context() == NULL) { 5025 // body. In a test context, undefined is false and any JSObject is true.
5026 if (call_context()->IsValue()) {
4994 ASSERT(function_return() != NULL); 5027 ASSERT(function_return() != NULL);
4995 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); 5028 HValue* return_value = function_state()->is_construct()
4996 if (call_context()->IsEffect()) { 5029 ? receiver
4997 current_block()->Goto(function_return(), drop_extra); 5030 : undefined;
4998 } else { 5031 current_block()->AddLeaveInlined(return_value,
4999 current_block()->AddLeaveInlined(undefined, 5032 function_return(),
5000 function_return(), 5033 function_state()->drop_extra());
5001 drop_extra); 5034 } else if (call_context()->IsEffect()) {
5002 } 5035 ASSERT(function_return() != NULL);
5036 current_block()->Goto(function_return(), function_state()->drop_extra());
5003 } else { 5037 } else {
5004 // The graph builder assumes control can reach both branches of a
5005 // test, so we materialize the undefined value and test it rather than
5006 // simply jumping to the false target.
5007 //
5008 // TODO(3168478): refactor to avoid this.
5009 ASSERT(call_context()->IsTest()); 5038 ASSERT(call_context()->IsTest());
5010 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 5039 ASSERT(inlined_test_context() != NULL);
5011 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 5040 HBasicBlock* target = function_state()->is_construct()
5012 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false); 5041 ? inlined_test_context()->if_true()
5013 current_block()->Finish(test); 5042 : inlined_test_context()->if_false();
5014 5043 current_block()->Goto(target, function_state()->drop_extra());
5015 empty_true->Goto(inlined_test_context()->if_true(), drop_extra);
5016 empty_false->Goto(inlined_test_context()->if_false(), drop_extra);
5017 } 5044 }
5018 } 5045 }
5019 5046
5020 // Fix up the function exits. 5047 // Fix up the function exits.
5021 if (inlined_test_context() != NULL) { 5048 if (inlined_test_context() != NULL) {
5022 HBasicBlock* if_true = inlined_test_context()->if_true(); 5049 HBasicBlock* if_true = inlined_test_context()->if_true();
5023 HBasicBlock* if_false = inlined_test_context()->if_false(); 5050 HBasicBlock* if_false = inlined_test_context()->if_false();
5024 5051
5025 // Pop the return test context from the expression context stack. 5052 // Pop the return test context from the expression context stack.
5026 ASSERT(ast_context() == inlined_test_context()); 5053 ASSERT(ast_context() == inlined_test_context());
5027 ClearInlinedTestContext(); 5054 ClearInlinedTestContext();
5028 delete target_state; 5055 delete target_state;
5029 5056
5030 // Forward to the real test context. 5057 // Forward to the real test context.
5031 if (if_true->HasPredecessor()) { 5058 if (if_true->HasPredecessor()) {
5032 if_true->SetJoinId(expr->id()); 5059 if_true->SetJoinId(ast_id);
5033 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 5060 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
5034 if_true->Goto(true_target, function_state()->drop_extra()); 5061 if_true->Goto(true_target, function_state()->drop_extra());
5035 } 5062 }
5036 if (if_false->HasPredecessor()) { 5063 if (if_false->HasPredecessor()) {
5037 if_false->SetJoinId(expr->id()); 5064 if_false->SetJoinId(ast_id);
5038 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 5065 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
5039 if_false->Goto(false_target, function_state()->drop_extra()); 5066 if_false->Goto(false_target, function_state()->drop_extra());
5040 } 5067 }
5041 set_current_block(NULL); 5068 set_current_block(NULL);
5042 return true; 5069 return true;
5043 5070
5044 } else if (function_return()->HasPredecessor()) { 5071 } else if (function_return()->HasPredecessor()) {
5045 function_return()->SetJoinId(expr->id()); 5072 function_return()->SetJoinId(ast_id);
5046 set_current_block(function_return()); 5073 set_current_block(function_return());
5047 } else { 5074 } else {
5048 set_current_block(NULL); 5075 set_current_block(NULL);
5049 } 5076 }
5050 delete target_state; 5077 delete target_state;
5051 return true; 5078 return true;
5052 } 5079 }
5053 5080
5054 5081
5082 bool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) {
5083 // The function call we are inlining is a method call if the call
5084 // is a property call.
5085 CallKind call_kind = (expr->expression()->AsProperty() == NULL)
5086 ? CALL_AS_FUNCTION
5087 : CALL_AS_METHOD;
5088
5089 return TryInline(call_kind,
5090 expr->target(),
5091 expr->arguments(),
5092 NULL,
5093 expr->id(),
5094 expr->ReturnId(),
5095 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN);
5096 }
5097
5098
5099 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
5100 return TryInline(CALL_AS_FUNCTION,
5101 expr->target(),
5102 expr->arguments(),
5103 receiver,
5104 expr->id(),
5105 expr->ReturnId(),
5106 CONSTRUCT_CALL_RETURN);
5107 }
5108
5109
5055 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, 5110 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
5056 HValue* receiver, 5111 HValue* receiver,
5057 Handle<Map> receiver_map, 5112 Handle<Map> receiver_map,
5058 CheckType check_type) { 5113 CheckType check_type) {
5059 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 5114 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
5060 // Try to inline calls like Math.* as operations in the calling function. 5115 // Try to inline calls like Math.* as operations in the calling function.
5061 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 5116 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
5062 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 5117 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
5063 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5118 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
5064 switch (id) { 5119 switch (id) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
5328 expr->check_type() != RECEIVER_MAP_CHECK) { 5383 expr->check_type() != RECEIVER_MAP_CHECK) {
5329 // When the target has a custom call IC generator, use the IC, 5384 // When the target has a custom call IC generator, use the IC,
5330 // because it is likely to generate better code. Also use the IC 5385 // because it is likely to generate better code. Also use the IC
5331 // when a primitive receiver check is required. 5386 // when a primitive receiver check is required.
5332 HValue* context = environment()->LookupContext(); 5387 HValue* context = environment()->LookupContext();
5333 call = PreProcessCall( 5388 call = PreProcessCall(
5334 new(zone()) HCallNamed(context, name, argument_count)); 5389 new(zone()) HCallNamed(context, name, argument_count));
5335 } else { 5390 } else {
5336 AddCheckConstantFunction(expr, receiver, receiver_map, true); 5391 AddCheckConstantFunction(expr, receiver, receiver_map, true);
5337 5392
5338 if (TryInline(expr)) return; 5393 if (TryInlineCall(expr)) return;
5339 call = PreProcessCall( 5394 call = PreProcessCall(
5340 new(zone()) HCallConstantFunction(expr->target(), 5395 new(zone()) HCallConstantFunction(expr->target(),
5341 argument_count)); 5396 argument_count));
5342 } 5397 }
5343 } else if (types != NULL && types->length() > 1) { 5398 } else if (types != NULL && types->length() > 1) {
5344 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 5399 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
5345 HandlePolymorphicCallNamed(expr, receiver, types, name); 5400 HandlePolymorphicCallNamed(expr, receiver, types, name);
5346 return; 5401 return;
5347 5402
5348 } else { 5403 } else {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5384 // Replace the global object with the global receiver. 5439 // Replace the global object with the global receiver.
5385 HGlobalReceiver* global_receiver = 5440 HGlobalReceiver* global_receiver =
5386 new(zone()) HGlobalReceiver(global_object); 5441 new(zone()) HGlobalReceiver(global_object);
5387 // Index of the receiver from the top of the expression stack. 5442 // Index of the receiver from the top of the expression stack.
5388 const int receiver_index = argument_count - 1; 5443 const int receiver_index = argument_count - 1;
5389 AddInstruction(global_receiver); 5444 AddInstruction(global_receiver);
5390 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 5445 ASSERT(environment()->ExpressionStackAt(receiver_index)->
5391 IsGlobalObject()); 5446 IsGlobalObject());
5392 environment()->SetExpressionStackAt(receiver_index, global_receiver); 5447 environment()->SetExpressionStackAt(receiver_index, global_receiver);
5393 5448
5394 if (TryInline(expr)) return; 5449 if (TryInlineCall(expr)) return;
5395 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 5450 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
5396 argument_count)); 5451 argument_count));
5397 } else { 5452 } else {
5398 HValue* context = environment()->LookupContext(); 5453 HValue* context = environment()->LookupContext();
5399 HGlobalObject* receiver = new(zone()) HGlobalObject(context); 5454 HGlobalObject* receiver = new(zone()) HGlobalObject(context);
5400 AddInstruction(receiver); 5455 AddInstruction(receiver);
5401 PushAndAdd(new(zone()) HPushArgument(receiver)); 5456 PushAndAdd(new(zone()) HPushArgument(receiver));
5402 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5457 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5403 5458
5404 call = new(zone()) HCallGlobal(context, var->name(), argument_count); 5459 call = new(zone()) HCallGlobal(context, var->name(), argument_count);
5405 Drop(argument_count); 5460 Drop(argument_count);
5406 } 5461 }
5407 5462
5408 } else if (expr->IsMonomorphic()) { 5463 } else if (expr->IsMonomorphic()) {
5409 // The function is on the stack in the unoptimized code during 5464 // The function is on the stack in the unoptimized code during
5410 // evaluation of the arguments. 5465 // evaluation of the arguments.
5411 CHECK_ALIVE(VisitForValue(expr->expression())); 5466 CHECK_ALIVE(VisitForValue(expr->expression()));
5412 HValue* function = Top(); 5467 HValue* function = Top();
5413 HValue* context = environment()->LookupContext(); 5468 HValue* context = environment()->LookupContext();
5414 HGlobalObject* global = new(zone()) HGlobalObject(context); 5469 HGlobalObject* global = new(zone()) HGlobalObject(context);
5415 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 5470 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
5416 AddInstruction(global); 5471 AddInstruction(global);
5417 PushAndAdd(receiver); 5472 PushAndAdd(receiver);
5418 CHECK_ALIVE(VisitExpressions(expr->arguments())); 5473 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5419 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 5474 AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5420 if (TryInline(expr, true)) { // Drop function from environment. 5475 if (TryInlineCall(expr, true)) { // Drop function from environment.
5421 return; 5476 return;
5422 } else { 5477 } else {
5423 call = PreProcessCall(new(zone()) HInvokeFunction(context, 5478 call = PreProcessCall(new(zone()) HInvokeFunction(context,
5424 function, 5479 function,
5425 argument_count)); 5480 argument_count));
5426 Drop(1); // The function. 5481 Drop(1); // The function.
5427 } 5482 }
5428 5483
5429 } else { 5484 } else {
5430 CHECK_ALIVE(VisitForValue(expr->expression())); 5485 CHECK_ALIVE(VisitForValue(expr->expression()));
5431 HValue* function = Top(); 5486 HValue* function = Top();
5432 HValue* context = environment()->LookupContext(); 5487 HValue* context = environment()->LookupContext();
5433 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 5488 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
5434 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); 5489 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
5435 AddInstruction(global_object); 5490 AddInstruction(global_object);
5436 AddInstruction(receiver); 5491 AddInstruction(receiver);
5437 PushAndAdd(new(zone()) HPushArgument(receiver)); 5492 PushAndAdd(new(zone()) HPushArgument(receiver));
5438 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5493 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5439 5494
5440 call = new(zone()) HCallFunction(context, function, argument_count); 5495 call = new(zone()) HCallFunction(context, function, argument_count);
5441 Drop(argument_count + 1); 5496 Drop(argument_count + 1);
5442 } 5497 }
5443 } 5498 }
5444 5499
5445 call->set_position(expr->position()); 5500 call->set_position(expr->position());
5446 return ast_context()->ReturnInstruction(call, expr->id()); 5501 return ast_context()->ReturnInstruction(call, expr->id());
5447 } 5502 }
5448 5503
5449 5504
5505 // Checks whether allocation using the given constructor can be inlined.
5506 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
5507 return constructor->has_initial_map() &&
5508 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE;
5509 }
5510
5511
5450 void HGraphBuilder::VisitCallNew(CallNew* expr) { 5512 void HGraphBuilder::VisitCallNew(CallNew* expr) {
5451 ASSERT(!HasStackOverflow()); 5513 ASSERT(!HasStackOverflow());
5452 ASSERT(current_block() != NULL); 5514 ASSERT(current_block() != NULL);
5453 ASSERT(current_block()->HasPredecessor()); 5515 ASSERT(current_block()->HasPredecessor());
5454 // The constructor function is also used as the receiver argument to the 5516 expr->RecordTypeFeedback(oracle());
5455 // JS construct call builtin. 5517 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
5456 HValue* constructor = NULL;
5457 CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
5458 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5459
5460 HValue* context = environment()->LookupContext(); 5518 HValue* context = environment()->LookupContext();
5461 5519
5462 // The constructor is both an operand to the instruction and an argument 5520 if (FLAG_inline_construct &&
5463 // to the construct call. 5521 expr->IsMonomorphic() &&
5464 int arg_count = expr->arguments()->length() + 1; // Plus constructor. 5522 IsAllocationInlineable(expr->target())) {
5465 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); 5523 // The constructor function is on the stack in the unoptimized code
5466 call->set_position(expr->position()); 5524 // during evaluation of the arguments.
5467 Drop(arg_count); 5525 CHECK_ALIVE(VisitForValue(expr->expression()));
5468 return ast_context()->ReturnInstruction(call, expr->id()); 5526 HValue* function = Top();
5527 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5528 Handle<JSFunction> constructor = expr->target();
5529 AddInstruction(new(zone()) HCheckFunction(function, constructor));
5530
5531 // Replace the constructor function with a newly allocated receiver.
5532 HInstruction* receiver = new(zone()) HAllocateObject(context, constructor);
5533 // Index of the receiver from the top of the expression stack.
5534 const int receiver_index = argument_count - 1;
5535 AddInstruction(receiver);
5536 ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
5537 environment()->SetExpressionStackAt(receiver_index, receiver);
5538
5539 if (TryInlineConstruct(expr, receiver)) return;
5540
5541 // TODO(mstarzinger): For now we remove the previous HAllocateObject and
5542 // add HPushArgument for the arguments in case inlining failed. What we
5543 // actually should do is emit HInvokeFunction on the constructor instead
5544 // of using HCallNew as a fallback.
5545 receiver->DeleteAndReplaceWith(NULL);
5546 environment()->SetExpressionStackAt(receiver_index, function);
5547 HInstruction* call = PreProcessCall(
5548 new(zone()) HCallNew(context, function, argument_count));
5549 call->set_position(expr->position());
5550 return ast_context()->ReturnInstruction(call, expr->id());
5551 } else {
5552 // The constructor function is both an operand to the instruction and an
5553 // argument to the construct call.
5554 HValue* constructor = NULL;
5555 CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
5556 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5557 HInstruction* call =
5558 new(zone()) HCallNew(context, constructor, argument_count);
5559 Drop(argument_count);
5560 call->set_position(expr->position());
5561 return ast_context()->ReturnInstruction(call, expr->id());
5562 }
5469 } 5563 }
5470 5564
5471 5565
5472 // Support for generating inlined runtime functions. 5566 // Support for generating inlined runtime functions.
5473 5567
5474 // Lookup table for generators for runtime calls that are generated inline. 5568 // Lookup table for generators for runtime calls that are generated inline.
5475 // Elements of the table are member pointers to functions of HGraphBuilder. 5569 // Elements of the table are member pointers to functions of HGraphBuilder.
5476 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 5570 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
5477 &HGraphBuilder::Generate##Name, 5571 &HGraphBuilder::Generate##Name,
5478 5572
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after
6503 CallRuntime* call) { 6597 CallRuntime* call) {
6504 return Bailout( 6598 return Bailout(
6505 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 6599 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
6506 } 6600 }
6507 6601
6508 6602
6509 // Support for construct call checks. 6603 // Support for construct call checks.
6510 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 6604 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
6511 ASSERT(call->arguments()->length() == 0); 6605 ASSERT(call->arguments()->length() == 0);
6512 if (function_state()->outer() != NULL) { 6606 if (function_state()->outer() != NULL) {
6513 // We are generating graph for inlined function. Currently 6607 // We are generating graph for inlined function.
6514 // constructor inlining is not supported and we can just return 6608 HValue* value = function_state()->is_construct()
6515 // false from %_IsConstructCall(). 6609 ? graph()->GetConstantTrue()
6516 return ast_context()->ReturnValue(graph()->GetConstantFalse()); 6610 : graph()->GetConstantFalse();
6611 return ast_context()->ReturnValue(value);
6517 } else { 6612 } else {
6518 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 6613 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
6519 call->id()); 6614 call->id());
6520 } 6615 }
6521 } 6616 }
6522 6617
6523 6618
6524 // Support for arguments.length and arguments[?]. 6619 // Support for arguments.length and arguments[?].
6525 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 6620 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
6526 // Our implementation of arguments (based on this stack frame or an 6621 // Our implementation of arguments (based on this stack frame or an
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
6894 #undef CHECK_BAILOUT 6989 #undef CHECK_BAILOUT
6895 #undef CHECK_ALIVE 6990 #undef CHECK_ALIVE
6896 6991
6897 6992
6898 HEnvironment::HEnvironment(HEnvironment* outer, 6993 HEnvironment::HEnvironment(HEnvironment* outer,
6899 Scope* scope, 6994 Scope* scope,
6900 Handle<JSFunction> closure) 6995 Handle<JSFunction> closure)
6901 : closure_(closure), 6996 : closure_(closure),
6902 values_(0), 6997 values_(0),
6903 assigned_variables_(4), 6998 assigned_variables_(4),
6999 frame_type_(JS_FUNCTION),
6904 parameter_count_(0), 7000 parameter_count_(0),
6905 specials_count_(1), 7001 specials_count_(1),
6906 local_count_(0), 7002 local_count_(0),
6907 outer_(outer), 7003 outer_(outer),
6908 pop_count_(0), 7004 pop_count_(0),
6909 push_count_(0), 7005 push_count_(0),
6910 ast_id_(AstNode::kNoNumber), 7006 ast_id_(AstNode::kNoNumber) {
6911 arguments_adaptor_(false) {
6912 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 7007 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
6913 } 7008 }
6914 7009
6915 7010
6916 HEnvironment::HEnvironment(const HEnvironment* other) 7011 HEnvironment::HEnvironment(const HEnvironment* other)
6917 : values_(0), 7012 : values_(0),
6918 assigned_variables_(0), 7013 assigned_variables_(0),
7014 frame_type_(JS_FUNCTION),
6919 parameter_count_(0), 7015 parameter_count_(0),
6920 specials_count_(1), 7016 specials_count_(1),
6921 local_count_(0), 7017 local_count_(0),
6922 outer_(NULL), 7018 outer_(NULL),
6923 pop_count_(0), 7019 pop_count_(0),
6924 push_count_(0), 7020 push_count_(0),
6925 ast_id_(other->ast_id()), 7021 ast_id_(other->ast_id()) {
6926 arguments_adaptor_(false) {
6927 Initialize(other); 7022 Initialize(other);
6928 } 7023 }
6929 7024
6930 7025
6931 HEnvironment::HEnvironment(HEnvironment* outer, 7026 HEnvironment::HEnvironment(HEnvironment* outer,
6932 Handle<JSFunction> closure, 7027 Handle<JSFunction> closure,
7028 FrameType frame_type,
6933 int arguments) 7029 int arguments)
6934 : closure_(closure), 7030 : closure_(closure),
6935 values_(arguments), 7031 values_(arguments),
6936 assigned_variables_(0), 7032 assigned_variables_(0),
7033 frame_type_(frame_type),
6937 parameter_count_(arguments), 7034 parameter_count_(arguments),
6938 local_count_(0), 7035 local_count_(0),
6939 outer_(outer), 7036 outer_(outer),
6940 pop_count_(0), 7037 pop_count_(0),
6941 push_count_(0), 7038 push_count_(0),
6942 ast_id_(AstNode::kNoNumber), 7039 ast_id_(AstNode::kNoNumber) {
6943 arguments_adaptor_(true) {
6944 } 7040 }
6945 7041
6946 7042
6947 void HEnvironment::Initialize(int parameter_count, 7043 void HEnvironment::Initialize(int parameter_count,
6948 int local_count, 7044 int local_count,
6949 int stack_height) { 7045 int stack_height) {
6950 parameter_count_ = parameter_count; 7046 parameter_count_ = parameter_count;
6951 local_count_ = local_count; 7047 local_count_ = local_count;
6952 7048
6953 // Avoid reallocating the temporaries' backing store on the first Push. 7049 // Avoid reallocating the temporaries' backing store on the first Push.
6954 int total = parameter_count + specials_count_ + local_count + stack_height; 7050 int total = parameter_count + specials_count_ + local_count + stack_height;
6955 values_.Initialize(total + 4); 7051 values_.Initialize(total + 4);
6956 for (int i = 0; i < total; ++i) values_.Add(NULL); 7052 for (int i = 0; i < total; ++i) values_.Add(NULL);
6957 } 7053 }
6958 7054
6959 7055
6960 void HEnvironment::Initialize(const HEnvironment* other) { 7056 void HEnvironment::Initialize(const HEnvironment* other) {
6961 closure_ = other->closure(); 7057 closure_ = other->closure();
6962 values_.AddAll(other->values_); 7058 values_.AddAll(other->values_);
6963 assigned_variables_.AddAll(other->assigned_variables_); 7059 assigned_variables_.AddAll(other->assigned_variables_);
7060 frame_type_ = other->frame_type_;
6964 parameter_count_ = other->parameter_count_; 7061 parameter_count_ = other->parameter_count_;
6965 local_count_ = other->local_count_; 7062 local_count_ = other->local_count_;
6966 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 7063 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy.
6967 pop_count_ = other->pop_count_; 7064 pop_count_ = other->pop_count_;
6968 push_count_ = other->push_count_; 7065 push_count_ = other->push_count_;
6969 ast_id_ = other->ast_id_; 7066 ast_id_ = other->ast_id_;
6970 arguments_adaptor_ = other->arguments_adaptor_;
6971 } 7067 }
6972 7068
6973 7069
6974 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 7070 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
6975 ASSERT(!block->IsLoopHeader()); 7071 ASSERT(!block->IsLoopHeader());
6976 ASSERT(values_.length() == other->values_.length()); 7072 ASSERT(values_.length() == other->values_.length());
6977 7073
6978 int length = values_.length(); 7074 int length = values_.length();
6979 for (int i = 0; i < length; ++i) { 7075 for (int i = 0; i < length; ++i) {
6980 HValue* value = values_[i]; 7076 HValue* value = values_[i];
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
7062 HPhi* phi = new(loop_header->zone()) HPhi(i); 7158 HPhi* phi = new(loop_header->zone()) HPhi(i);
7063 phi->AddInput(values_[i]); 7159 phi->AddInput(values_[i]);
7064 new_env->values_[i] = phi; 7160 new_env->values_[i] = phi;
7065 loop_header->AddPhi(phi); 7161 loop_header->AddPhi(phi);
7066 } 7162 }
7067 new_env->ClearHistory(); 7163 new_env->ClearHistory();
7068 return new_env; 7164 return new_env;
7069 } 7165 }
7070 7166
7071 7167
7168 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
7169 Handle<JSFunction> target,
7170 FrameType frame_type,
7171 int arguments) const {
7172 HEnvironment* new_env = new(closure()->GetIsolate()->zone())
7173 HEnvironment(outer, target, frame_type, arguments + 1);
7174 for (int i = 0; i <= arguments; ++i) { // Include receiver.
7175 new_env->Push(ExpressionStackAt(arguments - i));
7176 }
7177 new_env->ClearHistory();
7178 return new_env;
7179 }
7180
7181
7072 HEnvironment* HEnvironment::CopyForInlining( 7182 HEnvironment* HEnvironment::CopyForInlining(
7073 Handle<JSFunction> target, 7183 Handle<JSFunction> target,
7074 int arguments, 7184 int arguments,
7075 FunctionLiteral* function, 7185 FunctionLiteral* function,
7076 HConstant* undefined, 7186 HConstant* undefined,
7077 CallKind call_kind) const { 7187 CallKind call_kind,
7078 ASSERT(!is_arguments_adaptor()); 7188 bool is_construct) const {
7189 ASSERT(frame_type() == JS_FUNCTION);
7079 7190
7080 Zone* zone = closure()->GetIsolate()->zone(); 7191 Zone* zone = closure()->GetIsolate()->zone();
7081 7192
7082 // Outer environment is a copy of this one without the arguments. 7193 // Outer environment is a copy of this one without the arguments.
7083 int arity = function->scope()->num_parameters(); 7194 int arity = function->scope()->num_parameters();
7084 7195
7085 HEnvironment* outer = Copy(); 7196 HEnvironment* outer = Copy();
7086 outer->Drop(arguments + 1); // Including receiver. 7197 outer->Drop(arguments + 1); // Including receiver.
7087 outer->ClearHistory(); 7198 outer->ClearHistory();
7088 7199
7200 if (is_construct) {
7201 // Create artificial constructor stub environment. The receiver should
7202 // actually be the constructor function, but we pass the newly allocated
7203 // object instead, DoComputeConstructStubFrame() relies on that.
7204 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
7205 }
7206
7089 if (arity != arguments) { 7207 if (arity != arguments) {
7090 // Create artificial arguments adaptation environment. 7208 // Create artificial arguments adaptation environment.
7091 outer = new(zone) HEnvironment(outer, target, arguments + 1); 7209 outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
7092 for (int i = 0; i <= arguments; ++i) { // Include receiver.
7093 outer->Push(ExpressionStackAt(arguments - i));
7094 }
7095 outer->ClearHistory();
7096 } 7210 }
7097 7211
7098 HEnvironment* inner = 7212 HEnvironment* inner =
7099 new(zone) HEnvironment(outer, function->scope(), target); 7213 new(zone) HEnvironment(outer, function->scope(), target);
7100 // Get the argument values from the original environment. 7214 // Get the argument values from the original environment.
7101 for (int i = 0; i <= arity; ++i) { // Include receiver. 7215 for (int i = 0; i <= arity; ++i) { // Include receiver.
7102 HValue* push = (i <= arguments) ? 7216 HValue* push = (i <= arguments) ?
7103 ExpressionStackAt(arguments - i) : undefined; 7217 ExpressionStackAt(arguments - i) : undefined;
7104 inner->SetValueAt(i, push); 7218 inner->SetValueAt(i, push);
7105 } 7219 }
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
7453 } 7567 }
7454 } 7568 }
7455 7569
7456 #ifdef DEBUG 7570 #ifdef DEBUG
7457 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7571 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7458 if (allocator_ != NULL) allocator_->Verify(); 7572 if (allocator_ != NULL) allocator_->Verify();
7459 #endif 7573 #endif
7460 } 7574 }
7461 7575
7462 } } // namespace v8::internal 7576 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698