| 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 / +51 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
    
518
    void convertToPhantomNewObject()
519
    {
520
        ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
521
        m_op = PhantomNewObject;
522
        m_flags &= ~NodeHasVarArgs;
523
        m_opInfo = 0;
524
        m_opInfo2 = 0;
525
        children = AdjacencyList();
526
    }
527
    
498
    void convertToPhantomLocal()
528
    void convertToPhantomLocal()
499
    {
529
    {
500
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
530
        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:
729
        case PutById:
700
        case PutByIdFlush:
730
        case PutByIdFlush:
701
        case PutByIdDirect:
731
        case PutByIdDirect:
732
        case PutByOffsetHint:
702
            return true;
733
            return true;
703
        default:
734
        default:
704
            return false;
735
            return false;
Lines 1100-1105 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec4
1100
    {
1131
    {
1101
        switch (op()) {
1132
        switch (op()) {
1102
        case PutStructure:
1133
        case PutStructure:
1134
        case PutStructureHint:
1103
        case AllocatePropertyStorage:
1135
        case AllocatePropertyStorage:
1104
        case ReallocatePropertyStorage:
1136
        case ReallocatePropertyStorage:
1105
            return true;
1137
            return true;
Lines 1136-1141 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec5
1136
        case ArrayifyToStructure:
1168
        case ArrayifyToStructure:
1137
        case NewObject:
1169
        case NewObject:
1138
        case NewStringObject:
1170
        case NewStringObject:
1171
        case PhantomStructure:
1139
            return true;
1172
            return true;
1140
        default:
1173
        default:
1141
            return false;
1174
            return false;
Lines 1150-1156 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec6
1150
    
1183
    
1151
    bool hasStorageAccessData()
1184
    bool hasStorageAccessData()
1152
    {
1185
    {
1153
        return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset;
1186
        switch (op()) {
1187
        case GetByOffset:
1188
        case PutByOffset:
1189
        case GetGetterSetterByOffset:
1190
            return true;
1191
        default:
1192
            return false;
1193
        }
1154
    }
1194
    }
1155
    
1195
    
1156
    unsigned storageAccessDataIndex()
1196
    unsigned storageAccessDataIndex()
Lines 1179-1184 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec7
1179
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1219
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1180
    }
1220
    }
1181
    
1221
    
1222
    bool hasObjectMaterializationData()
1223
    {
1224
        return op() == MaterializeNewObject;
1225
    }
1226
    
1227
    ObjectMaterializationData& objectMaterializationData()
1228
    {
1229
        return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo);
1230
    }
1231
    
1182
    bool hasFunctionDeclIndex()
1232
    bool hasFunctionDeclIndex()
1183
    {
1233
    {
1184
        return op() == NewFunction
1234
        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 +734 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_ssaCalculator(graph)
45
        , m_insertionSet(graph)
46
    {
47
    }
48
    
49
    bool run()
50
    {
51
        ASSERT(m_graph.m_fixpointState == FixpointNotConverged);
52
        
53
        m_changed = false;
54
        
55
        // Logically we wish to consider every NewObject and sink it. However it's definitely not
56
        // profitable to sink a NewObject that will always escape. So, first we do a very simple
57
        // forward flow analysis that determines the set of NewObject nodes that have any chance
58
        // of benefiting from object allocation sinking. Then we fixpoint the following rules:
59
        //
60
        // - For each NewObject, we turn the original NewObject into a PhantomNewObject and then
61
        //   we insert MaterializeNewObject just before each escaping site. Note that Upsilons
62
        //   constitute escaping sites. Then we use forward flow to eliminate unnecessary cases of
63
        //   MaterializeNewObject. We use the SSACalculator to insert these materializations. If a
64
        //   Phi is ever created that has the PhantomNewObject as one of its kids, then we insert
65
        //   a MaterializeNewObject in front of it; this way we never have a Phi that is confused
66
        //   about whether or not it has the real object. We then turn each PutByOffset over a
67
        //   PhantomNewObject into a PutByOffsetHint.
68
        //
69
        // - We perform the same optimization for MaterializeNewObject. This allows us to cover
70
        //   cases where we had MaterializeNewObject flowing into a PutByOffsetHint.
71
        //
72
        // We could also add this rule:
73
        //
74
        // - If all of the Upsilons of a Phi have a MaterializeNewObject that isn't used by anyone
75
        //   else, then replace the Phi with the MaterializeNewObject.
76
        //
77
        //   FIXME: Implement this. Note that this totally doable but it requires some gnarly
78
        //   code, and to be effective the pruner needs to be aware of it. Currently any Upsilon
79
        //   is considered to be an escape even by the pruner, so it's unlikely that we'll see
80
        //   many cases of Phi over Materializations.
81
        //   https://bugs.webkit.org/show_bug.cgi?id=136927
82
        
83
        if (!performSinking())
84
            return false;
85
        
86
        while (performSinking()) { }
87
        
88
        return true;
89
    }
90
91
private:
92
    bool performSinking()
93
    {
94
        m_graph.computeRefCounts();
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
        lowerNonReadingOperationsOnPhantomAllocations();
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
        m_ssaCalculator.reset();
240
        
241
        HashMap<Node*, SSACalculator::Variable*> nodeToVariable;
242
        Vector<Node*> indexToNode;
243
        
244
        for (Node* node : m_sinkCandidates) {
245
            SSACalculator::Variable* variable = m_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
                    m_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
                        m_ssaCalculator.newDef(
265
                            nodeToVariable.get(edge.node()), block, materialize);
266
                    });
267
            }
268
        }
269
        
270
        m_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(allocation->prediction(), Phi, NodeOrigin());
277
                phiNode->mergeFlags(NodeResultJS);
278
                return phiNode;
279
            });
280
        
281
        // Place Phis in the right places. Replace all uses of any allocation with the appropriate
282
        // materialization. Create the appropriate Upsilon nodes.
283
        LocalOSRAvailabilityCalculator availabilityCalculator;
284
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
285
            HashMap<Node*, Node*> mapping;
286
            
287
            for (Node* candidate : block->ssa->liveAtHead) {
288
                SSACalculator::Variable* variable = nodeToVariable.get(candidate);
289
                if (!variable)
290
                    continue;
291
                
292
                Def* def = m_ssaCalculator.reachingDefAtHead(block, variable);
293
                if (!def)
294
                    continue;
295
                
296
                mapping.add(indexToNode[variable->index()], def->value());
297
            }
298
            
299
            availabilityCalculator.beginBlock(block);
300
            for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) {
301
                m_insertionSet.insert(0, phiDef->value());
302
                
303
                Node* originalNode = indexToNode[phiDef->variable()->index()];
304
                insertOSRHintsForUpdate(
305
                    m_insertionSet, 0, availabilityCalculator, originalNode, phiDef->value());
306
307
                mapping.add(originalNode, phiDef->value());
308
            }
