| Differences between
and this patch
- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h +2 lines
Lines 32-37 Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec1
32
#include "DFGBranchDirection.h"
32
#include "DFGBranchDirection.h"
33
#include "DFGGraph.h"
33
#include "DFGGraph.h"
34
#include "DFGNode.h"
34
#include "DFGNode.h"
35
#include "DFGPhiChildren.h"
35
36
36
namespace JSC { namespace DFG {
37
namespace JSC { namespace DFG {
37
38
Lines 195-200 private: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec2
195
    CodeBlock* m_codeBlock;
196
    CodeBlock* m_codeBlock;
196
    Graph& m_graph;
197
    Graph& m_graph;
197
    AbstractStateType& m_state;
198
    AbstractStateType& m_state;
199
    std::unique_ptr<PhiChildren> m_phiChildren;
198
};
200
};
199
201
200
} } // namespace JSC::DFG
202
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h +2 lines
Lines 43-48 AbstractInterpreter<AbstractStateType>:: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
43
    , m_graph(graph)
43
    , m_graph(graph)
44
    , m_state(state)
44
    , m_state(state)
45
{
45
{
46
    if (m_graph.m_form == SSA)
47
        m_phiChildren = std::make_unique<PhiChildren>(m_graph);
46
}
48
}
47
49
48
template<typename AbstractStateType>
50
template<typename AbstractStateType>
- Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp +86 lines
Line 0 Source/JavaScriptCore/dfg/DFGAvailabilityMap.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 "DFGAvailabilityMap.h"
28
29
#if ENABLE(DFG_JIT)
30
31
#include <wtf/ListDump.h>
32
33
namespace JSC { namespace DFG {
34
35
void AvailabilityMap::prune()
36
{
37
    HashSet<Node*> possibleNodes;
38
    
39
    for (unsigned i = m_locals.size(); i--;) {
40
        if (m_locals[i].hasNode())
41
            possibleNodes.add(m_locals[i].node());
42
    }
43
44
    unsigned oldPossibleNodesSize;
45
    do {
46
        oldPossibleNodesSize = possibleNodes.size();
47
        for (auto pair : m_heap) {
48
            if (pair.value.hasNode() && possibleNodes.contains(pair.key.base()))
49
                possibleNodes.add(pair.value.node());
50
        }
51
    } while (oldPossibleNodesSize != possibleNodes.size());
52
    
53
    HashMap<PromotedHeapLocation, Availability> newHeap;
54
    for (auto pair : m_heap) {
55
        if (possibleNodes.contains(pair.key.base()))
56
            newHeap.add(pair.key, pair.value);
57
    }
58
    m_heap = newHeap;
59
}
60
61
void AvailabilityMap::dump(PrintStream& out) const
62
{
63
    out.print("{locals = ", m_locals, "; heap = ", mapDump(m_heap), "}");
64
}
65
66
bool AvailabilityMap::operator==(const AvailabilityMap& other) const
67
{
68
    return m_locals == other.m_locals
69
        && m_heap == other.m_heap;
70
}
71
72
void AvailabilityMap::merge(const AvailabilityMap& other)
73
{
74
    for (unsigned i = other.m_locals.size(); i--;)
75
        locals[i] = other.m_locals[i].merge(locals[i]);
76
    
77
    for (auto pair : other.m_heap) {
78
        auto result = m_heap.add(pair.key, Availability());
79
        result.iterator->value = pair.value.merge(result.iterator->value);
80
    }
81
}
82
83
} } // namespace JSC::DFG
84
85
#endif // ENABLE(DFG_JIT)
86
- Source/JavaScriptCore/dfg/DFGAvailabilityMap.h +53 lines
Line 0 Source/JavaScriptCore/dfg/DFGAvailabilityMap.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 DFGAvailabilityMap_h
27
#define DFGAvailabilityMap_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGAvailability.h"
32
33
namespace JSC { namespace DFG {
34
35
struct AvailabilityMap {
36
    void prune();
37
    
38
    void dump(PrintStream& out) const;
39
    
40
    bool operator==(const AvailabilityMap& other) const;
41
    
42
    void merge(const AvailabilityMap& other);
43
    
44
    Operands<Availability> m_locals;
45
    HashMap<PromotedHeapLocation, Availability> m_heap;
46
};
47
48
} } // namespace JSC::DFG
49
50
#endif // ENABLE(DFG_JIT)
51
52
#endif // DFGAvailabilityMap_h
53
- Source/JavaScriptCore/dfg/DFGBasicBlock.cpp -2 / +2 lines
Lines 118-126 void BasicBlock::dump(PrintStream& out) Source/JavaScriptCore/dfg/DFGBasicBlock.cpp_sec1
118
}
118
}
119
119
120
BasicBlock::SSAData::SSAData(BasicBlock* block)
120
BasicBlock::SSAData::SSAData(BasicBlock* block)
121
    : availabilityAtHead(OperandsLike, block->variablesAtHead)
122
    , availabilityAtTail(OperandsLike, block->variablesAtHead)
123
{
121
{
122
    m_availabilityAtHead.m_locals = Operands<Availability>(OperandsLike, block->variablesAtHead);
123
    m_availabilityAtTail.m_locals = Operands<Availability>(OperandsLike, block->variablesAtHead);
124
}
124
}
125
125
126
BasicBlock::SSAData::~SSAData() { }
126
BasicBlock::SSAData::~SSAData() { }
- Source/JavaScriptCore/dfg/DFGBasicBlock.h -3 / +78 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 169-176 struct BasicBlock : RefCounted<BasicBloc Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec4
169
    unsigned innerMostLoopIndices[numberOfInnerMostLoopIndices];
243
    unsigned innerMostLoopIndices[numberOfInnerMostLoopIndices];
170
244
171
    struct SSAData {
245
    struct SSAData {
172
        Operands<Availability> availabilityAtHead;
246
        AvailabilityMap availabilityAtHead;
173
        Operands<Availability> availabilityAtTail;
247
        AvailabilityMap availabilityAtTail;
248
        
174
        HashSet<Node*> liveAtHead;
249
        HashSet<Node*> liveAtHead;
175
        HashSet<Node*> liveAtTail;
250
        HashSet<Node*> liveAtTail;
176
        HashMap<Node*, AbstractValue> valuesAtHead;
251
        HashMap<Node*, AbstractValue> valuesAtHead;
Lines 183-189 struct BasicBlock : RefCounted<BasicBloc Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec5
183
    
258
    
184
private:
259
private:
185
    friend class InsertionSet;
260
    friend class InsertionSet;
186
    Vector<Node*, 8> m_nodes;
261
    BlockNodeList m_nodes;
187
};
262
};
188
263
189
typedef Vector<BasicBlock*, 5> BlockList;
264
typedef Vector<BasicBlock*, 5> BlockList;
- Source/JavaScriptCore/dfg/DFGGraph.h +105 lines
Lines 676-681 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec1
676
    BlockList blocksInPreOrder();
676
    BlockList blocksInPreOrder();
677
    BlockList blocksInPostOrder();
677
    BlockList blocksInPostOrder();
678
    
678
    
