| Differences between
and this patch
- Source/JavaScriptCore/dfg/DFGBasicBlock.h -1 / +75 lines
Lines 46-51 class Graph; Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec1
46
class InsertionSet;
46
class InsertionSet;
47
47
48
typedef Vector<BasicBlock*, 2> PredecessorList;
48
typedef Vector<BasicBlock*, 2> PredecessorList;
49
typedef Vector<Node*, 8> BlockNodeList;
49
50
50
struct BasicBlock : RefCounted<BasicBlock> {
51
struct BasicBlock : RefCounted<BasicBlock> {
51
    BasicBlock(
52
    BasicBlock(
Lines 85-90 struct BasicBlock : RefCounted<BasicBloc Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec2
85
    bool isInPhis(Node* node) const;
86
    bool isInPhis(Node* node) const;
86
    bool isInBlock(Node* myNode) const;
87
    bool isInBlock(Node* myNode) const;
87
    
88
    
89
    BlockNodeList::iterator begin() { return m_nodes.begin(); }
90
    BlockNodeList::iterator end() { return m_nodes.end(); }
91
    
88
    unsigned numSuccessors() { return last()->numSuccessors(); }
92
    unsigned numSuccessors() { return last()->numSuccessors(); }
89
    
93
    
90
    BasicBlock*& successor(unsigned index)
94
    BasicBlock*& successor(unsigned index)
Lines 96-101 struct BasicBlock : RefCounted<BasicBloc Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec3
96
        return last()->successorForCondition(condition);
100
        return last()->successorForCondition(condition);
97
    }
101
    }
98
    
102
    
103
    class SuccessorsIterable {
104
    public:
105
        SuccessorsIterable()
106
            : m_block(nullptr)
107
        {
108
        }
109
        
110
        SuccessorsIterable(BasicBlock* block)
111
            : m_block(block)
112
        {
113
        }
114
        
115
        class iterator {
116
        public:
117
            iterator()
118
                : m_block(nullptr)
119
                , m_index(UINT_MAX)
120
            {
121
            }
122
            
123
            iterator(BasicBlock* block, unsigned index)
124
                : m_block(block)
125
                , m_index(index)
126
            {
127
            }
128
            
129
            BasicBlock* operator*()
130
            {
131
                return m_block->successor(index);
132
            }
133
            
134
            iterator& operator++()
135
            {
136
                m_index++;
137
                return *this;
138
            }
139
            
140
            bool operator==(const iterator& other) const
141
            {
142
                return m_index == other.m_index;
143
            }
144
            
145
            bool operator!=(const iterator& other) const
146
            {
147
                return !(*this == other);
148
            }
149
        private:
150
            BasicBlock* m_block;
151
            unsigned m_index;
152
        };
153
        
154
        iterator begin()
155
        {
156
            return iterator(m_block, 0);
157
        }
158
        
159
        iterator end()
160
        {
161
            return iterator(m_block, m_block->numSuccessors());
162
        }
163
        
164
    private:
165
        BasicBlock* m_block;
166
    };
167
    
168
    SuccessorsIterable successors()
169
    {
170
        return SuccessorsIterable(this);
171
    }
172
    
99
    void removePredecessor(BasicBlock* block);
173
    void removePredecessor(BasicBlock* block);
100
    void replacePredecessor(BasicBlock* from, BasicBlock* to);
174
    void replacePredecessor(BasicBlock* from, BasicBlock* to);
101
175
Lines 183-189 struct BasicBlock : RefCounted<BasicBloc Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec4
183
    
257
    
184
private:
258
private:
185
    friend class InsertionSet;
259
    friend class InsertionSet;
186
    Vector<Node*, 8> m_nodes;
260
    BlockNodeList m_nodes;
187
};
261
};
188
262
189
typedef Vector<BasicBlock*, 5> BlockList;
263
typedef Vector<BasicBlock*, 5> BlockList;
- Source/JavaScriptCore/dfg/DFGGraph.h +105 lines
Lines 681-686 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec1
681
    BlockList blocksInPreOrder();
681
    BlockList blocksInPreOrder();
682
    BlockList blocksInPostOrder();
682
    BlockList blocksInPostOrder();
683
    
683
    
684
    class NaturalBlockIterable {
685
    public:
686
        NaturalBlockIterable()
687
            : m_graph(nullptr)
688
        {
689
        }
690
        
691
        NaturalBlockIterable(Graph& graph)
692
            : m_graph(&graph)
693
        {
694
        }
695
        
696
        class iterator {
697
        public:
698
            iterator()
699
                : m_graph(nullptr)
700
                , m_index(0)
701
            {
702
            }
703
            
704
            iterator(Graph& graph, BlockIndex index)
705
                : m_graph(&graph)
706
                , m_index(findNext(index))
707
            {
708
            }
709
            
710
            BasicBlock *operator*()
711
            {
712
                return m_graph->block(index);
713
            }
714
            
715
            iterator& operator++()
716
            {
717
                m_index = findNext(m_index);
718
                return *this;
719
            }
720
            
721
            bool operator==(const iterator& other) const
722
            {
723
                return m_index == other.m_index;
724
            }
725
            
726
            bool operator!=(const iterator& other) const
727
            {
728
                return !(*this == other);
729
            }
730
            
731
        private:
732
            BlockIndex findNext(BlockIndex index)
733
            {
734
                while (index < m_graph->numBlocks() && !m_graph->block(index))
735
                    index++;
736
                return index;
737
            }
738
            
739
            Graph* m_graph;
740
            BlockIndex m_index;
741
        };
742
        
743
        iterator begin()
744
        {
745
            return iterator(*m_graph, 0);
746
        }
747
        
748
        iterator end()
749
        {
750
            return iterator(*m_graph, m_graph->numBlocks());
751
        }
752
        
753
    private:
754
        Graph* m_graph;
755
    };
756
    
