| 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
        m_opInfo = storageAccessData().identifierNumber;
504
        child1() = child2();
505
        child2() = child3();
506
        child3() = Edge();
507
    }
508
    
509
    void convertToPutStructureHint(Node* structure)
510
    {
511
        ASSERT(m_op == PutStructure);
512
        ASSERT(structure->structure() == transition()->next);
513
        m_op = PhantomPutStructure;
514
        m_opInfo = 0;
515
        child2() = Edge(structure, KnownCellUse);
516
    }
517
    
498
    void convertToPhantomLocal()
518
    void convertToPhantomLocal()
499
    {
519
    {
500
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
520
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
Lines 699-704 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec3
699
        case PutById:
719
        case PutById:
700
        case PutByIdFlush:
720
        case PutByIdFlush:
701
        case PutByIdDirect:
721
        case PutByIdDirect:
722
        case PutByOffsetHint:
702
            return true;
723
            return true;
703
        default:
724
        default:
704
            return false;
725
            return false;
Lines 1100-1105 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec4
1100
    {
1121
    {
1101
        switch (op()) {
1122
        switch (op()) {
1102
        case PutStructure:
1123
        case PutStructure:
1124
        case PutStructureHint:
1103
        case AllocatePropertyStorage:
1125
        case AllocatePropertyStorage:
1104
        case ReallocatePropertyStorage:
1126
        case ReallocatePropertyStorage:
1105
            return true;
1127
            return true;
Lines 1136-1141 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec5
1136
        case ArrayifyToStructure:
1158
        case ArrayifyToStructure:
1137
        case NewObject:
1159
        case NewObject:
1138
        case NewStringObject:
1160
        case NewStringObject:
1161
        case PhantomStructure:
1139
            return true;
1162
            return true;
1140
        default:
1163
        default:
1141
            return false;
1164
            return false;
Lines 1150-1156 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec6
1150
    
1173
    
1151
    bool hasStorageAccessData()
1174
    bool hasStorageAccessData()
1152
    {
1175
    {
1153
        return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset;
1176
        switch (op()) {
1177
        case GetByOffset:
1178
        case PutByOffset:
1179
        case GetGetterSetterByOffset:
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_sec7
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 +667 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
        // We could also add this rule:
72
        //
73
        // - If all of the Upsilons of a Phi have a MaterializeNewObject that isn't used by anyone
74
        //   else, then replace the Phi with the MaterializeNewObject.
75
        //
76
        //   FIXME: Implement this. Note that this totally doable but it requires some gnarly
77
        //   code, and to be effective the pruner needs to be aware of it. Currently any Upsilon
78
        //   is considered to be an escape even by the pruner, so it's unlikely that we'll see
79
        //   many cases of Phi over Materializations.
80
        //   https://bugs.webkit.org/show_bug.cgi?id=136927
81
        
82
        if (!performSinking(DontConsiderPhis))
83
            return false;
84
        
85
        while (performSinking(ConsiderPhis)) { }
86
        
87
        return true;
88
    }
89
90
private:
91
    bool performSinking(PhiMode phiMode)
92
    {
93
        m_graph.computeRefCounts();
94
        
95
        performLivenessAnalysis();
96
        performOSRAvailabilityAnalysis();
97
        
98
        // We want to only do sinking for those things that would benefit. We use a rough
99
        // heuristic: if it's possible for an allocation to make it to a return without escaping,
100
        // then we assume that it's worth sinking. It's a simple forward flow problem.
101
        //
102
        // It just so happens that this forward flow problem also tells us where we would
103
        // materialize those nodes that we choose to sink.
104
        pruneSinkingCandidates();
105
        if (m_sinkCandidates.isEmpty())
106
            return false;
107
        
108
        // At this point we are committed to sinking the sinking candidates.
109
        determineMaterializationPoints();
110
        placeMaterializationPoints();
111
        lowerOperationsOnPhantomAllocations();
112
        promoteSunkenFields();
113
        
114
        return true;
115
    }
116
    
117
    void pruneSinkingCandidates()
118
    {
119
        m_sinkCandidates.clear();
120
        BlockMap<HashSet<Node*>> sinkCandidatesAtHead(m_graph);
121
        BlockMap<HashSet<Node*>> sinkCandidatesAtTail(m_graph);
122
        
123
        bool changed;
124
        do {
125
            changed = false;
126
            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
127
                HashSet<Node*> sinkCandidates = sinkCandidatesAtHead[block];
128
                for (Node* node : *block) {
129
                    handleNode(
130
                        node,
131
                        [&] () {
132
                            sinkCandidates.add(node);
133
                        },
134
                        [&] (Node* escapee) {
135
                            sinkCandidates.remove(escapee);
136
                        });
137
                }
138
                if (sinkCandidatesAtTail[block] == sinkCandidates)
139
                    continue;
140
                
141
                sinkCandidatesAtTail[block] = sinkCandidates;
142
                changed = true;
143
                
144
                for (BasicBlock* successorBlock : block->successors()) {
145
                    for (Node* sinkCandidate : sinkCandidates) {
146
                        if (!successorBlock->ssa->liveAtHead.contains(sinkCandidate))
147
                            continue;
148
                        sinkCandidatesAtHead[successorBlock].add(sinkCandidate);
149
                    }
150
                }
151
            }
152
        } while (changed);
153
        
154
        // A node is a sink candidate if it is in the sinkCandidatesAtTail of a block but not in
155
        // the liveAtTail of that same block.
156
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
157
            for (Node* sinkCandidate : sinkCandidatesAtTail[block]) {
158
                if (!block->ssa->liveAtTail.contains(sinkCandidate))
159
                    m_sinkCandidates.add(sinkCandidate);
160
            }
161
        }
162
        
163
        // A node should be materialized if it is a sinking candidate, and we haven't removed it
164
        // from the sink candidates set yet - since that means that it may not have been
165
        // materialized yet.
166
        // FIXME: oddly, anytime that we would have a basic block where something is "maybe
167
        // materialized", we would make it always materialized by having the not-materializing
168
    }
169
    
170
    void determineMaterializationPoints()
171
    {
172
        // The premise of this pass is that if there exists a point in the program where some
173
        // path from a phantom allocation site to that point causes materialization, then *all*
174
        // paths cause materialization. This should mean that there are never any redundant
175
        // materializations.
176
        
177
        m_edgeToMaterializationPoint.clear();
178
        
179
        BlockMap<HashSet<Node*>> materializedAtHead;
180
        BlockMap<HashSet<Node*>> materializedAtTail;
181
        
182
        bool changed;
183
        do {
184
            changed = false;
185
            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
186
                HashSet<Node*> materialized = materializedAtHead[block];
187
                for (Node* node : *block) {
188
                    handleNode(
189
                        node,
190
                        doNothing,
191
                        [&] (Node* escapee) {
192
                            if (m_sinkCandidates.contains(escapee))
193
                                materialized.add(escapee);
194
                        });
195
                }
196
                
197
                if (materialized == materializedAtTail[block])
198
                    continue;
199
                
200
                changed = true;
201
                
202
                for (BasicBlock* successorBlock : block->successors()) {
203
                    for (Node* materializee : materialized) {
204
                        if (!successorBlock->ssa->liveAtHead.contains(materializee))
205
                            continue;
206
                        materializedAtHead[successorBlock].add(materializee);
207
                    }
208
                }
209
            }
210
        } while (changed);
211
        
212
        // A materialization edge exists at any point where a node escapes but hasn't been
213
        // materialized yet.
214
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
215
            HashSet<Node*> materialized = materializedAtHead[block];
216
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
217
                Node* node = block->at(nodeIndex);
218
                
219
                handleNode(
220
                    node,
221
                    doNothing,
222
                    [&] (Node* escapee) {
223
                        if (!m_sinkCandidates.contains(escapee))
224
                            return;
225
                        
226
                        if (!materialized.add(escapee))
227
                            return;
228
                        
229
                        m_edgeToMaterializationPoint.add(
230
                            std::make_pair(where, escapee),
231
                            createMaterialize(escapee, node->origin));
232
                    });
233
            }
234
        }
235
    }
236
    
237
    void placeMaterializationPoints()
238
    {
239
        SSACalculator ssaCalculator(m_graph);
240
        
241
        HashMap<Node*, SSACalculator::Variable*> nodeToVariable;
242
        Vector<Node*> indexToNode;
243
        
244
        for (Node* node : m_sinkCandidates) {
245
            SSACalculator::Variable* variable = ssaCalculator.newVariable();
246
            nodeToVariable.add(node, variable);
247
            ASSERT(indexToNode.size() == variable->index());
248
            indexToNode.append(node);
249
        }
250
        
251
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
252
            for (Node* node : *block) {
253
                if (SSACalculator::Variable* variable = nodeToVariable.get(node))
254
                    ssaCalculator.newDef(variable, block, node);
255
                
256
                m_graph.doToChildren(
257
                    node,
258
                    [&] (Edge edge) {
259
                        Node* materialize =
260
                            m_edgeToMaterializationPoint.get(std::make_pair(node, edge.node()));
261
                        if (!materialize)
262
                            return;
263
                        
264
                        ssaCalculator.newDef(
265
                            nodeToVariable.get(edge.node()), block, materialize);
266
                    });
267
            }
268
        }
269
        
270
        ssaCalculator.computePhis(
271
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
272
                Node* allocation = indexToNode[variable->index()];
273
                if (!block->ssa->liveAtHead.contains(allocation))
274
                    return nullptr;
275
                
276
                Node* phiNode = m_graph.addNode(
277
                    allocation->prediction(), Phi, NodeOrigin());
278
                phiNode->mergeFlags(NodeResultJS);
279
                return phiNode;
280
            });
281
        
282
        // Place Phis in the right places. Replace all uses of any allocation with the appropriate
283
        // materialization. Create the appropriate Upsilon nodes.
284
        LocalOSRAvailabilityCalculator availabilityCalculator;
285
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
286
            HashMap<Node*, Node*> mapping;
287
            
288
            for (Node* candidate : block->ssa->liveAtHead) {
289
                SSACalculator::Variable* variable = nodeToVariable.get(candidate);
290
                if (!variable)
291
                    continue;
292
                
293
                Def* def = ssaCalculator.reachingDefAtHead(block, variable);
294
                if (!def)
295
                    continue;
296
                
297
                mapping.add(indexToNode[variable->index()], def->value());
298
            }
299
            
300
            availabilityCalculator.beginBlock(block);
301
            for (SSACalculator::Def* phiDef : ssaCalculator.phisForBlock(block)) {
302
                m_insertionSet.insert(0, phiDef->value());
303
                
304
                Node* originalNode = indexToNode[phiDef->variable()->index()];
305
                insertOSRHintsForUpdate(
306
                    m_insertionSet, 0, availabilityCalculator, originalNode, phiDef->value());
307
308
                mapping.add(originalNode, phiDef->value());
309
            }
310
            
311
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
312
                Node* node = block->at(nodeIndex);
313
314
                m_graph.doToChildEdges(
315
                    node,
316
                    [&] (Edge edge) {
317
                        Node* materialize = m_edgeToMaterializationPoint.get(
318
                            std::make_pair(node, edge.node()));
319
                        if (materialize) {
320
                            m_insertionSet.insert(nodeIndex, materialize);
321
                            insertOSRHintsForUpdate(
322
                                m_insertionSet, nodeIndex, availabilityCalculator,
323
                                edge.node(), materialize);
324
                        }
325
                    });
326
327
                availabilityCalculator.executeNode(node);
328
                
329
                m_graph.doToChildEdges(
330
                    node,
331
                    [&] (Edge& edge) {
332
                        if (Node* materialize = mapping.get(edge.node()))
333
                            edge.setNode(materialize);
334
                    });
335
            }
336
            
337
            size_t upsilonInsertionPoint = block->size() - 1;
338
            NodeOrigin upsilonOrigin = block->last()->origin;
339
            for (BasicBlock* successorBlock : block->successors()) {
340
                for (SSACalculator::Def* phiDef : ssaCalculator.phisForBlock(successorBlock)) {
341
                    Node* phiNode = phiDef->value();
342
                    SSACalculator::Variable* variable = phiDef->variable();
343
                    Node* allocation = indexToNode[variable->index()];
344
                    
345
                    Node* originalIncoming = mapping.get(allocation);
346
                    Node* incoming;
347
                    if (originalIncoming == allocation) {
348
                        // If we have a Phi that combines materializations with the original
349
                        // phantom object, then the path with the phantom object must materialize.
350
                        
351
                        incoming = createMaterialize(allocation, upsilonOrigin);
352
                        m_insertionSet.insert(upsilonInsertionPoint, incoming);
353
                        insertOSRHintsForUpdate(
354
                            m_insertionSet, upsilonInsertionPoint, availabilityCalculator,
355
                            originalIncoming, incoming);
356
                    } else
357
                        incoming = originalIncoming;
358
                    
359
                    Node* upsilon = m_insertionSet.insertNode(
360
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
361
                        OpInfo(phiNode), incoming->defaultEdge());
362
                    
363
                    if (originalIncoming == allocation) {
364
                        m_edgeToMaterializationPoint.add(
365
                            std::make_pair(upsilon, allocation), incoming);
366
                    }
367
                }
368
            }
369
            
370
            m_insertionSet.execute(block);
371
        }
