| Differences between
and this patch
- Source/JavaScriptCore/bytecode/StructureSet.h +31 lines
Lines 166-171 public: Source/JavaScriptCore/bytecode/StructureSet.h_sec1
166
        return structureList()->list()[structureList()->m_length - 1];
166
        return structureList()->list()[structureList()->m_length - 1];
167
    }
167
    }
168
    
168
    
169
    class iterator {
170
    public:
171
        iterator()
172
            : m_set(nullptr)
173
            , m_index(0)
174
        {
175
        }
176
        
177
        iterator(const StructureSet* set, size_t index)
178
            : m_set(set)
179
            , m_index(index)
180
        {
181
        }
182
        
183
        Structure* operator*() const { return m_set->at(m_index); }
184
        iterator& operator++()
185
        {
186
            m_index++;
187
            return *this;
188
        }
189
        bool operator==(const iterator& other) const { return m_index == other.m_index; }
190
        bool operator!=(const iterator& other) const { return !(*this == other); }
191
        
192
    private:
193
        const StructureSet* m_set;
194
        size_t m_index;
195
    };
196
    
197
    iterator begin() const { return iterator(this, 0); }
198
    iterator end() const { return iterator(this, size()); }
199
    
169
    bool operator==(const StructureSet& other) const;
200
    bool operator==(const StructureSet& other) const;
170
    
201
    
171
    SpeculatedType speculationFromStructures() const;
202
    SpeculatedType speculationFromStructures() const;
- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h +4 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 146-151 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec2
146
    FiltrationResult filter(AbstractValue&, SpeculatedType);
147
    FiltrationResult filter(AbstractValue&, SpeculatedType);
147
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
148
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
148
    
149
    
150
    PhiChildren* phiChildren() { return m_phiChildren.get(); }
151
    
149
private:
152
private:
150
    void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
153
    void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
151
    void clobberCapturedVars(const CodeOrigin&);
154
    void clobberCapturedVars(const CodeOrigin&);
Lines 195-200 private: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec3
195
    CodeBlock* m_codeBlock;
198
    CodeBlock* m_codeBlock;
196
    Graph& m_graph;
199
    Graph& m_graph;
197
    AbstractStateType& m_state;
200
    AbstractStateType& m_state;
201
    std::unique_ptr<PhiChildren> m_phiChildren;
198
};
202
};
199
203
200
} } // namespace JSC::DFG
204
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -1 / +69 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>
Lines 1260-1265 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
1260
        forNode(node).set(m_graph, node->structure());
1262
        forNode(node).set(m_graph, node->structure());
1261
        break;
1263
        break;
1262
        
1264
        
1265
    case PhantomNewObject:
1266
        m_state.setDidCobber(true); // Prevent constant folding.
1267
        break;
1268
        
1269
    case PutByOffsetHint:
1270
    case PutStructureHint:
1271
        break;
1272
        
1273
    case MaterializeNewObject: {
1274
        StructureSet set;
1275
        
1276
        m_phiChildren->forAllTransitiveIncomingValues(
1277
            m_graph.varArgChild(node, 0).node(),
1278
            [&] (Node* incoming) {
1279
                Structure* structure = incoming->dynamicCastConstant<Structure*>();
1280
                DFG_ASSERT(m_graph, node, structure);
1281
                set.add(structure);
1282
            });
1283
        
1284
        forNode(node).set(m_graph, set);
1285
        break;
1286
    }
1287
        
1263
    case CreateActivation:
1288
    case CreateActivation:
1264
        forNode(node).set(
1289
        forNode(node).set(
1265
            m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
1290
            m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
Lines 1459-1465 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec3
1459
        break;
1484
        break;
1460
        
1485
        
1461
    case CheckStructure: {
1486
    case CheckStructure: {
1462
        // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
1463
        AbstractValue& value = forNode(node->child1());
1487
        AbstractValue& value = forNode(node->child1());
1464
        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1488
        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1465
1489
Lines 1478-1483 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec4
1478
        break;
1502
        break;
1479
    }
1503
    }
1480
        
1504
        
1505
    case CheckStructureImmediate: {
1506
        // FIXME: This currently can only reason about one structure at a time.
1507
        // https://bugs.webkit.org/show_bug.cgi?id=136988
1508
        
1509
        AbstractValue& value = forNode(node->child1());
1510
        StructureSet& set = node->structureSet();
1511
        
1512
        if (value.value()) {
1513
            if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
1514
                if (set.contains(structure)) {
1515
                    m_state.setFoundConstants(true);
1516
                    break;
1517
                }
1518
            }
1519
            m_state.setIsValid(false);
1520
            break;
1521
        }
1522
        
1523
        if (m_phiChildren) {
1524
            bool allGood = true;
1525
            m_phiChildren->forAllTransitiveIncomingValues(
1526
                node,
1527
                [&] (Node* incoming) {
1528
                    if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
1529
                        if (set.contains(structure))
1530
                            return;
1531
                    }
1532
                    allGood = false;
1533
                });
1534
            if (allGood) {
1535
                m_state.setFoundConstants(true);
1536
                break;
1537
            }
1538
        }
1539
            
1540
        if (Structure* structure = set.onlyStructure()) {
1541
            filterByValue(node->child1(), *m_graph.freeze(structure));
1542
            break;
1543
        }
1544
        
1545
        // Aw shucks, we can't do anything!
1546
        break;
1547
    }
1548
        
1481
    case PutStructure:
1549
    case PutStructure:
1482
        if (!forNode(node->child1()).m_structure.isClear()) {
1550
        if (!forNode(node->child1()).m_structure.isClear()) {
1483
            if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
1551
            if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
- 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/DFGClobberize.h -5 / +6 lines
Lines 109-114 void clobberize(Graph& graph, Node* node Source/JavaScriptCore/dfg/DFGClobberize.h_sec1
109
    case HardPhantom:
109
    case HardPhantom:
110
    case Check:
110
    case Check:
111
    case ExtractOSREntryLocal:
111
    case ExtractOSREntryLocal:
112
    case CheckStructureImmediate:
112
        return;
113
        return;
113
        
114
        
114
    case BitAnd:
115
    case BitAnd:
Lines 273-278 void clobberize(Graph& graph, Node* node Source/JavaScriptCore/dfg/DFGClobberize.h_sec2
273
    case ProfileDidCall:
274
    case ProfileDidCall:
274
    case StoreBarrier:
275
    case StoreBarrier:
275
    case StoreBarrierWithNullCheck:
276
    case StoreBarrierWithNullCheck:
277
    case PutByOffsetHint:
278
    case PutStructureHint:
276
        write(SideState);
279
        write(SideState);
277
        return;
280
        return;
278
        
281
        
Lines 787-803 void clobberize(Graph& graph, Node* node Source/JavaScriptCore/dfg/DFGClobberize.h_sec3
787
    case NewObject:
790
    case NewObject:
788
    case NewRegexp:
791
    case NewRegexp:
789
    case NewStringObject:
792
    case NewStringObject:
790
        read(HeapObjectCount);
793
    case PhantomNewObject:
791
        write(HeapObjectCount);
794
    case MaterializeNewObject:
792
        return;
793
        
794
    case NewFunctionNoCheck:
795
    case NewFunctionNoCheck:
795
    case NewFunction:
796
    case NewFunction:
796
    case NewFunctionExpression:
797
    case NewFunctionExpression:
797
        read(HeapObjectCount);
798
        read(HeapObjectCount);
798
        write(HeapObjectCount);
799
        write(HeapObjectCount);
799
        return;
800
        return;
800
801
        
801
    case RegExpExec:
802
    case RegExpExec:
802
    case RegExpTest:
803
    case RegExpTest:
803
        read(RegExpState);
804
        read(RegExpState);
- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp +36 lines
Lines 124-129 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec1
124
                break;
124
                break;
125
            }
125
            }
126
                
126
                
127
            case CheckStructureImmediate: {
128
                AbstractValue& value = m_state.forNode(node->child1());
129
                StructureSet& set = node->structureSet();
130
                
131
                if (value.value()) {
132
                    if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
133
                        if (set.contains(structure)) {
134
                            m_interpreter.execute(indexInBlock);
135
                            node->convertToPhantom();
136
                            eliminated = true;
137
                            break;
138
                        }
139
                    }
140
                }
141
                
142
                if (PhiChildren* phiChildren = m_interpreter.phiChildren()) {
143
                    bool allGood = true;
144
                    phiChildren->forAllTransitiveIncomingValues(
145
                        node,
146
                        [&] (Node* incoming) {
147
                            if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
148
                                if (set.contains(structure))
149
                                    return;
150
                            }
151
                            allGood = false;
152
                        });
153
                    if (allGood) {
154
                        m_interpreter.execute(indexInBlock);
155
                        node->convertToPhantom();
156
                        eliminated = true;
157
                        break;
158
                    }
159
                }
160
                break;
161
            }
162
                
127
            case CheckArray:
163
            case CheckArray:
128
            case Arrayify: {
164
            case Arrayify: {
129
                if (!node->arrayMode().alreadyChecked(m_graph, node, m_state.forNode(node->child1())))
165
                if (!node->arrayMode().alreadyChecked(m_graph, node, m_state.forNode(node->child1())))
- Source/JavaScriptCore/dfg/DFGDoesGC.cpp +5 lines
Lines 199-204 bool doesGC(Graph& graph, Node* node) Source/JavaScriptCore/dfg/DFGDoesGC.cpp_sec1
199
    case BooleanToNumber:
199
    case BooleanToNumber:
200
    case CheckBadCell:
200
    case CheckBadCell:
201
    case BottomValue:
201
    case BottomValue:
202
    case PhantomNewObject:
203
    case PutByOffsetHint:
204
    case CheckStructureImmediate:
205
    case PutStructureHint:
202
        return false;
206
        return false;
203
207
204
    case CreateActivation:
208
    case CreateActivation:
Lines 225-230 bool doesGC(Graph& graph, Node* node) Source/JavaScriptCore/dfg/DFGDoesGC.cpp_sec2
225
    case GetGenericPropertyEnumerator:
229
    case GetGenericPropertyEnumerator:
226
    case GetEnumeratorPname:
230
    case GetEnumeratorPname:
227
    case ToIndexString:
231
    case ToIndexString:
232
    case MaterializeNewObject:
228
        return true;
233
        return true;
229
        
234
        
230
    case MultiPutByOffset:
235
    case MultiPutByOffset:
- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +5 lines
Lines 1013-1018 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec1
1013
        case Int52Constant:
1013
        case Int52Constant:
1014
        case Identity: // This should have been cleaned up.
1014
        case Identity: // This should have been cleaned up.
1015
        case BooleanToNumber:
1015
        case BooleanToNumber:
1016
        case PhantomNewObject:
1017
        case PutByOffsetHint:
1018
        case CheckStructureImmediate:
1019
        case PutStructureHint:
1020
        case MaterializeNewObject:
1016
            // These are just nodes that we don't currently expect to see during fixup.
1021
            // These are just nodes that we don't currently expect to see during fixup.
1017
            // If we ever wanted to insert them prior to fixup, then we just have to create
1022
            // If we ever wanted to insert them prior to fixup, then we just have to create
1018
            // fixup rules for them.
1023
            // fixup rules for them.
- 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 -2 / +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 580-586 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec3
580
     
610
     
581
    bool isCellConstant()
611
    bool isCellConstant()
582
    {
612
    {
583
        return isConstant() && constant()->value().isCell();
613
        return isConstant() && constant()->value() && constant()->value().isCell();
584
    }
614
    }
585
     
615
     
586
    JSCell* asCell()
616
    JSCell* asCell()
Lines 704-709 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec4
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_sec5
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 1155-1161 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec6
1155
    
1187
    
1156
    bool hasStorageAccessData()
1188
    bool hasStorageAccessData()
1157
    {
1189
    {
1158
        return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset;
1190
        switch (op()) {
1191
        case GetByOffset:
1192
        case PutByOffset:
1193
        case GetGetterSetterByOffset:
1194
            return true;
1195
        default:
1196
            return false;
1197
        }
1159
    }
1198
    }
1160
    
1199
    
1161
    StorageAccessData& storageAccessData()
1200
    StorageAccessData& storageAccessData()
Lines 1184-1189 struct Node { Source/JavaScriptCore/dfg/DFGNode.h_sec7
1184
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1223
        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1185
    }
1224
    }
1186
    
1225
    
1226
    bool hasObjectMaterializationData()
1227
    {
1228
        return op() == MaterializeNewObject;
1229
    }
1230
    
1231
    ObjectMaterializationData& objectMaterializationData()
1232
    {
1233
        return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo);
1234
    }
1235
    
1236
    bool isPhantomObjectAllocation()
1237
    {
1238
        switch (op()) {
1239
        case PhantomNewObject:
1240
            return true;
1241
        default:
1242
            return false;
1243
        }
1244
    }
1245
    
1187
    bool hasFunctionDeclIndex()
1246
    bool hasFunctionDeclIndex()
1188
    {
1247
    {
1189
        return op() == NewFunction
1248
        return op() == NewFunction
- Source/JavaScriptCore/dfg/DFGNodeType.h +7 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(PutByOffsetHint, NodeMustGenerate) \
234
    macro(CheckStructureImmediate, NodeMustGenerate) \
235
    macro(PutStructureHint, NodeMustGenerate) \
236
    macro(MaterializeNewObject, NodeResultJS | NodeHasVarArgs) \
237
    \
231
    /* Nodes for misc operations. */\
238
    /* Nodes for misc operations. */\
232
    macro(Breakpoint, NodeMustGenerate) \
239
    macro(Breakpoint, NodeMustGenerate) \
233
    macro(ProfileWillCall, NodeMustGenerate) \
240
    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.insertConstant(
390
                            nodeIndex, node->origin, JSValue(node->transition()->next));
391
                        node->convertToPutStructureHint(structure);
392
                    }
393
                    break;
394
                }
395
                    
396
                case NewObject: {
397
                    if (m_sinkCandidates.contains(node)) {
398
                        Node* structure = m_insertionSet.insertConstant(
399
                            nodeIndex + 1, node->origin, JSValue(node->structure()));
400
                        m_insertionSet.insertNode(
401
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
402
                            Edge(node, KnownCellUse), Edge(structure, KnownCellUse));
403
                        node->convertToPhantomNewObject();
404
                    }
405
                    break;
406
                }
407
                    
408
                case MaterializeNewObject: {
409
                    if (m_sinkCandidates.contains(node)) {
410
                        m_insertionSet.insertNode(
411
                            nodeIndex + 1, SpecNone, PutStructureHint, node->origin,
412
                            Edge(node, KnownCellUse), m_graph.varArgChild(node, 0));
413
                        for (unsigned i = 0; i < node->objectMaterializationData().m_properties.size(); ++i) {
414
                            m_insertionSet.insertNode(
415
                                nodeIndex + 1, SpecNone, PutByOffsetHint, node->origin,
416
                                Edge(node, KnownCellUse),m_graph.varArgChild(node, i + 1));
417
                        }
418
                        node->convertToPhantomNewObject();
419
                    }
420
                    break;
421
                }
422
                    
423
                default:
424
                    break;
425
                }
426
            }
427
            m_insertionSet.execute(block);
428
        }
429
    }
430
    
431
    void promoteSunkenFields()
