Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(431)

Side by Side Diff: src/compiler/effect-control-linearizer.cc

Issue 2180373005: [turbofan] Add support for String.prototype.charCodeAt/charAt. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/effect-control-linearizer.h ('k') | src/compiler/js-builtin-reducer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/effect-control-linearizer.h ('k') | src/compiler/js-builtin-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698