372
        
373
        // At this point we have dummy materialization nodes along with edges to them. This means
374
        // that the part of the control flow graph that prefers to see actual object allocations
375
        // is completely fixed up, except for the materializations themselves.
376
    }
377
    
378
    void lowerNonReadingOperationsOnPhantomAllocations()
379
    {
380
        // Lower everything but reading operations on phantom allocations. We absolutely have to
381
        // lower all writes so as to reveal them to the SSA calculator. We cannot lower reads
382
        // because the whole point is that those go away completely.
383
        
384
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
385
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
386
                Node* node = block->at(nodeIndex);
387
                switch (node->op()) {
388
                case PutByOffset: {
389
                    if (m_sinkCandidates.contains(node->child2().node()))
390
                        node->convertToPutByOffsetHint();
391
                    break;
392
                }
393
                    
394
                case PutStructure: {
395
                    if (m_sinkCandidates.contains(node->child1().node())) {
396
                        Node* structure = m_insertionSet.insertNode(
397
                            nodeIndex, SpecCellOther, PhantomStructure, node->origin,
398
                            OpInfo(node->transition()->next));
399
                        node->convertToPutStructureHint(structure);
400
                    }
401
                    break;
402
                }
403
                    
404
                case NewObject: {
405
                    if (m_sinkCandidates.contains(node)) {
406
                        Node* structure = m_insertionSet.insertNode(
407
                            nodeIndex + 1, SpecCellOther, PhantomStructure, node->origin,
408
                            OpInfo(node->structure()));
409
                        m_insertionSet.insertNode(
410
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
411
                            Edge(node, KnownCellUse), Edge(structure, KnownCellUse));
412
                        node->convertToPhantomNewObject();
413
                    }
414
                    break;
415
                }
416
                    
417
                case MaterializeNewObject: {
418
                    if (m_sinkCandidates.contains(node)) {
419
                        m_insertionSet.insertNode(
420
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
421
                            Edge(node, KnownCellUse), m_graph.varArgChild(node, 0));
422
                        for (unsigned i = 0; i < node->objectMaterializationData().m_properties.size(); ++i) {
423
                            m_insertionSet.insertNode(
424
                                nodeIndex + 1, SpecNone, PutByOffsetHint, node->origin,
425
                                Edge(node, KnownCellUse),m_graph.varArgChild(node, i + 1));
426
                        }
427
                        node->convertToPhantomNewObject();
428
                    }
429
                    break;
430
                }
431
                    
432
                default:
433
                    break;
434
                }
435
            }