309
            
310
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
311
                Node* node = block->at(nodeIndex);
312
313
                m_graph.doToChildEdges(
314
                    node,
315
                    [&] (Edge edge) {
316
                        Node* materialize = m_edgeToMaterializationPoint.get(
317
                            std::make_pair(node, edge.node()));
318
                        if (materialize) {
319
                            m_insertionSet.insert(nodeIndex, materialize);
320
                            insertOSRHintsForUpdate(
321
                                m_insertionSet, nodeIndex, availabilityCalculator,
322
                                edge.node(), materialize);
323
                        }
324
                    });
325
326
                availabilityCalculator.executeNode(node);
327
                
328
                m_graph.doToChildEdges(
329
                    node,
330
                    [&] (Edge& edge) {
331
                        if (Node* materialize = mapping.get(edge.node()))
332
                            edge.setNode(materialize);
333
                    });
334
            }
335
            
336
            size_t upsilonInsertionPoint = block->size() - 1;
337
            NodeOrigin upsilonOrigin = block->last()->origin;
338
            for (BasicBlock* successorBlock : block->successors()) {
339
                for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) {
340
                    Node* phiNode = phiDef->value();
341
                    SSACalculator::Variable* variable = phiDef->variable();
342
                    Node* allocation = indexToNode[variable->index()];
343
                    
344
                    Node* originalIncoming = mapping.get(allocation);
345
                    Node* incoming;
346
                    if (originalIncoming == allocation) {
347
                        // If we have a Phi that combines materializations with the original
348
                        // phantom object, then the path with the phantom object must materialize.
349
                        
350
                        incoming = createMaterialize(allocation, upsilonOrigin);
351
                        m_insertionSet.insert(upsilonInsertionPoint, incoming);
352
                        insertOSRHintsForUpdate(
353
                            m_insertionSet, upsilonInsertionPoint, availabilityCalculator,
354
                            originalIncoming, incoming);
355
                    } else
356
                        incoming = originalIncoming;
357
                    
358
                    Node* upsilon = m_insertionSet.insertNode(
359
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
360
                        OpInfo(phiNode), incoming->defaultEdge());
361
                    
362
                    if (originalIncoming == allocation) {
363
                        m_edgeToMaterializationPoint.add(
364
                            std::make_pair(upsilon, allocation), incoming);
365
                    }
366
                }
