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" |
11 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
13 #include "src/compiler/operator-properties.h" | 13 #include "src/compiler/operator-properties.h" |
14 #include "src/type-cache.h" | 14 #include "src/type-cache.h" |
15 #include "src/types.h" | 15 #include "src/types.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 namespace compiler { | 19 namespace compiler { |
20 | 20 |
21 // A helper class to simplify the process of reducing a single binop node with a | 21 // A helper class to simplify the process of reducing a single binop node with a |
22 // JSOperator. This class manages the rewriting of context, control, and effect | 22 // JSOperator. This class manages the rewriting of context, control, and effect |
23 // dependencies during lowering of a binop and contains numerous helper | 23 // dependencies during lowering of a binop and contains numerous helper |
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 void ConvertInputsToNumber(Node* frame_state) { | 30 void ConvertInputsToNumberOrUndefined(Node* frame_state) { |
31 // To convert the inputs to numbers, we have to provide frame states | 31 // To convert the inputs to numbers, we have to provide frame states |
32 // for lazy bailouts in the ToNumber conversions. | 32 // for lazy bailouts in the ToNumber conversions. |
33 // We use a little hack here: we take the frame state before the binary | 33 // We use a little hack here: we take the frame state before the binary |
34 // operation and use it to construct the frame states for the conversion | 34 // operation and use it to construct the frame states for the conversion |
35 // so that after the deoptimization, the binary operation IC gets | 35 // so that after the deoptimization, the binary operation IC gets |
36 // already converted values from full code. This way we are sure that we | 36 // already converted values from full code. This way we are sure that we |
37 // will not re-do any of the side effects. | 37 // will not re-do any of the side effects. |
38 | 38 |
39 Node* left_input = nullptr; | 39 Node* left_input = nullptr; |
40 Node* right_input = nullptr; | 40 Node* right_input = nullptr; |
41 bool left_is_primitive = left_type()->Is(Type::PlainPrimitive()); | 41 bool left_is_primitive = left_type()->Is(Type::PlainPrimitive()); |
42 bool right_is_primitive = right_type()->Is(Type::PlainPrimitive()); | 42 bool right_is_primitive = right_type()->Is(Type::PlainPrimitive()); |
43 bool handles_exception = NodeProperties::IsExceptionalCall(node_); | 43 bool handles_exception = NodeProperties::IsExceptionalCall(node_); |
44 | 44 |
45 if (!left_is_primitive && !right_is_primitive && handles_exception) { | 45 if (!left_is_primitive && !right_is_primitive && handles_exception) { |
46 ConvertBothInputsToNumber(&left_input, &right_input, frame_state); | 46 ConvertBothInputsToNumber(&left_input, &right_input, frame_state); |
47 } else { | 47 } else { |
48 left_input = left_is_primitive | 48 left_input = left_is_primitive |
49 ? ConvertPlainPrimitiveToNumber(left()) | 49 ? ConvertPlainPrimitiveToNumberOrUndefined(left()) |
50 : ConvertSingleInputToNumber( | 50 : ConvertSingleInputToNumber( |
51 left(), CreateFrameStateForLeftInput(frame_state)); | 51 left(), CreateFrameStateForLeftInput(frame_state)); |
52 right_input = right_is_primitive | 52 right_input = right_is_primitive |
53 ? ConvertPlainPrimitiveToNumber(right()) | 53 ? ConvertPlainPrimitiveToNumberOrUndefined(right()) |
54 : ConvertSingleInputToNumber( | 54 : ConvertSingleInputToNumber( |
55 right(), CreateFrameStateForRightInput( | 55 right(), CreateFrameStateForRightInput( |
56 frame_state, left_input)); | 56 frame_state, left_input)); |
57 } | 57 } |
58 | 58 |
59 node_->ReplaceInput(0, left_input); | 59 node_->ReplaceInput(0, left_input); |
60 node_->ReplaceInput(1, right_input); | 60 node_->ReplaceInput(1, right_input); |
61 } | 61 } |
62 | 62 |
63 void ConvertInputsToUI32(Signedness left_signedness, | 63 void ConvertInputsToUI32(Signedness left_signedness, |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front()); | 235 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front()); |
236 | 236 |
237 return graph()->NewNode( | 237 return graph()->NewNode( |
238 op, frame_state->InputAt(kFrameStateParametersInput), | 238 op, frame_state->InputAt(kFrameStateParametersInput), |
239 frame_state->InputAt(kFrameStateLocalsInput), new_stack, | 239 frame_state->InputAt(kFrameStateLocalsInput), new_stack, |
240 frame_state->InputAt(kFrameStateContextInput), | 240 frame_state->InputAt(kFrameStateContextInput), |
241 frame_state->InputAt(kFrameStateFunctionInput), | 241 frame_state->InputAt(kFrameStateFunctionInput), |
242 frame_state->InputAt(kFrameStateOuterStateInput)); | 242 frame_state->InputAt(kFrameStateOuterStateInput)); |
243 } | 243 } |
244 | 244 |
245 Node* ConvertPlainPrimitiveToNumber(Node* node) { | 245 Node* ConvertPlainPrimitiveToNumberOrUndefined(Node* node) { |
246 DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive())); | 246 DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive())); |
| 247 if (NodeProperties::GetType(node)->Is(Type::NumberOrUndefined())) { |
| 248 return node; |
| 249 } |
247 // Avoid inserting too many eager ToNumber() operations. | 250 // Avoid inserting too many eager ToNumber() operations. |
248 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); | 251 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); |
249 if (reduction.Changed()) return reduction.replacement(); | 252 if (reduction.Changed()) return reduction.replacement(); |
250 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. | 253 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. |
251 return graph()->NewNode( | 254 return graph()->NewNode( |
252 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(), | 255 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(), |
253 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); | 256 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); |
254 } | 257 } |
255 | 258 |
256 Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) { | 259 Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 double max = kMaxInt / (1 << k); | 357 double max = kMaxInt / (1 << k); |
355 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 358 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
356 } | 359 } |
357 } | 360 } |
358 | 361 |
359 | 362 |
360 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 363 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
361 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 364 if (flags() & kDisableBinaryOpReduction) return NoChange(); |
362 | 365 |
363 JSBinopReduction r(this, node); | 366 JSBinopReduction r(this, node); |
364 if (r.BothInputsAre(Type::Number())) { | 367 if (r.BothInputsAre(Type::NumberOrUndefined())) { |
365 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 368 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
366 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 369 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
367 } | 370 } |
368 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { | 371 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { |
369 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 372 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
370 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 373 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
371 r.ConvertInputsToNumber(frame_state); | 374 r.ConvertInputsToNumberOrUndefined(frame_state); |
372 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 375 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
373 } | 376 } |
374 if (r.BothInputsAre(Type::String())) { | 377 if (r.BothInputsAre(Type::String())) { |
375 // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y) | 378 // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y) |
376 Callable const callable = | 379 Callable const callable = |
377 CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); | 380 CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); |
378 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( | 381 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
379 isolate(), graph()->zone(), callable.descriptor(), 0, | 382 isolate(), graph()->zone(), callable.descriptor(), 0, |
380 CallDescriptor::kNeedsFrameState, node->op()->properties()); | 383 CallDescriptor::kNeedsFrameState, node->op()->properties()); |
381 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op())); | 384 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op())); |
(...skipping 19 matching lines...) Expand all Loading... |
401 return NoChange(); | 404 return NoChange(); |
402 } | 405 } |
403 | 406 |
404 | 407 |
405 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, | 408 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
406 const Operator* numberOp) { | 409 const Operator* numberOp) { |
407 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 410 if (flags() & kDisableBinaryOpReduction) return NoChange(); |
408 | 411 |
409 JSBinopReduction r(this, node); | 412 JSBinopReduction r(this, node); |
410 if (numberOp == simplified()->NumberModulus()) { | 413 if (numberOp == simplified()->NumberModulus()) { |
411 if (r.BothInputsAre(Type::Number())) { | 414 if (r.BothInputsAre(Type::NumberOrUndefined())) { |
412 return r.ChangeToPureOperator(numberOp, Type::Number()); | 415 return r.ChangeToPureOperator(numberOp, Type::Number()); |
413 } | 416 } |
414 return NoChange(); | 417 return NoChange(); |
415 } | 418 } |
416 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 419 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
417 r.ConvertInputsToNumber(frame_state); | 420 r.ConvertInputsToNumberOrUndefined(frame_state); |
418 return r.ChangeToPureOperator(numberOp, Type::Number()); | 421 return r.ChangeToPureOperator(numberOp, Type::Number()); |
419 } | 422 } |
420 | 423 |
421 | 424 |
422 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { | 425 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { |
423 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 426 if (flags() & kDisableBinaryOpReduction) return NoChange(); |
424 | 427 |
425 JSBinopReduction r(this, node); | 428 JSBinopReduction r(this, node); |
426 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 429 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
427 r.ConvertInputsToNumber(frame_state); | 430 r.ConvertInputsToNumberOrUndefined(frame_state); |
428 r.ConvertInputsToUI32(kSigned, kSigned); | 431 r.ConvertInputsToUI32(kSigned, kSigned); |
429 return r.ChangeToPureOperator(intOp, Type::Integral32()); | 432 return r.ChangeToPureOperator(intOp, Type::Integral32()); |
430 } | 433 } |
431 | 434 |
432 | 435 |
433 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, | 436 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, |
434 Signedness left_signedness, | 437 Signedness left_signedness, |
435 const Operator* shift_op) { | 438 const Operator* shift_op) { |
436 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 439 if (flags() & kDisableBinaryOpReduction) return NoChange(); |
437 | 440 |
438 JSBinopReduction r(this, node); | 441 JSBinopReduction r(this, node); |
439 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 442 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
440 r.ConvertInputsToNumber(frame_state); | 443 // TODO(jarin) FIX |
| 444 r.ConvertInputsToNumberOrUndefined(frame_state); |
441 r.ConvertInputsToUI32(left_signedness, kUnsigned); | 445 r.ConvertInputsToUI32(left_signedness, kUnsigned); |
442 return r.ChangeToPureOperator(shift_op); | 446 return r.ChangeToPureOperator(shift_op); |
443 } | 447 } |
444 | 448 |
445 | 449 |
446 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 450 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
447 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 451 if (flags() & kDisableBinaryOpReduction) return NoChange(); |
448 | 452 |
449 JSBinopReduction r(this, node); | 453 JSBinopReduction r(this, node); |
450 if (r.BothInputsAre(Type::String())) { | 454 if (r.BothInputsAre(Type::String())) { |
(...skipping 25 matching lines...) Expand all Loading... |
476 const Operator* less_than_or_equal; | 480 const Operator* less_than_or_equal; |
477 if (r.BothInputsAre(Type::Unsigned32())) { | 481 if (r.BothInputsAre(Type::Unsigned32())) { |
478 less_than = machine()->Uint32LessThan(); | 482 less_than = machine()->Uint32LessThan(); |
479 less_than_or_equal = machine()->Uint32LessThanOrEqual(); | 483 less_than_or_equal = machine()->Uint32LessThanOrEqual(); |
480 } else if (r.BothInputsAre(Type::Signed32())) { | 484 } else if (r.BothInputsAre(Type::Signed32())) { |
481 less_than = machine()->Int32LessThan(); | 485 less_than = machine()->Int32LessThan(); |
482 less_than_or_equal = machine()->Int32LessThanOrEqual(); | 486 less_than_or_equal = machine()->Int32LessThanOrEqual(); |
483 } else { | 487 } else { |
484 // TODO(turbofan): mixed signed/unsigned int32 comparisons. | 488 // TODO(turbofan): mixed signed/unsigned int32 comparisons. |
485 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 489 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
486 r.ConvertInputsToNumber(frame_state); | 490 // TODO(jarin) FIX |
| 491 r.ConvertInputsToNumberOrUndefined(frame_state); |
487 less_than = simplified()->NumberLessThan(); | 492 less_than = simplified()->NumberLessThan(); |
488 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 493 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
489 } | 494 } |
490 const Operator* comparison; | 495 const Operator* comparison; |
491 switch (node->opcode()) { | 496 switch (node->opcode()) { |
492 case IrOpcode::kJSLessThan: | 497 case IrOpcode::kJSLessThan: |
493 comparison = less_than; | 498 comparison = less_than; |
494 break; | 499 break; |
495 case IrOpcode::kJSGreaterThan: | 500 case IrOpcode::kJSGreaterThan: |
496 comparison = less_than; | 501 comparison = less_than; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 simplified()->ReferenceEqual(Type::Receiver()), invert); | 603 simplified()->ReferenceEqual(Type::Receiver()), invert); |
599 } | 604 } |
600 if (r.BothInputsAre(Type::Unique())) { | 605 if (r.BothInputsAre(Type::Unique())) { |
601 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()), | 606 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()), |
602 invert); | 607 invert); |
603 } | 608 } |
604 if (r.BothInputsAre(Type::String())) { | 609 if (r.BothInputsAre(Type::String())) { |
605 return r.ChangeToStringComparisonOperator(simplified()->StringEqual(), | 610 return r.ChangeToStringComparisonOperator(simplified()->StringEqual(), |
606 invert); | 611 invert); |
607 } | 612 } |
608 if (r.BothInputsAre(Type::Number())) { | 613 if (r.BothInputsAre(Type::NumberOrUndefined())) { |
609 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 614 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
610 } | 615 } |
611 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) | 616 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) |
612 return NoChange(); | 617 return NoChange(); |
613 } | 618 } |
614 | 619 |
615 | 620 |
616 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 621 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
617 Node* const input = node->InputAt(0); | 622 Node* const input = node->InputAt(0); |
618 Type* const input_type = NodeProperties::GetType(input); | 623 Type* const input_type = NodeProperties::GetType(input); |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { | 1010 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { |
1006 // JSLoadProperty(typed-array, int32) | 1011 // JSLoadProperty(typed-array, int32) |
1007 Handle<FixedTypedArrayBase> elements = | 1012 Handle<FixedTypedArrayBase> elements = |
1008 Handle<FixedTypedArrayBase>::cast(handle(array->elements())); | 1013 Handle<FixedTypedArrayBase>::cast(handle(array->elements())); |
1009 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); | 1014 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); |
1010 Node* length = jsgraph()->Constant(byte_length); | 1015 Node* length = jsgraph()->Constant(byte_length); |
1011 Node* context = NodeProperties::GetContextInput(node); | 1016 Node* context = NodeProperties::GetContextInput(node); |
1012 Node* effect = NodeProperties::GetEffectInput(node); | 1017 Node* effect = NodeProperties::GetEffectInput(node); |
1013 Node* control = NodeProperties::GetControlInput(node); | 1018 Node* control = NodeProperties::GetControlInput(node); |
1014 // Convert to a number first. | 1019 // Convert to a number first. |
1015 if (!value_type->Is(Type::Number())) { | 1020 if (!value_type->Is(Type::NumberOrUndefined())) { |
1016 Reduction number_reduction = ReduceJSToNumberInput(value); | 1021 Reduction number_reduction = ReduceJSToNumberInput(value); |
1017 if (number_reduction.Changed()) { | 1022 if (number_reduction.Changed()) { |
1018 value = number_reduction.replacement(); | 1023 value = number_reduction.replacement(); |
1019 } else { | 1024 } else { |
1020 Node* frame_state_for_to_number = | 1025 Node* frame_state_for_to_number = |
1021 NodeProperties::GetFrameStateInput(node, 1); | 1026 NodeProperties::GetFrameStateInput(node, 1); |
1022 value = effect = | 1027 value = effect = |
1023 graph()->NewNode(javascript()->ToNumber(), value, context, | 1028 graph()->NewNode(javascript()->ToNumber(), value, context, |
1024 frame_state_for_to_number, effect, control); | 1029 frame_state_for_to_number, effect, control); |
1025 } | 1030 } |
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1807 } | 1812 } |
1808 | 1813 |
1809 | 1814 |
1810 CompilationDependencies* JSTypedLowering::dependencies() const { | 1815 CompilationDependencies* JSTypedLowering::dependencies() const { |
1811 return dependencies_; | 1816 return dependencies_; |
1812 } | 1817 } |
1813 | 1818 |
1814 } // namespace compiler | 1819 } // namespace compiler |
1815 } // namespace internal | 1820 } // namespace internal |
1816 } // namespace v8 | 1821 } // namespace v8 |
OLD | NEW |