679
    class NaturalBlockIterable {
680
    public:
681
        NaturalBlockIterable()
682
            : m_graph(nullptr)
683
        {
684
        }
685
        
686
        NaturalBlockIterable(Graph& graph)
687
            : m_graph(&graph)
688
        {
689
        }
690
        
691
        class iterator {
692
        public:
693
            iterator()
694
                : m_graph(nullptr)
695
                , m_index(0)
696
            {
697
            }
698
            
699
            iterator(Graph& graph, BlockIndex index)
700
                : m_graph(&graph)
701
                , m_index(findNext(index))
702
            {
703
            }
704
            
705
            BasicBlock *operator*()
706
            {
707
                return m_graph->block(index);
708
            }
709
            
710
            iterator& operator++()
711
            {
712
                m_index = findNext(m_index);
713
                return *this;
714
            }
715
            
716
            bool operator==(const iterator& other) const
717
            {
718
                return m_index == other.m_index;
719
            }
720
            
721
            bool operator!=(const iterator& other) const
722
            {
723
                return !(*this == other);
724
            }
725
            
726
        private:
727
            BlockIndex findNext(BlockIndex index)
728
            {
729
                while (index < m_graph->numBlocks() && !m_graph->block(index))
730
                    index++;
731
                return index;
732
            }
733
            
734
            Graph* m_graph;
735
            BlockIndex m_index;
736
        };
737
        
738
        iterator begin()
739
        {
740
            return iterator(*m_graph, 0);
741
        }
742
        
743
        iterator end()
744
        {
745
            return iterator(*m_graph, m_graph->numBlocks());
746
        }
747
        
748
    private:
749
        Graph* m_graph;
750
    };
751
    
752
    NaturalBlockIterable blocksInNaturalOrder()
753
    {
754
        return NaturalBlockIterable(*this);
755
    }
756
    
757
    template<typename ChildFunctor>
758
    void doToChildrenWithNode(Node* node, const ChildFunctor& functor)
759
    {
760
        DFG_NODE_DO_TO_CHILDREN(node, functor);
761
    }
762
    
763
    template<typename ChildFunctor>
764
    void doToChildEdges(Node* node, const ChildFunctor& functor)
765
    {
766
        doToChildrenWithNode(
767
            node,
768
            [&functor] (Node*, Edge& edge) {
769
                functor(edge);
770
            });
771
    }
772
    
773
    template<typename ChildFunctor>
774
    void doToChildren(Node* node, const ChildFunctor& functor)
775
    {
776
        doToChildrenWithNode(
777
            node,
778
            [&functor] (Node*, Edge edge) {
779
                functor(edge);
780
            });
781
    }
782
    
679
    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
783
    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
680
    
784
    
681
    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
785
    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
Lines 736-741 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec2
736
    Bag<SwitchData> m_switchData;
840
    Bag<SwitchData> m_switchData;
737
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
841
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
738
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
842
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
843
    Bag<ObjectMaterializationData> m_objectMaterializationData;
739
    Vector<InlineVariableData, 4> m_inlineVariableData;
844
    Vector<InlineVariableData, 4> m_inlineVariableData;
740
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
845
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
741
    bool m_hasArguments;
846
    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 +58 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, AvailabilityMap& availability,
35
    Node* originalNode, Node* newNode)
36
{
37
    for (unsigned i = availability.m_locals.size(); i--;) {
38
        int operand = availability.m_ocals.operandForIndex(i);
39
        
40
        if (availability.m_locals[i].hasNode() && availability.m_locals[i].node() == originalNode) {
41
            insertionSet.insertNode(
42
                nodeIndex, SpecNone, MovHint, NodeOrigin(), OpInfo(operand),
43
                newNode->defaultEdge());
44
        }
45
    }
46
    
47
    for (auto pair : availability.m_heap) {
48
        if (pair.value.hasNode() && pair.value.node() == originalNode) {
49
            insertionSet.insertNode(
50
                nodeIndex, pair.key.createHint(insertionSet.graph(), NodeOrigin(), newNode));
51
        }
52
    }
53
}
54
55
} } // namespace JSC::DFG
56
57
#endif // ENABLE(DFG_JIT)
58
- 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 "DFGAvailabilityMap.h"
33
34
namespace JSC { namespace DFG {
35
36
void insertOSRHintsForUpdate(
37
    InsertionSet&, unsigned nodeIndex, AvailabilityMap&,
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/DFGInsertionSet.h +2 lines
Lines 43-48 public: Source/JavaScriptCore/dfg/DFGInsertionSet.h_sec1
43
    {
43
    {
44
    }
44
    }
45
    
45
    
46
    Graph& graph() { return m_graph; }
47
    
46
    Node* insert(const Insertion& insertion)
48
    Node* insert(const Insertion& insertion)
47
    {
49
    {
48
        ASSERT(!m_insertions.size() || m_insertions.last().index() <= insertion.index());
50
        ASSERT(!m_insertions.size() || m_insertions.last().index() <= insertion.index());
- 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 500-505 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec2
500
        m_flags &= ~NodeClobbersWorld;
501
        m_flags &= ~NodeClobbersWorld;
501
    }
502
    }
502
    
503
    
504
    void convertToPutByOffsetHint()
505
    {
506
        ASSERT(m_op == PutByOffset);
507
        m_op = PutByOffsetHint;
508
        m_opInfo = storageAccessData().identifierNumber;
509
        child1() = child2();
510
        child2() = child3();
511
        child3() = Edge();
512
    }
513
    
514
    void convertToPutStructureHint(Node* structure)
515
    {
516
        ASSERT(m_op == PutStructure);
517
        ASSERT(structure->structure() == transition()->next);
518
        m_op = PhantomPutStructure;
519
        m_opInfo = 0;
520
        child2() = Edge(structure, KnownCellUse);
521
    }
522
    
523
    void convertToPhantomNewObject()
524
    {
525
        ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
526
        m_op = PhantomNewObject;
527
        m_flags &= ~NodeHasVarArgs;
528
        m_opInfo = 0;
529
        m_opInfo2 = 0;
530
        children = AdjacencyList();
531
    }
532
    
503
    void convertToPhantomLocal()
533
    void convertToPhantomLocal()
504
    {
534
    {
505
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
535
        ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
Lines 704-709 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec3
704
        case PutById:
734
        case PutById:
705
        case PutByIdFlush:
735
        case PutByIdFlush:
706
        case PutByIdDirect:
736
        case PutByIdDirect:
737
        case PutByOffsetHint:
707
            return true;
738
            return true;
708
        default:
739
        default:
709
            return false;
740
            return false;
Lines 1105-1110 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec4
1105
    {
1136
    {
1106
        switch (op()) {
1137
        switch (op()) {
1107
        case PutStructure:
1138
        case PutStructure:
1139
        case PutStructureHint:
1108
        case AllocatePropertyStorage:
1140
        case AllocatePropertyStorage:
1109
        case ReallocatePropertyStorage:
1141
        case ReallocatePropertyStorage:
1110
            return true;
1142
            return true;
Lines 1141-1146 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec5
1141
        case ArrayifyToStructure:
1173
        case ArrayifyToStructure:
1142
        case NewObject:
1174
        case NewObject:
1143
        case NewStringObject:
1175
        case NewStringObject:
1176
        case PhantomStructure:
1144
            return true;
1177
            return true;
1145
        default:
1178
        default:
1146
            return false;
1179
            return false;
Lines 1155-1161 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec6
1155
    
1188
    
1156
    bool hasStorageAccessData()
1189
    bool hasStorageAccessData()
1157
    {
1190
    {
1158
        return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset;
1191
        switch (op()) {
1192
        case GetByOffset:
1193
        case PutByOffset:
1194
        case GetGetterSetterByOffset:
1195
            return true;
1196
        default:
1197
            return false;
1198
        }
1159
    }
1199
    }
1160
    
1200
    
1161
    StorageAccessData& storageAccessData()
1201
    StorageAccessData& storageAccessData()
Lines 1184-1189 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec7
1184
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1224
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1185
    }
1225
    }
1186
    
1226
    
1227
    bool hasObjectMaterializationData()
1228
    {
1229
        return op() == MaterializeNewObject;
1230
    }
1231
    
1232
    ObjectMaterializationData& objectMaterializationData()
1233
    {
1234
        return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo);
1235
    }
1236
    
1187
    bool hasFunctionDeclIndex()
1237
    bool hasFunctionDeclIndex()
1188
    {
1238
    {
1189
        return op() == NewFunction
1239
        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 -10 / +20 lines
Lines 87-92 public: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp_sec1
87
                for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex)
87
                for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex)
88
                    calculator.executeNode(block->at(nodeIndex));
88
                    calculator.executeNode(block->at(nodeIndex));
89
                
89
                
90
                calculator.m_availability.prune();
91
                
90
                if (calculator.m_availability == block->ssa->availabilityAtTail)
92
                if (calculator.m_availability == block->ssa->availabilityAtTail)
91
                    continue;
93
                    continue;
92
                
94
                
Lines 95-105 public: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp_sec2
95
                
97
                
96
                for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
98
                for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
97
                    BasicBlock* successor = block->successor(successorIndex);
99
                    BasicBlock* successor = block->successor(successorIndex);
98
                    for (unsigned i = calculator.m_availability.size(); i--;) {
100
                    successor->ssa->availabilityAtHead.merge(calculator.m_availability);
99
                        successor->ssa->availabilityAtHead[i] =
100
                            calculator.m_availability[i].merge(
101
                                successor->ssa->availabilityAtHead[i]);
102
                    }
103
                }
101
                }
104
            }
102
            }
105
        } while (changed);
103
        } while (changed);