432
    {
433
        // Henceforth when we encounter a materialization point, we will want to ask *who* it is
434
        // a materialization for. Invert the map to be able to answer such questions.
435
        m_materializationPointToEscapee.clear();
436
        for (auto pair : m_edgeToMaterializationPoint)
437
            m_materializationPointToEscapee.add(pair.value, pair.key.second);
438
        
439
        // Collect the set of heap locations that we will be operating over.
440
        HashSet<PromotedHeapLocation> locations;
441
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
442
            for (Node* node : *block) {
443
                promote(
444
                    node,
445
                    [&] (PromotedHeapLocation location, Edge) {
446
                        locations.add(location);
447
                    },
448
                    [&] (PromotedHeapLocation location) {
449
                        locations.add(location);
450
                    });
451
            }
452
        }
453
        
454
        // Figure out which locations belong to which allocations.
455
        m_locationsForAllocation.clear();
456
        for (PromotedHeapLocation location : locations) {
457
            auto result = m_locationsForAllocation.add(location.base(), Vector<PromotedHeapLocation>());
458
            ASSERT(!result.iterator->value.contains(location));
459
            result.iterator->value.append(location);
460
        }
461
        
462
        // For each sunken thingy, make sure we create Bottom values for all of its fields.
463
        // Note that this has the hilarious slight inefficiency of creating redundant hints for
464
        // things that were previously materializations. This should only impact compile times and
465
        // not code quality, and it's necessary for soundness without some data structure hackage.
466
        // For example, a MaterializeNewObject that we choose to sink may have new fields added to
467
        // it conditionally. That would necessitate Bottoms.
468
        Node* bottom = nullptr;
469
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
470
            if (block == m_graph.block(0))
471
                bottom = m_insertionSet.insertNode(0, SpecNone, BottomValue, NodeOrigin());
472
            
473
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
474
                Node* node = block->at(nodeIndex);
475
                for (PromotedHeapLocation location : locationsForAllocation.get(node)) {
476
                    m_insertionSet.insertNode(
477
                        nodeIndex + 1, location.createHint(m_graph, node->origin, bottom));
478
                }
479
            }
480
            m_insertionSet.execute(block);
481
        }
482
483
        m_ssaCalculator.reset();
484
485
        // Collect the set of "variables" that we will be sinking.
486
        m_locationToVariable.clear();
487
        m_indexToLocation.clear();
488
        for (PromotedHeapLocation location : locations) {
489
            SSACalculator::Variable* variable = m_ssaCalculator.newVariable();
490
            locationToVariable.add(location, variable);
491
            ASSERT(indexToLocation.size() == variable->index());
492
            indexToLocation.append(location);
493
        }
494
        
495
        // Create Defs from the existing hints.
496
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
497
            for (Node* node : *block) {
498
                promote(
499
                    node,
500
                    [&] (PromotedHeapLocation location, Edge value) {
501
                        SSACalculator::Variable* variable = locationToVariable.get(location);
502
                        m_ssaCalculator.newDef(variable, block, value.node());
503
                    },
504
                    doNothing);
505
            }
506
        }
507
        
508
        // OMG run the SSA calculator to create Phis!
509
        m_ssaCalculator.computePhis(
510
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
511
                PromotedHeapLocation location = indexToLocation[variable->index()];
512
                if (!block->ssa->liveAtHead.contains(location.base()))
513
                    return nullptr;
514
                
515
                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin());
516
                phiNode->mergeFlags(NodeResultJS);
517
                return phiNode;
518
            });
519
        
520
        // Place Phis in the right places, replace all uses of any load with the appropriate
521
        // value, and create the appropriate Upsilon nodes.
522
        m_graph.clearReplacements();
523
        for (BasicBlock* block : m_graph.blocksInPreOrder()) {
524
            // This mapping table is intended to be lazy. If something is omitted from the table,
525
            // it means that there haven't been any local stores to that promoted heap location.
526
            m_localMapping.clear();
527
            
528
            // Insert the Phi functions that we had previously created.
529
            for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) {
530
                PromotedHeapLocation location = m_indexToLocation[phiDef->variable()->index()];
531
                
532
                m_insertionSet.insert(
533
                    0, phiDef->value());
534
                m_insertionSet.insert(
535
                    0, location.createHint(m_graph, NodeOrigin(), phiDef->value()));
536
                m_localMapping.add(location, phiDef->value());
537
            }
538
            
539
            // Process the block and replace all uses of loads with the promoted value.
540
            for (Node* node : *block) {
541
                m_graph.performSubstitution(node);
542
                
543
                if (Node* escapee = m_materializationPointToEscapee.get(node))
544
                    populateMaterialize(block, node, escapee);
545
                
546
                promote(
547
                    node,
548
                    [&] (PromotedHeapLocation location, Edge value) {
549
                        m_localMapping.set(location, edge.node());
550
                    },
551
                    [&] (PromotedHeapLocation location) {
552
                        node->replaceWith(resolve(block, location));
553
                    });
554
            }
555
            
556
            // Gotta drop some Upsilons.
557
            size_t upsilonInsertionPoint = block->size() - 1;
558
            NodeOrigin upsilonOrigin = block->last()->origin;
559
            for (BasicBlock* successorBlock : block->successors()) {
560
                for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) {
561
                    Node* phiNode = phiDef->value();
562
                    SSACalculator::Variable* variable = phiDef->variable();
563
                    PromotedHeapLocation location = m_indexToLocation[variable->index()];
564
                    Node* incoming = resolve(block, location);
565
                    
566
                    m_insertionSet.insertNode(
567
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
568
                        OpInfo(phiNode), incoming->defaultEdge());
569
                }
570
            }
571
            
572
            m_insertionSet.execute(block);
573
        }
574
    }
575
    
576
    Node* resolve(BasicBlock* block, PromotedHeapLocation location)
577
    {
578
        if (Node* result = m_localMapping.get(location))
579
            return result;
580
        
581
        // This implies that there is no local mapping. Find a non-local mapping.
582
        Def* def = m_ssaCalculator.nonLocalReachingDef(block, m_locationToVariable.get(location));
583
        ASSERT(def);
584
        ASSERT(def->value());
585
        m_localMapping.add(locaftion, def->value());
586
        return def->value();
587
    }
588
589
    template<typename... Args>
590
    static void doNothing(Args...) { }
591
    
592
    template<typename SinkCandidateFunctor, typename EscapeFunctor>
593
    void handleNode(
594
        Node* node,
595
        const SinkCandidateFunctor& sinkCandidate,
596
        const EscapeFunctor& escape)
597
    {
598
        switch (node->op()) {
599
        case NewObject:
600
        case MaterializeNewObject:
601
            sinkCandidate();
602
            break;
603
            
604
        case CheckStructure:
605
        case GetByOffset:
606
        case MultiGetByOffset:
607
        case PutStructure:
608
        case GetGetterSetterByOffset:
609
        case MovHint:
610
            break;
611
            
612
        case PutByOffset:
613
            escape(node->child3().node());
614
            break;
615
            
616
        case MultiPutByOffset:
617
            // FIXME: In the future we should be able to handle this. It's just a matter of
618
            // building the appropriate *Hint variant of this instruction, along with a
619
            // PhantomStructureSelect node - since this transforms the Structure in a conditional
620
            // way.
621
            // https://bugs.webkit.org/show_bug.cgi?id=136924
622
            escape(node->child1().node());
623
            escape(node->child2().node());
624
            break;
625
626
        default:
627
            m_graph.doToChildren(
628
                node,
629
                [&escape] (Edge edge) {
630
                    escape(edge.node());
631
                });
632
            break;
633
        }
634
    }
635
    
636
    Node* createMaterialize(Node* escapee, const NodeOrigin whereOrigin)