367
            }
368
            
369
            m_insertionSet.execute(block);
370
        }
371
        
372
        // At this point we have dummy materialization nodes along with edges to them. This means
373
        // that the part of the control flow graph that prefers to see actual object allocations
374
        // is completely fixed up, except for the materializations themselves.
375
    }
376
    
377
    void lowerNonReadingOperationsOnPhantomAllocations()
378
    {
379
        // Lower everything but reading operations on phantom allocations. We absolutely have to
380
        // lower all writes so as to reveal them to the SSA calculator. We cannot lower reads
381
        // because the whole point is that those go away completely.
382
        
383
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
384
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
385
                Node* node = block->at(nodeIndex);
386
                switch (node->op()) {
387
                case PutByOffset: {
388
                    if (m_sinkCandidates.contains(node->child2().node()))
389
                        node->convertToPutByOffsetHint();
390
                    break;
391
                }
392
                    
393
                case PutStructure: {
394
                    if (m_sinkCandidates.contains(node->child1().node())) {
395
                        Node* structure = m_insertionSet.insertNode(
396
                            nodeIndex, SpecCellOther, PhantomStructure, node->origin,
397
                            OpInfo(node->transition()->next));
398
                        node->convertToPutStructureHint(structure);
399
                    }
400
                    break;
401
                }
402
                    
403
                case NewObject: {
404
                    if (m_sinkCandidates.contains(node)) {
405
                        Node* structure = m_insertionSet.insertNode(
406
                            nodeIndex + 1, SpecCellOther, PhantomStructure, node->origin,
407
                            OpInfo(node->structure()));
408
                        m_insertionSet.insertNode(
409
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
410
                            Edge(node, KnownCellUse), Edge(structure, KnownCellUse));
411
                        node->convertToPhantomNewObject();
412
                    }
413
                    break;
414
                }
415
                    
416
                case MaterializeNewObject: {
417
                    if (m_sinkCandidates.contains(node)) {
418
                        m_insertionSet.insertNode(
419
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
420
                            Edge(node, KnownCellUse), m_graph.varArgChild(node, 0));
421
                        for (unsigned i = 0; i < node->objectMaterializationData().m_properties.size(); ++i) {
422
                            m_insertionSet.insertNode(
423
                                nodeIndex + 1, SpecNone, PutByOffsetHint, node->origin,
424
                                Edge(node, KnownCellUse),m_graph.varArgChild(node, i + 1));
425
                        }
426
                        node->convertToPhantomNewObject();
427
                    }
428
                    break;
429
                }
430
                    
431
                default:
432
                    break;
433
                }
434
            }
435
            m_insertionSet.execute(block);
436
        }
437
    }
438
    
439
    void promoteSunkenFields()
440
    {
441
        // Henceforth when we encounter a materialization point, we will want to ask *who* it is
442
        // a materialization for. Invert the map to be able to answer such questions.
443
        m_materializationPointToEscapee.clear();
444
        for (auto pair : m_edgeToMaterializationPoint)
445
            m_materializationPointToEscapee.add(pair.value, pair.key.second);
446
        
447
        // Collect the set of heap locations that we will be operating over.
448
        HashSet<PromotedHeapLocation> locations;
449
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
450
            for (Node* node : *block) {
451
                promote(
452
                    node,
453
                    [&] (PromotedHeapLocation location, Edge) {
454
                        locations.add(location);
455
                    },
456
                    [&] (PromotedHeapLocation location) {
457
                        locations.add(location);
458
                    });
459
            }
460
        }
