OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 break; | 712 break; |
713 case IrOpcode::kObjectIsUndetectable: | 713 case IrOpcode::kObjectIsUndetectable: |
714 state = LowerObjectIsUndetectable(node, *effect, *control); | 714 state = LowerObjectIsUndetectable(node, *effect, *control); |
715 break; | 715 break; |
716 case IrOpcode::kArrayBufferWasNeutered: | 716 case IrOpcode::kArrayBufferWasNeutered: |
717 state = LowerArrayBufferWasNeutered(node, *effect, *control); | 717 state = LowerArrayBufferWasNeutered(node, *effect, *control); |
718 break; | 718 break; |
719 case IrOpcode::kStringFromCharCode: | 719 case IrOpcode::kStringFromCharCode: |
720 state = LowerStringFromCharCode(node, *effect, *control); | 720 state = LowerStringFromCharCode(node, *effect, *control); |
721 break; | 721 break; |
| 722 case IrOpcode::kStringFromCodePoint: |
| 723 state = LowerStringFromCodePoint(node, *effect, *control); |
| 724 break; |
722 case IrOpcode::kStringCharCodeAt: | 725 case IrOpcode::kStringCharCodeAt: |
723 state = LowerStringCharCodeAt(node, *effect, *control); | 726 state = LowerStringCharCodeAt(node, *effect, *control); |
724 break; | 727 break; |
725 case IrOpcode::kStringEqual: | 728 case IrOpcode::kStringEqual: |
726 state = LowerStringEqual(node, *effect, *control); | 729 state = LowerStringEqual(node, *effect, *control); |
727 break; | 730 break; |
728 case IrOpcode::kStringLessThan: | 731 case IrOpcode::kStringLessThan: |
729 state = LowerStringLessThan(node, *effect, *control); | 732 state = LowerStringLessThan(node, *effect, *control); |
730 break; | 733 break; |
731 case IrOpcode::kStringLessThanOrEqual: | 734 case IrOpcode::kStringLessThanOrEqual: |
(...skipping 1808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2540 | 2543 |
2541 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 2544 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
2542 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | 2545 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
2543 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 2546 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
2544 vtrue0, vfalse0, control); | 2547 vtrue0, vfalse0, control); |
2545 | 2548 |
2546 return ValueEffectControl(value, effect, control); | 2549 return ValueEffectControl(value, effect, control); |
2547 } | 2550 } |
2548 | 2551 |
2549 EffectControlLinearizer::ValueEffectControl | 2552 EffectControlLinearizer::ValueEffectControl |
| 2553 EffectControlLinearizer::LowerStringFromCodePoint(Node* node, Node* effect, |
| 2554 Node* control) { |
| 2555 Node* value = node->InputAt(0); |
| 2556 Node* code = value; |
| 2557 |
| 2558 Node* etrue0 = effect; |
| 2559 Node* vtrue0; |
| 2560 |
| 2561 // Check if the {code} is a single code unit |
| 2562 Node* check0 = graph()->NewNode(machine()->Uint32LessThanOrEqual(), code, |
| 2563 jsgraph()->Uint32Constant(0xFFFF)); |
| 2564 Node* branch0 = |
| 2565 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
| 2566 |
| 2567 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 2568 { |
| 2569 // Check if the {code} is a one byte character |
| 2570 Node* check1 = graph()->NewNode( |
| 2571 machine()->Uint32LessThanOrEqual(), code, |
| 2572 jsgraph()->Uint32Constant(String::kMaxOneByteCharCode)); |
| 2573 Node* branch1 = |
| 2574 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); |
| 2575 |
| 2576 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 2577 Node* etrue1 = etrue0; |
| 2578 Node* vtrue1; |
| 2579 { |
| 2580 // Load the isolate wide single character string cache. |
| 2581 Node* cache = |
| 2582 jsgraph()->HeapConstant(factory()->single_character_string_cache()); |
| 2583 |
| 2584 // Compute the {cache} index for {code}. |
| 2585 Node* index = |
| 2586 machine()->Is32() |
| 2587 ? code |
| 2588 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code); |
| 2589 |
| 2590 // Check if we have an entry for the {code} in the single character string |
| 2591 // cache already. |
| 2592 Node* entry = etrue1 = graph()->NewNode( |
| 2593 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), |
| 2594 cache, index, etrue1, if_true1); |
| 2595 |
| 2596 Node* check2 = graph()->NewNode(machine()->WordEqual(), entry, |
| 2597 jsgraph()->UndefinedConstant()); |
| 2598 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 2599 check2, if_true1); |
| 2600 |
| 2601 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 2602 Node* etrue2 = etrue1; |
| 2603 Node* vtrue2; |
| 2604 { |
| 2605 // Allocate a new SeqOneByteString for {code}. |
| 2606 vtrue2 = etrue2 = graph()->NewNode( |
| 2607 simplified()->Allocate(NOT_TENURED), |
| 2608 jsgraph()->Int32Constant(SeqOneByteString::SizeFor(1)), etrue2, |
| 2609 if_true2); |
| 2610 etrue2 = graph()->NewNode( |
| 2611 simplified()->StoreField(AccessBuilder::ForMap()), vtrue2, |
| 2612 jsgraph()->HeapConstant(factory()->one_byte_string_map()), etrue2, |
| 2613 if_true2); |
| 2614 etrue2 = graph()->NewNode( |
| 2615 simplified()->StoreField(AccessBuilder::ForNameHashField()), vtrue2, |
| 2616 jsgraph()->IntPtrConstant(Name::kEmptyHashField), etrue2, if_true2); |
| 2617 etrue2 = graph()->NewNode( |
| 2618 simplified()->StoreField(AccessBuilder::ForStringLength()), vtrue2, |
| 2619 jsgraph()->SmiConstant(1), etrue2, if_true2); |
| 2620 etrue2 = graph()->NewNode( |
| 2621 machine()->Store(StoreRepresentation(MachineRepresentation::kWord8, |
| 2622 kNoWriteBarrier)), |
| 2623 vtrue2, jsgraph()->IntPtrConstant(SeqOneByteString::kHeaderSize - |
| 2624 kHeapObjectTag), |
| 2625 code, etrue2, if_true2); |
| 2626 |
| 2627 // Remember it in the {cache}. |
| 2628 etrue2 = graph()->NewNode( |
| 2629 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), |
| 2630 cache, index, vtrue2, etrue2, if_true2); |
| 2631 } |
| 2632 |
| 2633 // Use the {entry} from the {cache}. |
| 2634 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 2635 Node* efalse2 = etrue0; |
| 2636 Node* vfalse2 = entry; |
| 2637 |
| 2638 if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 2639 etrue1 = |
| 2640 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_true1); |
| 2641 vtrue1 = |
| 2642 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 2643 vtrue2, vfalse2, if_true1); |
| 2644 } |
| 2645 |
| 2646 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 2647 Node* efalse1 = effect; |
| 2648 Node* vfalse1; |
| 2649 { |
| 2650 // Allocate a new SeqTwoByteString for {code}. |
| 2651 vfalse1 = efalse1 = graph()->NewNode( |
| 2652 simplified()->Allocate(NOT_TENURED), |
| 2653 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(1)), efalse1, |
| 2654 if_false1); |
| 2655 efalse1 = graph()->NewNode( |
| 2656 simplified()->StoreField(AccessBuilder::ForMap()), vfalse1, |
| 2657 jsgraph()->HeapConstant(factory()->string_map()), efalse1, if_false1); |
| 2658 efalse1 = graph()->NewNode( |
| 2659 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse1, |
| 2660 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse1, if_false1); |
| 2661 efalse1 = graph()->NewNode( |
| 2662 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse1, |
| 2663 jsgraph()->SmiConstant(1), efalse1, if_false1); |
| 2664 efalse1 = graph()->NewNode( |
| 2665 machine()->Store(StoreRepresentation(MachineRepresentation::kWord16, |
| 2666 kNoWriteBarrier)), |
| 2667 vfalse1, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize - |
| 2668 kHeapObjectTag), |
| 2669 code, efalse1, if_false1); |
| 2670 } |
| 2671 |
| 2672 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 2673 etrue0 = |
| 2674 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); |
| 2675 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 2676 vtrue1, vfalse1, if_true0); |
| 2677 } |
| 2678 |
| 2679 // Generate surrogate pair string |
| 2680 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 2681 Node* efalse0 = effect; |
| 2682 Node* vfalse0; |
| 2683 { |
| 2684 switch (UnicodeEncodingOf(node->op())) { |
| 2685 case UnicodeEncoding::UTF16: |
| 2686 break; |
| 2687 |
| 2688 case UnicodeEncoding::UTF32: { |
| 2689 // Convert UTF32 to UTF16 code units, and store as a 32 bit word. |
| 2690 Node* lead_offset = jsgraph()->Int32Constant(0xD800 - (0x10000 >> 10)); |
| 2691 |
| 2692 // lead = (codepoint >> 10) + LEAD_OFFSET |
| 2693 Node* lead = |
| 2694 graph()->NewNode(machine()->Int32Add(), |
| 2695 graph()->NewNode(machine()->Word32Shr(), code, |
| 2696 jsgraph()->Int32Constant(10)), |
| 2697 lead_offset); |
| 2698 |
| 2699 // trail = (codepoint & 0x3FF) + 0xDC00; |
| 2700 Node* trail = |
| 2701 graph()->NewNode(machine()->Int32Add(), |
| 2702 graph()->NewNode(machine()->Word32And(), code, |
| 2703 jsgraph()->Int32Constant(0x3FF)), |
| 2704 jsgraph()->Int32Constant(0xDC00)); |
| 2705 |
| 2706 // codpoint = (trail << 16) | lead; |
| 2707 code = graph()->NewNode(machine()->Word32Or(), |
| 2708 graph()->NewNode(machine()->Word32Shl(), trail, |
| 2709 jsgraph()->Int32Constant(16)), |
| 2710 lead); |
| 2711 break; |
| 2712 } |
| 2713 } |
| 2714 |
| 2715 // Allocate a new SeqTwoByteString for {code}. |
| 2716 vfalse0 = efalse0 = |
| 2717 graph()->NewNode(simplified()->Allocate(NOT_TENURED), |
| 2718 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(2)), |
| 2719 efalse0, if_false0); |
| 2720 efalse0 = graph()->NewNode( |
| 2721 simplified()->StoreField(AccessBuilder::ForMap()), vfalse0, |
| 2722 jsgraph()->HeapConstant(factory()->string_map()), efalse0, if_false0); |
| 2723 efalse0 = graph()->NewNode( |
| 2724 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse0, |
| 2725 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse0, if_false0); |
| 2726 efalse0 = graph()->NewNode( |
| 2727 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse0, |
| 2728 jsgraph()->SmiConstant(2), efalse0, if_false0); |
| 2729 efalse0 = graph()->NewNode( |
| 2730 machine()->Store(StoreRepresentation(MachineRepresentation::kWord32, |
| 2731 kNoWriteBarrier)), |
| 2732 vfalse0, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize - |
| 2733 kHeapObjectTag), |
| 2734 code, efalse0, if_false0); |
| 2735 } |
| 2736 |
| 2737 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 2738 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 2739 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 2740 vtrue0, vfalse0, control); |
| 2741 |
| 2742 return ValueEffectControl(value, effect, control); |
| 2743 } |
| 2744 |
| 2745 EffectControlLinearizer::ValueEffectControl |
2550 EffectControlLinearizer::LowerStringComparison(Callable const& callable, | 2746 EffectControlLinearizer::LowerStringComparison(Callable const& callable, |
2551 Node* node, Node* effect, | 2747 Node* node, Node* effect, |
2552 Node* control) { | 2748 Node* control) { |
2553 Operator::Properties properties = Operator::kEliminatable; | 2749 Operator::Properties properties = Operator::kEliminatable; |
2554 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 2750 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
2555 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 2751 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
2556 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); | 2752 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
2557 node->InsertInput(graph()->zone(), 0, | 2753 node->InsertInput(graph()->zone(), 0, |
2558 jsgraph()->HeapConstant(callable.code())); | 2754 jsgraph()->HeapConstant(callable.code())); |
2559 node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant()); | 2755 node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant()); |
(...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3488 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3684 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
3489 Operator::kEliminatable); | 3685 Operator::kEliminatable); |
3490 to_number_operator_.set(common()->Call(desc)); | 3686 to_number_operator_.set(common()->Call(desc)); |
3491 } | 3687 } |
3492 return to_number_operator_.get(); | 3688 return to_number_operator_.get(); |
3493 } | 3689 } |
3494 | 3690 |
3495 } // namespace compiler | 3691 } // namespace compiler |
3496 } // namespace internal | 3692 } // namespace internal |
3497 } // namespace v8 | 3693 } // namespace v8 |
OLD | NEW |