OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 break; | 687 break; |
688 case IrOpcode::kObjectIsString: | 688 case IrOpcode::kObjectIsString: |
689 state = LowerObjectIsString(node, *effect, *control); | 689 state = LowerObjectIsString(node, *effect, *control); |
690 break; | 690 break; |
691 case IrOpcode::kObjectIsUndetectable: | 691 case IrOpcode::kObjectIsUndetectable: |
692 state = LowerObjectIsUndetectable(node, *effect, *control); | 692 state = LowerObjectIsUndetectable(node, *effect, *control); |
693 break; | 693 break; |
694 case IrOpcode::kStringFromCharCode: | 694 case IrOpcode::kStringFromCharCode: |
695 state = LowerStringFromCharCode(node, *effect, *control); | 695 state = LowerStringFromCharCode(node, *effect, *control); |
696 break; | 696 break; |
| 697 case IrOpcode::kStringCharCodeAt: |
| 698 state = LowerStringCharCodeAt(node, *effect, *control); |
| 699 break; |
697 case IrOpcode::kCheckFloat64Hole: | 700 case IrOpcode::kCheckFloat64Hole: |
698 state = LowerCheckFloat64Hole(node, frame_state, *effect, *control); | 701 state = LowerCheckFloat64Hole(node, frame_state, *effect, *control); |
699 break; | 702 break; |
700 case IrOpcode::kCheckTaggedHole: | 703 case IrOpcode::kCheckTaggedHole: |
701 state = LowerCheckTaggedHole(node, frame_state, *effect, *control); | 704 state = LowerCheckTaggedHole(node, frame_state, *effect, *control); |
702 break; | 705 break; |
703 case IrOpcode::kPlainPrimitiveToNumber: | 706 case IrOpcode::kPlainPrimitiveToNumber: |
704 state = LowerPlainPrimitiveToNumber(node, *effect, *control); | 707 state = LowerPlainPrimitiveToNumber(node, *effect, *control); |
705 break; | 708 break; |
706 case IrOpcode::kPlainPrimitiveToWord32: | 709 case IrOpcode::kPlainPrimitiveToWord32: |
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 | 1808 |
1806 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 1809 control = graph()->NewNode(common()->Merge(2), if_true, if_false); |
1807 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | 1810 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); |
1808 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, | 1811 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, |
1809 vfalse, control); | 1812 vfalse, control); |
1810 | 1813 |
1811 return ValueEffectControl(value, effect, control); | 1814 return ValueEffectControl(value, effect, control); |
1812 } | 1815 } |
1813 | 1816 |
1814 EffectControlLinearizer::ValueEffectControl | 1817 EffectControlLinearizer::ValueEffectControl |
| 1818 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect, |
| 1819 Node* control) { |
| 1820 Node* subject = node->InputAt(0); |
| 1821 Node* index = node->InputAt(1); |
| 1822 |
| 1823 // We may need to loop several times for ConsString/SlicedString {subject}s. |
| 1824 Node* loop = |
| 1825 graph()->NewNode(common()->Loop(4), control, control, control, control); |
| 1826 Node* lsubject = |
| 1827 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 4), |
| 1828 subject, subject, subject, subject, loop); |
| 1829 Node* lindex = |
| 1830 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 4), index, |
| 1831 index, index, index, loop); |
| 1832 Node* leffect = graph()->NewNode(common()->EffectPhi(4), effect, effect, |
| 1833 effect, effect, loop); |
| 1834 |
| 1835 control = loop; |
| 1836 effect = leffect; |
| 1837 |
| 1838 // Determine the instance type of {lsubject}. |
| 1839 Node* lsubject_map = effect = |
| 1840 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 1841 lsubject, effect, control); |
| 1842 Node* lsubject_instance_type = effect = graph()->NewNode( |
| 1843 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 1844 lsubject_map, effect, control); |
| 1845 |
| 1846 // Check if {lsubject} is a SeqString. |
| 1847 Node* check0 = graph()->NewNode( |
| 1848 machine()->Word32Equal(), |
| 1849 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 1850 jsgraph()->Int32Constant(kStringRepresentationMask)), |
| 1851 jsgraph()->Int32Constant(kSeqStringTag)); |
| 1852 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); |
| 1853 |
| 1854 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1855 Node* etrue0 = effect; |
| 1856 Node* vtrue0; |
| 1857 { |
| 1858 // Check if the {lsubject} is a TwoByteSeqString or a OneByteSeqString. |
| 1859 Node* check1 = graph()->NewNode( |
| 1860 machine()->Word32Equal(), |
| 1861 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 1862 jsgraph()->Int32Constant(kStringEncodingMask)), |
| 1863 jsgraph()->Int32Constant(kTwoByteStringTag)); |
| 1864 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); |
| 1865 |
| 1866 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1867 Node* etrue1 = etrue0; |
| 1868 Node* vtrue1 = etrue1 = |
| 1869 graph()->NewNode(simplified()->LoadElement( |
| 1870 AccessBuilder::ForSeqTwoByteStringCharacter()), |
| 1871 lsubject, lindex, etrue1, if_true1); |
| 1872 |
| 1873 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1874 Node* efalse1 = etrue0; |
| 1875 Node* vfalse1 = efalse1 = |
| 1876 graph()->NewNode(simplified()->LoadElement( |
| 1877 AccessBuilder::ForSeqOneByteStringCharacter()), |
| 1878 lsubject, lindex, efalse1, if_false1); |
| 1879 |
| 1880 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1881 etrue0 = |
| 1882 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); |
| 1883 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 1884 vtrue1, vfalse1, if_true0); |
| 1885 } |
| 1886 |
| 1887 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 1888 Node* efalse0 = effect; |
| 1889 Node* vfalse0; |
| 1890 { |
| 1891 // Check if the {lsubject} is a ConsString. |
| 1892 Node* check1 = graph()->NewNode( |
| 1893 machine()->Word32Equal(), |
| 1894 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 1895 jsgraph()->Int32Constant(kStringRepresentationMask)), |
| 1896 jsgraph()->Int32Constant(kConsStringTag)); |
| 1897 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); |
| 1898 |
| 1899 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1900 Node* etrue1 = efalse0; |
| 1901 { |
| 1902 // Load the right hand side of the {lsubject} ConsString. |
| 1903 Node* lsubject_second = etrue1 = graph()->NewNode( |
| 1904 simplified()->LoadField(AccessBuilder::ForConsStringSecond()), |
| 1905 lsubject, etrue1, if_true1); |
| 1906 |
| 1907 // Check whether the right hand side is the empty string (i.e. if |
| 1908 // this is really a flat string in a cons string). If that is not |
| 1909 // the case we flatten the string first. |
| 1910 Node* check2 = graph()->NewNode(machine()->WordEqual(), lsubject_second, |
| 1911 jsgraph()->EmptyStringConstant()); |
| 1912 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 1913 check2, if_true1); |
| 1914 |
| 1915 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 1916 Node* etrue2 = etrue1; |
| 1917 Node* vtrue2 = etrue2 = graph()->NewNode( |
| 1918 simplified()->LoadField(AccessBuilder::ForConsStringFirst()), |
| 1919 lsubject, etrue2, if_true2); |
| 1920 |
| 1921 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 1922 Node* efalse2 = etrue1; |
| 1923 Node* vfalse2; |
| 1924 { |
| 1925 // Flatten the {lsubject} ConsString first. |
| 1926 Operator::Properties properties = |
| 1927 Operator::kNoDeopt | Operator::kNoThrow; |
| 1928 Runtime::FunctionId id = Runtime::kFlattenString; |
| 1929 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( |
| 1930 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); |
| 1931 vfalse2 = efalse2 = graph()->NewNode( |
| 1932 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, |
| 1933 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), |
| 1934 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(), |
| 1935 efalse2, if_false2); |
| 1936 } |
| 1937 |
| 1938 // Retry the {loop} with the new subject. |
| 1939 loop->ReplaceInput(1, if_true2); |
| 1940 lindex->ReplaceInput(1, lindex); |
| 1941 leffect->ReplaceInput(1, etrue2); |
| 1942 lsubject->ReplaceInput(1, vtrue2); |
| 1943 loop->ReplaceInput(2, if_false2); |
| 1944 lindex->ReplaceInput(2, lindex); |
| 1945 leffect->ReplaceInput(2, efalse2); |
| 1946 lsubject->ReplaceInput(2, vfalse2); |
| 1947 } |
| 1948 |
| 1949 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1950 Node* efalse1 = efalse0; |
| 1951 Node* vfalse1; |
| 1952 { |
| 1953 // Check if the {lsubject} is an ExternalString. |
| 1954 Node* check2 = graph()->NewNode( |
| 1955 machine()->Word32Equal(), |
| 1956 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 1957 jsgraph()->Int32Constant(kStringRepresentationMask)), |
| 1958 jsgraph()->Int32Constant(kExternalStringTag)); |
| 1959 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 1960 check2, if_false1); |
| 1961 |
| 1962 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 1963 Node* etrue2 = efalse1; |
| 1964 Node* vtrue2; |
| 1965 { |
| 1966 // Check if the {lsubject} is a short external string. |
| 1967 Node* check3 = graph()->NewNode( |
| 1968 machine()->Word32Equal(), |
| 1969 graph()->NewNode( |
| 1970 machine()->Word32And(), lsubject_instance_type, |
| 1971 jsgraph()->Int32Constant(kShortExternalStringMask)), |
| 1972 jsgraph()->Int32Constant(0)); |
| 1973 Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 1974 check3, if_true2); |
| 1975 |
| 1976 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3); |
| 1977 Node* etrue3 = etrue2; |
| 1978 Node* vtrue3; |
| 1979 { |
| 1980 // Load the actual resource data from the {lsubject}. |
| 1981 Node* lsubject_resource_data = etrue3 = graph()->NewNode( |
| 1982 simplified()->LoadField( |
| 1983 AccessBuilder::ForExternalStringResourceData()), |
| 1984 lsubject, etrue3, if_true3); |
| 1985 |
| 1986 // Check if the {lsubject} is a TwoByteExternalString or a |
| 1987 // OneByteExternalString. |
| 1988 Node* check4 = graph()->NewNode( |
| 1989 machine()->Word32Equal(), |
| 1990 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 1991 jsgraph()->Int32Constant(kStringEncodingMask)), |
| 1992 jsgraph()->Int32Constant(kTwoByteStringTag)); |
| 1993 Node* branch4 = |
| 1994 graph()->NewNode(common()->Branch(), check4, if_true3); |
| 1995 |
| 1996 Node* if_true4 = graph()->NewNode(common()->IfTrue(), branch4); |
| 1997 Node* etrue4 = etrue3; |
| 1998 Node* vtrue4 = etrue4 = graph()->NewNode( |
| 1999 simplified()->LoadElement( |
| 2000 AccessBuilder::ForExternalTwoByteStringCharacter()), |
| 2001 lsubject_resource_data, lindex, etrue4, if_true4); |
| 2002 |
| 2003 Node* if_false4 = graph()->NewNode(common()->IfFalse(), branch4); |
| 2004 Node* efalse4 = etrue3; |
| 2005 Node* vfalse4 = efalse4 = graph()->NewNode( |
| 2006 simplified()->LoadElement( |
| 2007 AccessBuilder::ForExternalOneByteStringCharacter()), |
| 2008 lsubject_resource_data, lindex, efalse4, if_false4); |
| 2009 |
| 2010 if_true3 = graph()->NewNode(common()->Merge(2), if_true4, if_false4); |
| 2011 etrue3 = graph()->NewNode(common()->EffectPhi(2), etrue4, efalse4, |
| 2012 if_true3); |
| 2013 vtrue3 = |
| 2014 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 2015 vtrue4, vfalse4, if_true3); |
| 2016 } |
| 2017 |
| 2018 Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3); |
| 2019 Node* efalse3 = etrue2; |
| 2020 Node* vfalse3; |
| 2021 { |
| 2022 // The {lsubject} might be compressed, call the runtime. |
| 2023 Operator::Properties properties = |
| 2024 Operator::kNoDeopt | Operator::kNoThrow; |
| 2025 Runtime::FunctionId id = Runtime::kExternalStringGetChar; |
| 2026 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( |
| 2027 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); |
| 2028 vfalse3 = efalse3 = graph()->NewNode( |
| 2029 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, |
| 2030 ChangeInt32ToSmi(lindex), |
| 2031 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), |
| 2032 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), |
| 2033 efalse3, if_false3); |
| 2034 vfalse3 = ChangeSmiToInt32(vfalse3); |
| 2035 } |
| 2036 |
| 2037 if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3); |
| 2038 etrue2 = |
| 2039 graph()->NewNode(common()->EffectPhi(2), etrue3, efalse3, if_true2); |
| 2040 vtrue2 = |
| 2041 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 2042 vtrue3, vfalse3, if_true2); |
| 2043 } |
| 2044 |
| 2045 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 2046 Node* efalse2 = efalse1; |
| 2047 { |
| 2048 // The {lsubject} is a SlicedString, continue with its parent. |
| 2049 Node* lsubject_parent = efalse2 = graph()->NewNode( |
| 2050 simplified()->LoadField(AccessBuilder::ForSlicedStringParent()), |
| 2051 lsubject, efalse2, if_false2); |
| 2052 Node* lsubject_offset = efalse2 = graph()->NewNode( |
| 2053 simplified()->LoadField(AccessBuilder::ForSlicedStringOffset()), |
| 2054 lsubject, efalse2, if_false2); |
| 2055 Node* lsubject_index = graph()->NewNode( |
| 2056 machine()->Int32Add(), lindex, ChangeSmiToInt32(lsubject_offset)); |
| 2057 |
| 2058 // Retry the {loop} with the parent subject. |
| 2059 loop->ReplaceInput(3, if_false2); |
| 2060 leffect->ReplaceInput(3, efalse2); |
| 2061 lindex->ReplaceInput(3, lsubject_index); |
| 2062 lsubject->ReplaceInput(3, lsubject_parent); |
| 2063 } |
| 2064 |
| 2065 if_false1 = if_true2; |
| 2066 efalse1 = etrue2; |
| 2067 vfalse1 = vtrue2; |
| 2068 } |
| 2069 |
| 2070 if_false0 = if_false1; |
| 2071 efalse0 = efalse1; |
| 2072 vfalse0 = vfalse1; |
| 2073 } |
| 2074 |
| 2075 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 2076 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 2077 Node* value = |
| 2078 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0, |
| 2079 vfalse0, control); |
| 2080 |
| 2081 return ValueEffectControl(value, effect, control); |
| 2082 } |
| 2083 |
| 2084 EffectControlLinearizer::ValueEffectControl |
1815 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, | 2085 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, |
1816 Node* control) { | 2086 Node* control) { |
1817 Node* value = node->InputAt(0); | 2087 Node* value = node->InputAt(0); |
1818 | 2088 |
1819 // Compute the character code. | 2089 // Compute the character code. |
1820 Node* code = | 2090 Node* code = |
1821 graph()->NewNode(machine()->Word32And(), value, | 2091 graph()->NewNode(machine()->Word32And(), value, |
1822 jsgraph()->Int32Constant(String::kMaxUtf16CodeUnit)); | 2092 jsgraph()->Int32Constant(String::kMaxUtf16CodeUnit)); |
1823 | 2093 |
1824 // Check if the {code} is a one-byte char code. | 2094 // Check if the {code} is a one-byte char code. |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2228 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2498 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
2229 Operator::kNoThrow); | 2499 Operator::kNoThrow); |
2230 to_number_operator_.set(common()->Call(desc)); | 2500 to_number_operator_.set(common()->Call(desc)); |
2231 } | 2501 } |
2232 return to_number_operator_.get(); | 2502 return to_number_operator_.get(); |
2233 } | 2503 } |
2234 | 2504 |
2235 } // namespace compiler | 2505 } // namespace compiler |
2236 } // namespace internal | 2506 } // namespace internal |
2237 } // namespace v8 | 2507 } // namespace v8 |
OLD | NEW |