461
        
462
        // Figure out which locations belong to which allocations.
463
        m_locationsForAllocation.clear();
464
        for (PromotedHeapLocation location : locations) {
465
            auto result = m_locationsForAllocation.add(location.base(), Vector<PromotedHeapLocation>());
466
            ASSERT(!result.iterator->value.contains(location));
467
            result.iterator->value.append(location);
468
        }
469
        
470
        // For each sunken thingy, make sure we create Bottom values for all of its fields.
471
        // Note that this has the hilarious slight inefficiency of creating redundant hints for
472
        // things that were previously materializations. This should only impact compile times and
473
        // not code quality, and it's necessary for soundness without some data structure hackage.
474
        // For example, a MaterializeNewObject that we choose to sink may have new fields added to
475
        // it conditionally. That would necessitate Bottoms.
476
        Node* bottom = nullptr;
477
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
478
            if (block == m_graph.block(0))
479
                bottom = m_insertionSet.insertNode(0, SpecNone, Bottom, NodeOrigin());
480
            
481
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
482
                Node* node = block->at(nodeIndex);
483
                for (PromotedHeapLocation location : locationsForAllocation.get(node)) {
484
                    m_insertionSet.insertNode(
485
                        nodeIndex + 1, location.createHint(m_graph, node->origin, bottom));
486
                }
487
            }
488
            m_insertionSet.execute(block);
489
        }
490
491
        m_ssaCalculator.reset();
492
493
        // Collect the set of "variables" that we will be sinking.
494
        m_locationToVariable.clear();
495
        m_indexToLocation.clear();
496
        for (PromotedHeapLocation location : locations) {
497
            SSACalculator::Variable* variable = m_ssaCalculator.newVariable();
498
            locationToVariable.add(location, variable);
499
            ASSERT(indexToLocation.size() == variable->index());
500
            indexToLocation.append(location);
501
        }
502
        
503
        // Create Defs from the existing hints.
504
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
505
            for (Node* node : *block) {
506
                promote(
507
                    node,
508
                    [&] (PromotedHeapLocation location, Edge value) {
509
                        SSACalculator::Variable* variable = locationToVariable.get(location);
510
                        m_ssaCalculator.newDef(variable, block, value.node());
511
                    });
512
            }
513
        }
514
        
515
        // OMG run the SSA calculator to create Phis!
516
        m_ssaCalculator.computePhis(
517
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
518
                PromotedHeapLocation location = indexToLocation[variable->index()];
519
                if (!block->ssa->liveAtHead.contains(location.base()))
520
                    return nullptr;
521
                
522
                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
523
                phiNode->mergeFlags(NodeResultJS);
524
                return phiNode;
525
            });
526
        
527
        // Place Phis in the right places, replace all uses of any load with the appropriate
528
        // value, and create the appropriate Upsilon nodes.
529
        m_graph.clearReplacements();
530
        for (BasicBlock* block : m_graph.blocksInPreOrder()) {
531
            // This mapping table is intended to be lazy. If something is omitted from the table,
532
            // it means that there haven't been any local stores to that promoted heap location.
533
            m_localMapping.clear();
534
            
535
            // Insert the Phi functions that we had previously created.
536
            for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) {
537
                PromotedHeapLocation location = m_indexToLocation[phiDef->variable()->index()];
538
                
539
                m_insertionSet.insert(
540
                    0, phiDef->value());
541
                m_insertionSet.insert(
542
                    0, location.createHint(m_graph, NodeOrigin(), phiDef->value()));
543
                m_localMapping.add(location, phiDef->value());
544
            }
545
            
546
            // Process the block and replace all uses of loads with the promoted value.
547
            for (Node* node : *block) {
548
                m_graph.performSubstitution(node);
549
                
550
                if (Node* escapee = m_materializationPointToEscapee.get(node))
551
                    populateMaterialize(block, node, escapee);
552
                
553
                promote(
554
                    node,
555
                    [&] (PromotedHeapLocation location, Edge value) {
556
                        m_localMapping.set(location, edge.node());
557
                    },
558
                    [&] (PromotedHeapLocation location) {
559
                        node->replaceWith(resolve(block, location));
560
                    });
561
            }