Lines 127-164 void LocalOSRAvailabilityCalculator::beg Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp_sec3
127
    m_availability = block->ssa->availabilityAtHead;
125
    m_availability = block->ssa->availabilityAtHead;
128
}
126
}
129
127
128
void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block)
129
{
130
    m_availability = block->ssa->availabilityAtTail;
131
}
132
130
void LocalOSRAvailabilityCalculator::executeNode(Node* node)
133
void LocalOSRAvailabilityCalculator::executeNode(Node* node)
131
{
134
{
132
    switch (node->op()) {
135
    switch (node->op()) {
133
    case SetLocal: {
136
    case SetLocal: {
134
        VariableAccessData* variable = node->variableAccessData();
137
        VariableAccessData* variable = node->variableAccessData();
135
        m_availability.operand(variable->local()) =
138
        m_availability.m_locals.operand(variable->local()) =
136
            Availability(node->child1().node(), variable->flushedAt());
139
            Availability(node->child1().node(), variable->flushedAt());
137
        break;
140
        break;
138
    }
141
    }
139
142
140
    case GetArgument: {
143
    case GetArgument: {
141
        VariableAccessData* variable = node->variableAccessData();
144
        VariableAccessData* variable = node->variableAccessData();
142
        m_availability.operand(variable->local()) =
145
        m_availability.m_locals.operand(variable->local()) =
143
            Availability(node, variable->flushedAt());
146
            Availability(node, variable->flushedAt());
144
        break;
147
        break;
145
    }
148
    }
146
149
147
    case MovHint: {
150
    case MovHint: {
148
        m_availability.operand(node->unlinkedLocal()) =
151
        m_availability.m_locals.operand(node->unlinkedLocal()) =
149
            Availability(node->child1().node());
152
            Availability(node->child1().node());
150
        break;
153
        break;
151
    }
154
    }
152
155
153
    case ZombieHint: {
156
    case ZombieHint: {
154
        m_availability.operand(node->unlinkedLocal()) =
157
        m_availability.m_locals.operand(node->unlinkedLocal()) =
155
            Availability::unavailable();
158
            Availability::unavailable();
156
        break;
159
        break;
157
    }
160
    }
158
161
        
159
    default:
162
    default:
160
        break;
163
        break;
161
    }
164
    }
165
    
166
    promote(
167
        node,
168
        [&] (PromotedHeapLocation location, Edge value) {
169
            m_availability.m_heap.set(location, Availability(value.node()));
170
        },
171
        [&] (PromotedHeapLocation) { });
162
}
172
}
163
173
164
} } // namespace JSC::DFG
174
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h -1 / +2 lines
Lines 49-57 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
    AvailabilityMap m_availability;
55
};
56
};
56
57
57
} } // namespace JSC::DFG
58
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp +729 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
    
164
    void determineMaterializationPoints()
165
    {
166
        // The premise of this pass is that if there exists a point in the program where some
167
        // path from a phantom allocation site to that point causes materialization, then *all*
168
        // paths cause materialization. This should mean that there are never any redundant
169
        // materializations.
170
        
171
        m_edgeToMaterializationPoint.clear();
172
        
173
        BlockMap<HashSet<Node*>> materializedAtHead;
174
        BlockMap<HashSet<Node*>> materializedAtTail;
175
        
176
        bool changed;
177
        do {
178
            changed = false;
179
            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
180
                HashSet<Node*> materialized = materializedAtHead[block];
181
                for (Node* node : *block) {
182
                    handleNode(
183
                        node,
184
                        doNothing,
185
                        [&] (Node* escapee) {
186
                            if (m_sinkCandidates.contains(escapee))
187
                                materialized.add(escapee);
188
                        });
189
                }
190
                
191
                if (materialized == materializedAtTail[block])
192
                    continue;
193
                
194
                changed = true;
195
                
196
                for (BasicBlock* successorBlock : block->successors()) {
197
                    for (Node* materializee : materialized) {
198
                        if (!successorBlock->ssa->liveAtHead.contains(materializee))
199
                            continue;
200
                        materializedAtHead[successorBlock].add(materializee);
201
                    }
202
                }
203
            }
204
        } while (changed);
205
        
206
        // A materialization edge exists at any point where a node escapes but hasn't been
207
        // materialized yet.
208
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
209
            HashSet<Node*> materialized = materializedAtHead[block];
210
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
211
                Node* node = block->at(nodeIndex);
212
                
213
                handleNode(
214
                    node,
215
                    doNothing,
216
                    [&] (Node* escapee) {
217
                        if (!m_sinkCandidates.contains(escapee))
218
                            return;
219
                        
220
                        if (!materialized.add(escapee))
221
                            return;
222
                        
223
                        m_edgeToMaterializationPoint.add(
224
                            std::make_pair(where, escapee),
225
                            createMaterialize(escapee, node->origin));
226
                    });
227
            }
228
        }
229
    }
230
    
231
    void placeMaterializationPoints()
232
    {
233
        m_ssaCalculator.reset();
234
        
235
        HashMap<Node*, SSACalculator::Variable*> nodeToVariable;
236
        Vector<Node*> indexToNode;
237
        
238
        for (Node* node : m_sinkCandidates) {
239
            SSACalculator::Variable* variable = m_ssaCalculator.newVariable();
240
            nodeToVariable.add(node, variable);
241
            ASSERT(indexToNode.size() == variable->index());
242
            indexToNode.append(node);
243
        }
244
        
245
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
246
            for (Node* node : *block) {
247
                if (SSACalculator::Variable* variable = nodeToVariable.get(node))
248
                    m_ssaCalculator.newDef(variable, block, node);
249
                
250
                m_graph.doToChildren(
251
                    node,
252
                    [&] (Edge edge) {
253
                        Node* materialize =
254
                            m_edgeToMaterializationPoint.get(std::make_pair(node, edge.node()));
255
                        if (!materialize)
256
                            return;
257
                        
258
                        m_ssaCalculator.newDef(
259
                            nodeToVariable.get(edge.node()), block, materialize);
260
                    });
261
            }
262
        }