757
    NaturalBlockIterable blocksInNaturalOrder()
758
    {
759
        return NaturalBlockIterable(*this);
760
    }
761
    
762
    template<typename ChildFunctor>
763
    void doToChildrenWithNode(Node* node, const ChildFunctor& functor)
764
    {
765
        DFG_NODE_DO_TO_CHILDREN(node, functor);
766
    }
767
    
768
    template<typename ChildFunctor>
769
    void doToChildEdges(Node* node, const ChildFunctor& functor)
770
    {
771
        doToChildrenWithNode(
772
            node,
773
            [&functor] (Node*, Edge& edge) {
774
                functor(edge);
775
            });
776
    }
777
    
778
    template<typename ChildFunctor>
779
    void doToChildren(Node* node, const ChildFunctor& functor)
780
    {
781
        doToChildrenWithNode(
782
            node,
783
            [&functor] (Node*, Edge edge) {
784
                functor(edge);
785
            });
786
    }
787
    
684
    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
788
    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
685
    
789
    
686
    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
790
    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
Lines 741-746 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec2
741
    Bag<SwitchData> m_switchData;
845
    Bag<SwitchData> m_switchData;
742
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
846
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
743
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
847
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
848
    Bag<ObjectMaterializationData> m_objectMaterializationData;
744
    Vector<InlineVariableData, 4> m_inlineVariableData;
849
    Vector<InlineVariableData, 4> m_inlineVariableData;
745
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
850
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
746
    bool m_hasArguments;
851
    bool m_hasArguments;
- Source/JavaScriptCore/dfg/DFGHeapLocation.cpp +4 lines
Lines 147-152 void printInternal(PrintStream& out, Loc Source/JavaScriptCore/dfg/DFGHeapLocation.cpp_sec1
147
    case AllocationProfileWatchpointLoc:
147
    case AllocationProfileWatchpointLoc:
148
        out.print("AllocationProfileWatchpointLoc");
148
        out.print("AllocationProfileWatchpointLoc");
149
        return;
149
        return;
150
        
151
    case StructureLoc:
152
        out.print("StructureLoc");
153
        return;
150
    }
154
    }
151
    
155
    
152
    RELEASE_ASSERT_NOT_REACHED();
156
    RELEASE_ASSERT_NOT_REACHED();
- Source/JavaScriptCore/dfg/DFGHeapLocation.h +1 lines
Lines 55-60 enum LocationKind { Source/JavaScriptCore/dfg/DFGHeapLocation.h_sec1
55
    MyArgumentsLengthLoc,
55
    MyArgumentsLengthLoc,
56
    NamedPropertyLoc,
56
    NamedPropertyLoc,
57
    SetterLoc,
57
    SetterLoc,
58
    StructureLoc,
58
    TypeOfLoc,
59
    TypeOfLoc,
59
    TypedArrayByteOffsetLoc,
60
    TypedArrayByteOffsetLoc,
60
    VarInjectionWatchpointLoc,
61
    VarInjectionWatchpointLoc,
- Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.cpp +51 lines
Line 0 Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.cpp_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "DFGInsertOSRHintsForUpdate.h"
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
void insertOSRHintsForUpdate(
34
    InsertionSet& insertionSet, unsigned nodeIndex, LocalOSRAvailabilityCalculactor& availability,
35
    Node* originalNode, Node* newNode)
36
{
37
    for (unsigned i = availability.m_availability.size(); i--;) {
38
        int operand = availability.m_availability.operandForIndex(i);
39
        
40
        if (availability[i].hasNode() && availability[i].node() == originalNode) {
41
            insertionSet.insertNode(
42
                nodeIndex, SpecNone, MovHint, NodeOrigin(), OpInfo(operand),
43
                newNode->defaultEdge());
44
        }
45
    }
46
}
47
48
} } // namespace JSC::DFG
49
50
#endif // ENABLE(DFG_JIT)
51
- Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.h +45 lines
Line 0 Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.h_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGInsertOSRHintsForUpdate_h
27
#define DFGInsertOSRHintsForUpdate_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGInsertionSet.h"
32
#include "DFGOSRAvailabilityAnalysisPhase.h"
33
34
namespace JSC { namespace DFG {
35
36
void insertOSRHintsForUpdate(
37
    InsertionSet&, unsigned nodeIndex, LocalOSRAvailabilityCalculactor&,
38
    Node* originalNode, Node* newNode);
39
40
} } // namespace JSC::DFG
41
42
#endif // ENABLE(DFG_JIT)
43
44
#endif // DFGInsertOSRHintsForUpdate_h
45
- Source/JavaScriptCore/dfg/DFGNode.h -1 / +41 lines
Lines 38-43 Source/JavaScriptCore/dfg/DFGNode.h_sec1
38
#include "DFGNodeFlags.h"
38
#include "DFGNodeFlags.h"
39
#include "DFGNodeOrigin.h"
39
#include "DFGNodeOrigin.h"
40
#include "DFGNodeType.h"
40
#include "DFGNodeType.h"
41
#include "DFGObjectMaterializationData.h"
41
#include "DFGTransition.h"
42
#include "DFGTransition.h"
42
#include "DFGUseKind.h"
43
#include "DFGUseKind.h"
43
#include "DFGVariableAccessData.h"
44
#include "DFGVariableAccessData.h"
Lines 495-500 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec2
495
        m_flags &= ~NodeClobbersWorld;
496
        m_flags &= ~NodeClobbersWorld;
496
    }
497
    }
497
    
498
    
499
    void convertToPutByOffsetHint()
500
    {
501
        ASSERT(m_op == PutByOffset);
502
        m_op = PutByOffsetHint;
503
        child1() = child2();
504
        child2() = child3();
505
        child3() = Edge();
506
    }
507
    
508
    void convertToPutStructureHint(Node* structure)
