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 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1002 node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(flags)); | 1057 node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(flags)); |
1003 node->InsertInput(graph()->zone(), 0, stub_code); | 1058 node->InsertInput(graph()->zone(), 0, stub_code); |
1004 node->set_op(new_op); | 1059 node->set_op(new_op); |
1005 return Changed(node); | 1060 return Changed(node); |
1006 } | 1061 } |
1007 | 1062 |
1008 return NoChange(); | 1063 return NoChange(); |
1009 } | 1064 } |
1010 | 1065 |
1011 | 1066 |
1067 Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { | |
1068 DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode()); | |
1069 Node* const input = NodeProperties::GetValueInput(node, 0); | |
1070 Type* input_type = NodeProperties::GetBounds(input).upper; | |
1071 if (FLAG_turbo_allocate && input_type->Is(Type::Receiver())) { | |
1072 // JSCreateWithContext(o:receiver, f) | |
1073 Node* const effect = NodeProperties::GetEffectInput(node); | |
1074 Node* const control = NodeProperties::GetControlInput(node); | |
1075 Node* const closure = NodeProperties::GetValueInput(node, 1); | |
1076 Node* const context = NodeProperties::GetContextInput(node); | |
1077 Node* const load = graph()->NewNode( | |
1078 simplified()->LoadField( | |
1079 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | |
1080 context, effect, control); | |
1081 AllocationBuilder a(jsgraph(), simplified(), effect, control); | |
1082 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | |
1083 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); | |
1084 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | |
1085 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | |
1086 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); | |
1087 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | |
1088 // TODO(mstarzinger): This is weird! Make kFinish not require this. | |
Benedikt Meurer
2015/04/28 08:24:23
Hm, I think Finish is fine, the problem seems to b
Michael Starzinger
2015/04/30 07:53:51
Done. Rephrased the TODO.
| |
1089 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); | |
1090 NodeProperties::ReplaceWithValue(node, node, a.effect()); | |
1091 node->ReplaceInput(0, a.allocation()); | |
1092 node->ReplaceInput(1, a.effect()); | |
1093 node->set_op(common()->Finish(1)); | |
1094 node->TrimInputCount(2); | |
1095 return Changed(node); | |
1096 } | |
1097 return NoChange(); | |
1098 } | |
1099 | |
1100 | |
1101 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { | |
1102 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); | |
1103 Node* const input = NodeProperties::GetValueInput(node, 0); | |
1104 HeapObjectMatcher<ScopeInfo> minput(input); | |
1105 DCHECK(minput.HasValue()); // TODO(mstarzinger): Make ScopeInfo static. | |
1106 int context_length = minput.Value().handle()->ContextLength(); | |
1107 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { | |
1108 // JSCreateBlockContext(s:scope[length < limit], f) | |
1109 Node* const effect = NodeProperties::GetEffectInput(node); | |
1110 Node* const control = NodeProperties::GetControlInput(node); | |
1111 Node* const closure = NodeProperties::GetValueInput(node, 1); | |
1112 Node* const context = NodeProperties::GetContextInput(node); | |
1113 Node* const load = graph()->NewNode( | |
1114 simplified()->LoadField( | |
1115 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | |
1116 context, effect, control); | |
1117 AllocationBuilder a(jsgraph(), simplified(), effect, control); | |
1118 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | |
1119 a.AllocateArray(context_length, factory()->block_context_map()); | |
1120 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | |
1121 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | |
1122 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); | |
1123 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | |
1124 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | |
1125 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); | |
1126 } | |
1127 // TODO(mstarzinger): This is weird! Make kFinish not require this. | |
Benedikt Meurer
2015/04/28 08:24:23
Hm, I think Finish is fine, the problem seems to b
Michael Starzinger
2015/04/30 07:53:51
Likewise.
| |
1128 NodeProperties::SetBounds(a.allocation(), NodeProperties::GetBounds(node)); | |
1129 NodeProperties::ReplaceWithValue(node, node, a.effect()); | |
1130 node->ReplaceInput(0, a.allocation()); | |
1131 node->ReplaceInput(1, a.effect()); | |
1132 node->set_op(common()->Finish(1)); | |
1133 node->TrimInputCount(2); | |
1134 return Changed(node); | |
1135 } | |
1136 return NoChange(); | |
1137 } | |
1138 | |
1139 | |
1012 Reduction JSTypedLowering::Reduce(Node* node) { | 1140 Reduction JSTypedLowering::Reduce(Node* node) { |
1013 // Check if the output type is a singleton. In that case we already know the | 1141 // Check if the output type is a singleton. In that case we already know the |
1014 // result value and can simply replace the node if it's eliminable. | 1142 // result value and can simply replace the node if it's eliminable. |
1015 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && | 1143 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && |
1016 node->op()->HasProperty(Operator::kEliminatable)) { | 1144 node->op()->HasProperty(Operator::kEliminatable)) { |
1017 Type* upper = NodeProperties::GetBounds(node).upper; | 1145 Type* upper = NodeProperties::GetBounds(node).upper; |
1018 if (upper->IsConstant()) { | 1146 if (upper->IsConstant()) { |
1019 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value()); | 1147 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value()); |
1020 NodeProperties::ReplaceWithValue(node, replacement); | 1148 NodeProperties::ReplaceWithValue(node, replacement); |
1021 return Changed(replacement); | 1149 return Changed(replacement); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1094 case IrOpcode::kJSLoadContext: | 1222 case IrOpcode::kJSLoadContext: |
1095 return ReduceJSLoadContext(node); | 1223 return ReduceJSLoadContext(node); |
1096 case IrOpcode::kJSStoreContext: | 1224 case IrOpcode::kJSStoreContext: |
1097 return ReduceJSStoreContext(node); | 1225 return ReduceJSStoreContext(node); |
1098 case IrOpcode::kJSCreateClosure: | 1226 case IrOpcode::kJSCreateClosure: |
1099 return ReduceJSCreateClosure(node); | 1227 return ReduceJSCreateClosure(node); |
1100 case IrOpcode::kJSCreateLiteralArray: | 1228 case IrOpcode::kJSCreateLiteralArray: |
1101 return ReduceJSCreateLiteralArray(node); | 1229 return ReduceJSCreateLiteralArray(node); |
1102 case IrOpcode::kJSCreateLiteralObject: | 1230 case IrOpcode::kJSCreateLiteralObject: |
1103 return ReduceJSCreateLiteralObject(node); | 1231 return ReduceJSCreateLiteralObject(node); |
1232 case IrOpcode::kJSCreateWithContext: | |
1233 return ReduceJSCreateWithContext(node); | |
1234 case IrOpcode::kJSCreateBlockContext: | |
1235 return ReduceJSCreateBlockContext(node); | |
1104 default: | 1236 default: |
1105 break; | 1237 break; |
1106 } | 1238 } |
1107 return NoChange(); | 1239 return NoChange(); |
1108 } | 1240 } |
1109 | 1241 |
1110 | 1242 |
1111 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { | 1243 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { |
1112 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); | 1244 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); |
1113 // Avoid inserting too many eager ToNumber() operations. | 1245 // Avoid inserting too many eager ToNumber() operations. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1168 } | 1300 } |
1169 | 1301 |
1170 | 1302 |
1171 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1303 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1172 return jsgraph()->machine(); | 1304 return jsgraph()->machine(); |
1173 } | 1305 } |
1174 | 1306 |
1175 } // namespace compiler | 1307 } // namespace compiler |
1176 } // namespace internal | 1308 } // namespace internal |
1177 } // namespace v8 | 1309 } // namespace v8 |
OLD | NEW |