| 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/DFGAvailability.h +7 lines
Lines 85-90 public: Source/JavaScriptCore/dfg/DFGAvailability.h_sec1
85
    bool nodeIsUnavailable() const { return m_node == unavailableMarker(); }
85
    bool nodeIsUnavailable() const { return m_node == unavailableMarker(); }
86
    
86
    
87
    bool hasNode() const { return !nodeIsUndecided() && !nodeIsUnavailable(); }
87
    bool hasNode() const { return !nodeIsUndecided() && !nodeIsUnavailable(); }
88
    bool shouldUseNode() const { return !isFlushUseful() && hasNode(); }
88
    
89
    
89
    Node* node() const
90
    Node* node() const
90
    {
91
    {
Lines 94-99 public: Source/JavaScriptCore/dfg/DFGAvailability.h_sec2
94
    }
95
    }
95
    
96
    
96
    FlushedAt flushedAt() const { return m_flushedAt; }
97
    FlushedAt flushedAt() const { return m_flushedAt; }
98
    bool isFlushUseful() const
99
    {
100
        return flushedAt().format() != DeadFlush && flushedAt().format() != ConflictingFlush;
101
    }
102
    
103
    bool isDead() const { return !isFlushUseful() && !hasNode(); }
97
    
104
    
98
    bool operator!() const { return nodeIsUnavailable() && flushedAt().format() == ConflictingFlush; }
105
    bool operator!() const { return nodeIsUnavailable() && flushedAt().format() == ConflictingFlush; }
99
106
- Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp +89 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
    if (m_heap.isEmpty())
38
        return;
39
    
40
    HashSet<Node*> possibleNodes;
41
    
42
    for (unsigned i = m_locals.size(); i--;) {
43
        if (m_locals[i].hasNode())
44
            possibleNodes.add(m_locals[i].node());
45
    }
46
47
    unsigned oldPossibleNodesSize;
48
    do {
49
        oldPossibleNodesSize = possibleNodes.size();
50
        for (auto pair : m_heap) {
51
            if (pair.value.hasNode() && possibleNodes.contains(pair.key.base()))
52
                possibleNodes.add(pair.value.node());
53
        }
54
    } while (oldPossibleNodesSize != possibleNodes.size());
55
    
56
    HashMap<PromotedHeapLocation, Availability> newHeap;
57
    for (auto pair : m_heap) {
58
        if (possibleNodes.contains(pair.key.base()))
59
            newHeap.add(pair.key, pair.value);
60
    }
61
    m_heap = newHeap;
62
}
63
64
void AvailabilityMap::dump(PrintStream& out) const
65
{
66
    out.print("{locals = ", m_locals, "; heap = ", mapDump(m_heap), "}");
67
}
68
69
bool AvailabilityMap::operator==(const AvailabilityMap& other) const
70
{
71
    return m_locals == other.m_locals
72
        && m_heap == other.m_heap;
73
}
74
75
void AvailabilityMap::merge(const AvailabilityMap& other)
76
{
77
    for (unsigned i = other.m_locals.size(); i--;)
78
        locals[i] = other.m_locals[i].merge(locals[i]);
79
    
80
    for (auto pair : other.m_heap) {
81
        auto result = m_heap.add(pair.key, Availability());
82
        result.iterator->value = pair.value.merge(result.iterator->value);
83
    }
84
}
85
86
} } // namespace JSC::DFG
87
88
#endif // ENABLE(DFG_JIT)
89
- Source/JavaScriptCore/dfg/DFGAvailabilityMap.h +62 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
    template<typename Functor>
45
    void forEachAvailability(const Functor& functor)
46
    {
47
        for (unsigned i = m_locals.size(); i--;)
48
            functor(m_locals[i]);
49
        for (auto pair : m_heap)
50
            functor(pair.value);
51
    }
52
    
53
    Operands<Availability> m_locals;
54
    HashMap<PromotedHeapLocation, Availability> m_heap;
55
};
56
57
} } // namespace JSC::DFG
58
59
#endif // ENABLE(DFG_JIT)
60
61
#endif // DFGAvailabilityMap_h
62
- 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.cpp +21 lines
Lines 562-567 void Graph::resetReachability() Source/JavaScriptCore/dfg/DFGGraph.cpp_sec1
562
    determineReachability();
562
    determineReachability();