509
    {
510
        ASSERT(m_op == PutStructure);
511
        ASSERT(structure->structure() == transition()->next);
512
        m_op = PhantomPutStructure;
513
        m_opInfo = 0;
514
        child2() = Edge(structure, KnownCellUse);
515
    }
516
    
498
    void convertToPhantomLocal()
517
    void convertToPhantomLocal()
499
    {
518
    {
500
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
519
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
Lines 1100-1105 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec3
1100
    {
1119
    {
1101
        switch (op()) {
1120
        switch (op()) {
1102
        case PutStructure:
1121
        case PutStructure:
1122
        case PutStructureHint:
1103
        case AllocatePropertyStorage:
1123
        case AllocatePropertyStorage:
1104
        case ReallocatePropertyStorage:
1124
        case ReallocatePropertyStorage:
1105
            return true;
1125
            return true;
Lines 1136-1141 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec4
1136
        case ArrayifyToStructure:
1156
        case ArrayifyToStructure:
1137
        case NewObject:
1157
        case NewObject:
1138
        case NewStringObject:
1158
        case NewStringObject:
1159
        case PhantomNewObject:
1160
        case PhantomStructure:
1139
            return true;
1161
            return true;
1140
        default:
1162
        default:
1141
            return false;
1163
            return false;
Lines 1150-1156 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec5
1150
    
1172
    
1151
    bool hasStorageAccessData()
1173
    bool hasStorageAccessData()
1152
    {
1174
    {
1153
        return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset;
1175
        switch (op()) {
1176
        case GetByOffset:
1177
        case PutByOffset:
1178
        case GetGetterSetterByOffset:
1179
        case PutByOffsetHint:
1180
            return true;
1181
        default:
1182
            return false;
1183
        }
1154
    }
1184
    }
1155
    
1185
    
1156
    unsigned storageAccessDataIndex()
1186
    unsigned storageAccessDataIndex()
Lines 1179-1184 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec6
1179
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1209
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1180
    }
1210
    }
1181
    
1211
    
1212
    bool hasObjectMaterializationData()
1213
    {
1214
        return op() == MaterializeNewObject;
1215
    }
1216
    
1217
    ObjectMaterializationData& objectMaterializationData()
1218
    {
1219
        return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo);
1220
    }
1221
    
1182
    bool hasFunctionDeclIndex()
1222
    bool hasFunctionDeclIndex()
1183
    {
1223
    {
1184
        return op() == NewFunction
1224
        return op() == NewFunction
- Source/JavaScriptCore/dfg/DFGNodeType.h +8 lines
Lines 228-233 namespace JSC { namespace DFG { Source/JavaScriptCore/dfg/DFGNodeType.h_sec1
228
    macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \
228
    macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \
229
    macro(NewRegexp, NodeResultJS) \
229
    macro(NewRegexp, NodeResultJS) \
230
    \
230
    \
231
    /* Support for allocation sinking. */\
232
    macro(PhantomNewObject, NodeResultJS) \
233
    macro(PhantomStructure, NodeResultJS) \
234
    macro(PutByOffsetHint, NodeMustGenerate) \
235
    macro(CheckStructureImmediate, NodeMustGenerate) \
236
    macro(PutStructureHint, NodeMustGenerate) \
237
    macro(MaterializeNewObject, NodeResultJS | NodeHasVarArgs) \
238
    \
231
    /* Nodes for misc operations. */\
239
    /* Nodes for misc operations. */\
232
    macro(Breakpoint, NodeMustGenerate) \
240
    macro(Breakpoint, NodeMustGenerate) \
233
    macro(ProfileWillCall, NodeMustGenerate) \
241
    macro(ProfileWillCall, NodeMustGenerate) \
- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp +5 lines
Lines 127-132 void LocalOSRAvailabilityCalculator::beg Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp_sec1
127
    m_availability = block->ssa->availabilityAtHead;
127
    m_availability = block->ssa->availabilityAtHead;
128
}
128
}
129
129
130
void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block)
131
{
132
    m_availability = block->ssa->availabilityAtTail;
133
}
134
130
void LocalOSRAvailabilityCalculator::executeNode(Node* node)
135
void LocalOSRAvailabilityCalculator::executeNode(Node* node)
131
{
136
{
132
    switch (node->op()) {
137
    switch (node->op()) {
- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h +1 lines
Lines 49-54 public: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h_sec1
49
    ~LocalOSRAvailabilityCalculator();
49
    ~LocalOSRAvailabilityCalculator();
50
    
50
    
51
    void beginBlock(BasicBlock*);
51
    void beginBlock(BasicBlock*);
52
    void endBlock(BasicBlock*); // Useful if you want to get data for the end of the block. You don't need to call this if you did beginBlock() and then executeNode() for every node.
52
    void executeNode(Node*);
53
    void executeNode(Node*);
53
    
54
    
54
    Operands<Availability> m_availability;
55
    Operands<Availability> m_availability;
- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp +720 lines
Line 0 Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "DFGObjectAllocationSinkingPhase.h"
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGAbstractHeap.h"
32
#include "DFGClobberize.h"
33
#include "DFGGraph.h"
34
#include "DFGInsertionSet.h"
35
#include "DFGPhase.h"
36
#include "JSCInlines.h"
37
38
namespace JSC { namespace DFG {
39
40
class ObjectAllocationSinkingPhase : public Phase {
41
public:
42
    ObjectAllocationSinkingPhase(Graph& graph)
43
        : Phase(graph, "object allocation sinking")
44
        , m_insertionSet(graph)
45
    {
46
    }
47
    
48
    bool run()
49
    {
50
        ASSERT(m_graph.m_fixpointState == FixpointNotConverged);
51
        
52
        m_changed = false;
53
        
54
        // Logically we wish to consider every NewObject and sink it. However it's definitely not
55
        // profitable to sink a NewObject that will always escape. So, first we do a very simple
56
        // forward flow analysis that determines the set of NewObject nodes that have any chance
57
        // of benefiting from object allocation sinking. Then we fixpoint the following rules:
58
        //
59
        // - For each NewObject, we turn the original NewObject into a PhantomNewObject and then
60
        //   we insert MaterializeNewObject just before each escaping site. Note that Upsilons
61
        //   constitute escaping sites. Then we use forward flow to eliminate unnecessary cases of
62
        //   MaterializeNewObject. We use the SSACalculator to insert these materializations. If a
63
        //   Phi is ever created that has the PhantomNewObject as one of its kids, then we insert
64
        //   a MaterializeNewObject in front of it; this way we never have a Phi that is confused
65
        //   about whether or not it has the real object. We then turn each PutByOffset over a
66
        //   PhantomNewObject into a PutByOffsetHint.
67
        //
68
        // - We perform the same optimization for MaterializeNewObject. This allows us to cover
69
        //   cases where we had MaterializeNewObject flowing into a PutByOffsetHint.
70
        //
71
        // - If all of the Upsilons of a Phi have a MaterializeNewObject that isn't used by anyone
72
        //   else, then replace the Phi with the MaterializeNewObject.
73
        
74
        if (!performSinking(DontConsiderPhis))
75
            return false;
76
        
77
        while (performSinking(ConsiderPhis)) { }
78
        
79
        return true;
80
    }
81
82
private:
83
    enum PhiMode {
84
        ConsiderPhis,
85
        DontConsiderPhis
86
    };
87
    
88
    bool performSinking(PhiMode phiMode)
89
    {
90
        m_graph.computeRefCounts();
91
        m_phiChildren = PhiChildren(m_graph);
92
        
93
        performLivenessAnalysis();
94
        performOSRAvailabilityAnalysis();
95
        
96
        // Conduct one fixpoint iteration, that involves finding nodes that are candidates for
97
        // sinking and then sinking them. We proceed roughly as follows:
98
        //
99
        // 1) Identify Phis that it would be meaningful to sink.
100
        // 2) Figure out if the things that are sinkable would be profitable to sink.
101
        // 3) Sink them.
102
        
103
        m_phiSinkCandidates.clear();
104
        if (phiMode == ConsiderPhis)
105
            identifyPhiSinkingCandidates();
106
        
107
        // We want to only do sinking for those things that would benefit. We use a rough
108
        // heuristic: if it's possible for an allocation to make it to a return without escaping,
109
        // then we assume that it's worth sinking. It's a simple forward flow problem.
110
        //
111
        // It just so happens that this forward flow problem also tells us where we would
112
        // materialize those nodes that we choose to sink.
113
        pruneSinkingCandidates();
114
        if (m_sinkCandidates.isEmpty())
115
            return false;
116
        
117
        // At this point we are committed to sinking the sinking candidates.
118
        determineMaterializationPoints();
119
        placeMaterializationPoints();
120
        lowerOperationsOnPhantomAllocations();
121
        promoteSunkenFields();
122
        
123
        return true;
124
    }
125
    
126
    void identifyPhiSinkingCandidates()
127
    {
128
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
129
            for (Node* node : *block) {
130
                if (node->op() != Phi)
131
                    continue;
132
                
133
                PhiChildren::List& upsilons = phiChildren.upsilonsOf(node);
134
                if (upsilons.isEmpty())
135
                    continue;
136
                
137
                if (upsilons[0]->child1()->op() != MaterializeNewObject)
138
                    continue;
139
                
140
                bool allChildrenAreUniquelyReferenced = true;
141
                for (Node* upsilonNode : upsilons) {
142
                    if (upsilonNode->child1()->refCount() != 1) {
143
                        allChildrenAreUniquelyReferenced = false;
144
                        break;
145
                    }
146
                }
147
                if (!allChildrenAreUniquelyReferenced)
148
                    continue;
149
                
150
                bool allChildrenAreSameType = true;
151
                for (unsigned i = upsilons.size(); i-- > 1;) {
152
                    if (upsilons[i]->child1()->op() != upsilons[0]->child1()->op()) {
153
                        allChildrenAreSameType = false;
154
                        break;
155
                    }
156
                }
157
                if (!allChildrenAreSameType)
158
                    continue;
159
                
160
                // This could be a pessimisation if the various materializations are too
161
                // different from one another. We use a simple heuristic here: all of the
162
                // materializations must share at least half of their fields with the first
163
                // one.
164
                bool allAreSimilarEnough = true;
165
                for (unsigned i = upsilons.size(); i-- > 1;) {
166
                    float score =
167
                        upsilons[i]->child1()->objectMaterializationData().similarityScore(
168
                            upsilons[0]->child1()->objectMaterializationData());
169
                    if (score < 0.5) {
170
                        allAreSimilarEnough = false;
171
                        break;
172
                    }
173
                }
174
                if (!allAreSimilarEnough)
175
                    continue;
176
                    
177
                m_phiSinkCandidates.append(node);
178
            }
179
        }
180
    }
181
    
182
    void pruneSinkingCandidates()
183
    {
184
        m_sinkCandidates.clear();
185
        BlockMap<HashSet<Node*>> sinkCandidatesAtHead(m_graph);
186
        BlockMap<HashSet<Node*>> sinkCandidatesAtTail(m_graph);
187
        
188
        bool changed;
189
        do {
190
            changed = false;
191
            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
192
                HashSet<Node*> sinkCandidates = sinkCandidatesAtHead[block];
193
                for (Node* node : *block) {
194
                    handleNode(
195
                        node,
196
                        [&] () {
197
                            sinkCandidates.add(node);
198
                        },
199
                        [&] (Node* escapee) {
200
                            sinkCandidates.remove(escapee);
201
                        });
202
                }
203
                if (sinkCandidatesAtTail[block] == sinkCandidates)
204
                    continue;
205
                
206
                sinkCandidatesAtTail[block] = sinkCandidates;
207
                changed = true;
208
                
209
                for (BasicBlock* successorBlock : block->successors()) {
210
                    for (Node* sinkCandidate : sinkCandidates) {
211
                        if (!successorBlock->ssa->liveAtHead.contains(sinkCandidate))
212
                            continue;
213
                        sinkCandidatesAtHead[successorBlock].add(sinkCandidate);
214
                    }
215
                }
216
            }
217
        } while (changed);
218
        
219
        // A node is a sink candidate if it is in the sinkCandidatesAtTail of a block but not in
220
        // the liveAtTail of that same block.
221
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
222
            for (Node* sinkCandidate : sinkCandidatesAtTail[block]) {
223
                if (!block->ssa->liveAtTail.contains(sinkCandidate))
224
                    m_sinkCandidates.add(sinkCandidate);
225
            }
226
        }
227
        
228
        // A node should be materialized if it is a sinking candidate, and we haven't removed it
229
        // from the sink candidates set yet - since that means that it may not have been
230
        // materialized yet.
231
        // FIXME: oddly, anytime that we would have a basic block where something is "maybe
232
        // materialized", we would make it always materialized by having the not-materializing
233
    }
234
    
235
    void determineMaterializationPoints()
236
    {
237
        // The premise of this pass is that if there exists a point in the program where some
238
        // path from a phantom allocation site to that point causes materialization, then *all*
239
        // paths cause materialization. This should mean that there are never any redundant
240
        // materializations.
241
        
242
        m_edgeToMaterializationPoint.clear();
243
        
244
        BlockMap<HashSet<Node*>> materializedAtHead;
245
        BlockMap<HashSet<Node*>> materializedAtTail;
246
        
247
        bool changed;
248
        do {
249
            changed = false;
250
            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
251
                HashSet<Node*> materialized = materializedAtHead[block];
252
                for (Node* node : *block) {
253
                    handleNode(
254
                        node,
255
                        doNothing,
256
                        [&] (Node* escapee) {
257
                            if (m_sinkCandidates.contains(escapee))
258
                                materialized.add(escapee);
259
                        });
260
                }
261
                
262
                if (materialized == materializedAtTail[block])
263
                    continue;
264
                
265
                changed = true;
266
                
267
                for (BasicBlock* successorBlock : block->successors()) {
268
                    for (Node* materializee : materialized) {
269
                        if (!successorBlock->ssa->liveAtHead.contains(materializee))
270
                            continue;
271
                        materializedAtHead[successorBlock].add(materializee);
272
                    }
273
                }
274
            }
275
        } while (changed);
276
        
277
        // A materialization edge exists at any point where a node escapes but hasn't been
278
        // materialized yet.
279
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
280
            HashSet<Node*> materialized = materializedAtHead[block];
281
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
282
                Node* node = block->at(nodeIndex);
283
                
284
                handleNode(
285
                    node,
286
                    doNothing,
287
                    [&] (Node* escapee) {
288
                        if (!m_sinkCandidates.contains(escapee))
289
                            return;
290
                        
291
                        if (!materialized.add(escapee))
292
                            return;
293
                        
294
                        m_edgeToMaterializationPoint.add(
295
                            std::make_pair(where, escapee),
296
                            createMaterialize(escapee, node->origin));
297
                    });
298
            }
299
        }
300
    }
301
    
302
    void placeMaterializationPoints()
303
    {
304
        SSACalculator ssaCalculator(m_graph);
305
        
306
        HashMap<Node*, SSACalculator::Variable*> nodeToVariable;
307
        Vector<Node*> indexToNode;
308
        
309
        for (Node* node : m_sinkCandidates) {
310
            SSACalculator::Variable* variable = ssaCalculator.newVariable();
311
            nodeToVariable.add(node, variable);
312
            ASSERT(indexToNode.size() == variable->index());
313
            indexToNode.append(node);
314
        }
315
        
316
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
317
            for (Node* node : *block) {
318
                if (SSACalculator::Variable* variable = nodeToVariable.get(node))
319
                    ssaCalculator.newDef(variable, block, node);
320
                
321
                m_graph.doToChildren(
322
                    node,
323
                    [&] (Edge edge) {
324
                        Node* materialize =
325
                            m_edgeToMaterializationPoint.get(std::make_pair(node, edge.node()));
326
                        if (!materialize)
327
                            return;
328
                        
329
                        ssaCalculator.newDef(
330
                            nodeToVariable.get(edge.node()), block, materialize);
331
                    });
332
            }
333
        }
334
        
335
        ssaCalculator.computePhis(
336
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
337
                Node* allocation = indexToNode[variable->index()];
338
                if (!block->ssa->liveAtHead.contains(allocation))
339
                    return nullptr;
340
                
341
                Node* phiNode = m_graph.addNode(
342
                    allocation->prediction(), Phi, NodeOrigin());
343
                phiNode->mergeFlags(NodeResultJS);
344
                return phiNode;
345
            });
346
        
347
        // Place Phis in the right places. Replace all uses of any allocation with the appropriate
348
        // materialization. Create the appropriate Upsilon nodes.
349
        LocalOSRAvailabilityCalculator availabilityCalculator;
350
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
351
            HashMap<Node*, Node*> mapping;
352
            
353
            for (Node* candidate : block->ssa->liveAtHead) {
354
                SSACalculator::Variable* variable = nodeToVariable.get(candidate);
355
                if (!variable)
356
                    continue;
357
                
358
                Def* def = ssaCalculator.reachingDefAtHead(block, variable);
359
                if (!def)
360
                    continue;
361
                
362
                mapping.add(indexToNode[variable->index()], def->value());
363
            }
364
            
365
            availabilityCalculator.beginBlock(block);
366
            for (SSACalculator::Def* phiDef : ssaCalculator.phisForBlock(block)) {
367
                m_insertionSet.insert(0, phiDef->value());
368
                
369
                Node* originalNode = indexToNode[phiDef->variable()->index()];
370
                insertOSRHintsForUpdate(
371
                    m_insertionSet, 0, availabilityCalculator, originalNode, phiDef->value());
372
373
                mapping.add(originalNode, phiDef->value());
374
            }
375
            
376
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
377
                Node* node = block->at(nodeIndex);
378
379
                m_graph.doToChildEdges(
380
                    node,
381
                    [&] (Edge edge) {
382
                        Node* materialize = m_edgeToMaterializationPoint.get(
383
                            std::make_pair(node, edge.node()));
384
                        if (materialize) {
385
                            m_insertionSet.insert(nodeIndex, materialize);
386
                            insertOSRHintsForUpdate(
387
                                m_insertionSet, nodeIndex, availabilityCalculator,
388
                                edge.node(), materialize);
389
                        }
390
                    });
391
392
                availabilityCalculator.executeNode(node);
393
                
394
                m_graph.doToChildEdges(
395
                    node,
396
                    [&] (Edge& edge) {
397
                        if (Node* materialize = mapping.get(edge.node()))
398
                            edge.setNode(materialize);
399
                    });
400
            }
401
            
402
            size_t upsilonInsertionPoint = block->size() - 1;
403
            NodeOrigin upsilonOrigin = block->last()->origin;
404
            for (BasicBlock* successorBlock : block->successors()) {
405
                for (SSACalculator::Def* phiDef : ssaCalculator.phisForBlock(successorBlock)) {
406
                    Node* phiNode = phiDef->value();
407
                    SSACalculator::Variable* variable = phiDef->variable();
408
                    Node* allocation = indexToNode[variable->index()];
409
                    
410
                    Node* originalIncoming = mapping.get(allocation);
411
                    Node* incoming;
412
                    if (originalIncoming == allocation) {
413
                        // If we have a Phi that combines materializations with the original
414
                        // phantom object, then the path with the phantom object must materialize.
415
                        
416
                        incoming = createMaterialize(allocation, upsilonOrigin);
417
                        m_insertionSet.insert(upsilonInsertionPoint, incoming);
418
                        insertOSRHintsForUpdate(
419
                            m_insertionSet, upsilonInsertionPoint, availabilityCalculator,
420
                            originalIncoming, incoming);
421
                    } else
422
                        incoming = originalIncoming;
423
                    
424
                    Node* upsilon = m_insertionSet.insertNode(
425
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
426
                        OpInfo(phiNode), incoming->defaultEdge());
427
                    
428
                    if (originalIncoming == allocation) {
429
                        m_edgeToMaterializationPoint.add(
430
                            std::make_pair(upsilon, allocation), incoming);
431
                    }
432
                }
433
            }
434
            
435
            m_insertionSet.execute(block);
436
        }
437
        
438
        // At this point we have dummy materialization nodes along with edges to them. This means
439
        // that the part of the control flow graph that prefers to see actual object allocations
440
        // is completely fixed up, except for the materializations themselves.
441
    }
442
    
443
    void lowerWriteOperationsOnPhantomAllocations()
444
    {
445
        // Lower those operations on phantom allocations that write to properties of those
446
        // objects. It turns out that this is the only thing we can lower right now, and it's also
447
        // very useful to lower these things here. We can't yet lower operations like GetByOffset
448
        // because for those we would need to have done the SSA calculation. SSA calculation
449
        // depends on us doing the lowering, to reveal the SSA nodes for things like the structure
450
        // in a PutStructure. We also don't lower the allocations themselves, because their
451
        // original form still contains some useful information. It turns out that basically this
452
        // lowers all of the writing operations.
453
        
454
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
455
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
456
                Node* node = block->at(nodeIndex);
457
                switch (node->op()) {
458
                case PutByOffset: {
459
                    node->convertToPutByOffsetHint();
460
                    break;
461
                }
462
                    
463
                case PutStructure: {
464
                    Node* structure = m_insertionSet.insertNode(
465
                        nodeIndex, SpecNone, PhantomStructure, node->origin,
466
                        OpInfo(node->transition()->next));
467
                    node->convertToPutStructureHint(structure);
468
                    break;
469
                }
470
                    
471
                default:
472
                    break;
473
                }
474
            }
475
            m_insertionSet.execute(block);
476
        }