263
        
264
        m_ssaCalculator.computePhis(
265
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
266
                Node* allocation = indexToNode[variable->index()];
267
                if (!block->ssa->liveAtHead.contains(allocation))
268
                    return nullptr;
269
                
270
                Node* phiNode = m_graph.addNode(allocation->prediction(), Phi, NodeOrigin());
271
                phiNode->mergeFlags(NodeResultJS);
272
                return phiNode;
273
            });
274
        
275
        // Place Phis in the right places. Replace all uses of any allocation with the appropriate
276
        // materialization. Create the appropriate Upsilon nodes.
277
        LocalOSRAvailabilityCalculator availabilityCalculator;
278
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
279
            HashMap<Node*, Node*> mapping;
280
            
281
            for (Node* candidate : block->ssa->liveAtHead) {
282
                SSACalculator::Variable* variable = nodeToVariable.get(candidate);
283
                if (!variable)
284
                    continue;
285
                
286
                Def* def = m_ssaCalculator.reachingDefAtHead(block, variable);
287
                if (!def)
288
                    continue;
289
                
290
                mapping.add(indexToNode[variable->index()], def->value());
291
            }
292
            
293
            availabilityCalculator.beginBlock(block);
294
            for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) {
295
                m_insertionSet.insert(0, phiDef->value());
296
                
297
                Node* originalNode = indexToNode[phiDef->variable()->index()];
298
                insertOSRHintsForUpdate(
299
                    m_insertionSet, 0, availabilityCalculator, originalNode, phiDef->value());
300
301
                mapping.add(originalNode, phiDef->value());
302
            }
303
            
304
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
305
                Node* node = block->at(nodeIndex);
306
307
                m_graph.doToChildEdges(
308
                    node,
309
                    [&] (Edge edge) {
310
                        Node* materialize = m_edgeToMaterializationPoint.get(
311
                            std::make_pair(node, edge.node()));
312
                        if (materialize) {
313
                            m_insertionSet.insert(nodeIndex, materialize);
314
                            insertOSRHintsForUpdate(
315
                                m_insertionSet, nodeIndex, availabilityCalculator,
316
                                edge.node(), materialize);
317
                        }
318
                    });
319
320
                availabilityCalculator.executeNode(node);
321
                
322
                m_graph.doToChildEdges(
323
                    node,
324
                    [&] (Edge& edge) {
325
                        if (Node* materialize = mapping.get(edge.node()))
326
                            edge.setNode(materialize);
327
                    });
328
            }
329
            
330
            size_t upsilonInsertionPoint = block->size() - 1;
331
            NodeOrigin upsilonOrigin = block->last()->origin;
332
            for (BasicBlock* successorBlock : block->successors()) {
333
                for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) {
334
                    Node* phiNode = phiDef->value();
335
                    SSACalculator::Variable* variable = phiDef->variable();
336
                    Node* allocation = indexToNode[variable->index()];
337
                    
338
                    Node* originalIncoming = mapping.get(allocation);
339
                    Node* incoming;
340
                    if (originalIncoming == allocation) {
341
                        // If we have a Phi that combines materializations with the original
342
                        // phantom object, then the path with the phantom object must materialize.
343
                        
344
                        incoming = createMaterialize(allocation, upsilonOrigin);
345
                        m_insertionSet.insert(upsilonInsertionPoint, incoming);
346
                        insertOSRHintsForUpdate(
347
                            m_insertionSet, upsilonInsertionPoint, availabilityCalculator,
348
                            originalIncoming, incoming);
349
                    } else
350
                        incoming = originalIncoming;
351
                    
352
                    Node* upsilon = m_insertionSet.insertNode(
353
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
354
                        OpInfo(phiNode), incoming->defaultEdge());
355
                    
356
                    if (originalIncoming == allocation) {
357
                        m_edgeToMaterializationPoint.add(
358
                            std::make_pair(upsilon, allocation), incoming);
359
                    }
360
                }
361
            }
362
            
363
            m_insertionSet.execute(block);
364
        }
365
        
366
        // At this point we have dummy materialization nodes along with edges to them. This means
367
        // that the part of the control flow graph that prefers to see actual object allocations
368
        // is completely fixed up, except for the materializations themselves.
369
    }
370
    
371
    void lowerNonReadingOperationsOnPhantomAllocations()
372
    {
373
        // Lower everything but reading operations on phantom allocations. We absolutely have to
374
        // lower all writes so as to reveal them to the SSA calculator. We cannot lower reads
375
        // because the whole point is that those go away completely.
376
        
377
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
378
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
379
                Node* node = block->at(nodeIndex);
380
                switch (node->op()) {
381
                case PutByOffset: {
382
                    if (m_sinkCandidates.contains(node->child2().node()))
383
                        node->convertToPutByOffsetHint();
384
                    break;
385
                }
386
                    
387
                case PutStructure: {
388
                    if (m_sinkCandidates.contains(node->child1().node())) {
389
                        Node* structure = m_insertionSet.insertNode(
390
                            nodeIndex, SpecCellOther, PhantomStructure, node->origin,
391
                            OpInfo(node->transition()->next));
392
                        node->convertToPutStructureHint(structure);
393
                    }
394
                    break;
395
                }
396
                    
397
                case NewObject: {
398
                    if (m_sinkCandidates.contains(node)) {
399
                        Node* structure = m_insertionSet.insertNode(
400
                            nodeIndex + 1, SpecCellOther, PhantomStructure, node->origin,
401
                            OpInfo(node->structure()));
402
                        m_insertionSet.insertNode(
403
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
404
                            Edge(node, KnownCellUse), Edge(structure, KnownCellUse));
405
                        node->convertToPhantomNewObject();
406
                    }
407
                    break;
408
                }
409
                    
410
                case MaterializeNewObject: {
411
                    if (m_sinkCandidates.contains(node)) {
412
                        m_insertionSet.insertNode(
413
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
414
                            Edge(node, KnownCellUse), m_graph.varArgChild(node, 0));
415
                        for (unsigned i = 0; i < node->objectMaterializationData().m_properties.size(); ++i) {
416
                            m_insertionSet.insertNode(
417
                                nodeIndex + 1, SpecNone, PutByOffsetHint, node->origin,
418
                                Edge(node, KnownCellUse),m_graph.varArgChild(node, i + 1));
419
                        }
420
                        node->convertToPhantomNewObject();
421
                    }
422
                    break;
423
                }
424
                    
425
                default:
426
                    break;
427
                }
428
            }
429
            m_insertionSet.execute(block);
430
        }
431
    }
432
    
433
    void promoteSunkenFields()
