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

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: Ported deoptimizer to x64 and ARM. Created 8 years, 10 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, false, false),
Vyacheslav Egorov (Chromium) 2012/02/13 15:01:39 I think we should come up with enum at least for i
Michael Starzinger 2012/02/27 14:16:32 Done. Merged drop_extra and is_construct into one
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 bool drop_extra,
2030 bool is_construct)
2030 : owner_(owner), 2031 : owner_(owner),
2031 compilation_info_(info), 2032 compilation_info_(info),
2032 oracle_(oracle), 2033 oracle_(oracle),
2033 call_context_(NULL), 2034 call_context_(NULL),
2034 drop_extra_(drop_extra), 2035 drop_extra_(drop_extra),
2036 is_construct_(is_construct),
2035 function_return_(NULL), 2037 function_return_(NULL),
2036 test_context_(NULL), 2038 test_context_(NULL),
2037 outer_(owner->function_state()) { 2039 outer_(owner->function_state()) {
2038 if (outer_ != NULL) { 2040 if (outer_ != NULL) {
2039 // State for an inline function. 2041 // State for an inline function.
2040 if (owner->ast_context()->IsTest()) { 2042 if (owner->ast_context()->IsTest()) {
2041 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2043 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2042 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2044 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2043 if_true->MarkAsInlineReturnTarget(); 2045 if_true->MarkAsInlineReturnTarget();
2044 if_false->MarkAsInlineReturnTarget(); 2046 if_false->MarkAsInlineReturnTarget();
(...skipping 22 matching lines...) Expand all
2067 2069
2068 // Implementation of utility classes to represent an expression's context in 2070 // Implementation of utility classes to represent an expression's context in
2069 // the AST. 2071 // the AST.
2070 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 2072 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
2071 : owner_(owner), 2073 : owner_(owner),
2072 kind_(kind), 2074 kind_(kind),
2073 outer_(owner->ast_context()), 2075 outer_(owner->ast_context()),
2074 for_typeof_(false) { 2076 for_typeof_(false) {
2075 owner->set_ast_context(this); // Push. 2077 owner->set_ast_context(this); // Push.
2076 #ifdef DEBUG 2078 #ifdef DEBUG
2077 ASSERT(!owner->environment()->is_arguments_adaptor()); 2079 ASSERT(owner->environment()->frame_type() == JS_FUNCTION);
2078 original_length_ = owner->environment()->length(); 2080 original_length_ = owner->environment()->length();
2079 #endif 2081 #endif
2080 } 2082 }
2081 2083
2082 2084
2083 AstContext::~AstContext() { 2085 AstContext::~AstContext() {
2084 owner_->set_ast_context(outer_); // Pop. 2086 owner_->set_ast_context(outer_); // Pop.
2085 } 2087 }
2086 2088
2087 2089
2088 EffectContext::~EffectContext() { 2090 EffectContext::~EffectContext() {
2089 ASSERT(owner()->HasStackOverflow() || 2091 ASSERT(owner()->HasStackOverflow() ||
2090 owner()->current_block() == NULL || 2092 owner()->current_block() == NULL ||
2091 (owner()->environment()->length() == original_length_ && 2093 (owner()->environment()->length() == original_length_ &&
2092 !owner()->environment()->is_arguments_adaptor())); 2094 owner()->environment()->frame_type() == JS_FUNCTION));
2093 } 2095 }
2094 2096
2095 2097
2096 ValueContext::~ValueContext() { 2098 ValueContext::~ValueContext() {
2097 ASSERT(owner()->HasStackOverflow() || 2099 ASSERT(owner()->HasStackOverflow() ||
2098 owner()->current_block() == NULL || 2100 owner()->current_block() == NULL ||
2099 (owner()->environment()->length() == original_length_ + 1 && 2101 (owner()->environment()->length() == original_length_ + 1 &&
2100 !owner()->environment()->is_arguments_adaptor())); 2102 owner()->environment()->frame_type() == JS_FUNCTION));
2101 } 2103 }
2102 2104
2103 2105
2104 void EffectContext::ReturnValue(HValue* value) { 2106 void EffectContext::ReturnValue(HValue* value) {
2105 // The value is simply ignored. 2107 // The value is simply ignored.
2106 } 2108 }
2107 2109
2108 2110
2109 void ValueContext::ReturnValue(HValue* value) { 2111 void ValueContext::ReturnValue(HValue* value) {
2110 // The value is tracked in the bailout environment, and communicated 2112 // 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) { 2667 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2666 ASSERT(!HasStackOverflow()); 2668 ASSERT(!HasStackOverflow());
2667 ASSERT(current_block() != NULL); 2669 ASSERT(current_block() != NULL);
2668 ASSERT(current_block()->HasPredecessor()); 2670 ASSERT(current_block()->HasPredecessor());
2669 AstContext* context = call_context(); 2671 AstContext* context = call_context();
2670 if (context == NULL) { 2672 if (context == NULL) {
2671 // Not an inlined return, so an actual one. 2673 // Not an inlined return, so an actual one.
2672 CHECK_ALIVE(VisitForValue(stmt->expression())); 2674 CHECK_ALIVE(VisitForValue(stmt->expression()));
2673 HValue* result = environment()->Pop(); 2675 HValue* result = environment()->Pop();
2674 current_block()->FinishExit(new(zone()) HReturn(result)); 2676 current_block()->FinishExit(new(zone()) HReturn(result));
2675 set_current_block(NULL); 2677 } else if (function_state()->is_construct()) {
2678 // Return from an inlined construct call. In a test context the return
2679 // value will always evaluate to true, in a value context the return value
2680 // needs to be a JSObject.
2681 if (context->IsTest()) {
2682 TestContext* test = TestContext::cast(context);
2683 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2684 current_block()->Goto(test->if_true(), function_state()->drop_extra());
2685 } else if (context->IsEffect()) {
2686 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2687 current_block()->Goto(function_return(), function_state()->drop_extra());
2688 } else {
2689 ASSERT(context->IsValue());
2690 CHECK_ALIVE(VisitForValue(stmt->expression()));
2691 HValue* return_value = Pop();
2692 HValue* receiver = environment()->Lookup(0);
2693 HHasInstanceTypeAndBranch* typecheck =
2694 new(zone()) HHasInstanceTypeAndBranch(return_value,
2695 FIRST_SPEC_OBJECT_TYPE,
2696 LAST_SPEC_OBJECT_TYPE);
2697 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
2698 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
2699 typecheck->SetSuccessorAt(0, if_spec_object);
2700 typecheck->SetSuccessorAt(1, not_spec_object);
2701 current_block()->Finish(typecheck);
2702 if_spec_object->AddLeaveInlined(return_value,
2703 function_return(),
2704 function_state()->drop_extra());
2705 not_spec_object->AddLeaveInlined(receiver,
2706 function_return(),
2707 function_state()->drop_extra());
2708 }
2676 } else { 2709 } else {
2677 // Return from an inlined function, visit the subexpression in the 2710 // Return from an inlined function, visit the subexpression in the
2678 // expression context of the call. 2711 // expression context of the call.
2679 if (context->IsTest()) { 2712 if (context->IsTest()) {
2680 TestContext* test = TestContext::cast(context); 2713 TestContext* test = TestContext::cast(context);
2681 VisitForControl(stmt->expression(), 2714 VisitForControl(stmt->expression(),
2682 test->if_true(), 2715 test->if_true(),
2683 test->if_false()); 2716 test->if_false());
2684 } else if (context->IsEffect()) { 2717 } else if (context->IsEffect()) {
2685 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2718 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2686 current_block()->Goto(function_return(), function_state()->drop_extra()); 2719 current_block()->Goto(function_return(), function_state()->drop_extra());
2687 } else { 2720 } else {
2688 ASSERT(context->IsValue()); 2721 ASSERT(context->IsValue());
2689 CHECK_ALIVE(VisitForValue(stmt->expression())); 2722 CHECK_ALIVE(VisitForValue(stmt->expression()));
2690 HValue* return_value = environment()->Pop(); 2723 HValue* return_value = Pop();
2691 current_block()->AddLeaveInlined(return_value, 2724 current_block()->AddLeaveInlined(return_value,
2692 function_return(), 2725 function_return(),
2693 function_state()->drop_extra()); 2726 function_state()->drop_extra());
2694 } 2727 }
2695 set_current_block(NULL);
2696 } 2728 }
2729 set_current_block(NULL);
2697 } 2730 }
2698 2731
2699 2732
2700 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2733 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2701 ASSERT(!HasStackOverflow()); 2734 ASSERT(!HasStackOverflow());
2702 ASSERT(current_block() != NULL); 2735 ASSERT(current_block() != NULL);
2703 ASSERT(current_block()->HasPredecessor()); 2736 ASSERT(current_block()->HasPredecessor());
2704 return Bailout("WithStatement"); 2737 return Bailout("WithStatement");
2705 } 2738 }
2706 2739
(...skipping 1997 matching lines...) Expand 10 before | Expand all | Expand 10 after
4704 HCompareMap* compare = 4737 HCompareMap* compare =
4705 new(zone()) HCompareMap(receiver, map, if_true, if_false); 4738 new(zone()) HCompareMap(receiver, map, if_true, if_false);
4706 current_block()->Finish(compare); 4739 current_block()->Finish(compare);
4707 4740
4708 set_current_block(if_true); 4741 set_current_block(if_true);
4709 AddCheckConstantFunction(expr, receiver, map, false); 4742 AddCheckConstantFunction(expr, receiver, map, false);
4710 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 4743 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
4711 PrintF("Trying to inline the polymorphic call to %s\n", 4744 PrintF("Trying to inline the polymorphic call to %s\n",
4712 *name->ToCString()); 4745 *name->ToCString());
4713 } 4746 }
4714 if (FLAG_polymorphic_inlining && TryInline(expr)) { 4747 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
4715 // Trying to inline will signal that we should bailout from the 4748 // Trying to inline will signal that we should bailout from the
4716 // entire compilation by setting stack overflow on the visitor. 4749 // entire compilation by setting stack overflow on the visitor.
4717 if (HasStackOverflow()) return; 4750 if (HasStackOverflow()) return;
4718 } else { 4751 } else {
4719 HCallConstantFunction* call = 4752 HCallConstantFunction* call =
4720 new(zone()) HCallConstantFunction(expr->target(), argument_count); 4753 new(zone()) HCallConstantFunction(expr->target(), argument_count);
4721 call->set_position(expr->position()); 4754 call->set_position(expr->position());
4722 PreProcessCall(call); 4755 PreProcessCall(call);
4723 AddInstruction(call); 4756 AddInstruction(call);
4724 if (!ast_context()->IsEffect()) Push(call); 4757 if (!ast_context()->IsEffect()) Push(call);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4774 if (reason == NULL) { 4807 if (reason == NULL) {
4775 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 4808 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
4776 } else { 4809 } else {
4777 PrintF("Did not inline %s called from %s (%s).\n", 4810 PrintF("Did not inline %s called from %s (%s).\n",
4778 *target_name, *caller_name, reason); 4811 *target_name, *caller_name, reason);
4779 } 4812 }
4780 } 4813 }
4781 } 4814 }
4782 4815
4783 4816
4784 bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) { 4817 bool HGraphBuilder::TryInline(CallKind call_kind,
4818 Handle<JSFunction> target,
4819 ZoneList<Expression*>* arguments,
4820 HValue* receiver,
4821 int ast_id,
4822 int return_id,
4823 bool drop_extra,
Vyacheslav Egorov (Chromium) 2012/02/13 15:01:39 Consider introducing enums
Michael Starzinger 2012/02/27 14:16:32 Done. Merged drop_extra and is_construct into one
4824 bool is_construct) {
4785 if (!FLAG_use_inlining) return false; 4825 if (!FLAG_use_inlining) return false;
4786 4826
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 4827 // Precondition: call is monomorphic and we have found a target with the
4794 // appropriate arity. 4828 // appropriate arity.
4795 Handle<JSFunction> caller = info()->closure(); 4829 Handle<JSFunction> caller = info()->closure();
4796 Handle<JSFunction> target = expr->target();
4797 Handle<SharedFunctionInfo> target_shared(target->shared()); 4830 Handle<SharedFunctionInfo> target_shared(target->shared());
4798 4831
4799 // Do a quick check on source code length to avoid parsing large 4832 // Do a quick check on source code length to avoid parsing large
4800 // inlining candidates. 4833 // inlining candidates.
4801 if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) 4834 if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize)
4802 || target->shared()->SourceSize() > kUnlimitedMaxSourceSize) { 4835 || target->shared()->SourceSize() > kUnlimitedMaxSourceSize) {
4803 TraceInline(target, caller, "target text too big"); 4836 TraceInline(target, caller, "target text too big");
4804 return false; 4837 return false;
4805 } 4838 }
4806 4839
(...skipping 16 matching lines...) Expand all
4823 4856
4824 4857
4825 // Don't inline deeper than kMaxInliningLevels calls. 4858 // Don't inline deeper than kMaxInliningLevels calls.
4826 HEnvironment* env = environment(); 4859 HEnvironment* env = environment();
4827 int current_level = 1; 4860 int current_level = 1;
4828 while (env->outer() != NULL) { 4861 while (env->outer() != NULL) {
4829 if (current_level == Compiler::kMaxInliningLevels) { 4862 if (current_level == Compiler::kMaxInliningLevels) {
4830 TraceInline(target, caller, "inline depth limit reached"); 4863 TraceInline(target, caller, "inline depth limit reached");
4831 return false; 4864 return false;
4832 } 4865 }
4833 if (!env->outer()->is_arguments_adaptor()) { 4866 if (env->outer()->frame_type() == JS_FUNCTION) {
4834 current_level++; 4867 current_level++;
4835 } 4868 }
4836 env = env->outer(); 4869 env = env->outer();
4837 } 4870 }
4838 4871
4839 // Don't inline recursive functions. 4872 // Don't inline recursive functions.
4840 for (FunctionState* state = function_state(); 4873 for (FunctionState* state = function_state();
4841 state != NULL; 4874 state != NULL;
4842 state = state->outer()) { 4875 state = state->outer()) {
4843 if (state->compilation_info()->closure()->shared() == *target_shared) { 4876 if (state->compilation_info()->closure()->shared() == *target_shared) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
4934 4967
4935 // Save the pending call context and type feedback oracle. Set up new ones 4968 // Save the pending call context and type feedback oracle. Set up new ones
4936 // for the inlined function. 4969 // for the inlined function.
4937 ASSERT(target_shared->has_deoptimization_support()); 4970 ASSERT(target_shared->has_deoptimization_support());
4938 TypeFeedbackOracle target_oracle( 4971 TypeFeedbackOracle target_oracle(
4939 Handle<Code>(target_shared->code()), 4972 Handle<Code>(target_shared->code()),
4940 Handle<Context>(target->context()->global_context()), 4973 Handle<Context>(target->context()->global_context()),
4941 isolate()); 4974 isolate());
4942 // The function state is new-allocated because we need to delete it 4975 // The function state is new-allocated because we need to delete it
4943 // in two different places. 4976 // in two different places.
4944 FunctionState* target_state = 4977 FunctionState* target_state = new FunctionState(
4945 new FunctionState(this, &target_info, &target_oracle, drop_extra); 4978 this, &target_info, &target_oracle, drop_extra, is_construct);
4946 4979
4947 HConstant* undefined = graph()->GetConstantUndefined(); 4980 HConstant* undefined = graph()->GetConstantUndefined();
4948 HEnvironment* inner_env = 4981 HEnvironment* inner_env =
4949 environment()->CopyForInlining(target, 4982 environment()->CopyForInlining(target,
4950 expr->arguments()->length(), 4983 arguments->length(),
4951 function, 4984 function,
4952 undefined, 4985 undefined,
4953 call_kind); 4986 call_kind,
4987 is_construct);
4954 #ifdef V8_TARGET_ARCH_IA32 4988 #ifdef V8_TARGET_ARCH_IA32
4955 // IA32 only, overwrite the caller's context in the deoptimization 4989 // IA32 only, overwrite the caller's context in the deoptimization
4956 // environment with the correct one. 4990 // environment with the correct one.
4957 // 4991 //
4958 // TODO(kmillikin): implement the same inlining on other platforms so we 4992 // TODO(kmillikin): implement the same inlining on other platforms so we
4959 // can remove the unsightly ifdefs in this function. 4993 // can remove the unsightly ifdefs in this function.
4960 HConstant* context = new HConstant(Handle<Context>(target->context()), 4994 HConstant* context = new HConstant(Handle<Context>(target->context()),
4961 Representation::Tagged()); 4995 Representation::Tagged());
4962 AddInstruction(context); 4996 AddInstruction(context);
4963 inner_env->BindContext(context); 4997 inner_env->BindContext(context);
4964 #endif 4998 #endif
4965 HBasicBlock* body_entry = CreateBasicBlock(inner_env); 4999 HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4966 current_block()->Goto(body_entry); 5000 current_block()->Goto(body_entry);
4967 body_entry->SetJoinId(expr->ReturnId()); 5001 body_entry->SetJoinId(return_id);
4968 set_current_block(body_entry); 5002 set_current_block(body_entry);
4969 AddInstruction(new(zone()) HEnterInlined(target, 5003 AddInstruction(new(zone()) HEnterInlined(target,
4970 expr->arguments()->length(), 5004 arguments->length(),
4971 function, 5005 function,
4972 call_kind)); 5006 call_kind,
5007 is_construct));
4973 VisitDeclarations(target_info.scope()->declarations()); 5008 VisitDeclarations(target_info.scope()->declarations());
4974 VisitStatements(function->body()); 5009 VisitStatements(function->body());
4975 if (HasStackOverflow()) { 5010 if (HasStackOverflow()) {
4976 // Bail out if the inline function did, as we cannot residualize a call 5011 // Bail out if the inline function did, as we cannot residualize a call
4977 // instead. 5012 // instead.
4978 TraceInline(target, caller, "inline graph construction failed"); 5013 TraceInline(target, caller, "inline graph construction failed");
4979 target_shared->DisableOptimization(*target); 5014 target_shared->DisableOptimization(*target);
4980 inline_bailout_ = true; 5015 inline_bailout_ = true;
4981 delete target_state; 5016 delete target_state;
4982 return true; 5017 return true;
4983 } 5018 }
4984 5019
4985 // Update inlined nodes count. 5020 // Update inlined nodes count.
4986 inlined_count_ += nodes_added; 5021 inlined_count_ += nodes_added;
4987 5022
4988 TraceInline(target, caller, NULL); 5023 TraceInline(target, caller, NULL);
4989 5024
4990 if (current_block() != NULL) { 5025 if (current_block() != NULL) {
4991 // Add a return of undefined if control can fall off the body. In a 5026 // Add default return value (i.e. undefined for normals calls or the newly
4992 // test context, undefined is false. 5027 // allocated receiver for construct calls) if control can fall off the
5028 // body. In a test context, undefined is false and any JSObject is true.
5029 HValue* return_value = is_construct ? receiver : undefined;
4993 if (inlined_test_context() == NULL) { 5030 if (inlined_test_context() == NULL) {
4994 ASSERT(function_return() != NULL); 5031 ASSERT(function_return() != NULL);
4995 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); 5032 ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4996 if (call_context()->IsEffect()) { 5033 if (call_context()->IsEffect()) {
4997 current_block()->Goto(function_return(), drop_extra); 5034 current_block()->Goto(function_return(), drop_extra);
4998 } else { 5035 } else {
4999 current_block()->AddLeaveInlined(undefined, 5036 current_block()->AddLeaveInlined(return_value,
5000 function_return(), 5037 function_return(),
5001 drop_extra); 5038 drop_extra);
5002 } 5039 }
5003 } else { 5040 } else {
5004 // The graph builder assumes control can reach both branches of a 5041 // The graph builder assumes control can reach both branches of a
5005 // test, so we materialize the undefined value and test it rather than 5042 // test, so we materialize the undefined value and test it rather than
5006 // simply jumping to the false target. 5043 // simply jumping to the false target.
5007 // 5044 //
5008 // TODO(3168478): refactor to avoid this. 5045 // TODO(3168478): refactor to avoid this.
Vyacheslav Egorov (Chromium) 2012/02/13 15:01:39 It seems this comment&todo is outdated (see r7601)
Michael Starzinger 2012/02/27 14:16:32 Done.
5009 ASSERT(call_context()->IsTest()); 5046 ASSERT(call_context()->IsTest());
5010 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 5047 HBasicBlock* empty_true = graph()->CreateBasicBlock();
5011 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 5048 HBasicBlock* empty_false = graph()->CreateBasicBlock();
5012 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false); 5049 HBranch* test =
5050 new(zone()) HBranch(return_value, empty_true, empty_false);
5013 current_block()->Finish(test); 5051 current_block()->Finish(test);
5014 5052
5015 empty_true->Goto(inlined_test_context()->if_true(), drop_extra); 5053 empty_true->Goto(inlined_test_context()->if_true(), drop_extra);
5016 empty_false->Goto(inlined_test_context()->if_false(), drop_extra); 5054 empty_false->Goto(inlined_test_context()->if_false(), drop_extra);
5017 } 5055 }
5018 } 5056 }
5019 5057
5020 // Fix up the function exits. 5058 // Fix up the function exits.
5021 if (inlined_test_context() != NULL) { 5059 if (inlined_test_context() != NULL) {
5022 HBasicBlock* if_true = inlined_test_context()->if_true(); 5060 HBasicBlock* if_true = inlined_test_context()->if_true();
5023 HBasicBlock* if_false = inlined_test_context()->if_false(); 5061 HBasicBlock* if_false = inlined_test_context()->if_false();
5024 5062
5025 // Pop the return test context from the expression context stack. 5063 // Pop the return test context from the expression context stack.
5026 ASSERT(ast_context() == inlined_test_context()); 5064 ASSERT(ast_context() == inlined_test_context());
5027 ClearInlinedTestContext(); 5065 ClearInlinedTestContext();
5028 delete target_state; 5066 delete target_state;
5029 5067
5030 // Forward to the real test context. 5068 // Forward to the real test context.
5031 if (if_true->HasPredecessor()) { 5069 if (if_true->HasPredecessor()) {
5032 if_true->SetJoinId(expr->id()); 5070 if_true->SetJoinId(ast_id);
5033 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 5071 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
5034 if_true->Goto(true_target, function_state()->drop_extra()); 5072 if_true->Goto(true_target, function_state()->drop_extra());
5035 } 5073 }
5036 if (if_false->HasPredecessor()) { 5074 if (if_false->HasPredecessor()) {
5037 if_false->SetJoinId(expr->id()); 5075 if_false->SetJoinId(ast_id);
5038 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 5076 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
5039 if_false->Goto(false_target, function_state()->drop_extra()); 5077 if_false->Goto(false_target, function_state()->drop_extra());
5040 } 5078 }
5041 set_current_block(NULL); 5079 set_current_block(NULL);
5042 return true; 5080 return true;
5043 5081
5044 } else if (function_return()->HasPredecessor()) { 5082 } else if (function_return()->HasPredecessor()) {
5045 function_return()->SetJoinId(expr->id()); 5083 function_return()->SetJoinId(ast_id);
5046 set_current_block(function_return()); 5084 set_current_block(function_return());
5047 } else { 5085 } else {
5048 set_current_block(NULL); 5086 set_current_block(NULL);
5049 } 5087 }
5050 delete target_state; 5088 delete target_state;
5051 return true; 5089 return true;
5052 } 5090 }
5053 5091
5054 5092
5093 bool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) {
5094 Handle<JSFunction> target = expr->target();
5095 ZoneList<Expression*>* arguments = expr->arguments();
5096 HValue* receiver = NULL;
5097 int return_id = expr->ReturnId();
5098 int ast_id = expr->id();
5099
5100 // The function call we are inlining is a method call if the call
5101 // is a property call.
5102 CallKind call_kind = (expr->expression()->AsProperty() == NULL)
5103 ? CALL_AS_FUNCTION
5104 : CALL_AS_METHOD;
5105
5106 return TryInline(call_kind, target, arguments, receiver, ast_id, return_id,
5107 drop_extra, false);
5108 }
5109
5110
5111 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
5112 Handle<JSFunction> target = expr->target();
5113 ZoneList<Expression*>* arguments = expr->arguments();
5114 CallKind call_kind = CALL_AS_FUNCTION;
5115 int return_id = expr->ReturnId();
5116 int ast_id = expr->id();
5117
5118 return TryInline(call_kind, target, arguments, receiver, ast_id, return_id,
5119 false, true);
5120 }
5121
5122
5055 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, 5123 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
5056 HValue* receiver, 5124 HValue* receiver,
5057 Handle<Map> receiver_map, 5125 Handle<Map> receiver_map,
5058 CheckType check_type) { 5126 CheckType check_type) {
5059 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 5127 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
5060 // Try to inline calls like Math.* as operations in the calling function. 5128 // Try to inline calls like Math.* as operations in the calling function.
5061 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 5129 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
5062 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 5130 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
5063 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5131 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
5064 switch (id) { 5132 switch (id) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
5328 expr->check_type() != RECEIVER_MAP_CHECK) { 5396 expr->check_type() != RECEIVER_MAP_CHECK) {
5329 // When the target has a custom call IC generator, use the IC, 5397 // 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 5398 // because it is likely to generate better code. Also use the IC
5331 // when a primitive receiver check is required. 5399 // when a primitive receiver check is required.
5332 HValue* context = environment()->LookupContext(); 5400 HValue* context = environment()->LookupContext();
5333 call = PreProcessCall( 5401 call = PreProcessCall(
5334 new(zone()) HCallNamed(context, name, argument_count)); 5402 new(zone()) HCallNamed(context, name, argument_count));
5335 } else { 5403 } else {
5336 AddCheckConstantFunction(expr, receiver, receiver_map, true); 5404 AddCheckConstantFunction(expr, receiver, receiver_map, true);
5337 5405
5338 if (TryInline(expr)) return; 5406 if (TryInlineCall(expr)) return;
5339 call = PreProcessCall( 5407 call = PreProcessCall(
5340 new(zone()) HCallConstantFunction(expr->target(), 5408 new(zone()) HCallConstantFunction(expr->target(),
5341 argument_count)); 5409 argument_count));
5342 } 5410 }
5343 } else if (types != NULL && types->length() > 1) { 5411 } else if (types != NULL && types->length() > 1) {
5344 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 5412 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
5345 HandlePolymorphicCallNamed(expr, receiver, types, name); 5413 HandlePolymorphicCallNamed(expr, receiver, types, name);
5346 return; 5414 return;
5347 5415
5348 } else { 5416 } else {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5384 // Replace the global object with the global receiver. 5452 // Replace the global object with the global receiver.
5385 HGlobalReceiver* global_receiver = 5453 HGlobalReceiver* global_receiver =
5386 new(zone()) HGlobalReceiver(global_object); 5454 new(zone()) HGlobalReceiver(global_object);
5387 // Index of the receiver from the top of the expression stack. 5455 // Index of the receiver from the top of the expression stack.
5388 const int receiver_index = argument_count - 1; 5456 const int receiver_index = argument_count - 1;
5389 AddInstruction(global_receiver); 5457 AddInstruction(global_receiver);
5390 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 5458 ASSERT(environment()->ExpressionStackAt(receiver_index)->
5391 IsGlobalObject()); 5459 IsGlobalObject());
5392 environment()->SetExpressionStackAt(receiver_index, global_receiver); 5460 environment()->SetExpressionStackAt(receiver_index, global_receiver);
5393 5461
5394 if (TryInline(expr)) return; 5462 if (TryInlineCall(expr)) return;
5395 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 5463 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
5396 argument_count)); 5464 argument_count));
5397 } else { 5465 } else {
5398 HValue* context = environment()->LookupContext(); 5466 HValue* context = environment()->LookupContext();
5399 HGlobalObject* receiver = new(zone()) HGlobalObject(context); 5467 HGlobalObject* receiver = new(zone()) HGlobalObject(context);
5400 AddInstruction(receiver); 5468 AddInstruction(receiver);
5401 PushAndAdd(new(zone()) HPushArgument(receiver)); 5469 PushAndAdd(new(zone()) HPushArgument(receiver));
5402 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5470 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5403 5471
5404 call = new(zone()) HCallGlobal(context, var->name(), argument_count); 5472 call = new(zone()) HCallGlobal(context, var->name(), argument_count);
5405 Drop(argument_count); 5473 Drop(argument_count);
5406 } 5474 }
5407 5475
5408 } else if (expr->IsMonomorphic()) { 5476 } else if (expr->IsMonomorphic()) {
5409 // The function is on the stack in the unoptimized code during 5477 // The function is on the stack in the unoptimized code during
5410 // evaluation of the arguments. 5478 // evaluation of the arguments.
5411 CHECK_ALIVE(VisitForValue(expr->expression())); 5479 CHECK_ALIVE(VisitForValue(expr->expression()));
5412 HValue* function = Top(); 5480 HValue* function = Top();
5413 HValue* context = environment()->LookupContext(); 5481 HValue* context = environment()->LookupContext();
5414 HGlobalObject* global = new(zone()) HGlobalObject(context); 5482 HGlobalObject* global = new(zone()) HGlobalObject(context);
5415 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 5483 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
5416 AddInstruction(global); 5484 AddInstruction(global);
5417 PushAndAdd(receiver); 5485 PushAndAdd(receiver);
5418 CHECK_ALIVE(VisitExpressions(expr->arguments())); 5486 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5419 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 5487 AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5420 if (TryInline(expr, true)) { // Drop function from environment. 5488 if (TryInlineCall(expr, true)) { // Drop function from environment.
5421 return; 5489 return;
5422 } else { 5490 } else {
5423 call = PreProcessCall(new(zone()) HInvokeFunction(context, 5491 call = PreProcessCall(new(zone()) HInvokeFunction(context,
5424 function, 5492 function,
5425 argument_count)); 5493 argument_count));
5426 Drop(1); // The function. 5494 Drop(1); // The function.
5427 } 5495 }
5428 5496
5429 } else { 5497 } else {
5430 CHECK_ALIVE(VisitForValue(expr->expression())); 5498 CHECK_ALIVE(VisitForValue(expr->expression()));
5431 HValue* function = Top(); 5499 HValue* function = Top();
5432 HValue* context = environment()->LookupContext(); 5500 HValue* context = environment()->LookupContext();
5433 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 5501 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
5434 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); 5502 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
5435 AddInstruction(global_object); 5503 AddInstruction(global_object);
5436 AddInstruction(receiver); 5504 AddInstruction(receiver);
5437 PushAndAdd(new(zone()) HPushArgument(receiver)); 5505 PushAndAdd(new(zone()) HPushArgument(receiver));
5438 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5506 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5439 5507
5440 call = new(zone()) HCallFunction(context, function, argument_count); 5508 call = new(zone()) HCallFunction(context, function, argument_count);
5441 Drop(argument_count + 1); 5509 Drop(argument_count + 1);
5442 } 5510 }
5443 } 5511 }
5444 5512
5445 call->set_position(expr->position()); 5513 call->set_position(expr->position());
5446 return ast_context()->ReturnInstruction(call, expr->id()); 5514 return ast_context()->ReturnInstruction(call, expr->id());
5447 } 5515 }
5448 5516
5449 5517
5518 // Checks whether allocation using the given constructor can be inlined.
5519 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
5520 return constructor->has_initial_map() &&
5521 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE;
5522 }
5523
5524
5450 void HGraphBuilder::VisitCallNew(CallNew* expr) { 5525 void HGraphBuilder::VisitCallNew(CallNew* expr) {
5451 ASSERT(!HasStackOverflow()); 5526 ASSERT(!HasStackOverflow());
5452 ASSERT(current_block() != NULL); 5527 ASSERT(current_block() != NULL);
5453 ASSERT(current_block()->HasPredecessor()); 5528 ASSERT(current_block()->HasPredecessor());
5454 // The constructor function is also used as the receiver argument to the 5529 expr->RecordTypeFeedback(oracle());
5455 // JS construct call builtin. 5530 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(); 5531 HValue* context = environment()->LookupContext();
5461 5532
5462 // The constructor is both an operand to the instruction and an argument 5533 if (FLAG_inline_construct &&
5463 // to the construct call. 5534 expr->IsMonomorphic() &&
5464 int arg_count = expr->arguments()->length() + 1; // Plus constructor. 5535 IsAllocationInlineable(expr->target())) {
5465 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); 5536 // The constructor function is on the stack in the unoptimized code
5466 call->set_position(expr->position()); 5537 // during evaluation of the arguments.
5467 Drop(arg_count); 5538 CHECK_ALIVE(VisitForValue(expr->expression()));
5468 return ast_context()->ReturnInstruction(call, expr->id()); 5539 HValue* function = Top();
5540 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5541 Handle<JSFunction> constructor = expr->target();
5542 AddInstruction(new(zone()) HCheckFunction(function, constructor));
5543
5544 // Replace the constructor function with a newly allocated receiver.
5545 HInstruction* receiver = new(zone()) HAllocateObject(context,
5546 function,
5547 constructor);
5548 // Index of the receiver from the top of the expression stack.
5549 const int receiver_index = argument_count - 1;
5550 AddInstruction(receiver);
5551 ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
5552 environment()->SetExpressionStackAt(receiver_index, receiver);
5553
5554 if (TryInlineConstruct(expr, receiver)) return;
5555 HInstruction* call = PreProcessCall(
Vyacheslav Egorov (Chromium) 2012/02/13 15:01:39 Is lazy bailout handled correctly on this call-sit
Michael Starzinger 2012/02/27 14:16:32 Done. I temporarily disabled partial inlining as s
5556 new(zone()) HInvokeFunction(context, function, argument_count));
5557 PushAndAdd(call);
5558 AddSimulate(expr->id());
5559
5560 // Check whether return value of constructor is a JSObject.
5561 HValue* return_value = Pop();
5562 HHasInstanceTypeAndBranch* typecheck =
Vyacheslav Egorov (Chromium) 2012/02/13 15:01:39 Branch construction code seems to be duplicated wi
Michael Starzinger 2012/02/27 14:16:32 Comment no longer applies after addressing previou
5563 new(zone()) HHasInstanceTypeAndBranch(return_value,
5564 FIRST_SPEC_OBJECT_TYPE,
5565 LAST_SPEC_OBJECT_TYPE);
5566 HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
5567 HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
5568 typecheck->SetSuccessorAt(0, if_spec_object);
5569 typecheck->SetSuccessorAt(1, not_spec_object);
5570 current_block()->Finish(typecheck);
5571 if_spec_object->last_environment()->Push(return_value);
5572 not_spec_object->last_environment()->Push(receiver);
5573 set_current_block(CreateJoin(if_spec_object, not_spec_object, expr->id()));
5574 return ast_context()->ReturnValue(Pop());
5575 } else {
5576 // The constructor function is both an operand to the instruction and an
5577 // argument to the construct call.
5578 HValue* constructor = NULL;
5579 CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
5580 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
5581 HInstruction* call =
5582 new(zone()) HCallNew(context, constructor, argument_count);
5583 Drop(argument_count);
5584 call->set_position(expr->position());
5585 return ast_context()->ReturnInstruction(call, expr->id());
5586 }
5469 } 5587 }
5470 5588
5471 5589
5472 // Support for generating inlined runtime functions. 5590 // Support for generating inlined runtime functions.
5473 5591
5474 // Lookup table for generators for runtime calls that are generated inline. 5592 // Lookup table for generators for runtime calls that are generated inline.
5475 // Elements of the table are member pointers to functions of HGraphBuilder. 5593 // Elements of the table are member pointers to functions of HGraphBuilder.
5476 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 5594 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
5477 &HGraphBuilder::Generate##Name, 5595 &HGraphBuilder::Generate##Name,
5478 5596
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after
6503 CallRuntime* call) { 6621 CallRuntime* call) {
6504 return Bailout( 6622 return Bailout(
6505 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 6623 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
6506 } 6624 }
6507 6625
6508 6626
6509 // Support for construct call checks. 6627 // Support for construct call checks.
6510 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 6628 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
6511 ASSERT(call->arguments()->length() == 0); 6629 ASSERT(call->arguments()->length() == 0);
6512 if (function_state()->outer() != NULL) { 6630 if (function_state()->outer() != NULL) {
6513 // We are generating graph for inlined function. Currently 6631 // We are generating graph for inlined function.
6514 // constructor inlining is not supported and we can just return 6632 HValue* value = function_state()->is_construct()
6515 // false from %_IsConstructCall(). 6633 ? graph()->GetConstantTrue()
6516 return ast_context()->ReturnValue(graph()->GetConstantFalse()); 6634 : graph()->GetConstantFalse();
6635 return ast_context()->ReturnValue(value);
6517 } else { 6636 } else {
6518 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 6637 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
6519 call->id()); 6638 call->id());
6520 } 6639 }
6521 } 6640 }
6522 6641
6523 6642
6524 // Support for arguments.length and arguments[?]. 6643 // Support for arguments.length and arguments[?].
6525 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 6644 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
6526 // Our implementation of arguments (based on this stack frame or an 6645 // 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 7013 #undef CHECK_BAILOUT
6895 #undef CHECK_ALIVE 7014 #undef CHECK_ALIVE
6896 7015
6897 7016
6898 HEnvironment::HEnvironment(HEnvironment* outer, 7017 HEnvironment::HEnvironment(HEnvironment* outer,
6899 Scope* scope, 7018 Scope* scope,
6900 Handle<JSFunction> closure) 7019 Handle<JSFunction> closure)
6901 : closure_(closure), 7020 : closure_(closure),
6902 values_(0), 7021 values_(0),
6903 assigned_variables_(4), 7022 assigned_variables_(4),
7023 frame_type_(JS_FUNCTION),
6904 parameter_count_(0), 7024 parameter_count_(0),
6905 specials_count_(1), 7025 specials_count_(1),
6906 local_count_(0), 7026 local_count_(0),
6907 outer_(outer), 7027 outer_(outer),
6908 pop_count_(0), 7028 pop_count_(0),
6909 push_count_(0), 7029 push_count_(0),
6910 ast_id_(AstNode::kNoNumber), 7030 ast_id_(AstNode::kNoNumber) {
6911 arguments_adaptor_(false) {
6912 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 7031 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
6913 } 7032 }
6914 7033
6915 7034
6916 HEnvironment::HEnvironment(const HEnvironment* other) 7035 HEnvironment::HEnvironment(const HEnvironment* other)
6917 : values_(0), 7036 : values_(0),
6918 assigned_variables_(0), 7037 assigned_variables_(0),
7038 frame_type_(JS_FUNCTION),
6919 parameter_count_(0), 7039 parameter_count_(0),
6920 specials_count_(1), 7040 specials_count_(1),
6921 local_count_(0), 7041 local_count_(0),
6922 outer_(NULL), 7042 outer_(NULL),
6923 pop_count_(0), 7043 pop_count_(0),
6924 push_count_(0), 7044 push_count_(0),
6925 ast_id_(other->ast_id()), 7045 ast_id_(other->ast_id()) {
6926 arguments_adaptor_(false) {
6927 Initialize(other); 7046 Initialize(other);
6928 } 7047 }
6929 7048
6930 7049
6931 HEnvironment::HEnvironment(HEnvironment* outer, 7050 HEnvironment::HEnvironment(HEnvironment* outer,
6932 Handle<JSFunction> closure, 7051 Handle<JSFunction> closure,
6933 int arguments) 7052 int arguments)
6934 : closure_(closure), 7053 : closure_(closure),
6935 values_(arguments), 7054 values_(arguments),
6936 assigned_variables_(0), 7055 assigned_variables_(0),
7056 frame_type_(ARGUMENTS_ADAPTOR),
6937 parameter_count_(arguments), 7057 parameter_count_(arguments),
6938 local_count_(0), 7058 local_count_(0),
6939 outer_(outer), 7059 outer_(outer),
6940 pop_count_(0), 7060 pop_count_(0),
6941 push_count_(0), 7061 push_count_(0),
6942 ast_id_(AstNode::kNoNumber), 7062 ast_id_(AstNode::kNoNumber) {
6943 arguments_adaptor_(true) {
6944 } 7063 }
6945 7064
6946 7065
7066 HEnvironment::HEnvironment(HEnvironment* outer,
7067 Handle<JSFunction> closure)
7068 : closure_(closure),
7069 values_(0),
7070 assigned_variables_(0),
7071 frame_type_(JS_CONSTRUCT),
7072 parameter_count_(0),
7073 local_count_(0),
7074 outer_(outer),
7075 pop_count_(0),
7076 push_count_(0),
7077 ast_id_(AstNode::kNoNumber) {
7078 }
7079
7080
6947 void HEnvironment::Initialize(int parameter_count, 7081 void HEnvironment::Initialize(int parameter_count,
6948 int local_count, 7082 int local_count,
6949 int stack_height) { 7083 int stack_height) {
6950 parameter_count_ = parameter_count; 7084 parameter_count_ = parameter_count;
6951 local_count_ = local_count; 7085 local_count_ = local_count;
6952 7086
6953 // Avoid reallocating the temporaries' backing store on the first Push. 7087 // Avoid reallocating the temporaries' backing store on the first Push.
6954 int total = parameter_count + specials_count_ + local_count + stack_height; 7088 int total = parameter_count + specials_count_ + local_count + stack_height;
6955 values_.Initialize(total + 4); 7089 values_.Initialize(total + 4);
6956 for (int i = 0; i < total; ++i) values_.Add(NULL); 7090 for (int i = 0; i < total; ++i) values_.Add(NULL);
6957 } 7091 }
6958 7092
6959 7093
6960 void HEnvironment::Initialize(const HEnvironment* other) { 7094 void HEnvironment::Initialize(const HEnvironment* other) {
6961 closure_ = other->closure(); 7095 closure_ = other->closure();
6962 values_.AddAll(other->values_); 7096 values_.AddAll(other->values_);
6963 assigned_variables_.AddAll(other->assigned_variables_); 7097 assigned_variables_.AddAll(other->assigned_variables_);
7098 frame_type_ = other->frame_type_;
6964 parameter_count_ = other->parameter_count_; 7099 parameter_count_ = other->parameter_count_;
6965 local_count_ = other->local_count_; 7100 local_count_ = other->local_count_;
6966 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 7101 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy.
6967 pop_count_ = other->pop_count_; 7102 pop_count_ = other->pop_count_;
6968 push_count_ = other->push_count_; 7103 push_count_ = other->push_count_;
6969 ast_id_ = other->ast_id_; 7104 ast_id_ = other->ast_id_;
6970 arguments_adaptor_ = other->arguments_adaptor_;
6971 } 7105 }
6972 7106
6973 7107
6974 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 7108 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
6975 ASSERT(!block->IsLoopHeader()); 7109 ASSERT(!block->IsLoopHeader());
6976 ASSERT(values_.length() == other->values_.length()); 7110 ASSERT(values_.length() == other->values_.length());
6977 7111
6978 int length = values_.length(); 7112 int length = values_.length();
6979 for (int i = 0; i < length; ++i) { 7113 for (int i = 0; i < length; ++i) {
6980 HValue* value = values_[i]; 7114 HValue* value = values_[i];
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
7067 new_env->ClearHistory(); 7201 new_env->ClearHistory();
7068 return new_env; 7202 return new_env;
7069 } 7203 }
7070 7204
7071 7205
7072 HEnvironment* HEnvironment::CopyForInlining( 7206 HEnvironment* HEnvironment::CopyForInlining(
7073 Handle<JSFunction> target, 7207 Handle<JSFunction> target,
7074 int arguments, 7208 int arguments,
7075 FunctionLiteral* function, 7209 FunctionLiteral* function,
7076 HConstant* undefined, 7210 HConstant* undefined,
7077 CallKind call_kind) const { 7211 CallKind call_kind,
7078 ASSERT(!is_arguments_adaptor()); 7212 bool is_construct) const {
7213 ASSERT(frame_type() == JS_FUNCTION);
7079 7214
7080 Zone* zone = closure()->GetIsolate()->zone(); 7215 Zone* zone = closure()->GetIsolate()->zone();
7081 7216
7082 // Outer environment is a copy of this one without the arguments. 7217 // Outer environment is a copy of this one without the arguments.
7083 int arity = function->scope()->num_parameters(); 7218 int arity = function->scope()->num_parameters();
7084 7219
7085 HEnvironment* outer = Copy(); 7220 HEnvironment* outer = Copy();
7086 outer->Drop(arguments + 1); // Including receiver. 7221 outer->Drop(arguments + 1); // Including receiver.
7087 outer->ClearHistory(); 7222 outer->ClearHistory();
7088 7223
7224 if (is_construct) {
7225 // Create artificial constructor stub environment. The receiver should
7226 // actually be the constructor function, but we pass the newly allocated
7227 // object instead, DoComputeConstructStubFrame() relies on that.
7228 outer = new(zone) HEnvironment(outer, target);
7229 for (int i = 0; i <= arguments; ++i) { // Include receiver.
7230 outer->Push(ExpressionStackAt(arguments - i));
7231 }
7232 outer->ClearHistory();
7233 }
7234
7089 if (arity != arguments) { 7235 if (arity != arguments) {
7090 // Create artificial arguments adaptation environment. 7236 // Create artificial arguments adaptation environment.
7091 outer = new(zone) HEnvironment(outer, target, arguments + 1); 7237 outer = new(zone) HEnvironment(outer, target, arguments + 1);
Vyacheslav Egorov (Chromium) 2012/02/13 15:01:39 I think HEnvironent constructor for the "artificia
Michael Starzinger 2012/02/27 14:16:32 Done.
7092 for (int i = 0; i <= arguments; ++i) { // Include receiver. 7238 for (int i = 0; i <= arguments; ++i) { // Include receiver.
7093 outer->Push(ExpressionStackAt(arguments - i)); 7239 outer->Push(ExpressionStackAt(arguments - i));
7094 } 7240 }
7095 outer->ClearHistory(); 7241 outer->ClearHistory();
7096 } 7242 }
7097 7243
7098 HEnvironment* inner = 7244 HEnvironment* inner =
7099 new(zone) HEnvironment(outer, function->scope(), target); 7245 new(zone) HEnvironment(outer, function->scope(), target);
7100 // Get the argument values from the original environment. 7246 // Get the argument values from the original environment.
7101 for (int i = 0; i <= arity; ++i) { // Include receiver. 7247 for (int i = 0; i <= arity; ++i) { // Include receiver.
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
7453 } 7599 }
7454 } 7600 }
7455 7601
7456 #ifdef DEBUG 7602 #ifdef DEBUG
7457 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7603 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7458 if (allocator_ != NULL) allocator_->Verify(); 7604 if (allocator_ != NULL) allocator_->Verify();
7459 #endif 7605 #endif
7460 } 7606 }
7461 7607
7462 } } // namespace v8::internal 7608 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698