637
    {
638
        switch (escapee->op()) {
639
        case NewObject:
640
        case MaterializeNewObject: {
641
            ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
642
            
643
            return m_graph.addNode(
644
                escapee->prediction(), MaterializeNewObject,
645
                NodeOrigin(
646
                    escapee->origin.semantic,
647
                    whereOrigin.forExit),
648
                OpInfo(data), OpInfo(), 0, 0);
649
        }
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() == BottomValue) {
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 +86 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
        if (node->op() != Phi) {
56
            functor(node);
57
            return;
58
        }
59
        HashSet<Node*> seen;
60
        Vector<Node*> worklist;
61
        seen.add(node);
62
        worklist.append(node);
63
        while (!worklist.isEmpty()) {
64
            Node* currentNode = worklist.takeLast();
65
            forAllIncomingValues(
66
                currentNode,
67
                [&] (Node* incomingNode) {
68
                    if (incomingNode->op() == Phi) {
69
                        if (seen.add(incomingNode))
70
                            worklist.append(incomingNode);
71
                    } else
72
                        functor(incomingNode);
73
                });
74
        }
75
    }
76
    
77
private:
78
    HashMap<Node*, List> m_children;
79
};
80
81
} } // namespace JSC::DFG
82
83
#endif // ENABLE(DFG_JIT)
84
85
#endif // DFGPhiChildren_h
86
- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp -1 / +6 lines
Lines 560-566 private: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp_sec1
560
        case DoubleConstant:
560
        case DoubleConstant:
561
        case Int52Constant:
561
        case Int52Constant:
562
        case Identity:
562
        case Identity:
563
        case BooleanToNumber: {
563
        case BooleanToNumber:
564
        case PhantomNewObject:
565
        case PutByOffsetHint:
566
        case CheckStructureImmediate:
567
        case PutStructureHint:
568
        case MaterializeNewObject: {
564
            // This node should never be visible at this stage of compilation. It is
569
            // This node should never be visible at this stage of compilation. It is
565
            // inserted by fixup(), which follows this phase.
570
            // inserted by fixup(), which follows this phase.
566
            RELEASE_ASSERT_NOT_REACHED();
571
            RELEASE_ASSERT_NOT_REACHED();
- 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/dfg/DFGSafeToExecute.h +5 lines
Lines 270-275 bool safeToExecute(AbstractStateType& st Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec1
270
    case GetGenericPropertyEnumerator:
270
    case GetGenericPropertyEnumerator:
271
    case GetEnumeratorPname:
271
    case GetEnumeratorPname:
272
    case ToIndexString:
272
    case ToIndexString:
273
    case PhantomNewObject:
274
    case PutByOffsetHint:
275
    case CheckStructureImmediate:
276
    case PutStructureHint:
277
    case MaterializeNewObject:
273
        return true;
278
        return true;
274
279
275
    case NativeCall:
280
    case NativeCall:
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +5 lines
Lines 4912-4917 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp_sec1
4912
    case NativeConstruct:
4912
    case NativeConstruct:
4913
    case CheckBadCell:
4913
    case CheckBadCell:
4914
    case BottomValue:
4914
    case BottomValue:
4915
    case PhantomNewObject:
4916
    case PutByOffsetHint:
4917
    case CheckStructureImmediate:
4918
    case PutStructureHint:
4919
    case MaterializeNewObject:
4915
        RELEASE_ASSERT_NOT_REACHED();
4920
        RELEASE_ASSERT_NOT_REACHED();
4916
        break;
4921
        break;
4917
    }
4922
    }
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +5 lines
Lines 4982-4987 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp_sec1
4982
    case FiatInt52:
4982
    case FiatInt52:
4983
    case CheckBadCell:
4983
    case CheckBadCell:
4984
    case BottomValue:
4984
    case BottomValue:
4985
    case PhantomNewObject:
4986
    case PutByOffsetHint:
4987
    case CheckStructureImmediate:
4988
    case PutStructureHint:
4989
    case MaterializeNewObject:
4985
        DFG_CRASH(m_jit.graph(), node, "Unexpected node");
4990
        DFG_CRASH(m_jit.graph(), node, "Unexpected node");
4986
        break;
4991
        break;
4987
    }
4992
    }
- Source/JavaScriptCore/ftl/FTLCapabilities.cpp +5 lines
Lines 168-173 inline CapabilityLevel canCompile(Node* Source/JavaScriptCore/ftl/FTLCapabilities.cpp_sec1
168
    case GetEnumeratorPname:
168
    case GetEnumeratorPname:
169
    case ToIndexString:
169
    case ToIndexString:
170
    case BottomValue:
170
    case BottomValue:
171
    case PhantomNewObject:
172
    case PutByOffsetHint:
173
    case CheckStructureImmediate:
174
    case PutStructureHint:
175
    case MaterializeNewObject:
171
        // These are OK.
176
        // These are OK.
172
        break;
177
        break;
173
    case ProfiledCall:
178
    case ProfiledCall:
- 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 -152 / +295 lines
Lines 725-730 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
725
        case ToIndexString:
725
        case ToIndexString:
726
            compileToIndexString();
726
            compileToIndexString();
727
            break;
727
            break;
728
        case CheckStructureImmediate:
729
            compileCheckStructureImmediate();
730
            break;
731
        case MaterializeNewObject:
732
            compileMaterializeNewObject();
733
            break;
728
734
729
        case PhantomLocal:
735
        case PhantomLocal:
730
        case SetArgument:
736
        case SetArgument:
Lines 735-740 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
735
        case AllocationProfileWatchpoint:
741
        case AllocationProfileWatchpoint:
736
        case MovHint:
742
        case MovHint:
737
        case ZombieHint:
743
        case ZombieHint:
744
        case PhantomNewObject:
745
        case PutByOffsetHint:
746
        case PutStructureHint:
738
            break;
747
            break;
739
        default:
748
        default:
740
            DFG_CRASH(m_graph, m_node, "Unrecognized node in FTL backend");
749
            DFG_CRASH(m_graph, m_node, "Unrecognized node in FTL backend");
Lines 1704-1733 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
1704
        
1713
        
1705
        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
1714
        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
1706
        
1715
        
1707
        if (m_node->structureSet().size() == 1) {
1716
        checkStructure(structureID, jsValueValue(cell), exitKind, node->structureSet());
1708
            speculate(
1709
                exitKind, jsValueValue(cell), 0,
1710
                m_out.notEqual(structureID, weakStructure(m_node->structureSet()[0])));
1711
            return;
1712
        }
1713
        
1714
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure continuation"));
1715
        
1716
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
1717
        for (unsigned i = 0; i < m_node->structureSet().size() - 1; ++i) {
1718
            LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("CheckStructure nextStructure"));
1719
            m_out.branch(
1720
                m_out.equal(structureID, weakStructure(m_node->structureSet()[i])),
1721
                unsure(continuation), unsure(nextStructure));
1722
            m_out.appendTo(nextStructure);
1723
        }
1724
        
1725
        speculate(
1726
            exitKind, jsValueValue(cell), 0,
1727
            m_out.notEqual(structureID, weakStructure(m_node->structureSet().last())));
1728
        
1729
        m_out.jump(continuation);
1730
        m_out.appendTo(continuation, lastNext);
1731
    }
1717
    }
1732
    
1718
    
1733
    void compileCheckCell()
1719
    void compileCheckCell()
Lines 2649-2676 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
2649
    
2635
    
2650
    void compileNewObject()
2636
    void compileNewObject()
2651
    {
2637
    {
2652
        Structure* structure = m_node->structure();
2638
        setJSValue(allocateObject(m_node->structure()));
2653
        size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
2654
        MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
2655
        
2656
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("NewObject slow path"));
2657
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewObject continuation"));
2658
        
2659
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
2660
        
2661
        ValueFromBlock fastResult = m_out.anchor(allocateObject(
2662
            m_out.constIntPtr(allocator), structure, m_out.intPtrZero, slowPath));
2663
        
2664
        m_out.jump(continuation);
2665
        
2666
        m_out.appendTo(slowPath, continuation);
2667
        
2668
        ValueFromBlock slowResult = m_out.anchor(vmCall(
2669
            m_out.operation(operationNewObject), m_callFrame, m_out.constIntPtr(structure)));
2670
        m_out.jump(continuation);
2671
        
2672
        m_out.appendTo(continuation, lastNext);
2673
        setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
2674
    }