562
            
563
            // Gotta drop some Upsilons.
564
            size_t upsilonInsertionPoint = block->size() - 1;
565
            NodeOrigin upsilonOrigin = block->last()->origin;
566
            for (BasicBlock* successorBlock : block->successors()) {
567
                for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) {
568
                    Node* phiNode = phiDef->value();
569
                    SSACalculator::Variable* variable = phiDef->variable();
570
                    PromotedHeapLocation location = m_indexToLocation[variable->index()];
571
                    Node* incoming = resolve(block, location);
572
                    
573
                    m_insertionSet.insertNode(
574
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
575
                        OpInfo(phiNode), incoming->defaultEdge());
576
                }
577
            }
578
            
579
            m_insertionSet.execute(block);
580
        }
581
    }
582
    
583
    Node* resolve(BasicBlock* block, PromotedHeapLocation location)
584
    {
585
        if (Node* result = m_localMapping.get(location))
586
            return result;
587
        
588
        // This implies that there is no local mapping. Find a non-local mapping.
589
        Def* def = m_ssaCalculator.nonLocalReachingDef(block, m_locationToVariable.get(location));
590
        ASSERT(def);
591
        ASSERT(def->value());
592
        m_localMapping.add(locaftion, def->value());
593
        return def->value();
594
    }
595
596
    template<typename... Args>
597
    static void doNothing(Args...) { }
598
    
599
    template<typename SinkCandidateFunctor, typename EscapeFunctor>
600
    void handleNode(
601
        Node* node,
602
        const SinkCandidateFunctor& sinkCandidate,
603
        const EscapeFunctor& escape)
604
    {
605
        switch (node->op()) {
606
        case NewObject:
607
        case MaterializeNewObject:
608
            sinkCandidate();
609
            break;
610
            
611
        case CheckStructure:
612
        case GetByOffset:
613
        case MultiGetByOffset:
614
        case PutStructure:
615
        case GetGetterSetterByOffset:
616
        case MovHint:
617
            break;
618
            
619
        case PutByOffset:
620
            escape(node->child3().node());
621
            break;
622
            
623
        case MultiPutByOffset:
624
            // FIXME: In the future we should be able to handle this. It's just a matter of
625
            // building the appropriate *Hint variant of this instruction, along with a
626
            // PhantomStructureSelect node - since this transforms the Structure in a conditional
627
            // way.
628
            // https://bugs.webkit.org/show_bug.cgi?id=136924
629
            escape(node->child1().node());
630
            escape(node->child2().node());
631
            break;
632
633
        default:
634
            m_graph.doToChildren(
635
                node,
636
                [&escape] (Edge edge) {
637
                    escape(edge.node());
638
                });
639
            break;
640
        }
641
    }
642
    
643
    Node* createMaterialize(Node* escapee, const NodeOrigin whereOrigin)
644
    {
645
        switch (escapee->op()) {
646
        case NewObject:
647
        case MaterializeNewObject:
648
            return m_graph.addNode(
649
                escapee->prediction(), MaterializeNewObject,
650
                NodeOrigin(
651
                    escapee->origin.semantic,
652
                    whereOrigin.forExit),
653
                OpInfo(m_graph.m_objectMaterializationData.add()),
654
                OpInfo(), 0, 0);
655
            
656
        default:
657
            DFG_CRASH(m_graph, where, "Bad escapee op");
658
            return nullptr;
659
        }
660
        
661
        return result;
662
    }
663
    
664
    void populateMaterialize(BasicBlock* block, Node* node, Node* escapee)