434
    {
435
        // Henceforth when we encounter a materialization point, we will want to ask *who* it is
436
        // a materialization for. Invert the map to be able to answer such questions.
437
        m_materializationPointToEscapee.clear();
438
        for (auto pair : m_edgeToMaterializationPoint)
439
            m_materializationPointToEscapee.add(pair.value, pair.key.second);
440
        
441
        // Collect the set of heap locations that we will be operating over.
442
        HashSet<PromotedHeapLocation> locations;
443
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
444
            for (Node* node : *block) {
445
                promote(
446
                    node,
447
                    [&] (PromotedHeapLocation location, Edge) {
448
                        locations.add(location);
449
                    },
450
                    [&] (PromotedHeapLocation location) {
451
                        locations.add(location);
452
                    });
453
            }
454
        }
455
        
456
        // Figure out which locations belong to which allocations.
457
        m_locationsForAllocation.clear();
458
        for (PromotedHeapLocation location : locations) {
459
            auto result = m_locationsForAllocation.add(location.base(), Vector<PromotedHeapLocation>());
460
            ASSERT(!result.iterator->value.contains(location));
461
            result.iterator->value.append(location);
462
        }
463
        
464
        // For each sunken thingy, make sure we create Bottom values for all of its fields.
465
        // Note that this has the hilarious slight inefficiency of creating redundant hints for
466
        // things that were previously materializations. This should only impact compile times and
467
        // not code quality, and it's necessary for soundness without some data structure hackage.
468
        // For example, a MaterializeNewObject that we choose to sink may have new fields added to
469
        // it conditionally. That would necessitate Bottoms.
470
        Node* bottom = nullptr;
471
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
472
            if (block == m_graph.block(0))
473
                bottom = m_insertionSet.insertNode(0, SpecNone, Bottom, NodeOrigin());
474
            
475
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
476
                Node* node = block->at(nodeIndex);
477
                for (PromotedHeapLocation location : locationsForAllocation.get(node)) {
478
                    m_insertionSet.insertNode(
479
                        nodeIndex + 1, location.createHint(m_graph, node->origin, bottom));
480
                }
481
            }
482
            m_insertionSet.execute(block);
483
        }
484
485
        m_ssaCalculator.reset();
486
487
        // Collect the set of "variables" that we will be sinking.
488
        m_locationToVariable.clear();
489
        m_indexToLocation.clear();
490
        for (PromotedHeapLocation location : locations) {
491
            SSACalculator::Variable* variable = m_ssaCalculator.newVariable();
492
            locationToVariable.add(location, variable);
493
            ASSERT(indexToLocation.size() == variable->index());
494
            indexToLocation.append(location);
495
        }
496
        
497
        // Create Defs from the existing hints.
498
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
499
            for (Node* node : *block) {
500
                promote(
501
                    node,
502
                    [&] (PromotedHeapLocation location, Edge value) {
503
                        SSACalculator::Variable* variable = locationToVariable.get(location);
504
                        m_ssaCalculator.newDef(variable, block, value.node());
505
                    },
506
                    doNothing);
507
            }
508
        }
509
        
510
        // OMG run the SSA calculator to create Phis!
511
        m_ssaCalculator.computePhis(
512
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
513
                PromotedHeapLocation location = indexToLocation[variable->index()];
514
                if (!block->ssa->liveAtHead.contains(location.base()))
515
                    return nullptr;
516
                
517
                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
518
                phiNode->mergeFlags(NodeResultJS);
519
                return phiNode;
520
            });
521
        
522
        // Place Phis in the right places, replace all uses of any load with the appropriate
523
        // value, and create the appropriate Upsilon nodes.
524
        m_graph.clearReplacements();
525
        for (BasicBlock* block : m_graph.blocksInPreOrder()) {
526
            // This mapping table is intended to be lazy. If something is omitted from the table,
527
            // it means that there haven't been any local stores to that promoted heap location.
528
            m_localMapping.clear();
529
            
530
            // Insert the Phi functions that we had previously created.
531
            for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) {
532
                PromotedHeapLocation location = m_indexToLocation[phiDef->variable()->index()];
533
                
534
                m_insertionSet.insert(
535
                    0, phiDef->value());
536
                m_insertionSet.insert(
537
                    0, location.createHint(m_graph, NodeOrigin(), phiDef->value()));
538
                m_localMapping.add(location, phiDef->value());
539
            }
540
            
541
            // Process the block and replace all uses of loads with the promoted value.
542
            for (Node* node : *block) {
543
                m_graph.performSubstitution(node);
544
                
545
                if (Node* escapee = m_materializationPointToEscapee.get(node))
546
                    populateMaterialize(block, node, escapee);
547
                
548
                promote(
549
                    node,
550
                    [&] (PromotedHeapLocation location, Edge value) {
551
                        m_localMapping.set(location, edge.node());
552
                    },
553
                    [&] (PromotedHeapLocation location) {
554
                        node->replaceWith(resolve(block, location));
555
                    });
556
            }
557
            
558
            // Gotta drop some Upsilons.
559
            size_t upsilonInsertionPoint = block->size() - 1;
560
            NodeOrigin upsilonOrigin = block->last()->origin;
561
            for (BasicBlock* successorBlock : block->successors()) {
562
                for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) {
563
                    Node* phiNode = phiDef->value();
564
                    SSACalculator::Variable* variable = phiDef->variable();
565
                    PromotedHeapLocation location = m_indexToLocation[variable->index()];
566
                    Node* incoming = resolve(block, location);
567
                    
568
                    m_insertionSet.insertNode(
569
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
570
                        OpInfo(phiNode), incoming->defaultEdge());
571
                }
572
            }
573
            
574
            m_insertionSet.execute(block);
575
        }
576
    }
577
    
578
    Node* resolve(BasicBlock* block, PromotedHeapLocation location)
579
    {
580
        if (Node* result = m_localMapping.get(location))
581
            return result;
582
        
583
        // This implies that there is no local mapping. Find a non-local mapping.
584
        Def* def = m_ssaCalculator.nonLocalReachingDef(block, m_locationToVariable.get(location));
585
        ASSERT(def);
586
        ASSERT(def->value());
587
        m_localMapping.add(locaftion, def->value());
588
        return def->value();
589
    }
590
591
    template<typename... Args>
592
    static void doNothing(Args...) { }
593
    
594
    template<typename SinkCandidateFunctor, typename EscapeFunctor>
595
    void handleNode(
596
        Node* node,
597
        const SinkCandidateFunctor& sinkCandidate,
598
        const EscapeFunctor& escape)
599
    {
600
        switch (node->op()) {
601
        case NewObject:
602
        case MaterializeNewObject:
603
            sinkCandidate();
604
            break;
605
            
606
        case CheckStructure:
607
        case GetByOffset:
608
        case MultiGetByOffset:
609
        case PutStructure:
610
        case GetGetterSetterByOffset:
611
        case MovHint:
612
            break;
613
            
614
        case PutByOffset:
615
            escape(node->child3().node());
616
            break;
617
            
618
        case MultiPutByOffset:
619
            // FIXME: In the future we should be able to handle this. It's just a matter of
620
            // building the appropriate *Hint variant of this instruction, along with a
621
            // PhantomStructureSelect node - since this transforms the Structure in a conditional
622
            // way.
623
            // https://bugs.webkit.org/show_bug.cgi?id=136924
624
            escape(node->child1().node());
625
            escape(node->child2().node());
626
            break;
627
628
        default:
629
            m_graph.doToChildren(
630
                node,
631
                [&escape] (Edge edge) {
632
                    escape(edge.node());
633
                });
634
            break;
635
        }
636
    }
637
    
638
    Node* createMaterialize(Node* escapee, const NodeOrigin whereOrigin)
