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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2066 // The value is tracked in the bailout environment, and communicated | 2057 // The value is tracked in the bailout environment, and communicated |
2067 // through the environment as the result of the expression. | 2058 // through the environment as the result of the expression. |
2068 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { | 2059 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { |
2069 owner()->Bailout("bad value context for arguments value"); | 2060 owner()->Bailout("bad value context for arguments value"); |
2070 } | 2061 } |
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, new HTest(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) { |
Kevin Millikin (Chromium)
2011/06/30 10:52:03
An alternative that I like better is to add a meth
fschneider
2011/06/30 13:13:36
Done.
| |
2081 owner()->AddInstruction(instr); | 2072 if (!instr->IsControlInstruction()) { |
2082 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | 2073 owner()->AddInstruction(instr); |
2074 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | |
2075 } else { | |
2076 ASSERT(!instr->HasSideEffects()); | |
2077 owner()->MaterializeBoolean(HControlInstruction::cast(instr), ast_id); | |
Kevin Millikin (Chromium)
2011/06/30 10:52:03
I wonder why it is necessary to materialize anythi
fschneider
2011/06/30 13:13:36
Done. Removed MaterializeBoolean.
| |
2078 } | |
2083 } | 2079 } |
2084 | 2080 |
2085 | 2081 |
2086 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { | 2082 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
2087 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 2083 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
2088 owner()->Bailout("bad value context for arguments object value"); | 2084 return owner()->Bailout("bad value context for arguments object value"); |
2089 } | 2085 } |
2090 owner()->AddInstruction(instr); | 2086 if (!instr->IsControlInstruction()) { |
2091 owner()->Push(instr); | 2087 owner()->AddInstruction(instr); |
2092 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | 2088 owner()->Push(instr); |
2089 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | |
2090 } else { | |
2091 ASSERT(!instr->HasSideEffects()); | |
2092 owner()->MaterializeBoolean(HControlInstruction::cast(instr), ast_id); | |
2093 } | |
2093 } | 2094 } |
2094 | 2095 |
2095 | 2096 |
2096 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { | 2097 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
2097 HGraphBuilder* builder = owner(); | 2098 if (!instr->IsControlInstruction()) { |
2098 builder->AddInstruction(instr); | 2099 HGraphBuilder* builder = owner(); |
2099 // We expect a simulate after every expression with side effects, though | 2100 builder->AddInstruction(instr); |
2100 // this one isn't actually needed (and wouldn't work if it were targeted). | 2101 // We expect a simulate after every expression with side effects, though |
2101 if (instr->HasSideEffects()) { | 2102 // this one isn't actually needed (and wouldn't work if it were targeted). |
2102 builder->Push(instr); | 2103 if (instr->HasSideEffects()) { |
2103 builder->AddSimulate(ast_id); | 2104 builder->Push(instr); |
2104 builder->Pop(); | 2105 builder->AddSimulate(ast_id); |
2106 builder->Pop(); | |
2107 } | |
2108 BuildBranch(instr, new HTest(instr)); | |
2109 } else { | |
2110 BuildBranch(NULL, HControlInstruction::cast(instr)); | |
2105 } | 2111 } |
2106 BuildBranch(instr); | |
2107 } | 2112 } |
2108 | 2113 |
2109 | 2114 |
2110 void TestContext::BuildBranch(HValue* value) { | 2115 void TestContext::BuildBranch(HValue* value, HControlInstruction* test) { |
Kevin Millikin (Chromium)
2011/06/30 10:52:03
This is trying to do too much. It's strange that
fschneider
2011/06/30 13:13:36
Done.
| |
2111 // We expect the graph to be in edge-split form: there is no edge that | 2116 // 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 | 2117 // 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 | 2118 // property by always adding an empty block on the outgoing edges of this |
2114 // branch. | 2119 // branch. |
2115 HGraphBuilder* builder = owner(); | 2120 HGraphBuilder* builder = owner(); |
2116 if (value->CheckFlag(HValue::kIsArguments)) { | 2121 ASSERT(value == NULL || !value->IsControlInstruction()); |
2122 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | |
2117 builder->Bailout("arguments object value in a test context"); | 2123 builder->Bailout("arguments object value in a test context"); |
2118 } | 2124 } |
2119 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2125 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2120 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2126 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2121 HTest* test = new(zone()) HTest(value, empty_true, empty_false); | 2127 test->SetSuccessorAt(0, empty_true); |
2128 test->SetSuccessorAt(1, empty_false); | |
2122 builder->current_block()->Finish(test); | 2129 builder->current_block()->Finish(test); |
2123 | 2130 |
2124 empty_true->Goto(if_true()); | 2131 empty_true->Goto(if_true()); |
2125 empty_false->Goto(if_false()); | 2132 empty_false->Goto(if_false()); |
2126 builder->set_current_block(NULL); | 2133 builder->set_current_block(NULL); |
2127 } | 2134 } |
2128 | 2135 |
2129 | 2136 |
2130 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2137 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
2131 #define CHECK_BAILOUT(call) \ | 2138 #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 | 2624 // Finish with deoptimize and add uses of enviroment values to |
2618 // account for invisible uses. | 2625 // account for invisible uses. |
2619 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 2626 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
2620 set_current_block(NULL); | 2627 set_current_block(NULL); |
2621 break; | 2628 break; |
2622 } | 2629 } |
2623 | 2630 |
2624 // Otherwise generate a compare and branch. | 2631 // Otherwise generate a compare and branch. |
2625 CHECK_ALIVE(VisitForValue(clause->label())); | 2632 CHECK_ALIVE(VisitForValue(clause->label())); |
2626 HValue* label_value = Pop(); | 2633 HValue* label_value = Pop(); |
2627 HCompare* compare = | 2634 HCompareIDAndBranch* compare = |
2628 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); | 2635 new(zone()) HCompareIDAndBranch(tag_value, |
2636 label_value, | |
2637 Token::EQ_STRICT); | |
2629 compare->SetInputRepresentation(Representation::Integer32()); | 2638 compare->SetInputRepresentation(Representation::Integer32()); |
2630 ASSERT(!compare->HasSideEffects()); | |
2631 AddInstruction(compare); | |
2632 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 2639 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
2633 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 2640 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
2634 HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); | 2641 compare->SetSuccessorAt(0, body_block); |
2635 current_block()->Finish(branch); | 2642 compare->SetSuccessorAt(1, next_test_block); |
2643 current_block()->Finish(compare); | |
2636 set_current_block(next_test_block); | 2644 set_current_block(next_test_block); |
2637 } | 2645 } |
2638 | 2646 |
2639 // Save the current block to use for the default or to join with the | 2647 // Save the current block to use for the default or to join with the |
2640 // exit. This block is NULL if we deoptimized. | 2648 // exit. This block is NULL if we deoptimized. |
2641 HBasicBlock* last_block = current_block(); | 2649 HBasicBlock* last_block = current_block(); |
2642 | 2650 |
2643 // 2. Loop over the clauses and the linked list of tests in lockstep, | 2651 // 2. Loop over the clauses and the linked list of tests in lockstep, |
2644 // translating the clause bodies. | 2652 // translating the clause bodies. |
2645 HBasicBlock* curr_test_block = first_test_block; | 2653 HBasicBlock* curr_test_block = first_test_block; |
(...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3948 elements->ClearFlag(HValue::kUseGVN); | 3956 elements->ClearFlag(HValue::kUseGVN); |
3949 HInstruction* length = | 3957 HInstruction* length = |
3950 AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3958 AddInstruction(new(zone()) HExternalArrayLength(elements)); |
3951 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3959 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3952 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 3960 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
3953 AddInstruction(external_elements); | 3961 AddInstruction(external_elements); |
3954 } | 3962 } |
3955 if (type_todo[elements_kind]) { | 3963 if (type_todo[elements_kind]) { |
3956 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 3964 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
3957 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 3965 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
3958 HCompareConstantEq* compare = new(zone()) HCompareConstantEq( | 3966 HCompareConstantEqAndBranch* compare = |
3959 elements_kind_instr, | 3967 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, |
3960 elements_kind, | 3968 elements_kind, |
3961 Token::EQ_STRICT); | 3969 Token::EQ_STRICT); |
3962 AddInstruction(compare); | 3970 compare->SetSuccessorAt(0, if_true); |
3963 HTest* branch = new(zone()) HTest(compare, if_true, if_false); | 3971 compare->SetSuccessorAt(1, if_false); |
3964 current_block()->Finish(branch); | 3972 current_block()->Finish(compare); |
3965 | 3973 |
3966 set_current_block(if_true); | 3974 set_current_block(if_true); |
3967 HInstruction* access; | 3975 HInstruction* access; |
3968 if (elements_kind == JSObject::FAST_ELEMENTS) { | 3976 if (elements_kind == JSObject::FAST_ELEMENTS) { |
3969 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 3977 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
3970 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 3978 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
3971 HInstruction* typecheck = | 3979 HHasInstanceTypeAndBranch* typecheck = |
3972 AddInstruction(new(zone()) HHasInstanceType(object, JS_ARRAY_TYPE)); | 3980 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
3973 HTest* test = new(zone()) HTest(typecheck, if_jsarray, if_fastobject); | 3981 typecheck->SetSuccessorAt(0, if_jsarray); |
3974 current_block()->Finish(test); | 3982 typecheck->SetSuccessorAt(1, if_fastobject); |
3983 current_block()->Finish(typecheck); | |
3975 | 3984 |
3976 set_current_block(if_jsarray); | 3985 set_current_block(if_jsarray); |
3977 HInstruction* length = new(zone()) HJSArrayLength(object); | 3986 HInstruction* length = new(zone()) HJSArrayLength(object); |
3978 AddInstruction(length); | 3987 AddInstruction(length); |
3979 length->ClearFlag(HValue::kUseGVN); | 3988 length->ClearFlag(HValue::kUseGVN); |
3980 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3989 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3981 elements = AddInstruction(new(zone()) HLoadElements(object)); | 3990 elements = AddInstruction(new(zone()) HLoadElements(object)); |
3982 elements->ClearFlag(HValue::kUseGVN); | 3991 elements->ClearFlag(HValue::kUseGVN); |
3983 if (is_store) { | 3992 if (is_store) { |
3984 access = AddInstruction( | 3993 access = AddInstruction( |
(...skipping 1502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5487 if (info.IsNumber()) return Representation::Double(); | 5496 if (info.IsNumber()) return Representation::Double(); |
5488 return Representation::Tagged(); | 5497 return Representation::Tagged(); |
5489 } | 5498 } |
5490 | 5499 |
5491 | 5500 |
5492 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr, | 5501 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr, |
5493 Expression* expr, | 5502 Expression* expr, |
5494 Handle<String> check) { | 5503 Handle<String> check) { |
5495 CHECK_ALIVE(VisitForTypeOf(expr)); | 5504 CHECK_ALIVE(VisitForTypeOf(expr)); |
5496 HValue* expr_value = Pop(); | 5505 HValue* expr_value = Pop(); |
5497 HInstruction* instr = new(zone()) HTypeofIs(expr_value, check); | 5506 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check); |
5498 instr->set_position(compare_expr->position()); | 5507 instr->set_position(compare_expr->position()); |
5499 ast_context()->ReturnInstruction(instr, compare_expr->id()); | 5508 ast_context()->ReturnInstruction(instr, compare_expr->id()); |
5500 } | 5509 } |
5501 | 5510 |
5502 | 5511 |
5503 void HGraphBuilder::HandleLiteralCompareUndefined( | 5512 void HGraphBuilder::HandleLiteralCompareUndefined( |
5504 CompareOperation* compare_expr, Expression* expr) { | 5513 CompareOperation* compare_expr, Expression* expr) { |
5505 CHECK_ALIVE(VisitForValue(expr)); | 5514 CHECK_ALIVE(VisitForValue(expr)); |
5506 HValue* lhs = Pop(); | 5515 HValue* lhs = Pop(); |
5507 HValue* rhs = graph()->GetConstantUndefined(); | 5516 HValue* rhs = graph()->GetConstantUndefined(); |
5508 HInstruction* instr = | 5517 HCompareObjectEqAndBranch* instr = |
5509 new(zone()) HCompareObjectEq(lhs, rhs); | 5518 new(zone()) HCompareObjectEqAndBranch(lhs, rhs); |
5510 instr->set_position(compare_expr->position()); | 5519 instr->set_position(compare_expr->position()); |
5511 ast_context()->ReturnInstruction(instr, compare_expr->id()); | 5520 ast_context()->ReturnInstruction(instr, compare_expr->id()); |
5512 } | 5521 } |
5513 | 5522 |
5514 | 5523 |
5515 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 5524 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
5516 ASSERT(!HasStackOverflow()); | 5525 ASSERT(!HasStackOverflow()); |
5517 ASSERT(current_block() != NULL); | 5526 ASSERT(current_block() != NULL); |
5518 ASSERT(current_block()->HasPredecessor()); | 5527 ASSERT(current_block()->HasPredecessor()); |
5519 if (IsClassOfTest(expr)) { | 5528 if (IsClassOfTest(expr)) { |
5520 CallRuntime* call = expr->left()->AsCallRuntime(); | 5529 CallRuntime* call = expr->left()->AsCallRuntime(); |
5530 ASSERT(call->arguments()->length() == 1); | |
5521 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5531 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5522 HValue* value = Pop(); | 5532 HValue* value = Pop(); |
5523 Literal* literal = expr->right()->AsLiteral(); | 5533 Literal* literal = expr->right()->AsLiteral(); |
5524 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 5534 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
5525 HInstruction* instr = new(zone()) HClassOfTest(value, rhs); | 5535 HClassOfTestAndBranch* instr = |
5536 new(zone()) HClassOfTestAndBranch(value, rhs); | |
5526 instr->set_position(expr->position()); | 5537 instr->set_position(expr->position()); |
5527 ast_context()->ReturnInstruction(instr, expr->id()); | 5538 ast_context()->ReturnInstruction(instr, expr->id()); |
5528 return; | 5539 return; |
5529 } | 5540 } |
5530 | 5541 |
5531 // Check for special cases that compare against literals. | 5542 // Check for special cases that compare against literals. |
5532 Expression *sub_expr; | 5543 Expression *sub_expr; |
5533 Handle<String> check; | 5544 Handle<String> check; |
5534 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 5545 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
5535 HandleLiteralCompareTypeof(expr, sub_expr, check); | 5546 HandleLiteralCompareTypeof(expr, sub_expr, check); |
(...skipping 13 matching lines...) Expand all Loading... | |
5549 type_info = TypeInfo::Unknown(); | 5560 type_info = TypeInfo::Unknown(); |
5550 } | 5561 } |
5551 | 5562 |
5552 CHECK_ALIVE(VisitForValue(expr->left())); | 5563 CHECK_ALIVE(VisitForValue(expr->left())); |
5553 CHECK_ALIVE(VisitForValue(expr->right())); | 5564 CHECK_ALIVE(VisitForValue(expr->right())); |
5554 | 5565 |
5555 HValue* right = Pop(); | 5566 HValue* right = Pop(); |
5556 HValue* left = Pop(); | 5567 HValue* left = Pop(); |
5557 Token::Value op = expr->op(); | 5568 Token::Value op = expr->op(); |
5558 | 5569 |
5559 HInstruction* instr = NULL; | |
5560 if (op == Token::INSTANCEOF) { | 5570 if (op == Token::INSTANCEOF) { |
5561 // Check to see if the rhs of the instanceof is a global function not | 5571 // 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 | 5572 // residing in new space. If it is we assume that the function will stay the |
5563 // same. | 5573 // same. |
5564 Handle<JSFunction> target = Handle<JSFunction>::null(); | 5574 Handle<JSFunction> target = Handle<JSFunction>::null(); |
5565 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); | 5575 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); |
5566 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); | 5576 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); |
5567 if (global_function && | 5577 if (global_function && |
5568 info()->has_global_object() && | 5578 info()->has_global_object() && |
5569 !info()->global_object()->IsAccessCheckNeeded()) { | 5579 !info()->global_object()->IsAccessCheckNeeded()) { |
(...skipping 10 matching lines...) Expand all Loading... | |
5580 if (!isolate()->heap()->InNewSpace(*candidate)) { | 5590 if (!isolate()->heap()->InNewSpace(*candidate)) { |
5581 target = candidate; | 5591 target = candidate; |
5582 } | 5592 } |
5583 } | 5593 } |
5584 } | 5594 } |
5585 | 5595 |
5586 // If the target is not null we have found a known global function that is | 5596 // If the target is not null we have found a known global function that is |
5587 // assumed to stay the same for this instanceof. | 5597 // assumed to stay the same for this instanceof. |
5588 if (target.is_null()) { | 5598 if (target.is_null()) { |
5589 HValue* context = environment()->LookupContext(); | 5599 HValue* context = environment()->LookupContext(); |
5590 instr = new(zone()) HInstanceOf(context, left, right); | 5600 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
5601 result->set_position(expr->position()); | |
5602 ast_context()->ReturnInstruction(result, expr->id()); | |
Kevin Millikin (Chromium)
2011/06/30 10:52:03
Maybe we should take to writing
return ast_contex
fschneider
2011/06/30 13:13:36
Done.
| |
5603 return; | |
5591 } else { | 5604 } else { |
5592 AddInstruction(new(zone()) HCheckFunction(right, target)); | 5605 AddInstruction(new(zone()) HCheckFunction(right, target)); |
5593 instr = new(zone()) HInstanceOfKnownGlobal(left, target); | 5606 HInstanceOfKnownGlobal* result = |
5607 new(zone()) HInstanceOfKnownGlobal(left, target); | |
5608 result->set_position(expr->position()); | |
5609 ast_context()->ReturnInstruction(result, expr->id()); | |
5610 return; | |
5594 } | 5611 } |
5595 } else if (op == Token::IN) { | 5612 } else if (op == Token::IN) { |
5596 instr = new(zone()) HIn(left, right); | 5613 HIn* result = new(zone()) HIn(left, right); |
5614 result->set_position(expr->position()); | |
5615 ast_context()->ReturnInstruction(result, expr->id()); | |
5616 return; | |
5597 } else if (type_info.IsNonPrimitive()) { | 5617 } else if (type_info.IsNonPrimitive()) { |
5598 switch (op) { | 5618 switch (op) { |
5599 case Token::EQ: | 5619 case Token::EQ: |
5600 case Token::EQ_STRICT: { | 5620 case Token::EQ_STRICT: { |
5601 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5621 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5602 AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); | 5622 AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); |
5603 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5623 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5604 AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); | 5624 AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); |
5605 instr = new(zone()) HCompareObjectEq(left, right); | 5625 HCompareObjectEqAndBranch* result = |
5606 break; | 5626 new(zone()) HCompareObjectEqAndBranch(left, right); |
5627 result->set_position(expr->position()); | |
5628 ast_context()->ReturnInstruction(result, expr->id()); | |
5629 return; | |
5607 } | 5630 } |
5608 default: | 5631 default: |
5609 return Bailout("Unsupported non-primitive compare"); | 5632 return Bailout("Unsupported non-primitive compare"); |
5610 break; | |
5611 } | 5633 } |
5612 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && | 5634 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && |
5613 (op == Token::EQ || op == Token::EQ_STRICT)) { | 5635 (op == Token::EQ || op == Token::EQ_STRICT)) { |
5614 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5636 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5615 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); | 5637 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); |
5616 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5638 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5617 AddInstruction(HCheckInstanceType::NewIsSymbol(right)); | 5639 AddInstruction(HCheckInstanceType::NewIsSymbol(right)); |
5618 instr = new(zone()) HCompareObjectEq(left, right); | 5640 HCompareObjectEqAndBranch* result = |
5641 new(zone()) HCompareObjectEqAndBranch(left, right); | |
5642 result->set_position(expr->position()); | |
5643 ast_context()->ReturnInstruction(result, expr->id()); | |
5644 return; | |
5619 } else { | 5645 } else { |
5620 HCompare* compare = new(zone()) HCompare(left, right, op); | |
5621 Representation r = ToRepresentation(type_info); | 5646 Representation r = ToRepresentation(type_info); |
5622 compare->SetInputRepresentation(r); | 5647 if (r.IsTagged()) { |
5623 instr = compare; | 5648 HCompareGeneric* result = new(zone()) HCompareGeneric(left, right, op); |
5649 result->set_position(expr->position()); | |
5650 ast_context()->ReturnInstruction(result, expr->id()); | |
5651 return; | |
5652 } else { | |
5653 HCompareIDAndBranch* result = | |
5654 new(zone()) HCompareIDAndBranch(left, right, op); | |
5655 result->set_position(expr->position()); | |
5656 result->SetInputRepresentation(r); | |
5657 ast_context()->ReturnInstruction(result, expr->id()); | |
5658 return; | |
5659 } | |
5624 } | 5660 } |
5625 instr->set_position(expr->position()); | 5661 } |
5626 ast_context()->ReturnInstruction(instr, expr->id()); | 5662 |
5663 | |
5664 void HGraphBuilder::MaterializeBoolean(HControlInstruction* instr, | |
Kevin Millikin (Chromium)
2011/06/30 10:52:03
I find this function weird. It should never be ca
fschneider
2011/06/30 13:13:36
Removed.
| |
5665 int join_id) { | |
5666 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); | |
5667 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); | |
5668 instr->SetSuccessorAt(0, materialize_true); | |
5669 instr->SetSuccessorAt(1, materialize_false); | |
5670 current_block()->Finish(instr); | |
5671 set_current_block(materialize_false); | |
5672 Push(graph()->GetConstantFalse()); | |
5673 set_current_block(materialize_true); | |
5674 Push(graph()->GetConstantTrue()); | |
5675 HBasicBlock* join = | |
5676 CreateJoin(materialize_false, materialize_true, join_id); | |
5677 set_current_block(join); | |
5678 ast_context()->ReturnValue(Pop()); | |
5627 } | 5679 } |
5628 | 5680 |
5629 | 5681 |
5630 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { | 5682 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
5631 ASSERT(!HasStackOverflow()); | 5683 ASSERT(!HasStackOverflow()); |
5632 ASSERT(current_block() != NULL); | 5684 ASSERT(current_block() != NULL); |
5633 ASSERT(current_block()->HasPredecessor()); | 5685 ASSERT(current_block()->HasPredecessor()); |
5634 CHECK_ALIVE(VisitForValue(expr->expression())); | 5686 CHECK_ALIVE(VisitForValue(expr->expression())); |
5635 | |
5636 HValue* value = Pop(); | 5687 HValue* value = Pop(); |
5637 HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); | 5688 HIsNullAndBranch* instr = |
5638 ast_context()->ReturnInstruction(compare, expr->id()); | 5689 new(zone()) HIsNullAndBranch(value, expr->is_strict()); |
5690 ast_context()->ReturnInstruction(instr, expr->id()); | |
5639 } | 5691 } |
5640 | 5692 |
5641 | 5693 |
5642 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 5694 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
5643 ASSERT(!HasStackOverflow()); | 5695 ASSERT(!HasStackOverflow()); |
5644 ASSERT(current_block() != NULL); | 5696 ASSERT(current_block() != NULL); |
5645 ASSERT(current_block()->HasPredecessor()); | 5697 ASSERT(current_block()->HasPredecessor()); |
5646 HThisFunction* self = new(zone()) HThisFunction; | 5698 HThisFunction* self = new(zone()) HThisFunction; |
5647 return ast_context()->ReturnInstruction(self, expr->id()); | 5699 return ast_context()->ReturnInstruction(self, expr->id()); |
5648 } | 5700 } |
(...skipping 12 matching lines...) Expand all Loading... | |
5661 } | 5713 } |
5662 } | 5714 } |
5663 | 5715 |
5664 | 5716 |
5665 // Generators for inline runtime functions. | 5717 // Generators for inline runtime functions. |
5666 // Support for types. | 5718 // Support for types. |
5667 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 5719 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
5668 ASSERT(call->arguments()->length() == 1); | 5720 ASSERT(call->arguments()->length() == 1); |
5669 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5721 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5670 HValue* value = Pop(); | 5722 HValue* value = Pop(); |
5671 HIsSmi* result = new(zone()) HIsSmi(value); | 5723 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
5672 ast_context()->ReturnInstruction(result, call->id()); | 5724 ast_context()->ReturnInstruction(result, call->id()); |
5673 } | 5725 } |
5674 | 5726 |
5675 | 5727 |
5676 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 5728 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
5677 ASSERT(call->arguments()->length() == 1); | 5729 ASSERT(call->arguments()->length() == 1); |
5678 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5730 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5679 HValue* value = Pop(); | 5731 HValue* value = Pop(); |
5680 HHasInstanceType* result = | 5732 HHasInstanceTypeAndBranch* result = |
5681 new(zone()) HHasInstanceType(value, | 5733 new(zone()) HHasInstanceTypeAndBranch(value, |
5682 FIRST_SPEC_OBJECT_TYPE, | 5734 FIRST_SPEC_OBJECT_TYPE, |
5683 LAST_SPEC_OBJECT_TYPE); | 5735 LAST_SPEC_OBJECT_TYPE); |
5684 ast_context()->ReturnInstruction(result, call->id()); | 5736 ast_context()->ReturnInstruction(result, call->id()); |
5685 } | 5737 } |
5686 | 5738 |
5687 | 5739 |
5688 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 5740 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
5689 ASSERT(call->arguments()->length() == 1); | 5741 ASSERT(call->arguments()->length() == 1); |
5690 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5742 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5691 HValue* value = Pop(); | 5743 HValue* value = Pop(); |
5692 HHasInstanceType* result = | 5744 HHasInstanceTypeAndBranch* result = |
5693 new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); | 5745 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); |
5694 ast_context()->ReturnInstruction(result, call->id()); | 5746 ast_context()->ReturnInstruction(result, call->id()); |
5695 } | 5747 } |
5696 | 5748 |
5697 | 5749 |
5698 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 5750 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
5699 ASSERT(call->arguments()->length() == 1); | 5751 ASSERT(call->arguments()->length() == 1); |
5700 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5752 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5701 HValue* value = Pop(); | 5753 HValue* value = Pop(); |
5702 HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); | 5754 HHasCachedArrayIndexAndBranch* result = |
5755 new(zone()) HHasCachedArrayIndexAndBranch(value); | |
5703 ast_context()->ReturnInstruction(result, call->id()); | 5756 ast_context()->ReturnInstruction(result, call->id()); |
5704 } | 5757 } |
5705 | 5758 |
5706 | 5759 |
5707 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { | 5760 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
5708 ASSERT(call->arguments()->length() == 1); | 5761 ASSERT(call->arguments()->length() == 1); |
5709 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5762 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5710 HValue* value = Pop(); | 5763 HValue* value = Pop(); |
5711 HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); | 5764 HHasInstanceTypeAndBranch* result = |
5765 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); | |
5712 ast_context()->ReturnInstruction(result, call->id()); | 5766 ast_context()->ReturnInstruction(result, call->id()); |
5713 } | 5767 } |
5714 | 5768 |
5715 | 5769 |
5716 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 5770 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
5717 ASSERT(call->arguments()->length() == 1); | 5771 ASSERT(call->arguments()->length() == 1); |
5718 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5772 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5719 HValue* value = Pop(); | 5773 HValue* value = Pop(); |
5720 HHasInstanceType* result = | 5774 HHasInstanceTypeAndBranch* result = |
5721 new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); | 5775 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); |
5722 ast_context()->ReturnInstruction(result, call->id()); | 5776 ast_context()->ReturnInstruction(result, call->id()); |
5723 } | 5777 } |
5724 | 5778 |
5725 | 5779 |
5726 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { | 5780 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
5727 ASSERT(call->arguments()->length() == 1); | 5781 ASSERT(call->arguments()->length() == 1); |
5728 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5782 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5729 HValue* value = Pop(); | 5783 HValue* value = Pop(); |
5730 HIsObject* test = new(zone()) HIsObject(value); | 5784 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
5731 ast_context()->ReturnInstruction(test, call->id()); | 5785 ast_context()->ReturnInstruction(result, call->id()); |
5732 } | 5786 } |
5733 | 5787 |
5734 | 5788 |
5735 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 5789 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
5736 return Bailout("inlined runtime function: IsNonNegativeSmi"); | 5790 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
5737 } | 5791 } |
5738 | 5792 |
5739 | 5793 |
5740 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 5794 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
5741 ASSERT(call->arguments()->length() == 1); | 5795 ASSERT(call->arguments()->length() == 1); |
5742 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5796 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5743 HValue* value = Pop(); | 5797 HValue* value = Pop(); |
5744 ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value), | 5798 HIsUndetectableAndBranch* result = |
5745 call->id()); | 5799 new(zone()) HIsUndetectableAndBranch(value); |
5800 ast_context()->ReturnInstruction(result, call->id()); | |
5746 } | 5801 } |
5747 | 5802 |
5748 | 5803 |
5749 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 5804 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
5750 CallRuntime* call) { | 5805 CallRuntime* call) { |
5751 return Bailout( | 5806 return Bailout( |
5752 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 5807 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
5753 } | 5808 } |
5754 | 5809 |
5755 | 5810 |
5756 // Support for construct call checks. | 5811 // Support for construct call checks. |
5757 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 5812 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
5758 ASSERT(call->arguments()->length() == 0); | 5813 ASSERT(call->arguments()->length() == 0); |
5759 if (function_state()->outer() != NULL) { | 5814 if (function_state()->outer() != NULL) { |
5760 // We are generating graph for inlined function. Currently | 5815 // We are generating graph for inlined function. Currently |
5761 // constructor inlining is not supported and we can just return | 5816 // constructor inlining is not supported and we can just return |
5762 // false from %_IsConstructCall(). | 5817 // false from %_IsConstructCall(). |
5763 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 5818 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
5764 } else { | 5819 } else { |
5765 ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); | 5820 ast_context()->ReturnInstruction(new(zone()) HIsConstructCallAndBranch, |
5821 call->id()); | |
5766 } | 5822 } |
5767 } | 5823 } |
5768 | 5824 |
5769 | 5825 |
5770 // Support for arguments.length and arguments[?]. | 5826 // Support for arguments.length and arguments[?]. |
5771 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 5827 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
5772 // Our implementation of arguments (based on this stack frame or an | 5828 // Our implementation of arguments (based on this stack frame or an |
5773 // adapter below it) does not work for inlined functions. This runtime | 5829 // adapter below it) does not work for inlined functions. This runtime |
5774 // function is blacklisted by AstNode::IsInlineable. | 5830 // function is blacklisted by AstNode::IsInlineable. |
5775 ASSERT(function_state()->outer() == NULL); | 5831 ASSERT(function_state()->outer() == NULL); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5854 } | 5910 } |
5855 | 5911 |
5856 | 5912 |
5857 // Fast support for object equality testing. | 5913 // Fast support for object equality testing. |
5858 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 5914 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
5859 ASSERT(call->arguments()->length() == 2); | 5915 ASSERT(call->arguments()->length() == 2); |
5860 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5916 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5861 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 5917 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5862 HValue* right = Pop(); | 5918 HValue* right = Pop(); |
5863 HValue* left = Pop(); | 5919 HValue* left = Pop(); |
5864 HCompareObjectEq* result = new(zone()) HCompareObjectEq(left, right); | 5920 HCompareObjectEqAndBranch* result = |
5921 new(zone()) HCompareObjectEqAndBranch(left, right); | |
5865 ast_context()->ReturnInstruction(result, call->id()); | 5922 ast_context()->ReturnInstruction(result, call->id()); |
5866 } | 5923 } |
5867 | 5924 |
5868 | 5925 |
5869 void HGraphBuilder::GenerateLog(CallRuntime* call) { | 5926 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
5870 // %_Log is ignored in optimized code. | 5927 // %_Log is ignored in optimized code. |
5871 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 5928 ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
5872 } | 5929 } |
5873 | 5930 |
5874 | 5931 |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6577 } | 6634 } |
6578 } | 6635 } |
6579 | 6636 |
6580 #ifdef DEBUG | 6637 #ifdef DEBUG |
6581 if (graph_ != NULL) graph_->Verify(); | 6638 if (graph_ != NULL) graph_->Verify(); |
6582 if (allocator_ != NULL) allocator_->Verify(); | 6639 if (allocator_ != NULL) allocator_->Verify(); |
6583 #endif | 6640 #endif |
6584 } | 6641 } |
6585 | 6642 |
6586 } } // namespace v8::internal | 6643 } } // namespace v8::internal |
OLD | NEW |