436
            m_insertionSet.execute(block);
437
        }
438
    }
439
    
440
    void promoteSunkenFields()
441
    {
442
        // Henceforth when we encounter a materialization point, we will want to ask *who* it is
443
        // a materialization for. Invert the map to be able to answer such questions.
444
        m_materializationPointToEscapee.clear();
445
        for (auto pair : m_edgeToMaterializationPoint)
446
            m_materializationPointToEscapee.add(pair.value, pair.key.second);
447
        
448
        // Collect the set of heap locations that we will be operating over.
449
        HashSet<HeapLocation> locations;
450
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
451
            for (Node* node : *block) {
452
                promote(
453
                    node,
454
                    [&] (HeapLocation location, Edge) {
455
                        locations.add(location);
456
                    },
457
                    [&] (HeapLocation location) {
458
                        locations.add(location);
459
                    });
460
            }
461
        }
462
        
463
        // Figure out which locations belong to which allocations.
464
        HashMap<Node*, Vector<HeapLocation>> locationsForAllocation;
465
        for (HeapLocation location : locations) {
466
            auto result = locationsForAllocation.add(location.base(), Vector<HeapLocation>());
467
            ASSERT(!result.iterator->value.contains(location));
468
            result.iterator->value.append(location);
469
        }
470
        