563
}
563
}
564
564
565
void Graph::mergeRelevantToOSR()
566
{
567
    for (BasicBlock* block : blocksInNaturalOrder()) {
568
        for (Node* node : *block) {
569
            switch (node->op()) {
570
            case MovHint:
571
                node->child1()->mergeFlags(NodeRelevantToOSR);
572
                break;
573
                
574
            case PutStructureHint:
575
            case PutByOffsetHint:
576
                node->child2()->mergeFlags(NodeRelevantToOSR);
577
                break;
578
                
579
            default:
580
                break;
581
            }
582
        }
583
    }
584
}
585
565
namespace {
586
namespace {
566
587
567
class RefCountCalculator {
588
class RefCountCalculator {
- Source/JavaScriptCore/dfg/DFGGraph.h +107 lines
Lines 565-570 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec1
565
    void determineReachability();
565
    void determineReachability();
566
    void resetReachability();
566
    void resetReachability();
567
    
567
    
568
    void mergeRelevantToOSR();
569
    
568
    void computeRefCounts();
570
    void computeRefCounts();
569
    
571
    
570
    unsigned varArgNumChildren(Node* node)
572
    unsigned varArgNumChildren(Node* node)
Lines 676-681 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec2
676
    BlockList blocksInPreOrder();
678
    BlockList blocksInPreOrder();
677
    BlockList blocksInPostOrder();
679
    BlockList blocksInPostOrder();
678
    
680
    
681
    class NaturalBlockIterable {
682
    public:
683
        NaturalBlockIterable()
684
            : m_graph(nullptr)
685
        {
686
        }
687
        
688
        NaturalBlockIterable(Graph& graph)
689
            : m_graph(&graph)
690
        {
691
        }
692
        
693
        class iterator {
694
        public:
695
            iterator()
696
                : m_graph(nullptr)
697
                , m_index(0)
698
            {
699
            }
700
            
701
            iterator(Graph& graph, BlockIndex index)
702
                : m_graph(&graph)
703
                , m_index(findNext(index))
704
            {
705
            }
706
            
707
            BasicBlock *operator*()
708
            {
709
                return m_graph->block(index);
710
            }
711
            
712
            iterator& operator++()
713
            {
714
                m_index = findNext(m_index);
715
                return *this;
716
            }
717
            
718
            bool operator==(const iterator& other) const
719
            {
720
                return m_index == other.m_index;
721
            }
722
            
723
            bool operator!=(const iterator& other) const
724
            {
725
                return !(*this == other);
726
            }
727
            
728
        private:
729
            BlockIndex findNext(BlockIndex index)
730
            {
731
                while (index < m_graph->numBlocks() && !m_graph->block(index))
732
                    index++;
733
                return index;
734
            }
735
            
736
            Graph* m_graph;
737
            BlockIndex m_index;
738
        };
739
        
740
        iterator begin()
741
        {
742
            return iterator(*m_graph, 0);
743
        }
744
        
745
        iterator end()
746
        {
747
            return iterator(*m_graph, m_graph->numBlocks());
748
        }
749
        
750
    private:
751
        Graph* m_graph;
752
    };
753
    
754
    NaturalBlockIterable blocksInNaturalOrder()
755
    {
756
        return NaturalBlockIterable(*this);
757
    }
758
    
759
    template<typename ChildFunctor>
760
    void doToChildrenWithNode(Node* node, const ChildFunctor& functor)
761
    {
762
        DFG_NODE_DO_TO_CHILDREN(node, functor);
763
    }
764
    
765
    template<typename ChildFunctor>
766
    void doToChildEdges(Node* node, const ChildFunctor& functor)
767
    {
768
        doToChildrenWithNode(
769
            node,
770
            [&functor] (Node*, Edge& edge) {
771
                functor(edge);
772
            });
773
    }
774
    
775
    template<typename ChildFunctor>
776
    void doToChildren(Node* node, const ChildFunctor& functor)
777
    {
778
        doToChildrenWithNode(
779
            node,
780
            [&functor] (Node*, Edge edge) {
781
                functor(edge);
782
            });
783
    }
784
    
679
    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
785
    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
680
    
786
    
681
    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
787
    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
Lines 736-741 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec3
736
    Bag<SwitchData> m_switchData;
842
    Bag<SwitchData> m_switchData;
737
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
843
    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
738
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
844
    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
845
    Bag<ObjectMaterializationData> m_objectMaterializationData;
739
    Vector<InlineVariableData, 4> m_inlineVariableData;
846
    Vector<InlineVariableData, 4> m_inlineVariableData;
740
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
847
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
741
    bool m_hasArguments;
848
    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 / +61 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
    
1237
    bool isPhantomObjectAllocation()
1238
    {
1239
        switch (op()) {
1240
        case PhantomNewObject:
1241
            return true;
1242
        default:
1243
            return false;
1244
        }
1245
    }
1246
    
1187
    bool hasFunctionDeclIndex()
1247
    bool hasFunctionDeclIndex()
1188
    {
1248
    {
1189
        return op() == NewFunction
1249
        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/DFGPhantomCanonicalizationPhase.cpp -12 / +1 lines
Lines 52-69 public: Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp_sec1
52
        ASSERT(m_graph.m_form == SSA);
52
        ASSERT(m_graph.m_form == SSA);
53
        
53
        
54
        m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeNeedsHardPhantom | NodeRelevantToOSR);
54
        m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeNeedsHardPhantom | NodeRelevantToOSR);
55
        
55
        m_graph.mergeRelevantToOSR();
56
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
57
            BasicBlock* block = m_graph.block(blockIndex);
58
            if (!block)
59
                continue;
60
            
61
            for (unsigned i = block->size(); i--;) {
62
                Node* node = block->at(i);
63
                if (node->op() == MovHint)
64
                    node->child1()->mergeFlags(NodeRelevantToOSR);
65
            }
66
        }
67
        
56
        
68
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
57
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
69
            BasicBlock* block = m_graph.block(blockIndex);
58
            BasicBlock* block = m_graph.block(blockIndex);
- Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp -11 / +1 lines
Lines 74-90 public: Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp_sec1
74
            }
74
            }
75
        }
75
        }
76
        
76
        
77
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
77
        m_graph.mergeRelevantToOSR();
78
            BasicBlock* block = m_graph.block(blockIndex);
79
            if (!block)
80
                continue;
81
            
82
            for (unsigned i = block->size(); i--;) {
83
                Node* node = block->at(i);
84
                if (node->op() == MovHint)
85
                    node->child1()->mergeFlags(NodeRelevantToOSR);
86
            }
87
        }
88
        
78
        
89
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
79
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
90
            BasicBlock* block = m_graph.block(blockIndex);
80
            BasicBlock* block = m_graph.block(blockIndex);
