OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/compiler/access-builder.h" | 6 #include "src/compiler/access-builder.h" |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 graph()->NewNode(common()->Merge(2), check_true, check_false); | 1120 graph()->NewNode(common()->Merge(2), check_true, check_false); |
1121 Node* new_effect = | 1121 Node* new_effect = |
1122 graph()->NewNode(common()->EffectPhi(2), fast, slow, new_control); | 1122 graph()->NewNode(common()->EffectPhi(2), fast, slow, new_control); |
1123 Node* new_value = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), fast, | 1123 Node* new_value = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), fast, |
1124 slow, new_control); | 1124 slow, new_control); |
1125 ReplaceWithValue(node, new_value, new_effect, new_control); | 1125 ReplaceWithValue(node, new_value, new_effect, new_control); |
1126 return Changed(new_value); | 1126 return Changed(new_value); |
1127 } | 1127 } |
1128 | 1128 |
1129 | 1129 |
| 1130 namespace { |
| 1131 |
| 1132 // Retrieves the frame state holding actual argument values. |
| 1133 Node* GetArgumentsFrameState(Node* frame_state) { |
| 1134 Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput); |
| 1135 FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state); |
| 1136 return outer_state_info.type() == FrameStateType::kArgumentsAdaptor |
| 1137 ? outer_state |
| 1138 : frame_state; |
| 1139 } |
| 1140 |
| 1141 } // namespace |
| 1142 |
| 1143 |
1130 Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) { | 1144 Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) { |
1131 DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode()); | 1145 DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode()); |
1132 CreateArgumentsParameters const& p = CreateArgumentsParametersOf(node->op()); | 1146 CreateArgumentsParameters const& p = CreateArgumentsParametersOf(node->op()); |
1133 Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0); | 1147 Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0); |
1134 Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput); | 1148 Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput); |
1135 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | 1149 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); |
1136 | 1150 |
1137 // Use the ArgumentsAccessStub for materializing both mapped and unmapped | 1151 // Use the ArgumentsAccessStub for materializing both mapped and unmapped |
1138 // arguments object, but only for non-inlined (i.e. outermost) frames. | 1152 // arguments object, but only for non-inlined (i.e. outermost) frames. |
1139 if (p.type() != CreateArgumentsParameters::kRestArray && | 1153 if (p.type() != CreateArgumentsParameters::kRestArray && |
(...skipping 15 matching lines...) Expand all Loading... |
1155 Node* parameter_pointer = graph()->NewNode( | 1169 Node* parameter_pointer = graph()->NewNode( |
1156 machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()), | 1170 machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()), |
1157 jsgraph()->IntPtrConstant(offset)); | 1171 jsgraph()->IntPtrConstant(offset)); |
1158 node->InsertInput(graph()->zone(), 0, stub_code); | 1172 node->InsertInput(graph()->zone(), 0, stub_code); |
1159 node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(parameter_count)); | 1173 node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(parameter_count)); |
1160 node->InsertInput(graph()->zone(), 3, parameter_pointer); | 1174 node->InsertInput(graph()->zone(), 3, parameter_pointer); |
1161 NodeProperties::ChangeOp(node, new_op); | 1175 NodeProperties::ChangeOp(node, new_op); |
1162 return Changed(node); | 1176 return Changed(node); |
1163 } | 1177 } |
1164 | 1178 |
| 1179 // Use inline allocation for all mapped arguments objects within inlined |
| 1180 // (i.e. non-outermost) frames, independent of the object size. |
| 1181 if (p.type() == CreateArgumentsParameters::kMappedArguments && |
| 1182 outer_state->opcode() == IrOpcode::kFrameState) { |
| 1183 Handle<SharedFunctionInfo> shared; |
| 1184 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); |
| 1185 Node* const callee = NodeProperties::GetValueInput(node, 0); |
| 1186 Node* const effect = NodeProperties::GetEffectInput(node); |
| 1187 Node* const control = NodeProperties::GetControlInput(node); |
| 1188 Node* const context = NodeProperties::GetContextInput(node); |
| 1189 // TODO(mstarzinger): Duplicate parameters are not handled yet. |
| 1190 if (shared->has_duplicate_parameters()) return NoChange(); |
| 1191 // Choose the correct frame state and frame state info depending on whether |
| 1192 // there conceptually is an arguments adaptor frame in the call chain. |
| 1193 Node* const args_state = GetArgumentsFrameState(frame_state); |
| 1194 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state); |
| 1195 // Prepare element backing store to be used by arguments object. |
| 1196 bool has_aliased_arguments = false; |
| 1197 Node* const elements = AllocateAliasedArguments( |
| 1198 effect, control, args_state, context, shared, &has_aliased_arguments); |
| 1199 // Load the arguments object map from the current native context. |
| 1200 Node* const load_global_object = graph()->NewNode( |
| 1201 simplified()->LoadField( |
| 1202 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| 1203 context, effect, control); |
| 1204 Node* const load_native_context = graph()->NewNode( |
| 1205 simplified()->LoadField(AccessBuilder::ForGlobalObjectNativeContext()), |
| 1206 load_global_object, effect, control); |
| 1207 Node* const load_arguments_map = graph()->NewNode( |
| 1208 simplified()->LoadField(AccessBuilder::ForContextSlot( |
| 1209 has_aliased_arguments ? Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX |
| 1210 : Context::SLOPPY_ARGUMENTS_MAP_INDEX)), |
| 1211 load_native_context, effect, control); |
| 1212 // Actually allocate and initialize the arguments object. |
| 1213 AllocationBuilder a(jsgraph(), effect, control); |
| 1214 Node* properties = jsgraph()->EmptyFixedArrayConstant(); |
| 1215 int length = args_state_info.parameter_count() - 1; // Minus receiver. |
| 1216 STATIC_ASSERT(Heap::kSloppyArgumentsObjectSize == 5 * kPointerSize); |
| 1217 a.Allocate(Heap::kSloppyArgumentsObjectSize); |
| 1218 a.Store(AccessBuilder::ForMap(), load_arguments_map); |
| 1219 a.Store(AccessBuilder::ForJSObjectProperties(), properties); |
| 1220 a.Store(AccessBuilder::ForJSObjectElements(), elements); |
| 1221 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); |
| 1222 a.Store(AccessBuilder::ForArgumentsCallee(), callee); |
| 1223 RelaxControls(node); |
| 1224 a.FinishAndChange(node); |
| 1225 return Changed(node); |
| 1226 } |
| 1227 |
1165 // Use inline allocation for all unmapped arguments objects within inlined | 1228 // Use inline allocation for all unmapped arguments objects within inlined |
1166 // (i.e. non-outermost) frames, independent of the object size. | 1229 // (i.e. non-outermost) frames, independent of the object size. |
1167 if (p.type() == CreateArgumentsParameters::kUnmappedArguments && | 1230 if (p.type() == CreateArgumentsParameters::kUnmappedArguments && |
1168 outer_state->opcode() == IrOpcode::kFrameState) { | 1231 outer_state->opcode() == IrOpcode::kFrameState) { |
1169 Node* const effect = NodeProperties::GetEffectInput(node); | 1232 Node* const effect = NodeProperties::GetEffectInput(node); |
1170 Node* const control = NodeProperties::GetControlInput(node); | 1233 Node* const control = NodeProperties::GetControlInput(node); |
1171 Node* const context = NodeProperties::GetContextInput(node); | 1234 Node* const context = NodeProperties::GetContextInput(node); |
1172 FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state); | |
1173 // Choose the correct frame state and frame state info depending on whether | 1235 // Choose the correct frame state and frame state info depending on whether |
1174 // there conceptually is an arguments adaptor frame in the call chain. | 1236 // there conceptually is an arguments adaptor frame in the call chain. |
1175 Node* const args_state = | 1237 Node* const args_state = GetArgumentsFrameState(frame_state); |
1176 outer_state_info.type() == FrameStateType::kArgumentsAdaptor | |
1177 ? outer_state | |
1178 : frame_state; | |
1179 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state); | 1238 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state); |
1180 // Prepare element backing store to be used by arguments object. | 1239 // Prepare element backing store to be used by arguments object. |
1181 Node* const elements = AllocateArguments(effect, control, args_state); | 1240 Node* const elements = AllocateArguments(effect, control, args_state); |
1182 // Load the arguments object map from the current native context. | 1241 // Load the arguments object map from the current native context. |
1183 Node* const load_global_object = graph()->NewNode( | 1242 Node* const load_global_object = graph()->NewNode( |
1184 simplified()->LoadField( | 1243 simplified()->LoadField( |
1185 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1244 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
1186 context, effect, control); | 1245 context, effect, control); |
1187 Node* const load_native_context = graph()->NewNode( | 1246 Node* const load_native_context = graph()->NewNode( |
1188 simplified()->LoadField(AccessBuilder::ForGlobalObjectNativeContext()), | 1247 simplified()->LoadField(AccessBuilder::ForGlobalObjectNativeContext()), |
1189 load_global_object, effect, control); | 1248 load_global_object, effect, control); |
1190 Node* const load_arguments_map = graph()->NewNode( | 1249 Node* const load_arguments_map = graph()->NewNode( |
1191 simplified()->LoadField( | 1250 simplified()->LoadField( |
1192 AccessBuilder::ForContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX)), | 1251 AccessBuilder::ForContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX)), |
1193 load_native_context, effect, control); | 1252 load_native_context, effect, control); |
1194 // Actually allocate and initialize the arguments object. | 1253 // Actually allocate and initialize the arguments object. |
1195 AllocationBuilder a(jsgraph(), effect, control); | 1254 AllocationBuilder a(jsgraph(), effect, control); |
1196 Handle<Object> properties = factory()->empty_fixed_array(); | 1255 Node* properties = jsgraph()->EmptyFixedArrayConstant(); |
1197 int length = args_state_info.parameter_count() - 1; // Minus receiver. | 1256 int length = args_state_info.parameter_count() - 1; // Minus receiver. |
1198 STATIC_ASSERT(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize); | 1257 STATIC_ASSERT(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize); |
1199 a.Allocate(Heap::kStrictArgumentsObjectSize); | 1258 a.Allocate(Heap::kStrictArgumentsObjectSize); |
1200 a.Store(AccessBuilder::ForMap(), load_arguments_map); | 1259 a.Store(AccessBuilder::ForMap(), load_arguments_map); |
1201 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | 1260 a.Store(AccessBuilder::ForJSObjectProperties(), properties); |
1202 a.Store(AccessBuilder::ForJSObjectElements(), elements); | 1261 a.Store(AccessBuilder::ForJSObjectElements(), elements); |
1203 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); | 1262 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); |
1204 RelaxControls(node); | 1263 RelaxControls(node); |
1205 a.FinishAndChange(node); | 1264 a.FinishAndChange(node); |
1206 return Changed(node); | 1265 return Changed(node); |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1872 return graph()->NewNode(machine()->Word32Shl(), lhs, | 1931 return graph()->NewNode(machine()->Word32Shl(), lhs, |
1873 jsgraph()->Int32Constant(rhs)); | 1932 jsgraph()->Int32Constant(rhs)); |
1874 } | 1933 } |
1875 | 1934 |
1876 | 1935 |
1877 // Helper that allocates a FixedArray holding argument values recorded in the | 1936 // Helper that allocates a FixedArray holding argument values recorded in the |
1878 // given {frame_state}. Serves as backing store for JSCreateArguments nodes. | 1937 // given {frame_state}. Serves as backing store for JSCreateArguments nodes. |
1879 Node* JSTypedLowering::AllocateArguments(Node* effect, Node* control, | 1938 Node* JSTypedLowering::AllocateArguments(Node* effect, Node* control, |
1880 Node* frame_state) { | 1939 Node* frame_state) { |
1881 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | 1940 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); |
1882 int length = state_info.parameter_count() - 1; // Minus receiver argument. | 1941 int argument_count = state_info.parameter_count() - 1; // Minus receiver. |
1883 if (length == 0) return jsgraph()->Constant(factory()->empty_fixed_array()); | 1942 if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); |
| 1943 |
| 1944 // Prepare an iterator over argument values recorded in the frame state. |
1884 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); | 1945 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); |
1885 StateValuesAccess parameters_access(parameters); | 1946 StateValuesAccess parameters_access(parameters); |
1886 auto paratemers_it = ++parameters_access.begin(); | 1947 auto paratemers_it = ++parameters_access.begin(); |
| 1948 |
| 1949 // Actually allocate the backing store. |
1887 AllocationBuilder a(jsgraph(), effect, control); | 1950 AllocationBuilder a(jsgraph(), effect, control); |
1888 a.AllocateArray(length, factory()->fixed_array_map()); | 1951 a.AllocateArray(argument_count, factory()->fixed_array_map()); |
1889 for (int i = 0; i < length; ++i, ++paratemers_it) { | 1952 for (int i = 0; i < argument_count; ++i, ++paratemers_it) { |
1890 a.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node); | 1953 a.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node); |
1891 } | 1954 } |
1892 return a.Finish(); | 1955 return a.Finish(); |
1893 } | 1956 } |
1894 | 1957 |
1895 | 1958 |
| 1959 // Helper that allocates a FixedArray serving as a parameter map for values |
| 1960 // recorded in the given {frame_state}. Some elements map to slots within the |
| 1961 // given {context}. Serves as backing store for JSCreateArguments nodes. |
| 1962 Node* JSTypedLowering::AllocateAliasedArguments( |
| 1963 Node* effect, Node* control, Node* frame_state, Node* context, |
| 1964 Handle<SharedFunctionInfo> shared, bool* has_aliased_arguments) { |
| 1965 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); |
| 1966 int argument_count = state_info.parameter_count() - 1; // Minus receiver. |
| 1967 if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); |
| 1968 |
| 1969 // If there is no aliasing, the arguments object elements are not special in |
| 1970 // any way, we can just return an unmapped backing store instead. |
| 1971 int parameter_count = shared->internal_formal_parameter_count(); |
| 1972 if (parameter_count == 0) { |
| 1973 return AllocateArguments(effect, control, frame_state); |
| 1974 } |
| 1975 |
| 1976 // Calculate number of argument values being aliased/mapped. |
| 1977 int mapped_count = Min(argument_count, parameter_count); |
| 1978 *has_aliased_arguments = true; |
| 1979 |
| 1980 // Prepare an iterator over argument values recorded in the frame state. |
| 1981 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); |
| 1982 StateValuesAccess parameters_access(parameters); |
| 1983 auto paratemers_it = ++parameters_access.begin(); |
| 1984 |
| 1985 // The unmapped argument values recorded in the frame state are stored yet |
| 1986 // another indirection away and then linked into the parameter map below, |
| 1987 // whereas mapped argument values are replaced with a hole instead. |
| 1988 AllocationBuilder aa(jsgraph(), effect, control); |
| 1989 aa.AllocateArray(argument_count, factory()->fixed_array_map()); |
| 1990 for (int i = 0; i < mapped_count; ++i, ++paratemers_it) { |
| 1991 aa.Store(AccessBuilder::ForFixedArraySlot(i), jsgraph()->TheHoleConstant()); |
| 1992 } |
| 1993 for (int i = mapped_count; i < argument_count; ++i, ++paratemers_it) { |
| 1994 aa.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node); |
| 1995 } |
| 1996 Node* arguments = aa.Finish(); |
| 1997 |
| 1998 // Actually allocate the backing store. |
| 1999 AllocationBuilder a(jsgraph(), effect, control); |
| 2000 a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map()); |
| 2001 a.Store(AccessBuilder::ForFixedArraySlot(0), context); |
| 2002 a.Store(AccessBuilder::ForFixedArraySlot(1), arguments); |
| 2003 for (int i = 0; i < mapped_count; ++i) { |
| 2004 int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i; |
| 2005 a.Store(AccessBuilder::ForFixedArraySlot(i + 2), jsgraph()->Constant(idx)); |
| 2006 } |
| 2007 return a.Finish(); |
| 2008 } |
| 2009 |
| 2010 |
1896 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } | 2011 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } |
1897 | 2012 |
1898 | 2013 |
1899 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); } | 2014 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); } |
1900 | 2015 |
1901 | 2016 |
1902 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); } | 2017 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); } |
1903 | 2018 |
1904 | 2019 |
1905 JSOperatorBuilder* JSTypedLowering::javascript() const { | 2020 JSOperatorBuilder* JSTypedLowering::javascript() const { |
(...skipping 11 matching lines...) Expand all Loading... |
1917 } | 2032 } |
1918 | 2033 |
1919 | 2034 |
1920 MachineOperatorBuilder* JSTypedLowering::machine() const { | 2035 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1921 return jsgraph()->machine(); | 2036 return jsgraph()->machine(); |
1922 } | 2037 } |
1923 | 2038 |
1924 } // namespace compiler | 2039 } // namespace compiler |
1925 } // namespace internal | 2040 } // namespace internal |
1926 } // namespace v8 | 2041 } // namespace v8 |
OLD | NEW |