2639
    }
2675
    
2640
    
2676
    void compileNewArray()
2641
    void compileNewArray()
Lines 3370-3376 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
3370
        LBasicBlock lastNext = m_out.m_nextBlock;
3335
        LBasicBlock lastNext = m_out.m_nextBlock;
3371
        
3336
        
3372
        for (unsigned i = data.variants.size(); i--;) {
3337
        for (unsigned i = data.variants.size(); i--;) {
3373
            m_out.appendTo(blocks[i], i  + 1 < data.variants.size() ? blocks[i + 1] : exit);
3338
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
3374
            
3339
            
3375
            PutByIdVariant variant = data.variants[i];
3340
            PutByIdVariant variant = data.variants[i];
3376
            
3341
            
Lines 3953-3964 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
3953
    void compileInvalidationPoint()
3918
    void compileInvalidationPoint()
3954
    {
3919
    {
3955
        if (verboseCompilationEnabled())
3920
        if (verboseCompilationEnabled())
3956
            dataLog("    Invalidation point with availability: ", availability(), "\n");
3921
            dataLog("    Invalidation point with availability: ", availabilityMap(), "\n");
3957
        
3922
        
3958
        m_ftlState.jitCode->osrExit.append(OSRExit(
3923
        m_ftlState.jitCode->osrExit.append(OSRExit(
3959
            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
3924
            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
3960
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
3925
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
3961
            availability().numberOfArguments(), availability().numberOfLocals()));
3926
            availabilityMap().m_locals.numberOfArguments(),
3927
            availabilityMap().m_locals.numberOfLocals()));
3962
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
3928
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
3963
        
3929
        
3964
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
3930
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
Lines 4360-4365 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
4360
        LValue index = lowInt32(m_node->child1());
4326
        LValue index = lowInt32(m_node->child1());
4361
        setJSValue(vmCall(m_out.operation(operationToIndexString), m_callFrame, index));
4327
        setJSValue(vmCall(m_out.operation(operationToIndexString), m_callFrame, index));
4362
    }
4328
    }
4329
    
4330
    void compileCheckStructureImmediate()
4331
    {
4332
        LValue structureID = lowCell(m_nde->child1());
4333
        checkStructure(structureID, noValue(), BadCache, node->structureSet());
4334
    }
4335
    
4336
    void compileMaterializeNewObject()
4337
    {
4338
        ObjectMaterializationData& data = m_node->objectMaterializationData();
4339
        
4340
        StructureSet set;
4341
        m_interpreter.phiChildren()->forAllTransitiveIncomingValues(
4342
            m_node,
4343
            [&] (Node* incoming) {
4344
                Structure* structure = incoming->dynamicCastConstant<Structure*>();
4345
                DFG_ASSERT(m_graph, m_node, structure);
4346
                set.add(structure);
4347
            });
4348
        
4349
        Vector<LBasicBlock, 1> blocks(set.size());
4350
        for (unsigned i = set.size(); i--;)
4351
            blocks[i] = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject case ", i));
4352
        LBasicBlock dummyDefault = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject default case"));
4353
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject continuation"));
4354
        
4355
        Vector<SwitchCase, 1> cases(set.size());
4356
        for (unsigned i = set.size(); i--;)
4357
            cases[i] = SwitchCase(weakStructure(set[i]), blocks[i], Weight(1));
4358
        m_out.switchInstruction(
4359
            lowCell(m_graph.varArgChild(m_node, 0)), cases, dummyDefault, Weight(0));
4360
        
4361
        LBasicBlock outerLastNext = m_out.nextBlock;
4362
        
4363
        for (unsigned i = set.size(); i--;) {
4364
            m_out.appendTo(blocks[i], i + 1 < set.size() ? blocks[i + 1] : dummyDefault);
4365
            
4366
            Structure* structure = set[i];
4367
            
4368
            // Find a primordial structure. This is goofy. We don't actually care to find *the*
4369
            // primordial structure for *this* structure - only one that matches the important
4370
            // bits, like the inline size, the structure ID blob stuff, and the prototype.
4371
            Structure* primordialStructure = nullptr;
4372
            for (Structure* candidatePrimordialStructure : data.m_primordialStructures) {
4373
                if (candidatePrimordialStructure->canIseForAllocatonsOf(structure)) {
4374
                    primordialStructure = candidatePrimordialStructure;
4375
                    break;
4376
                }
4377
            }
4378
            DFG_ASSERT(m_graph, m_node, primordialStructure);
4379
            
4380
            LValue object;
4381
            LValue butterfly;
4382
            
4383
            if (structure->outOfLineCapacity()) {
4384
                size_t allocationSize = JSFinalObject::allocationSize(primordialStructure->inlineCapacity());
4385
                MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
4386
                
4387
                LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject complex object allocation slow path"));
4388
                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject complex object allocation continuation"));
4389
                
4390
                LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4391
                
4392
                ValueFromBlock fastResult = m_out.anchor(allocateObject(
4393
                    m_out.constIntPtr(allocator), primordialStructure, m_out.intPtrZero, slowPath));
4394
                
4395
                
4396
                
4397
                m_out.jump(continuation);
4398
                
4399
                m_out.appendTo(
4400
            } else {
4401
                // In the easy case where we can do a one-shot allocation, we simply allocate the
4402
                // object to directly have the desired structure.
4403
                object = allocateObject(structure);
4404
                butterfly = nullptr; // Don't have one, don't need one.
4405
            }
4406
        }
4407
    }
4363
4408
4364
#if ENABLE(FTL_NATIVE_CALL_INLINING)
4409
#if ENABLE(FTL_NATIVE_CALL_INLINING)
4365
    LValue getFunctionBySymbol(const CString symbol)
4410
    LValue getFunctionBySymbol(const CString symbol)
Lines 4525-4530 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec8
4525
        return m_out.booleanFalse;
4570
        return m_out.booleanFalse;
4526
    }
4571
    }
4527
    
4572
    
4573
    void checkStructure(
4574
        LValue structureID, const FormattedValue& formattedValue, ExitKind exitKind,
4575
        const StructureSet& set)
4576
    {
4577
        if (set.size() == 1) {
4578
            speculate(
4579
                exitKind, formattedValue, 0,
4580
                m_out.notEqual(structureID, weakStructure(set[0])));
4581
            return;
4582
        }
4583
        
4584
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkStructure continuation"));
4585
        
4586
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
4587
        for (unsigned i = 0; i < set.size() - 1; ++i) {
4588
            LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("checkStructure nextStructure"));
4589
            m_out.branch(
4590
                m_out.equal(structureID, weakStructure(set[i])),
4591
                unsure(continuation), unsure(nextStructure));
4592
            m_out.appendTo(nextStructure);
4593
        }
4594
        
4595
        speculate(
4596
            exitKind, formattedValue, 0,
4597
            m_out.notEqual(structureID, weakStructure(set.last())));
4598
        
4599
        m_out.jump(continuation);
4600
        m_out.appendTo(continuation, lastNext);
4601
    }
4602
    
4528
    LValue numberOrNotCellToInt32(Edge edge, LValue value)
4603
    LValue numberOrNotCellToInt32(Edge edge, LValue value)
4529
    {
4604
    {
4530
        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 int case"));
4605
        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 int case"));
Lines 4624-4707 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec9
4624
                m_callFrame, object);
4699
                m_callFrame, object);
4625
        }
4700
        }
4626
        
4701
        
4627
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage slow path"));
4702
        LValue result = allocatePropertyStorageWithSizeImpl(initialOutOfLineCapacity);
