Chromium Code Reviews| 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 19 matching lines...) Expand all Loading... | |
| 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, SimplifiedOperatorBuilder* simplified, |
| 40 Node* effect, Node* control) | 40 Node* node, Node* effect, Node* control) |
| 41 : jsgraph_(jsgraph), | 41 : jsgraph_(jsgraph), |
| 42 simplified_(simplified), | 42 simplified_(simplified), |
| 43 allocation_(nullptr), | 43 allocation_(nullptr), |
| 44 node_(node), | |
| 44 effect_(effect), | 45 effect_(effect), |
| 45 control_(control) {} | 46 control_(control) {} |
| 46 | 47 |
| 48 ~AllocationBuilder() { | |
| 49 // Make sure we are finished. | |
| 50 DCHECK_EQ(IrOpcode::kFinishRegion, node_->opcode()); | |
| 51 } | |
| 52 | |
| 47 // Primitive allocation of static size. | 53 // Primitive allocation of static size. |
| 48 void Allocate(int size) { | 54 void Allocate(int size) { |
| 55 effect_ = graph()->NewNode(jsgraph()->common()->BeginRegion(), effect_); | |
| 49 allocation_ = graph()->NewNode( | 56 allocation_ = graph()->NewNode( |
| 50 simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_); | 57 simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_); |
| 51 effect_ = allocation_; | 58 effect_ = allocation_; |
| 52 } | 59 } |
| 53 | 60 |
| 54 // Primitive store into a field. | 61 // Primitive store into a field. |
| 55 void Store(const FieldAccess& access, Node* value) { | 62 void Store(const FieldAccess& access, Node* value) { |
| 56 effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_, | 63 effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_, |
| 57 value, effect_, control_); | 64 value, effect_, control_); |
| 58 } | 65 } |
| 59 | 66 |
| 60 // Compound allocation of a FixedArray. | 67 // Compound allocation of a FixedArray. |
| 61 void AllocateArray(int length, Handle<Map> map) { | 68 void AllocateArray(int length, Handle<Map> map) { |
| 62 Allocate(FixedArray::SizeFor(length)); | 69 Allocate(FixedArray::SizeFor(length)); |
| 63 Store(AccessBuilder::ForMap(), map); | 70 Store(AccessBuilder::ForMap(), map); |
| 64 Store(AccessBuilder::ForFixedArrayLength(graph()->zone()), | 71 Store(AccessBuilder::ForFixedArrayLength(graph()->zone()), |
| 65 jsgraph()->Constant(length)); | 72 jsgraph()->Constant(length)); |
| 66 } | 73 } |
| 67 | 74 |
| 68 // Compound store of a constant into a field. | 75 // Compound store of a constant into a field. |
| 69 void Store(const FieldAccess& access, Handle<Object> value) { | 76 void Store(const FieldAccess& access, Handle<Object> value) { |
| 70 Store(access, jsgraph()->Constant(value)); | 77 Store(access, jsgraph()->Constant(value)); |
| 71 } | 78 } |
| 72 | 79 |
| 73 Node* allocation() const { return allocation_; } | 80 void Finish() { |
|
Benedikt Meurer
2015/10/13 19:12:09
Nit: I think this helper should return the Reducti
Jarin
2015/10/14 06:37:20
Ack. I will leave the decision to Michi, I do not
| |
| 74 Node* effect() const { return effect_; } | 81 NodeProperties::SetType(allocation_, NodeProperties::GetType(node_)); |
| 82 node_->ReplaceInput(0, allocation_); | |
| 83 node_->ReplaceInput(1, effect_); | |
| 84 node_->TrimInputCount(2); | |
| 85 NodeProperties::ChangeOp(node_, jsgraph()->common()->FinishRegion()); | |
| 86 } | |
| 75 | 87 |
| 76 protected: | 88 protected: |
| 77 JSGraph* jsgraph() { return jsgraph_; } | 89 JSGraph* jsgraph() { return jsgraph_; } |
| 78 Graph* graph() { return jsgraph_->graph(); } | 90 Graph* graph() { return jsgraph_->graph(); } |
| 79 SimplifiedOperatorBuilder* simplified() { return simplified_; } | 91 SimplifiedOperatorBuilder* simplified() { return simplified_; } |
| 80 | 92 |
| 81 private: | 93 private: |
| 82 JSGraph* const jsgraph_; | 94 JSGraph* const jsgraph_; |
| 83 SimplifiedOperatorBuilder* simplified_; | 95 SimplifiedOperatorBuilder* simplified_; |
| 84 Node* allocation_; | 96 Node* allocation_; |
| 97 Node* node_; | |
| 85 Node* effect_; | 98 Node* effect_; |
| 86 Node* control_; | 99 Node* control_; |
| 87 }; | 100 }; |
| 88 | 101 |
| 89 | 102 |
| 90 // A helper class to simplify the process of reducing a single binop node with a | 103 // A helper class to simplify the process of reducing a single binop node with a |
| 91 // JSOperator. This class manages the rewriting of context, control, and effect | 104 // JSOperator. This class manages the rewriting of context, control, and effect |
| 92 // dependencies during lowering of a binop and contains numerous helper | 105 // dependencies during lowering of a binop and contains numerous helper |
| 93 // functions for matching the types of inputs to an operation. | 106 // functions for matching the types of inputs to an operation. |
| 94 class JSBinopReduction final { | 107 class JSBinopReduction final { |
| (...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1256 // JSCreateFunctionContext[slot_count < limit]](fun) | 1269 // JSCreateFunctionContext[slot_count < limit]](fun) |
| 1257 Node* const effect = NodeProperties::GetEffectInput(node); | 1270 Node* const effect = NodeProperties::GetEffectInput(node); |
| 1258 Node* const control = NodeProperties::GetControlInput(node); | 1271 Node* const control = NodeProperties::GetControlInput(node); |
| 1259 Node* const closure = NodeProperties::GetValueInput(node, 0); | 1272 Node* const closure = NodeProperties::GetValueInput(node, 0); |
| 1260 Node* const context = NodeProperties::GetContextInput(node); | 1273 Node* const context = NodeProperties::GetContextInput(node); |
| 1261 Node* const extension = jsgraph()->ZeroConstant(); | 1274 Node* const extension = jsgraph()->ZeroConstant(); |
| 1262 Node* const load = graph()->NewNode( | 1275 Node* const load = graph()->NewNode( |
| 1263 simplified()->LoadField( | 1276 simplified()->LoadField( |
| 1264 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1277 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| 1265 context, effect, control); | 1278 context, effect, control); |
| 1266 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1279 RelaxControls(node); |
| 1280 AllocationBuilder a(jsgraph(), simplified(), node, effect, control); | |
| 1267 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1281 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
| 1268 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; | 1282 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; |
| 1269 a.AllocateArray(context_length, factory()->function_context_map()); | 1283 a.AllocateArray(context_length, factory()->function_context_map()); |
| 1270 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1284 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1271 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1285 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1272 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); | 1286 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); |
| 1273 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1287 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1274 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | 1288 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { |
| 1275 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); | 1289 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); |
| 1276 } | 1290 } |
| 1277 // TODO(mstarzinger): We could mutate {node} into the allocation instead. | 1291 a.Finish(); |
| 1278 NodeProperties::SetType(a.allocation(), NodeProperties::GetType(node)); | |
| 1279 ReplaceWithValue(node, node, a.effect()); | |
| 1280 node->ReplaceInput(0, a.allocation()); | |
| 1281 node->ReplaceInput(1, a.effect()); | |
| 1282 node->TrimInputCount(2); | |
| 1283 NodeProperties::ChangeOp(node, common()->Finish(1)); | |
| 1284 return Changed(node); | 1292 return Changed(node); |
| 1285 } | 1293 } |
| 1286 | 1294 |
| 1287 // Use the FastNewContextStub only for function contexts up maximum size. | 1295 // Use the FastNewContextStub only for function contexts up maximum size. |
| 1288 if (slot_count <= FastNewContextStub::kMaximumSlots) { | 1296 if (slot_count <= FastNewContextStub::kMaximumSlots) { |
| 1289 Isolate* isolate = jsgraph()->isolate(); | 1297 Isolate* isolate = jsgraph()->isolate(); |
| 1290 Callable callable = CodeFactory::FastNewContext(isolate, slot_count); | 1298 Callable callable = CodeFactory::FastNewContext(isolate, slot_count); |
| 1291 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1299 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 1292 isolate, graph()->zone(), callable.descriptor(), 0, | 1300 isolate, graph()->zone(), callable.descriptor(), 0, |
| 1293 CallDescriptor::kNoFlags); | 1301 CallDescriptor::kNoFlags); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1311 if (FLAG_turbo_allocate && input_type->Is(Type::Receiver())) { | 1319 if (FLAG_turbo_allocate && input_type->Is(Type::Receiver())) { |
| 1312 // JSCreateWithContext(o:receiver, fun) | 1320 // JSCreateWithContext(o:receiver, fun) |
| 1313 Node* const effect = NodeProperties::GetEffectInput(node); | 1321 Node* const effect = NodeProperties::GetEffectInput(node); |
| 1314 Node* const control = NodeProperties::GetControlInput(node); | 1322 Node* const control = NodeProperties::GetControlInput(node); |
| 1315 Node* const closure = NodeProperties::GetValueInput(node, 1); | 1323 Node* const closure = NodeProperties::GetValueInput(node, 1); |
| 1316 Node* const context = NodeProperties::GetContextInput(node); | 1324 Node* const context = NodeProperties::GetContextInput(node); |
| 1317 Node* const load = graph()->NewNode( | 1325 Node* const load = graph()->NewNode( |
| 1318 simplified()->LoadField( | 1326 simplified()->LoadField( |
| 1319 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1327 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| 1320 context, effect, control); | 1328 context, effect, control); |
| 1321 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1329 RelaxControls(node); |
| 1330 AllocationBuilder a(jsgraph(), simplified(), node, effect, control); | |
| 1322 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1331 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
| 1323 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); | 1332 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); |
| 1324 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1333 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1325 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1334 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1326 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); | 1335 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
| 1327 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1336 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1328 // TODO(mstarzinger): We could mutate {node} into the allocation instead. | 1337 a.Finish(); |
| 1329 NodeProperties::SetType(a.allocation(), NodeProperties::GetType(node)); | |
| 1330 ReplaceWithValue(node, node, a.effect()); | |
| 1331 node->ReplaceInput(0, a.allocation()); | |
| 1332 node->ReplaceInput(1, a.effect()); | |
| 1333 node->TrimInputCount(2); | |
| 1334 NodeProperties::ChangeOp(node, common()->Finish(1)); | |
| 1335 return Changed(node); | 1338 return Changed(node); |
| 1336 } | 1339 } |
| 1337 | 1340 |
| 1338 return NoChange(); | 1341 return NoChange(); |
| 1339 } | 1342 } |
| 1340 | 1343 |
| 1341 | 1344 |
| 1342 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { | 1345 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { |
| 1343 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); | 1346 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); |
| 1344 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); | 1347 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); |
| 1345 int context_length = scope_info->ContextLength(); | 1348 int context_length = scope_info->ContextLength(); |
| 1346 | 1349 |
| 1347 // Use inline allocation for block contexts up to a size limit. | 1350 // Use inline allocation for block contexts up to a size limit. |
| 1348 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { | 1351 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { |
| 1349 // JSCreateBlockContext[scope[length < limit]](fun) | 1352 // JSCreateBlockContext[scope[length < limit]](fun) |
| 1350 Node* const effect = NodeProperties::GetEffectInput(node); | 1353 Node* const effect = NodeProperties::GetEffectInput(node); |
| 1351 Node* const control = NodeProperties::GetControlInput(node); | 1354 Node* const control = NodeProperties::GetControlInput(node); |
| 1352 Node* const closure = NodeProperties::GetValueInput(node, 1); | 1355 Node* const closure = NodeProperties::GetValueInput(node, 1); |
| 1353 Node* const context = NodeProperties::GetContextInput(node); | 1356 Node* const context = NodeProperties::GetContextInput(node); |
| 1354 Node* const extension = jsgraph()->Constant(scope_info); | 1357 Node* const extension = jsgraph()->Constant(scope_info); |
| 1355 Node* const load = graph()->NewNode( | 1358 Node* const load = graph()->NewNode( |
| 1356 simplified()->LoadField( | 1359 simplified()->LoadField( |
| 1357 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1360 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| 1358 context, effect, control); | 1361 context, effect, control); |
| 1359 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1362 RelaxControls(node); |
| 1363 AllocationBuilder a(jsgraph(), simplified(), node, effect, control); | |
| 1360 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1364 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
| 1361 a.AllocateArray(context_length, factory()->block_context_map()); | 1365 a.AllocateArray(context_length, factory()->block_context_map()); |
| 1362 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1366 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1363 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1367 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1364 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); | 1368 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); |
| 1365 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1369 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1366 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | 1370 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { |
| 1367 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); | 1371 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); |
| 1368 } | 1372 } |
| 1369 // TODO(mstarzinger): We could mutate {node} into the allocation instead. | 1373 a.Finish(); |
| 1370 NodeProperties::SetType(a.allocation(), NodeProperties::GetType(node)); | |
| 1371 ReplaceWithValue(node, node, a.effect()); | |
| 1372 node->ReplaceInput(0, a.allocation()); | |
| 1373 node->ReplaceInput(1, a.effect()); | |
| 1374 node->TrimInputCount(2); | |
| 1375 NodeProperties::ChangeOp(node, common()->Finish(1)); | |
| 1376 return Changed(node); | 1374 return Changed(node); |
| 1377 } | 1375 } |
| 1378 | 1376 |
| 1379 return NoChange(); | 1377 return NoChange(); |
| 1380 } | 1378 } |
| 1381 | 1379 |
| 1382 | 1380 |
| 1383 Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) { | 1381 Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) { |
| 1384 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 1382 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
| 1385 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 1383 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1830 } | 1828 } |
| 1831 | 1829 |
| 1832 | 1830 |
| 1833 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1831 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 1834 return jsgraph()->machine(); | 1832 return jsgraph()->machine(); |
| 1835 } | 1833 } |
| 1836 | 1834 |
| 1837 } // namespace compiler | 1835 } // namespace compiler |
| 1838 } // namespace internal | 1836 } // namespace internal |
| 1839 } // namespace v8 | 1837 } // namespace v8 |
| OLD | NEW |