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/compilation-dependencies.h" | 6 #include "src/compilation-dependencies.h" |
7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/js-typed-lowering.h" | 9 #include "src/compiler/js-typed-lowering.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 // functions for matching the types of inputs to an operation. | 24 // functions for matching the types of inputs to an operation. |
25 class JSBinopReduction final { | 25 class JSBinopReduction final { |
26 public: | 26 public: |
27 JSBinopReduction(JSTypedLowering* lowering, Node* node) | 27 JSBinopReduction(JSTypedLowering* lowering, Node* node) |
28 : lowering_(lowering), node_(node) {} | 28 : lowering_(lowering), node_(node) {} |
29 | 29 |
30 BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() { | 30 BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() { |
31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
32 DCHECK_NE(0, node_->op()->ControlOutputCount()); | 32 DCHECK_NE(0, node_->op()->ControlOutputCount()); |
33 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 33 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
34 DCHECK_LE(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 34 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); | 35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); |
36 BinaryOperationHints::Hint combined = hints.combined(); | 36 BinaryOperationHints::Hint combined = hints.combined(); |
37 if (combined == BinaryOperationHints::kSignedSmall || | 37 if (combined == BinaryOperationHints::kSignedSmall || |
38 combined == BinaryOperationHints::kSigned32 || | 38 combined == BinaryOperationHints::kSigned32 || |
39 combined == BinaryOperationHints::kNumberOrOddball) { | 39 combined == BinaryOperationHints::kNumberOrOddball) { |
40 return combined; | 40 return combined; |
41 } | 41 } |
42 } | 42 } |
43 return BinaryOperationHints::kAny; | 43 return BinaryOperationHints::kAny; |
44 } | 44 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 144 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
145 DCHECK_EQ(1, op->ControlInputCount()); | 145 DCHECK_EQ(1, op->ControlInputCount()); |
146 DCHECK_EQ(0, op->ControlOutputCount()); | 146 DCHECK_EQ(0, op->ControlOutputCount()); |
147 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); | 147 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); |
148 DCHECK_EQ(2, op->ValueInputCount()); | 148 DCHECK_EQ(2, op->ValueInputCount()); |
149 | 149 |
150 DCHECK_EQ(1, node_->op()->EffectInputCount()); | 150 DCHECK_EQ(1, node_->op()->EffectInputCount()); |
151 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 151 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
152 DCHECK_EQ(1, node_->op()->ControlInputCount()); | 152 DCHECK_EQ(1, node_->op()->ControlInputCount()); |
153 DCHECK_LT(1, node_->op()->ControlOutputCount()); | 153 DCHECK_LT(1, node_->op()->ControlOutputCount()); |
154 DCHECK_LE(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 154 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
155 DCHECK_EQ(2, node_->op()->ValueInputCount()); | 155 DCHECK_EQ(2, node_->op()->ValueInputCount()); |
156 | 156 |
157 // Reconnect the control output to bypass the IfSuccess node and | 157 // Reconnect the control output to bypass the IfSuccess node and |
158 // possibly disconnect from the IfException node. | 158 // possibly disconnect from the IfException node. |
159 for (Edge edge : node_->use_edges()) { | 159 for (Edge edge : node_->use_edges()) { |
160 Node* const user = edge.from(); | 160 Node* const user = edge.from(); |
161 DCHECK(!user->IsDead()); | 161 DCHECK(!user->IsDead()); |
162 if (NodeProperties::IsControlEdge(edge)) { | 162 if (NodeProperties::IsControlEdge(edge)) { |
163 if (user->opcode() == IrOpcode::kIfSuccess) { | 163 if (user->opcode() == IrOpcode::kIfSuccess) { |
164 user->ReplaceUses(NodeProperties::GetControlInput(node_)); | 164 user->ReplaceUses(NodeProperties::GetControlInput(node_)); |
165 user->Kill(); | 165 user->Kill(); |
166 } else { | 166 } else { |
167 DCHECK_EQ(user->opcode(), IrOpcode::kIfException); | 167 DCHECK_EQ(user->opcode(), IrOpcode::kIfException); |
168 edge.UpdateTo(jsgraph()->Dead()); | 168 edge.UpdateTo(jsgraph()->Dead()); |
169 } | 169 } |
170 } | 170 } |
171 } | 171 } |
172 | 172 |
173 // Remove both bailout frame states and the context. | 173 // Remove the frame state and the context. |
174 if (OperatorProperties::GetFrameStateInputCount(node_->op()) == 2) { | |
175 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_) + 1); | |
176 } | |
177 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); | 174 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); |
178 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); | 175 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); |
179 | 176 |
180 NodeProperties::ChangeOp(node_, op); | 177 NodeProperties::ChangeOp(node_, op); |
181 | 178 |
182 // Update the type to number. | 179 // Update the type to number. |
183 Type* node_type = NodeProperties::GetType(node_); | 180 Type* node_type = NodeProperties::GetType(node_); |
184 NodeProperties::SetType(node_, | 181 NodeProperties::SetType(node_, |
185 Type::Intersect(node_type, upper_bound, zone())); | 182 Type::Intersect(node_type, upper_bound, zone())); |
186 | 183 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 JSGraph* jsgraph() { return lowering_->jsgraph(); } | 217 JSGraph* jsgraph() { return lowering_->jsgraph(); } |
221 JSOperatorBuilder* javascript() { return lowering_->javascript(); } | 218 JSOperatorBuilder* javascript() { return lowering_->javascript(); } |
222 CommonOperatorBuilder* common() { return jsgraph()->common(); } | 219 CommonOperatorBuilder* common() { return jsgraph()->common(); } |
223 Zone* zone() const { return graph()->zone(); } | 220 Zone* zone() const { return graph()->zone(); } |
224 | 221 |
225 private: | 222 private: |
226 JSTypedLowering* lowering_; // The containing lowering instance. | 223 JSTypedLowering* lowering_; // The containing lowering instance. |
227 Node* node_; // The original node. | 224 Node* node_; // The original node. |
228 | 225 |
229 Node* CreateFrameStateForLeftInput() { | 226 Node* CreateFrameStateForLeftInput() { |
230 if (OperatorProperties::GetFrameStateInputCount(node_->op()) < 2) { | 227 // Deoptimization is disabled => return dummy frame state instead. |
231 // Deoptimization is disabled => return dummy frame state instead. | 228 Node* dummy_state = NodeProperties::GetFrameStateInput(node_); |
232 Node* dummy_state = NodeProperties::GetFrameStateInput(node_, 0); | 229 DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone()); |
233 DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone()); | 230 return dummy_state; |
234 return dummy_state; | |
235 } | |
236 | |
237 Node* frame_state = NodeProperties::GetFrameStateInput(node_, 1); | |
238 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | |
239 | |
240 if (state_info.bailout_id() == BailoutId::None()) { | |
241 // Dummy frame state => just leave it as is. | |
242 return frame_state; | |
243 } | |
244 | |
245 // If the frame state is already the right one, just return it. | |
246 if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt && | |
247 state_info.state_combine().GetOffsetToPokeAt() == 1) { | |
248 return frame_state; | |
249 } | |
250 | |
251 // Here, we smash the result of the conversion into the slot just below | |
252 // the stack top. This is the slot that full code uses to store the | |
253 // left operand. | |
254 const Operator* op = jsgraph()->common()->FrameState( | |
255 state_info.bailout_id(), OutputFrameStateCombine::PokeAt(1), | |
256 state_info.function_info()); | |
257 | |
258 return graph()->NewNode(op, | |
259 frame_state->InputAt(kFrameStateParametersInput), | |
260 frame_state->InputAt(kFrameStateLocalsInput), | |
261 frame_state->InputAt(kFrameStateStackInput), | |
262 frame_state->InputAt(kFrameStateContextInput), | |
263 frame_state->InputAt(kFrameStateFunctionInput), | |
264 frame_state->InputAt(kFrameStateOuterStateInput)); | |
265 } | 231 } |
266 | 232 |
267 Node* CreateFrameStateForRightInput(Node* converted_left) { | 233 Node* CreateFrameStateForRightInput(Node* converted_left) { |
268 if (OperatorProperties::GetFrameStateInputCount(node_->op()) < 2) { | 234 // Deoptimization is disabled => return dummy frame state instead. |
269 // Deoptimization is disabled => return dummy frame state instead. | 235 Node* dummy_state = NodeProperties::GetFrameStateInput(node_); |
270 Node* dummy_state = NodeProperties::GetFrameStateInput(node_, 0); | 236 DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone()); |
271 DCHECK(OpParameter<FrameStateInfo>(dummy_state).bailout_id().IsNone()); | 237 return dummy_state; |
272 return dummy_state; | |
273 } | |
274 | |
275 Node* frame_state = NodeProperties::GetFrameStateInput(node_, 1); | |
276 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | |
277 | |
278 if (state_info.bailout_id() == BailoutId::None()) { | |
279 // Dummy frame state => just leave it as is. | |
280 return frame_state; | |
281 } | |
282 | |
283 // Create a frame state that stores the result of the operation to the | |
284 // top of the stack (i.e., the slot used for the right operand). | |
285 const Operator* op = jsgraph()->common()->FrameState( | |
286 state_info.bailout_id(), OutputFrameStateCombine::PokeAt(0), | |
287 state_info.function_info()); | |
288 | |
289 // Change the left operand {converted_left} on the expression stack. | |
290 Node* stack = frame_state->InputAt(2); | |
291 DCHECK_EQ(stack->opcode(), IrOpcode::kStateValues); | |
292 DCHECK_GE(stack->InputCount(), 2); | |
293 | |
294 // TODO(jarin) Allocate in a local zone or a reusable buffer. | |
295 NodeVector new_values(stack->InputCount(), zone()); | |
296 for (int i = 0; i < stack->InputCount(); i++) { | |
297 if (i == stack->InputCount() - 2) { | |
298 new_values[i] = converted_left; | |
299 } else { | |
300 new_values[i] = stack->InputAt(i); | |
301 } | |
302 } | |
303 Node* new_stack = | |
304 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front()); | |
305 | |
306 return graph()->NewNode( | |
307 op, frame_state->InputAt(kFrameStateParametersInput), | |
308 frame_state->InputAt(kFrameStateLocalsInput), new_stack, | |
309 frame_state->InputAt(kFrameStateContextInput), | |
310 frame_state->InputAt(kFrameStateFunctionInput), | |
311 frame_state->InputAt(kFrameStateOuterStateInput)); | |
312 } | 238 } |
313 | 239 |
314 Node* ConvertPlainPrimitiveToNumber(Node* node) { | 240 Node* ConvertPlainPrimitiveToNumber(Node* node) { |
315 DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive())); | 241 DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive())); |
316 // Avoid inserting too many eager ToNumber() operations. | 242 // Avoid inserting too many eager ToNumber() operations. |
317 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); | 243 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); |
318 if (reduction.Changed()) return reduction.replacement(); | 244 if (reduction.Changed()) return reduction.replacement(); |
319 if (NodeProperties::GetType(node)->Is(Type::Number())) { | 245 if (NodeProperties::GetType(node)->Is(Type::Number())) { |
320 return node; | 246 return node; |
321 } | 247 } |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 } | 953 } |
1028 return NoChange(); | 954 return NoChange(); |
1029 } | 955 } |
1030 | 956 |
1031 | 957 |
1032 Reduction JSTypedLowering::ReduceJSToObject(Node* node) { | 958 Reduction JSTypedLowering::ReduceJSToObject(Node* node) { |
1033 DCHECK_EQ(IrOpcode::kJSToObject, node->opcode()); | 959 DCHECK_EQ(IrOpcode::kJSToObject, node->opcode()); |
1034 Node* receiver = NodeProperties::GetValueInput(node, 0); | 960 Node* receiver = NodeProperties::GetValueInput(node, 0); |
1035 Type* receiver_type = NodeProperties::GetType(receiver); | 961 Type* receiver_type = NodeProperties::GetType(receiver); |
1036 Node* context = NodeProperties::GetContextInput(node); | 962 Node* context = NodeProperties::GetContextInput(node); |
1037 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | 963 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
1038 Node* effect = NodeProperties::GetEffectInput(node); | 964 Node* effect = NodeProperties::GetEffectInput(node); |
1039 Node* control = NodeProperties::GetControlInput(node); | 965 Node* control = NodeProperties::GetControlInput(node); |
1040 if (receiver_type->Is(Type::Receiver())) { | 966 if (receiver_type->Is(Type::Receiver())) { |
1041 ReplaceWithValue(node, receiver, effect, control); | 967 ReplaceWithValue(node, receiver, effect, control); |
1042 return Replace(receiver); | 968 return Replace(receiver); |
1043 } | 969 } |
1044 | 970 |
1045 // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks. | 971 // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks. |
1046 if (receiver_type->Maybe(Type::NullOrUndefined()) && | 972 if (receiver_type->Maybe(Type::NullOrUndefined()) && |
1047 NodeProperties::IsExceptionalCall(node)) { | 973 NodeProperties::IsExceptionalCall(node)) { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 } | 1155 } |
1230 } | 1156 } |
1231 } | 1157 } |
1232 return NoChange(); | 1158 return NoChange(); |
1233 } | 1159 } |
1234 | 1160 |
1235 | 1161 |
1236 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { | 1162 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { |
1237 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); | 1163 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); |
1238 Node* const context = NodeProperties::GetContextInput(node); | 1164 Node* const context = NodeProperties::GetContextInput(node); |
1239 Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0); | 1165 Node* const frame_state = NodeProperties::GetFrameStateInput(node); |
1240 | 1166 |
1241 // If deoptimization is disabled, we cannot optimize. | 1167 // If deoptimization is disabled, we cannot optimize. |
1242 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 1168 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
1243 | 1169 |
1244 // If we are in a try block, don't optimize since the runtime call | 1170 // If we are in a try block, don't optimize since the runtime call |
1245 // in the proxy case can throw. | 1171 // in the proxy case can throw. |
1246 if (NodeProperties::IsExceptionalCall(node)) return NoChange(); | 1172 if (NodeProperties::IsExceptionalCall(node)) return NoChange(); |
1247 | 1173 |
1248 JSBinopReduction r(this, node); | 1174 JSBinopReduction r(this, node); |
1249 Node* effect = r.effect(); | 1175 Node* effect = r.effect(); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 } | 1376 } |
1451 | 1377 |
1452 | 1378 |
1453 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) { | 1379 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) { |
1454 DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode()); | 1380 DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode()); |
1455 ConvertReceiverMode mode = ConvertReceiverModeOf(node->op()); | 1381 ConvertReceiverMode mode = ConvertReceiverModeOf(node->op()); |
1456 Node* receiver = NodeProperties::GetValueInput(node, 0); | 1382 Node* receiver = NodeProperties::GetValueInput(node, 0); |
1457 Type* receiver_type = NodeProperties::GetType(receiver); | 1383 Type* receiver_type = NodeProperties::GetType(receiver); |
1458 Node* context = NodeProperties::GetContextInput(node); | 1384 Node* context = NodeProperties::GetContextInput(node); |
1459 Type* context_type = NodeProperties::GetType(context); | 1385 Type* context_type = NodeProperties::GetType(context); |
1460 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | 1386 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
1461 Node* effect = NodeProperties::GetEffectInput(node); | 1387 Node* effect = NodeProperties::GetEffectInput(node); |
1462 Node* control = NodeProperties::GetControlInput(node); | 1388 Node* control = NodeProperties::GetControlInput(node); |
1463 if (!receiver_type->Is(Type::Receiver())) { | 1389 if (!receiver_type->Is(Type::Receiver())) { |
1464 if (receiver_type->Is(Type::NullOrUndefined()) || | 1390 if (receiver_type->Is(Type::NullOrUndefined()) || |
1465 mode == ConvertReceiverMode::kNullOrUndefined) { | 1391 mode == ConvertReceiverMode::kNullOrUndefined) { |
1466 if (context_type->IsConstant()) { | 1392 if (context_type->IsConstant()) { |
1467 Handle<JSObject> global_proxy( | 1393 Handle<JSObject> global_proxy( |
1468 Handle<Context>::cast(context_type->AsConstant()->Value()) | 1394 Handle<Context>::cast(context_type->AsConstant()->Value()) |
1469 ->global_proxy(), | 1395 ->global_proxy(), |
1470 isolate()); | 1396 isolate()); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1724 } | 1650 } |
1725 | 1651 |
1726 | 1652 |
1727 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) { | 1653 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) { |
1728 DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode()); | 1654 DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode()); |
1729 Node* receiver = NodeProperties::GetValueInput(node, 0); | 1655 Node* receiver = NodeProperties::GetValueInput(node, 0); |
1730 Node* cache_array = NodeProperties::GetValueInput(node, 1); | 1656 Node* cache_array = NodeProperties::GetValueInput(node, 1); |
1731 Node* cache_type = NodeProperties::GetValueInput(node, 2); | 1657 Node* cache_type = NodeProperties::GetValueInput(node, 2); |
1732 Node* index = NodeProperties::GetValueInput(node, 3); | 1658 Node* index = NodeProperties::GetValueInput(node, 3); |
1733 Node* context = NodeProperties::GetContextInput(node); | 1659 Node* context = NodeProperties::GetContextInput(node); |
1734 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | 1660 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
1735 Node* effect = NodeProperties::GetEffectInput(node); | 1661 Node* effect = NodeProperties::GetEffectInput(node); |
1736 Node* control = NodeProperties::GetControlInput(node); | 1662 Node* control = NodeProperties::GetControlInput(node); |
1737 | 1663 |
1738 // Load the next {key} from the {cache_array}. | 1664 // Load the next {key} from the {cache_array}. |
1739 Node* key = effect = graph()->NewNode( | 1665 Node* key = effect = graph()->NewNode( |
1740 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), | 1666 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), |
1741 cache_array, index, effect, control); | 1667 cache_array, index, effect, control); |
1742 | 1668 |
1743 // Load the map of the {receiver}. | 1669 // Load the map of the {receiver}. |
1744 Node* receiver_map = effect = | 1670 Node* receiver_map = effect = |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2170 } | 2096 } |
2171 | 2097 |
2172 | 2098 |
2173 CompilationDependencies* JSTypedLowering::dependencies() const { | 2099 CompilationDependencies* JSTypedLowering::dependencies() const { |
2174 return dependencies_; | 2100 return dependencies_; |
2175 } | 2101 } |
2176 | 2102 |
2177 } // namespace compiler | 2103 } // namespace compiler |
2178 } // namespace internal | 2104 } // namespace internal |
2179 } // namespace v8 | 2105 } // namespace v8 |
OLD | NEW |