- 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 +91 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
void BaselessPromotedHeapLocation::dump(PrintStream& out) const
34
{
35
    out.print(m_kind, "(", m_info, ")");
36
}
37
38
Node* PromotedHeapLocation::createHint(Graph& graph, NodeOrigin origin, Node* value)
39
{
40
    switch (kind()) {
41
    case StructurePLoc:
42
        return graph.addNode(
43
            SpecNone, PutStructureHint, origin,
44
            Edge(base(), KnownCellUse), value);
45
        
46
    case NamedPropertyPLoc:
47
        return graph.addNode(
48
            SpecNone, PutByOffsetHint, origin,
49
            OpInfo(info()), Edge(base(), KnownCellUse), value);
50
        
51
    case InvalidPromotedLocationKind:
52
        return nullptr;
53
    }
54
    
55
    RELEASE_ASSERT_NOT_REACHED();
56
}
57
58
void PromotedHeapLocation::dump(PrintStream& out) const
59
{
60
    out.print(kind(), "(", m_base, ", ", info(), ")");
61
}
62
63
} } // namespace JSC::DFG
64
65
namespace WTF {
66
67
using namespace JSC::DFG;
68
69
void printInternal(PrintStream& out, PromotedLocationKind kind)
70
{
71
    switch (kind) {
72
    case InvalidPromotedLocationKind:
73
        out.print("InvalidPromotedLocationKind");
74
        return;
75
        
76
    case StructurePLoc:
77
        out.print("StructurePLoc");
78
        return;
79
        
80
    case NamedPropertyPLoc:
81
        out.print("NamedPropertyPLoc");
82
        return;
83
    }
84
    
85
    RELEASE_ASSERT_NOT_REACHED();
86
}
87
88
} // namespace WTF;
89
90
#endif // ENABLE(DFG_JIT)
91
- Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h +212 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 BaselessPromotedHeapLocation {
44
    BaselessPromotedHeapLocation(
45
        PromotedLocationKind kind = InvalidPromotedLocationKind, unsigned info = 0)
46
        : m_kind(kind)
47
        , m_info(info)
48
    {
49
    }
50
    
51
    bool operator!() const { return m_kind == InvalidPromotedLocationKind; }
52
    
53
    PromotedLocationKind kind() const { return m_kind; }
54
    unsigned info() const { return m_info; }
55
    
56
    unsigned hash() const
57
    {
58
        return m_kind + m_info;
59
    }
60
    
61
    bool operator==(const BaselessPromotedHeapLocation& other) const
62
    {
63
        return m_kind == other.m_kind
64
            && m_info == other.m_info;
65
    }
66
67
    bool isHashTableDeletedValue() const
68
    {
69
        return m_kind == InvalidPromotedLocationKind && m_info;
70
    }
71
    
72
    void dump(PrintStream& out) const;
73
74
private:
75
    PromtoedLocationKind m_kind;
76
    unsigned m_info;
77
};
78
79
class PromotedHeapLocation {
80
public:
81
    PromotedHeapLocation(
82
        PromotedLocationKind kind = InvalidPromotedLocationKind,
83
        Node* base = nullptr, unsigned info = 0)
84
        : m_base(base)
85
        , m_meta(kind, info)
86
    {
87
    }
88
    
89
    PromotedHeapLocation(
90
        PromotedLocationKind kind, Edge base, unsigned info = 0)
91
        : PromotedHeapLocation(kind, base.node(), info)
92
    {
93
    }
94
    
95
    PromotedHeapLocaftion(Node* base, BaselessPromotedHeapLocation meta)
96
        : m_base(base)
97
        , m_meta(meta)
98
    {
99
    }
100
    
101
    PromotedHeapLocation(WTF::HashTableDeletedValueType)
102
        : m_base(nullptr)
103
        , m_meta(InvalidPromotedLocationKind, 1)
104
    {
105
    }
106
    
107
    Node* createHint(Graph&, NodeOrigin, Node* value);
108
    
109
    bool operator!() const { return kind() == InvalidPromotedLocationKind; }
110
    
111
    PromotedLocationKind kind() const { return m_meta.kind(); }
112
    Node* base() const { return m_base; }
113
    unsigned info() const { return m_meta.info(); }
114
    BaselessPromotedHeapLocation baseless() const { return m_info; }
115
    
116
    unsigned hash() const
117
    {
118
        return m_meta.hash() + WTF::PtrHash<Node*>::hash(m_base);
119
    }
120
    
121
    bool operator==(const PromotedHeapLocation& other) const
122
    {
123
        return m_base == other.m_base
124
            && m_meta == other.m_meta;
125
    }
126
    
127
    bool isHashTableDeletedValue() const
128
    {
129
        return m_meta.isHashTableDeletedValue();
130
    }
131
    
132
    void dump(PrintStream& out) const;
133
    
134
private:
135
    Node* m_base;
136
    BaselessPromotedHeapLocation m_meta;
137
};
138
139
// Note that the write functor is really the useful thing here. The read functor is only useful
140
// for the object allocation sinking phase.
141
template<typename WriteFunctor, typename ReadFunctor>
142
void promote(Node* node, const WriteFunctor& write, const ReadFunctor& read)
143
{
144
    switch (node->op()) {
145
    case CheckStructure:
146
        if (m_sinkCandidates.contains(node->child1().node()))
147
            read(PromotedHeapLocation(StructurePLoc, node->child1()));
148
        break;
149
            
150
    case GetByOffset:
151
    case GetGetterSetterByOffset:
152
        if (m_sinkCandidates.contains(node->child2().node())) {
153
            unsigned identifierNumber =
154
                graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
155
            read(PromotedHeapLocation(NamedPropertyPLoc, node->child2(), identifierNumber));
156
        }
157
        break;
158
                                  
159
    case MultiGetByOffset:
160
        if (m_sinkCandidates.contains(node->child1().node())) {
161
            unsigned identifierNumber = node->multiGetByOffsetData().identifierNumber;
162
            read(PromotedHeapLocation(NamedPropertyPLoc, node->child1(), identiferNumber));
163
        }
164
        break;
165
            
166
    case PutStructureHint:
167
        if (m_sinkCandidates.contains(node->child1().node()))
168
            write(PromotedHeapLocation(StructurePLoc, node->child1()), node->child2());
169
        break;
170
            
171
    case PutByOffsetHint:
172
        if (m_sinkCandidates.contains(node->child1().node())) {
173
            unsigned identifierNumber = node->identifierNumber();
174
            write(
175
                PromotedHeapLocation(NamedPropertyPLoc, node->child1(), identifierNumber),
176
                node->child2().node());
177
        }
178
        break;
179
180
    default:
181
        break;
182
    }
183
}
184
185
struct PromotedHeapLocationHash {
186
    static unsigned hash(const PromotedHeapLocation& key) { return key.hash(); }
187
    static bool equal(const PromotedHeapLocation& a, const PromotedHeapLocation& b) { return a == b; }
188
    static const bool safeToCompareToEmptyOrDeleted = true;
189
};
190
191
} } // namespace JSC::DFG
192
193
namespace WTF {
194
195
void printInternal(PrintStream&, JSC::DFG::PromotedLocationKind);
196
197
template<typename T> struct DefaultHash;
198
template<> struct DefaultHash<JSC::DFG::PromotedHeapLocation> {
199
    typedef JSC::DFG::PromotedHeapLocationHash Hash;
200
};
201
202
template<typename T> struct HashTraits;
203
template<> struct HashTraits<JSC::DFG::PromotedHeapLocation> : SimpleClassHashTraits<JSC::DFG::PromotedHeapLocation> {
204
    static const bool emptyValueIsZero = false;
205
};
206
207
} // namespace WTF
208
209
#endif // ENABLE(DFG_JIT)
210
211
#endif // DFGPromotedHeapLocation_h
212
- 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_location, " => ", m_value);
36
}
37
38
} } // namespace JSC::FTL
39
40
#endif // ENABLE(FTL_JIT)
41
- Source/JavaScriptCore/ftl/FTLExitPropertyValue.h +68 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 "DFGPromotedHeapLocation.h"
32
#include "FTLExitValue.h"
33
#include <wtf/StringImpl.h>
34
35
namespace JSC { namespace FTL {
36
37
class ExitPropertyValue {
38
public:
39
    ExitPropertyValue()
40
        : m_uid(nullptr)
41
    {
42
    }
43
    
44
    ExitPropertyValue(BaselessPromotedHeapLocation location, const ExitValue& value)
45
        : m_location(location)
46
        , m_value(value)
47
    {
48
        ASSERT(!!uid == !!value);
49
    }
50
    
51
    bool operator!() const { return !m_uid; }
52
    
53
    BaselessPromotedHeapLocation location() const { return m_location; }
54
    const ExitValue& value() const { return m_value; }
55
    
56
    void dump(PrintStream& out) const;
57
58
private:
59
    BaselessPromotedHeapLocation m_location;
60
    ExitValue m_value;
61
};
62
63
} } // namespace JSC::FTL
64
65
#endif // ENABLE(FTL_JIT)
66
67
#endif // FTLExitPropertyValue_h
68
- Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp +65 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(NodeType type)
34
    : m_type(type)