477
    }
478
    
479
    void promoteSunkenFields()
480
    {
481
        // Henceforth when we encounter a materialization point, we will want to ask *who* it is
482
        // a materialization for. Invert the map to be able to answer such questions.
483
        m_materializationPointToEscapee.clear();
484
        for (auto pair : m_edgeToMaterializationPoint)
485
            m_materializationPointToEscapee.add(pair.value, pair.key.second);
486
        
487
        // Collect the set of heap locations that we will be operating over.
488
        HashSet<HeapLocation> locations;
489
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
490
            for (Node* node : *block) {
491
                promoteIncludingMaterializations(
492
                    node,
493
                    [&] (HeapLocation location, Edge) {
494
                        locations.add(location);
495
                    },
496
                    [&] (HeapLocation location) {
497
                        locations.add(location);
498
                    });
499
            }
500
        }
501
        
502
        // Figure out which locations belong to which allocations.
503
        HashMap<Node*, Vector<HeapLocation>> locationsForAllocation;
504
        for (HeapLocation location : locations) {
505
            auto result = locationsForAllocation.add(location.base(), Vector<HeapLocation>());
506
            ASSERT(!result.iterator->value.contains(location));
507
            result.iterator->value.append(location);
508
        }
509
        
510
        // Fix up 
511
512
        SSACalculator ssaCalculator(m_graph);