639
    {
640
        switch (escapee->op()) {
641
        case NewObject:
642
        case MaterializeNewObject:
643
            return m_graph.addNode(
644
                escapee->prediction(), MaterializeNewObject,
645
                NodeOrigin(
646
                    escapee->origin.semantic,
647
                    whereOrigin.forExit),
648
                OpInfo(m_graph.m_objectMaterializationData.add()),
649
                OpInfo(), 0, 0);
650
            
651
        default:
652
            DFG_CRASH(m_graph, where, "Bad escapee op");
653
            return nullptr;
654
        }
655
        
656
        return result;
657
    }
658
    
659
    void populateMaterialize(BasicBlock* block, Node* node, Node* escapee)
660
    {
661
        switch (node->op()) {
662
        case MaterializeNewObject: {
663
            ObjectMaterializationData* data = node->objectMaterializationData();
664
            unsigned firstChild = m_graph.m_varArgChildren.size();
665
            
666
            Vector<PromotedHeapLocation>& locations = m_LocationsForAllocation.get(escapee);
667
            
668
            PromotedHeapLocation structure(StructurePLoc, escapee);
669
            ASSERT(locations.contains(structure));
670
            
671
            m_graph.m_varArgChildren.append(resolve(block, structure));
672
            
673
            for (unsigned i = 0; i < locations.size(); ++i) {
674
                switch (locations[i].kind()) {
675
                case StructurePLoc: {
676
                    ASSERT(locations[i] == structure);
677
                    break;
678
                }
679
                    
680
                case NamedPropertyPLoc: {
681
                    Node* value = resolve(block, locations[i]);
682
                    if (value->op() == Bottom) {
683
                        // We can skip Bottoms entirely.
684
                        break;
685
                    }
686
                    
687
                    data->m_properties.append(PhantomPropertyValue(locations[i].info()));
688
                    m_graph.m_varArgChildren.append(value);
689
                    break;
690
                }
691
                    
692
                default:
693
                    DFG_CRASH(m_graph, node, "Bad location kind");
694
                }
695
            }
696
            
697
            node->children = AdjacencyList(
698
                AdjacencyList::Variable,
699
                firstChild, m_graph.m_varArgChildren.size() - firstChild);
700
            break;
701
        }
702
            
703
        default:
704
            DFG_CRASH(m_graph, node, "Bad materialize op");
705
            break;
706
        }
707
    }
708
    
709
    SSACalculator m_ssaCalculator;
710
    HashSet<Node*> m_sinkCandidates;
711
    HashMap<std::pair<Node*, Node*>, Node*> m_edgeToMaterializationPoint;
712
    HashMap<Node*, Node*> m_materializationPointToEscapee;
713
    HashMap<Node*, Vector<PromotedHeapLocation>> m_locationsForAllocation;
714
    HashMap<PromotedHeapLocation, SSACalculator::Variable*> m_locationToVariable;
715
    Vector<PromotedHeapLocation> m_indexToLocation;
716
    HashMap<PromotedHeapLocation, Node*> m_localMapping;
717
    InsertionSet m_insertionSet;
718
};
719
    
720
bool performObjectAllocationSinking(Graph& graph)
721
{
722
    SamplingRegion samplingRegion("DFG Object Allocation Sinking Phase");
723
    return runPhase<ObjectAllocationSinkingPhase>(graph);
724
}
725
726
} } // namespace JSC::DFG
727
728
#endif // ENABLE(DFG_JIT)
729
- 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 +82 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
    template<typename Functor>
45
    void forAllIncomingValues(Node* node, const Functor& functor)
46
    {
47
        for (Node* upsilon : upsilonsOf(node))
48
            functor(node->child1().node());
49
    }
50
    
51
    // This walks the Phi graph.
52
    template<typename Functor>
53
    void forAllTransitiveIncomingValues(Node* node, const Functor& functor)
54
    {
55
        HashSet<Node*> seen;
56
        Vector<Node*> worklist;
57
        seen.add(node);
58
        worklist.append(node);
59
        while (!worklist.isEmpty()) {
60
            Node* currentNode = worklist.takeLast();
61
            forAllIncomingValues(
62
                currentNode,
63
                [&] (Node* incomingNode) {
64
                    if (incomingNode->op() == Phi) {
65
                        if (seen.add(incomingNode))
66
                            worklist.append(incomingNode);
67
                    } else
68
                        functor(incomingNode);
69
                });
70
        }
71
    }
72
    
73
private:
74
    HashMap<Node*, List> m_children;