35
{
36
}
37
38
ExitTimeObjectMaterialization::~ExitTimeObjectMaterialization()
39
{
40
}
41
42
void ExitTimeObjectMaterialization::add(
43
    BaselessPromotedHeapLocation location, const ExitValue& value)
44
{
45
    m_properties.append(ExitPropertyValue(location, value));
46
}
47
48
const ExitValue& ExitTimeObjectMaterialization::get(BaselessPromotedHeapLocation location) const
49
{
50
    for (ExitPropertyValue value : m_properties) {
51
        if (value.location() == location)
52
            return value.value();
53
    }
54
    return ExitValue();
55
}
56
57
void ExitTimeObjectMaterialization::dump(PrintStream& out) const
58
{
59
    out.print("<", Graph::opName(m_type), ": ", listDump(m_properties), ">");
60
}
61
62
} } // namespace JSC::FTL
63
64
#endif // ENABLE(FTL_JIT)
65
- Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h +62 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
#include <wtf/Noncopyable.h>
34
35
namespace JSC { namespace FTL {
36
37
class ExitTimeObjectMaterialization {
38
    WTF_MAKE_NONCOPYABLE(ExitTimeObjectMaterialization)
39
public:
40
    ExitTimeObjectMaterialization(NodeType);
41
    ~ExitTimeObjectMaterialization();
42
    
43
    void add(DFG::BaselessPromptedHeapLocation, const ExitValue&);
44
    
45
    NodeType type() const { return m_type; }
46
    
47
    const ExitValue& get(DFG::BaselessPromotedHeapLocation) const;
48
    const Vector<ExitPropertyValue>& properties() const { return m_properties; }
49
    
50
    void dump(PrintStream& out) const;
51
    
52
private:
53
    NodeType m_type;
54
    Vector<ExitPropertyValue> m_properties;
55
};
56
57
} } // namespace JSC::FTL
58
59
#endif // ENABLE(FTL_JIT)
60
61
#endif // FTLExitTimeObjectMaterialization_h
62
- Source/JavaScriptCore/ftl/FTLExitValue.cpp +11 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
void ExitValue ExitValue::materializeNewObject(ExitTimeObjectMaterialization* data)
36
{
37
    ExitValue result;
38
    result.m_kind = ExitValueMaterializeNewObject;
39
    result.u.newObjectMaterializationData = data;
40
    return result;
41
}
42
35
void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const
43
void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const
36
{
44
{
37
    switch (kind()) {
45
    switch (kind()) {
Lines 65-70 void ExitValue::dumpInContext(PrintStrea Source/JavaScriptCore/ftl/FTLExitValue.cpp_sec2
65
    case ExitValueRecovery:
73
    case ExitValueRecovery:
66
        out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")");
74
        out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")");
67
        return;
75
        return;
76
    case ExitValueMaterializeNewObject:
77
        out.print("Materialize(", pointerDump(objectMaterialization()), ")");
78
        return;
68
    }
79
    }
69
    
80
    
70
    RELEASE_ASSERT_NOT_REACHED();
81
    RELEASE_ASSERT_NOT_REACHED();
- Source/JavaScriptCore/ftl/FTLExitValue.h -3 / +17 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 137-142 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec2
137
        return result;
140
        return result;
138
    }
141
    }
139
    
142
    
143
    static ExitValue materializeNewObject(const ExitTimeObjectMaterialization*);
144
    
140
    ExitValueKind kind() const { return m_kind; }
145
    ExitValueKind kind() const { return m_kind; }
141
    
146
    
142
    bool isDead() const { return kind() == ExitValueDead; }
147
    bool isDead() const { return kind() == ExitValueDead; }
Lines 156-161 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec3
156
    bool isArgument() const { return kind() == ExitValueArgument; }
161
    bool isArgument() const { return kind() == ExitValueArgument; }
157
    bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; }
162
    bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; }
158
    bool isRecovery() const { return kind() == ExitValueRecovery; }
163
    bool isRecovery() const { return kind() == ExitValueRecovery; }
164
    bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject; }
159
    
165
    
160
    ExitArgument exitArgument() const
166
    ExitArgument exitArgument() const
161
    {
167
    {
Lines 199-205 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec4
199
        return VirtualRegister(u.virtualRegister);
205
        return VirtualRegister(u.virtualRegister);
200
    }
206
    }
201
    
207
    
202
    ExitValue withVirtualRegister(VirtualRegister virtualRegister)
208
    ExitTimeObjectMaterialization* objectMaterialization() const
209
    {
210
        ASSERT(isObjectMaterialization());
211
        return u.newObjectMaterializationData;
212
    }
213
214
    ExitValue withVirtualRegister(VirtualRegister virtualRegister) const
203
    {
215
    {
204
        ASSERT(isInJSStackSomehow());
216
        ASSERT(isInJSStackSomehow());
205
        ExitValue result;
217
        ExitValue result;
Lines 207-213 public: Source/JavaScriptCore/ftl/FTLExitValue.h_sec5
207
        result.u.virtualRegister = virtualRegister.offset();
219
        result.u.virtualRegister = virtualRegister.offset();
208
        return result;
220
        return result;
209
    }
221
    }