513
514
        // Collect the set of "variables" that we will be sinking.
515
        HashMap<HeapLocation, SSACalculator::Variable*> locationToVariable;
516
        Vector<HeapLocation> indexToLocation;
517
        for (HeapLocation location : locations) {
518
            SSACalculator::Variable* variable = ssaCalculator.newVariable();
519
            locationToVariable.add(location, variable);
520
            ASSERT(indexToLocation.size() == variable->index());
521
            indexToLocation.append(location);
522
        }
523
        
524
        // Create all of the Defs. This includes:
525
        //
526
        // - Defs for the sunken fields at the point of creation. We create Bottom values when
527
        //   necessary. The point is to always have *some* value for each field that could ever
528
        //   be associated with an object.
529
        //
530
        // - Upsilons and Phis for the constituent fields of a Phi over materializations that we
531
        //   decided to sink.
532
        //
533
        // - Defs for the actual stores to fields that occur in the program.
534
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
535
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
536
                Node* node = block->at(nodeIndex);
537
                
538
                if (node->op() == Upsilon) {
539
                    if (!m_sinkCandidates.contains(node->phi()))
540
                        continue;
541
                    
542
                    
543
                    continue;
544
                }
545
            }
546
            m_insertionSet.execute(block);
547
        }
548
    }
