OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
879 | 879 |
880 class HRangeAnalysis BASE_EMBEDDED { | 880 class HRangeAnalysis BASE_EMBEDDED { |
881 public: | 881 public: |
882 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} | 882 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} |
883 | 883 |
884 void Analyze(); | 884 void Analyze(); |
885 | 885 |
886 private: | 886 private: |
887 void TraceRange(const char* msg, ...); | 887 void TraceRange(const char* msg, ...); |
888 void Analyze(HBasicBlock* block); | 888 void Analyze(HBasicBlock* block); |
889 void InferControlFlowRange(HTest* test, HBasicBlock* dest); | 889 void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest); |
890 void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); | 890 void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other); |
891 void InferPhiRange(HPhi* phi); | |
892 void InferRange(HValue* value); | 891 void InferRange(HValue* value); |
893 void RollBackTo(int index); | 892 void RollBackTo(int index); |
894 void AddRange(HValue* value, Range* range); | 893 void AddRange(HValue* value, Range* range); |
895 | 894 |
896 HGraph* graph_; | 895 HGraph* graph_; |
897 ZoneList<HValue*> changed_ranges_; | 896 ZoneList<HValue*> changed_ranges_; |
898 }; | 897 }; |
899 | 898 |
900 | 899 |
901 void HRangeAnalysis::TraceRange(const char* msg, ...) { | 900 void HRangeAnalysis::TraceRange(const char* msg, ...) { |
(...skipping 13 matching lines...) Expand all Loading... | |
915 | 914 |
916 | 915 |
917 void HRangeAnalysis::Analyze(HBasicBlock* block) { | 916 void HRangeAnalysis::Analyze(HBasicBlock* block) { |
918 TraceRange("Analyzing block B%d\n", block->block_id()); | 917 TraceRange("Analyzing block B%d\n", block->block_id()); |
919 | 918 |
920 int last_changed_range = changed_ranges_.length() - 1; | 919 int last_changed_range = changed_ranges_.length() - 1; |
921 | 920 |
922 // Infer range based on control flow. | 921 // Infer range based on control flow. |
923 if (block->predecessors()->length() == 1) { | 922 if (block->predecessors()->length() == 1) { |
924 HBasicBlock* pred = block->predecessors()->first(); | 923 HBasicBlock* pred = block->predecessors()->first(); |
925 if (pred->end()->IsTest()) { | 924 if (pred->end()->IsCompareIDAndBranch()) { |
926 InferControlFlowRange(HTest::cast(pred->end()), block); | 925 InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block); |
927 } | 926 } |
928 } | 927 } |
929 | 928 |
930 // Process phi instructions. | 929 // Process phi instructions. |
931 for (int i = 0; i < block->phis()->length(); ++i) { | 930 for (int i = 0; i < block->phis()->length(); ++i) { |
932 HPhi* phi = block->phis()->at(i); | 931 HPhi* phi = block->phis()->at(i); |
933 InferPhiRange(phi); | 932 InferRange(phi); |
934 } | 933 } |
935 | 934 |
936 // Go through all instructions of the current block. | 935 // Go through all instructions of the current block. |
937 HInstruction* instr = block->first(); | 936 HInstruction* instr = block->first(); |
938 while (instr != block->end()) { | 937 while (instr != block->end()) { |
939 InferRange(instr); | 938 InferRange(instr); |
940 instr = instr->next(); | 939 instr = instr->next(); |
941 } | 940 } |
942 | 941 |
943 // Continue analysis in all dominated blocks. | 942 // Continue analysis in all dominated blocks. |
944 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { | 943 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
945 Analyze(block->dominated_blocks()->at(i)); | 944 Analyze(block->dominated_blocks()->at(i)); |
946 } | 945 } |
947 | 946 |
948 RollBackTo(last_changed_range); | 947 RollBackTo(last_changed_range); |
949 } | 948 } |
950 | 949 |
951 | 950 |
952 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { | 951 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, |
952 HBasicBlock* dest) { | |
953 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | 953 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); |
954 if (test->value()->IsCompare()) { | 954 if (test->GetInputRepresentation().IsInteger32()) { |
955 HCompare* compare = HCompare::cast(test->value()); | 955 Token::Value op = test->token(); |
956 if (compare->GetInputRepresentation().IsInteger32()) { | 956 if (test->SecondSuccessor() == dest) { |
957 Token::Value op = compare->token(); | 957 op = Token::NegateCompareOp(op); |
958 if (test->SecondSuccessor() == dest) { | |
959 op = Token::NegateCompareOp(op); | |
960 } | |
961 Token::Value inverted_op = Token::InvertCompareOp(op); | |
962 InferControlFlowRange(op, compare->left(), compare->right()); | |
963 InferControlFlowRange(inverted_op, compare->right(), compare->left()); | |
964 } | 958 } |
959 Token::Value inverted_op = Token::InvertCompareOp(op); | |
960 UpdateControlFlowRange(op, test->left(), test->right()); | |
961 UpdateControlFlowRange(inverted_op, test->right(), test->left()); | |
965 } | 962 } |
966 } | 963 } |
967 | 964 |
968 | 965 |
969 // We know that value [op] other. Use this information to update the range on | 966 // We know that value [op] other. Use this information to update the range on |
970 // value. | 967 // value. |
971 void HRangeAnalysis::InferControlFlowRange(Token::Value op, | 968 void HRangeAnalysis::UpdateControlFlowRange(Token::Value op, |
972 HValue* value, | 969 HValue* value, |
973 HValue* other) { | 970 HValue* other) { |
974 Range temp_range; | 971 Range temp_range; |
975 Range* range = other->range() != NULL ? other->range() : &temp_range; | 972 Range* range = other->range() != NULL ? other->range() : &temp_range; |
976 Range* new_range = NULL; | 973 Range* new_range = NULL; |
977 | 974 |
978 TraceRange("Control flow range infer %d %s %d\n", | 975 TraceRange("Control flow range infer %d %s %d\n", |
979 value->id(), | 976 value->id(), |
980 Token::Name(op), | 977 Token::Name(op), |
981 other->id()); | 978 other->id()); |
982 | 979 |
983 if (op == Token::EQ || op == Token::EQ_STRICT) { | 980 if (op == Token::EQ || op == Token::EQ_STRICT) { |
(...skipping 10 matching lines...) Expand all Loading... | |
994 new_range->AddConstant(1); | 991 new_range->AddConstant(1); |
995 } | 992 } |
996 } | 993 } |
997 | 994 |
998 if (new_range != NULL && !new_range->IsMostGeneric()) { | 995 if (new_range != NULL && !new_range->IsMostGeneric()) { |
999 AddRange(value, new_range); | 996 AddRange(value, new_range); |
1000 } | 997 } |
1001 } | 998 } |
1002 | 999 |
1003 | 1000 |
1004 void HRangeAnalysis::InferPhiRange(HPhi* phi) { | |
1005 // TODO(twuerthinger): Infer loop phi ranges. | |
1006 InferRange(phi); | |
1007 } | |
1008 | |
1009 | |
1010 void HRangeAnalysis::InferRange(HValue* value) { | 1001 void HRangeAnalysis::InferRange(HValue* value) { |
1011 ASSERT(!value->HasRange()); | 1002 ASSERT(!value->HasRange()); |
1012 if (!value->representation().IsNone()) { | 1003 if (!value->representation().IsNone()) { |
1013 value->ComputeInitialRange(); | 1004 value->ComputeInitialRange(); |
1014 Range* range = value->range(); | 1005 Range* range = value->range(); |
1015 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", | 1006 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", |
1016 value->id(), | 1007 value->id(), |
1017 value->Mnemonic(), | 1008 value->Mnemonic(), |
1018 range->lower(), | 1009 range->lower(), |
1019 range->upper()); | 1010 range->upper()); |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1933 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); | 1924 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); |
1934 } | 1925 } |
1935 } | 1926 } |
1936 } | 1927 } |
1937 | 1928 |
1938 | 1929 |
1939 void HGraph::MarkDeoptimizeOnUndefined() { | 1930 void HGraph::MarkDeoptimizeOnUndefined() { |
1940 HPhase phase("MarkDeoptimizeOnUndefined", this); | 1931 HPhase phase("MarkDeoptimizeOnUndefined", this); |
1941 // Compute DeoptimizeOnUndefined flag for phis. | 1932 // Compute DeoptimizeOnUndefined flag for phis. |
1942 // Any phi that can reach a use with DeoptimizeOnUndefined set must | 1933 // Any phi that can reach a use with DeoptimizeOnUndefined set must |
1943 // have DeoptimizeOnUndefined set. Currently only HCompare, with | 1934 // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with |
1944 // double input representation, has this flag set. | 1935 // double input representation, has this flag set. |
1945 // The flag is used by HChange tagged->double, which must deoptimize | 1936 // The flag is used by HChange tagged->double, which must deoptimize |
1946 // if one of its uses has this flag set. | 1937 // if one of its uses has this flag set. |
1947 for (int i = 0; i < phi_list()->length(); i++) { | 1938 for (int i = 0; i < phi_list()->length(); i++) { |
1948 HPhi* phi = phi_list()->at(i); | 1939 HPhi* phi = phi_list()->at(i); |
1949 if (phi->representation().IsDouble()) { | 1940 if (phi->representation().IsDouble()) { |
1950 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { | 1941 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
1951 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) { | 1942 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) { |
1952 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); | 1943 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
1953 break; | 1944 break; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2071 owner()->Push(value); | 2062 owner()->Push(value); |
2072 } | 2063 } |
2073 | 2064 |
2074 | 2065 |
2075 void TestContext::ReturnValue(HValue* value) { | 2066 void TestContext::ReturnValue(HValue* value) { |
2076 BuildBranch(value); | 2067 BuildBranch(value); |
2077 } | 2068 } |
2078 | 2069 |
2079 | 2070 |
2080 void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { | 2071 void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
2072 ASSERT(!instr->IsControlInstruction()); | |
2081 owner()->AddInstruction(instr); | 2073 owner()->AddInstruction(instr); |
2082 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | 2074 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); |
2083 } | 2075 } |
2084 | 2076 |
2085 | 2077 |
2078 void EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) { | |
2079 ASSERT(!instr->HasSideEffects()); | |
2080 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | |
2081 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | |
2082 instr->SetSuccessorAt(0, empty_true); | |
2083 instr->SetSuccessorAt(1, empty_false); | |
2084 owner()->current_block()->Finish(instr); | |
2085 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | |
2086 owner()->set_current_block(join); | |
2087 } | |
2088 | |
2089 | |
2086 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { | 2090 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
2091 ASSERT(!instr->IsControlInstruction()); | |
2087 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2092 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2088 owner()->Bailout("bad value context for arguments object value"); | 2093 return owner()->Bailout("bad value context for arguments object value"); |
2089 } | 2094 } |
2090 owner()->AddInstruction(instr); | 2095 owner()->AddInstruction(instr); |
2091 owner()->Push(instr); | 2096 owner()->Push(instr); |
2092 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | 2097 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); |
2093 } | 2098 } |
2094 | 2099 |
2095 | 2100 |
2101 void ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) { | |
2102 ASSERT(!instr->HasSideEffects()); | |
2103 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | |
2104 return owner()->Bailout("bad value context for arguments object value"); | |
2105 } | |
2106 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | |
2107 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | |
2108 instr->SetSuccessorAt(0, materialize_true); | |
2109 instr->SetSuccessorAt(1, materialize_false); | |
2110 owner()->current_block()->Finish(instr); | |
2111 owner()->set_current_block(materialize_true); | |
2112 owner()->Push(owner()->graph()->GetConstantTrue()); | |
2113 owner()->set_current_block(materialize_false); | |
2114 owner()->Push(owner()->graph()->GetConstantFalse()); | |
2115 HBasicBlock* join = | |
2116 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | |
2117 owner()->set_current_block(join); | |
2118 ReturnValue(owner()->Pop()); | |
Kevin Millikin (Chromium)
2011/06/30 13:31:05
No need for this last line. All it does is check
| |
2119 } | |
2120 | |
2121 | |
2096 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { | 2122 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
2123 ASSERT(!instr->IsControlInstruction()); | |
2097 HGraphBuilder* builder = owner(); | 2124 HGraphBuilder* builder = owner(); |
2098 builder->AddInstruction(instr); | 2125 builder->AddInstruction(instr); |
2099 // We expect a simulate after every expression with side effects, though | 2126 // We expect a simulate after every expression with side effects, though |
2100 // this one isn't actually needed (and wouldn't work if it were targeted). | 2127 // this one isn't actually needed (and wouldn't work if it were targeted). |
2101 if (instr->HasSideEffects()) { | 2128 if (instr->HasSideEffects()) { |
2102 builder->Push(instr); | 2129 builder->Push(instr); |
2103 builder->AddSimulate(ast_id); | 2130 builder->AddSimulate(ast_id); |
2104 builder->Pop(); | 2131 builder->Pop(); |
2105 } | 2132 } |
2106 BuildBranch(instr); | 2133 BuildBranch(instr); |
2107 } | 2134 } |
2108 | 2135 |
2109 | 2136 |
2137 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { | |
2138 ASSERT(!instr->HasSideEffects()); | |
2139 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | |
2140 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | |
2141 instr->SetSuccessorAt(0, empty_true); | |
2142 instr->SetSuccessorAt(1, empty_false); | |
2143 owner()->current_block()->Finish(instr); | |
2144 empty_true->Goto(if_true()); | |
2145 empty_false->Goto(if_false()); | |
2146 owner()->set_current_block(NULL); | |
2147 } | |
2148 | |
2149 | |
2110 void TestContext::BuildBranch(HValue* value) { | 2150 void TestContext::BuildBranch(HValue* value) { |
2111 // We expect the graph to be in edge-split form: there is no edge that | 2151 // We expect the graph to be in edge-split form: there is no edge that |
2112 // connects a branch node to a join node. We conservatively ensure that | 2152 // connects a branch node to a join node. We conservatively ensure that |
2113 // property by always adding an empty block on the outgoing edges of this | 2153 // property by always adding an empty block on the outgoing edges of this |
2114 // branch. | 2154 // branch. |
2115 HGraphBuilder* builder = owner(); | 2155 HGraphBuilder* builder = owner(); |
2116 if (value->CheckFlag(HValue::kIsArguments)) { | 2156 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
2117 builder->Bailout("arguments object value in a test context"); | 2157 builder->Bailout("arguments object value in a test context"); |
2118 } | 2158 } |
2119 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2159 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2120 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2160 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2121 HTest* test = new(zone()) HTest(value, empty_true, empty_false); | 2161 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false); |
2122 builder->current_block()->Finish(test); | 2162 builder->current_block()->Finish(test); |
2123 | 2163 |
2124 empty_true->Goto(if_true()); | 2164 empty_true->Goto(if_true()); |
2125 empty_false->Goto(if_false()); | 2165 empty_false->Goto(if_false()); |
2126 builder->set_current_block(NULL); | 2166 builder->set_current_block(NULL); |
2127 } | 2167 } |
2128 | 2168 |
2129 | 2169 |
2130 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2170 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
2131 #define CHECK_BAILOUT(call) \ | 2171 #define CHECK_BAILOUT(call) \ |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2617 // Finish with deoptimize and add uses of enviroment values to | 2657 // Finish with deoptimize and add uses of enviroment values to |
2618 // account for invisible uses. | 2658 // account for invisible uses. |
2619 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 2659 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
2620 set_current_block(NULL); | 2660 set_current_block(NULL); |
2621 break; | 2661 break; |
2622 } | 2662 } |
2623 | 2663 |
2624 // Otherwise generate a compare and branch. | 2664 // Otherwise generate a compare and branch. |
2625 CHECK_ALIVE(VisitForValue(clause->label())); | 2665 CHECK_ALIVE(VisitForValue(clause->label())); |
2626 HValue* label_value = Pop(); | 2666 HValue* label_value = Pop(); |
2627 HCompare* compare = | 2667 HCompareIDAndBranch* compare = |
2628 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); | 2668 new(zone()) HCompareIDAndBranch(tag_value, |
2669 label_value, | |
2670 Token::EQ_STRICT); | |
2629 compare->SetInputRepresentation(Representation::Integer32()); | 2671 compare->SetInputRepresentation(Representation::Integer32()); |
2630 ASSERT(!compare->HasSideEffects()); | |
2631 AddInstruction(compare); | |
2632 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 2672 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
2633 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 2673 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
2634 HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); | 2674 compare->SetSuccessorAt(0, body_block); |
2635 current_block()->Finish(branch); | 2675 compare->SetSuccessorAt(1, next_test_block); |
2676 current_block()->Finish(compare); | |
2636 set_current_block(next_test_block); | 2677 set_current_block(next_test_block); |
2637 } | 2678 } |
2638 | 2679 |
2639 // Save the current block to use for the default or to join with the | 2680 // Save the current block to use for the default or to join with the |
2640 // exit. This block is NULL if we deoptimized. | 2681 // exit. This block is NULL if we deoptimized. |
2641 HBasicBlock* last_block = current_block(); | 2682 HBasicBlock* last_block = current_block(); |
2642 | 2683 |
2643 // 2. Loop over the clauses and the linked list of tests in lockstep, | 2684 // 2. Loop over the clauses and the linked list of tests in lockstep, |
2644 // translating the clause bodies. | 2685 // translating the clause bodies. |
2645 HBasicBlock* curr_test_block = first_test_block; | 2686 HBasicBlock* curr_test_block = first_test_block; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2711 return statement->OsrEntryId() == info()->osr_ast_id(); | 2752 return statement->OsrEntryId() == info()->osr_ast_id(); |
2712 } | 2753 } |
2713 | 2754 |
2714 | 2755 |
2715 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 2756 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
2716 if (!HasOsrEntryAt(statement)) return; | 2757 if (!HasOsrEntryAt(statement)) return; |
2717 | 2758 |
2718 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 2759 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
2719 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 2760 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
2720 HValue* true_value = graph()->GetConstantTrue(); | 2761 HValue* true_value = graph()->GetConstantTrue(); |
2721 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); | 2762 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
2722 current_block()->Finish(test); | 2763 current_block()->Finish(test); |
2723 | 2764 |
2724 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 2765 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
2725 non_osr_entry->Goto(loop_predecessor); | 2766 non_osr_entry->Goto(loop_predecessor); |
2726 | 2767 |
2727 set_current_block(osr_entry); | 2768 set_current_block(osr_entry); |
2728 int osr_entry_id = statement->OsrEntryId(); | 2769 int osr_entry_id = statement->OsrEntryId(); |
2729 // We want the correct environment at the OsrEntry instruction. Build | 2770 // We want the correct environment at the OsrEntry instruction. Build |
2730 // it explicitly. The expression stack should be empty. | 2771 // it explicitly. The expression stack should be empty. |
2731 ASSERT(environment()->ExpressionStackIsEmpty()); | 2772 ASSERT(environment()->ExpressionStackIsEmpty()); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2955 Handle<SharedFunctionInfo> shared_info = | 2996 Handle<SharedFunctionInfo> shared_info = |
2956 SearchSharedFunctionInfo(info()->shared_info()->code(), | 2997 SearchSharedFunctionInfo(info()->shared_info()->code(), |
2957 expr); | 2998 expr); |
2958 if (shared_info.is_null()) { | 2999 if (shared_info.is_null()) { |
2959 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 3000 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
2960 } | 3001 } |
2961 // We also have a stack overflow if the recursive compilation did. | 3002 // We also have a stack overflow if the recursive compilation did. |
2962 if (HasStackOverflow()) return; | 3003 if (HasStackOverflow()) return; |
2963 HFunctionLiteral* instr = | 3004 HFunctionLiteral* instr = |
2964 new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); | 3005 new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); |
2965 ast_context()->ReturnInstruction(instr, expr->id()); | 3006 return ast_context()->ReturnInstruction(instr, expr->id()); |
Kevin Millikin (Chromium)
2011/06/30 13:31:05
:)
| |
2966 } | 3007 } |
2967 | 3008 |
2968 | 3009 |
2969 void HGraphBuilder::VisitSharedFunctionInfoLiteral( | 3010 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
2970 SharedFunctionInfoLiteral* expr) { | 3011 SharedFunctionInfoLiteral* expr) { |
2971 ASSERT(!HasStackOverflow()); | 3012 ASSERT(!HasStackOverflow()); |
2972 ASSERT(current_block() != NULL); | 3013 ASSERT(current_block() != NULL); |
2973 ASSERT(current_block()->HasPredecessor()); | 3014 ASSERT(current_block()->HasPredecessor()); |
2974 return Bailout("SharedFunctionInfoLiteral"); | 3015 return Bailout("SharedFunctionInfoLiteral"); |
2975 } | 3016 } |
(...skipping 24 matching lines...) Expand all Loading... | |
3000 CHECK_BAILOUT(Visit(expr->else_expression())); | 3041 CHECK_BAILOUT(Visit(expr->else_expression())); |
3001 cond_false = current_block(); | 3042 cond_false = current_block(); |
3002 } else { | 3043 } else { |
3003 cond_false = NULL; | 3044 cond_false = NULL; |
3004 } | 3045 } |
3005 | 3046 |
3006 if (!ast_context()->IsTest()) { | 3047 if (!ast_context()->IsTest()) { |
3007 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 3048 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
3008 set_current_block(join); | 3049 set_current_block(join); |
3009 if (join != NULL && !ast_context()->IsEffect()) { | 3050 if (join != NULL && !ast_context()->IsEffect()) { |
3010 ast_context()->ReturnValue(Pop()); | 3051 return ast_context()->ReturnValue(Pop()); |
3011 } | 3052 } |
3012 } | 3053 } |
3013 } | 3054 } |
3014 | 3055 |
3015 | 3056 |
3016 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( | 3057 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
3017 Variable* var, LookupResult* lookup, bool is_store) { | 3058 Variable* var, LookupResult* lookup, bool is_store) { |
3018 if (var->is_this() || !info()->has_global_object()) { | 3059 if (var->is_this() || !info()->has_global_object()) { |
3019 return kUseGeneric; | 3060 return kUseGeneric; |
3020 } | 3061 } |
(...skipping 29 matching lines...) Expand all Loading... | |
3050 ASSERT(current_block()->HasPredecessor()); | 3091 ASSERT(current_block()->HasPredecessor()); |
3051 Variable* variable = expr->AsVariable(); | 3092 Variable* variable = expr->AsVariable(); |
3052 if (variable == NULL) { | 3093 if (variable == NULL) { |
3053 return Bailout("reference to rewritten variable"); | 3094 return Bailout("reference to rewritten variable"); |
3054 } else if (variable->IsStackAllocated()) { | 3095 } else if (variable->IsStackAllocated()) { |
3055 HValue* value = environment()->Lookup(variable); | 3096 HValue* value = environment()->Lookup(variable); |
3056 if (variable->mode() == Variable::CONST && | 3097 if (variable->mode() == Variable::CONST && |
3057 value == graph()->GetConstantHole()) { | 3098 value == graph()->GetConstantHole()) { |
3058 return Bailout("reference to uninitialized const variable"); | 3099 return Bailout("reference to uninitialized const variable"); |
3059 } | 3100 } |
3060 ast_context()->ReturnValue(value); | 3101 return ast_context()->ReturnValue(value); |
3061 } else if (variable->IsContextSlot()) { | 3102 } else if (variable->IsContextSlot()) { |
3062 if (variable->mode() == Variable::CONST) { | 3103 if (variable->mode() == Variable::CONST) { |
3063 return Bailout("reference to const context slot"); | 3104 return Bailout("reference to const context slot"); |
3064 } | 3105 } |
3065 HValue* context = BuildContextChainWalk(variable); | 3106 HValue* context = BuildContextChainWalk(variable); |
3066 int index = variable->AsSlot()->index(); | 3107 int index = variable->AsSlot()->index(); |
3067 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); | 3108 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); |
3068 ast_context()->ReturnInstruction(instr, expr->id()); | 3109 return ast_context()->ReturnInstruction(instr, expr->id()); |
3069 } else if (variable->is_global()) { | 3110 } else if (variable->is_global()) { |
3070 LookupResult lookup; | 3111 LookupResult lookup; |
3071 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); | 3112 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
3072 | 3113 |
3073 if (type == kUseCell && | 3114 if (type == kUseCell && |
3074 info()->global_object()->IsAccessCheckNeeded()) { | 3115 info()->global_object()->IsAccessCheckNeeded()) { |
3075 type = kUseGeneric; | 3116 type = kUseGeneric; |
3076 } | 3117 } |
3077 | 3118 |
3078 if (type == kUseCell) { | 3119 if (type == kUseCell) { |
3079 Handle<GlobalObject> global(info()->global_object()); | 3120 Handle<GlobalObject> global(info()->global_object()); |
3080 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3121 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
3081 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3122 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
3082 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); | 3123 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); |
3083 ast_context()->ReturnInstruction(instr, expr->id()); | 3124 return ast_context()->ReturnInstruction(instr, expr->id()); |
3084 } else { | 3125 } else { |
3085 HValue* context = environment()->LookupContext(); | 3126 HValue* context = environment()->LookupContext(); |
3086 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 3127 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
3087 AddInstruction(global_object); | 3128 AddInstruction(global_object); |
3088 HLoadGlobalGeneric* instr = | 3129 HLoadGlobalGeneric* instr = |
3089 new(zone()) HLoadGlobalGeneric(context, | 3130 new(zone()) HLoadGlobalGeneric(context, |
3090 global_object, | 3131 global_object, |
3091 variable->name(), | 3132 variable->name(), |
3092 ast_context()->is_for_typeof()); | 3133 ast_context()->is_for_typeof()); |
3093 instr->set_position(expr->position()); | 3134 instr->set_position(expr->position()); |
3094 ASSERT(instr->HasSideEffects()); | 3135 ASSERT(instr->HasSideEffects()); |
3095 ast_context()->ReturnInstruction(instr, expr->id()); | 3136 return ast_context()->ReturnInstruction(instr, expr->id()); |
3096 } | 3137 } |
3097 } else { | 3138 } else { |
3098 return Bailout("reference to a variable which requires dynamic lookup"); | 3139 return Bailout("reference to a variable which requires dynamic lookup"); |
3099 } | 3140 } |
3100 } | 3141 } |
3101 | 3142 |
3102 | 3143 |
3103 void HGraphBuilder::VisitLiteral(Literal* expr) { | 3144 void HGraphBuilder::VisitLiteral(Literal* expr) { |
3104 ASSERT(!HasStackOverflow()); | 3145 ASSERT(!HasStackOverflow()); |
3105 ASSERT(current_block() != NULL); | 3146 ASSERT(current_block() != NULL); |
3106 ASSERT(current_block()->HasPredecessor()); | 3147 ASSERT(current_block()->HasPredecessor()); |
3107 HConstant* instr = | 3148 HConstant* instr = |
3108 new(zone()) HConstant(expr->handle(), Representation::Tagged()); | 3149 new(zone()) HConstant(expr->handle(), Representation::Tagged()); |
3109 ast_context()->ReturnInstruction(instr, expr->id()); | 3150 return ast_context()->ReturnInstruction(instr, expr->id()); |
3110 } | 3151 } |
3111 | 3152 |
3112 | 3153 |
3113 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 3154 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
3114 ASSERT(!HasStackOverflow()); | 3155 ASSERT(!HasStackOverflow()); |
3115 ASSERT(current_block() != NULL); | 3156 ASSERT(current_block() != NULL); |
3116 ASSERT(current_block()->HasPredecessor()); | 3157 ASSERT(current_block()->HasPredecessor()); |
3117 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), | 3158 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), |
3118 expr->flags(), | 3159 expr->flags(), |
3119 expr->literal_index()); | 3160 expr->literal_index()); |
3120 ast_context()->ReturnInstruction(instr, expr->id()); | 3161 return ast_context()->ReturnInstruction(instr, expr->id()); |
3121 } | 3162 } |
3122 | 3163 |
3123 | 3164 |
3124 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 3165 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
3125 ASSERT(!HasStackOverflow()); | 3166 ASSERT(!HasStackOverflow()); |
3126 ASSERT(current_block() != NULL); | 3167 ASSERT(current_block() != NULL); |
3127 ASSERT(current_block()->HasPredecessor()); | 3168 ASSERT(current_block()->HasPredecessor()); |
3128 HValue* context = environment()->LookupContext(); | 3169 HValue* context = environment()->LookupContext(); |
3129 HObjectLiteral* literal = | 3170 HObjectLiteral* literal = |
3130 new(zone()) HObjectLiteral(context, | 3171 new(zone()) HObjectLiteral(context, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3180 } | 3221 } |
3181 | 3222 |
3182 if (expr->has_function()) { | 3223 if (expr->has_function()) { |
3183 // Return the result of the transformation to fast properties | 3224 // Return the result of the transformation to fast properties |
3184 // instead of the original since this operation changes the map | 3225 // instead of the original since this operation changes the map |
3185 // of the object. This makes sure that the original object won't | 3226 // of the object. This makes sure that the original object won't |
3186 // be used by other optimized code before it is transformed | 3227 // be used by other optimized code before it is transformed |
3187 // (e.g. because of code motion). | 3228 // (e.g. because of code motion). |
3188 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 3229 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
3189 AddInstruction(result); | 3230 AddInstruction(result); |
3190 ast_context()->ReturnValue(result); | 3231 return ast_context()->ReturnValue(result); |
3191 } else { | 3232 } else { |
3192 ast_context()->ReturnValue(Pop()); | 3233 return ast_context()->ReturnValue(Pop()); |
3193 } | 3234 } |
3194 } | 3235 } |
3195 | 3236 |
3196 | 3237 |
3197 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 3238 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
3198 ASSERT(!HasStackOverflow()); | 3239 ASSERT(!HasStackOverflow()); |
3199 ASSERT(current_block() != NULL); | 3240 ASSERT(current_block() != NULL); |
3200 ASSERT(current_block()->HasPredecessor()); | 3241 ASSERT(current_block()->HasPredecessor()); |
3201 ZoneList<Expression*>* subexprs = expr->values(); | 3242 ZoneList<Expression*>* subexprs = expr->values(); |
3202 int length = subexprs->length(); | 3243 int length = subexprs->length(); |
(...skipping 23 matching lines...) Expand all Loading... | |
3226 elements = new(zone()) HLoadElements(literal); | 3267 elements = new(zone()) HLoadElements(literal); |
3227 AddInstruction(elements); | 3268 AddInstruction(elements); |
3228 } | 3269 } |
3229 | 3270 |
3230 HValue* key = AddInstruction( | 3271 HValue* key = AddInstruction( |
3231 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), | 3272 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
3232 Representation::Integer32())); | 3273 Representation::Integer32())); |
3233 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); | 3274 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); |
3234 AddSimulate(expr->GetIdForElement(i)); | 3275 AddSimulate(expr->GetIdForElement(i)); |
3235 } | 3276 } |
3236 ast_context()->ReturnValue(Pop()); | 3277 return ast_context()->ReturnValue(Pop()); |
3237 } | 3278 } |
3238 | 3279 |
3239 | 3280 |
3240 // Sets the lookup result and returns true if the store can be inlined. | 3281 // Sets the lookup result and returns true if the store can be inlined. |
3241 static bool ComputeStoredField(Handle<Map> type, | 3282 static bool ComputeStoredField(Handle<Map> type, |
3242 Handle<String> name, | 3283 Handle<String> name, |
3243 LookupResult* lookup) { | 3284 LookupResult* lookup) { |
3244 type->LookupInDescriptors(NULL, *name, lookup); | 3285 type->LookupInDescriptors(NULL, *name, lookup); |
3245 if (!lookup->IsPropertyOrTransition()) return false; | 3286 if (!lookup->IsPropertyOrTransition()) return false; |
3246 if (lookup->type() == FIELD) return true; | 3287 if (lookup->type() == FIELD) return true; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3388 // unoptimized code). | 3429 // unoptimized code). |
3389 if (instr->HasSideEffects()) { | 3430 if (instr->HasSideEffects()) { |
3390 if (ast_context()->IsEffect()) { | 3431 if (ast_context()->IsEffect()) { |
3391 AddSimulate(expr->id()); | 3432 AddSimulate(expr->id()); |
3392 } else { | 3433 } else { |
3393 Push(value); | 3434 Push(value); |
3394 AddSimulate(expr->id()); | 3435 AddSimulate(expr->id()); |
3395 Drop(1); | 3436 Drop(1); |
3396 } | 3437 } |
3397 } | 3438 } |
3398 ast_context()->ReturnValue(value); | 3439 return ast_context()->ReturnValue(value); |
3399 return; | |
3400 } | 3440 } |
3401 } | 3441 } |
3402 | 3442 |
3403 ASSERT(join != NULL); | 3443 ASSERT(join != NULL); |
3404 join->SetJoinId(expr->id()); | 3444 join->SetJoinId(expr->id()); |
3405 set_current_block(join); | 3445 set_current_block(join); |
3406 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 3446 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
3407 } | 3447 } |
3408 | 3448 |
3409 | 3449 |
3410 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 3450 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
3411 Property* prop = expr->target()->AsProperty(); | 3451 Property* prop = expr->target()->AsProperty(); |
3412 ASSERT(prop != NULL); | 3452 ASSERT(prop != NULL); |
3413 expr->RecordTypeFeedback(oracle()); | 3453 expr->RecordTypeFeedback(oracle()); |
3414 CHECK_ALIVE(VisitForValue(prop->obj())); | 3454 CHECK_ALIVE(VisitForValue(prop->obj())); |
3415 | 3455 |
3416 HValue* value = NULL; | 3456 HValue* value = NULL; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3448 HValue* key = Pop(); | 3488 HValue* key = Pop(); |
3449 HValue* object = Pop(); | 3489 HValue* object = Pop(); |
3450 bool has_side_effects = false; | 3490 bool has_side_effects = false; |
3451 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 3491 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
3452 expr->position(), | 3492 expr->position(), |
3453 true, // is_store | 3493 true, // is_store |
3454 &has_side_effects); | 3494 &has_side_effects); |
3455 Push(value); | 3495 Push(value); |
3456 ASSERT(has_side_effects); // Stores always have side effects. | 3496 ASSERT(has_side_effects); // Stores always have side effects. |
3457 AddSimulate(expr->AssignmentId()); | 3497 AddSimulate(expr->AssignmentId()); |
3458 ast_context()->ReturnValue(Pop()); | 3498 return ast_context()->ReturnValue(Pop()); |
3459 return; | |
3460 } | 3499 } |
3461 Push(value); | 3500 Push(value); |
3462 instr->set_position(expr->position()); | 3501 instr->set_position(expr->position()); |
3463 AddInstruction(instr); | 3502 AddInstruction(instr); |
3464 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3503 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3465 ast_context()->ReturnValue(Pop()); | 3504 return ast_context()->ReturnValue(Pop()); |
3466 } | 3505 } |
3467 | 3506 |
3468 | 3507 |
3469 // Because not every expression has a position and there is not common | 3508 // Because not every expression has a position and there is not common |
3470 // superclass of Assignment and CountOperation, we cannot just pass the | 3509 // superclass of Assignment and CountOperation, we cannot just pass the |
3471 // owning expression instead of position and ast_id separately. | 3510 // owning expression instead of position and ast_id separately. |
3472 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3511 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
3473 HValue* value, | 3512 HValue* value, |
3474 int position, | 3513 int position, |
3475 int ast_id) { | 3514 int ast_id) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3543 | 3582 |
3544 HValue* context = BuildContextChainWalk(var); | 3583 HValue* context = BuildContextChainWalk(var); |
3545 int index = var->AsSlot()->index(); | 3584 int index = var->AsSlot()->index(); |
3546 HStoreContextSlot* instr = | 3585 HStoreContextSlot* instr = |
3547 new(zone()) HStoreContextSlot(context, index, Top()); | 3586 new(zone()) HStoreContextSlot(context, index, Top()); |
3548 AddInstruction(instr); | 3587 AddInstruction(instr); |
3549 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3588 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3550 } else { | 3589 } else { |
3551 return Bailout("compound assignment to lookup slot"); | 3590 return Bailout("compound assignment to lookup slot"); |
3552 } | 3591 } |
3553 ast_context()->ReturnValue(Pop()); | 3592 return ast_context()->ReturnValue(Pop()); |
3554 | 3593 |
3555 } else if (prop != NULL) { | 3594 } else if (prop != NULL) { |
3556 prop->RecordTypeFeedback(oracle()); | 3595 prop->RecordTypeFeedback(oracle()); |
3557 | 3596 |
3558 if (prop->key()->IsPropertyName()) { | 3597 if (prop->key()->IsPropertyName()) { |
3559 // Named property. | 3598 // Named property. |
3560 CHECK_ALIVE(VisitForValue(prop->obj())); | 3599 CHECK_ALIVE(VisitForValue(prop->obj())); |
3561 HValue* obj = Top(); | 3600 HValue* obj = Top(); |
3562 | 3601 |
3563 HInstruction* load = NULL; | 3602 HInstruction* load = NULL; |
(...skipping 14 matching lines...) Expand all Loading... | |
3578 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 3617 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
3579 PushAndAdd(instr); | 3618 PushAndAdd(instr); |
3580 if (instr->HasSideEffects()) AddSimulate(operation->id()); | 3619 if (instr->HasSideEffects()) AddSimulate(operation->id()); |
3581 | 3620 |
3582 HInstruction* store = BuildStoreNamed(obj, instr, prop); | 3621 HInstruction* store = BuildStoreNamed(obj, instr, prop); |
3583 AddInstruction(store); | 3622 AddInstruction(store); |
3584 // Drop the simulated receiver and value. Return the value. | 3623 // Drop the simulated receiver and value. Return the value. |
3585 Drop(2); | 3624 Drop(2); |
3586 Push(instr); | 3625 Push(instr); |
3587 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3626 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3588 ast_context()->ReturnValue(Pop()); | 3627 return ast_context()->ReturnValue(Pop()); |
3589 | 3628 |
3590 } else { | 3629 } else { |
3591 // Keyed property. | 3630 // Keyed property. |
3592 CHECK_ALIVE(VisitForValue(prop->obj())); | 3631 CHECK_ALIVE(VisitForValue(prop->obj())); |
3593 CHECK_ALIVE(VisitForValue(prop->key())); | 3632 CHECK_ALIVE(VisitForValue(prop->key())); |
3594 HValue* obj = environment()->ExpressionStackAt(1); | 3633 HValue* obj = environment()->ExpressionStackAt(1); |
3595 HValue* key = environment()->ExpressionStackAt(0); | 3634 HValue* key = environment()->ExpressionStackAt(0); |
3596 | 3635 |
3597 bool has_side_effects = false; | 3636 bool has_side_effects = false; |
3598 HValue* load = HandleKeyedElementAccess( | 3637 HValue* load = HandleKeyedElementAccess( |
(...skipping 16 matching lines...) Expand all Loading... | |
3615 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | 3654 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
3616 RelocInfo::kNoPosition, | 3655 RelocInfo::kNoPosition, |
3617 true, // is_store | 3656 true, // is_store |
3618 &has_side_effects); | 3657 &has_side_effects); |
3619 | 3658 |
3620 // Drop the simulated receiver, key, and value. Return the value. | 3659 // Drop the simulated receiver, key, and value. Return the value. |
3621 Drop(3); | 3660 Drop(3); |
3622 Push(instr); | 3661 Push(instr); |
3623 ASSERT(has_side_effects); // Stores always have side effects. | 3662 ASSERT(has_side_effects); // Stores always have side effects. |
3624 AddSimulate(expr->AssignmentId()); | 3663 AddSimulate(expr->AssignmentId()); |
3625 ast_context()->ReturnValue(Pop()); | 3664 return ast_context()->ReturnValue(Pop()); |
3626 } | 3665 } |
3627 | 3666 |
3628 } else { | 3667 } else { |
3629 return Bailout("invalid lhs in compound assignment"); | 3668 return Bailout("invalid lhs in compound assignment"); |
3630 } | 3669 } |
3631 } | 3670 } |
3632 | 3671 |
3633 | 3672 |
3634 void HGraphBuilder::VisitAssignment(Assignment* expr) { | 3673 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
3635 ASSERT(!HasStackOverflow()); | 3674 ASSERT(!HasStackOverflow()); |
(...skipping 26 matching lines...) Expand all Loading... | |
3662 if (proxy->IsArguments()) return Bailout("assignment to arguments"); | 3701 if (proxy->IsArguments()) return Bailout("assignment to arguments"); |
3663 | 3702 |
3664 // Handle the assignment. | 3703 // Handle the assignment. |
3665 if (var->IsStackAllocated()) { | 3704 if (var->IsStackAllocated()) { |
3666 // We do not allow the arguments object to occur in a context where it | 3705 // We do not allow the arguments object to occur in a context where it |
3667 // may escape, but assignments to stack-allocated locals are | 3706 // may escape, but assignments to stack-allocated locals are |
3668 // permitted. | 3707 // permitted. |
3669 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 3708 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
3670 HValue* value = Pop(); | 3709 HValue* value = Pop(); |
3671 Bind(var, value); | 3710 Bind(var, value); |
3672 ast_context()->ReturnValue(value); | 3711 return ast_context()->ReturnValue(value); |
3673 | 3712 |
3674 } else if (var->IsContextSlot()) { | 3713 } else if (var->IsContextSlot()) { |
3675 ASSERT(var->mode() != Variable::CONST); | 3714 ASSERT(var->mode() != Variable::CONST); |
3676 // Bail out if we try to mutate a parameter value in a function using | 3715 // Bail out if we try to mutate a parameter value in a function using |
3677 // the arguments object. We do not (yet) correctly handle the | 3716 // the arguments object. We do not (yet) correctly handle the |
3678 // arguments property of the function. | 3717 // arguments property of the function. |
3679 if (info()->scope()->arguments() != NULL) { | 3718 if (info()->scope()->arguments() != NULL) { |
3680 // Parameters will rewrite to context slots. We have no direct way | 3719 // Parameters will rewrite to context slots. We have no direct way |
3681 // to detect that the variable is a parameter. | 3720 // to detect that the variable is a parameter. |
3682 int count = info()->scope()->num_parameters(); | 3721 int count = info()->scope()->num_parameters(); |
3683 for (int i = 0; i < count; ++i) { | 3722 for (int i = 0; i < count; ++i) { |
3684 if (var == info()->scope()->parameter(i)) { | 3723 if (var == info()->scope()->parameter(i)) { |
3685 Bailout("assignment to parameter, function uses arguments object"); | 3724 Bailout("assignment to parameter, function uses arguments object"); |
3686 } | 3725 } |
3687 } | 3726 } |
3688 } | 3727 } |
3689 | 3728 |
3690 CHECK_ALIVE(VisitForValue(expr->value())); | 3729 CHECK_ALIVE(VisitForValue(expr->value())); |
3691 HValue* context = BuildContextChainWalk(var); | 3730 HValue* context = BuildContextChainWalk(var); |
3692 int index = var->AsSlot()->index(); | 3731 int index = var->AsSlot()->index(); |
3693 HStoreContextSlot* instr = | 3732 HStoreContextSlot* instr = |
3694 new(zone()) HStoreContextSlot(context, index, Top()); | 3733 new(zone()) HStoreContextSlot(context, index, Top()); |
3695 AddInstruction(instr); | 3734 AddInstruction(instr); |
3696 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3735 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3697 ast_context()->ReturnValue(Pop()); | 3736 return ast_context()->ReturnValue(Pop()); |
3698 | 3737 |
3699 } else if (var->is_global()) { | 3738 } else if (var->is_global()) { |
3700 CHECK_ALIVE(VisitForValue(expr->value())); | 3739 CHECK_ALIVE(VisitForValue(expr->value())); |
3701 HandleGlobalVariableAssignment(var, | 3740 HandleGlobalVariableAssignment(var, |
3702 Top(), | 3741 Top(), |
3703 expr->position(), | 3742 expr->position(), |
3704 expr->AssignmentId()); | 3743 expr->AssignmentId()); |
3705 ast_context()->ReturnValue(Pop()); | 3744 return ast_context()->ReturnValue(Pop()); |
3706 | 3745 |
3707 } else { | 3746 } else { |
3708 return Bailout("assignment to LOOKUP or const CONTEXT variable"); | 3747 return Bailout("assignment to LOOKUP or const CONTEXT variable"); |
3709 } | 3748 } |
3710 | 3749 |
3711 } else if (prop != NULL) { | 3750 } else if (prop != NULL) { |
3712 HandlePropertyAssignment(expr); | 3751 HandlePropertyAssignment(expr); |
3713 } else { | 3752 } else { |
3714 return Bailout("invalid left-hand side in assignment"); | 3753 return Bailout("invalid left-hand side in assignment"); |
3715 } | 3754 } |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3948 elements->ClearFlag(HValue::kUseGVN); | 3987 elements->ClearFlag(HValue::kUseGVN); |
3949 HInstruction* length = | 3988 HInstruction* length = |
3950 AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3989 AddInstruction(new(zone()) HExternalArrayLength(elements)); |
3951 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3990 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3952 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 3991 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
3953 AddInstruction(external_elements); | 3992 AddInstruction(external_elements); |
3954 } | 3993 } |
3955 if (type_todo[elements_kind]) { | 3994 if (type_todo[elements_kind]) { |
3956 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 3995 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
3957 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 3996 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
3958 HCompareConstantEq* compare = new(zone()) HCompareConstantEq( | 3997 HCompareConstantEqAndBranch* compare = |
3959 elements_kind_instr, | 3998 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, |
3960 elements_kind, | 3999 elements_kind, |
3961 Token::EQ_STRICT); | 4000 Token::EQ_STRICT); |
3962 AddInstruction(compare); | 4001 compare->SetSuccessorAt(0, if_true); |
3963 HTest* branch = new(zone()) HTest(compare, if_true, if_false); | 4002 compare->SetSuccessorAt(1, if_false); |
3964 current_block()->Finish(branch); | 4003 current_block()->Finish(compare); |
3965 | 4004 |
3966 set_current_block(if_true); | 4005 set_current_block(if_true); |
3967 HInstruction* access; | 4006 HInstruction* access; |
3968 if (elements_kind == JSObject::FAST_ELEMENTS) { | 4007 if (elements_kind == JSObject::FAST_ELEMENTS) { |
3969 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 4008 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
3970 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 4009 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
3971 HInstruction* typecheck = | 4010 HHasInstanceTypeAndBranch* typecheck = |
3972 AddInstruction(new(zone()) HHasInstanceType(object, JS_ARRAY_TYPE)); | 4011 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
3973 HTest* test = new(zone()) HTest(typecheck, if_jsarray, if_fastobject); | 4012 typecheck->SetSuccessorAt(0, if_jsarray); |
3974 current_block()->Finish(test); | 4013 typecheck->SetSuccessorAt(1, if_fastobject); |
4014 current_block()->Finish(typecheck); | |
3975 | 4015 |
3976 set_current_block(if_jsarray); | 4016 set_current_block(if_jsarray); |
3977 HInstruction* length = new(zone()) HJSArrayLength(object); | 4017 HInstruction* length = new(zone()) HJSArrayLength(object); |
3978 AddInstruction(length); | 4018 AddInstruction(length); |
3979 length->ClearFlag(HValue::kUseGVN); | 4019 length->ClearFlag(HValue::kUseGVN); |
3980 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4020 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3981 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4021 elements = AddInstruction(new(zone()) HLoadElements(object)); |
3982 elements->ClearFlag(HValue::kUseGVN); | 4022 elements->ClearFlag(HValue::kUseGVN); |
3983 if (is_store) { | 4023 if (is_store) { |
3984 access = AddInstruction( | 4024 access = AddInstruction( |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4171 &has_side_effects); | 4211 &has_side_effects); |
4172 if (has_side_effects) { | 4212 if (has_side_effects) { |
4173 if (ast_context()->IsEffect()) { | 4213 if (ast_context()->IsEffect()) { |
4174 AddSimulate(expr->id()); | 4214 AddSimulate(expr->id()); |
4175 } else { | 4215 } else { |
4176 Push(load); | 4216 Push(load); |
4177 AddSimulate(expr->id()); | 4217 AddSimulate(expr->id()); |
4178 Drop(1); | 4218 Drop(1); |
4179 } | 4219 } |
4180 } | 4220 } |
4181 ast_context()->ReturnValue(load); | 4221 return ast_context()->ReturnValue(load); |
4182 return; | |
4183 } | 4222 } |
4184 instr->set_position(expr->position()); | 4223 instr->set_position(expr->position()); |
4185 ast_context()->ReturnInstruction(instr, expr->id()); | 4224 return ast_context()->ReturnInstruction(instr, expr->id()); |
4186 } | 4225 } |
4187 | 4226 |
4188 | 4227 |
4189 void HGraphBuilder::AddCheckConstantFunction(Call* expr, | 4228 void HGraphBuilder::AddCheckConstantFunction(Call* expr, |
4190 HValue* receiver, | 4229 HValue* receiver, |
4191 Handle<Map> receiver_map, | 4230 Handle<Map> receiver_map, |
4192 bool smi_and_map_check) { | 4231 bool smi_and_map_check) { |
4193 // Constant functions have the nice property that the map will change if they | 4232 // Constant functions have the nice property that the map will change if they |
4194 // are overwritten. Therefore it is enough to check the map of the holder and | 4233 // are overwritten. Therefore it is enough to check the map of the holder and |
4195 // its prototypes. | 4234 // its prototypes. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4263 HValue* context = environment()->LookupContext(); | 4302 HValue* context = environment()->LookupContext(); |
4264 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 4303 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
4265 call->set_position(expr->position()); | 4304 call->set_position(expr->position()); |
4266 PreProcessCall(call); | 4305 PreProcessCall(call); |
4267 | 4306 |
4268 if (join != NULL) { | 4307 if (join != NULL) { |
4269 AddInstruction(call); | 4308 AddInstruction(call); |
4270 if (!ast_context()->IsEffect()) Push(call); | 4309 if (!ast_context()->IsEffect()) Push(call); |
4271 current_block()->Goto(join); | 4310 current_block()->Goto(join); |
4272 } else { | 4311 } else { |
4273 ast_context()->ReturnInstruction(call, expr->id()); | 4312 return ast_context()->ReturnInstruction(call, expr->id()); |
4274 return; | |
4275 } | 4313 } |
4276 } | 4314 } |
4277 | 4315 |
4278 // We assume that control flow is always live after an expression. So | 4316 // We assume that control flow is always live after an expression. So |
4279 // even without predecessors to the join block, we set it as the exit | 4317 // even without predecessors to the join block, we set it as the exit |
4280 // block and continue by adding instructions there. | 4318 // block and continue by adding instructions there. |
4281 ASSERT(join != NULL); | 4319 ASSERT(join != NULL); |
4282 if (join->HasPredecessor()) { | 4320 if (join->HasPredecessor()) { |
4283 set_current_block(join); | 4321 set_current_block(join); |
4284 join->SetJoinId(expr->id()); | 4322 join->SetJoinId(expr->id()); |
4285 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4323 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
4286 } else { | 4324 } else { |
4287 set_current_block(NULL); | 4325 set_current_block(NULL); |
4288 } | 4326 } |
4289 } | 4327 } |
4290 | 4328 |
4291 | 4329 |
4292 void HGraphBuilder::TraceInline(Handle<JSFunction> target, | 4330 void HGraphBuilder::TraceInline(Handle<JSFunction> target, |
4293 Handle<JSFunction> caller, | 4331 Handle<JSFunction> caller, |
4294 const char* reason) { | 4332 const char* reason) { |
4295 if (FLAG_trace_inlining) { | 4333 if (FLAG_trace_inlining) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4489 current_block()->AddLeaveInlined(undefined, function_return()); | 4527 current_block()->AddLeaveInlined(undefined, function_return()); |
4490 } | 4528 } |
4491 } else { | 4529 } else { |
4492 // The graph builder assumes control can reach both branches of a | 4530 // The graph builder assumes control can reach both branches of a |
4493 // test, so we materialize the undefined value and test it rather than | 4531 // test, so we materialize the undefined value and test it rather than |
4494 // simply jumping to the false target. | 4532 // simply jumping to the false target. |
4495 // | 4533 // |
4496 // TODO(3168478): refactor to avoid this. | 4534 // TODO(3168478): refactor to avoid this. |
4497 HBasicBlock* empty_true = graph()->CreateBasicBlock(); | 4535 HBasicBlock* empty_true = graph()->CreateBasicBlock(); |
4498 HBasicBlock* empty_false = graph()->CreateBasicBlock(); | 4536 HBasicBlock* empty_false = graph()->CreateBasicBlock(); |
4499 HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); | 4537 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false); |
4500 current_block()->Finish(test); | 4538 current_block()->Finish(test); |
4501 | 4539 |
4502 empty_true->Goto(inlined_test_context()->if_true()); | 4540 empty_true->Goto(inlined_test_context()->if_true()); |
4503 empty_false->Goto(inlined_test_context()->if_false()); | 4541 empty_false->Goto(inlined_test_context()->if_false()); |
4504 } | 4542 } |
4505 } | 4543 } |
4506 | 4544 |
4507 // Fix up the function exits. | 4545 // Fix up the function exits. |
4508 if (inlined_test_context() != NULL) { | 4546 if (inlined_test_context() != NULL) { |
4509 HBasicBlock* if_true = inlined_test_context()->if_true(); | 4547 HBasicBlock* if_true = inlined_test_context()->if_true(); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4702 HValue* receiver = Pop(); | 4740 HValue* receiver = Pop(); |
4703 Push(key); | 4741 Push(key); |
4704 Push(receiver); | 4742 Push(receiver); |
4705 | 4743 |
4706 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 4744 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
4707 | 4745 |
4708 HValue* context = environment()->LookupContext(); | 4746 HValue* context = environment()->LookupContext(); |
4709 call = new(zone()) HCallKeyed(context, key, argument_count); | 4747 call = new(zone()) HCallKeyed(context, key, argument_count); |
4710 call->set_position(expr->position()); | 4748 call->set_position(expr->position()); |
4711 Drop(argument_count + 1); // 1 is the key. | 4749 Drop(argument_count + 1); // 1 is the key. |
4712 ast_context()->ReturnInstruction(call, expr->id()); | 4750 return ast_context()->ReturnInstruction(call, expr->id()); |
4713 return; | |
4714 } | 4751 } |
4715 | 4752 |
4716 // Named function call. | 4753 // Named function call. |
4717 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); | 4754 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); |
4718 | 4755 |
4719 if (TryCallApply(expr)) return; | 4756 if (TryCallApply(expr)) return; |
4720 | 4757 |
4721 CHECK_ALIVE(VisitForValue(prop->obj())); | 4758 CHECK_ALIVE(VisitForValue(prop->obj())); |
4722 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4759 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4723 | 4760 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4827 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 4864 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
4828 | 4865 |
4829 // The function to call is treated as an argument to the call function | 4866 // The function to call is treated as an argument to the call function |
4830 // stub. | 4867 // stub. |
4831 call = new(zone()) HCallFunction(context, argument_count + 1); | 4868 call = new(zone()) HCallFunction(context, argument_count + 1); |
4832 Drop(argument_count + 1); | 4869 Drop(argument_count + 1); |
4833 } | 4870 } |
4834 } | 4871 } |
4835 | 4872 |
4836 call->set_position(expr->position()); | 4873 call->set_position(expr->position()); |
4837 ast_context()->ReturnInstruction(call, expr->id()); | 4874 return ast_context()->ReturnInstruction(call, expr->id()); |
4838 } | 4875 } |
4839 | 4876 |
4840 | 4877 |
4841 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 4878 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
4842 ASSERT(!HasStackOverflow()); | 4879 ASSERT(!HasStackOverflow()); |
4843 ASSERT(current_block() != NULL); | 4880 ASSERT(current_block() != NULL); |
4844 ASSERT(current_block()->HasPredecessor()); | 4881 ASSERT(current_block()->HasPredecessor()); |
4845 // The constructor function is also used as the receiver argument to the | 4882 // The constructor function is also used as the receiver argument to the |
4846 // JS construct call builtin. | 4883 // JS construct call builtin. |
4847 HValue* constructor = NULL; | 4884 HValue* constructor = NULL; |
4848 CHECK_ALIVE(constructor = VisitArgument(expr->expression())); | 4885 CHECK_ALIVE(constructor = VisitArgument(expr->expression())); |
4849 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 4886 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
4850 | 4887 |
4851 HValue* context = environment()->LookupContext(); | 4888 HValue* context = environment()->LookupContext(); |
4852 | 4889 |
4853 // The constructor is both an operand to the instruction and an argument | 4890 // The constructor is both an operand to the instruction and an argument |
4854 // to the construct call. | 4891 // to the construct call. |
4855 int arg_count = expr->arguments()->length() + 1; // Plus constructor. | 4892 int arg_count = expr->arguments()->length() + 1; // Plus constructor. |
4856 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); | 4893 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); |
4857 call->set_position(expr->position()); | 4894 call->set_position(expr->position()); |
4858 Drop(arg_count); | 4895 Drop(arg_count); |
4859 ast_context()->ReturnInstruction(call, expr->id()); | 4896 return ast_context()->ReturnInstruction(call, expr->id()); |
4860 } | 4897 } |
4861 | 4898 |
4862 | 4899 |
4863 // Support for generating inlined runtime functions. | 4900 // Support for generating inlined runtime functions. |
4864 | 4901 |
4865 // Lookup table for generators for runtime calls that are generated inline. | 4902 // Lookup table for generators for runtime calls that are generated inline. |
4866 // Elements of the table are member pointers to functions of HGraphBuilder. | 4903 // Elements of the table are member pointers to functions of HGraphBuilder. |
4867 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 4904 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
4868 &HGraphBuilder::Generate##Name, | 4905 &HGraphBuilder::Generate##Name, |
4869 | 4906 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4901 } else { | 4938 } else { |
4902 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 4939 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
4903 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 4940 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
4904 | 4941 |
4905 Handle<String> name = expr->name(); | 4942 Handle<String> name = expr->name(); |
4906 int argument_count = expr->arguments()->length(); | 4943 int argument_count = expr->arguments()->length(); |
4907 HCallRuntime* call = | 4944 HCallRuntime* call = |
4908 new(zone()) HCallRuntime(name, function, argument_count); | 4945 new(zone()) HCallRuntime(name, function, argument_count); |
4909 call->set_position(RelocInfo::kNoPosition); | 4946 call->set_position(RelocInfo::kNoPosition); |
4910 Drop(argument_count); | 4947 Drop(argument_count); |
4911 ast_context()->ReturnInstruction(call, expr->id()); | 4948 return ast_context()->ReturnInstruction(call, expr->id()); |
4912 } | 4949 } |
4913 } | 4950 } |
4914 | 4951 |
4915 | 4952 |
4916 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 4953 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
4917 ASSERT(!HasStackOverflow()); | 4954 ASSERT(!HasStackOverflow()); |
4918 ASSERT(current_block() != NULL); | 4955 ASSERT(current_block() != NULL); |
4919 ASSERT(current_block()->HasPredecessor()); | 4956 ASSERT(current_block()->HasPredecessor()); |
4920 switch (expr->op()) { | 4957 switch (expr->op()) { |
4921 case Token::DELETE: return VisitDelete(expr); | 4958 case Token::DELETE: return VisitDelete(expr); |
4922 case Token::VOID: return VisitVoid(expr); | 4959 case Token::VOID: return VisitVoid(expr); |
4923 case Token::TYPEOF: return VisitTypeof(expr); | 4960 case Token::TYPEOF: return VisitTypeof(expr); |
4924 case Token::ADD: return VisitAdd(expr); | 4961 case Token::ADD: return VisitAdd(expr); |
4925 case Token::SUB: return VisitSub(expr); | 4962 case Token::SUB: return VisitSub(expr); |
4926 case Token::BIT_NOT: return VisitBitNot(expr); | 4963 case Token::BIT_NOT: return VisitBitNot(expr); |
4927 case Token::NOT: return VisitNot(expr); | 4964 case Token::NOT: return VisitNot(expr); |
4928 default: UNREACHABLE(); | 4965 default: UNREACHABLE(); |
4929 } | 4966 } |
4930 } | 4967 } |
4931 | 4968 |
4932 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { | 4969 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { |
4933 Property* prop = expr->expression()->AsProperty(); | 4970 Property* prop = expr->expression()->AsProperty(); |
4934 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4971 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
4935 if (prop == NULL && var == NULL) { | 4972 if (prop == NULL && var == NULL) { |
4936 // Result of deleting non-property, non-variable reference is true. | 4973 // Result of deleting non-property, non-variable reference is true. |
4937 // Evaluate the subexpression for side effects. | 4974 // Evaluate the subexpression for side effects. |
4938 CHECK_ALIVE(VisitForEffect(expr->expression())); | 4975 CHECK_ALIVE(VisitForEffect(expr->expression())); |
4939 ast_context()->ReturnValue(graph()->GetConstantTrue()); | 4976 return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
4940 } else if (var != NULL && | 4977 } else if (var != NULL && |
4941 !var->is_global() && | 4978 !var->is_global() && |
4942 var->AsSlot() != NULL && | 4979 var->AsSlot() != NULL && |
4943 var->AsSlot()->type() != Slot::LOOKUP) { | 4980 var->AsSlot()->type() != Slot::LOOKUP) { |
4944 // Result of deleting non-global, non-dynamic variables is false. | 4981 // Result of deleting non-global, non-dynamic variables is false. |
4945 // The subexpression does not have side effects. | 4982 // The subexpression does not have side effects. |
4946 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4983 return ast_context()->ReturnValue(graph()->GetConstantFalse()); |
4947 } else if (prop != NULL) { | 4984 } else if (prop != NULL) { |
4948 if (prop->is_synthetic()) { | 4985 if (prop->is_synthetic()) { |
4949 // Result of deleting parameters is false, even when they rewrite | 4986 // Result of deleting parameters is false, even when they rewrite |
4950 // to accesses on the arguments object. | 4987 // to accesses on the arguments object. |
4951 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4988 return ast_context()->ReturnValue(graph()->GetConstantFalse()); |
4952 } else { | 4989 } else { |
4953 CHECK_ALIVE(VisitForValue(prop->obj())); | 4990 CHECK_ALIVE(VisitForValue(prop->obj())); |
4954 CHECK_ALIVE(VisitForValue(prop->key())); | 4991 CHECK_ALIVE(VisitForValue(prop->key())); |
4955 HValue* key = Pop(); | 4992 HValue* key = Pop(); |
4956 HValue* obj = Pop(); | 4993 HValue* obj = Pop(); |
4957 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); | 4994 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); |
4958 ast_context()->ReturnInstruction(instr, expr->id()); | 4995 return ast_context()->ReturnInstruction(instr, expr->id()); |
4959 } | 4996 } |
4960 } else if (var->is_global()) { | 4997 } else if (var->is_global()) { |
4961 Bailout("delete with global variable"); | 4998 Bailout("delete with global variable"); |
4962 } else { | 4999 } else { |
4963 Bailout("delete with non-global variable"); | 5000 Bailout("delete with non-global variable"); |
4964 } | 5001 } |
4965 } | 5002 } |
4966 | 5003 |
4967 | 5004 |
4968 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { | 5005 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { |
4969 CHECK_ALIVE(VisitForEffect(expr->expression())); | 5006 CHECK_ALIVE(VisitForEffect(expr->expression())); |
4970 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 5007 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
4971 } | 5008 } |
4972 | 5009 |
4973 | 5010 |
4974 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 5011 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
4975 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 5012 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
4976 HValue* value = Pop(); | 5013 HValue* value = Pop(); |
4977 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); | 5014 return ast_context()->ReturnInstruction(new(zone()) HTypeof(value), |
5015 expr->id()); | |
4978 } | 5016 } |
4979 | 5017 |
4980 | 5018 |
4981 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { | 5019 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { |
4982 CHECK_ALIVE(VisitForValue(expr->expression())); | 5020 CHECK_ALIVE(VisitForValue(expr->expression())); |
4983 HValue* value = Pop(); | 5021 HValue* value = Pop(); |
4984 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1()); | 5022 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1()); |
4985 ast_context()->ReturnInstruction(instr, expr->id()); | 5023 return ast_context()->ReturnInstruction(instr, expr->id()); |
4986 } | 5024 } |
4987 | 5025 |
4988 | 5026 |
4989 void HGraphBuilder::VisitSub(UnaryOperation* expr) { | 5027 void HGraphBuilder::VisitSub(UnaryOperation* expr) { |
4990 CHECK_ALIVE(VisitForValue(expr->expression())); | 5028 CHECK_ALIVE(VisitForValue(expr->expression())); |
4991 HValue* value = Pop(); | 5029 HValue* value = Pop(); |
4992 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); | 5030 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); |
4993 TypeInfo info = oracle()->UnaryType(expr); | 5031 TypeInfo info = oracle()->UnaryType(expr); |
4994 if (info.IsUninitialized()) { | 5032 if (info.IsUninitialized()) { |
4995 AddInstruction(new(zone()) HSoftDeoptimize); | 5033 AddInstruction(new(zone()) HSoftDeoptimize); |
4996 current_block()->MarkAsDeoptimizing(); | 5034 current_block()->MarkAsDeoptimizing(); |
4997 info = TypeInfo::Unknown(); | 5035 info = TypeInfo::Unknown(); |
4998 } | 5036 } |
4999 Representation rep = ToRepresentation(info); | 5037 Representation rep = ToRepresentation(info); |
5000 TraceRepresentation(expr->op(), info, instr, rep); | 5038 TraceRepresentation(expr->op(), info, instr, rep); |
5001 instr->AssumeRepresentation(rep); | 5039 instr->AssumeRepresentation(rep); |
5002 ast_context()->ReturnInstruction(instr, expr->id()); | 5040 return ast_context()->ReturnInstruction(instr, expr->id()); |
5003 } | 5041 } |
5004 | 5042 |
5005 | 5043 |
5006 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 5044 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
5007 CHECK_ALIVE(VisitForValue(expr->expression())); | 5045 CHECK_ALIVE(VisitForValue(expr->expression())); |
5008 HValue* value = Pop(); | 5046 HValue* value = Pop(); |
5009 TypeInfo info = oracle()->UnaryType(expr); | 5047 TypeInfo info = oracle()->UnaryType(expr); |
5010 if (info.IsUninitialized()) { | 5048 if (info.IsUninitialized()) { |
5011 AddInstruction(new(zone()) HSoftDeoptimize); | 5049 AddInstruction(new(zone()) HSoftDeoptimize); |
5012 current_block()->MarkAsDeoptimizing(); | 5050 current_block()->MarkAsDeoptimizing(); |
5013 } | 5051 } |
5014 HInstruction* instr = new(zone()) HBitNot(value); | 5052 HInstruction* instr = new(zone()) HBitNot(value); |
5015 ast_context()->ReturnInstruction(instr, expr->id()); | 5053 return ast_context()->ReturnInstruction(instr, expr->id()); |
5016 } | 5054 } |
5017 | 5055 |
5018 | 5056 |
5019 void HGraphBuilder::VisitNot(UnaryOperation* expr) { | 5057 void HGraphBuilder::VisitNot(UnaryOperation* expr) { |
5020 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. | 5058 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. |
5021 if (ast_context()->IsTest()) { | 5059 if (ast_context()->IsTest()) { |
5022 TestContext* context = TestContext::cast(ast_context()); | 5060 TestContext* context = TestContext::cast(ast_context()); |
5023 VisitForControl(expr->expression(), | 5061 VisitForControl(expr->expression(), |
5024 context->if_false(), | 5062 context->if_false(), |
5025 context->if_true()); | 5063 context->if_true()); |
(...skipping 24 matching lines...) Expand all Loading... | |
5050 materialize_true->SetJoinId(expr->expression()->id()); | 5088 materialize_true->SetJoinId(expr->expression()->id()); |
5051 set_current_block(materialize_true); | 5089 set_current_block(materialize_true); |
5052 Push(graph()->GetConstantTrue()); | 5090 Push(graph()->GetConstantTrue()); |
5053 } else { | 5091 } else { |
5054 materialize_true = NULL; | 5092 materialize_true = NULL; |
5055 } | 5093 } |
5056 | 5094 |
5057 HBasicBlock* join = | 5095 HBasicBlock* join = |
5058 CreateJoin(materialize_false, materialize_true, expr->id()); | 5096 CreateJoin(materialize_false, materialize_true, expr->id()); |
5059 set_current_block(join); | 5097 set_current_block(join); |
5060 if (join != NULL) ast_context()->ReturnValue(Pop()); | 5098 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
5061 } | 5099 } |
5062 | 5100 |
5063 | 5101 |
5064 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, | 5102 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, |
5065 CountOperation* expr) { | 5103 CountOperation* expr) { |
5066 // The input to the count operation is on top of the expression stack. | 5104 // The input to the count operation is on top of the expression stack. |
5067 TypeInfo info = oracle()->IncrementType(expr); | 5105 TypeInfo info = oracle()->IncrementType(expr); |
5068 Representation rep = ToRepresentation(info); | 5106 Representation rep = ToRepresentation(info); |
5069 if (rep.IsTagged()) { | 5107 if (rep.IsTagged()) { |
5070 rep = Representation::Integer32(); | 5108 rep = Representation::Integer32(); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5225 // original value if necessary. | 5263 // original value if necessary. |
5226 Drop(1); | 5264 Drop(1); |
5227 environment()->SetExpressionStackAt(0, after); | 5265 environment()->SetExpressionStackAt(0, after); |
5228 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | 5266 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
5229 ASSERT(has_side_effects); // Stores always have side effects. | 5267 ASSERT(has_side_effects); // Stores always have side effects. |
5230 AddSimulate(expr->AssignmentId()); | 5268 AddSimulate(expr->AssignmentId()); |
5231 } | 5269 } |
5232 } | 5270 } |
5233 | 5271 |
5234 Drop(returns_original_input ? 2 : 1); | 5272 Drop(returns_original_input ? 2 : 1); |
5235 ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 5273 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
5236 } | 5274 } |
5237 | 5275 |
5238 | 5276 |
5239 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, | 5277 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, |
5240 HValue* index) { | 5278 HValue* index) { |
5241 AddInstruction(new(zone()) HCheckNonSmi(string)); | 5279 AddInstruction(new(zone()) HCheckNonSmi(string)); |
5242 AddInstruction(HCheckInstanceType::NewIsString(string)); | 5280 AddInstruction(HCheckInstanceType::NewIsString(string)); |
5243 HStringLength* length = new(zone()) HStringLength(string); | 5281 HStringLength* length = new(zone()) HStringLength(string); |
5244 AddInstruction(length); | 5282 AddInstruction(length); |
5245 HInstruction* checked_index = | 5283 HInstruction* checked_index = |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5385 Visit(expr->right()); | 5423 Visit(expr->right()); |
5386 } | 5424 } |
5387 | 5425 |
5388 } else if (ast_context()->IsValue()) { | 5426 } else if (ast_context()->IsValue()) { |
5389 CHECK_ALIVE(VisitForValue(expr->left())); | 5427 CHECK_ALIVE(VisitForValue(expr->left())); |
5390 ASSERT(current_block() != NULL); | 5428 ASSERT(current_block() != NULL); |
5391 | 5429 |
5392 // We need an extra block to maintain edge-split form. | 5430 // We need an extra block to maintain edge-split form. |
5393 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 5431 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
5394 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 5432 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
5395 HTest* test = is_logical_and | 5433 HBranch* test = is_logical_and |
5396 ? new(zone()) HTest(Top(), eval_right, empty_block) | 5434 ? new(zone()) HBranch(Top(), eval_right, empty_block) |
5397 : new(zone()) HTest(Top(), empty_block, eval_right); | 5435 : new(zone()) HBranch(Top(), empty_block, eval_right); |
5398 current_block()->Finish(test); | 5436 current_block()->Finish(test); |
5399 | 5437 |
5400 set_current_block(eval_right); | 5438 set_current_block(eval_right); |
5401 Drop(1); // Value of the left subexpression. | 5439 Drop(1); // Value of the left subexpression. |
5402 CHECK_BAILOUT(VisitForValue(expr->right())); | 5440 CHECK_BAILOUT(VisitForValue(expr->right())); |
5403 | 5441 |
5404 HBasicBlock* join_block = | 5442 HBasicBlock* join_block = |
5405 CreateJoin(empty_block, current_block(), expr->id()); | 5443 CreateJoin(empty_block, current_block(), expr->id()); |
5406 set_current_block(join_block); | 5444 set_current_block(join_block); |
5407 ast_context()->ReturnValue(Pop()); | 5445 return ast_context()->ReturnValue(Pop()); |
5408 | 5446 |
5409 } else { | 5447 } else { |
5410 ASSERT(ast_context()->IsEffect()); | 5448 ASSERT(ast_context()->IsEffect()); |
5411 // In an effect context, we don't need the value of the left subexpression, | 5449 // In an effect context, we don't need the value of the left subexpression, |
5412 // only its control flow and side effects. We need an extra block to | 5450 // only its control flow and side effects. We need an extra block to |
5413 // maintain edge-split form. | 5451 // maintain edge-split form. |
5414 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 5452 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
5415 HBasicBlock* right_block = graph()->CreateBasicBlock(); | 5453 HBasicBlock* right_block = graph()->CreateBasicBlock(); |
5416 if (is_logical_and) { | 5454 if (is_logical_and) { |
5417 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); | 5455 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5449 } | 5487 } |
5450 | 5488 |
5451 | 5489 |
5452 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 5490 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { |
5453 CHECK_ALIVE(VisitForValue(expr->left())); | 5491 CHECK_ALIVE(VisitForValue(expr->left())); |
5454 CHECK_ALIVE(VisitForValue(expr->right())); | 5492 CHECK_ALIVE(VisitForValue(expr->right())); |
5455 HValue* right = Pop(); | 5493 HValue* right = Pop(); |
5456 HValue* left = Pop(); | 5494 HValue* left = Pop(); |
5457 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 5495 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
5458 instr->set_position(expr->position()); | 5496 instr->set_position(expr->position()); |
5459 ast_context()->ReturnInstruction(instr, expr->id()); | 5497 return ast_context()->ReturnInstruction(instr, expr->id()); |
5460 } | 5498 } |
5461 | 5499 |
5462 | 5500 |
5463 void HGraphBuilder::TraceRepresentation(Token::Value op, | 5501 void HGraphBuilder::TraceRepresentation(Token::Value op, |
5464 TypeInfo info, | 5502 TypeInfo info, |
5465 HValue* value, | 5503 HValue* value, |
5466 Representation rep) { | 5504 Representation rep) { |
5467 if (!FLAG_trace_representation) return; | 5505 if (!FLAG_trace_representation) return; |
5468 // TODO(svenpanne) Under which circumstances are we actually not flexible? | 5506 // TODO(svenpanne) Under which circumstances are we actually not flexible? |
5469 // At first glance, this looks a bit weird... | 5507 // At first glance, this looks a bit weird... |
(...skipping 17 matching lines...) Expand all Loading... | |
5487 if (info.IsNumber()) return Representation::Double(); | 5525 if (info.IsNumber()) return Representation::Double(); |
5488 return Representation::Tagged(); | 5526 return Representation::Tagged(); |
5489 } | 5527 } |
5490 | 5528 |
5491 | 5529 |
5492 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr, | 5530 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr, |
5493 Expression* expr, | 5531 Expression* expr, |
5494 Handle<String> check) { | 5532 Handle<String> check) { |
5495 CHECK_ALIVE(VisitForTypeOf(expr)); | 5533 CHECK_ALIVE(VisitForTypeOf(expr)); |
5496 HValue* expr_value = Pop(); | 5534 HValue* expr_value = Pop(); |
5497 HInstruction* instr = new(zone()) HTypeofIs(expr_value, check); | 5535 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check); |
5498 instr->set_position(compare_expr->position()); | 5536 instr->set_position(compare_expr->position()); |
5499 ast_context()->ReturnInstruction(instr, compare_expr->id()); | 5537 return ast_context()->ReturnControl(instr, compare_expr->id()); |
5500 } | 5538 } |
5501 | 5539 |
5502 | 5540 |
5503 void HGraphBuilder::HandleLiteralCompareUndefined( | 5541 void HGraphBuilder::HandleLiteralCompareUndefined( |
5504 CompareOperation* compare_expr, Expression* expr) { | 5542 CompareOperation* compare_expr, Expression* expr) { |
5505 CHECK_ALIVE(VisitForValue(expr)); | 5543 CHECK_ALIVE(VisitForValue(expr)); |
5506 HValue* lhs = Pop(); | 5544 HValue* lhs = Pop(); |
5507 HValue* rhs = graph()->GetConstantUndefined(); | 5545 HValue* rhs = graph()->GetConstantUndefined(); |
5508 HInstruction* instr = | 5546 HCompareObjectEqAndBranch* instr = |
5509 new(zone()) HCompareObjectEq(lhs, rhs); | 5547 new(zone()) HCompareObjectEqAndBranch(lhs, rhs); |
5510 instr->set_position(compare_expr->position()); | 5548 instr->set_position(compare_expr->position()); |
5511 ast_context()->ReturnInstruction(instr, compare_expr->id()); | 5549 return ast_context()->ReturnControl(instr, compare_expr->id()); |
5512 } | 5550 } |
5513 | 5551 |
5514 | 5552 |
5515 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 5553 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
5516 ASSERT(!HasStackOverflow()); | 5554 ASSERT(!HasStackOverflow()); |
5517 ASSERT(current_block() != NULL); | 5555 ASSERT(current_block() != NULL); |
5518 ASSERT(current_block()->HasPredecessor()); | 5556 ASSERT(current_block()->HasPredecessor()); |
5519 if (IsClassOfTest(expr)) { | 5557 if (IsClassOfTest(expr)) { |
5520 CallRuntime* call = expr->left()->AsCallRuntime(); | 5558 CallRuntime* call = expr->left()->AsCallRuntime(); |
5559 ASSERT(call->arguments()->length() == 1); | |
5521 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5560 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5522 HValue* value = Pop(); | 5561 HValue* value = Pop(); |
5523 Literal* literal = expr->right()->AsLiteral(); | 5562 Literal* literal = expr->right()->AsLiteral(); |
5524 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 5563 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
5525 HInstruction* instr = new(zone()) HClassOfTest(value, rhs); | 5564 HClassOfTestAndBranch* instr = |
5565 new(zone()) HClassOfTestAndBranch(value, rhs); | |
5526 instr->set_position(expr->position()); | 5566 instr->set_position(expr->position()); |
5527 ast_context()->ReturnInstruction(instr, expr->id()); | 5567 return ast_context()->ReturnControl(instr, expr->id()); |
5528 return; | |
5529 } | 5568 } |
5530 | 5569 |
5531 // Check for special cases that compare against literals. | 5570 // Check for special cases that compare against literals. |
5532 Expression *sub_expr; | 5571 Expression *sub_expr; |
5533 Handle<String> check; | 5572 Handle<String> check; |
5534 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 5573 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
5535 HandleLiteralCompareTypeof(expr, sub_expr, check); | 5574 HandleLiteralCompareTypeof(expr, sub_expr, check); |
5536 return; | 5575 return; |
5537 } | 5576 } |
5538 | 5577 |
(...skipping 10 matching lines...) Expand all Loading... | |
5549 type_info = TypeInfo::Unknown(); | 5588 type_info = TypeInfo::Unknown(); |
5550 } | 5589 } |
5551 | 5590 |
5552 CHECK_ALIVE(VisitForValue(expr->left())); | 5591 CHECK_ALIVE(VisitForValue(expr->left())); |
5553 CHECK_ALIVE(VisitForValue(expr->right())); | 5592 CHECK_ALIVE(VisitForValue(expr->right())); |
5554 | 5593 |
5555 HValue* right = Pop(); | 5594 HValue* right = Pop(); |
5556 HValue* left = Pop(); | 5595 HValue* left = Pop(); |
5557 Token::Value op = expr->op(); | 5596 Token::Value op = expr->op(); |
5558 | 5597 |
5559 HInstruction* instr = NULL; | |
5560 if (op == Token::INSTANCEOF) { | 5598 if (op == Token::INSTANCEOF) { |
5561 // Check to see if the rhs of the instanceof is a global function not | 5599 // Check to see if the rhs of the instanceof is a global function not |
5562 // residing in new space. If it is we assume that the function will stay the | 5600 // residing in new space. If it is we assume that the function will stay the |
5563 // same. | 5601 // same. |
5564 Handle<JSFunction> target = Handle<JSFunction>::null(); | 5602 Handle<JSFunction> target = Handle<JSFunction>::null(); |
5565 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); | 5603 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); |
5566 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); | 5604 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); |
5567 if (global_function && | 5605 if (global_function && |
5568 info()->has_global_object() && | 5606 info()->has_global_object() && |
5569 !info()->global_object()->IsAccessCheckNeeded()) { | 5607 !info()->global_object()->IsAccessCheckNeeded()) { |
(...skipping 10 matching lines...) Expand all Loading... | |
5580 if (!isolate()->heap()->InNewSpace(*candidate)) { | 5618 if (!isolate()->heap()->InNewSpace(*candidate)) { |
5581 target = candidate; | 5619 target = candidate; |
5582 } | 5620 } |
5583 } | 5621 } |
5584 } | 5622 } |
5585 | 5623 |
5586 // If the target is not null we have found a known global function that is | 5624 // If the target is not null we have found a known global function that is |
5587 // assumed to stay the same for this instanceof. | 5625 // assumed to stay the same for this instanceof. |
5588 if (target.is_null()) { | 5626 if (target.is_null()) { |
5589 HValue* context = environment()->LookupContext(); | 5627 HValue* context = environment()->LookupContext(); |
5590 instr = new(zone()) HInstanceOf(context, left, right); | 5628 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
5629 result->set_position(expr->position()); | |
5630 return ast_context()->ReturnInstruction(result, expr->id()); | |
5591 } else { | 5631 } else { |
5592 AddInstruction(new(zone()) HCheckFunction(right, target)); | 5632 AddInstruction(new(zone()) HCheckFunction(right, target)); |
5593 instr = new(zone()) HInstanceOfKnownGlobal(left, target); | 5633 HInstanceOfKnownGlobal* result = |
5634 new(zone()) HInstanceOfKnownGlobal(left, target); | |
5635 result->set_position(expr->position()); | |
5636 return ast_context()->ReturnInstruction(result, expr->id()); | |
5594 } | 5637 } |
5595 } else if (op == Token::IN) { | 5638 } else if (op == Token::IN) { |
5596 instr = new(zone()) HIn(left, right); | 5639 HIn* result = new(zone()) HIn(left, right); |
5640 result->set_position(expr->position()); | |
5641 return ast_context()->ReturnInstruction(result, expr->id()); | |
5597 } else if (type_info.IsNonPrimitive()) { | 5642 } else if (type_info.IsNonPrimitive()) { |
5598 switch (op) { | 5643 switch (op) { |
5599 case Token::EQ: | 5644 case Token::EQ: |
5600 case Token::EQ_STRICT: { | 5645 case Token::EQ_STRICT: { |
5601 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5646 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5602 AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); | 5647 AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); |
5603 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5648 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5604 AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); | 5649 AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); |
5605 instr = new(zone()) HCompareObjectEq(left, right); | 5650 HCompareObjectEqAndBranch* result = |
5606 break; | 5651 new(zone()) HCompareObjectEqAndBranch(left, right); |
5652 result->set_position(expr->position()); | |
5653 return ast_context()->ReturnControl(result, expr->id()); | |
5607 } | 5654 } |
5608 default: | 5655 default: |
5609 return Bailout("Unsupported non-primitive compare"); | 5656 return Bailout("Unsupported non-primitive compare"); |
5610 break; | |
5611 } | 5657 } |
5612 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && | 5658 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && |
5613 (op == Token::EQ || op == Token::EQ_STRICT)) { | 5659 (op == Token::EQ || op == Token::EQ_STRICT)) { |
5614 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5660 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5615 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); | 5661 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); |
5616 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5662 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5617 AddInstruction(HCheckInstanceType::NewIsSymbol(right)); | 5663 AddInstruction(HCheckInstanceType::NewIsSymbol(right)); |
5618 instr = new(zone()) HCompareObjectEq(left, right); | 5664 HCompareObjectEqAndBranch* result = |
5665 new(zone()) HCompareObjectEqAndBranch(left, right); | |
5666 result->set_position(expr->position()); | |
5667 return ast_context()->ReturnControl(result, expr->id()); | |
5619 } else { | 5668 } else { |
5620 HCompare* compare = new(zone()) HCompare(left, right, op); | |
5621 Representation r = ToRepresentation(type_info); | 5669 Representation r = ToRepresentation(type_info); |
5622 compare->SetInputRepresentation(r); | 5670 if (r.IsTagged()) { |
5623 instr = compare; | 5671 HCompareGeneric* result = new(zone()) HCompareGeneric(left, right, op); |
5672 result->set_position(expr->position()); | |
5673 return ast_context()->ReturnInstruction(result, expr->id()); | |
5674 } else { | |
5675 HCompareIDAndBranch* result = | |
5676 new(zone()) HCompareIDAndBranch(left, right, op); | |
5677 result->set_position(expr->position()); | |
5678 result->SetInputRepresentation(r); | |
5679 return ast_context()->ReturnControl(result, expr->id()); | |
5680 } | |
5624 } | 5681 } |
5625 instr->set_position(expr->position()); | |
5626 ast_context()->ReturnInstruction(instr, expr->id()); | |
5627 } | 5682 } |
5628 | 5683 |
5629 | 5684 |
5630 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { | 5685 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
5631 ASSERT(!HasStackOverflow()); | 5686 ASSERT(!HasStackOverflow()); |
5632 ASSERT(current_block() != NULL); | 5687 ASSERT(current_block() != NULL); |
5633 ASSERT(current_block()->HasPredecessor()); | 5688 ASSERT(current_block()->HasPredecessor()); |
5634 CHECK_ALIVE(VisitForValue(expr->expression())); | 5689 CHECK_ALIVE(VisitForValue(expr->expression())); |
5635 | |
5636 HValue* value = Pop(); | 5690 HValue* value = Pop(); |
5637 HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); | 5691 HIsNullAndBranch* instr = |
5638 ast_context()->ReturnInstruction(compare, expr->id()); | 5692 new(zone()) HIsNullAndBranch(value, expr->is_strict()); |
5693 return ast_context()->ReturnControl(instr, expr->id()); | |
5639 } | 5694 } |
5640 | 5695 |
5641 | 5696 |
5642 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 5697 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
5643 ASSERT(!HasStackOverflow()); | 5698 ASSERT(!HasStackOverflow()); |
5644 ASSERT(current_block() != NULL); | 5699 ASSERT(current_block() != NULL); |
5645 ASSERT(current_block()->HasPredecessor()); | 5700 ASSERT(current_block()->HasPredecessor()); |
5646 HThisFunction* self = new(zone()) HThisFunction; | 5701 HThisFunction* self = new(zone()) HThisFunction; |
5647 return ast_context()->ReturnInstruction(self, expr->id()); | 5702 return ast_context()->ReturnInstruction(self, expr->id()); |
5648 } | 5703 } |
(...skipping 12 matching lines...) Expand all Loading... | |
5661 } | 5716 } |
5662 } | 5717 } |
5663 | 5718 |
5664 | 5719 |
5665 // Generators for inline runtime functions. | 5720 // Generators for inline runtime functions. |
5666 // Support for types. | 5721 // Support for types. |
5667 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 5722 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
5668 ASSERT(call->arguments()->length() == 1); | 5723 ASSERT(call->arguments()->length() == 1); |
5669 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5724 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5670 HValue* value = Pop(); | 5725 HValue* value = Pop(); |
5671 HIsSmi* result = new(zone()) HIsSmi(value); | 5726 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
5672 ast_context()->ReturnInstruction(result, call->id()); | 5727 return ast_context()->ReturnControl(result, call->id()); |
5673 } | 5728 } |
5674 | 5729 |
5675 | 5730 |
5676 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 5731 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
5677 ASSERT(call->arguments()->length() == 1); | 5732 ASSERT(call->arguments()->length() == 1); |
5678 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5733 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5679 HValue* value = Pop(); | 5734 HValue* value = Pop(); |
5680 HHasInstanceType* result = | 5735 HHasInstanceTypeAndBranch* result = |
5681 new(zone()) HHasInstanceType(value, | 5736 new(zone()) HHasInstanceTypeAndBranch(value, |
5682 FIRST_SPEC_OBJECT_TYPE, | 5737 FIRST_SPEC_OBJECT_TYPE, |
5683 LAST_SPEC_OBJECT_TYPE); | 5738 LAST_SPEC_OBJECT_TYPE); |
5684 ast_context()->ReturnInstruction(result, call->id()); | 5739 return ast_context()->ReturnControl(result, call->id()); |
5685 } | 5740 } |
5686 | 5741 |
5687 | 5742 |
5688 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 5743 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
5689 ASSERT(call->arguments()->length() == 1); | 5744 ASSERT(call->arguments()->length() == 1); |
5690 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5745 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5691 HValue* value = Pop(); | 5746 HValue* value = Pop(); |
5692 HHasInstanceType* result = | 5747 HHasInstanceTypeAndBranch* result = |
5693 new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); | 5748 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); |
5694 ast_context()->ReturnInstruction(result, call->id()); | 5749 return ast_context()->ReturnControl(result, call->id()); |
5695 } | 5750 } |
5696 | 5751 |
5697 | 5752 |
5698 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 5753 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
5699 ASSERT(call->arguments()->length() == 1); | 5754 ASSERT(call->arguments()->length() == 1); |
5700 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5755 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5701 HValue* value = Pop(); | 5756 HValue* value = Pop(); |
5702 HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); | 5757 HHasCachedArrayIndexAndBranch* result = |
5703 ast_context()->ReturnInstruction(result, call->id()); | 5758 new(zone()) HHasCachedArrayIndexAndBranch(value); |
5759 return ast_context()->ReturnControl(result, call->id()); | |
5704 } | 5760 } |
5705 | 5761 |
5706 | 5762 |
5707 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { | 5763 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
5708 ASSERT(call->arguments()->length() == 1); | 5764 ASSERT(call->arguments()->length() == 1); |
5709 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5765 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5710 HValue* value = Pop(); | 5766 HValue* value = Pop(); |
5711 HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); | 5767 HHasInstanceTypeAndBranch* result = |
5712 ast_context()->ReturnInstruction(result, call->id()); | 5768 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); |
5769 return ast_context()->ReturnControl(result, call->id()); | |
5713 } | 5770 } |
5714 | 5771 |
5715 | 5772 |
5716 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 5773 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
5717 ASSERT(call->arguments()->length() == 1); | 5774 ASSERT(call->arguments()->length() == 1); |
5718 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5775 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5719 HValue* value = Pop(); | 5776 HValue* value = Pop(); |
5720 HHasInstanceType* result = | 5777 HHasInstanceTypeAndBranch* result = |
5721 new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); | 5778 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); |
5722 ast_context()->ReturnInstruction(result, call->id()); | 5779 return ast_context()->ReturnControl(result, call->id()); |
5723 } | 5780 } |
5724 | 5781 |
5725 | 5782 |
5726 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { | 5783 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
5727 ASSERT(call->arguments()->length() == 1); | 5784 ASSERT(call->arguments()->length() == 1); |
5728 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5785 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5729 HValue* value = Pop(); | 5786 HValue* value = Pop(); |
5730 HIsObject* test = new(zone()) HIsObject(value); | 5787 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
5731 ast_context()->ReturnInstruction(test, call->id()); | 5788 return ast_context()->ReturnControl(result, call->id()); |
5732 } | 5789 } |
5733 | 5790 |
5734 | 5791 |
5735 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 5792 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
5736 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 5793 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
5737 } | 5794 } |
5738 | 5795 |
5739 | 5796 |
5740 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 5797 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
5741 ASSERT(call->arguments()->length() == 1); | 5798 ASSERT(call->arguments()->length() == 1); |
5742 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5799 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5743 HValue* value = Pop(); | 5800 HValue* value = Pop(); |
5744 ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value), | 5801 HIsUndetectableAndBranch* result = |
5745 call->id()); | 5802 new(zone()) HIsUndetectableAndBranch(value); |
5803 return ast_context()->ReturnControl(result, call->id()); | |
5746 } | 5804 } |
5747 | 5805 |
5748 | 5806 |
5749 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 5807 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
5750 CallRuntime* call) { | 5808 CallRuntime* call) { |
5751 return Bailout( | 5809 return Bailout( |
5752 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 5810 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
5753 } | 5811 } |
5754 | 5812 |
5755 | 5813 |
5756 // Support for construct call checks. | 5814 // Support for construct call checks. |
5757 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 5815 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
5758 ASSERT(call->arguments()->length() == 0); | 5816 ASSERT(call->arguments()->length() == 0); |
5759 if (function_state()->outer() != NULL) { | 5817 if (function_state()->outer() != NULL) { |
5760 // We are generating graph for inlined function. Currently | 5818 // We are generating graph for inlined function. Currently |
5761 // constructor inlining is not supported and we can just return | 5819 // constructor inlining is not supported and we can just return |
5762 // false from %_IsConstructCall(). | 5820 // false from %_IsConstructCall(). |
5763 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 5821 return ast_context()->ReturnValue(graph()->GetConstantFalse()); |
5764 } else { | 5822 } else { |
5765 ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); | 5823 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, |
5824 call->id()); | |
5766 } | 5825 } |
5767 } | 5826 } |
5768 | 5827 |
5769 | 5828 |
5770 // Support for arguments.length and arguments[?]. | 5829 // Support for arguments.length and arguments[?]. |
5771 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 5830 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
5772 // Our implementation of arguments (based on this stack frame or an | 5831 // Our implementation of arguments (based on this stack frame or an |
5773 // adapter below it) does not work for inlined functions. This runtime | 5832 // adapter below it) does not work for inlined functions. This runtime |
5774 // function is blacklisted by AstNode::IsInlineable. | 5833 // function is blacklisted by AstNode::IsInlineable. |
5775 ASSERT(function_state()->outer() == NULL); | 5834 ASSERT(function_state()->outer() == NULL); |
5776 ASSERT(call->arguments()->length() == 0); | 5835 ASSERT(call->arguments()->length() == 0); |
5777 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 5836 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
5778 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 5837 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
5779 ast_context()->ReturnInstruction(result, call->id()); | 5838 return ast_context()->ReturnInstruction(result, call->id()); |
5780 } | 5839 } |
5781 | 5840 |
5782 | 5841 |
5783 void HGraphBuilder::GenerateArguments(CallRuntime* call) { | 5842 void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
5784 // Our implementation of arguments (based on this stack frame or an | 5843 // Our implementation of arguments (based on this stack frame or an |
5785 // adapter below it) does not work for inlined functions. This runtime | 5844 // adapter below it) does not work for inlined functions. This runtime |
5786 // function is blacklisted by AstNode::IsInlineable. | 5845 // function is blacklisted by AstNode::IsInlineable. |
5787 ASSERT(function_state()->outer() == NULL); | 5846 ASSERT(function_state()->outer() == NULL); |
5788 ASSERT(call->arguments()->length() == 1); | 5847 ASSERT(call->arguments()->length() == 1); |
5789 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5848 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5790 HValue* index = Pop(); | 5849 HValue* index = Pop(); |
5791 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 5850 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
5792 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 5851 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
5793 HAccessArgumentsAt* result = | 5852 HAccessArgumentsAt* result = |
5794 new(zone()) HAccessArgumentsAt(elements, length, index); | 5853 new(zone()) HAccessArgumentsAt(elements, length, index); |
5795 ast_context()->ReturnInstruction(result, call->id()); | 5854 return ast_context()->ReturnInstruction(result, call->id()); |
5796 } | 5855 } |
5797 | 5856 |
5798 | 5857 |
5799 // Support for accessing the class and value fields of an object. | 5858 // Support for accessing the class and value fields of an object. |
5800 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { | 5859 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
5801 // The special form detected by IsClassOfTest is detected before we get here | 5860 // The special form detected by IsClassOfTest is detected before we get here |
5802 // and does not cause a bailout. | 5861 // and does not cause a bailout. |
5803 return Bailout("inlined runtime function: ClassOf"); | 5862 return Bailout("inlined runtime function: ClassOf"); |
5804 } | 5863 } |
5805 | 5864 |
5806 | 5865 |
5807 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { | 5866 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
5808 ASSERT(call->arguments()->length() == 1); | 5867 ASSERT(call->arguments()->length() == 1); |
5809 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5868 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5810 HValue* value = Pop(); | 5869 HValue* value = Pop(); |
5811 HValueOf* result = new(zone()) HValueOf(value); | 5870 HValueOf* result = new(zone()) HValueOf(value); |
5812 ast_context()->ReturnInstruction(result, call->id()); | 5871 return ast_context()->ReturnInstruction(result, call->id()); |
5813 } | 5872 } |
5814 | 5873 |
5815 | 5874 |
5816 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 5875 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
5817 return Bailout("inlined runtime function: SetValueOf"); | 5876 return Bailout("inlined runtime function: SetValueOf"); |
5818 } | 5877 } |
5819 | 5878 |
5820 | 5879 |
5821 // Fast support for charCodeAt(n). | 5880 // Fast support for charCodeAt(n). |
5822 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 5881 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
5823 ASSERT(call->arguments()->length() == 2); | 5882 ASSERT(call->arguments()->length() == 2); |
5824 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5883 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5825 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 5884 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5826 HValue* index = Pop(); | 5885 HValue* index = Pop(); |
5827 HValue* string = Pop(); | 5886 HValue* string = Pop(); |
5828 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); | 5887 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); |
5829 ast_context()->ReturnInstruction(result, call->id()); | 5888 return ast_context()->ReturnInstruction(result, call->id()); |
5830 } | 5889 } |
5831 | 5890 |
5832 | 5891 |
5833 // Fast support for string.charAt(n) and string[n]. | 5892 // Fast support for string.charAt(n) and string[n]. |
5834 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 5893 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
5835 ASSERT(call->arguments()->length() == 1); | 5894 ASSERT(call->arguments()->length() == 1); |
5836 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5895 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5837 HValue* char_code = Pop(); | 5896 HValue* char_code = Pop(); |
5838 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); | 5897 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
5839 ast_context()->ReturnInstruction(result, call->id()); | 5898 return ast_context()->ReturnInstruction(result, call->id()); |
5840 } | 5899 } |
5841 | 5900 |
5842 | 5901 |
5843 // Fast support for string.charAt(n) and string[n]. | 5902 // Fast support for string.charAt(n) and string[n]. |
5844 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 5903 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
5845 ASSERT(call->arguments()->length() == 2); | 5904 ASSERT(call->arguments()->length() == 2); |
5846 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5905 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5847 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 5906 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5848 HValue* index = Pop(); | 5907 HValue* index = Pop(); |
5849 HValue* string = Pop(); | 5908 HValue* string = Pop(); |
5850 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); | 5909 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
5851 AddInstruction(char_code); | 5910 AddInstruction(char_code); |
5852 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); | 5911 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
5853 ast_context()->ReturnInstruction(result, call->id()); | 5912 return ast_context()->ReturnInstruction(result, call->id()); |
5854 } | 5913 } |
5855 | 5914 |
5856 | 5915 |
5857 // Fast support for object equality testing. | 5916 // Fast support for object equality testing. |
5858 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 5917 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
5859 ASSERT(call->arguments()->length() == 2); | 5918 ASSERT(call->arguments()->length() == 2); |
5860 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5919 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5861 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 5920 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5862 HValue* right = Pop(); | 5921 HValue* right = Pop(); |
5863 HValue* left = Pop(); | 5922 HValue* left = Pop(); |
5864 HCompareObjectEq* result = new(zone()) HCompareObjectEq(left, right); | 5923 HCompareObjectEqAndBranch* result = |
5865 ast_context()->ReturnInstruction(result, call->id()); | 5924 new(zone()) HCompareObjectEqAndBranch(left, right); |
5925 return ast_context()->ReturnControl(result, call->id()); | |
5866 } | 5926 } |
5867 | 5927 |
5868 | 5928 |
5869 void HGraphBuilder::GenerateLog(CallRuntime* call) { | 5929 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
5870 // %_Log is ignored in optimized code. | 5930 // %_Log is ignored in optimized code. |
5871 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 5931 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
5872 } | 5932 } |
5873 | 5933 |
5874 | 5934 |
5875 // Fast support for Math.random(). | 5935 // Fast support for Math.random(). |
5876 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 5936 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
5877 return Bailout("inlined runtime function: RandomHeapNumber"); | 5937 return Bailout("inlined runtime function: RandomHeapNumber"); |
5878 } | 5938 } |
5879 | 5939 |
5880 | 5940 |
5881 // Fast support for StringAdd. | 5941 // Fast support for StringAdd. |
5882 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 5942 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
5883 ASSERT_EQ(2, call->arguments()->length()); | 5943 ASSERT_EQ(2, call->arguments()->length()); |
5884 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5944 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5885 HValue* context = environment()->LookupContext(); | 5945 HValue* context = environment()->LookupContext(); |
5886 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 5946 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
5887 Drop(2); | 5947 Drop(2); |
5888 ast_context()->ReturnInstruction(result, call->id()); | 5948 return ast_context()->ReturnInstruction(result, call->id()); |
5889 } | 5949 } |
5890 | 5950 |
5891 | 5951 |
5892 // Fast support for SubString. | 5952 // Fast support for SubString. |
5893 void HGraphBuilder::GenerateSubString(CallRuntime* call) { | 5953 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
5894 ASSERT_EQ(3, call->arguments()->length()); | 5954 ASSERT_EQ(3, call->arguments()->length()); |
5895 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5955 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5896 HValue* context = environment()->LookupContext(); | 5956 HValue* context = environment()->LookupContext(); |
5897 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 5957 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
5898 Drop(3); | 5958 Drop(3); |
5899 ast_context()->ReturnInstruction(result, call->id()); | 5959 return ast_context()->ReturnInstruction(result, call->id()); |
5900 } | 5960 } |
5901 | 5961 |
5902 | 5962 |
5903 // Fast support for StringCompare. | 5963 // Fast support for StringCompare. |
5904 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 5964 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
5905 ASSERT_EQ(2, call->arguments()->length()); | 5965 ASSERT_EQ(2, call->arguments()->length()); |
5906 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5966 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5907 HValue* context = environment()->LookupContext(); | 5967 HValue* context = environment()->LookupContext(); |
5908 HCallStub* result = | 5968 HCallStub* result = |
5909 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 5969 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
5910 Drop(2); | 5970 Drop(2); |
5911 ast_context()->ReturnInstruction(result, call->id()); | 5971 return ast_context()->ReturnInstruction(result, call->id()); |
5912 } | 5972 } |
5913 | 5973 |
5914 | 5974 |
5915 // Support for direct calls from JavaScript to native RegExp code. | 5975 // Support for direct calls from JavaScript to native RegExp code. |
5916 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 5976 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
5917 ASSERT_EQ(4, call->arguments()->length()); | 5977 ASSERT_EQ(4, call->arguments()->length()); |
5918 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5978 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5919 HValue* context = environment()->LookupContext(); | 5979 HValue* context = environment()->LookupContext(); |
5920 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 5980 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
5921 Drop(4); | 5981 Drop(4); |
5922 ast_context()->ReturnInstruction(result, call->id()); | 5982 return ast_context()->ReturnInstruction(result, call->id()); |
5923 } | 5983 } |
5924 | 5984 |
5925 | 5985 |
5926 // Construct a RegExp exec result with two in-object properties. | 5986 // Construct a RegExp exec result with two in-object properties. |
5927 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 5987 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
5928 ASSERT_EQ(3, call->arguments()->length()); | 5988 ASSERT_EQ(3, call->arguments()->length()); |
5929 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5989 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5930 HValue* context = environment()->LookupContext(); | 5990 HValue* context = environment()->LookupContext(); |
5931 HCallStub* result = | 5991 HCallStub* result = |
5932 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 5992 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
5933 Drop(3); | 5993 Drop(3); |
5934 ast_context()->ReturnInstruction(result, call->id()); | 5994 return ast_context()->ReturnInstruction(result, call->id()); |
5935 } | 5995 } |
5936 | 5996 |
5937 | 5997 |
5938 // Support for fast native caches. | 5998 // Support for fast native caches. |
5939 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 5999 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
5940 return Bailout("inlined runtime function: GetFromCache"); | 6000 return Bailout("inlined runtime function: GetFromCache"); |
5941 } | 6001 } |
5942 | 6002 |
5943 | 6003 |
5944 // Fast support for number to string. | 6004 // Fast support for number to string. |
5945 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 6005 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
5946 ASSERT_EQ(1, call->arguments()->length()); | 6006 ASSERT_EQ(1, call->arguments()->length()); |
5947 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 6007 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5948 HValue* context = environment()->LookupContext(); | 6008 HValue* context = environment()->LookupContext(); |
5949 HCallStub* result = | 6009 HCallStub* result = |
5950 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 6010 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
5951 Drop(1); | 6011 Drop(1); |
5952 ast_context()->ReturnInstruction(result, call->id()); | 6012 return ast_context()->ReturnInstruction(result, call->id()); |
5953 } | 6013 } |
5954 | 6014 |
5955 | 6015 |
5956 // Fast swapping of elements. Takes three expressions, the object and two | 6016 // Fast swapping of elements. Takes three expressions, the object and two |
5957 // indices. This should only be used if the indices are known to be | 6017 // indices. This should only be used if the indices are known to be |
5958 // non-negative and within bounds of the elements array at the call site. | 6018 // non-negative and within bounds of the elements array at the call site. |
5959 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { | 6019 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { |
5960 return Bailout("inlined runtime function: SwapElements"); | 6020 return Bailout("inlined runtime function: SwapElements"); |
5961 } | 6021 } |
5962 | 6022 |
5963 | 6023 |
5964 // Fast call for custom callbacks. | 6024 // Fast call for custom callbacks. |
5965 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 6025 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
5966 // 1 ~ The function to call is not itself an argument to the call. | 6026 // 1 ~ The function to call is not itself an argument to the call. |
5967 int arg_count = call->arguments()->length() - 1; | 6027 int arg_count = call->arguments()->length() - 1; |
5968 ASSERT(arg_count >= 1); // There's always at least a receiver. | 6028 ASSERT(arg_count >= 1); // There's always at least a receiver. |
5969 | 6029 |
5970 for (int i = 0; i < arg_count; ++i) { | 6030 for (int i = 0; i < arg_count; ++i) { |
5971 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 6031 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
5972 } | 6032 } |
5973 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 6033 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
5974 HValue* function = Pop(); | 6034 HValue* function = Pop(); |
5975 HValue* context = environment()->LookupContext(); | 6035 HValue* context = environment()->LookupContext(); |
5976 HInvokeFunction* result = | 6036 HInvokeFunction* result = |
5977 new(zone()) HInvokeFunction(context, function, arg_count); | 6037 new(zone()) HInvokeFunction(context, function, arg_count); |
5978 Drop(arg_count); | 6038 Drop(arg_count); |
5979 ast_context()->ReturnInstruction(result, call->id()); | 6039 return ast_context()->ReturnInstruction(result, call->id()); |
5980 } | 6040 } |
5981 | 6041 |
5982 | 6042 |
5983 // Fast call to math functions. | 6043 // Fast call to math functions. |
5984 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { | 6044 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
5985 ASSERT_EQ(2, call->arguments()->length()); | 6045 ASSERT_EQ(2, call->arguments()->length()); |
5986 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 6046 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5987 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 6047 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5988 HValue* right = Pop(); | 6048 HValue* right = Pop(); |
5989 HValue* left = Pop(); | 6049 HValue* left = Pop(); |
5990 HPower* result = new(zone()) HPower(left, right); | 6050 HPower* result = new(zone()) HPower(left, right); |
5991 ast_context()->ReturnInstruction(result, call->id()); | 6051 return ast_context()->ReturnInstruction(result, call->id()); |
5992 } | 6052 } |
5993 | 6053 |
5994 | 6054 |
5995 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { | 6055 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
5996 ASSERT_EQ(1, call->arguments()->length()); | 6056 ASSERT_EQ(1, call->arguments()->length()); |
5997 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 6057 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5998 HValue* context = environment()->LookupContext(); | 6058 HValue* context = environment()->LookupContext(); |
5999 HCallStub* result = | 6059 HCallStub* result = |
6000 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 6060 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
6001 result->set_transcendental_type(TranscendentalCache::SIN); | 6061 result->set_transcendental_type(TranscendentalCache::SIN); |
6002 Drop(1); | 6062 Drop(1); |
6003 ast_context()->ReturnInstruction(result, call->id()); | 6063 return ast_context()->ReturnInstruction(result, call->id()); |
6004 } | 6064 } |
6005 | 6065 |
6006 | 6066 |
6007 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { | 6067 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
6008 ASSERT_EQ(1, call->arguments()->length()); | 6068 ASSERT_EQ(1, call->arguments()->length()); |
6009 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 6069 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
6010 HValue* context = environment()->LookupContext(); | 6070 HValue* context = environment()->LookupContext(); |
6011 HCallStub* result = | 6071 HCallStub* result = |
6012 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 6072 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
6013 result->set_transcendental_type(TranscendentalCache::COS); | 6073 result->set_transcendental_type(TranscendentalCache::COS); |
6014 Drop(1); | 6074 Drop(1); |
6015 ast_context()->ReturnInstruction(result, call->id()); | 6075 return ast_context()->ReturnInstruction(result, call->id()); |
6016 } | 6076 } |
6017 | 6077 |
6018 | 6078 |
6019 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { | 6079 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
6020 ASSERT_EQ(1, call->arguments()->length()); | 6080 ASSERT_EQ(1, call->arguments()->length()); |
6021 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 6081 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
6022 HValue* context = environment()->LookupContext(); | 6082 HValue* context = environment()->LookupContext(); |
6023 HCallStub* result = | 6083 HCallStub* result = |
6024 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 6084 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
6025 result->set_transcendental_type(TranscendentalCache::LOG); | 6085 result->set_transcendental_type(TranscendentalCache::LOG); |
6026 Drop(1); | 6086 Drop(1); |
6027 ast_context()->ReturnInstruction(result, call->id()); | 6087 return ast_context()->ReturnInstruction(result, call->id()); |
6028 } | 6088 } |
6029 | 6089 |
6030 | 6090 |
6031 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 6091 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
6032 return Bailout("inlined runtime function: MathSqrt"); | 6092 return Bailout("inlined runtime function: MathSqrt"); |
6033 } | 6093 } |
6034 | 6094 |
6035 | 6095 |
6036 // Check whether two RegExps are equivalent | 6096 // Check whether two RegExps are equivalent |
6037 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 6097 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
6038 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 6098 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
6039 } | 6099 } |
6040 | 6100 |
6041 | 6101 |
6042 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 6102 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
6043 ASSERT(call->arguments()->length() == 1); | 6103 ASSERT(call->arguments()->length() == 1); |
6044 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 6104 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
6045 HValue* value = Pop(); | 6105 HValue* value = Pop(); |
6046 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 6106 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
6047 ast_context()->ReturnInstruction(result, call->id()); | 6107 return ast_context()->ReturnInstruction(result, call->id()); |
6048 } | 6108 } |
6049 | 6109 |
6050 | 6110 |
6051 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 6111 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
6052 return Bailout("inlined runtime function: FastAsciiArrayJoin"); | 6112 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
6053 } | 6113 } |
6054 | 6114 |
6055 | 6115 |
6056 #undef CHECK_BAILOUT | 6116 #undef CHECK_BAILOUT |
6057 #undef CHECK_ALIVE | 6117 #undef CHECK_ALIVE |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6577 } | 6637 } |
6578 } | 6638 } |
6579 | 6639 |
6580 #ifdef DEBUG | 6640 #ifdef DEBUG |
6581 if (graph_ != NULL) graph_->Verify(); | 6641 if (graph_ != NULL) graph_->Verify(); |
6582 if (allocator_ != NULL) allocator_->Verify(); | 6642 if (allocator_ != NULL) allocator_->Verify(); |
6583 #endif | 6643 #endif |
6584 } | 6644 } |
6585 | 6645 |
6586 } } // namespace v8::internal | 6646 } } // namespace v8::internal |
OLD | NEW |