210
222
    
211
    // If it's in the JSStack somehow, this will tell you what format it's in, in a manner
223
    // 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
224
    // 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
225
    // 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_sec6
223
        case ExitValueConstant:
235
        case ExitValueConstant:
224
        case ExitValueInJSStack:
236
        case ExitValueInJSStack:
225
        case ExitValueArgumentsObjectThatWasNotCreated:
237
        case ExitValueArgumentsObjectThatWasNotCreated:
238
        case ExitValueMaterializeNewObject:
226
            return ValueFormatJSValue;
239
            return ValueFormatJSValue;
227
            
240
            
228
        case ExitValueArgument:
241
        case ExitValueArgument:
Lines 260-265 private: Source/JavaScriptCore/ftl/FTLExitValue.h_sec7
260
            uint16_t opcode;
273
            uint16_t opcode;
261
            uint16_t format;
274
            uint16_t format;
262
        } recovery;
275
        } recovery;
276
        ExitTimeObjectMaterialization* newObjectMaterializationData;
263
    } u;
277
    } u;
264
};
278
};
265
279
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -51 / +96 lines
Lines 3953-3964 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
3953
    void compileInvalidationPoint()
3953
    void compileInvalidationPoint()
3954
    {
3954
    {
3955
        if (verboseCompilationEnabled())
3955
        if (verboseCompilationEnabled())
3956
            dataLog("    Invalidation point with availability: ", availability(), "\n");
3956
            dataLog("    Invalidation point with availability: ", availabilityMap(), "\n");
3957
        
3957
        
3958
        m_ftlState.jitCode->osrExit.append(OSRExit(
3958
        m_ftlState.jitCode->osrExit.append(OSRExit(
3959
            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
3959
            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
3960
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
3960
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
3961
            availability().numberOfArguments(), availability().numberOfLocals()));
3961
            availabilityMap().m_locals.numberOfArguments(),
3962
            availabilityMap().m_locals.numberOfLocals()));
3962
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
3963
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
3963
        
3964
        
3964
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
3965
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
Lines 6344-6350 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
6344
        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
6345
        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
6345
    {
6346
    {
6346
        if (verboseCompilationEnabled()) {
6347
        if (verboseCompilationEnabled()) {
6347
            dataLog("    OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", availability(), "\n");
6348
            dataLog("    OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", availabilityMap(), "\n");
6348
            if (!m_availableRecoveries.isEmpty())
6349
            if (!m_availableRecoveries.isEmpty())
6349
                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
6350
                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
6350
        }
6351
        }
Lines 6354-6360 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
6354
        m_ftlState.jitCode->osrExit.append(OSRExit(
6355
        m_ftlState.jitCode->osrExit.append(OSRExit(
6355
            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
6356
            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
6356
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
6357
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
6357
            availability().numberOfArguments(), availability().numberOfLocals()));
6358
            availabilityMap().m_locals.numberOfArguments(),
6359
            availabilityMap().m_locals.numberOfLocals()));
6358
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
6360
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
6359
        
6361
        
6360
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
6362
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
Lines 6394-6449 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
6394
        if (!!lowValue)
6396
        if (!!lowValue)
6395
            arguments.append(lowValue.value());
6397
            arguments.append(lowValue.value());
6396
        
6398
        
6399
        AvailabilityMap availabilityMap = availabilityMap();
6400
        
6397
        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
6401
        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
6398
            int operand = exit.m_values.operandForIndex(i);
6402
            int operand = exit.m_values.operandForIndex(i);
6399
            bool isLive = m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin);
6403
            if (!m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin))
6400
            if (!isLive) {
6404
                availabilityMap.m_locals[i] = Availability();
6401
                exit.m_values[i] = ExitValue::dead();
6405
        }
6402
                continue;
6406
        
6403
            }
6407
        availabilityMap.prune();
6404
            
6408
        
6405
            Availability availability = this->availability()[i];
6409
        HashMap<Node*, ExitTimeObjectMaterialization*> map;
6406
            FlushedAt flush = availability.flushedAt();
6410
        availabilityMap.forEachAvailability(
6407
            switch (flush.format()) {
6411
            [&] (Availability availability) {
6408
            case DeadFlush:
6412
                if (!availability.shouldUseNode())
6409
            case ConflictingFlush:
6413
                    return;
6410
                if (availability.hasNode()) {
6411
                    exit.m_values[i] = exitValueForNode(arguments, availability.node());
6412
                    break;
6413
                }
6414
                
6415
                if (Options::validateFTLOSRExitLiveness())
6416
                    DFG_CRASH(m_graph, m_node, toCString("Expected r", operand, " to be available but it wasn't.").data());
6417
                
6418
                // This means that the DFG's DCE proved that the value is dead in bytecode
6419
                // even though the bytecode liveness analysis thinks it's live. This is
6420
                // acceptable since the DFG's DCE is by design more aggressive while still
6421
                // being sound.
6422
                exit.m_values[i] = ExitValue::dead();
6423
                break;
6424
6425
            case FlushedJSValue:
6426
            case FlushedCell:
6427
            case FlushedBoolean:
6428
                exit.m_values[i] = ExitValue::inJSStack(flush.virtualRegister());
6429
                break;
6430
                
6431
            case FlushedInt32:
6432
                exit.m_values[i] = ExitValue::inJSStackAsInt32(flush.virtualRegister());
6433
                break;
6434
                
6435
            case FlushedInt52:
6436
                exit.m_values[i] = ExitValue::inJSStackAsInt52(flush.virtualRegister());
6437
                break;
6438
                
6414
                
6439
            case FlushedDouble:
6415
                Node* node = availability.node();
6440
                exit.m_values[i] = ExitValue::inJSStackAsDouble(flush.virtualRegister());
6416
                if (!node->isPhantomObjectAllocation())
6441
                break;
6417
                    return;
6442
                
6418
                
6443
            case FlushedArguments:
6419
                auto result = map.add(node, nullptr);
6444
                exit.m_values[i] = ExitValue::argumentsObjectThatWasNotCreated();
6420
                if (result.isNewEntry)
6445
                break;
6421
                    result.iterator->value = exit.m_materializations.add(node->op());
6422
            });
6423
        
6424
        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
6425
            int operand = exit.m_values.operandForIndex(i);
6426
            
6427
            Availability availability = this->availabilityMap().m_locals[i];
6428
            
6429
            if (Options::validateFTLOSRExitLiveness()) {
6430
                DFG_ASSERT(
6431
                    m_graph, m_node,
6432
                    m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin)
6433
                    == availability.isDead());
6446
            }
6434
            }