471
        // For each sunken thingy, make sure we create Bottom values for all of its fields.
472
        // Note that this has the hilarious slight inefficiency of creating redundant hints for
473
        // things that were previously materializations. This should only impact compile times and
474
        // not code quality, and it's necessary for soundness without some data structure hackage.
475
        // For example, a MaterializeNewObject that we choose to sink may have new fields added to
476
        // it conditionally. That would necessitate Bottoms.
477
        Node* bottom = nullptr;
478
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
479
            if (block == m_graph.block(0))
480
                bottom = m_insertionSet.insertNode(0, SpecNone, Bottom, NodeOrigin());
481
            
482
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
483
                Node* node = block->at(nodeIndex);
484
                for (HeapLocation location : locationsForAllocation.get(node)) {
485
                    switch (location.kind()) {
486
                    case StructureLoc:
487
                        ASSERT(location.heap() == AbstractHeap(JSCell_structureID));
488
                        m_insertionSet.insertNode(
489
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
490
                            Edge(node, KnownCellUse), bottom);
491
                        break;
492
                        
493
                    case NamedPropertyLoc:
494
                        ASSERT(location.heap().kind() == NamedProperties);
495
                        m_insertionSet.insertNode(
496
                            nodeIndex + 1, SpecNone, PutByOffsetHint, node->origin,
497
                            OpInfo(location.heap().payload().value()),
498
                            Edge(node, KnownCellUse), bottom);
499
                        break;
500
                        
501
                    default:
502
                        DFG_CRASH(m_graph, node, "Bad heap location kind");
503
                    }
504
                }
