Chromium Code Reviews| 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 |