6435
            
6436
            exit.m_values[i] = exitValueForAvailability(arguments, map, availability);
6437
        }
6438
        
6439
        for (auto heapPair : availabilityMap.m_heap) {
6440
            Node* node = heapPair.key.base();
6441
            ExitTimeObjectMaterialization* materialization = map.get(node);
6442
            materialization->add(
6443
                heapPair.key.baseless(),
6444
                exitValueForAvailability(arguments, map, heapPair.value));
6447
        }
6445
        }
6448
        
6446
        
6449
        if (verboseCompilationEnabled())
6447
        if (verboseCompilationEnabled())
Lines 6459-6471 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
6459
        m_out.call(m_out.stackmapIntrinsic(), arguments);
6457
        m_out.call(m_out.stackmapIntrinsic(), arguments);
6460
    }
6458
    }
6461
    
6459
    
6462
    ExitValue exitValueForNode(ExitArgumentList& arguments, Node* node)
6460
    ExitValue exitValueForAvailability(
6461
        ExitArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map,
6462
        Availability availability)
6463
    {
6464
        FlushedAt flush = availability.flushedAt();
6465
        switch (flush.format()) {
6466
        case DeadFlush:
6467
        case ConflictingFlush:
6468
            if (availability.hasNode())
6469
                return exitValueForNode(arguments, map, availability.node());
6470
            
6471
            // This means that the value is dead. It could be dead in bytecode or it could have
6472
            // been killed by our DCE, which can sometimes kill things even if they were live in
6473
            // bytecode.
6474
            return ExitValue::dead();
6475
6476
        case FlushedJSValue:
6477
        case FlushedCell:
6478
        case FlushedBoolean:
6479
            return ExitValue::inJSStack(flush.virtualRegister());
6480
                
6481
        case FlushedInt32:
6482
            return ExitValue::inJSStackAsInt32(flush.virtualRegister());
6483
                
6484
        case FlushedInt52:
6485
            return ExitValue::inJSStackAsInt52(flush.virtualRegister());
6486
                
6487
        case FlushedDouble:
6488
            return ExitValue::inJSStackAsDouble(flush.virtualRegister());
6489
                
6490
        case FlushedArguments:
6491
            return ExitValue::argumentsObjectThatWasNotCreated();
6492
        }
6493
        
6494
        DFG_CRASH(m_graph, m_node, "Invalid flush format");
6495
    }
6496
    
6497
    ExitValue exitValueForNode(
6498
        ExitArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map,
6499
        Node* node)
