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

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 1403363004: [turbofan] Lower mapped arguments objects in inline frame. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment. Created 5 years, 1 month 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/js-typed-lowering.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698