75
};
76
77
} } // namespace JSC::DFG
78
79
#endif // ENABLE(DFG_JIT)
80
81
#endif // DFGPhiChildren_h
82
- 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/JavaScriptCore/ftl/FTLExitPropertyValue.cpp +41 lines
Line 0 Source/JavaScriptCore/ftl/FTLExitPropertyValue.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 "FTLExitPropertyValue.h"
28
29
#if ENABLE(FTL_JIT)
30
31
namespace JSC { namespace FTL {
32
33
void ExitPropertyValue::dump(PrintStream& out) const
34
{
35
    out.print(m_uid, " => ", m_value);
36
}
37
38
} } // namespace JSC::FTL
39
40
#endif // ENABLE(FTL_JIT)
41
- Source/JavaScriptCore/ftl/FTLExitPropertyValue.h +67 lines
Line 0 Source/JavaScriptCore/ftl/FTLExitPropertyValue.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 FTLExitPropertyValue_h
27
#define FTLExitPropertyValue_h
28
29
#if ENABLE(FTL_JIT)
30
31
#include "FTLExitValue.h"
32
#include <wtf/StringImpl.h>
33
34
namespace JSC { namespace FTL {
35
36
class ExitPropertyValue {
37
public:
38
    ExitPropertyValue()
39
        : m_uid(nullptr)
40
    {
41
    }
42
    
43
    ExitPropertyValue(StringImpl* uid, const ExitValue& value)
44
        : m_uid(uid)
45
        , m_value(value)
46
    {
47
        ASSERT(!!uid == !!value);
48
    }
49
    
50
    bool operator!() const { return !m_uid; }
51
    
52
    StringImpl* uid() const { return m_uid; }
53
    const ExitValue& value() const { return m_value; }
54
    
55
    void dump(PrintStream& out) const;
56
57
private:
58
    StringImpl* m_uid;
59
    ExitValue m_value;
60
};
61
62
} } // namespace JSC::FTL
63
64
#endif // ENABLE(FTL_JIT)
65
66
#endif // FTLExitPropertyValue_h
67
- Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp +45 lines
Line 0 Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.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 "FTLExitTimeObjectMaterialization.h"
28
29
#if ENABLE(FTL_JIT)
30
31
namespace JSC { namespace FTL {
32
33
ExitTimeObjectMaterialization::~ExitTimeObjectMaterialization()
34
{
35
}
36
37
void ExitTimeObjectMaterialization::dump(PrintStream& out) const
38
{
39
    out.print("<new Object: structure => ", m_structure, ", {", listDump(m_properties), "}>");
40
}
41
42
} } // namespace JSC::FTL
43
44
#endif // ENABLE(FTL_JIT)
45
- Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h +69 lines
Line 0 Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.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 FTLExitTimeObjectMaterialization_h
27
#define FTLExitTimeObjectMaterialization_h
28
29
#if ENABLE(FTL_JIT)
30
31
#include "FTLExitPropertyValue.h"
32
#include "FTLExitValue.h"
33
34
namespace JSC { namespace FTL {
35
36
class ExitTimeObjectMaterialization {
37
public:
38
    ExitTimeObjectMaterialization()
39
    {
40
    }
41
    
42
    ~ExitTimeObjectMaterialization();
43
    
44
    void setStructure(const ExitValue& value)
45
    {
46
        m_structure = value;
47
    }
48
    
49
    void addProperty(const ExitPropertyValue& value)
50
    {
51
        m_properties.append(value);
52
    }
53
    
54
    const ExitValue& structure() const { return m_structure; }
55
    const Vector<ExitPropertyValue>& properties() const { return m_properties; }
56
    
57
    void dump(PrintStream& out) const;
58
    
59
private:
60
    ExitValue m_structure;
61
    Vector<ExitPropertyValue> m_properties;
62
};
63
64
} } // namespace JSC::FTL
65
66
#endif // ENABLE(FTL_JIT)
67
68
#endif // FTLExitTimeObjectMaterialization_h
69
- Source/JavaScriptCore/ftl/FTLExitValue.cpp +53 lines
Lines 32-37 Source/JavaScriptCore/ftl/FTLExitValue.cpp_sec1
32
32
33
namespace JSC { namespace FTL {
33
namespace JSC { namespace FTL {
34
34
35
ExitValue::~ExitValue()
36
{
37
    deleteData();
38
}
39
40
void ExitValue::deleteData()
41
{
42
    switch (kind()) {
43
    case ExitValueMaterializeNewObject:
44
        delete u.newObjectMaterializationData;
45
        break;
46
    default:
47
        break;
48
    }
49
}
50
51
ExitValue::ExitValue(const ExitValue& other)
52
    : m_kind(InvalidExitValue)
53
{
54
    *this = other;
55
}
56
57
ExitValue& ExitValue::operator=(const ExitValue& other)
58
{
59
    if (this == &other)
60
        return;
61
    
62
    deleteData();
63
    
64
    m_kind = other.m_kind;
65
    u = other.u;
66
    
67
    switch (kind()) {
68
    case ExitValueMaterializeNewObject:
69
        u.newObjectMaterializationData =
70
            new ExitTimeObjectMaterialization(*u.newObjectMaterializationData);
71
        break;
72
    default:
73
        break;
74
    }
75
}
76
77
void ExitValue ExitValue::materializeNewObject(const ExitTimeObjectMaterialization& data)
78
{
79
    ExitValue result;
80
    result.m_kind = ExitValueMaterializeNewObject;
81
    result.u.newObjectMaterializationData = new ExitTimeObjectMaterialization(data);
82
    return result;
83
}
84
35
void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const
85
void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const
36
{
86
{
37
    switch (kind()) {
87
    switch (kind()) {
Lines 65-70 void ExitValue::dumpInContext(PrintStrea Source/JavaScriptCore/ftl/FTLExitValue.cpp_sec2
65
    case ExitValueRecovery:
115
    case ExitValueRecovery:
66
        out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")");
116
        out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")");
67
        return;
117
        return;
118
    case ExitValueMaterializeNewObject:
119
        out.print("Materialize(", objectMaterialization(), ")");
120
        return;
68
    }
121
    }
69
    
122
    
70
    RELEASE_ASSERT_NOT_REACHED();
123
    RELEASE_ASSERT_NOT_REACHED();
- Source/JavaScriptCore/ftl/FTLExitValue.h -3 / +24 lines
Lines 52-60 enum ExitValueKind { Source/JavaScriptCore/ftl/FTLExitValue.h_sec1
52
    ExitValueInJSStackAsInt52,
52
    ExitValueInJSStackAsInt52,
53
    ExitValueInJSStackAsDouble,
53
    ExitValueInJSStackAsDouble,
54
    ExitValueArgumentsObjectThatWasNotCreated,
54
    ExitValueArgumentsObjectThatWasNotCreated,
55
    ExitValueRecovery
55
    ExitValueRecovery,
56
    ExitValueMaterializeNewObject
56
};
57
};
57
58
59
class ExitTimeObjectMaterialization;
60
58
class ExitValue {
61
class ExitValue {
59
public:
62
public:
60
    ExitValue()
63
    ExitValue()
Lines 62-67 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec2
62
    {
65
    {
63
    }
66
    }
64
    
67
    
68
    ~ExitValue();
69
    
70
    ExitValue(const ExitValue&);
71
    ExitValue& operator=(const ExitValue&);
72
    
65
    bool operator!() const { return m_kind == InvalidExitValue; }
73
    bool operator!() const { return m_kind == InvalidExitValue; }
66
    
74
    
67
    static ExitValue dead()
75
    static ExitValue dead()
Lines 137-142 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec3
137
        return result;
145
        return result;
138
    }
146
    }
139
    
147
    
148
    static ExitValue materializeNewObject(const ExitTimeObjectMaterialization&);
149
    
140
    ExitValueKind kind() const { return m_kind; }
150
    ExitValueKind kind() const { return m_kind; }
141
    
151
    
142
    bool isDead() const { return kind() == ExitValueDead; }
152
    bool isDead() const { return kind() == ExitValueDead; }
Lines 156-161 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec4
156
    bool isArgument() const { return kind() == ExitValueArgument; }
166
    bool isArgument() const { return kind() == ExitValueArgument; }
157
    bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; }
167
    bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; }
158
    bool isRecovery() const { return kind() == ExitValueRecovery; }
168
    bool isRecovery() const { return kind() == ExitValueRecovery; }
169
    bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject; }
159
    
170
    
160
    ExitArgument exitArgument() const
171
    ExitArgument exitArgument() const
161
    {
172
    {
Lines 199-205 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec5
199
        return VirtualRegister(u.virtualRegister);
210
        return VirtualRegister(u.virtualRegister);
200
    }
211
    }
201
    
212
    
202
    ExitValue withVirtualRegister(VirtualRegister virtualRegister)
213
    const ExitTimeObjectMaterialization& objectMaterialization() const
214
    {
215
        ASSERT(isObjectMaterialization());
216
        return *u.newObjectMaterializationData;
217
    }
218
219
    ExitValue withVirtualRegister(VirtualRegister virtualRegister) const
203
    {
220
    {
204
        ASSERT(isInJSStackSomehow());
221
        ASSERT(isInJSStackSomehow());
205
        ExitValue result;
222
        ExitValue result;
Lines 207-213 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec6
207
        result.u.virtualRegister = virtualRegister.offset();
224
        result.u.virtualRegister = virtualRegister.offset();
208
        return result;
225
        return result;
209
    }
226
    }
210
227
    
211
    // If it's in the JSStack somehow, this will tell you what format it's in, in a manner
228
    // If it's in the JSStack somehow, this will tell you what format it's in, in a manner
212
    // that is compatible with exitArgument().format(). If it's a constant or it's dead, it
229
    // that is compatible with exitArgument().format(). If it's a constant or it's dead, it
213
    // will claim to be a JSValue. If it's an argument then it will tell you the argument's
230
    // will claim to be a JSValue. If it's an argument then it will tell you the argument's
Lines 223-228 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec7
223
        case ExitValueConstant:
240
        case ExitValueConstant:
224
        case ExitValueInJSStack:
241
        case ExitValueInJSStack:
225
        case ExitValueArgumentsObjectThatWasNotCreated:
242
        case ExitValueArgumentsObjectThatWasNotCreated:
243
        case ExitValueMaterializeNewObject:
226
            return ValueFormatJSValue;
244
            return ValueFormatJSValue;
227
            
245
            
228
        case ExitValueArgument:
246
        case ExitValueArgument:
Lines 249-254 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec8
249
    void dumpInContext(PrintStream&, DumpContext*) const;
267
    void dumpInContext(PrintStream&, DumpContext*) const;
250
    
268
    
251
private:
269
private:
270
    void deleteData();
271
    
252
    ExitValueKind m_kind;
272
    ExitValueKind m_kind;
253
    union {
273
    union {
254
        ExitArgumentRepresentation argument;
274
        ExitArgumentRepresentation argument;
Lines 260-265 private: Source/JavaScriptCore/ftl/FTLExitValue.h_sec9
260
            uint16_t opcode;
280
            uint16_t opcode;
261
            uint16_t format;
281
            uint16_t format;
262
        } recovery;
282
        } recovery;
283
        ExitTimeObjectMaterialization* newObjectMaterializationData;
263
    } u;
