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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 } | 50 } |
51 } | 51 } |
52 | 52 |
53 | 53 |
54 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { | 54 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { |
55 NodeProperties::ReplaceWithValue(old, node, node); | 55 NodeProperties::ReplaceWithValue(old, node, node); |
56 return Changed(node); | 56 return Changed(node); |
57 } | 57 } |
58 | 58 |
59 | 59 |
| 60 // A helper class to construct inline allocations on the simplified operator |
| 61 // level. This keeps track of the effect chain for initial stores on a newly |
| 62 // allocated object and also provides helpers for commonly allocated objects. |
| 63 class AllocationBuilder final { |
| 64 public: |
| 65 AllocationBuilder(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, |
| 66 Node* effect, Node* control) |
| 67 : jsgraph_(jsgraph), |
| 68 simplified_(simplified), |
| 69 allocation_(nullptr), |
| 70 effect_(effect), |
| 71 control_(control) {} |
| 72 |
| 73 // Primitive allocation of static size. |
| 74 void Allocate(int size) { |
| 75 allocation_ = graph()->NewNode( |
| 76 simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_); |
| 77 effect_ = allocation_; |
| 78 } |
| 79 |
| 80 // Primitive store into a field. |
| 81 void Store(const FieldAccess& access, Node* value) { |
| 82 effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_, |
| 83 value, effect_, control_); |
| 84 } |
| 85 |
| 86 // Compound allocation of a FixedArray. |
| 87 void AllocateArray(int length, Handle<Map> map) { |
| 88 Allocate(FixedArray::SizeFor(length)); |
| 89 Store(AccessBuilder::ForMap(), map); |
| 90 Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length)); |
| 91 } |
| 92 |
| 93 // Compound store of a constant into a field. |
| 94 void Store(const FieldAccess& access, Handle<Object> value) { |
| 95 Store(access, jsgraph()->Constant(value)); |
| 96 } |
| 97 |
| 98 Node* allocation() const { return allocation_; } |
| 99 Node* effect() const { return effect_; } |
| 100 |
| 101 protected: |
| 102 JSGraph* jsgraph() { return jsgraph_; } |
| 103 Graph* graph() { return jsgraph_->graph(); } |
| 104 SimplifiedOperatorBuilder* simplified() { return simplified_; } |
| 105 |
| 106 private: |
| 107 JSGraph* const jsgraph_; |
| 108 SimplifiedOperatorBuilder* simplified_; |
| 109 Node* allocation_; |
| 110 Node* effect_; |
| 111 Node* control_; |
| 112 }; |
| 113 |
| 114 |
60 // A helper class to simplify the process of reducing a single binop node with a | 115 // A helper class to simplify the process of reducing a single binop node with a |
61 // JSOperator. This class manages the rewriting of context, control, and effect | 116 // JSOperator. This class manages the rewriting of context, control, and effect |
62 // dependencies during lowering of a binop and contains numerous helper | 117 // dependencies during lowering of a binop and contains numerous helper |
63 // functions for matching the types of inputs to an operation. | 118 // functions for matching the types of inputs to an operation. |
64 class JSBinopReduction final { | 119 class JSBinopReduction final { |
65 public: | 120 public: |
66 JSBinopReduction(JSTypedLowering* lowering, Node* node) | 121 JSBinopReduction(JSTypedLowering* lowering, Node* node) |
67 : lowering_(lowering), node_(node) {} | 122 : lowering_(lowering), node_(node) {} |
68 | 123 |
69 void ConvertPrimitiveInputsToNumber() { | 124 void ConvertPrimitiveInputsToNumber() { |
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(flags)); | 1067 node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(flags)); |
1013 node->InsertInput(graph()->zone(), 0, stub_code); | 1068 node->InsertInput(graph()->zone(), 0, stub_code); |
1014 node->set_op(new_op); | 1069 node->set_op(new_op); |
1015 return Changed(node); | 1070 return Changed(node); |
1016 } | 1071 } |
1017 | 1072 |
1018 return NoChange(); | 1073 return NoChange(); |
1019 } | 1074 } |
1020 | 1075 |
1021 | 1076 |
| 1077 Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { |
| 1078 DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode()); |
| 1079 Node* const input = NodeProperties::GetValueInput(node, 0); |
| 1080 Type* input_type = NodeProperties::GetBounds(input).upper; |
| 1081 if (FLAG_turbo_allocate && input_type->Is(Type::Receiver())) { |
| 1082 // JSCreateWithContext(o:receiver, f) |
| 1083 Node* const effect = NodeProperties::GetEffectInput(node); |
| 1084 Node* const control = NodeProperties::GetControlInput(node); |
| 1085 Node* const closure = NodeProperties::GetValueInput(node, 1); |
| 1086 Node* const context = NodeProperties::GetContextInput(node); |
| 1087 Node* const load = graph()->NewNode( |
| 1088 simplified()->LoadField( |
| 1089 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| 1090 context, effect, control); |
| 1091 AllocationBuilder a(jsgraph(), simplified(), effect, control); |
| 1092 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
| 1093 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); |
| 1094 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1095 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1096 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
| 1097 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1098 // TODO(mstarzinger): We could mutate {node} into the allocation instead. |
| 1099 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); |
| 1100 NodeProperties::ReplaceWithValue(node, node, a.effect()); |
| 1101 node->ReplaceInput(0, a.allocation()); |
| 1102 node->ReplaceInput(1, a.effect()); |
| 1103 node->set_op(common()->Finish(1)); |
| 1104 node->TrimInputCount(2); |
| 1105 return Changed(node); |
| 1106 } |
| 1107 return NoChange(); |
| 1108 } |
| 1109 |
| 1110 |
| 1111 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { |
| 1112 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); |
| 1113 Node* const input = NodeProperties::GetValueInput(node, 0); |
| 1114 HeapObjectMatcher<ScopeInfo> minput(input); |
| 1115 DCHECK(minput.HasValue()); // TODO(mstarzinger): Make ScopeInfo static. |
| 1116 int context_length = minput.Value().handle()->ContextLength(); |
| 1117 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { |
| 1118 // JSCreateBlockContext(s:scope[length < limit], f) |
| 1119 Node* const effect = NodeProperties::GetEffectInput(node); |
| 1120 Node* const control = NodeProperties::GetControlInput(node); |
| 1121 Node* const closure = NodeProperties::GetValueInput(node, 1); |
| 1122 Node* const context = NodeProperties::GetContextInput(node); |
| 1123 Node* const load = graph()->NewNode( |
| 1124 simplified()->LoadField( |
| 1125 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| 1126 context, effect, control); |
| 1127 AllocationBuilder a(jsgraph(), simplified(), effect, control); |
| 1128 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
| 1129 a.AllocateArray(context_length, factory()->block_context_map()); |
| 1130 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
| 1131 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
| 1132 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
| 1133 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
| 1134 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { |
| 1135 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); |
| 1136 } |
| 1137 // TODO(mstarzinger): We could mutate {node} into the allocation instead. |
| 1138 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); |
| 1139 NodeProperties::ReplaceWithValue(node, node, a.effect()); |
| 1140 node->ReplaceInput(0, a.allocation()); |
| 1141 node->ReplaceInput(1, a.effect()); |
| 1142 node->set_op(common()->Finish(1)); |
| 1143 node->TrimInputCount(2); |
| 1144 return Changed(node); |
| 1145 } |
| 1146 return NoChange(); |
| 1147 } |
| 1148 |
| 1149 |
1022 Reduction JSTypedLowering::Reduce(Node* node) { | 1150 Reduction JSTypedLowering::Reduce(Node* node) { |
1023 // Check if the output type is a singleton. In that case we already know the | 1151 // Check if the output type is a singleton. In that case we already know the |
1024 // result value and can simply replace the node if it's eliminable. | 1152 // result value and can simply replace the node if it's eliminable. |
1025 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && | 1153 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && |
1026 node->op()->HasProperty(Operator::kEliminatable)) { | 1154 node->op()->HasProperty(Operator::kEliminatable)) { |
1027 Type* upper = NodeProperties::GetBounds(node).upper; | 1155 Type* upper = NodeProperties::GetBounds(node).upper; |
1028 if (upper->IsConstant()) { | 1156 if (upper->IsConstant()) { |
1029 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value()); | 1157 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value()); |
1030 NodeProperties::ReplaceWithValue(node, replacement); | 1158 NodeProperties::ReplaceWithValue(node, replacement); |
1031 return Changed(replacement); | 1159 return Changed(replacement); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 case IrOpcode::kJSLoadContext: | 1232 case IrOpcode::kJSLoadContext: |
1105 return ReduceJSLoadContext(node); | 1233 return ReduceJSLoadContext(node); |
1106 case IrOpcode::kJSStoreContext: | 1234 case IrOpcode::kJSStoreContext: |
1107 return ReduceJSStoreContext(node); | 1235 return ReduceJSStoreContext(node); |
1108 case IrOpcode::kJSCreateClosure: | 1236 case IrOpcode::kJSCreateClosure: |
1109 return ReduceJSCreateClosure(node); | 1237 return ReduceJSCreateClosure(node); |
1110 case IrOpcode::kJSCreateLiteralArray: | 1238 case IrOpcode::kJSCreateLiteralArray: |
1111 return ReduceJSCreateLiteralArray(node); | 1239 return ReduceJSCreateLiteralArray(node); |
1112 case IrOpcode::kJSCreateLiteralObject: | 1240 case IrOpcode::kJSCreateLiteralObject: |
1113 return ReduceJSCreateLiteralObject(node); | 1241 return ReduceJSCreateLiteralObject(node); |
| 1242 case IrOpcode::kJSCreateWithContext: |
| 1243 return ReduceJSCreateWithContext(node); |
| 1244 case IrOpcode::kJSCreateBlockContext: |
| 1245 return ReduceJSCreateBlockContext(node); |
1114 default: | 1246 default: |
1115 break; | 1247 break; |
1116 } | 1248 } |
1117 return NoChange(); | 1249 return NoChange(); |
1118 } | 1250 } |
1119 | 1251 |
1120 | 1252 |
1121 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { | 1253 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { |
1122 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); | 1254 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); |
1123 // Avoid inserting too many eager ToNumber() operations. | 1255 // Avoid inserting too many eager ToNumber() operations. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 } | 1310 } |
1179 | 1311 |
1180 | 1312 |
1181 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1313 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1182 return jsgraph()->machine(); | 1314 return jsgraph()->machine(); |
1183 } | 1315 } |
1184 | 1316 |
1185 } // namespace compiler | 1317 } // namespace compiler |
1186 } // namespace internal | 1318 } // namespace internal |
1187 } // namespace v8 | 1319 } // namespace v8 |
OLD | NEW |