665
    {
666
        switch (node->op()) {
667
        case MaterializeNewObject: {
668
            ObjectMaterializationData* data = node->objectMaterializationData();
669
            unsigned firstChild = m_graph.m_varArgChildren.size();
670
            
671
            Vector<PromotedHeapLocation>& locations = m_LocationsForAllocation.get(escapee);
672
            
673
            PromotedHeapLocation structure(StructurePLoc, escapee);
674
            ASSERT(locations.contains(structure));
675
            
676
            m_graph.m_varArgChildren.append(resolve(block, structure));
677
            
678
            for (unsigned i = 0; i < locations.size(); ++i) {
679
                switch (locations[i].kind()) {
680
                case StructurePLoc: {
681
                    ASSERT(locations[i] == structure);
682
                    break;
683
                }
684
                    
685
                case NamedPropertyPLoc: {
686
                    Node* value = resolve(block, locations[i]);
687
                    if (value->op() == Bottom) {
688
                        // We can skip Bottoms entirely.
689
                        break;
690
                    }
691
                    
692
                    data->m_properties.append(PhantomPropertyValue(locations[i].info()));
693
                    m_graph.m_varArgChildren.append(value);
694
                    break;
695
                }
696
                    
697
                default:
698
                    DFG_CRASH(m_graph, node, "Bad location kind");
699
                }
700
            }
701
            
702
            node->children = AdjacencyList(
703
                AdjacencyList::Variable,
704
                firstChild, m_graph.m_varArgChildren.size() - firstChild);
705
            break;
706
        }
707
            
708
        default:
709
            DFG_CRASH(m_graph, node, "Bad materialize op");
710
            break;
711
        }
712
    }
713
    
714
    SSACalculator m_ssaCalculator;
715
    HashSet<Node*> m_sinkCandidates;
716
    HashMap<std::pair<Node*, Node*>, Node*> m_edgeToMaterializationPoint;
717
    HashMap<Node*, Node*> m_materializationPointToEscapee;
718
    HashMap<Node*, Vector<PromotedHeapLocation>> m_locationsForAllocation;
719
    HashMap<PromotedHeapLocation, SSACalculator::Variable*> m_locationToVariable;
720
    Vector<PromotedHeapLocation> m_indexToLocation;
721
    HashMap<PromotedHeapLocation, Node*> m_localMapping;
722
    InsertionSet m_insertionSet;
723
};
724
    
725
bool performObjectAllocationSinking(Graph& graph)
726
{
727
    SamplingRegion samplingRegion("DFG Object Allocation Sinking Phase");
728
    return runPhase<ObjectAllocationSinkingPhase>(graph);
729
}
730
731
} } // namespace JSC::DFG
732
733
#endif // ENABLE(DFG_JIT)
734
- 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 +72 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
    PhantomPropertyValue()
35
        : m_identifierNumber(UINT_MAX)
36
    {
37
    }
38
    
39
    PhantomPropertyValue(unsigned identifierNumber)
40
        : m_identifierNumber(identifierNumber)
41
    {
42
    }
43
    
44
    unsigned m_identifierNumber;
45
    
46
    bool operator==(const PhantomPropertyValue& other) const
47
    {
48
        return m_identifierNumber == other.m_identifierNumber;
49
    }
50
    
51
    void dump(PrintStream&) const;
