| Differences between
and this patch
- Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h -2 lines
Lines 36-43 namespace JSC { Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h_sec1
36
36
37
class CodeBlock;
37
class CodeBlock;
38
38
39
typedef HashMap<unsigned, FastBitVector, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > BytecodeToBitmapMap;
40
41
class BytecodeBasicBlock : public RefCounted<BytecodeBasicBlock> {
39
class BytecodeBasicBlock : public RefCounted<BytecodeBasicBlock> {
42
public:
40
public:
43
    enum SpecialBlockType { EntryBlock, ExitBlock };
41
    enum SpecialBlockType { EntryBlock, ExitBlock };
- Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp -61 / +47 lines
Lines 26-31 Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "BytecodeLivenessAnalysis.h"
27
#include "BytecodeLivenessAnalysis.h"
28
28
29
#include "BytecodeLivenessAnalysisInlines.h"
29
#include "CodeBlock.h"
30
#include "CodeBlock.h"
30
#include "PreciseJumpTargets.h"
31
#include "PreciseJumpTargets.h"
31
32
Lines 38-81 BytecodeLivenessAnalysis::BytecodeLivene Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec2
38
    compute();
39
    compute();
39
}
40
}
40
41
41
static int numberOfCapturedVariables(CodeBlock* codeBlock)
42
{
43
    if (!codeBlock->symbolTable())
44
        return 0;
45
    return codeBlock->symbolTable()->captureCount();
46
}
47
48
static int captureStart(CodeBlock* codeBlock)
49
{
50
    if (!codeBlock->symbolTable())
51
        return 0;
52
    return codeBlock->symbolTable()->captureStart();
53
}
54
55
static int captureEnd(CodeBlock* codeBlock)
56
{
57
    if (!codeBlock->symbolTable())
58
        return 0;
59
    return codeBlock->symbolTable()->captureEnd();
60
}
61
62
static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand)
42
static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand)
63
{
43
{
64
    VirtualRegister virtualReg(operand);
44
    VirtualRegister virtualReg(operand);
65
    return !codeBlock->isConstantRegisterIndex(operand) // Don't care about constants.
45
    return !codeBlock->isConstantRegisterIndex(operand) // Don't care about constants.
66
        && virtualReg.isLocal() // Don't care about arguments.
46
        && virtualReg.isLocal() // Don't care about arguments.
67
        && (!numberOfCapturedVariables(codeBlock) // If we have no captured variables, we're good to go.
47
        && (!codeBlock->captureCount() // If we have no captured variables, we're good to go.
68
            || (virtualReg.offset() > captureStart(codeBlock) || (virtualReg.offset() <= captureEnd(codeBlock))));
48
            || (virtualReg.offset() > codeBlock->captureStart() || (virtualReg.offset() <= codeBlock->captureEnd())));
69
}
49
}
70
50
71
static void setForOperand(CodeBlock* codeBlock, FastBitVector& bits, int operand)
51
static void setForOperand(CodeBlock* codeBlock, FastBitVector& bits, int operand)
72
{
52
{
73
    ASSERT(isValidRegisterForLiveness(codeBlock, operand));
53
    ASSERT(isValidRegisterForLiveness(codeBlock, operand));
74
    VirtualRegister virtualReg(operand);
54
    VirtualRegister virtualReg(operand);
75
    if (virtualReg.offset() > captureStart(codeBlock))
55
    if (virtualReg.offset() > codeBlock->captureStart())
76
        bits.set(virtualReg.toLocal());
56
        bits.set(virtualReg.toLocal());
77
    else
57
    else
78
        bits.set(virtualReg.toLocal() - numberOfCapturedVariables(codeBlock));
58
        bits.set(virtualReg.toLocal() - codeBlock->captureCount());
79
}
59
}
80
60
81
static void computeUsesForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& uses)
61
static void computeUsesForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& uses)
Lines 533-538 static BytecodeBasicBlock* findBasicBloc Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec3
533
    return basicBlock[1].get();
513
    return basicBlock[1].get();
534
}
514
}
535
515
516
static void stepOverInstruction(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock>>& basicBlocks, unsigned bytecodeOffset, FastBitVector& uses, FastBitVector& defs, FastBitVector& out)
517
{
518
    uses.clearAll();
519
    defs.clearAll();
520
    
521
    computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, uses);