549
550
    template<typename... Args>
551
    static void doNothing(Args...) { }
552
    
553
    template<typename SinkCandidateFunctor, typename EscapeFunctor>
554
    void handleNode(
555
        Node* node,
556
        const SinkCandidateFunctor& sinkCandidate,
557
        const EscapeFunctor& escape)
558
    {
559
        switch (node->op()) {
560
        case NewObject:
561
        case MaterializeNewObject:
562
            sinkCandidate();
563
            break;
564
            
565
        case Phi:
566
            if (m_phiSinkCandidates.contains(node))
567
                sinkCandidate();
568
            break;
569
            
570
        case CheckStructure:
571
        case GetByOffset:
572
        case MultiGetByOffset:
573
        case PutStructure:
574
        case GetGetterSetterByOffset:
575
        case MovHint:
576
            break;
577
            
578
        case PutByOffset:
579
            escape(node->child3().node());
580
            break;
581
            
582
        case MultiPutByOffset:
583
            // FIXME: In the future we should be able to handle this. It's just a matter of
584
            // building the appropriate *Hint variant of this instruction, along with a
585
            // PhantomStructureSelect node - since this transforms the Structure in a conditional
586
            // way.
587
            // https://bugs.webkit.org/show_bug.cgi?id=136924
588
            escape(node->child1().node());
589
            escape(node->child2().node());
590
            break;
591
592
        default:
593
            m_graph.doToChildren(
594
                node,
595
                [&escape] (Edge edge) {
596
                    escape(edge.node());
597
                });
598
            break;
599
        }
600
    }