52
};
53
54
struct ObjectMaterializationData {
55
    // Determines the meaning of the passed nodes.
56
    Vector<PhantomPropertyValue> m_properties;
57
    
58
    void dump(PrintStream&) const;
59
    
60
    // The fraction of my properties that the other data has.
61
    float oneWaySimilarityScore(const ObjectMaterializationData&) const;
62
    
63
    // The minimum of the two possible one-way scores.
64
    float similarityScore(const ObjectMaterializationData&) const;
65
};
66
67
} } // namespace JSC::DFG
68
69
#endif // ENABLE(DFG_JIT)
70
71
#endif // DFGObjectMaterializationData_h
72
- 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
- Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp +86 lines
Line 0 Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.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 "DFGPromotedHeapLocation.h"
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
Node* PromotedHeapLocation::createHint(Graph& graph, NodeOrigin origin, Node* value)
34
{
35
    switch (kind()) {
36
    case StructurePLoc:
37
        return graph.addNode(
38
            SpecNone, PutStructureHint, origin,
39
            Edge(base(), KnownCellUse), value);
40
        
41
    case NamedPropertyPLoc:
42
        return graph.addNode(
43
            SpecNone, PutByOffsetHint, origin,
44
            OpInfo(location.info()), Edge(base(), KnownCellUse), value);
45
        
46
    case InvalidPromotedLocationKind:
47
        return nullptr;
48
    }
49
    
50
    RELEASE_ASSERT_NOT_REACHED();
51
}
52
53
void PromotedHeapLocation::dump(PrintStream& out) const
54
{
55
    out.print(m_kind, "(", m_base, ", ", m_info, ")");
56
}
57
58
} } // namespace JSC::DFG
59
60
namespace WTF {
61
62
using namespace JSC::DFG;
63
64
void printInternal(PrintStream& out, PromotedLocationKind kind)
65
{
66
    switch (kind) {
67
    case InvalidPromotedLocationKind:
68
        out.print("InvalidPromotedLocationKind");
69
        return;
70
        
71
    case StructurePLoc:
72
        out.print("StructurePLoc");
73
        return;
74
        
75
    case NamedPropertyPLoc:
76
        out.print("NamedPropertyPLoc");
77
        return;
78
    }
79
    
80
    RELEASE_ASSERT_NOT_REACHED();
81
}
82
83
} // namespace WTF;
84
85
#endif // ENABLE(DFG_JIT)
86
- Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h +173 lines
Line 0 Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.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 DFGPromotedHeapLocation_h
27
#define DFGPromotedHeapLocation_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGNode.h"
32
#include <wtf/PrintStream.h>
33
34
namespace JSC { namespace DFG {
35
36
enum PromotedLocationKind {
37
    InvalidPromotedLocationKind,
38
    
39
    StructurePLoc,
40
    NamedPropertyPLoc
41
};
42
43
class PromotedHeapLocation {
44
public:
45
    PromotedHeapLocation(
46
        PromotedLocationKind kind = InvalidPromotedLocationKind,
47
        Node* base = nullptr, unsigned info = 0)
48
        : m_base(base)
49
        , m_kind(kind)
50
        , m_info(info)
51
    {
52
    }
53
    
54
    PromotedHeapLocation(
55
        PromotedLocationKind kind, Edge base, unsigned info = 0)
56
        : PromotedHeapLocation(kind, base.node(), info)
57
    {
58
    }
59
    
60
    PromotedHeapLocation(WTF::HashTableDeletedValueType)
61
        : m_base(nullptr)
62
        , m_kind(InvalidPromotedLocationKind)
63
        , m_info(1)
64
    {
65
    }
66
    
67
    Node* createHint(Graph&, NodeOrigin, Node* value);
68
    
69
    bool operator!() const { return m_kind == InvalidPromotedLocationKind; }
70
    
71
    PromotedLocationKind kind() const { return m_kind; }
72
    Node* base() const { return m_base; }
73
    unsigned info() const { return m_info; }
74
    
75
    unsigned hash() const
76
    {
77
        return m_kind + WTF::PtrHash<Node*>::hash(m_base) + m_info;
78
    }
79
    
80
    bool operator==(const PromotedHeapLocation& other) const
81
    {
82
        return m_base == other.m_base
83
            && m_kind == other.m_kind
84
            && m_info == other.m_info;
85
    }
86
    
87
    bool isHashTableDeletedValue() const
88
    {
89
        return m_kind == InvalidPromotedLocationKind && m_info;
90
    }
91
    
92
    void dump(PrintStream& out) const;
93
    
94
private:
95
    Node* m_base;
96
    PromotedLocationKind m_kind;
97
    unsigned m_info;
98
};
99
100
// Note that the write functor is really the useful thing here. The read functor is only useful
101
// for the object allocation sinking phase.
102
template<typename WriteFunctor, typename ReadFunctor>
103
void promote(Node* node, const WriteFunctor& write, const ReadFunctor& read)
104
{
105
    switch (node->op()) {
106
    case CheckStructure:
107
        if (m_sinkCandidates.contains(node->child1().node()))
108
            read(PromotedHeapLocation(StructurePLoc, node->child1()));
109
        break;
110
            
111
    case GetByOffset:
112
    case GetGetterSetterByOffset:
113
        if (m_sinkCandidates.contains(node->child2().node())) {
114
            unsigned identifierNumber =
115
                graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
116
            read(PromotedHeapLocation(NamedPropertyPLoc, node->child2(), identifierNumber));
117
        }
118
        break;
119
                                  
120
    case MultiGetByOffset:
121
        if (m_sinkCandidates.contains(node->child1().node())) {
122
            unsigned identifierNumber = node->multiGetByOffsetData().identifierNumber;
123
            read(PromotedHeapLocation(NamedPropertyPLoc, node->child1(), identiferNumber));
124
        }
125
        break;
126
            
127
    case PutStructureHint:
128
        if (m_sinkCandidates.contains(node->child1().node()))
129
            write(PromotedHeapLocation(StructurePLoc, node->child1()), node->child2());
130
        break;
131
            
132
    case PutByOffsetHint:
133
        if (m_sinkCandidates.contains(node->child1().node())) {
134
            unsigned identifierNumber = node->identifierNumber();
135
            write(
136
                PromotedHeapLocation(NamedPropertyPLoc, node->child1(), identifierNumber),
137
                node->child2().node());
138
        }
139
        break;
140
141
    default:
142
        break;
143
    }
144
}
145
146
struct PromotedHeapLocationHash {
147
    static unsigned hash(const PromotedHeapLocation& key) { return key.hash(); }
148
    static bool equal(const PromotedHeapLocation& a, const PromotedHeapLocation& b) { return a == b; }
149
    static const bool safeToCompareToEmptyOrDeleted = true;
150
};
151
152
} } // namespace JSC::DFG
153
154
namespace WTF {
155
156
void printInternal(PrintStream&, JSC::DFG::PromotedLocationKind);
157
158
template<typename T> struct DefaultHash;
159
template<> struct DefaultHash<JSC::DFG::PromotedHeapLocation> {
160
    typedef JSC::DFG::PromotedHeapLocationHash Hash;
161
};
162
163
template<typename T> struct HashTraits;
164
template<> struct HashTraits<JSC::DFG::PromotedHeapLocation> : SimpleClassHashTraits<JSC::DFG::PromotedHeapLocation> {
165
    static const bool emptyValueIsZero = false;
166
};
167
168
} // namespace WTF
169
170
#endif // ENABLE(DFG_JIT)
171
172
#endif // DFGPromotedHeapLocation_h
173
- Source/JavaScriptCore/dfg/DFGSSACalculator.cpp +11 lines
Lines 66-71 SSACalculator::~SSACalculator() Source/JavaScriptCore/dfg/DFGSSACalculator.cpp_sec1
66
{
66
{
67
}
67
}
68
68
69
void SSACalculator::reset()
70
{
71
    m_variables.clear();
72
    m_defs.clear();
73
    m_phis.clear();
74
    for (BlockIndex blockIndex = m_data.size(); blockIndex--;) {
75
        m_data[blockIndex].m_defs.clear();
76
        m_data[blockIndex].m_phis.clear();
77
    }
78
}
79
69
SSACalculator::Variable* SSACalculator::newVariable()
80
SSACalculator::Variable* SSACalculator::newVariable()
70
{
81
{
71
    return &m_variables.alloc(Variable(m_variables.size()));
82
    return &m_variables.alloc(Variable(m_variables.size()));
- Source/JavaScriptCore/dfg/DFGSSACalculator.h +2 lines
Lines 105-110 public: Source/JavaScriptCore/dfg/DFGSSACalculator.h_sec1
105
    SSACalculator(Graph&);
105
    SSACalculator(Graph&);
106
    ~SSACalculator();
106
    ~SSACalculator();
107
    
107
    
108
    void reset();
109
    
108
    class Variable {
110
    class Variable {
109
    public:
111
    public:
110
        unsigned index() const { return m_index; }
112
        unsigned index() const { return m_index; }
- Source/WTF/wtf/Bag.h -1 / +7 lines
Lines 46-62 private: Source/WTF/wtf/Bag.h_sec1
46
    
46
    
47
public:
47
public:
48
    Bag()
48
    Bag()
49
        : m_head(0)
49
        : m_head(nullptr)
50
    {
50
    {
51
    }
51
    }
52
    
52
    
53
    ~Bag()
53
    ~Bag()
54
    {
54
    {
55
        clear();
56
    }
57
    
58
    void clear()
59
    {
55
        while (m_head) {
60
        while (m_head) {
56
            Node* current = m_head;
61
            Node* current = m_head;
57
            m_head = current->m_next;
62
            m_head = current->m_next;
58
            delete current;
63
            delete current;
59
        }
64
        }
65
        m_head = nullptr;
60
    }
66
    }
61
    
67
    
62
    template<typename... Args>
68
    template<typename... Args>

Return to Bug 136330