4628
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage continuation"));
4629
        
4630
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4631
        
4632
        LValue endOfStorage = allocateBasicStorageAndGetEnd(
4633
            m_out.constIntPtr(initialOutOfLineCapacity * sizeof(JSValue)), slowPath);
4634
        
4635
        ValueFromBlock fastButterfly = m_out.anchor(
4636
            m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
4637
        
4638
        m_out.jump(continuation);
4639
        
4640
        m_out.appendTo(slowPath, continuation);
4641
        
4642
        ValueFromBlock slowButterfly = m_out.anchor(vmCall(
4643
            m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), m_callFrame));
4644
        
4645
        m_out.jump(continuation);
4646
        
4647
        m_out.appendTo(continuation, lastNext);
4648
        
4649
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
4650
        m_out.storePtr(result, object, m_heaps.JSObject_butterfly);
4703
        m_out.storePtr(result, object, m_heaps.JSObject_butterfly);
4651
        
4652
        return result;
4704
        return result;
4653
    }
4705
    }
4654
    
4706
    
4655
    LValue reallocatePropertyStorage(
4707
    LValue reallocatePropertyStorage(
4656
        LValue object, LValue oldStorage, Structure* previous, Structure* next)
4708
        LValue object, LValue oldStorage, Structure* previous, Structure* next)
4657
    {
4709
    {
4658
        size_t oldSize = previous->outOfLineCapacity() * sizeof(JSValue);
4710
        size_t oldSize = previous->outOfLineCapacity();
4659
        size_t newSize = oldSize * outOfLineGrowthFactor; 
4711
        size_t newSize = oldSize * outOfLineGrowthFactor; 
4660
4712
4661
        ASSERT_UNUSED(next, newSize == next->outOfLineCapacity() * sizeof(JSValue));
4713
        ASSERT_UNUSED(next, newSize == next->outOfLineCapacity());
4662
        
4714
        
4663
        if (previous->couldHaveIndexingHeader()) {
4715
        if (previous->couldHaveIndexingHeader()) {
4664
            LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));                    
4716
            LValue newAllocSize = m_out.constIntPtr(newSize);                    
4665
            return vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize);
4717
            return vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize);
4666
        }
4718
        }
4667
        
4719
        
4668
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage slow path"));
4720
        LValue result = allocatePropertyStorageWithSizeImpl(newSize);
4669
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage continuation"));
4721
4722
        ptrdiff_t headerSize = -sizeof(IndexingHeader) - sizeof(void*);
4723
        ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize * sizeof(JSValue));
4724
4725
        for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
4726
            LValue loaded = 
4727
                m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
4728
            m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
4729
        }
4730
        
4731
        m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly));
4732
        
4733
        return result;
4734
    }
4735
    
4736
    LValue allocatePropertyStorageWithSizeImpl(size_t sizeInValues)
4737
    {
4738
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorageWithSizeImpl slow path"));
4739
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorageWithSizeImpl continuation"));
4740
        
4670
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4741
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4671
        
4742
        
4672
        LValue endOfStorage = 
4743
        LValue endOfStorage = allocateBasicStorageAndGetEnd(
4673
            allocateBasicStorageAndGetEnd(m_out.constIntPtr(newSize), slowPath);
4744
            m_out.constIntPtr(sizeInValues * sizeof(JSValue)), slowPath);
4674
        
4745
        
4675
        ValueFromBlock fastButterfly = m_out.anchor(m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
4746
        ValueFromBlock fastButterfly = m_out.anchor(
4747
            m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
4676
        
4748
        
4677
        m_out.jump(continuation);
4749
        m_out.jump(continuation);
4678
        
4750
        
4679
        m_out.appendTo(slowPath, continuation);
4751
        m_out.appendTo(slowPath, continuation);
4680
        
4752
        
4681
        LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));       
4753
        LValue slowButterflyValue;
4682
        
4754
        if (sizeInValues == initialOutOfLineCapacity) {
4683
        LValue storageLocation = vmCall(m_out.operation(operationAllocatePropertyStorage), m_callFrame, newAllocSize);
4755
            slowButterflyValue = vmCall(
4684
        
4756
                m_out.operation(operationAllocatePropertyStorageWithInitialCapacity),
4685
        ValueFromBlock slowButterfly = m_out.anchor(storageLocation);
4757
                m_callFrame);
4758
        } else {
4759
            slowButterflyValue = vmCall(
4760
                m_out.operation(operationAllocatePropertyStorage),
4761
                m_callFrame, m_out.constIntPtr(sizeInValues));
4762
        }
4763
        ValueFromBlock slowButterfly = m_out.anchor(slowButterflyValue);
4686
        
4764
        
4687
        m_out.jump(continuation);
4765
        m_out.jump(continuation);
4688
        
4766
        
4689
        m_out.appendTo(continuation, lastNext);
4767
        m_out.appendTo(continuation, lastNext);
4690
        
4768
        
4691
        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
4769
        return m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
4692
4693
        ptrdiff_t headerSize = -sizeof(JSValue) - sizeof(void *);
4694
        ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize);
4695
4696
        for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
4697
            LValue loaded = 
4698
                m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
4699
            m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
4700
        }
4701
        
4702
        m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly));
4703
        
4704
        return result;
4705
    }
4770
    }
4706
    
4771
    
4707
    LValue getById(LValue base)
4772
    LValue getById(LValue base)
Lines 4841-4847 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec10
4841
        setBoolean(m_out.phi(m_out.boolean, fastResult, slowResult));
4906
        setBoolean(m_out.phi(m_out.boolean, fastResult, slowResult));
4842
    }
4907
    }
4843
4908
4844
    LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath)
4909
    LValue allocateCell(LValue allocator, LBasicBlock slowPath)
4845
    {
4910
    {
4846
        LBasicBlock success = FTL_NEW_BLOCK(m_out, ("object allocation success"));
4911
        LBasicBlock success = FTL_NEW_BLOCK(m_out, ("object allocation success"));
4847
        
4912
        
Lines 4856-4867 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec11
4856
            m_out.loadPtr(result, m_heaps.JSCell_freeListNext),
4921
            m_out.loadPtr(result, m_heaps.JSCell_freeListNext),
4857
            allocator, m_heaps.MarkedAllocator_freeListHead);
4922
            allocator, m_heaps.MarkedAllocator_freeListHead);
4858
        
4923
        
4924
        return result;
4925
    }
4926
    
4927
    void storeStructure(LValue object, Structure* structure)
4928
    {
4859
        m_out.store32(m_out.constInt32(structure->id()), result, m_heaps.JSCell_structureID);
4929
        m_out.store32(m_out.constInt32(structure->id()), result, m_heaps.JSCell_structureID);
4860
        
4861
        m_out.store32(
4930
        m_out.store32(
4862
            m_out.constInt32(structure->objectInitializationBlob()),
4931
            m_out.constInt32(structure->objectInitializationBlob()),
4863
            result, m_heaps.JSCell_usefulBytes);
4932
            result, m_heaps.JSCell_usefulBytes);
4864
        
4933
    }
4934
4935
    LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath)
4936
    {
4937
        LValue result = allocateCell(allocator, slowPath);
4938
        storeStructure(result, structure);
4865
        return result;
4939
        return result;
4866
    }
4940
    }
4867
4941
Lines 4908-4913 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec12
4908
            m_out.loadPtr(m_out.absolute(&allocator.m_currentPayloadEnd)), newRemaining);
4982
            m_out.loadPtr(m_out.absolute(&allocator.m_currentPayloadEnd)), newRemaining);
4909
    }
4983
    }
4910
    
4984
    
4985
    LValue allocateObject(Structure* structure)