6463
    {
6500
    {
6464
        ASSERT(node->shouldGenerate());
6501
        ASSERT(node->shouldGenerate());
6465
        ASSERT(node->hasResult());
6502
        ASSERT(node->hasResult());
6466
6503
6467
        if (node) {
6504
        if (node) {
6468
            switch (node->op()) {
6505
            switch (node->op()) {
6506
            case Bottom:
6507
                // This might arise in object materializations. I actually doubt that it would,
6508
                // but it seems worthwhile to be conservative.
6509
                return ExitValue::dead();
6510
                
6469
            case JSConstant:
6511
            case JSConstant:
6470
            case Int52Constant:
6512
            case Int52Constant:
6471
            case DoubleConstant:
6513
            case DoubleConstant:
Lines 6474-6479 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
6474
            case PhantomArguments:
6516
            case PhantomArguments:
6475
                return ExitValue::argumentsObjectThatWasNotCreated();
6517
                return ExitValue::argumentsObjectThatWasNotCreated();
6476
                
6518
                
6519
            case PhantomNewObject:
6520
                return ExitValue::materializeNewObject(map.get(node));
6521
                
6477
            default:
6522
            default:
6478
                break;
6523
                break;
6479
            }
6524
            }
Lines 6721-6727 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
6721
        m_out.unreachable();
6766
        m_out.unreachable();
6722
    }
6767
    }
6723
    
6768
    
6724
    Operands<Availability>& availability() { return m_availabilityCalculator.m_availability; }
6769
    AvailabilityMap& availabilityMap() { return m_availabilityCalculator.m_availability; }
6725
    
6770
    
6726
    VM& vm() { return m_graph.m_vm; }
6771
    VM& vm() { return m_graph.m_vm; }
6727
    CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
6772
    CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
- Source/JavaScriptCore/ftl/FTLOSRExit.h -1 / +2 lines
Lines 1-5 Source/JavaScriptCore/ftl/FTLOSRExit.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2013 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 160-165 struct OSRExit : public DFG::OSRExitBase Source/JavaScriptCore/ftl/FTLOSRExit.h_sec2
160
    unsigned m_patchableCodeOffset;
160
    unsigned m_patchableCodeOffset;
161
    
161
    
162
    Operands<ExitValue> m_values;
162
    Operands<ExitValue> m_values;
163
    Bag<ExitTimeObjectMaterialization> m_materializations;
163
    
164
    
164
    uint32_t m_stackmapID;
165
    uint32_t m_stackmapID;
165
    
166
    
- Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp -76 / +166 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
    const HashMap<ExitTimeObjectMaterialization*, EncodedJSValue*>& materializationToPointer)
53
{
54
    switch (value.kind()) {
55
    case ExitValueDead:
56
        jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0);
57
        break;
58
            
59
    case ExitValueConstant:
60
        jit.move(MacroAssembler::TrustedImm64(JSValue::encode(value.constant())), GPRInfo::regT0);
61
        break;
62
            
63
    case ExitValueArgument:
64
        record->locations[value.exitArgument().argument()].restoreInto(
65
            jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
66
        break;
67
            
68
    case ExitValueInJSStack:
69
    case ExitValueInJSStackAsInt32:
70
    case ExitValueInJSStackAsInt52:
71
    case ExitValueInJSStackAsDouble:
72
        jit.load64(AssemblyHelpers::addressFor(value.virtualRegister()), GPRInfo::regT0);
73
        break;
74
            
75
    case ExitValueArgumentsObjectThatWasNotCreated:
76
        // We can't actually recover this yet, but we can make the stack look sane. This is
77
        // a prerequisite to running the actual arguments recovery.
78
        jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0);
79
        break;
80
            
81
    case ExitValueRecovery:
82
        record->locations[value.rightRecoveryArgument()].restoreInto(
83
            jit, jitCode->stackmaps, registerScratch, GPRInfo::regT1);
84
        record->locations[value.leftRecoveryArgument()].restoreInto(
85
            jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
86
        switch (value.recoveryOpcode()) {
87
        case AddRecovery:
88
            switch (value.recoveryFormat()) {
89
            case ValueFormatInt32:
90
                jit.add32(GPRInfo::regT1, GPRInfo::regT0);
91
                break;
92
            case ValueFormatInt52:
93
                jit.add64(GPRInfo::regT1, GPRInfo::regT0);
94
                break;
95
            default:
96
                RELEASE_ASSERT_NOT_REACHED();
97
                break;
98
            }
99
            break;
100
        case SubRecovery:
101
            switch (value.recoveryFormat()) {
102
            case ValueFormatInt32:
103
                jit.sub32(GPRInfo::regT1, GPRInfo::regT0);
104
                break;
105
            case ValueFormatInt52:
106
                jit.sub64(GPRInfo::regT1, GPRInfo::regT0);
107
                break;
108
            default:
109
                RELEASE_ASSERT_NOT_REACHED();
110
                break;
111
            }
112
            break;
113
        default:
114
            RELEASE_ASSERT_NOT_REACHED();
115
            break;
116
        }
117
        break;
118
        
119
    case ExitValueMaterializeNewObject:
120
        jit.loadPtr(materializationToPointer.get(value.objectMaterialization()), GPRInfo::regT0);
121
        break;
122
            
123
    default:
124
        RELEASE_ASSERT_NOT_REACHED();
125
        break;
126
    }
127
        
128
    reboxAccordingToFormat(
129
        value.valueFormat(), jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
130
}
131
49
static void compileStub(
132
static void compileStub(
50
    unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock)
133
    unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock)
51
{
134
{
Lines 64-76 static void compileStub( Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp_sec2
64
147
65
    CCallHelpers jit(vm, codeBlock);
148
    CCallHelpers jit(vm, codeBlock);
66
    
149
    
67
    // We need scratch space to save all registers and to build up the JSStack.
150
    // We need scratch space to save all registers, to build up the JS stack, to deal with unwind
68
    // Use a scratch buffer to transfer all values.
151
    // fixup, pointers to all of the objects we materialize, and the elements inside those objects
69
    ScratchBuffer* scratchBuffer = vm->scratchBufferForSize(sizeof(EncodedJSValue) * exit.m_values.size() + requiredScratchMemorySizeInBytes() + jitCode->unwindInfo.m_registers.size() * sizeof(uint64_t));
152
    // that we materialize.
153
    
154
    // Figure out how much space we need for those object allocations.
155
    unsigned numMaterializations = 0;
156
    unsigned maxMaterializationNumArguments = 0;
157
    for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) {
158
        numMaterializations++;
159
        
160
        maxMaterializationNumArguments = std::max(
161
            maxMaterializationNumArguments,
162
            materialization.properties().size());
163
    }
164
    
165
    ScratchBuffer* scratchBuffer = vm->scratchBufferForSize(
166
        sizeof(EncodedJSValue) * (
167
            exit.m_values.size() + numMaterializations + maxMaterializationNumArguments) +
168
        requiredScratchMemorySizeInBytes() +
169
        jitCode->unwindInfo.m_registers.size() * sizeof(uint64_t));
70
    EncodedJSValue* scratch = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
170
    EncodedJSValue* scratch = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
71
    char* registerScratch = bitwise_cast<char*>(scratch + exit.m_values.size());
171
    EncodedJSValue* materializationPointers = scratch + exit.m_values.size();
172
    EncodedJSValue* materializationArguments = materializationPointers + numMaterializations;
173
    char* registerScratch = bitwise_cast<char*>(materializationArguments + maxMaterializationNumArguments);
72
    uint64_t* unwindScratch = bitwise_cast<uint64_t*>(registerScratch + requiredScratchMemorySizeInBytes());
174
    uint64_t* unwindScratch = bitwise_cast<uint64_t*>(registerScratch + requiredScratchMemorySizeInBytes());
73
    
175
    
176
    HashMap<ExitTimeObjectMaterialization*, EncodedJSValue*> materializationToPointer;
177
    unsigned materializationCount = 0;
178
    for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) {
179
        materializationToPointer.add(
180
            materialization, materializationPointers + materializationCount++);
181
    }
182
    
74
    // Note that we come in here, the stack used to be as LLVM left it except that someone called pushToSave().
183
    // Note that we come in here, the stack used to be as LLVM left it except that someone called pushToSave().
75
    // We don't care about the value they saved. But, we do appreciate the fact that they did it, because we use
184
    // We don't care about the value they saved. But, we do appreciate the fact that they did it, because we use
76
    // that slot for saveAllRegisters().
185
    // that slot for saveAllRegisters().
Lines 120-205 static void compileStub( Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp_sec3
120
        if (!!exit.m_valueProfile)
229
        if (!!exit.m_valueProfile)
121
            jit.store64(GPRInfo::regT0, exit.m_valueProfile.getSpecFailBucket(0));
230
            jit.store64(GPRInfo::regT0, exit.m_valueProfile.getSpecFailBucket(0));
122
    }
231
    }
123
124
    // Save all state from wherever the exit data tells us it was, into the appropriate place in
125
    // the scratch buffer. This also does the reboxing.
126
    
232
    
127
    for (unsigned index = exit.m_values.size(); index--;) {
233
    // Materialize all objects. Don't materialize an object until all of the objects it needs
128
        ExitValue value = exit.m_values[index];
234
    // have been materialized.
235
    HashSet<ExitTimeObjectMaterialization*> toMaterialize;
236
    for (ExitTimeObjectMaterialization* materialization : exit.m_materializations)
237
        toMaterialize.add(materialization);
238
    
239
    while (!toMaterialize.isEmpty()) {
240
        size_t previousToMaterializeSize = toMaterialize.size();
129
        
241
        
130
        switch (value.kind()) {
242
        Vector<ExitTimeObjectMaterialization*> worklist;
131
        case ExitValueDead:
243
        worklist.appendRange(toMaterialize.begin(), toMaterialize.end());
132
            jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0);
244
        for (ExitTimeObjectMaterialization* materialization : worklist) {
133
            break;
245
            // Check if we can do anything about this right now.
134
            
246
            bool allGood = true;
135
        case ExitValueConstant:
247
            for (ExitPropertyValue value : materialization->properties()) {
136
            jit.move(MacroAssembler::TrustedImm64(JSValue::encode(value.constant())), GPRInfo::regT0);
248
                if (!value.value().isObjectMaterialization())
137
            break;
249
                    continue;
138
            
250
                if (toMaterialize.contains(value.value().objectMaterialization())) {
139
        case ExitValueArgument:
251
                    // Gotta skip this one, since one of its fields points to a materialization
140
            record->locations[value.exitArgument().argument()].restoreInto(
252
                    // that hasn't been materialized.
141
                jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
253
                    allGood = false;
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;
254
                    break;
187
                }
255
                }
188
                break;
189
            default:
190
                RELEASE_ASSERT_NOT_REACHED();
191
                break;
192
            }
256
            }
193
            break;
257
            if (!allGood)
258
                continue;
194
            
259
            
195
        default:
260
            // All systems go for materializing the object. First we recover the values of all of
196
            RELEASE_ASSERT_NOT_REACHED();
261
            // its fields and then we call a function to actually allocate the beast.
197
            break;
262
            for (unsigned propertyIndex = materialization->properties().size(); propertyIndex--;) {
263
                const ExitValue& value = materialization->properties()[propertyIndex].value();
264
                compileRecovery(
265
                    jit, value, record, jitCode->stackmaps, registerScratch,
266
                    materializationToPointer);
267
                jit.storePtr(GPRInfo::regT0, materializationArguments + propertyIndex);
268
            }
269
            
270
            // This call assumes that we don't pass arguments on the stack.
271
            jit.setupArgumentsWithExecState(materialization, materializationArguments);
272
            jit.move(CCallHelpers::TrustedImmPtr(operationMaterializeObjectInOSR), GPRInfo::nonArgGPR0);
273
            jit.call(GPRInfo::nonArgGPR0);
274
            jit.storePtr(GPRInfo::returnValueGPR, materializationToPointer.get(materialization));
275
            
276
            // Let everyone know that we're done.
277
            toMaterialize.remove(materialization);
198
        }
278
        }
199
        
279
        
200
        reboxAccordingToFormat(
280
        // We expect progress! This ensures that we crash rather than looping infinitely if there
201
            value.valueFormat(), jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
281
        // is something broken about this fixpoint. Or, this could happen if we ever violate the
202
        
282
        // "materializations form a DAG" rule.
283
        RELEASE_ASSERT(toMaterialize.size() < previousToMaterializeSize);
284
    }
285
286
    // Save all state from wherever the exit data tells us it was, into the appropriate place in
287
    // the scratch buffer. This also does the reboxing.
288
    
289
    for (unsigned index = exit.m_values.size(); index--;) {
290
        compileRecovery(
291
            jit, exit.m_values[index], record, jitCode->stackmaps, registerScratch,
292
            materializationToPointer);
203
        jit.store64(GPRInfo::regT0, scratch + index);
293
        jit.store64(GPRInfo::regT0, scratch + index);
204
    }
294
    }
205
    
295
    
- Source/JavaScriptCore/ftl/FTLOperations.cpp +82 lines
Line 0 Source/JavaScriptCore/ftl/FTLOperations.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 "FTLOperations.h"
28
29
#if ENABLE(FTL_JIT)
30
31
namespace JSC { namespace FTL {
32
33
extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
34
    ExecState* exec, FTL::ExitTimeObjectMaterialization* materialization, EncodedJSValue* values)
35
{
36
    VM& vm = exec->vm();
37
    CodeBlock* codeBlock = exec->codeBlock();
38
39
    // We cannot GC. We've got pointers in evil places.
40
    DeferGCForAWhile deferGC(vm.heap);
41
    
42
    // In the future, we may have many different kinds of materializations. For now we just
43
    // materialize NewObject.
44
    RELEASE_ASSERT(materialization->type() == PhantomNewObject);
45
    
46
    // First figure out what the structure is.
47
    Structure* structure = nullptr;
48
    for (unsigned i = materialization.properties().size(); i--;) {
49
        const ExitPropertyValue& property = materialization.properties()[i];
50
        if (property.location() != BaselessPromotedHeapLocation(StructurePLoc))
51
            continue;
52
        
53
        structure = jsCast<Structure*>(JSValue::decode(values[i]));
54
    }
55
    RELEASE_ASSERT(structure);
56
    
57
    // Let's create that object!
58
    JSFinalObject* result = JSFinalObject::create(vm, structure);
59
    
60
    // Now figure out what the heck to populate the object with. We use the "concurrently" forms
61
    // of structure methods because those happen to be lower-level and more convenient. Also they
62
    // don't change the materialization of the property table, which is convenient: we actually
63
    // want to have minimal visible effects on the system.
64
    for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
65
        for (unsigned i = materialization.properties().size(); i--;) {
66
            const ExitPropertyValue& property = materialization.properties()[i];
67
            if (property.location().kind() != NamedPropertyPLoc)
68
                continue;
69
            if (codeBlock->identifier(property.location().info()).impl() != entry.key)
70
                continue;
71
            
72
            result->putDirect(vm, entry.offset, JSValue::decode(values[i]));
73
        }
74
    }
75
    
76
    return result;
77
}
78
79
} } // namespace JSC::FTL
80
81
#endif // ENABLE(FTL_JIT)
82
- Source/JavaScriptCore/ftl/FTLOperations.h +47 lines
Line 0 Source/JavaScriptCore/ftl/FTLOperations.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 FTLOperations_h
27
#define FTLOperations_h
28
29
#if ENABLE(FTL_JIT)
30
31
#include "DFGOperations.h"
32
33
namespace JSC { namespace FTL {
34
35
extern "C" {
36
37
JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
38
    ExecState*, FTL::ExitTimeObjectMaterialization*, EncodedJSValue*) WTF_INTERNAL;
39
40
} // extern "C"
41
42
} } // namespace JSC::DFG
43
44
#endif // ENABLE(FTL_JIT)
45
46
#endif // FTLOperations_h
47
- 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