601
    
602
    NodeType allocationType(Node* escapee)
603
    {
604
        if (escapee->op() == Phi)
605
            return m_phiChildren.upsilonsOf(escapee)->child1().node()->op();
606
        
607
        return esapee->op();
608
    }
609
    
610
    Node* createMaterialize(Node* escapee, const NodeOrigin whereOrigin)
611
    {
612
        switch (allocationType(escapee)) {
613
        case NewObject:
614
        case MaterializeNewObject:
615
            return m_graph.addNode(
616
                escapee->prediction(), MaterializeNewObject,
617
                NodeOrigin(
618
                    escapee->origin.semantic,
619
                    whereOrigin.forExit),
620
                OpInfo(m_graph.m_objectMaterializationData.add()));
621
            
622
        default:
623
            DFG_CRASH(m_graph, where, "Bad escapee op");
624
            return nullpt;
625
        }
626
        
627
        return result;
628
    }
629
    
630
    template<typename WriteFunctor, typename ReadFunctor>
631
    void promoteIncludingMaterializations(
632
        Node* node, const WriteFunctor& write, const ReadFunctor& read)
633
    {
634
        if (node->op() == Upsilon) {
635
            if (!m_sinkCandidates.contains(node->phi()))
636
                return;
637
            
638
            promoteMaterialization(node->child1().node(), node->phi(), write);
639
            return;
640
        }
641
        
642
        promote(node, write, read);
643
    }
644
    
645
    template<typename WriteFunctor, typename ReadFunctor>
646
    void promote(Node* node, const WriteFunctor& write, const ReadFunctor& read)
647
    {
648
        switch (node->op()) {
649
        case CheckStructure:
650
            if (m_sinkCandidates.contains(node->child1().node()))
651
                read(HeapLocation(StructureLoc, JSCell_structureID, node->child1()));
652
            break;
653
            
654
        case GetByOffset:
655
        case GetGetterSetterByOffset:
656
            if (m_sinkCandidates.contains(node->child2().node())) {
657
                unsigned identifierNumber =
658
                    graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
659
                AbstractHeap heap(NamedProperties, identifierNumber);
660
                read(HeapLocation(NamedPropertyLoc, heap, node->child2()));
661
            }
662
            break;
663
                                  
664
        case MultiGetByOffset:
665
            if (m_sinkCandidates.contains(node->child1().node())) {
666
                AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
667
                read(HeapLocation(NamedPropertyLoc, heap, node->child1()));
668
            }
669
            break;
670
            
671
        case PutStructureHint:
672
            if (m_sinkCandidates.contains(node->child1().node()))
673
                write(HeapLocation(StructureLoc, JSCell_structureID, node->child1()), node->child2());
674
            break;
675
            
676
        case PutByOffset:
677
            if (m_sinkCandidates.contains(node->child2().node())) {
678
                unsigned identifierNumber =
679
                    graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
680
                AbstractHeap heap(NamedProperties, identifierNumber);
681
                write(HeapLocation(NamedPropertyLoc, heap, node->child2()), node->child3().node());
682
            }
683
            break;
684
685
        default:
686
            break;
687
        }
688
    }
689
    
690
    template<typename WriteFunctor>
691
    void promoteMaterialization(Node* node, Node* phi, const WriteFunctor& write)