522
    computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, defs);
523
    
524
    out.exclude(defs);
525
    out.merge(uses);
526
    
527
    // If we have an exception handler, we want the live-in variables of the 
528
    // exception handler block to be included in the live-in of this particular bytecode.
529
    if ((handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
530
        BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target);
531
        ASSERT(handlerBlock);
532
        out.merge(handlerBlock->in());
533
    }
534
}
535
536
static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks, unsigned targetOffset, FastBitVector& result)
536
static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks, unsigned targetOffset, FastBitVector& result)
537
{
537
{
538
    ASSERT(!block->isExitBlock());
538
    ASSERT(!block->isExitBlock());
Lines 550-572 static void computeLocalLivenessForBytec Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec4
550
        unsigned bytecodeOffset = block->bytecodeOffsets()[i];
550
        unsigned bytecodeOffset = block->bytecodeOffsets()[i];
551
        if (targetOffset > bytecodeOffset)
551
        if (targetOffset > bytecodeOffset)
552
            break;
552
            break;
553
553
        
554
        uses.clearAll();
554
        stepOverInstruction(codeBlock, basicBlocks, bytecodeOffset, uses, defs, out);
555
        defs.clearAll();
556
557
        computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, uses);
558
        computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, defs);
559
560
        out.exclude(defs);
561
        out.merge(uses);
562
563
        // If we have an exception handler, we want the live-in variables of the 
564
        // exception handler block to be included in the live-in of this particular bytecode.
565
        if ((handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
566
            BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target);
567
            ASSERT(handlerBlock);
568
            out.merge(handlerBlock->in());
569
        }
570
    }
555
    }
571
556
572
    result.set(out);
557
    result.set(out);
Lines 583-589 void BytecodeLivenessAnalysis::runLivene Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec5
583
{
568
{
584
    UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock();
569
    UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock();
585
    unsigned numberOfVariables = unlinkedCodeBlock->m_numVars + 
570
    unsigned numberOfVariables = unlinkedCodeBlock->m_numVars + 
586
        unlinkedCodeBlock->m_numCalleeRegisters - numberOfCapturedVariables(m_codeBlock);
571
        unlinkedCodeBlock->m_numCalleeRegisters - m_codeBlock->captureCount();
587
572
588
    for (unsigned i = 0; i < m_basicBlocks.size(); i++) {
573
    for (unsigned i = 0; i < m_basicBlocks.size(); i++) {
589
        BytecodeBasicBlock* block = m_basicBlocks[i].get();
574
        BytecodeBasicBlock* block = m_basicBlocks[i].get();
Lines 622-657 void BytecodeLivenessAnalysis::getLivene Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec6
622
607
623
bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset)
608
bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset)
624
{
609
{
625
    int numCapturedVars = numberOfCapturedVariables(m_codeBlock);
610
    if (operandIsAlwaysLive(m_codeBlock, operand))
626
    if (VirtualRegister(operand).isArgument())
627
        return true;
628
    if (operand <= captureStart(m_codeBlock) && operand > captureEnd(m_codeBlock))
629
        return true;
611
        return true;
630
    FastBitVector result;
612
    FastBitVector result;
631
    getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, result);
613
    getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, result);
632
    return result.get(operand - numCapturedVars);
614
    return operandThatIsNotAlwaysLiveIsLive(m_codeBlock, result, operand);
633
}
615
}
634
616
635
FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset)
617
FastBitVector getLivenessInfo(CodeBlock* codeBlock, const FastBitVector& out)
636
{
618
{
637
    FastBitVector temp;
638
    FastBitVector result;
619
    FastBitVector result;
639
620
640
    getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, temp);
621
    unsigned numCapturedVars = m_codeBlock->captureCount();
641
642
    unsigned numCapturedVars = numberOfCapturedVariables(m_codeBlock);
643
    if (numCapturedVars) {
622
    if (numCapturedVars) {
644
        int firstCapturedLocal = VirtualRegister(captureStart(m_codeBlock)).toLocal();
623
        int firstCapturedLocal = VirtualRegister(m_codeBlock->captureStart()).toLocal();
645
        result.resize(temp.numBits() + numCapturedVars);
624
        result.resize(out.numBits() + numCapturedVars);
646
        for (unsigned i = 0; i < numCapturedVars; ++i)
625
        for (unsigned i = 0; i < numCapturedVars; ++i)
647
            result.set(firstCapturedLocal + i);
626
            result.set(firstCapturedLocal + i);
648
    } else
627
    } else
649
        result.resize(temp.numBits());
628
        result.resize(out.numBits());
650
629
651
    int tempLength = temp.numBits();
630
    int outLength = out.numBits();
652
    ASSERT(tempLength >= 0);
631
    ASSERT(outLength >= 0);
653
    for (int i = 0; i < tempLength; i++) {
632
    for (int i = 0; i < outLength; i++) {
654
        if (!temp.get(i))
633
        if (!out.get(i))
655
            continue;
634
            continue;
656
635
657
        if (!numCapturedVars) {
636
        if (!numCapturedVars) {
Lines 659-665 FastBitVector BytecodeLivenessAnalysis:: Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec7
659
            continue;
638
            continue;
660
        }
639
        }
661
640
662
        if (virtualRegisterForLocal(i).offset() > captureStart(m_codeBlock))
641
        if (virtualRegisterForLocal(i).offset() > m_codeBlock->captureStart())
663
            result.set(i);
642
            result.set(i);
664
        else 
643
        else 
665
            result.set(numCapturedVars + i);
644
            result.set(numCapturedVars + i);
Lines 667-672 FastBitVector BytecodeLivenessAnalysis:: Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp_sec8
667
    return result;
646
    return result;
668
}
647
}
669
648
649
FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset)
650
{
651
    FastBitVector out;
652
    getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, out);