505
            }
506
            m_insertionSet.execute(block);
507
        }
508
        
509
        SSACalculator ssaCalculator(m_graph);
510
511
        // Collect the set of "variables" that we will be sinking.
512
        HashMap<HeapLocation, SSACalculator::Variable*> locationToVariable;
513
        Vector<HeapLocation> indexToLocation;
514
        for (HeapLocation location : locations) {
515
            SSACalculator::Variable* variable = ssaCalculator.newVariable();
516
            locationToVariable.add(location, variable);
517
            ASSERT(indexToLocation.size() == variable->index());
518
            indexToLocation.append(location);
519
        }
520
        
521
        // Create Defs from the existing hints.
522
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
523
            for (Node* node : *block) {
524
                promote(
525
                    node,
526
                    [&] (HeapLocation location, Edge value) {
527
                        SSACalculator::Variable* variable = locationToVariable.get(location);
528
                        ssaCalculator.newDef(variable, block, value.node());
529
                    });
530
            }
531
        }
532
        
533
        // OMG run the SSA calculator to create Phis!
534
        ssaCalculator.computePhis(
535
            [&] (SSACalculator::Variable* variable, BasicBlock* block) {
536
                
537
            });
538
    }
539
540
    template<typename... Args>
541
    static void doNothing(Args...) { }
542
    
543
    template<typename SinkCandidateFunctor, typename EscapeFunctor>
544
    void handleNode(
545
        Node* node,
546
        const SinkCandidateFunctor& sinkCandidate,
547
        const EscapeFunctor& escape)
