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/compiler/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
6 #include "src/compiler/js-graph.h" | 6 #include "src/compiler/js-graph.h" |
7 #include "src/compiler/js-typed-lowering.h" | 7 #include "src/compiler/js-typed-lowering.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 #include "src/compiler/operator-properties.h" | 10 #include "src/compiler/operator-properties.h" |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 // Avoid introducing too many eager ToString() operations. | 204 // Avoid introducing too many eager ToString() operations. |
205 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 205 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
206 if (reduced.Changed()) return reduced.replacement(); | 206 if (reduced.Changed()) return reduced.replacement(); |
207 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), | 207 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), |
208 effect(), control()); | 208 effect(), control()); |
209 update_effect(n); | 209 update_effect(n); |
210 return n; | 210 return n; |
211 } | 211 } |
212 | 212 |
213 Node* CreateFrameStateForLeftInput(Node* frame_state) { | 213 Node* CreateFrameStateForLeftInput(Node* frame_state) { |
214 if (!FLAG_turbo_deoptimization) return nullptr; | |
215 | |
216 FrameStateCallInfo state_info = | 214 FrameStateCallInfo state_info = |
217 OpParameter<FrameStateCallInfo>(frame_state); | 215 OpParameter<FrameStateCallInfo>(frame_state); |
| 216 |
| 217 if (state_info.bailout_id() == BailoutId::None()) { |
| 218 // Dummy frame state => just leave it as is. |
| 219 return frame_state; |
| 220 } |
| 221 |
218 // If the frame state is already the right one, just return it. | 222 // If the frame state is already the right one, just return it. |
219 if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt && | 223 if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt && |
220 state_info.state_combine().GetOffsetToPokeAt() == 1) { | 224 state_info.state_combine().GetOffsetToPokeAt() == 1) { |
221 return frame_state; | 225 return frame_state; |
222 } | 226 } |
223 | 227 |
224 // Here, we smash the result of the conversion into the slot just below | 228 // Here, we smash the result of the conversion into the slot just below |
225 // the stack top. This is the slot that full code uses to store the | 229 // the stack top. This is the slot that full code uses to store the |
226 // left operand. | 230 // left operand. |
227 const Operator* op = jsgraph()->common()->FrameState( | 231 const Operator* op = jsgraph()->common()->FrameState( |
228 state_info.type(), state_info.bailout_id(), | 232 state_info.type(), state_info.bailout_id(), |
229 OutputFrameStateCombine::PokeAt(1)); | 233 OutputFrameStateCombine::PokeAt(1)); |
230 | 234 |
231 return graph()->NewNode(op, frame_state->InputAt(0), | 235 return graph()->NewNode(op, frame_state->InputAt(0), |
232 frame_state->InputAt(1), frame_state->InputAt(2), | 236 frame_state->InputAt(1), frame_state->InputAt(2), |
233 frame_state->InputAt(3), frame_state->InputAt(4)); | 237 frame_state->InputAt(3), frame_state->InputAt(4)); |
234 } | 238 } |
235 | 239 |
236 Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) { | 240 Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) { |
237 if (!FLAG_turbo_deoptimization) return nullptr; | |
238 | |
239 FrameStateCallInfo state_info = | 241 FrameStateCallInfo state_info = |
240 OpParameter<FrameStateCallInfo>(frame_state); | 242 OpParameter<FrameStateCallInfo>(frame_state); |
241 | 243 |
242 if (state_info.bailout_id() == BailoutId::None()) { | 244 if (state_info.bailout_id() == BailoutId::None()) { |
243 // Dummy frame state => just leave it as is. | 245 // Dummy frame state => just leave it as is. |
244 return frame_state; | 246 return frame_state; |
245 } | 247 } |
246 | 248 |
247 // Create a frame state that stores the result of the operation to the | 249 // Create a frame state that stores the result of the operation to the |
248 // top of the stack (i.e., the slot used for the right operand). | 250 // top of the stack (i.e., the slot used for the right operand). |
(...skipping 23 matching lines...) Expand all Loading... |
272 frame_state->InputAt(3), frame_state->InputAt(4)); | 274 frame_state->InputAt(3), frame_state->InputAt(4)); |
273 } | 275 } |
274 | 276 |
275 Node* ConvertPrimitiveToNumber(Node* node) { | 277 Node* ConvertPrimitiveToNumber(Node* node) { |
276 return lowering_->ConvertPrimitiveToNumber(node); | 278 return lowering_->ConvertPrimitiveToNumber(node); |
277 } | 279 } |
278 | 280 |
279 Node* ConvertToNumber(Node* node, Node* frame_state) { | 281 Node* ConvertToNumber(Node* node, Node* frame_state) { |
280 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { | 282 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { |
281 return ConvertPrimitiveToNumber(node); | 283 return ConvertPrimitiveToNumber(node); |
282 } else if (!FLAG_turbo_deoptimization) { | |
283 // We cannot use ConvertToPrimitiveNumber here because we need context | |
284 // for converting general values. | |
285 Node* const n = graph()->NewNode(javascript()->ToNumber(), node, | |
286 context(), effect(), control()); | |
287 update_effect(n); | |
288 return n; | |
289 } else { | 284 } else { |
290 Node* const n = | 285 Node* const n = |
291 graph()->NewNode(javascript()->ToNumber(), node, context(), | 286 graph()->NewNode(javascript()->ToNumber(), node, context(), |
292 frame_state, effect(), control()); | 287 frame_state, effect(), control()); |
293 update_effect(n); | 288 update_effect(n); |
294 return n; | 289 return n; |
295 } | 290 } |
296 } | 291 } |
297 | 292 |
298 Node* ConvertToUI32(Node* node, Signedness signedness) { | 293 Node* ConvertToUI32(Node* node, Signedness signedness) { |
(...skipping 19 matching lines...) Expand all Loading... |
318 | 313 |
319 | 314 |
320 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 315 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
321 JSBinopReduction r(this, node); | 316 JSBinopReduction r(this, node); |
322 if (r.BothInputsAre(Type::Number())) { | 317 if (r.BothInputsAre(Type::Number())) { |
323 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 318 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
324 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 319 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
325 } | 320 } |
326 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { | 321 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { |
327 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 322 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
328 Node* frame_state = FLAG_turbo_deoptimization | 323 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
329 ? NodeProperties::GetFrameStateInput(node, 1) | |
330 : nullptr; | |
331 r.ConvertInputsToNumber(frame_state); | 324 r.ConvertInputsToNumber(frame_state); |
332 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 325 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
333 } | 326 } |
334 #if 0 | 327 #if 0 |
335 // TODO(turbofan): Lowering of StringAdd is disabled for now because: | 328 // TODO(turbofan): Lowering of StringAdd is disabled for now because: |
336 // a) The inserted ToString operation screws up valueOf vs. toString order. | 329 // a) The inserted ToString operation screws up valueOf vs. toString order. |
337 // b) Deoptimization at ToString doesn't have corresponding bailout id. | 330 // b) Deoptimization at ToString doesn't have corresponding bailout id. |
338 // c) Our current StringAddStub is actually non-pure and requires context. | 331 // c) Our current StringAddStub is actually non-pure and requires context. |
339 if (r.OneInputIs(Type::String())) { | 332 if (r.OneInputIs(Type::String())) { |
340 // JSAdd(x:string, y:string) => StringAdd(x, y) | 333 // JSAdd(x:string, y:string) => StringAdd(x, y) |
341 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) | 334 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) |
342 // JSAdd(x, y:string) => StringAdd(ToString(x), y) | 335 // JSAdd(x, y:string) => StringAdd(ToString(x), y) |
343 r.ConvertInputsToString(); | 336 r.ConvertInputsToString(); |
344 return r.ChangeToPureOperator(simplified()->StringAdd()); | 337 return r.ChangeToPureOperator(simplified()->StringAdd()); |
345 } | 338 } |
346 #endif | 339 #endif |
347 return NoChange(); | 340 return NoChange(); |
348 } | 341 } |
349 | 342 |
350 | 343 |
351 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, | 344 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
352 const Operator* numberOp) { | 345 const Operator* numberOp) { |
353 JSBinopReduction r(this, node); | 346 JSBinopReduction r(this, node); |
354 Node* frame_state = FLAG_turbo_deoptimization | 347 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
355 ? NodeProperties::GetFrameStateInput(node, 1) | |
356 : nullptr; | |
357 r.ConvertInputsToNumber(frame_state); | 348 r.ConvertInputsToNumber(frame_state); |
358 return r.ChangeToPureOperator(numberOp, Type::Number()); | 349 return r.ChangeToPureOperator(numberOp, Type::Number()); |
359 } | 350 } |
360 | 351 |
361 | 352 |
362 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { | 353 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { |
363 JSBinopReduction r(this, node); | 354 JSBinopReduction r(this, node); |
364 Node* frame_state = FLAG_turbo_deoptimization | 355 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
365 ? NodeProperties::GetFrameStateInput(node, 1) | |
366 : nullptr; | |
367 r.ConvertInputsToNumber(frame_state); | 356 r.ConvertInputsToNumber(frame_state); |
368 r.ConvertInputsToUI32(kSigned, kSigned); | 357 r.ConvertInputsToUI32(kSigned, kSigned); |
369 return r.ChangeToPureOperator(intOp, Type::Integral32()); | 358 return r.ChangeToPureOperator(intOp, Type::Integral32()); |
370 } | 359 } |
371 | 360 |
372 | 361 |
373 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, | 362 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, |
374 Signedness left_signedness, | 363 Signedness left_signedness, |
375 const Operator* shift_op) { | 364 const Operator* shift_op) { |
376 JSBinopReduction r(this, node); | 365 JSBinopReduction r(this, node); |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 if (NodeProperties::GetContextInput(node) != | 682 if (NodeProperties::GetContextInput(node) != |
694 jsgraph()->NoContextConstant() || | 683 jsgraph()->NoContextConstant() || |
695 NodeProperties::GetEffectInput(node) != graph()->start() || | 684 NodeProperties::GetEffectInput(node) != graph()->start() || |
696 NodeProperties::GetControlInput(node) != graph()->start()) { | 685 NodeProperties::GetControlInput(node) != graph()->start()) { |
697 // JSToNumber(x:plain-primitive,context,effect,control) | 686 // JSToNumber(x:plain-primitive,context,effect,control) |
698 // => JSToNumber(x,no-context,start,start) | 687 // => JSToNumber(x,no-context,start,start) |
699 RelaxEffectsAndControls(node); | 688 RelaxEffectsAndControls(node); |
700 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); | 689 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); |
701 NodeProperties::ReplaceControlInput(node, graph()->start()); | 690 NodeProperties::ReplaceControlInput(node, graph()->start()); |
702 NodeProperties::ReplaceEffectInput(node, graph()->start()); | 691 NodeProperties::ReplaceEffectInput(node, graph()->start()); |
703 if (FLAG_turbo_deoptimization) { | 692 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
704 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 693 NodeProperties::ReplaceFrameStateInput(node, 0, |
705 NodeProperties::ReplaceFrameStateInput(node, 0, | 694 jsgraph()->EmptyFrameState()); |
706 jsgraph()->EmptyFrameState()); | |
707 } | |
708 return Changed(node); | 695 return Changed(node); |
709 } | 696 } |
710 } | 697 } |
711 return NoChange(); | 698 return NoChange(); |
712 } | 699 } |
713 | 700 |
714 | 701 |
715 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 702 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
716 if (input->opcode() == IrOpcode::kJSToString) { | 703 if (input->opcode() == IrOpcode::kJSToString) { |
717 // Recursively try to reduce the input first. | 704 // Recursively try to reduce the input first. |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 Node* length = jsgraph()->Constant(byte_length); | 821 Node* length = jsgraph()->Constant(byte_length); |
835 Node* context = NodeProperties::GetContextInput(node); | 822 Node* context = NodeProperties::GetContextInput(node); |
836 Node* effect = NodeProperties::GetEffectInput(node); | 823 Node* effect = NodeProperties::GetEffectInput(node); |
837 Node* control = NodeProperties::GetControlInput(node); | 824 Node* control = NodeProperties::GetControlInput(node); |
838 // Convert to a number first. | 825 // Convert to a number first. |
839 if (!value_type->Is(Type::Number())) { | 826 if (!value_type->Is(Type::Number())) { |
840 Reduction number_reduction = ReduceJSToNumberInput(value); | 827 Reduction number_reduction = ReduceJSToNumberInput(value); |
841 if (number_reduction.Changed()) { | 828 if (number_reduction.Changed()) { |
842 value = number_reduction.replacement(); | 829 value = number_reduction.replacement(); |
843 } else { | 830 } else { |
844 DCHECK(FLAG_turbo_deoptimization == | 831 Node* frame_state_for_to_number = |
845 (OperatorProperties::GetFrameStateInputCount( | 832 NodeProperties::GetFrameStateInput(node, 1); |
846 javascript()->ToNumber()) == 1)); | 833 value = effect = |
847 if (FLAG_turbo_deoptimization) { | 834 graph()->NewNode(javascript()->ToNumber(), value, context, |
848 Node* frame_state_for_to_number = | 835 frame_state_for_to_number, effect, control); |
849 NodeProperties::GetFrameStateInput(node, 1); | |
850 value = effect = | |
851 graph()->NewNode(javascript()->ToNumber(), value, context, | |
852 frame_state_for_to_number, effect, control); | |
853 } else { | |
854 value = effect = graph()->NewNode(javascript()->ToNumber(), value, | |
855 context, effect, control); | |
856 } | |
857 } | 836 } |
858 } | 837 } |
859 // For integer-typed arrays, convert to the integer type. | 838 // For integer-typed arrays, convert to the integer type. |
860 if (TypeOf(access.machine_type()) == kTypeInt32 && | 839 if (TypeOf(access.machine_type()) == kTypeInt32 && |
861 !value_type->Is(Type::Signed32())) { | 840 !value_type->Is(Type::Signed32())) { |
862 value = graph()->NewNode(simplified()->NumberToInt32(), value); | 841 value = graph()->NewNode(simplified()->NumberToInt32(), value); |
863 } else if (TypeOf(access.machine_type()) == kTypeUint32 && | 842 } else if (TypeOf(access.machine_type()) == kTypeUint32 && |
864 !value_type->Is(Type::Unsigned32())) { | 843 !value_type->Is(Type::Unsigned32())) { |
865 value = graph()->NewNode(simplified()->NumberToUint32(), value); | 844 value = graph()->NewNode(simplified()->NumberToUint32(), value); |
866 } | 845 } |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 return NoChange(); | 1008 return NoChange(); |
1030 } | 1009 } |
1031 | 1010 |
1032 | 1011 |
1033 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { | 1012 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { |
1034 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); | 1013 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); |
1035 // Avoid inserting too many eager ToNumber() operations. | 1014 // Avoid inserting too many eager ToNumber() operations. |
1036 Reduction const reduction = ReduceJSToNumberInput(input); | 1015 Reduction const reduction = ReduceJSToNumberInput(input); |
1037 if (reduction.Changed()) return reduction.replacement(); | 1016 if (reduction.Changed()) return reduction.replacement(); |
1038 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. | 1017 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. |
1039 Node* const conversion = | 1018 Node* const conversion = graph()->NewNode( |
1040 FLAG_turbo_deoptimization | 1019 javascript()->ToNumber(), input, jsgraph()->NoContextConstant(), |
1041 ? graph()->NewNode(javascript()->ToNumber(), input, | 1020 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); |
1042 jsgraph()->NoContextConstant(), | |
1043 jsgraph()->EmptyFrameState(), graph()->start(), | |
1044 graph()->start()) | |
1045 : graph()->NewNode(javascript()->ToNumber(), input, | |
1046 jsgraph()->NoContextConstant(), graph()->start(), | |
1047 graph()->start()); | |
1048 InsertConversion(conversion); | 1021 InsertConversion(conversion); |
1049 return conversion; | 1022 return conversion; |
1050 } | 1023 } |
1051 | 1024 |
1052 | 1025 |
1053 template <IrOpcode::Value kOpcode> | 1026 template <IrOpcode::Value kOpcode> |
1054 Node* JSTypedLowering::FindConversion(Node* input) { | 1027 Node* JSTypedLowering::FindConversion(Node* input) { |
1055 size_t const input_id = input->id(); | 1028 size_t const input_id = input->id(); |
1056 if (input_id < conversions_.size()) { | 1029 if (input_id < conversions_.size()) { |
1057 Node* const conversion = conversions_[input_id]; | 1030 Node* const conversion = conversions_[input_id]; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 } | 1069 } |
1097 | 1070 |
1098 | 1071 |
1099 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1072 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1100 return jsgraph()->machine(); | 1073 return jsgraph()->machine(); |
1101 } | 1074 } |
1102 | 1075 |
1103 } // namespace compiler | 1076 } // namespace compiler |
1104 } // namespace internal | 1077 } // namespace internal |
1105 } // namespace v8 | 1078 } // namespace v8 |
OLD | NEW |