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

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

Issue 1412113004: [turbofan] Lower unmapped arguments objects in inline frame. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 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
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 18 matching lines...) Expand all
29 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 29 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
30 } 30 }
31 } 31 }
32 32
33 33
34 // A helper class to construct inline allocations on the simplified operator 34 // A helper class to construct inline allocations on the simplified operator
35 // level. This keeps track of the effect chain for initial stores on a newly 35 // level. This keeps track of the effect chain for initial stores on a newly
36 // allocated object and also provides helpers for commonly allocated objects. 36 // allocated object and also provides helpers for commonly allocated objects.
37 class AllocationBuilder final { 37 class AllocationBuilder final {
38 public: 38 public:
39 AllocationBuilder(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, 39 AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control)
40 Node* effect, Node* control)
41 : jsgraph_(jsgraph), 40 : jsgraph_(jsgraph),
42 simplified_(simplified),
43 allocation_(nullptr), 41 allocation_(nullptr),
44 effect_(effect), 42 effect_(effect),
45 control_(control) {} 43 control_(control) {}
46 44
47 // Primitive allocation of static size. 45 // Primitive allocation of static size.
48 void Allocate(int size) { 46 void Allocate(int size) {
49 effect_ = graph()->NewNode(jsgraph()->common()->BeginRegion(), effect_); 47 effect_ = graph()->NewNode(common()->BeginRegion(), effect_);
50 allocation_ = graph()->NewNode( 48 allocation_ = graph()->NewNode(
51 simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_); 49 simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_);
52 effect_ = allocation_; 50 effect_ = allocation_;
53 } 51 }
54 52
55 // Primitive store into a field. 53 // Primitive store into a field.
56 void Store(const FieldAccess& access, Node* value) { 54 void Store(const FieldAccess& access, Node* value) {
57 effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_, 55 effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_,
58 value, effect_, control_); 56 value, effect_, control_);
59 } 57 }
60 58
61 // Compound allocation of a FixedArray. 59 // Compound allocation of a FixedArray.
62 void AllocateArray(int length, Handle<Map> map) { 60 void AllocateArray(int length, Handle<Map> map) {
63 Allocate(FixedArray::SizeFor(length)); 61 Allocate(FixedArray::SizeFor(length));
64 Store(AccessBuilder::ForMap(), map); 62 Store(AccessBuilder::ForMap(), map);
65 Store(AccessBuilder::ForFixedArrayLength(graph()->zone()), 63 Store(AccessBuilder::ForFixedArrayLength(graph()->zone()),
66 jsgraph()->Constant(length)); 64 jsgraph()->Constant(length));
67 } 65 }
68 66
69 // Compound store of a constant into a field. 67 // Compound store of a constant into a field.
70 void Store(const FieldAccess& access, Handle<Object> value) { 68 void Store(const FieldAccess& access, Handle<Object> value) {
71 Store(access, jsgraph()->Constant(value)); 69 Store(access, jsgraph()->Constant(value));
72 } 70 }
73 71
74 void Finish(Node* node) { 72 void Finish(Node* node) {
75 NodeProperties::SetType(allocation_, NodeProperties::GetType(node)); 73 NodeProperties::SetType(allocation_, NodeProperties::GetType(node));
76 node->ReplaceInput(0, allocation_); 74 node->ReplaceInput(0, allocation_);
77 node->ReplaceInput(1, effect_); 75 node->ReplaceInput(1, effect_);
78 node->TrimInputCount(2); 76 node->TrimInputCount(2);
79 NodeProperties::ChangeOp(node, jsgraph()->common()->FinishRegion()); 77 NodeProperties::ChangeOp(node, common()->FinishRegion());
78 }
79
80 Node* Finish() {
Jarin 2015/10/23 14:09:22 I would prefer not to overload Finish. Perhaps ren
Michael Starzinger 2015/10/23 15:09:40 Done. As discussed offline, I went with "FinishAnd
81 return graph()->NewNode(common()->FinishRegion(), allocation_, effect_);
80 } 82 }
81 83
82 protected: 84 protected:
83 JSGraph* jsgraph() { return jsgraph_; } 85 JSGraph* jsgraph() { return jsgraph_; }
84 Graph* graph() { return jsgraph_->graph(); } 86 Graph* graph() { return jsgraph_->graph(); }
85 SimplifiedOperatorBuilder* simplified() { return simplified_; } 87 CommonOperatorBuilder* common() { return jsgraph_->common(); }
88 SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); }
86 89
87 private: 90 private:
88 JSGraph* const jsgraph_; 91 JSGraph* const jsgraph_;
89 SimplifiedOperatorBuilder* simplified_;
90 Node* allocation_; 92 Node* allocation_;
91 Node* effect_; 93 Node* effect_;
92 Node* control_; 94 Node* control_;
93 }; 95 };
94 96
95 97
96 // A helper class to simplify the process of reducing a single binop node with a 98 // A helper class to simplify the process of reducing a single binop node with a
97 // JSOperator. This class manages the rewriting of context, control, and effect 99 // JSOperator. This class manages the rewriting of context, control, and effect
98 // dependencies during lowering of a binop and contains numerous helper 100 // dependencies during lowering of a binop and contains numerous helper
99 // functions for matching the types of inputs to an operation. 101 // functions for matching the types of inputs to an operation.
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 Node* parameter_pointer = graph()->NewNode( 1154 Node* parameter_pointer = graph()->NewNode(
1153 machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()), 1155 machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()),
1154 jsgraph()->IntPtrConstant(offset)); 1156 jsgraph()->IntPtrConstant(offset));
1155 node->InsertInput(graph()->zone(), 0, stub_code); 1157 node->InsertInput(graph()->zone(), 0, stub_code);
1156 node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(parameter_count)); 1158 node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(parameter_count));
1157 node->InsertInput(graph()->zone(), 3, parameter_pointer); 1159 node->InsertInput(graph()->zone(), 3, parameter_pointer);
1158 NodeProperties::ChangeOp(node, new_op); 1160 NodeProperties::ChangeOp(node, new_op);
1159 return Changed(node); 1161 return Changed(node);
1160 } 1162 }
1161 1163
1164 // Use inline allocation for all unmapped arguments objects within inlined
1165 // (i.e. non-outermost) frames, independent of the object size.
1166 if (p.type() == CreateArgumentsParameters::kUnmappedArguments &&
1167 outer_state->opcode() == IrOpcode::kFrameState) {
1168 Node* const effect = NodeProperties::GetEffectInput(node);
1169 Node* const control = NodeProperties::GetControlInput(node);
1170 Node* const context = NodeProperties::GetContextInput(node);
1171 FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state);
1172 // Choose the correct frame state and frame state info depending on whether
1173 // there conceptually is an arguments adaptor frame in the call chain.
1174 Node* const args_state =
1175 outer_state_info.type() == FrameStateType::kArgumentsAdaptor
1176 ? outer_state
1177 : frame_state;
1178 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
1179 // Prepare element backing store to be used by arguments object.
1180 Node* const elements = AllocateArguments(effect, control, args_state);
1181 // Load the arguments object map from the current native context.
1182 Node* const load_global_object = graph()->NewNode(
1183 simplified()->LoadField(
1184 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)),
1185 context, effect, control);
1186 Node* const load_native_context = graph()->NewNode(
1187 simplified()->LoadField(AccessBuilder::ForGlobalObjectNativeContext()),
1188 load_global_object, effect, control);
1189 Node* const load_arguments_map = graph()->NewNode(
1190 simplified()->LoadField(
1191 AccessBuilder::ForContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX)),
1192 load_native_context, effect, control);
1193 // Actually allocate and initialize the arguments object.
1194 AllocationBuilder a(jsgraph(), effect, control);
1195 Handle<Object> properties = factory()->empty_fixed_array();
1196 int length = args_state_info.parameter_count() - 1; // Minus receiver.
1197 STATIC_ASSERT(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize);
1198 a.Allocate(Heap::kStrictArgumentsObjectSize);
1199 a.Store(AccessBuilder::ForMap(), load_arguments_map);
1200 a.Store(AccessBuilder::ForJSObjectProperties(), properties);
1201 a.Store(AccessBuilder::ForJSObjectElements(), elements);
1202 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
1203 RelaxControls(node);
1204 a.Finish(node);
1205 return Changed(node);
1206 }
1207
1162 return NoChange(); 1208 return NoChange();
1163 } 1209 }
1164 1210
1165 1211
1166 Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) { 1212 Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
1167 DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode()); 1213 DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
1168 CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); 1214 CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
1169 Handle<SharedFunctionInfo> shared = p.shared_info(); 1215 Handle<SharedFunctionInfo> shared = p.shared_info();
1170 1216
1171 // Use the FastNewClosureStub that allocates in new space only for nested 1217 // Use the FastNewClosureStub that allocates in new space only for nested
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 closure->opcode() != IrOpcode::kNumberConstant) { 1309 closure->opcode() != IrOpcode::kNumberConstant) {
1264 // JSCreateFunctionContext[slot_count < limit]](fun) 1310 // JSCreateFunctionContext[slot_count < limit]](fun)
1265 Node* const effect = NodeProperties::GetEffectInput(node); 1311 Node* const effect = NodeProperties::GetEffectInput(node);
1266 Node* const control = NodeProperties::GetControlInput(node); 1312 Node* const control = NodeProperties::GetControlInput(node);
1267 Node* const context = NodeProperties::GetContextInput(node); 1313 Node* const context = NodeProperties::GetContextInput(node);
1268 Node* const extension = jsgraph()->ZeroConstant(); 1314 Node* const extension = jsgraph()->ZeroConstant();
1269 Node* const load = graph()->NewNode( 1315 Node* const load = graph()->NewNode(
1270 simplified()->LoadField( 1316 simplified()->LoadField(
1271 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), 1317 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)),
1272 context, effect, control); 1318 context, effect, control);
1273 AllocationBuilder a(jsgraph(), simplified(), effect, control); 1319 AllocationBuilder a(jsgraph(), effect, control);
1274 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. 1320 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1275 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; 1321 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
1276 a.AllocateArray(context_length, factory()->function_context_map()); 1322 a.AllocateArray(context_length, factory()->function_context_map());
1277 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); 1323 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
1278 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1324 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1279 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); 1325 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1280 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); 1326 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load);
1281 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { 1327 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
1282 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); 1328 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
1283 } 1329 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 if (input_type->Is(Type::Receiver()) && 1364 if (input_type->Is(Type::Receiver()) &&
1319 closure->opcode() != IrOpcode::kNumberConstant) { 1365 closure->opcode() != IrOpcode::kNumberConstant) {
1320 // JSCreateWithContext(o:receiver, fun) 1366 // JSCreateWithContext(o:receiver, fun)
1321 Node* const effect = NodeProperties::GetEffectInput(node); 1367 Node* const effect = NodeProperties::GetEffectInput(node);
1322 Node* const control = NodeProperties::GetControlInput(node); 1368 Node* const control = NodeProperties::GetControlInput(node);
1323 Node* const context = NodeProperties::GetContextInput(node); 1369 Node* const context = NodeProperties::GetContextInput(node);
1324 Node* const load = graph()->NewNode( 1370 Node* const load = graph()->NewNode(
1325 simplified()->LoadField( 1371 simplified()->LoadField(
1326 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), 1372 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)),
1327 context, effect, control); 1373 context, effect, control);
1328 AllocationBuilder a(jsgraph(), simplified(), effect, control); 1374 AllocationBuilder a(jsgraph(), effect, control);
1329 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. 1375 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1330 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); 1376 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
1331 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); 1377 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
1332 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1378 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1333 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); 1379 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input);
1334 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); 1380 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load);
1335 RelaxControls(node); 1381 RelaxControls(node);
1336 a.Finish(node); 1382 a.Finish(node);
1337 return Changed(node); 1383 return Changed(node);
1338 } 1384 }
(...skipping 17 matching lines...) Expand all
1356 closure->opcode() != IrOpcode::kNumberConstant) { 1402 closure->opcode() != IrOpcode::kNumberConstant) {
1357 // JSCreateBlockContext[scope[length < limit]](fun) 1403 // JSCreateBlockContext[scope[length < limit]](fun)
1358 Node* const effect = NodeProperties::GetEffectInput(node); 1404 Node* const effect = NodeProperties::GetEffectInput(node);
1359 Node* const control = NodeProperties::GetControlInput(node); 1405 Node* const control = NodeProperties::GetControlInput(node);
1360 Node* const context = NodeProperties::GetContextInput(node); 1406 Node* const context = NodeProperties::GetContextInput(node);
1361 Node* const extension = jsgraph()->Constant(scope_info); 1407 Node* const extension = jsgraph()->Constant(scope_info);
1362 Node* const load = graph()->NewNode( 1408 Node* const load = graph()->NewNode(
1363 simplified()->LoadField( 1409 simplified()->LoadField(
1364 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), 1410 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)),
1365 context, effect, control); 1411 context, effect, control);
1366 AllocationBuilder a(jsgraph(), simplified(), effect, control); 1412 AllocationBuilder a(jsgraph(), effect, control);
1367 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. 1413 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1368 a.AllocateArray(context_length, factory()->block_context_map()); 1414 a.AllocateArray(context_length, factory()->block_context_map());
1369 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); 1415 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
1370 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1416 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1371 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); 1417 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1372 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); 1418 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load);
1373 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { 1419 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
1374 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); 1420 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant());
1375 } 1421 }
1376 RelaxControls(node); 1422 RelaxControls(node);
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
1806 } 1852 }
1807 1853
1808 1854
1809 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { 1855 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
1810 if (rhs == 0) return lhs; 1856 if (rhs == 0) return lhs;
1811 return graph()->NewNode(machine()->Word32Shl(), lhs, 1857 return graph()->NewNode(machine()->Word32Shl(), lhs,
1812 jsgraph()->Int32Constant(rhs)); 1858 jsgraph()->Int32Constant(rhs));
1813 } 1859 }
1814 1860
1815 1861
1862 // Helper that allocates a FixedArray holding argument values recorded in the
1863 // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
1864 Node* JSTypedLowering::AllocateArguments(Node* effect, Node* control,
1865 Node* frame_state) {
1866 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
1867 int length = state_info.parameter_count() - 1; // Minus receiver argument.
1868 if (length == 0) return jsgraph()->Constant(factory()->empty_fixed_array());
1869 Node* const params = frame_state->InputAt(kFrameStateParametersInput);
1870 AllocationBuilder a(jsgraph(), effect, control);
1871 a.AllocateArray(length, factory()->fixed_array_map());
1872 for (int i = 0; i < length; ++i) {
Jarin 2015/10/23 14:09:22 Could you use StateValuesIterator for this?
Michael Starzinger 2015/10/23 15:09:39 Done.
1873 a.Store(AccessBuilder::ForFixedArraySlot(i), params->InputAt(i + 1));
1874 }
1875 return a.Finish();
1876 }
1877
1878
1816 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } 1879 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
1817 1880
1818 1881
1819 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); } 1882 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
1820 1883
1821 1884
1822 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); } 1885 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
1823 1886
1824 1887
1825 JSOperatorBuilder* JSTypedLowering::javascript() const { 1888 JSOperatorBuilder* JSTypedLowering::javascript() const {
(...skipping 11 matching lines...) Expand all
1837 } 1900 }
1838 1901
1839 1902
1840 MachineOperatorBuilder* JSTypedLowering::machine() const { 1903 MachineOperatorBuilder* JSTypedLowering::machine() const {
1841 return jsgraph()->machine(); 1904 return jsgraph()->machine();
1842 } 1905 }
1843 1906
1844 } // namespace compiler 1907 } // namespace compiler
1845 } // namespace internal 1908 } // namespace internal
1846 } // namespace v8 1909 } // namespace v8
OLDNEW
« src/compiler/access-builder.h ('K') | « src/compiler/js-typed-lowering.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698