653
    return getLivenessInfo(m_codeBlock, out);
654
}
655
670
void BytecodeLivenessAnalysis::dumpResults()
656
void BytecodeLivenessAnalysis::dumpResults()
671
{
657
{
672
    Interpreter* interpreter = m_codeBlock->vm()->interpreter;
658
    Interpreter* interpreter = m_codeBlock->vm()->interpreter;
- Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h -1 / +9 lines
Lines 38-46 class CodeBlock; Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h_sec1
38
class BytecodeLivenessAnalysis {
38
class BytecodeLivenessAnalysis {
39
public:
39
public:
40
    BytecodeLivenessAnalysis(CodeBlock*);
40
    BytecodeLivenessAnalysis(CodeBlock*);
41
41
    
42
    bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset);
42
    bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset);
43
    FastBitVector getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset);
43
    FastBitVector getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset);
44
    
45
    void computeFullLiveness(FullBytecodeLiveness&);
44
46
45
private:
47
private:
46
    void compute();
48
    void compute();
Lines 53-58 private: Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h_sec2
53
    Vector<RefPtr<BytecodeBasicBlock> > m_basicBlocks;
55
    Vector<RefPtr<BytecodeBasicBlock> > m_basicBlocks;
54
};
56
};
55
57
58
inline bool operandIsAlwaysLive(CodeBlock* codeBlock, int operand);
59
inline bool operandThatIsNotAlwaysLiveIsLive(CodeBlock* codeBlock, const FastBitVector& out, int operand);
60
inline bool operandIsLive(CodeBlock* codeBlock, const FastBitVector& out, int operand);
61
62
FastBitVector getLivenessInfo(CodeBlock*, const FastBitVector& out);
63
56
} // namespace JSC
64
} // namespace JSC
57
65
58
#endif // BytecodeLivenessAnalysis_h
66
#endif // BytecodeLivenessAnalysis_h
- Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h +55 lines
Line 0 Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h_sec1
1
/*
2
 * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef BytecodeLivenessAnalysisInlines_h
27
#define BytecodeLivenessAnalysisInlines_h
28
29
#include "BytecodeLivenessAnalysis.h"
30
#include "CodeBlock.h"
31
32
namespace JSC {
33
34
inline bool operandIsAlwaysLive(CodeBlock* codeBlock, int operand)
35
{
36
    if (VirtualRegister(operand).isArgument())
37
        return true;
38
    int numCapturedVars = numberOfCapturedVariables(m_codeBlock);
39
    return operand <= m_codeBlock->captureStart() && operand > m_codeBlock->captureEnd();
40
}
41
42
inline bool operandThatIsNotAlwaysLiveIsLive(CodeBlock* codeBlock, const FastBitVector& out, int operand)
43
{
44
    return out.get(operand - codeBlock->captureCount());
45
}
46
47
inline bool operandIsLive(CodeBlock* codeBlock, const FastBitVector& out, int operand)
48
{
49
    return operandIsAlwaysLive(codeBlock, operand) || operandThatIsNotAlwaysLiveIsLive(codeBlock, out, operand);
50
}
51
52
} // namespace JSC
53
54
#endif // BytecodeLivenessAnalysisInlines_h
55
- Source/JavaScriptCore/bytecode/CodeBlock.h +21 lines
Lines 354-359 public: Source/JavaScriptCore/bytecode/CodeBlock.h_sec1
354
    {
354
    {
355
        return m_needsActivation;
355
        return m_needsActivation;
356
    }
356
    }
357
    
358
    unsigned captureCount() const
359
    {
360
        if (!symbolTable())
361
            return 0;
362
        return symbolTable()->captureCount();
363
    }
364
    
365
    int captureStart() const
366
    {
367
        if (!symbolTable())
368
            return 0;
369
        return symbolTable()->captureStart();
370
    }
371
    
372
    int captureEnd() const
373
    {
374
        if (!symbolTable())
375
            return 0;
376
        return symboLTable()->captureEnd();
377
    }
357
378
358
    bool isCaptured(VirtualRegister operand, InlineCallFrame* = 0) const;
379
    bool isCaptured(VirtualRegister operand, InlineCallFrame* = 0) const;
359
    
380
    
- Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h +70 lines
Line 0 Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h_sec1
1
/*
2
 * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef FullBytecodeLiveness_h
27
#define FullBytecodeLiveness_h
28
29
#include <wtf/FastBitVector.h>
30
31
namespace JSC {
32
33
class BytecodeLivenessAnalysis;
34
35
typedef HashMap<unsigned, FastBitVector, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > BytecodeToBitmapMap;
36
37
class FullBytecodeLiveness {
38
public:
39
    FullBytecodeLiveness() : m_codeBlock(0) { }
40
    
41
    // We say "out" to refer to the bitvector that contains raw results for a bytecode
42
    // instruction.
43
    const FastBitVector& getOut(unsigned bytecodeIndex) const
44
    {
45
        BytecodeToBitmapMap::const_iterator iter = m_map.find(bytecodeIndex);
46
        ASSERT(iter != m_map.end());
47
        return iter->value;
48
    }
49
    
50
    bool operandIsLive(int operand, unsigned bytecodeIndex) const
51
    {
52
        return operandIsAlwaysLive(m_codeBlock, operand) || operandThatIsNotAlwaysLiveIsLive(m_codeBlock, getOut(bytecodeIndex), operand);
53
    }
54
    
55
    FastBitVector getLiveness(unsigned bytecodeIndex) const
56
    {
57
        return getLivenessInfo(m_codeBlock, getOut(bytecodeIndex));
58
    }
59
    
60
private:
61
    friend class BytecodeLivenessAnalysis;
62
    
63
    CodeBlock* m_codeBlock;
64
    BytecodeToBitmapMap m_map;
65
};
66
67
} // namespace JSC
68
69
#endif // FullBytecodeLiveness_h
70
- Source/JavaScriptCore/dfg/DFGBasicBlock.h -2 / +2 lines
Lines 140-147 struct BasicBlock : RefCounted<BasicBloc Source/JavaScriptCore/dfg/DFGBasicBlock.h_sec1
140
    struct SSAData {
140
    struct SSAData {
141
        Operands<FlushedAt> flushAtHead;
141
        Operands<FlushedAt> flushAtHead;
142
        Operands<FlushedAt> flushAtTail;
142
        Operands<FlushedAt> flushAtTail;
143
        Operands<Node*> availabilityAtHead;
143
        Operands<FlushFormat> availabilityAtHead;
144
        Operands<Node*> availabilityAtTail;
144
        Operands<FlushFormat> availabilityAtTail;
145
        HashSet<Node*> liveAtHead;
145
        HashSet<Node*> liveAtHead;
146
        HashSet<Node*> liveAtTail;
146
        HashSet<Node*> liveAtTail;
147
        HashMap<Node*, AbstractValue> valuesAtHead;
147
        HashMap<Node*, AbstractValue> valuesAtHead;
- Source/JavaScriptCore/dfg/DFGFlushFormat.cpp +3 lines
Lines 56-61 void printInternal(PrintStream& out, Flu Source/JavaScriptCore/dfg/DFGFlushFormat.cpp_sec1
56
    case FlushedJSValue:
56
    case FlushedJSValue:
57
        out.print("FlushedJSValue");
57
        out.print("FlushedJSValue");
58
        return;
58
        return;
59
    case ConflictingFlush:
60
        out.print("ConflictingFlush");
61
        return;
59
    }
62
    }
60
    RELEASE_ASSERT_NOT_REACHED();
63
    RELEASE_ASSERT_NOT_REACHED();
61
}
64
}
- Source/JavaScriptCore/dfg/DFGFlushFormat.h -1 / +16 lines
Lines 45-51 enum FlushFormat { Source/JavaScriptCore/dfg/DFGFlushFormat.h_sec1
45
    FlushedDouble,
45
    FlushedDouble,
46
    FlushedCell,
46
    FlushedCell,
47
    FlushedBoolean,
47
    FlushedBoolean,
48
    FlushedJSValue
48
    FlushedJSValue,
49
    ConflictingFlush
49
};
50
};
50
51
51
inline NodeFlags resultFor(FlushFormat format)
52
inline NodeFlags resultFor(FlushFormat format)
Lines 54-59 inline NodeFlags resultFor(FlushFormat f Source/JavaScriptCore/dfg/DFGFlushFormat.h_sec2
54
    case DeadFlush:
55
    case DeadFlush:
55
    case FlushedJSValue:
56
    case FlushedJSValue:
56
    case FlushedCell:
57
    case FlushedCell:
58
    case ConflictingFlush:
57
        return NodeResultJS;
59
        return NodeResultJS;
58
    case FlushedInt32:
60
    case FlushedInt32:
59
        return NodeResultInt32;
61
        return NodeResultInt32;
Lines 73-78 inline UseKind useKindFor(FlushFormat fo Source/JavaScriptCore/dfg/DFGFlushFormat.h_sec3
73
    switch (format) {
75
    switch (format) {
74
    case DeadFlush:
76
    case DeadFlush:
75
    case FlushedJSValue:
77
    case FlushedJSValue:
78
    case ConflictingFlush:
76
        return UntypedUse;
79
        return UntypedUse;
77
    case FlushedCell:
80
    case FlushedCell:
78
        return CellUse;
81
        return CellUse;
Lines 93-98 inline DataFormat dataFormatFor(FlushFor Source/JavaScriptCore/dfg/DFGFlushFormat.h_sec4
93
{
96
{
94
    switch (format) {
97
    switch (format) {
95
    case DeadFlush:
98
    case DeadFlush:
99
    case ConflictingFlush:
96
        return DataFormatDead;
100
        return DataFormatDead;
97
    case FlushedJSValue:
101
    case FlushedJSValue:
98
        return DataFormatJS;
102
        return DataFormatJS;
Lines 111-116 inline DataFormat dataFormatFor(FlushFor Source/JavaScriptCore/dfg/DFGFlushFormat.h_sec5
111
    return DataFormatDead;
115
    return DataFormatDead;
112
}
116
}
113
117
118
inline FlushFormat merge(FlushFormat a, FlushFormat b)
119
{
120
    if (a == DeadFlush)
121
        return b;
122
    if (b == DeadFlush)
123
        return a;
124
    if (a != b)
125
        return ContradictingFlush;
126
    return a;
127
}
128
114
} } // namespace JSC::DFG
129
} } // namespace JSC::DFG
115
130
116
namespace WTF {
131
namespace WTF {
- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp -65 / +61 lines
Lines 47-123 public: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp_sec1
47
    {
47
    {
48
        ASSERT(m_graph.m_form == SSA);
48
        ASSERT(m_graph.m_form == SSA);
49
        
49
        
50
        Vector<BasicBlock*> depthFirst;
50
        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
51
        m_graph.getBlocksInDepthFirstOrder(depthFirst);
51
            BasicBlock* block = m_graph.block(blockIndex);
52
        
52
            if (!block)
53
        for (unsigned i = 0; i < depthFirst.size(); ++i) {
53
                continue;
54
            BasicBlock* block = depthFirst[i];
54
            block->ssa->availabilityAtHead.fill(DeadFlush);
55
            block->ssa->availabilityAtHead.fill(0);
55
            block->ssa->availabilityAtTail.fill(DeadFlush);
56
            block->ssa->availabilityAtTail.fill(0);
57
        }
56
        }
58
        
57
        
59
        for (unsigned i = 0; i < depthFirst.size(); ++i) {
58
        BasicBlock* root = m_graph.block(0);
60
            BasicBlock* block = depthFirst[i];
59
        for (unsigned argument = root->ssa->availabilityAtHead.numberOfArguments(); argument--;)
61
            
60
            root->ssa->availabilityAtHead.argument(argument) = FlushedJSValue;
62
            // We edit availabilityAtTail in-place, but first initialize it to
61
        for (unsigned local = root->ssa->availabilityAtHead.numberOfLocals(); local--;)
63
            // availabilityAtHead.
62
            root->ssa->availabilityAtHead.local(local) = ConflictingFlush;
64
            Operands<Node*>& availability = block->ssa->availabilityAtTail;
63
        
65
            availability = block->ssa->availabilityAtHead;
64
        // This could be made more efficient by processing blocks in reverse postorder.
65
        Operands<FlushFormat> availability;
66
        bool changed;
67
        do {
68
            changed = false;
66
            
69
            
67
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
70
            for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
68
                Node* node = block->at(nodeIndex);
71
                BasicBlock* block = m_graph.block(blockIndex);
69
                switch (node->op()) {
72
                if (!block)
70
                case SetLocal:
73
                    continue;
71
                case MovHint:
74
                
72
                case MovHintAndCheck: {
75
                availability = block->ssa->availabilityAtHead;
73
                    availability.operand(node->local()) = node->child1().node();
76
                
74
                    break;
77
                for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
75
                }
78
                    Node* node = block->at(nodeIndex);
76
                    
79
                    
77
                case ZombieHint: {
80
                    switch (node->op()) {
78
                    availability.operand(node->local()) = 0;
81
                    case SetLocal:
79
                    break;
82
                    case MovHint:
80
                }
83
                    case MovHintAndCheck:
81
                    
84
                    case GetArgument: {
82
                case GetArgument: {
85
                        VariableAccessData* variable = node->variableAccessData();
83
                    availability.operand(node->local()) = node;
86
                        availability.operand(variable->local()) = variable->flushFormat();
84
                    break;
87
                        break;
88
                    }
89
                        
90
                    case ZombieHint: {
91
                        // This means that our DCE has proved that nobody will use this
92
                        // value, ever.
93
                        availability.operand(node->local()) = ContradictingFlush;
94
                    }
95
                        
96
                    default:
97
                        break;
98
                    }
85
                }
99
                }
86
                    
100
                
87
                default:
101
                if (availability == block->ssa->availabilityAtTail)
88
                    break;
102
                    continue;
103
                
104
                block->ssa->availabilityAtTail = availability;
105
                changed = true;
106
                
107
                for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
108
                    BasicBlock* successor = block->successor(successorIndex);
109
                    for (unsigned i = availability.size(); i--;) {
110
                        successor->ssa->availabilityAtHead[i] = merge(
111
                            successor->ssa->availabilityAtHead[i],
112
                            availability[i]);
113
                    }
89
                }
114
                }
90
            }
115
            }
91
            
116
        } while (changed);
92
            for (unsigned j = block->numSuccessors(); j--;) {
93
                BasicBlock* successor = block->successor(j);
94
                Operands<Node*>& successorAvailability = successor->ssa->availabilityAtHead;
95
                for (unsigned k = availability.size(); k--;) {
96
                    Node* myNode = availability[k];
97
                    if (!myNode)
98
                        continue;
99
                    
100
                    if (!successor->ssa->liveAtHead.contains(myNode))
101
                        continue;
102
                    
103
                    // Note that this may overwrite availability with a bogus node
104
                    // at merge points. This is fine, since merge points have
105
                    // MovHint(Phi)'s to work around this. The outcome of this is
106
                    // you might have a program in which a node happens to remain
107
                    // live into some block B, and separately (due to copy
108
                    // propagation) just one of the predecessors of B issued a
109
                    // MovHint putting that node into some local. Then in B we might
110
                    // think that that node is a valid value for that local. Of
111
                    // course if that local was actually live in B, B would have a
112
                    // Phi for it. So essentially we'll have OSR exit dropping this
113
                    // node's value into the local when we otherwise (in the DFG)
114
                    // would have dropped undefined into the local. This seems
115
                    // harmless.
116
                    
117
                    successorAvailability[k] = myNode;
118
                }
119
            }
120
        }
121
        
117
        
122
        return true;
118
        return true;
123
    }
119
    }
- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h -3 / +5 lines
Lines 36-44 namespace JSC { namespace DFG { Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h_sec1
36
36
37
class Graph;
37
class Graph;
38
38
39
// Computes BasicBlock::ssa->availabiltiyAtHead/Tail. This relies on liveness
39
// Computes BasicBlock::ssa->availabiltiyAtHead/Tail. This is a forward flow type inference
40
// analysis phase having been run and the graph not having been transformed
40
// over MovHints. At the time when MovHints are introduced, we were certain that at any
41
// after that.
41
// point in the program where a bytecode variable had been live, all of the MovHints that
42
// flowed into that point for that variable had the same FlushFormat. This analysis will tell
43
// you what that format would have been.
42
44
43
bool performOSRAvailabilityAnalysis(Graph&);
45
bool performOSRAvailabilityAnalysis(Graph&);
44
46
- Source/JavaScriptCore/dfg/DFGValueSource.h +1 lines
Lines 145-150 public: Source/JavaScriptCore/dfg/DFGValueSource.h_sec1
145
    {
145
    {
146
        switch (format) {
146
        switch (format) {
147
        case DeadFlush:
147
        case DeadFlush:
148
        case ConflictingFlush:
148
            return ValueSource(SourceIsDead);
149
            return ValueSource(SourceIsDead);
149
        case FlushedJSValue:
150
        case FlushedJSValue:
150
            return ValueSource(ValueInJSStack, where);
151
            return ValueSource(ValueInJSStack, where);
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -1 / +3 lines
Lines 661-666 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
661
        }
661
        }
662
            
662
            
663
        case DeadFlush:
663
        case DeadFlush:
664
        case ConflictingFlush:
664
            RELEASE_ASSERT_NOT_REACHED();
665
            RELEASE_ASSERT_NOT_REACHED();
665
        }
666
        }
666
        
667
        
Lines 3851-3857 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
3851
        for (unsigned i = m_valueSources.size(); i--;) {
3852
        for (unsigned i = m_valueSources.size(); i--;) {
3852
            FlushedAt flush = m_highBlock->ssa->flushAtHead[i];
3853
            FlushedAt flush = m_highBlock->ssa->flushAtHead[i];
3853
            switch (flush.format()) {
3854
            switch (flush.format()) {
3854
            case DeadFlush: {
3855
            case DeadFlush:
3856
            case ConflictingFlush: {
3855
                // Must consider available nodes instead.
3857
                // Must consider available nodes instead.
3856
                Node* node = m_highBlock->ssa->availabilityAtHead[i];
3858
                Node* node = m_highBlock->ssa->availabilityAtHead[i];
3857
                if (!node) {
3859
                if (!node) {
- Source/JavaScriptCore/runtime/SymbolTable.h -3 / +3 lines
Lines 469-481 public: Source/JavaScriptCore/runtime/SymbolTable.h_sec1
469
    bool usesNonStrictEval() { return m_usesNonStrictEval; }
469
    bool usesNonStrictEval() { return m_usesNonStrictEval; }
470
    void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
470
    void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
471
471
472
    int captureStart() { return m_captureStart; }
472
    int captureStart() const { return m_captureStart; }
473
    void setCaptureStart(int captureStart) { m_captureStart = captureStart; }
473
    void setCaptureStart(int captureStart) { m_captureStart = captureStart; }
474
474
475
    int captureEnd() { return m_captureEnd; }
475
    int captureEnd() const { return m_captureEnd; }
476
    void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; }
476
    void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; }
477
477
478
    int captureCount() { return -(m_captureEnd - m_captureStart); }
478
    int captureCount() const { return -(m_captureEnd - m_captureStart); }
479
479
480
    int parameterCount() { return m_parameterCountIncludingThis - 1; }
480
    int parameterCount() { return m_parameterCountIncludingThis - 1; }
481
    int parameterCountIncludingThis() { return m_parameterCountIncludingThis; }
481
    int parameterCountIncludingThis() { return m_parameterCountIncludingThis; }

Return to Bug 124181