284
    } u;
264
};
285
};
265
286
- Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp -74 / +81 lines
Lines 46-51 namespace JSC { namespace FTL { Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp_sec1
46
46
47
using namespace DFG;
47
using namespace DFG;
48
48
49
static void compileRecovery(
50
    CCallHeleprs& jit, const ExitValue& value, StackMaps::Record* record, StackMaps& stackmaps,
51
    char *registerScratch)
52
{
53
    switch (value.kind()) {
54
    case ExitValueDead:
55
        jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0);
56
        break;
57
            
58
    case ExitValueConstant:
59
        jit.move(MacroAssembler::TrustedImm64(JSValue::encode(value.constant())), GPRInfo::regT0);
60
        break;
61
            
62
    case ExitValueArgument:
63
        record->locations[value.exitArgument().argument()].restoreInto(
64
            jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
65
        break;
66
            
67
    case ExitValueInJSStack:
68
    case ExitValueInJSStackAsInt32:
69
    case ExitValueInJSStackAsInt52:
70
    case ExitValueInJSStackAsDouble:
71
        jit.load64(AssemblyHelpers::addressFor(value.virtualRegister()), GPRInfo::regT0);
72
        break;
73
            
74
    case ExitValueArgumentsObjectThatWasNotCreated:
75
        // We can't actually recover this yet, but we can make the stack look sane. This is
76
        // a prerequisite to running the actual arguments recovery.
77
        jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0);
78
        break;
79
            
80
    case ExitValueRecovery:
81
        record->locations[value.rightRecoveryArgument()].restoreInto(
82
            jit, jitCode->stackmaps, registerScratch, GPRInfo::regT1);
83
        record->locations[value.leftRecoveryArgument()].restoreInto(
84
            jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
85
        switch (value.recoveryOpcode()) {
86
        case AddRecovery:
87
            switch (value.recoveryFormat()) {
88
            case ValueFormatInt32:
89
                jit.add32(GPRInfo::regT1, GPRInfo::regT0);
90
                break;
91
            case ValueFormatInt52:
92
                jit.add64(GPRInfo::regT1, GPRInfo::regT0);
93
                break;
94
            default:
95
                RELEASE_ASSERT_NOT_REACHED();
96
                break;
97
            }
98
            break;
99
        case SubRecovery:
100
            switch (value.recoveryFormat()) {
101
            case ValueFormatInt32:
102
                jit.sub32(GPRInfo::regT1, GPRInfo::regT0);
103
                break;
104
            case ValueFormatInt52:
105
                jit.sub64(GPRInfo::regT1, GPRInfo::regT0);
106
                break;
107
            default:
108
                RELEASE_ASSERT_NOT_REACHED();
109
                break;
110
            }
111
            break;
112
        default:
113
            RELEASE_ASSERT_NOT_REACHED();
114
            break;
115
        }
116
        break;
117
            
118
    default:
119
        RELEASE_ASSERT_NOT_REACHED();
120
        break;
121
    }
122
        
123
    reboxAccordingToFormat(
124
        value.valueFormat(), jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
125
}
126
49
static void compileStub(
127
static void compileStub(
50
    unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock)
128
    unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock)
51
{
129
{
Lines 125-204 static void compileStub( Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp_sec2
125
    // the scratch buffer. This also does the reboxing.
203
    // the scratch buffer. This also does the reboxing.
126
    
204
    
127
    for (unsigned index = exit.m_values.size(); index--;) {
205
    for (unsigned index = exit.m_values.size(); index--;) {
128
        ExitValue value = exit.m_values[index];
206
        ExitValue& value = exit.m_values[index];
129
        
207
130
        switch (value.kind()) {
208
        compileRecovery(jit, value, record, jitCode->stackmaps, registerScratch);
131
        case ExitValueDead:
132
            jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0);
133
            break;
134
            
135
        case ExitValueConstant:
136
            jit.move(MacroAssembler::TrustedImm64(JSValue::encode(value.constant())), GPRInfo::regT0);
137
            break;
138
            
139
        case ExitValueArgument:
140
            record->locations[value.exitArgument().argument()].restoreInto(
141
                jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
142
            break;
143
            
144
        case ExitValueInJSStack:
145
        case ExitValueInJSStackAsInt32:
146
        case ExitValueInJSStackAsInt52:
147
        case ExitValueInJSStackAsDouble:
148
            jit.load64(AssemblyHelpers::addressFor(value.virtualRegister()), GPRInfo::regT0);
149
            break;
150
            
151
        case ExitValueArgumentsObjectThatWasNotCreated:
152
            // We can't actually recover this yet, but we can make the stack look sane. This is
153
            // a prerequisite to running the actual arguments recovery.
154
            jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0);
155
            break;
156
            
157
        case ExitValueRecovery:
158
            record->locations[value.rightRecoveryArgument()].restoreInto(
159
                jit, jitCode->stackmaps, registerScratch, GPRInfo::regT1);
160
            record->locations[value.leftRecoveryArgument()].restoreInto(
161
                jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
162
            switch (value.recoveryOpcode()) {
163
            case AddRecovery:
164
                switch (value.recoveryFormat()) {
165
                case ValueFormatInt32:
166
                    jit.add32(GPRInfo::regT1, GPRInfo::regT0);
167
                    break;
168
                case ValueFormatInt52:
169
                    jit.add64(GPRInfo::regT1, GPRInfo::regT0);
170
                    break;
171
                default:
172
                    RELEASE_ASSERT_NOT_REACHED();
173
                    break;
174
                }
175
                break;
176
            case SubRecovery:
177
                switch (value.recoveryFormat()) {
178
                case ValueFormatInt32:
179
                    jit.sub32(GPRInfo::regT1, GPRInfo::regT0);
180
                    break;
181
                case ValueFormatInt52:
182
                    jit.sub64(GPRInfo::regT1, GPRInfo::regT0);
183
                    break;
184
                default:
185
                    RELEASE_ASSERT_NOT_REACHED();
186
                    break;
187
                }
188
                break;
189
            default:
190
                RELEASE_ASSERT_NOT_REACHED();
191
                break;
192
            }
193
            break;
194
            
195
        default:
196
            RELEASE_ASSERT_NOT_REACHED();
197
            break;
198
        }
199
        
200
        reboxAccordingToFormat(
201
            value.valueFormat(), jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
202
        
209
        
203
        jit.store64(GPRInfo::regT0, scratch + index);
210
        jit.store64(GPRInfo::regT0, scratch + index);
204
    }
211
    }
- 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