4986
    {
4987
        size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
4988
        MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
4989
        
4990
        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocateObject slow path"));
4991
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocateObject continuation"));
4992
        
4993
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4994
        
4995
        ValueFromBlock fastResult = m_out.anchor(allocateObject(
4996
            m_out.constIntPtr(allocator), structure, m_out.intPtrZero, slowPath));
4997
        
4998
        m_out.jump(continuation);
4999
        
5000
        m_out.appendTo(slowPath, continuation);
5001
        
5002
        ValueFromBlock slowResult = m_out.anchor(vmCall(
5003
            m_out.operation(operationNewObject), m_callFrame, m_out.constIntPtr(structure)));
5004
        m_out.jump(continuation);
5005
        
5006
        m_out.appendTo(continuation, lastNext);
5007
        return m_out.phi(m_out.intPtr, fastResult, slowResult);
5008
    }
5009
    
4911
    struct ArrayValues {
5010
    struct ArrayValues {
4912
        ArrayValues()
5011
        ArrayValues()
4913
            : array(0)
5012
            : array(0)
Lines 6344-6350 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec13
6344
        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
6443
        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
6345
    {
6444
    {
6346
        if (verboseCompilationEnabled()) {
6445
        if (verboseCompilationEnabled()) {
6347
            dataLog("    OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", availability(), "\n");
6446
            dataLog("    OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", availabilityMap(), "\n");
6348
            if (!m_availableRecoveries.isEmpty())
6447
            if (!m_availableRecoveries.isEmpty())
6349
                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
6448
                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
6350
        }
6449
        }
Lines 6354-6360 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec14
6354
        m_ftlState.jitCode->osrExit.append(OSRExit(
6453
        m_ftlState.jitCode->osrExit.append(OSRExit(
6355
            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
6454
            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
6356
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
6455
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
6357
            availability().numberOfArguments(), availability().numberOfLocals()));
6456
            availabilityMap().m_locals.numberOfArguments(),
6457
            availabilityMap().m_locals.numberOfLocals()));
6358
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
6458
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
6359
        
6459
        
6360
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
6460
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
Lines 6394-6449 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec15
6394
        if (!!lowValue)
6494
        if (!!lowValue)
6395
            arguments.append(lowValue.value());
6495
            arguments.append(lowValue.value());
6396
        
6496
        
6497
        AvailabilityMap availabilityMap = availabilityMap();
6498
        
6397
        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
6499
        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
6398
            int operand = exit.m_values.operandForIndex(i);
6500
            int operand = exit.m_values.operandForIndex(i);
6399
            bool isLive = m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin);
6501
            if (!m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin))
6400
            if (!isLive) {
6502
                availabilityMap.m_locals[i] = Availability();
6401
                exit.m_values[i] = ExitValue::dead();
6503
        }
6402
                continue;
6504
        
6403
            }
6505
        availabilityMap.prune();
6404
            
6506
        
6405
            Availability availability = this->availability()[i];
6507
        HashMap<Node*, ExitTimeObjectMaterialization*> map;
6406
            FlushedAt flush = availability.flushedAt();
6508
        availabilityMap.forEachAvailability(
6407
            switch (flush.format()) {
6509
            [&] (Availability availability) {
6408
            case DeadFlush:
6510
                if (!availability.shouldUseNode())
6409
            case ConflictingFlush:
6511
                    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
                
6512
                
6439
            case FlushedDouble:
6513
                Node* node = availability.node();
6440
                exit.m_values[i] = ExitValue::inJSStackAsDouble(flush.virtualRegister());
6514
                if (!node->isPhantomObjectAllocation())
6441
                break;
6515
                    return;
6442
                
6516
                
6443
            case FlushedArguments:
6517
                auto result = map.add(node, nullptr);
6444
                exit.m_values[i] = ExitValue::argumentsObjectThatWasNotCreated();
6518
                if (result.isNewEntry)
6445
                break;
6519
                    result.iterator->value = exit.m_materializations.add(node->op());
6520
            });
6521
        
6522
        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
6523
            int operand = exit.m_values.operandForIndex(i);
6524
            
6525
            Availability availability = this->availabilityMap().m_locals[i];
6526
            
6527
            if (Options::validateFTLOSRExitLiveness()) {
6528
                DFG_ASSERT(
6529
                    m_graph, m_node,
6530
                    m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin)
6531
                    == availability.isDead());
6446
            }
6532
            }
6533
            
6534
            exit.m_values[i] = exitValueForAvailability(arguments, map, availability);
6535
        }
6536
        
6537
        for (auto heapPair : availabilityMap.m_heap) {
6538
            Node* node = heapPair.key.base();
6539
            ExitTimeObjectMaterialization* materialization = map.get(node);
6540
            materialization->add(
6541
                heapPair.key.baseless(),
6542
                exitValueForAvailability(arguments, map, heapPair.value));
6447
        }
6543
        }
6448
        
6544
        
6449
        if (verboseCompilationEnabled())
6545
        if (verboseCompilationEnabled())
Lines 6459-6471 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec16
6459
        m_out.call(m_out.stackmapIntrinsic(), arguments);
6555
        m_out.call(m_out.stackmapIntrinsic(), arguments);
6460
    }
6556
    }
6461
    
6557
    
6462
    ExitValue exitValueForNode(ExitArgumentList& arguments, Node* node)
6558
    ExitValue exitValueForAvailability(
6559
        ExitArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map,
6560
        Availability availability)
6561
    {
6562
        FlushedAt flush = availability.flushedAt();
6563
        switch (flush.format()) {
6564
        case DeadFlush:
6565
        case ConflictingFlush:
6566
            if (availability.hasNode())
6567
                return exitValueForNode(arguments, map, availability.node());
6568
            
6569
            // This means that the value is dead. It could be dead in bytecode or it could have
6570
            // been killed by our DCE, which can sometimes kill things even if they were live in
6571
            // bytecode.
6572
            return ExitValue::dead();
6573
6574
        case FlushedJSValue:
6575
        case FlushedCell:
6576
        case FlushedBoolean:
6577
            return ExitValue::inJSStack(flush.virtualRegister());
6578
                
6579
        case FlushedInt32:
6580
            return ExitValue::inJSStackAsInt32(flush.virtualRegister());
6581
                
6582
        case FlushedInt52:
6583
            return ExitValue::inJSStackAsInt52(flush.virtualRegister());
6584
                
6585
        case FlushedDouble:
6586
            return ExitValue::inJSStackAsDouble(flush.virtualRegister());
6587
                
6588
        case FlushedArguments:
6589
            return ExitValue::argumentsObjectThatWasNotCreated();
6590
        }
6591
        
6592
        DFG_CRASH(m_graph, m_node, "Invalid flush format");
6593
    }
6594
    
6595
    ExitValue exitValueForNode(
6596
        ExitArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map,
6597
        Node* node)