548
    {
549
        switch (node->op()) {
550
        case NewObject:
551
        case MaterializeNewObject:
552
            sinkCandidate();
553
            break;
554
            
555
        case CheckStructure:
556
        case GetByOffset:
557
        case MultiGetByOffset:
558
        case PutStructure:
559
        case GetGetterSetterByOffset:
560
        case MovHint:
561
            break;
562
            
563
        case PutByOffset:
564
            escape(node->child3().node());
565
            break;
566
            
567
        case MultiPutByOffset:
568
            // FIXME: In the future we should be able to handle this. It's just a matter of
569
            // building the appropriate *Hint variant of this instruction, along with a
570
            // PhantomStructureSelect node - since this transforms the Structure in a conditional
571
            // way.
572
            // https://bugs.webkit.org/show_bug.cgi?id=136924
573
            escape(node->child1().node());
574
            escape(node->child2().node());
575
            break;
576
577
        default:
578
            m_graph.doToChildren(
579
                node,
580
                [&escape] (Edge edge) {
581
                    escape(edge.node());
582
                });
583
            break;
584
        }
585
    }
586
    
587
    Node* createMaterialize(Node* escapee, const NodeOrigin whereOrigin)
588
    {
589
        switch (escapee->op()) {
590
        case NewObject:
591
        case MaterializeNewObject:
592
            return m_graph.addNode(
593
                escapee->prediction(), MaterializeNewObject,
594
                NodeOrigin(
595
                    escapee->origin.semantic,
596
                    whereOrigin.forExit),
597
                OpInfo(m_graph.m_objectMaterializationData.add()));
598
            
599
        default:
600
            DFG_CRASH(m_graph, where, "Bad escapee op");
601
            return nullpt;
602
        }
603
        
604
        return result;
605
    }
606
    
607
    template<typename WriteFunctor, typename ReadFunctor>
608
    void promote(Node* node, const WriteFunctor& write, const ReadFunctor& read)
609
    {
610
        switch (node->op()) {
611
        case CheckStructure:
612
            if (m_sinkCandidates.contains(node->child1().node()))
613
                read(HeapLocation(StructureLoc, JSCell_structureID, node->child1()));
614
            break;
615
            
616
        case GetByOffset:
617
        case GetGetterSetterByOffset:
618
            if (m_sinkCandidates.contains(node->child2().node())) {
619
                unsigned identifierNumber =
620
                    graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
621
                AbstractHeap heap(NamedProperties, identifierNumber);
622
                read(HeapLocation(NamedPropertyLoc, heap, node->child2()));
623
            }
624
            break;
625
                                  
626
        case MultiGetByOffset:
627
            if (m_sinkCandidates.contains(node->child1().node())) {
628
                AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
629
                read(HeapLocation(NamedPropertyLoc, heap, node->child1()));
630
            }
631
            break;
632
            
633
        case PutStructureHint:
634
            if (m_sinkCandidates.contains(node->child1().node()))
635
                write(HeapLocation(StructureLoc, JSCell_structureID, node->child1()), node->child2());
636
            break;
637
            
638
        case PutByOffsetHint:
639
            if (m_sinkCandidates.contains(node->child1().node())) {
640
                unsigned identifierNumber = node->identifierNumber();
641
                AbstractHeap heap(NamedProperties, identifierNumber);
642
                write(HeapLocation(NamedPropertyLoc, heap, node->child1()), node->child2().node());
643
            }
644
            break;
645
646
        default:
647
            break;
648
        }
649
    }
650
    
651
    PhiChildren m_phiChildren;
652
    HashSet<Node*> m_sinkCandidates;
653
    HashMap<std::pair<Node*, Node*>, Node*> m_edgeToMaterializationPoint;
654
    HashMap<Node*, Node*> m_materializationPointToEscapee;
655
    InsertionSet m_insertionSet;
656
};
657
    
658
bool performObjectAllocationSinking(Graph& graph)
659
{
660
    SamplingRegion samplingRegion("DFG Object Allocation Sinking Phase");
661
    return runPhase<ObjectAllocationSinkingPhase>(graph);
662
}
663
664
} } // namespace JSC::DFG
665
666
#endif // ENABLE(DFG_JIT)
667
- 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