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

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 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
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 554 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 int count = expr->arguments()->length();
5547 ZoneList<HValue*> arguments(count);
5548 for (int i = 0; i < count; ++i) {
5549 arguments.Add(Pop());
5550 }
5551 Pop();
Vyacheslav Egorov (Chromium) 2012/02/27 15:06:02 I think we can replace receiver with function with
Michael Starzinger 2012/02/28 09:07:10 Done. Made PreProcessCall more templatey.
5552 AddInstruction(new(zone()) HPushArgument(function));
5553 while (!arguments.is_empty()) {
5554 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
5555 }
5556 HInstruction* call =
5557 new(zone()) HCallNew(context, function, argument_count);
5558 call->set_position(expr->position());
5559 return ast_context()->ReturnInstruction(call, expr->id());
5560 } else {
5561 // The constructor function is both an operand to the instruction and an
5562 // argument to the construct call.
5563 HValue* constructor = NULL;
5564 CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
5565 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5566 HInstruction* call =
5567 new(zone()) HCallNew(context, constructor, argument_count);
5568 Drop(argument_count);
5569 call->set_position(expr->position());
5570 return ast_context()->ReturnInstruction(call, expr->id());
5571 }
5469 } 5572 }
5470 5573
5471 5574
5472 // Support for generating inlined runtime functions. 5575 // Support for generating inlined runtime functions.
5473 5576
5474 // Lookup table for generators for runtime calls that are generated inline. 5577 // Lookup table for generators for runtime calls that are generated inline.
5475 // Elements of the table are member pointers to functions of HGraphBuilder. 5578 // Elements of the table are member pointers to functions of HGraphBuilder.
5476 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 5579 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
5477 &HGraphBuilder::Generate##Name, 5580 &HGraphBuilder::Generate##Name,
5478 5581
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after
6503 CallRuntime* call) { 6606 CallRuntime* call) {
6504 return Bailout( 6607 return Bailout(
6505 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 6608 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
6506 } 6609 }
6507 6610
6508 6611
6509 // Support for construct call checks. 6612 // Support for construct call checks.
6510 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 6613 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
6511 ASSERT(call->arguments()->length() == 0); 6614 ASSERT(call->arguments()->length() == 0);
6512 if (function_state()->outer() != NULL) { 6615 if (function_state()->outer() != NULL) {
6513 // We are generating graph for inlined function. Currently 6616 // We are generating graph for inlined function.
6514 // constructor inlining is not supported and we can just return 6617 HValue* value = function_state()->is_construct()
6515 // false from %_IsConstructCall(). 6618 ? graph()->GetConstantTrue()
6516 return ast_context()->ReturnValue(graph()->GetConstantFalse()); 6619 : graph()->GetConstantFalse();
6620 return ast_context()->ReturnValue(value);
6517 } else { 6621 } else {
6518 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 6622 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
6519 call->id()); 6623 call->id());
6520 } 6624 }
6521 } 6625 }
6522 6626
6523 6627
6524 // Support for arguments.length and arguments[?]. 6628 // Support for arguments.length and arguments[?].
6525 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 6629 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
6526 // Our implementation of arguments (based on this stack frame or an 6630 // 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 6998 #undef CHECK_BAILOUT
6895 #undef CHECK_ALIVE 6999 #undef CHECK_ALIVE
6896 7000
6897 7001
6898 HEnvironment::HEnvironment(HEnvironment* outer, 7002 HEnvironment::HEnvironment(HEnvironment* outer,
6899 Scope* scope, 7003 Scope* scope,
6900 Handle<JSFunction> closure) 7004 Handle<JSFunction> closure)
6901 : closure_(closure), 7005 : closure_(closure),
6902 values_(0), 7006 values_(0),
6903 assigned_variables_(4), 7007 assigned_variables_(4),
7008 frame_type_(JS_FUNCTION),
6904 parameter_count_(0), 7009 parameter_count_(0),
6905 specials_count_(1), 7010 specials_count_(1),
6906 local_count_(0), 7011 local_count_(0),
6907 outer_(outer), 7012 outer_(outer),
6908 pop_count_(0), 7013 pop_count_(0),
6909 push_count_(0), 7014 push_count_(0),
6910 ast_id_(AstNode::kNoNumber), 7015 ast_id_(AstNode::kNoNumber) {
6911 arguments_adaptor_(false) {
6912 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 7016 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
6913 } 7017 }
6914 7018
6915 7019
6916 HEnvironment::HEnvironment(const HEnvironment* other) 7020 HEnvironment::HEnvironment(const HEnvironment* other)
6917 : values_(0), 7021 : values_(0),
6918 assigned_variables_(0), 7022 assigned_variables_(0),
7023 frame_type_(JS_FUNCTION),
6919 parameter_count_(0), 7024 parameter_count_(0),
6920 specials_count_(1), 7025 specials_count_(1),
6921 local_count_(0), 7026 local_count_(0),
6922 outer_(NULL), 7027 outer_(NULL),
6923 pop_count_(0), 7028 pop_count_(0),
6924 push_count_(0), 7029 push_count_(0),
6925 ast_id_(other->ast_id()), 7030 ast_id_(other->ast_id()) {
6926 arguments_adaptor_(false) {
6927 Initialize(other); 7031 Initialize(other);
6928 } 7032 }
6929 7033
6930 7034
6931 HEnvironment::HEnvironment(HEnvironment* outer, 7035 HEnvironment::HEnvironment(HEnvironment* outer,
6932 Handle<JSFunction> closure, 7036 Handle<JSFunction> closure,
7037 FrameType frame_type,
6933 int arguments) 7038 int arguments)
6934 : closure_(closure), 7039 : closure_(closure),
6935 values_(arguments), 7040 values_(arguments),
6936 assigned_variables_(0), 7041 assigned_variables_(0),
7042 frame_type_(frame_type),
6937 parameter_count_(arguments), 7043 parameter_count_(arguments),
6938 local_count_(0), 7044 local_count_(0),
6939 outer_(outer), 7045 outer_(outer),
6940 pop_count_(0), 7046 pop_count_(0),
6941 push_count_(0), 7047 push_count_(0),
6942 ast_id_(AstNode::kNoNumber), 7048 ast_id_(AstNode::kNoNumber) {
6943 arguments_adaptor_(true) {
6944 } 7049 }
6945 7050
6946 7051
6947 void HEnvironment::Initialize(int parameter_count, 7052 void HEnvironment::Initialize(int parameter_count,
6948 int local_count, 7053 int local_count,
6949 int stack_height) { 7054 int stack_height) {
6950 parameter_count_ = parameter_count; 7055 parameter_count_ = parameter_count;
6951 local_count_ = local_count; 7056 local_count_ = local_count;
6952 7057
6953 // Avoid reallocating the temporaries' backing store on the first Push. 7058 // Avoid reallocating the temporaries' backing store on the first Push.
6954 int total = parameter_count + specials_count_ + local_count + stack_height; 7059 int total = parameter_count + specials_count_ + local_count + stack_height;
6955 values_.Initialize(total + 4); 7060 values_.Initialize(total + 4);
6956 for (int i = 0; i < total; ++i) values_.Add(NULL); 7061 for (int i = 0; i < total; ++i) values_.Add(NULL);
6957 } 7062 }
6958 7063
6959 7064
6960 void HEnvironment::Initialize(const HEnvironment* other) { 7065 void HEnvironment::Initialize(const HEnvironment* other) {
6961 closure_ = other->closure(); 7066 closure_ = other->closure();
6962 values_.AddAll(other->values_); 7067 values_.AddAll(other->values_);
6963 assigned_variables_.AddAll(other->assigned_variables_); 7068 assigned_variables_.AddAll(other->assigned_variables_);
7069 frame_type_ = other->frame_type_;
6964 parameter_count_ = other->parameter_count_; 7070 parameter_count_ = other->parameter_count_;
6965 local_count_ = other->local_count_; 7071 local_count_ = other->local_count_;
6966 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 7072 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy.
6967 pop_count_ = other->pop_count_; 7073 pop_count_ = other->pop_count_;
6968 push_count_ = other->push_count_; 7074 push_count_ = other->push_count_;
6969 ast_id_ = other->ast_id_; 7075 ast_id_ = other->ast_id_;
6970 arguments_adaptor_ = other->arguments_adaptor_;
6971 } 7076 }
6972 7077
6973 7078
6974 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 7079 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
6975 ASSERT(!block->IsLoopHeader()); 7080 ASSERT(!block->IsLoopHeader());
6976 ASSERT(values_.length() == other->values_.length()); 7081 ASSERT(values_.length() == other->values_.length());
6977 7082
6978 int length = values_.length(); 7083 int length = values_.length();
6979 for (int i = 0; i < length; ++i) { 7084 for (int i = 0; i < length; ++i) {
6980 HValue* value = values_[i]; 7085 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); 7167 HPhi* phi = new(loop_header->zone()) HPhi(i);
7063 phi->AddInput(values_[i]); 7168 phi->AddInput(values_[i]);
7064 new_env->values_[i] = phi; 7169 new_env->values_[i] = phi;
7065 loop_header->AddPhi(phi); 7170 loop_header->AddPhi(phi);
7066 } 7171 }
7067 new_env->ClearHistory(); 7172 new_env->ClearHistory();
7068 return new_env; 7173 return new_env;
7069 } 7174 }
7070 7175
7071 7176
7177 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
7178 Handle<JSFunction> target,
7179 FrameType frame_type,
7180 int arguments) const {
7181 HEnvironment* new_env = new(closure()->GetIsolate()->zone())
7182 HEnvironment(outer, target, frame_type, arguments + 1);
7183 for (int i = 0; i <= arguments; ++i) { // Include receiver.
7184 new_env->Push(ExpressionStackAt(arguments - i));
7185 }
7186 new_env->ClearHistory();
7187 return new_env;
7188 }
7189
7190
7072 HEnvironment* HEnvironment::CopyForInlining( 7191 HEnvironment* HEnvironment::CopyForInlining(
7073 Handle<JSFunction> target, 7192 Handle<JSFunction> target,
7074 int arguments, 7193 int arguments,
7075 FunctionLiteral* function, 7194 FunctionLiteral* function,
7076 HConstant* undefined, 7195 HConstant* undefined,
7077 CallKind call_kind) const { 7196 CallKind call_kind,
7078 ASSERT(!is_arguments_adaptor()); 7197 bool is_construct) const {
7198 ASSERT(frame_type() == JS_FUNCTION);
7079 7199
7080 Zone* zone = closure()->GetIsolate()->zone(); 7200 Zone* zone = closure()->GetIsolate()->zone();
7081 7201
7082 // Outer environment is a copy of this one without the arguments. 7202 // Outer environment is a copy of this one without the arguments.
7083 int arity = function->scope()->num_parameters(); 7203 int arity = function->scope()->num_parameters();
7084 7204
7085 HEnvironment* outer = Copy(); 7205 HEnvironment* outer = Copy();
7086 outer->Drop(arguments + 1); // Including receiver. 7206 outer->Drop(arguments + 1); // Including receiver.
7087 outer->ClearHistory(); 7207 outer->ClearHistory();
7088 7208
7209 if (is_construct) {
7210 // Create artificial constructor stub environment. The receiver should
7211 // actually be the constructor function, but we pass the newly allocated
7212 // object instead, DoComputeConstructStubFrame() relies on that.
7213 outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
7214 }
7215
7089 if (arity != arguments) { 7216 if (arity != arguments) {
7090 // Create artificial arguments adaptation environment. 7217 // Create artificial arguments adaptation environment.
7091 outer = new(zone) HEnvironment(outer, target, arguments + 1); 7218 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 } 7219 }
7097 7220
7098 HEnvironment* inner = 7221 HEnvironment* inner =
7099 new(zone) HEnvironment(outer, function->scope(), target); 7222 new(zone) HEnvironment(outer, function->scope(), target);
7100 // Get the argument values from the original environment. 7223 // Get the argument values from the original environment.
7101 for (int i = 0; i <= arity; ++i) { // Include receiver. 7224 for (int i = 0; i <= arity; ++i) { // Include receiver.
7102 HValue* push = (i <= arguments) ? 7225 HValue* push = (i <= arguments) ?
7103 ExpressionStackAt(arguments - i) : undefined; 7226 ExpressionStackAt(arguments - i) : undefined;
7104 inner->SetValueAt(i, push); 7227 inner->SetValueAt(i, push);
7105 } 7228 }
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
7453 } 7576 }
7454 } 7577 }
7455 7578
7456 #ifdef DEBUG 7579 #ifdef DEBUG
7457 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7580 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7458 if (allocator_ != NULL) allocator_->Verify(); 7581 if (allocator_ != NULL) allocator_->Verify();
7459 #endif 7582 #endif
7460 } 7583 }
7461 7584
7462 } } // namespace v8::internal 7585 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/mips/lithium-codegen-mips.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698