6463
    {
6598
    {
6464
        ASSERT(node->shouldGenerate());
6599
        ASSERT(node->shouldGenerate());
6465
        ASSERT(node->hasResult());
6600
        ASSERT(node->hasResult());
6466
6601
6467
        if (node) {
6602
        if (node) {
6468
            switch (node->op()) {
6603
            switch (node->op()) {
6604
            case BottomValue:
6605
                // This might arise in object materializations. I actually doubt that it would,
6606
                // but it seems worthwhile to be conservative.
6607
                return ExitValue::dead();
6608
                
6469
            case JSConstant:
6609
            case JSConstant:
6470
            case Int52Constant:
6610
            case Int52Constant:
6471
            case DoubleConstant:
6611
            case DoubleConstant:
Lines 6474-6479 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec17
6474
            case PhantomArguments:
6614
            case PhantomArguments:
6475
                return ExitValue::argumentsObjectThatWasNotCreated();
6615
                return ExitValue::argumentsObjectThatWasNotCreated();
6476
                
6616
                
6617
            case PhantomNewObject:
6618
                return ExitValue::materializeNewObject(map.get(node));
6619
                
6477
            default:
6620
            default:
6478
                break;
6621
                break;
6479
            }
6622
            }
Lines 6721-6727 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec18
6721
        m_out.unreachable();
6864
        m_out.unreachable();
6722
    }
6865
    }
6723
    
6866
    
6724
    Operands<Availability>& availability() { return m_availabilityCalculator.m_availability; }
6867
    AvailabilityMap& availabilityMap() { return m_availabilityCalculator.m_availability; }
6725
    
6868
    
6726
    VM& vm() { return m_graph.m_vm; }
6869
    VM& vm() { return m_graph.m_vm; }
6727
    CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
6870
    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 +94 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 operationNewObjectWithButterfly(ExecState*, Structure* structure)
34
{
35
    VM& vm = &exec->vm();
36
    NativeCallFrameTracer tracer(&vm, exec);
37
    
38
    Butterfly* buttefly = Butterfly::create(
39
        vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
40
    
41
    return JSFinalObject::create(exec, structure, butterfly);
42
}
43
44
extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
45
    ExecState* exec, FTL::ExitTimeObjectMaterialization* materialization, EncodedJSValue* values)
46
{
47
    VM& vm = exec->vm();
48
    CodeBlock* codeBlock = exec->codeBlock();
49
50
    // We cannot GC. We've got pointers in evil places.
51
    DeferGCForAWhile deferGC(vm.heap);
52
    
53
    // In the future, we may have many different kinds of materializations. For now we just
54
    // materialize NewObject.
55
    RELEASE_ASSERT(materialization->type() == PhantomNewObject);
56
    
57
    // First figure out what the structure is.
58
    Structure* structure = nullptr;
59
    for (unsigned i = materialization.properties().size(); i--;) {
60
        const ExitPropertyValue& property = materialization.properties()[i];
61
        if (property.location() != BaselessPromotedHeapLocation(StructurePLoc))
62
            continue;
63
        
64
        structure = jsCast<Structure*>(JSValue::decode(values[i]));
65
    }
66
    RELEASE_ASSERT(structure);
67
    
68
    // Let's create that object!
69
    JSFinalObject* result = JSFinalObject::create(vm, structure);
70
    
71
    // Now figure out what the heck to populate the object with. Use getPropertiesConcurrently()
72
    // because that happens to be lower-level and more convenient. It doesn't change the
73
    // materialization of the property table. We want to have minimal visible effects on the
74
    // system. Also, don't mind that this is O(n^2). It doesn't matter. We only get here from OSR
75
    // exit.
76
    for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
77
        for (unsigned i = materialization.properties().size(); i--;) {
78
            const ExitPropertyValue& property = materialization.properties()[i];
79
            if (property.location().kind() != NamedPropertyPLoc)
80
                continue;
81
            if (codeBlock->identifier(property.location().info()).impl() != entry.key)
82
                continue;
83
            
84
            result->putDirect(vm, entry.offset, JSValue::decode(values[i]));
85
        }
86
    }
87
    
88
    return result;
89
}
90
91
} } // namespace JSC::FTL
92
93
#endif // ENABLE(FTL_JIT)
94
- Source/JavaScriptCore/ftl/FTLOperations.h +49 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 operationNewObjectWithButterfly(ExecState*, Structure* primordialStructure, Structure* actualStructure) WTF_INTERNAL;
38
39
JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
40
    ExecState*, FTL::ExitTimeObjectMaterialization*, EncodedJSValue*) WTF_INTERNAL;
41
42
} // extern "C"
43
44
} } // namespace JSC::DFG
45
46
#endif // ENABLE(FTL_JIT)
47
48
#endif // FTLOperations_h
49
- Source/JavaScriptCore/runtime/JSObject.h -5 / +6 lines
Lines 1052-1058 public: Source/JavaScriptCore/runtime/JSObject.h_sec1
1052
        return (maxSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>);
1052
        return (maxSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>);
1053
    }
1053
    }
1054
1054
1055
    static JSFinalObject* create(ExecState*, Structure*);
1055
    static JSFinalObject* create(ExecState*, Structure*, Butterfly* = nullptr);
1056
    static JSFinalObject* create(VM&, Structure*);
1056
    static JSFinalObject* create(VM&, Structure*);
1057
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, unsigned inlineCapacity)
1057
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, unsigned inlineCapacity)
1058
    {
1058
    {
Lines 1076-1090 protected: Source/JavaScriptCore/runtime/JSObject.h_sec2
1076
private:
1076
private:
1077
    friend class LLIntOffsetsExtractor;
1077
    friend class LLIntOffsetsExtractor;
1078
1078
1079
    explicit JSFinalObject(VM& vm, Structure* structure)
1079
    explicit JSFinalObject(VM& vm, Structure* structure, Butterfly* butterfly = nullptr)
1080
        : JSObject(vm, structure)
1080
        : JSObject(vm, structure, butterfly)
1081
    {
1081
    {
1082
    }
1082
    }
1083
1083
1084
    static const unsigned StructureFlags = JSObject::StructureFlags;
1084
    static const unsigned StructureFlags = JSObject::StructureFlags;
1085
};
1085
};
1086
1086
1087
inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structure)
1087
inline JSFinalObject* JSFinalObject::create(
1088
    ExecState* exec, Structure* structure, Butterfly* butterfly)
1088
{
1089
{
1089
    JSFinalObject* finalObject = new (
1090
    JSFinalObject* finalObject = new (
1090
        NotNull, 
1091
        NotNull, 
Lines 1092-1098 inline JSFinalObject* JSFinalObject::cre Source/JavaScriptCore/runtime/JSObject.h_sec3
1092
            *exec->heap(),
1093
            *exec->heap(),
1093
            allocationSize(structure->inlineCapacity())
1094
            allocationSize(structure->inlineCapacity())
1094
        )
1095
        )
1095
    ) JSFinalObject(exec->vm(), structure);
1096
    ) JSFinalObject(exec->vm(), structure, butterfly);
1096
    finalObject->finishCreation(exec->vm());
1097
    finalObject->finishCreation(exec->vm());
1097
    return finalObject;
1098
    return finalObject;
1098
}
1099
}
- Source/JavaScriptCore/runtime/Structure.cpp +7 lines
Lines 1105-1110 PassRefPtr<StructureShape> Structure::to Source/JavaScriptCore/runtime/Structure.cpp_sec1
1105
    return baseShape.release();
1105
    return baseShape.release();
1106
}
1106
}
1107
1107
1108
bool Structure::canUseForAllocationsOf(Structure* other)
1109
{
1110
    return inlineCapacity() == other->inlineCapacity()
1111
        && storedPrototype() == other->storedPrototype()
1112
        && objectInitializationBlob() == other->objectInitializationBlob();
1113
}
1114
1108
void Structure::dump(PrintStream& out) const
1115
void Structure::dump(PrintStream& out) const
1109
{
1116
{
1110
    out.print(RawPointer(this), ":[", classInfo()->className, ", {");
1117
    out.print(RawPointer(this), ":[", classInfo()->className, ", {");
- Source/JavaScriptCore/runtime/Structure.h +4 lines
Lines 433-438 public: Source/JavaScriptCore/runtime/Structure.h_sec1
433
433
434
    PassRefPtr<StructureShape> toStructureShape(JSValue);
434
    PassRefPtr<StructureShape> toStructureShape(JSValue);
435
    
435
    
436
    // Determines if the two structures match enough that this one could be used for allocations
437
    // of the other one.
438
    bool canUseForAllocationsOf(Structure*);
439
    
436
    void dump(PrintStream&) const;
440
    void dump(PrintStream&) const;
437
    void dumpInContext(PrintStream&, DumpContext*) const;
441
    void dumpInContext(PrintStream&, DumpContext*) const;
438
    void dumpBrief(PrintStream&, const CString&) const;
442
    void dumpBrief(PrintStream&, const CString&) const;
- 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