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 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 |