OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 20 matching lines...) Expand all Loading... |
31 | 31 |
32 #include "v8.h" | 32 #include "v8.h" |
33 #include "codegen.h" | 33 #include "codegen.h" |
34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
35 #include "hashmap.h" | 35 #include "hashmap.h" |
36 #include "lithium-allocator.h" | 36 #include "lithium-allocator.h" |
37 #include "parser.h" | 37 #include "parser.h" |
38 #include "scopeinfo.h" | 38 #include "scopeinfo.h" |
39 #include "scopes.h" | 39 #include "scopes.h" |
40 #include "stub-cache.h" | 40 #include "stub-cache.h" |
| 41 #include "typing.h" |
41 | 42 |
42 #if V8_TARGET_ARCH_IA32 | 43 #if V8_TARGET_ARCH_IA32 |
43 #include "ia32/lithium-codegen-ia32.h" | 44 #include "ia32/lithium-codegen-ia32.h" |
44 #elif V8_TARGET_ARCH_X64 | 45 #elif V8_TARGET_ARCH_X64 |
45 #include "x64/lithium-codegen-x64.h" | 46 #include "x64/lithium-codegen-x64.h" |
46 #elif V8_TARGET_ARCH_ARM | 47 #elif V8_TARGET_ARCH_ARM |
47 #include "arm/lithium-codegen-arm.h" | 48 #include "arm/lithium-codegen-arm.h" |
48 #elif V8_TARGET_ARCH_MIPS | 49 #elif V8_TARGET_ARCH_MIPS |
49 #include "mips/lithium-codegen-mips.h" | 50 #include "mips/lithium-codegen-mips.h" |
50 #else | 51 #else |
(...skipping 1962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2013 | 2014 |
2014 if (fill_with_hole) { | 2015 if (fill_with_hole) { |
2015 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 2016 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, |
2016 graph()->GetConstant0(), capacity); | 2017 graph()->GetConstant0(), capacity); |
2017 } | 2018 } |
2018 | 2019 |
2019 return new_object; | 2020 return new_object; |
2020 } | 2021 } |
2021 | 2022 |
2022 | 2023 |
2023 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 2024 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
2024 TypeFeedbackOracle* oracle) | |
2025 : HGraphBuilder(info), | 2025 : HGraphBuilder(info), |
2026 function_state_(NULL), | 2026 function_state_(NULL), |
2027 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 2027 initial_function_state_(this, info, NORMAL_RETURN), |
2028 ast_context_(NULL), | 2028 ast_context_(NULL), |
2029 break_scope_(NULL), | 2029 break_scope_(NULL), |
2030 inlined_count_(0), | 2030 inlined_count_(0), |
2031 globals_(10, info->zone()), | 2031 globals_(10, info->zone()), |
2032 inline_bailout_(false) { | 2032 inline_bailout_(false) { |
2033 // This is not initialized in the initializer list because the | 2033 // This is not initialized in the initializer list because the |
2034 // constructor for the initial state relies on function_state_ == NULL | 2034 // constructor for the initial state relies on function_state_ == NULL |
2035 // to know it's the initial state. | 2035 // to know it's the initial state. |
2036 function_state_= &initial_function_state_; | 2036 function_state_= &initial_function_state_; |
2037 InitializeAstVisitor(); | 2037 InitializeAstVisitor(); |
(...skipping 2369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4407 } | 4407 } |
4408 } | 4408 } |
4409 } | 4409 } |
4410 } | 4410 } |
4411 | 4411 |
4412 | 4412 |
4413 // Implementation of utility class to encapsulate the translation state for | 4413 // Implementation of utility class to encapsulate the translation state for |
4414 // a (possibly inlined) function. | 4414 // a (possibly inlined) function. |
4415 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, | 4415 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, |
4416 CompilationInfo* info, | 4416 CompilationInfo* info, |
4417 TypeFeedbackOracle* oracle, | |
4418 InliningKind inlining_kind) | 4417 InliningKind inlining_kind) |
4419 : owner_(owner), | 4418 : owner_(owner), |
4420 compilation_info_(info), | 4419 compilation_info_(info), |
4421 oracle_(oracle), | |
4422 call_context_(NULL), | 4420 call_context_(NULL), |
4423 inlining_kind_(inlining_kind), | 4421 inlining_kind_(inlining_kind), |
4424 function_return_(NULL), | 4422 function_return_(NULL), |
4425 test_context_(NULL), | 4423 test_context_(NULL), |
4426 entry_(NULL), | 4424 entry_(NULL), |
4427 arguments_elements_(NULL), | 4425 arguments_elements_(NULL), |
4428 outer_(owner->function_state()) { | 4426 outer_(owner->function_state()) { |
4429 if (outer_ != NULL) { | 4427 if (outer_ != NULL) { |
4430 // State for an inline function. | 4428 // State for an inline function. |
4431 if (owner->ast_context()->IsTest()) { | 4429 if (owner->ast_context()->IsTest()) { |
4432 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); | 4430 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); |
4433 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); | 4431 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); |
4434 if_true->MarkAsInlineReturnTarget(); | 4432 if_true->MarkAsInlineReturnTarget(); |
4435 if_false->MarkAsInlineReturnTarget(); | 4433 if_false->MarkAsInlineReturnTarget(); |
4436 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); | 4434 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); |
4437 Expression* cond = outer_test_context->condition(); | 4435 Expression* cond = outer_test_context->condition(); |
4438 TypeFeedbackOracle* outer_oracle = outer_test_context->oracle(); | |
4439 // The AstContext constructor pushed on the context stack. This newed | 4436 // The AstContext constructor pushed on the context stack. This newed |
4440 // instance is the reason that AstContext can't be BASE_EMBEDDED. | 4437 // instance is the reason that AstContext can't be BASE_EMBEDDED. |
4441 test_context_ = | 4438 test_context_ = new TestContext(owner, cond, if_true, if_false); |
4442 new TestContext(owner, cond, outer_oracle, if_true, if_false); | |
4443 } else { | 4439 } else { |
4444 function_return_ = owner->graph()->CreateBasicBlock(); | 4440 function_return_ = owner->graph()->CreateBasicBlock(); |
4445 function_return()->MarkAsInlineReturnTarget(); | 4441 function_return()->MarkAsInlineReturnTarget(); |
4446 } | 4442 } |
4447 // Set this after possibly allocating a new TestContext above. | 4443 // Set this after possibly allocating a new TestContext above. |
4448 call_context_ = owner->ast_context(); | 4444 call_context_ = owner->ast_context(); |
4449 } | 4445 } |
4450 | 4446 |
4451 // Push on the state stack. | 4447 // Push on the state stack. |
4452 owner->set_function_state(this); | 4448 owner->set_function_state(this); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4666 if (constant_value->BooleanValue()) { | 4662 if (constant_value->BooleanValue()) { |
4667 builder->current_block()->Goto(if_true(), builder->function_state()); | 4663 builder->current_block()->Goto(if_true(), builder->function_state()); |
4668 } else { | 4664 } else { |
4669 builder->current_block()->Goto(if_false(), builder->function_state()); | 4665 builder->current_block()->Goto(if_false(), builder->function_state()); |
4670 } | 4666 } |
4671 builder->set_current_block(NULL); | 4667 builder->set_current_block(NULL); |
4672 return; | 4668 return; |
4673 } | 4669 } |
4674 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 4670 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
4675 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 4671 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
4676 TypeFeedbackId test_id = condition()->test_id(); | 4672 ToBooleanStub::Types expected(condition()->to_boolean_types()); |
4677 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); | |
4678 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); | 4673 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); |
4679 builder->current_block()->Finish(test); | 4674 builder->current_block()->Finish(test); |
4680 | 4675 |
4681 empty_true->Goto(if_true(), builder->function_state()); | 4676 empty_true->Goto(if_true(), builder->function_state()); |
4682 empty_false->Goto(if_false(), builder->function_state()); | 4677 empty_false->Goto(if_false(), builder->function_state()); |
4683 builder->set_current_block(NULL); | 4678 builder->set_current_block(NULL); |
4684 } | 4679 } |
4685 | 4680 |
4686 | 4681 |
4687 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 4682 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4722 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 4717 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
4723 for_value.set_for_typeof(true); | 4718 for_value.set_for_typeof(true); |
4724 Visit(expr); | 4719 Visit(expr); |
4725 } | 4720 } |
4726 | 4721 |
4727 | 4722 |
4728 | 4723 |
4729 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, | 4724 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, |
4730 HBasicBlock* true_block, | 4725 HBasicBlock* true_block, |
4731 HBasicBlock* false_block) { | 4726 HBasicBlock* false_block) { |
4732 TestContext for_test(this, expr, oracle(), true_block, false_block); | 4727 TestContext for_test(this, expr, true_block, false_block); |
4733 Visit(expr); | 4728 Visit(expr); |
4734 } | 4729 } |
4735 | 4730 |
4736 | 4731 |
4737 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { | 4732 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { |
4738 CHECK_ALIVE(VisitForValue(expr)); | 4733 CHECK_ALIVE(VisitForValue(expr)); |
4739 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); | 4734 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
4740 } | 4735 } |
4741 | 4736 |
4742 | 4737 |
(...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5729 return block; | 5724 return block; |
5730 } | 5725 } |
5731 | 5726 |
5732 | 5727 |
5733 void HOptimizedGraphBuilder::VisitContinueStatement( | 5728 void HOptimizedGraphBuilder::VisitContinueStatement( |
5734 ContinueStatement* stmt) { | 5729 ContinueStatement* stmt) { |
5735 ASSERT(!HasStackOverflow()); | 5730 ASSERT(!HasStackOverflow()); |
5736 ASSERT(current_block() != NULL); | 5731 ASSERT(current_block() != NULL); |
5737 ASSERT(current_block()->HasPredecessor()); | 5732 ASSERT(current_block()->HasPredecessor()); |
5738 int drop_extra = 0; | 5733 int drop_extra = 0; |
5739 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), | 5734 HBasicBlock* continue_block = break_scope()->Get( |
5740 CONTINUE, | 5735 stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); |
5741 &drop_extra); | |
5742 Drop(drop_extra); | 5736 Drop(drop_extra); |
5743 current_block()->Goto(continue_block); | 5737 current_block()->Goto(continue_block); |
5744 set_current_block(NULL); | 5738 set_current_block(NULL); |
5745 } | 5739 } |
5746 | 5740 |
5747 | 5741 |
5748 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 5742 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
5749 ASSERT(!HasStackOverflow()); | 5743 ASSERT(!HasStackOverflow()); |
5750 ASSERT(current_block() != NULL); | 5744 ASSERT(current_block() != NULL); |
5751 ASSERT(current_block()->HasPredecessor()); | 5745 ASSERT(current_block()->HasPredecessor()); |
5752 int drop_extra = 0; | 5746 int drop_extra = 0; |
5753 HBasicBlock* break_block = break_scope()->Get(stmt->target(), | 5747 HBasicBlock* break_block = break_scope()->Get( |
5754 BREAK, | 5748 stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); |
5755 &drop_extra); | |
5756 Drop(drop_extra); | 5749 Drop(drop_extra); |
5757 current_block()->Goto(break_block); | 5750 current_block()->Goto(break_block); |
5758 set_current_block(NULL); | 5751 set_current_block(NULL); |
5759 } | 5752 } |
5760 | 5753 |
5761 | 5754 |
5762 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 5755 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
5763 ASSERT(!HasStackOverflow()); | 5756 ASSERT(!HasStackOverflow()); |
5764 ASSERT(current_block() != NULL); | 5757 ASSERT(current_block() != NULL); |
5765 ASSERT(current_block()->HasPredecessor()); | 5758 ASSERT(current_block()->HasPredecessor()); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5836 ASSERT(current_block() != NULL); | 5829 ASSERT(current_block() != NULL); |
5837 ASSERT(current_block()->HasPredecessor()); | 5830 ASSERT(current_block()->HasPredecessor()); |
5838 return Bailout("WithStatement"); | 5831 return Bailout("WithStatement"); |
5839 } | 5832 } |
5840 | 5833 |
5841 | 5834 |
5842 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 5835 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
5843 ASSERT(!HasStackOverflow()); | 5836 ASSERT(!HasStackOverflow()); |
5844 ASSERT(current_block() != NULL); | 5837 ASSERT(current_block() != NULL); |
5845 ASSERT(current_block()->HasPredecessor()); | 5838 ASSERT(current_block()->HasPredecessor()); |
| 5839 |
5846 // We only optimize switch statements with smi-literal smi comparisons, | 5840 // We only optimize switch statements with smi-literal smi comparisons, |
5847 // with a bounded number of clauses. | 5841 // with a bounded number of clauses. |
5848 const int kCaseClauseLimit = 128; | 5842 const int kCaseClauseLimit = 128; |
5849 ZoneList<CaseClause*>* clauses = stmt->cases(); | 5843 ZoneList<CaseClause*>* clauses = stmt->cases(); |
5850 int clause_count = clauses->length(); | 5844 int clause_count = clauses->length(); |
5851 if (clause_count > kCaseClauseLimit) { | 5845 if (clause_count > kCaseClauseLimit) { |
5852 return Bailout("SwitchStatement: too many clauses"); | 5846 return Bailout("SwitchStatement: too many clauses"); |
5853 } | 5847 } |
5854 | 5848 |
| 5849 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
| 5850 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
| 5851 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
| 5852 } |
| 5853 |
5855 HValue* context = environment()->LookupContext(); | 5854 HValue* context = environment()->LookupContext(); |
5856 | 5855 |
5857 CHECK_ALIVE(VisitForValue(stmt->tag())); | 5856 CHECK_ALIVE(VisitForValue(stmt->tag())); |
5858 AddSimulate(stmt->EntryId()); | 5857 AddSimulate(stmt->EntryId()); |
5859 HValue* tag_value = Pop(); | 5858 HValue* tag_value = Pop(); |
5860 HBasicBlock* first_test_block = current_block(); | 5859 HBasicBlock* first_test_block = current_block(); |
5861 | 5860 |
5862 SwitchType switch_type = UNKNOWN_SWITCH; | |
5863 | |
5864 // 1. Extract clause type | |
5865 for (int i = 0; i < clause_count; ++i) { | |
5866 CaseClause* clause = clauses->at(i); | |
5867 if (clause->is_default()) continue; | |
5868 | |
5869 if (switch_type == UNKNOWN_SWITCH) { | |
5870 if (clause->label()->IsSmiLiteral()) { | |
5871 switch_type = SMI_SWITCH; | |
5872 } else if (clause->label()->IsStringLiteral()) { | |
5873 switch_type = STRING_SWITCH; | |
5874 } else { | |
5875 return Bailout("SwitchStatement: non-literal switch label"); | |
5876 } | |
5877 } else if ((switch_type == STRING_SWITCH && | |
5878 !clause->label()->IsStringLiteral()) || | |
5879 (switch_type == SMI_SWITCH && | |
5880 !clause->label()->IsSmiLiteral())) { | |
5881 return Bailout("SwitchStatement: mixed label types are not supported"); | |
5882 } | |
5883 } | |
5884 | |
5885 HUnaryControlInstruction* string_check = NULL; | 5861 HUnaryControlInstruction* string_check = NULL; |
5886 HBasicBlock* not_string_block = NULL; | 5862 HBasicBlock* not_string_block = NULL; |
5887 | 5863 |
5888 // Test switch's tag value if all clauses are string literals | 5864 // Test switch's tag value if all clauses are string literals |
5889 if (switch_type == STRING_SWITCH) { | 5865 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
5890 string_check = new(zone()) HIsStringAndBranch(tag_value); | 5866 string_check = new(zone()) HIsStringAndBranch(tag_value); |
5891 first_test_block = graph()->CreateBasicBlock(); | 5867 first_test_block = graph()->CreateBasicBlock(); |
5892 not_string_block = graph()->CreateBasicBlock(); | 5868 not_string_block = graph()->CreateBasicBlock(); |
5893 | 5869 |
5894 string_check->SetSuccessorAt(0, first_test_block); | 5870 string_check->SetSuccessorAt(0, first_test_block); |
5895 string_check->SetSuccessorAt(1, not_string_block); | 5871 string_check->SetSuccessorAt(1, not_string_block); |
5896 current_block()->Finish(string_check); | 5872 current_block()->Finish(string_check); |
5897 | 5873 |
5898 set_current_block(first_test_block); | 5874 set_current_block(first_test_block); |
5899 } | 5875 } |
5900 | 5876 |
5901 // 2. Build all the tests, with dangling true branches | 5877 // 1. Build all the tests, with dangling true branches |
5902 BailoutId default_id = BailoutId::None(); | 5878 BailoutId default_id = BailoutId::None(); |
5903 for (int i = 0; i < clause_count; ++i) { | 5879 for (int i = 0; i < clause_count; ++i) { |
5904 CaseClause* clause = clauses->at(i); | 5880 CaseClause* clause = clauses->at(i); |
5905 if (clause->is_default()) { | 5881 if (clause->is_default()) { |
5906 default_id = clause->EntryId(); | 5882 default_id = clause->EntryId(); |
5907 continue; | 5883 continue; |
5908 } | 5884 } |
5909 if (switch_type == SMI_SWITCH) { | |
5910 clause->RecordTypeFeedback(oracle()); | |
5911 } | |
5912 | 5885 |
5913 // Generate a compare and branch. | 5886 // Generate a compare and branch. |
5914 CHECK_ALIVE(VisitForValue(clause->label())); | 5887 CHECK_ALIVE(VisitForValue(clause->label())); |
5915 HValue* label_value = Pop(); | 5888 HValue* label_value = Pop(); |
5916 | 5889 |
5917 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 5890 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
5918 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 5891 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
5919 | 5892 |
5920 HControlInstruction* compare; | 5893 HControlInstruction* compare; |
5921 | 5894 |
5922 if (switch_type == SMI_SWITCH) { | 5895 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
5923 if (!clause->IsSmiCompare()) { | 5896 if (!clause->IsSmiCompare()) { |
5924 // Finish with deoptimize and add uses of enviroment values to | 5897 // Finish with deoptimize and add uses of enviroment values to |
5925 // account for invisible uses. | 5898 // account for invisible uses. |
5926 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 5899 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
5927 set_current_block(NULL); | 5900 set_current_block(NULL); |
5928 break; | 5901 break; |
5929 } | 5902 } |
5930 | 5903 |
5931 HCompareIDAndBranch* compare_ = | 5904 HCompareIDAndBranch* compare_ = |
5932 new(zone()) HCompareIDAndBranch(tag_value, | 5905 new(zone()) HCompareIDAndBranch(tag_value, |
(...skipping 17 matching lines...) Expand all Loading... |
5950 | 5923 |
5951 // Save the current block to use for the default or to join with the | 5924 // Save the current block to use for the default or to join with the |
5952 // exit. This block is NULL if we deoptimized. | 5925 // exit. This block is NULL if we deoptimized. |
5953 HBasicBlock* last_block = current_block(); | 5926 HBasicBlock* last_block = current_block(); |
5954 | 5927 |
5955 if (not_string_block != NULL) { | 5928 if (not_string_block != NULL) { |
5956 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); | 5929 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); |
5957 last_block = CreateJoin(last_block, not_string_block, join_id); | 5930 last_block = CreateJoin(last_block, not_string_block, join_id); |
5958 } | 5931 } |
5959 | 5932 |
5960 // 3. Loop over the clauses and the linked list of tests in lockstep, | 5933 // 2. Loop over the clauses and the linked list of tests in lockstep, |
5961 // translating the clause bodies. | 5934 // translating the clause bodies. |
5962 HBasicBlock* curr_test_block = first_test_block; | 5935 HBasicBlock* curr_test_block = first_test_block; |
5963 HBasicBlock* fall_through_block = NULL; | 5936 HBasicBlock* fall_through_block = NULL; |
5964 | 5937 |
5965 BreakAndContinueInfo break_info(stmt); | 5938 BreakAndContinueInfo break_info(stmt); |
5966 { BreakAndContinueScope push(&break_info, this); | 5939 { BreakAndContinueScope push(&break_info, this); |
5967 for (int i = 0; i < clause_count; ++i) { | 5940 for (int i = 0; i < clause_count; ++i) { |
5968 CaseClause* clause = clauses->at(i); | 5941 CaseClause* clause = clauses->at(i); |
5969 | 5942 |
5970 // Identify the block where normal (non-fall-through) control flow | 5943 // Identify the block where normal (non-fall-through) control flow |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6237 | 6210 |
6238 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 6211 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
6239 ASSERT(!HasStackOverflow()); | 6212 ASSERT(!HasStackOverflow()); |
6240 ASSERT(current_block() != NULL); | 6213 ASSERT(current_block() != NULL); |
6241 ASSERT(current_block()->HasPredecessor()); | 6214 ASSERT(current_block()->HasPredecessor()); |
6242 | 6215 |
6243 if (!FLAG_optimize_for_in) { | 6216 if (!FLAG_optimize_for_in) { |
6244 return Bailout("ForInStatement optimization is disabled"); | 6217 return Bailout("ForInStatement optimization is disabled"); |
6245 } | 6218 } |
6246 | 6219 |
6247 if (!oracle()->IsForInFastCase(stmt)) { | 6220 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { |
6248 return Bailout("ForInStatement is not fast case"); | 6221 return Bailout("ForInStatement is not fast case"); |
6249 } | 6222 } |
6250 | 6223 |
6251 if (!stmt->each()->IsVariableProxy() || | 6224 if (!stmt->each()->IsVariableProxy() || |
6252 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 6225 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
6253 return Bailout("ForInStatement with non-local each variable"); | 6226 return Bailout("ForInStatement with non-local each variable"); |
6254 } | 6227 } |
6255 | 6228 |
6256 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 6229 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
6257 | 6230 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6378 ASSERT(!HasStackOverflow()); | 6351 ASSERT(!HasStackOverflow()); |
6379 ASSERT(current_block() != NULL); | 6352 ASSERT(current_block() != NULL); |
6380 ASSERT(current_block()->HasPredecessor()); | 6353 ASSERT(current_block()->HasPredecessor()); |
6381 return Bailout("DebuggerStatement"); | 6354 return Bailout("DebuggerStatement"); |
6382 } | 6355 } |
6383 | 6356 |
6384 | 6357 |
6385 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 6358 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
6386 Code* unoptimized_code, FunctionLiteral* expr) { | 6359 Code* unoptimized_code, FunctionLiteral* expr) { |
6387 int start_position = expr->start_position(); | 6360 int start_position = expr->start_position(); |
6388 RelocIterator it(unoptimized_code); | 6361 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { |
6389 for (;!it.done(); it.next()) { | |
6390 RelocInfo* rinfo = it.rinfo(); | 6362 RelocInfo* rinfo = it.rinfo(); |
6391 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 6363 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
6392 Object* obj = rinfo->target_object(); | 6364 Object* obj = rinfo->target_object(); |
6393 if (obj->IsSharedFunctionInfo()) { | 6365 if (obj->IsSharedFunctionInfo()) { |
6394 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 6366 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
6395 if (shared->start_position() == start_position) { | 6367 if (shared->start_position() == start_position) { |
6396 return Handle<SharedFunctionInfo>(shared); | 6368 return Handle<SharedFunctionInfo>(shared); |
6397 } | 6369 } |
6398 } | 6370 } |
6399 } | 6371 } |
6400 | 6372 |
6401 return Handle<SharedFunctionInfo>(); | 6373 return Handle<SharedFunctionInfo>(); |
6402 } | 6374 } |
6403 | 6375 |
6404 | 6376 |
6405 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 6377 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
6406 ASSERT(!HasStackOverflow()); | 6378 ASSERT(!HasStackOverflow()); |
6407 ASSERT(current_block() != NULL); | 6379 ASSERT(current_block() != NULL); |
6408 ASSERT(current_block()->HasPredecessor()); | 6380 ASSERT(current_block()->HasPredecessor()); |
6409 Handle<SharedFunctionInfo> shared_info = | 6381 Handle<SharedFunctionInfo> shared_info = |
6410 SearchSharedFunctionInfo(info()->shared_info()->code(), | 6382 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); |
6411 expr); | |
6412 if (shared_info.is_null()) { | 6383 if (shared_info.is_null()) { |
6413 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 6384 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
6414 } | 6385 } |
6415 // We also have a stack overflow if the recursive compilation did. | 6386 // We also have a stack overflow if the recursive compilation did. |
6416 if (HasStackOverflow()) return; | 6387 if (HasStackOverflow()) return; |
6417 HValue* context = environment()->LookupContext(); | 6388 HValue* context = environment()->LookupContext(); |
6418 HFunctionLiteral* instr = | 6389 HFunctionLiteral* instr = |
6419 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 6390 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
6420 return ast_context()->ReturnInstruction(instr, expr->id()); | 6391 return ast_context()->ReturnInstruction(instr, expr->id()); |
6421 } | 6392 } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6827 Literal* key = property->key(); | 6798 Literal* key = property->key(); |
6828 Expression* value = property->value(); | 6799 Expression* value = property->value(); |
6829 | 6800 |
6830 switch (property->kind()) { | 6801 switch (property->kind()) { |
6831 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 6802 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
6832 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 6803 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
6833 // Fall through. | 6804 // Fall through. |
6834 case ObjectLiteral::Property::COMPUTED: | 6805 case ObjectLiteral::Property::COMPUTED: |
6835 if (key->handle()->IsInternalizedString()) { | 6806 if (key->handle()->IsInternalizedString()) { |
6836 if (property->emit_store()) { | 6807 if (property->emit_store()) { |
6837 property->RecordTypeFeedback(oracle()); | |
6838 CHECK_ALIVE(VisitForValue(value)); | 6808 CHECK_ALIVE(VisitForValue(value)); |
6839 HValue* value = Pop(); | 6809 HValue* value = Pop(); |
6840 Handle<Map> map = property->GetReceiverType(); | 6810 Handle<Map> map = property->GetReceiverType(); |
6841 Handle<String> name = property->key()->AsPropertyName(); | 6811 Handle<String> name = property->key()->AsPropertyName(); |
6842 HInstruction* store; | 6812 HInstruction* store; |
6843 if (map.is_null()) { | 6813 if (map.is_null()) { |
6844 // If we don't know the monomorphic type, do a generic store. | 6814 // If we don't know the monomorphic type, do a generic store. |
6845 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); | 6815 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); |
6846 } else { | 6816 } else { |
6847 #if DEBUG | 6817 #if DEBUG |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7398 ASSERT(join != NULL); | 7368 ASSERT(join != NULL); |
7399 join->SetJoinId(expr->id()); | 7369 join->SetJoinId(expr->id()); |
7400 set_current_block(join); | 7370 set_current_block(join); |
7401 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 7371 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
7402 } | 7372 } |
7403 | 7373 |
7404 | 7374 |
7405 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 7375 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
7406 Property* prop = expr->target()->AsProperty(); | 7376 Property* prop = expr->target()->AsProperty(); |
7407 ASSERT(prop != NULL); | 7377 ASSERT(prop != NULL); |
7408 expr->RecordTypeFeedback(oracle(), zone()); | |
7409 CHECK_ALIVE(VisitForValue(prop->obj())); | 7378 CHECK_ALIVE(VisitForValue(prop->obj())); |
7410 | 7379 |
7411 if (prop->key()->IsPropertyName()) { | 7380 if (prop->key()->IsPropertyName()) { |
7412 // Named store. | 7381 // Named store. |
7413 CHECK_ALIVE(VisitForValue(expr->value())); | 7382 CHECK_ALIVE(VisitForValue(expr->value())); |
7414 HValue* value = environment()->ExpressionStackAt(0); | 7383 HValue* value = environment()->ExpressionStackAt(0); |
7415 HValue* object = environment()->ExpressionStackAt(1); | 7384 HValue* object = environment()->ExpressionStackAt(1); |
7416 | 7385 |
7417 Literal* key = prop->key()->AsLiteral(); | 7386 Literal* key = prop->key()->AsLiteral(); |
7418 Handle<String> name = Handle<String>::cast(key->handle()); | 7387 Handle<String> name = Handle<String>::cast(key->handle()); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7596 } | 7565 } |
7597 break; | 7566 break; |
7598 } | 7567 } |
7599 | 7568 |
7600 case Variable::LOOKUP: | 7569 case Variable::LOOKUP: |
7601 return Bailout("compound assignment to lookup slot"); | 7570 return Bailout("compound assignment to lookup slot"); |
7602 } | 7571 } |
7603 return ast_context()->ReturnValue(Pop()); | 7572 return ast_context()->ReturnValue(Pop()); |
7604 | 7573 |
7605 } else if (prop != NULL) { | 7574 } else if (prop != NULL) { |
7606 prop->RecordTypeFeedback(oracle(), zone()); | |
7607 | |
7608 if (prop->key()->IsPropertyName()) { | 7575 if (prop->key()->IsPropertyName()) { |
7609 // Named property. | 7576 // Named property. |
7610 CHECK_ALIVE(VisitForValue(prop->obj())); | 7577 CHECK_ALIVE(VisitForValue(prop->obj())); |
7611 HValue* object = Top(); | 7578 HValue* object = Top(); |
7612 | 7579 |
7613 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 7580 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
7614 Handle<Map> map; | 7581 Handle<Map> map; |
7615 HInstruction* load; | 7582 HInstruction* load; |
7616 bool monomorphic = prop->IsMonomorphic(); | 7583 bool monomorphic = prop->IsMonomorphic(); |
7617 if (monomorphic) { | 7584 if (monomorphic) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7679 HValue* key = environment()->ExpressionStackAt(0); | 7646 HValue* key = environment()->ExpressionStackAt(0); |
7680 | 7647 |
7681 bool has_side_effects = false; | 7648 bool has_side_effects = false; |
7682 HValue* load = HandleKeyedElementAccess( | 7649 HValue* load = HandleKeyedElementAccess( |
7683 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 7650 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
7684 false, // is_store | 7651 false, // is_store |
7685 &has_side_effects); | 7652 &has_side_effects); |
7686 Push(load); | 7653 Push(load); |
7687 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7654 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7688 | 7655 |
7689 | |
7690 CHECK_ALIVE(VisitForValue(expr->value())); | 7656 CHECK_ALIVE(VisitForValue(expr->value())); |
7691 HValue* right = Pop(); | 7657 HValue* right = Pop(); |
7692 HValue* left = Pop(); | 7658 HValue* left = Pop(); |
7693 | 7659 |
7694 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 7660 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
7695 PushAndAdd(instr); | 7661 PushAndAdd(instr); |
7696 if (instr->HasObservableSideEffects()) { | 7662 if (instr->HasObservableSideEffects()) { |
7697 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 7663 AddSimulate(operation->id(), REMOVABLE_SIMULATE); |
7698 } | 7664 } |
7699 | 7665 |
7700 expr->RecordTypeFeedback(oracle(), zone()); | |
7701 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 7666 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
7702 RelocInfo::kNoPosition, | 7667 RelocInfo::kNoPosition, |
7703 true, // is_store | 7668 true, // is_store |
7704 &has_side_effects); | 7669 &has_side_effects); |
7705 | 7670 |
7706 // Drop the simulated receiver, key, and value. Return the value. | 7671 // Drop the simulated receiver, key, and value. Return the value. |
7707 Drop(3); | 7672 Drop(3); |
7708 Push(instr); | 7673 Push(instr); |
7709 ASSERT(has_side_effects); // Stores always have side effects. | 7674 ASSERT(has_side_effects); // Stores always have side effects. |
7710 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7675 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8443 } | 8408 } |
8444 ast_context()->ReturnInstruction(result, expr->id()); | 8409 ast_context()->ReturnInstruction(result, expr->id()); |
8445 return true; | 8410 return true; |
8446 } | 8411 } |
8447 | 8412 |
8448 | 8413 |
8449 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 8414 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
8450 ASSERT(!HasStackOverflow()); | 8415 ASSERT(!HasStackOverflow()); |
8451 ASSERT(current_block() != NULL); | 8416 ASSERT(current_block() != NULL); |
8452 ASSERT(current_block()->HasPredecessor()); | 8417 ASSERT(current_block()->HasPredecessor()); |
8453 expr->RecordTypeFeedback(oracle(), zone()); | |
8454 | 8418 |
8455 if (TryArgumentsAccess(expr)) return; | 8419 if (TryArgumentsAccess(expr)) return; |
8456 | 8420 |
8457 CHECK_ALIVE(VisitForValue(expr->obj())); | 8421 CHECK_ALIVE(VisitForValue(expr->obj())); |
8458 | 8422 |
8459 HInstruction* instr = NULL; | 8423 HInstruction* instr = NULL; |
8460 if (expr->IsStringLength()) { | 8424 if (expr->IsStringLength()) { |
8461 HValue* string = Pop(); | 8425 HValue* string = Pop(); |
8462 BuildCheckNonSmi(string); | 8426 BuildCheckNonSmi(string); |
8463 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8427 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8934 target_shared->EnableDeoptimizationSupport(*target_info.code()); | 8898 target_shared->EnableDeoptimizationSupport(*target_info.code()); |
8935 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, | 8899 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, |
8936 &target_info, | 8900 &target_info, |
8937 target_shared); | 8901 target_shared); |
8938 } | 8902 } |
8939 | 8903 |
8940 // ---------------------------------------------------------------- | 8904 // ---------------------------------------------------------------- |
8941 // After this point, we've made a decision to inline this function (so | 8905 // After this point, we've made a decision to inline this function (so |
8942 // TryInline should always return true). | 8906 // TryInline should always return true). |
8943 | 8907 |
8944 // Save the pending call context and type feedback oracle. Set up new ones | 8908 // Type-check the inlined function. |
8945 // for the inlined function. | |
8946 ASSERT(target_shared->has_deoptimization_support()); | 8909 ASSERT(target_shared->has_deoptimization_support()); |
8947 Handle<Code> unoptimized_code(target_shared->code()); | 8910 AstTyper::Type(&target_info); |
8948 TypeFeedbackOracle target_oracle( | 8911 |
8949 unoptimized_code, | 8912 // Save the pending call context. Set up new one for the inlined function. |
8950 Handle<Context>(target->context()->native_context()), | |
8951 isolate(), | |
8952 zone()); | |
8953 // The function state is new-allocated because we need to delete it | 8913 // The function state is new-allocated because we need to delete it |
8954 // in two different places. | 8914 // in two different places. |
8955 FunctionState* target_state = new FunctionState( | 8915 FunctionState* target_state = new FunctionState( |
8956 this, &target_info, &target_oracle, inlining_kind); | 8916 this, &target_info, inlining_kind); |
8957 | 8917 |
8958 HConstant* undefined = graph()->GetConstantUndefined(); | 8918 HConstant* undefined = graph()->GetConstantUndefined(); |
8959 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( | 8919 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( |
8960 target, function, call_kind, inlining_kind); | 8920 target, function, call_kind, inlining_kind); |
8961 HEnvironment* inner_env = | 8921 HEnvironment* inner_env = |
8962 environment()->CopyForInlining(target, | 8922 environment()->CopyForInlining(target, |
8963 arguments_count, | 8923 arguments_count, |
8964 function, | 8924 function, |
8965 undefined, | 8925 undefined, |
8966 function_state()->inlining_kind(), | 8926 function_state()->inlining_kind(), |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9020 TraceInline(target, caller, "inline graph construction failed"); | 8980 TraceInline(target, caller, "inline graph construction failed"); |
9021 target_shared->DisableOptimization("inlining bailed out"); | 8981 target_shared->DisableOptimization("inlining bailed out"); |
9022 inline_bailout_ = true; | 8982 inline_bailout_ = true; |
9023 delete target_state; | 8983 delete target_state; |
9024 return true; | 8984 return true; |
9025 } | 8985 } |
9026 | 8986 |
9027 // Update inlined nodes count. | 8987 // Update inlined nodes count. |
9028 inlined_count_ += nodes_added; | 8988 inlined_count_ += nodes_added; |
9029 | 8989 |
| 8990 Handle<Code> unoptimized_code(target_shared->code()); |
9030 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 8991 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
9031 Handle<TypeFeedbackInfo> type_info( | 8992 Handle<TypeFeedbackInfo> type_info( |
9032 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 8993 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
9033 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); | 8994 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); |
9034 | 8995 |
9035 TraceInline(target, caller, NULL); | 8996 TraceInline(target, caller, NULL); |
9036 | 8997 |
9037 if (current_block() != NULL) { | 8998 if (current_block() != NULL) { |
9038 FunctionState* state = function_state(); | 8999 FunctionState* state = function_state(); |
9039 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 9000 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9236 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 9197 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
9237 switch (id) { | 9198 switch (id) { |
9238 case kStringCharCodeAt: | 9199 case kStringCharCodeAt: |
9239 case kStringCharAt: | 9200 case kStringCharAt: |
9240 if (argument_count == 2 && check_type == STRING_CHECK) { | 9201 if (argument_count == 2 && check_type == STRING_CHECK) { |
9241 HValue* index = Pop(); | 9202 HValue* index = Pop(); |
9242 HValue* string = Pop(); | 9203 HValue* string = Pop(); |
9243 HValue* context = environment()->LookupContext(); | 9204 HValue* context = environment()->LookupContext(); |
9244 ASSERT(!expr->holder().is_null()); | 9205 ASSERT(!expr->holder().is_null()); |
9245 AddInstruction(new(zone()) HCheckPrototypeMaps( | 9206 AddInstruction(new(zone()) HCheckPrototypeMaps( |
9246 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), | 9207 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, |
| 9208 expr->holder()->GetIsolate()), |
9247 expr->holder(), | 9209 expr->holder(), |
9248 zone())); | 9210 zone())); |
9249 HInstruction* char_code = | 9211 HInstruction* char_code = |
9250 BuildStringCharCodeAt(context, string, index); | 9212 BuildStringCharCodeAt(context, string, index); |
9251 if (id == kStringCharCodeAt) { | 9213 if (id == kStringCharCodeAt) { |
9252 ast_context()->ReturnInstruction(char_code, expr->id()); | 9214 ast_context()->ReturnInstruction(char_code, expr->id()); |
9253 return true; | 9215 return true; |
9254 } | 9216 } |
9255 AddInstruction(char_code); | 9217 AddInstruction(char_code); |
9256 HInstruction* result = | 9218 HInstruction* result = |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9551 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 9513 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
9552 | 9514 |
9553 HValue* context = environment()->LookupContext(); | 9515 HValue* context = environment()->LookupContext(); |
9554 call = new(zone()) HCallKeyed(context, key, argument_count); | 9516 call = new(zone()) HCallKeyed(context, key, argument_count); |
9555 call->set_position(expr->position()); | 9517 call->set_position(expr->position()); |
9556 Drop(argument_count + 1); // 1 is the key. | 9518 Drop(argument_count + 1); // 1 is the key. |
9557 return ast_context()->ReturnInstruction(call, expr->id()); | 9519 return ast_context()->ReturnInstruction(call, expr->id()); |
9558 } | 9520 } |
9559 | 9521 |
9560 // Named function call. | 9522 // Named function call. |
9561 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); | |
9562 | |
9563 if (TryCallApply(expr)) return; | 9523 if (TryCallApply(expr)) return; |
9564 | 9524 |
9565 CHECK_ALIVE(VisitForValue(prop->obj())); | 9525 CHECK_ALIVE(VisitForValue(prop->obj())); |
9566 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9526 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
9567 | 9527 |
9568 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 9528 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
9569 SmallMapList* types = expr->GetReceiverTypes(); | 9529 SmallMapList* types = expr->GetReceiverTypes(); |
9570 | 9530 |
9571 bool monomorphic = expr->IsMonomorphic(); | 9531 bool monomorphic = expr->IsMonomorphic(); |
9572 Handle<Map> receiver_map; | 9532 Handle<Map> receiver_map; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9618 HandlePolymorphicCallNamed(expr, receiver, types, name); | 9578 HandlePolymorphicCallNamed(expr, receiver, types, name); |
9619 return; | 9579 return; |
9620 | 9580 |
9621 } else { | 9581 } else { |
9622 HValue* context = environment()->LookupContext(); | 9582 HValue* context = environment()->LookupContext(); |
9623 call = PreProcessCall( | 9583 call = PreProcessCall( |
9624 new(zone()) HCallNamed(context, name, argument_count)); | 9584 new(zone()) HCallNamed(context, name, argument_count)); |
9625 } | 9585 } |
9626 | 9586 |
9627 } else { | 9587 } else { |
9628 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); | |
9629 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9588 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
9630 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 9589 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
9631 | 9590 |
9632 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 9591 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
9633 return Bailout("possible direct call to eval"); | 9592 return Bailout("possible direct call to eval"); |
9634 } | 9593 } |
9635 | 9594 |
9636 if (global_call) { | 9595 if (global_call) { |
9637 Variable* var = proxy->var(); | 9596 Variable* var = proxy->var(); |
9638 bool known_global_function = false; | 9597 bool known_global_function = false; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9754 return constructor->has_initial_map() && | 9713 return constructor->has_initial_map() && |
9755 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 9714 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
9756 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 9715 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
9757 } | 9716 } |
9758 | 9717 |
9759 | 9718 |
9760 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 9719 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
9761 ASSERT(!HasStackOverflow()); | 9720 ASSERT(!HasStackOverflow()); |
9762 ASSERT(current_block() != NULL); | 9721 ASSERT(current_block() != NULL); |
9763 ASSERT(current_block()->HasPredecessor()); | 9722 ASSERT(current_block()->HasPredecessor()); |
9764 expr->RecordTypeFeedback(oracle()); | |
9765 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 9723 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
9766 HValue* context = environment()->LookupContext(); | 9724 HValue* context = environment()->LookupContext(); |
9767 | 9725 |
9768 if (FLAG_inline_construct && | 9726 if (FLAG_inline_construct && |
9769 expr->IsMonomorphic() && | 9727 expr->IsMonomorphic() && |
9770 IsAllocationInlineable(expr->target())) { | 9728 IsAllocationInlineable(expr->target())) { |
9771 // The constructor function is on the stack in the unoptimized code | 9729 // The constructor function is on the stack in the unoptimized code |
9772 // during evaluation of the arguments. | 9730 // during evaluation of the arguments. |
9773 CHECK_ALIVE(VisitForValue(expr->expression())); | 9731 CHECK_ALIVE(VisitForValue(expr->expression())); |
9774 HValue* function = Top(); | 9732 HValue* function = Top(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9814 CHECK_ALIVE(VisitArgument(expr->expression())); | 9772 CHECK_ALIVE(VisitArgument(expr->expression())); |
9815 HValue* constructor = HPushArgument::cast(Top())->argument(); | 9773 HValue* constructor = HPushArgument::cast(Top())->argument(); |
9816 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 9774 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
9817 HCallNew* call; | 9775 HCallNew* call; |
9818 if (use_call_new_array) { | 9776 if (use_call_new_array) { |
9819 // TODO(mvstanton): It would be better to use the already created global | 9777 // TODO(mvstanton): It would be better to use the already created global |
9820 // property cell that is shared by full code gen. That way, any transition | 9778 // property cell that is shared by full code gen. That way, any transition |
9821 // information that happened after crankshaft won't be lost. The right | 9779 // information that happened after crankshaft won't be lost. The right |
9822 // way to do that is to begin passing the cell to the type feedback oracle | 9780 // way to do that is to begin passing the cell to the type feedback oracle |
9823 // instead of just the value in the cell. Do this in a follow-up checkin. | 9781 // instead of just the value in the cell. Do this in a follow-up checkin. |
9824 Handle<Object> feedback = oracle()->GetInfo(expr->CallNewFeedbackId()); | 9782 Handle<Smi> feedback = expr->allocation_elements_kind(); |
9825 ASSERT(feedback->IsSmi()); | |
9826 Handle<JSGlobalPropertyCell> cell = | 9783 Handle<JSGlobalPropertyCell> cell = |
9827 isolate()->factory()->NewJSGlobalPropertyCell(feedback); | 9784 isolate()->factory()->NewJSGlobalPropertyCell(feedback); |
9828 | 9785 |
9829 // TODO(mvstanton): Here we should probably insert code to check if the | 9786 // TODO(mvstanton): Here we should probably insert code to check if the |
9830 // type cell elements kind is different from when we compiled, and deopt | 9787 // type cell elements kind is different from when we compiled, and deopt |
9831 // in that case. Do this in a follow-up checin. | 9788 // in that case. Do this in a follow-up checin. |
9832 call = new(zone()) HCallNewArray(context, constructor, argument_count, | 9789 call = new(zone()) HCallNewArray(context, constructor, argument_count, |
9833 cell); | 9790 cell); |
9834 } else { | 9791 } else { |
9835 call = new(zone()) HCallNew(context, constructor, argument_count); | 9792 call = new(zone()) HCallNew(context, constructor, argument_count); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9903 case Token::DELETE: return VisitDelete(expr); | 9860 case Token::DELETE: return VisitDelete(expr); |
9904 case Token::VOID: return VisitVoid(expr); | 9861 case Token::VOID: return VisitVoid(expr); |
9905 case Token::TYPEOF: return VisitTypeof(expr); | 9862 case Token::TYPEOF: return VisitTypeof(expr); |
9906 case Token::SUB: return VisitSub(expr); | 9863 case Token::SUB: return VisitSub(expr); |
9907 case Token::BIT_NOT: return VisitBitNot(expr); | 9864 case Token::BIT_NOT: return VisitBitNot(expr); |
9908 case Token::NOT: return VisitNot(expr); | 9865 case Token::NOT: return VisitNot(expr); |
9909 default: UNREACHABLE(); | 9866 default: UNREACHABLE(); |
9910 } | 9867 } |
9911 } | 9868 } |
9912 | 9869 |
| 9870 |
9913 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 9871 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
9914 Property* prop = expr->expression()->AsProperty(); | 9872 Property* prop = expr->expression()->AsProperty(); |
9915 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9873 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
9916 if (prop != NULL) { | 9874 if (prop != NULL) { |
9917 CHECK_ALIVE(VisitForValue(prop->obj())); | 9875 CHECK_ALIVE(VisitForValue(prop->obj())); |
9918 CHECK_ALIVE(VisitForValue(prop->key())); | 9876 CHECK_ALIVE(VisitForValue(prop->key())); |
9919 HValue* key = Pop(); | 9877 HValue* key = Pop(); |
9920 HValue* obj = Pop(); | 9878 HValue* obj = Pop(); |
9921 HValue* context = environment()->LookupContext(); | 9879 HValue* context = environment()->LookupContext(); |
9922 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); | 9880 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9959 return ast_context()->ReturnInstruction(instr, expr->id()); | 9917 return ast_context()->ReturnInstruction(instr, expr->id()); |
9960 } | 9918 } |
9961 | 9919 |
9962 | 9920 |
9963 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 9921 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
9964 CHECK_ALIVE(VisitForValue(expr->expression())); | 9922 CHECK_ALIVE(VisitForValue(expr->expression())); |
9965 HValue* value = Pop(); | 9923 HValue* value = Pop(); |
9966 HValue* context = environment()->LookupContext(); | 9924 HValue* context = environment()->LookupContext(); |
9967 HInstruction* instr = | 9925 HInstruction* instr = |
9968 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); | 9926 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); |
9969 TypeInfo info = oracle()->UnaryType(expr); | 9927 TypeInfo info = expr->type(); |
9970 Representation rep = ToRepresentation(info); | 9928 Representation rep = ToRepresentation(info); |
9971 if (info.IsUninitialized()) { | 9929 if (info.IsUninitialized()) { |
9972 AddSoftDeoptimize(); | 9930 AddSoftDeoptimize(); |
9973 info = TypeInfo::Unknown(); | 9931 info = TypeInfo::Unknown(); |
9974 } | 9932 } |
9975 if (instr->IsBinaryOperation()) { | 9933 if (instr->IsBinaryOperation()) { |
9976 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); | 9934 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); |
9977 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); | 9935 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); |
9978 } | 9936 } |
9979 return ast_context()->ReturnInstruction(instr, expr->id()); | 9937 return ast_context()->ReturnInstruction(instr, expr->id()); |
9980 } | 9938 } |
9981 | 9939 |
9982 | 9940 |
9983 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 9941 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
9984 CHECK_ALIVE(VisitForValue(expr->expression())); | 9942 CHECK_ALIVE(VisitForValue(expr->expression())); |
9985 HValue* value = Pop(); | 9943 HValue* value = Pop(); |
9986 TypeInfo info = oracle()->UnaryType(expr); | 9944 TypeInfo info = expr->type(); |
9987 if (info.IsUninitialized()) { | 9945 if (info.IsUninitialized()) { |
9988 AddSoftDeoptimize(); | 9946 AddSoftDeoptimize(); |
9989 } | 9947 } |
9990 HInstruction* instr = new(zone()) HBitNot(value); | 9948 HInstruction* instr = new(zone()) HBitNot(value); |
9991 return ast_context()->ReturnInstruction(instr, expr->id()); | 9949 return ast_context()->ReturnInstruction(instr, expr->id()); |
9992 } | 9950 } |
9993 | 9951 |
9994 | 9952 |
9995 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 9953 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
9996 if (ast_context()->IsTest()) { | 9954 if (ast_context()->IsTest()) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10033 CreateJoin(materialize_false, materialize_true, expr->id()); | 9991 CreateJoin(materialize_false, materialize_true, expr->id()); |
10034 set_current_block(join); | 9992 set_current_block(join); |
10035 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 9993 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
10036 } | 9994 } |
10037 | 9995 |
10038 | 9996 |
10039 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 9997 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
10040 bool returns_original_input, | 9998 bool returns_original_input, |
10041 CountOperation* expr) { | 9999 CountOperation* expr) { |
10042 // The input to the count operation is on top of the expression stack. | 10000 // The input to the count operation is on top of the expression stack. |
10043 TypeInfo info = oracle()->IncrementType(expr); | 10001 TypeInfo info = expr->type(); |
10044 Representation rep = ToRepresentation(info); | 10002 Representation rep = ToRepresentation(info); |
10045 if (rep.IsTagged()) { | 10003 if (rep.IsTagged()) { |
10046 rep = Representation::Integer32(); | 10004 rep = Representation::Integer32(); |
10047 } | 10005 } |
10048 | 10006 |
10049 if (returns_original_input) { | 10007 if (returns_original_input) { |
10050 // We need an explicit HValue representing ToNumber(input). The | 10008 // We need an explicit HValue representing ToNumber(input). The |
10051 // actual HChange instruction we need is (sometimes) added in a later | 10009 // actual HChange instruction we need is (sometimes) added in a later |
10052 // phase, so it is not available now to be used as an input to HAdd and | 10010 // phase, so it is not available now to be used as an input to HAdd and |
10053 // as the return value. | 10011 // as the return value. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10147 break; | 10105 break; |
10148 } | 10106 } |
10149 | 10107 |
10150 case Variable::LOOKUP: | 10108 case Variable::LOOKUP: |
10151 return Bailout("lookup variable in count operation"); | 10109 return Bailout("lookup variable in count operation"); |
10152 } | 10110 } |
10153 | 10111 |
10154 } else { | 10112 } else { |
10155 // Argument of the count operation is a property. | 10113 // Argument of the count operation is a property. |
10156 ASSERT(prop != NULL); | 10114 ASSERT(prop != NULL); |
10157 prop->RecordTypeFeedback(oracle(), zone()); | |
10158 | 10115 |
10159 if (prop->key()->IsPropertyName()) { | 10116 if (prop->key()->IsPropertyName()) { |
10160 // Named property. | 10117 // Named property. |
10161 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 10118 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
10162 | 10119 |
10163 CHECK_ALIVE(VisitForValue(prop->obj())); | 10120 CHECK_ALIVE(VisitForValue(prop->obj())); |
10164 HValue* object = Top(); | 10121 HValue* object = Top(); |
10165 | 10122 |
10166 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 10123 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
10167 Handle<Map> map; | 10124 Handle<Map> map; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10230 HValue* load = HandleKeyedElementAccess( | 10187 HValue* load = HandleKeyedElementAccess( |
10231 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 10188 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
10232 false, // is_store | 10189 false, // is_store |
10233 &has_side_effects); | 10190 &has_side_effects); |
10234 Push(load); | 10191 Push(load); |
10235 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 10192 if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
10236 | 10193 |
10237 after = BuildIncrement(returns_original_input, expr); | 10194 after = BuildIncrement(returns_original_input, expr); |
10238 input = environment()->ExpressionStackAt(0); | 10195 input = environment()->ExpressionStackAt(0); |
10239 | 10196 |
10240 expr->RecordTypeFeedback(oracle(), zone()); | |
10241 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | 10197 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), |
10242 RelocInfo::kNoPosition, | 10198 RelocInfo::kNoPosition, |
10243 true, // is_store | 10199 true, // is_store |
10244 &has_side_effects); | 10200 &has_side_effects); |
10245 | 10201 |
10246 // Drop the key and the original value from the bailout environment. | 10202 // Drop the key and the original value from the bailout environment. |
10247 // Overwrite the receiver with the result of the operation, and the | 10203 // Overwrite the receiver with the result of the operation, and the |
10248 // placeholder with the original value if necessary. | 10204 // placeholder with the original value if necessary. |
10249 Drop(2); | 10205 Drop(2); |
10250 environment()->SetExpressionStackAt(0, after); | 10206 environment()->SetExpressionStackAt(0, after); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10339 } | 10295 } |
10340 return true; | 10296 return true; |
10341 } | 10297 } |
10342 | 10298 |
10343 | 10299 |
10344 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 10300 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
10345 BinaryOperation* expr, | 10301 BinaryOperation* expr, |
10346 HValue* left, | 10302 HValue* left, |
10347 HValue* right) { | 10303 HValue* right) { |
10348 HValue* context = environment()->LookupContext(); | 10304 HValue* context = environment()->LookupContext(); |
10349 TypeInfo left_info, right_info, result_info, combined_info; | 10305 TypeInfo left_info = expr->left_type(); |
10350 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); | 10306 TypeInfo right_info = expr->right_type(); |
| 10307 TypeInfo result_info = expr->result_type(); |
| 10308 TypeInfo combined_info; |
10351 Representation left_rep = ToRepresentation(left_info); | 10309 Representation left_rep = ToRepresentation(left_info); |
10352 Representation right_rep = ToRepresentation(right_info); | 10310 Representation right_rep = ToRepresentation(right_info); |
10353 Representation result_rep = ToRepresentation(result_info); | 10311 Representation result_rep = ToRepresentation(result_info); |
10354 if (left_info.IsUninitialized()) { | 10312 if (left_info.IsUninitialized()) { |
10355 // Can't have initialized one but not the other. | 10313 // Can't have initialized one but not the other. |
10356 ASSERT(right_info.IsUninitialized()); | 10314 ASSERT(right_info.IsUninitialized()); |
10357 AddSoftDeoptimize(); | 10315 AddSoftDeoptimize(); |
10358 left_info = right_info = TypeInfo::Unknown(); | 10316 left_info = right_info = TypeInfo::Unknown(); |
10359 } | 10317 } |
10360 HInstruction* instr = NULL; | 10318 HInstruction* instr = NULL; |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10498 (!is_logical_and && !left_constant->BooleanValue())) { | 10456 (!is_logical_and && !left_constant->BooleanValue())) { |
10499 Drop(1); // left_value. | 10457 Drop(1); // left_value. |
10500 CHECK_BAILOUT(VisitForValue(expr->right())); | 10458 CHECK_BAILOUT(VisitForValue(expr->right())); |
10501 } | 10459 } |
10502 return ast_context()->ReturnValue(Pop()); | 10460 return ast_context()->ReturnValue(Pop()); |
10503 } | 10461 } |
10504 | 10462 |
10505 // We need an extra block to maintain edge-split form. | 10463 // We need an extra block to maintain edge-split form. |
10506 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 10464 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
10507 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 10465 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
10508 TypeFeedbackId test_id = expr->left()->test_id(); | 10466 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); |
10509 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); | |
10510 HBranch* test = is_logical_and | 10467 HBranch* test = is_logical_and |
10511 ? new(zone()) HBranch(left_value, eval_right, empty_block, expected) | 10468 ? new(zone()) HBranch(left_value, eval_right, empty_block, expected) |
10512 : new(zone()) HBranch(left_value, empty_block, eval_right, expected); | 10469 : new(zone()) HBranch(left_value, empty_block, eval_right, expected); |
10513 current_block()->Finish(test); | 10470 current_block()->Finish(test); |
10514 | 10471 |
10515 set_current_block(eval_right); | 10472 set_current_block(eval_right); |
10516 Drop(1); // Value of the left subexpression. | 10473 Drop(1); // Value of the left subexpression. |
10517 CHECK_BAILOUT(VisitForValue(expr->right())); | 10474 CHECK_BAILOUT(VisitForValue(expr->right())); |
10518 | 10475 |
10519 HBasicBlock* join_block = | 10476 HBasicBlock* join_block = |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10667 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10624 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
10668 HValue* value = Pop(); | 10625 HValue* value = Pop(); |
10669 Literal* literal = expr->right()->AsLiteral(); | 10626 Literal* literal = expr->right()->AsLiteral(); |
10670 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 10627 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
10671 HClassOfTestAndBranch* instr = | 10628 HClassOfTestAndBranch* instr = |
10672 new(zone()) HClassOfTestAndBranch(value, rhs); | 10629 new(zone()) HClassOfTestAndBranch(value, rhs); |
10673 instr->set_position(expr->position()); | 10630 instr->set_position(expr->position()); |
10674 return ast_context()->ReturnControl(instr, expr->id()); | 10631 return ast_context()->ReturnControl(instr, expr->id()); |
10675 } | 10632 } |
10676 | 10633 |
10677 TypeInfo left_type, right_type, overall_type_info; | 10634 TypeInfo left_type = expr->left_type(); |
10678 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info); | 10635 TypeInfo right_type = expr->right_type(); |
10679 Representation combined_rep = ToRepresentation(overall_type_info); | 10636 TypeInfo overall_type = expr->overall_type(); |
| 10637 Representation combined_rep = ToRepresentation(overall_type); |
10680 Representation left_rep = ToRepresentation(left_type); | 10638 Representation left_rep = ToRepresentation(left_type); |
10681 Representation right_rep = ToRepresentation(right_type); | 10639 Representation right_rep = ToRepresentation(right_type); |
10682 // Check if this expression was ever executed according to type feedback. | 10640 // Check if this expression was ever executed according to type feedback. |
10683 // Note that for the special typeof/null/undefined cases we get unknown here. | 10641 // Note that for the special typeof/null/undefined cases we get unknown here. |
10684 if (overall_type_info.IsUninitialized()) { | 10642 if (overall_type.IsUninitialized()) { |
10685 AddSoftDeoptimize(); | 10643 AddSoftDeoptimize(); |
10686 overall_type_info = left_type = right_type = TypeInfo::Unknown(); | 10644 overall_type = left_type = right_type = TypeInfo::Unknown(); |
10687 } | 10645 } |
10688 | 10646 |
10689 CHECK_ALIVE(VisitForValue(expr->left())); | 10647 CHECK_ALIVE(VisitForValue(expr->left())); |
10690 CHECK_ALIVE(VisitForValue(expr->right())); | 10648 CHECK_ALIVE(VisitForValue(expr->right())); |
10691 | 10649 |
10692 HValue* context = environment()->LookupContext(); | 10650 HValue* context = environment()->LookupContext(); |
10693 HValue* right = Pop(); | 10651 HValue* right = Pop(); |
10694 HValue* left = Pop(); | 10652 HValue* left = Pop(); |
10695 Token::Value op = expr->op(); | 10653 Token::Value op = expr->op(); |
10696 | 10654 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10748 AddInstruction(new(zone()) HCheckFunction(right, target)); | 10706 AddInstruction(new(zone()) HCheckFunction(right, target)); |
10749 HInstanceOfKnownGlobal* result = | 10707 HInstanceOfKnownGlobal* result = |
10750 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 10708 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
10751 result->set_position(expr->position()); | 10709 result->set_position(expr->position()); |
10752 return ast_context()->ReturnInstruction(result, expr->id()); | 10710 return ast_context()->ReturnInstruction(result, expr->id()); |
10753 } | 10711 } |
10754 } else if (op == Token::IN) { | 10712 } else if (op == Token::IN) { |
10755 HIn* result = new(zone()) HIn(context, left, right); | 10713 HIn* result = new(zone()) HIn(context, left, right); |
10756 result->set_position(expr->position()); | 10714 result->set_position(expr->position()); |
10757 return ast_context()->ReturnInstruction(result, expr->id()); | 10715 return ast_context()->ReturnInstruction(result, expr->id()); |
10758 } else if (overall_type_info.IsNonPrimitive()) { | 10716 } else if (overall_type.IsNonPrimitive()) { |
10759 switch (op) { | 10717 switch (op) { |
10760 case Token::EQ: | 10718 case Token::EQ: |
10761 case Token::EQ_STRICT: { | 10719 case Token::EQ_STRICT: { |
10762 // Can we get away with map check and not instance type check? | 10720 // Can we get away with map check and not instance type check? |
10763 Handle<Map> map = oracle()->GetCompareMap(expr); | 10721 Handle<Map> map = expr->map(); |
10764 if (!map.is_null()) { | 10722 if (!map.is_null()) { |
10765 AddCheckMapsWithTransitions(left, map); | 10723 AddCheckMapsWithTransitions(left, map); |
10766 AddCheckMapsWithTransitions(right, map); | 10724 AddCheckMapsWithTransitions(right, map); |
10767 HCompareObjectEqAndBranch* result = | 10725 HCompareObjectEqAndBranch* result = |
10768 new(zone()) HCompareObjectEqAndBranch(left, right); | 10726 new(zone()) HCompareObjectEqAndBranch(left, right); |
10769 result->set_position(expr->position()); | 10727 result->set_position(expr->position()); |
10770 return ast_context()->ReturnControl(result, expr->id()); | 10728 return ast_context()->ReturnControl(result, expr->id()); |
10771 } else { | 10729 } else { |
10772 BuildCheckNonSmi(left); | 10730 BuildCheckNonSmi(left); |
10773 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 10731 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
10774 BuildCheckNonSmi(right); | 10732 BuildCheckNonSmi(right); |
10775 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 10733 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
10776 HCompareObjectEqAndBranch* result = | 10734 HCompareObjectEqAndBranch* result = |
10777 new(zone()) HCompareObjectEqAndBranch(left, right); | 10735 new(zone()) HCompareObjectEqAndBranch(left, right); |
10778 result->set_position(expr->position()); | 10736 result->set_position(expr->position()); |
10779 return ast_context()->ReturnControl(result, expr->id()); | 10737 return ast_context()->ReturnControl(result, expr->id()); |
10780 } | 10738 } |
10781 } | 10739 } |
10782 default: | 10740 default: |
10783 return Bailout("Unsupported non-primitive compare"); | 10741 return Bailout("Unsupported non-primitive compare"); |
10784 } | 10742 } |
10785 } else if (overall_type_info.IsInternalizedString() && | 10743 } else if (overall_type.IsInternalizedString() && |
10786 Token::IsEqualityOp(op)) { | 10744 Token::IsEqualityOp(op)) { |
10787 BuildCheckNonSmi(left); | 10745 BuildCheckNonSmi(left); |
10788 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 10746 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
10789 BuildCheckNonSmi(right); | 10747 BuildCheckNonSmi(right); |
10790 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 10748 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
10791 HCompareObjectEqAndBranch* result = | 10749 HCompareObjectEqAndBranch* result = |
10792 new(zone()) HCompareObjectEqAndBranch(left, right); | 10750 new(zone()) HCompareObjectEqAndBranch(left, right); |
10793 result->set_position(expr->position()); | 10751 result->set_position(expr->position()); |
10794 return ast_context()->ReturnControl(result, expr->id()); | 10752 return ast_context()->ReturnControl(result, expr->id()); |
10795 } else { | 10753 } else { |
(...skipping 17 matching lines...) Expand all Loading... |
10813 | 10771 |
10814 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 10772 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
10815 HValue* value, | 10773 HValue* value, |
10816 NilValue nil) { | 10774 NilValue nil) { |
10817 ASSERT(!HasStackOverflow()); | 10775 ASSERT(!HasStackOverflow()); |
10818 ASSERT(current_block() != NULL); | 10776 ASSERT(current_block() != NULL); |
10819 ASSERT(current_block()->HasPredecessor()); | 10777 ASSERT(current_block()->HasPredecessor()); |
10820 EqualityKind kind = | 10778 EqualityKind kind = |
10821 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; | 10779 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; |
10822 HIfContinuation continuation; | 10780 HIfContinuation continuation; |
10823 TypeFeedbackId id = expr->CompareOperationFeedbackId(); | |
10824 CompareNilICStub::Types types; | 10781 CompareNilICStub::Types types; |
10825 if (kind == kStrictEquality) { | 10782 if (kind == kStrictEquality) { |
10826 if (nil == kNullValue) { | 10783 if (nil == kNullValue) { |
10827 types = CompareNilICStub::kCompareAgainstNull; | 10784 types = CompareNilICStub::kCompareAgainstNull; |
10828 } else { | 10785 } else { |
10829 types = CompareNilICStub::kCompareAgainstUndefined; | 10786 types = CompareNilICStub::kCompareAgainstUndefined; |
10830 } | 10787 } |
10831 } else { | 10788 } else { |
10832 types = static_cast<CompareNilICStub::Types>( | 10789 types = static_cast<CompareNilICStub::Types>(expr->compare_nil_types()); |
10833 oracle()->CompareNilTypes(id)); | |
10834 if (types == 0) types = CompareNilICStub::kFullCompare; | 10790 if (types == 0) types = CompareNilICStub::kFullCompare; |
10835 } | 10791 } |
10836 Handle<Map> map_handle(oracle()->CompareNilMonomorphicReceiverType(id)); | 10792 Handle<Map> map_handle = expr->map(); |
10837 BuildCompareNil(value, kind, types, map_handle, | 10793 BuildCompareNil(value, kind, types, map_handle, |
10838 expr->position(), &continuation); | 10794 expr->position(), &continuation); |
10839 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 10795 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
10840 } | 10796 } |
10841 | 10797 |
10842 | 10798 |
10843 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 10799 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
10844 // If we share optimized code between different closures, the | 10800 // If we share optimized code between different closures, the |
10845 // this-function is not a constant, except inside an inlined body. | 10801 // this-function is not a constant, except inside an inlined body. |
10846 if (function_state()->outer() != NULL) { | 10802 if (function_state()->outer() != NULL) { |
(...skipping 1612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12459 } | 12415 } |
12460 } | 12416 } |
12461 | 12417 |
12462 #ifdef DEBUG | 12418 #ifdef DEBUG |
12463 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12419 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
12464 if (allocator_ != NULL) allocator_->Verify(); | 12420 if (allocator_ != NULL) allocator_->Verify(); |
12465 #endif | 12421 #endif |
12466 } | 12422 } |
12467 | 12423 |
12468 } } // namespace v8::internal | 12424 } } // namespace v8::internal |
OLD | NEW |