692
    {
693
        ASSERT(node->op() == MaterializeNewObject);
694
        
695
        write(HeapLocation(StructureLoc, JSCell_structureID, phi), m_graph.varArgChild(node, 0));
696
        for (unsigned i = 0; i < node->objectMaterializationData().m_properties.size(); ++i) {
697
            Edge edge = m_graph.varArgChild(node, i + 1);
698
            AbstractHeap heap(NamedProperties, value.m_identifierNumber);
699
            write(HeapLocation(NamedPropertyLoc, heap, phi), edge);
700
        }
701
    }
702
    
703
    PhiChildren m_phiChildren;
704
    HashSet<Node*> m_phiSinkCandidates;
705
    HashSet<Node*> m_sinkCandidates;
706
    HashMap<std::pair<Node*, Node*>, Node*> m_edgeToMaterializationPoint;
707
    HashMap<Node*, Node*> m_materializationPointToEscapee;
708
    InsertionSet m_insertionSet;
709
};
710
    
711
bool performObjectAllocationSinking(Graph& graph)
712
{
713
    SamplingRegion samplingRegion("DFG Object Allocation Sinking Phase");
714
    return runPhase<ObjectAllocationSinkingPhase>(graph);
715
}
716
717
} } // namespace JSC::DFG
718
719
#endif // ENABLE(DFG_JIT)
720
- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.h +47 lines
Line 0 Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.h_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGObjectAllocationSinkingPhase_h
27
#define DFGObjectAllocationSinkingPhase_h
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
class Graph;
34
35
// Sinks object allocations down to their uses. This will sink the allocations over OSR exits, by
36
// replacing all stores to those objects with store hints so that OSR exit can materialize the
37
// object. This may sink allocations past returns, creating control flow paths along which the
38
// objects are not allocated at all. Replaces all uses of the objects' fields with SSA data flow.
39
40
bool performObjectAllocationSinking(Graph&);
41
42
} } // namespace JSC::DFG
43
44
#endif // ENABLE(DFG_JIT)
45
46
#endif // DFGObjectAllocationSinkingPhase_h
47
- Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp +58 lines
Line 0 Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "DFGObjectMaterializationData.h"
28
29
namespace JSC { namespace DFG {
30
31
void PhantomPropertyValue::dump(PrintStream& out) const
32
{
33
    out.print("id", m_identifierNumber);
34
}
35
36
void ObjectMaterializationData::dump(PrintStream& out) const
37
{
38
    out.print("[", listDump(m_properties), "]");
39
}
40
41
float ObjectMaterializationData::oneWaySimilarityScore(
42
    const ObjectMaterializationData& other) const
43
{
44
    unsigned numHits = 0;
45
    for (PhantomPropertyValue value : m_properties) {
46
        if (other.m_properties.contains(value))
47
            numHits++;
48
    }
49
    return static_cast<float>(numHits) / static_cast<float>(m_properties.size());
50
}
51
52
float ObjectMaterializationData::similarityScore(const ObjectMaterializationData& other) const
53
{
54
    return std::min(oneWaySimilarityScore(other), other.oneWaySimilarityScore(*this));
55
}
56
57
} } // namespace JSC::DFG
58
- Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h +62 lines
Line 0 Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGObjectMaterializationData_h
27
#define DFGObjectMaterializationData_h
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
struct PhantomPropertyValue {
34
    unsigned m_identifierNumber;
35
    
36
    bool operator==(const PhantomPropertyValue& other) const
37
    {
38
        return m_identifierNumber == other.m_identifierNumber;
39
    }
40
    
41
    void dump(PrintStream&) const;
42
};
43
44
struct ObjectMaterializationData {
45
    // Determines the meaning of the passed nodes.
46
    Vector<PhantomPropertyValue> m_properties;
47
    
48
    void dump(PrintStream&) const;
49
    
50
    // The fraction of my properties that the other data has.
51
    float oneWaySimilarityScore(const ObjectMaterializationData&) const;
52
    
53
    // The minimum of the two possible one-way scores.
54
    float similarityScore(const ObjectMaterializationData&) const;
55
};
56
57
} } // namespace JSC::DFG
58
59
#endif // ENABLE(DFG_JIT)
60
61
#endif // DFGObjectMaterializationData_h
62
- Source/JavaScriptCore/dfg/DFGPhiChildren.cpp +61 lines
Line 0 Source/JavaScriptCore/dfg/DFGPhiChildren.cpp_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "DFGPhiChildren.h"
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
PhiChildren::PhiChildren()
34
{
35
}
36
37
PhiChildren::PhiChildren(Graph& graph)
38
{
39
    for (BasicBlock* block : graph.blocksInNaturalOrder()) {
40
        for (Node* node : *block) {
41
            if (node->op() != Upsilon)
42
                continue;
43
            
44
            m_children.add(node->phi(), List()).iterator->value.append(node);
45
        }
46
    }
47
}
48
49
PhiChildren::~PhiChildren()
50
{
51
}
52
53
const PhiChildren::List& PhiChildren::childrenOf(Node* node) const
54
{
55
    return m_children.get(node);
56
}
57
58
} } // namespace JSC::DFG
59
60
#endif // ENABLE(DFG_JIT)
61
- Source/JavaScriptCore/dfg/DFGPhiChildren.h +53 lines
Line 0 Source/JavaScriptCore/dfg/DFGPhiChildren.h_sec1
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGPhiChildren_h
27
#define DFGPhiChildren_h
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
class PhiChildren {
34
public:
35
    typedef Vector<Node*, 3> List;
36
    
37
    PhiChildren();
38
    PhiChildren(Graph&);
39
    ~PhiChildren();
40
    
41
    // The list of Upsilons that point to the children of the Phi.
42
    const List& upsilonsOf(Node*) const;
43
    
44
private:
45
    HashMap<Node*, List> m_children;
46
};
47
48
} } // namespace JSC::DFG
49
50
#endif // ENABLE(DFG_JIT)
51
52
#endif // DFGPhiChildren_h
53

Return to Bug 136330