| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +67 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2015-11-30  Filip Pizlo  <fpizlo@apple.com>
2
3
        B3 stackmaps should support early clobber
4
        https://bugs.webkit.org/show_bug.cgi?id=151668
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        While starting work on FTL lazy slow paths, I realized that we needed some way to say that r11 is
9
        off limits. Not just that it's clobbered, but that it cannot be used for any input values to a
10
        stackmap.
11
12
        In LLVM we do this by having the AnyRegCC forbid r11.
13
14
        In B3, we want something more flexible. In this and other cases, what we really want is an early
15
        clobber set. B3 already supported a late clobber set for every stackmap value. Late clobber means
16
        that the act of performing the operation will cause garbage to be written into those registers.
17
        But here we want: assume that garbage magically appears in those registers in the moment before
18
        the operation executes. Any registers in that set will be off-limits to the inputs to the
19
        stackmap. This should be great for other things, like the way the we handle exceptions.
20
21
        This adds the early clobber feature, does some minor Inst refactoring to make this less scary,
22
        and adds a test. The test is simple but it's very comprehensive - for example it tests the
23
        early-clobber-after-Move special case.
24
25
        * b3/B3StackmapSpecial.cpp:
26
        (JSC::B3::StackmapSpecial::extraClobberedRegs):
27
        (JSC::B3::StackmapSpecial::extraEarlyClobberedRegs):
28
        (JSC::B3::StackmapSpecial::forEachArgImpl):
29
        * b3/B3StackmapSpecial.h:
30
        * b3/B3StackmapValue.cpp:
31
        (JSC::B3::StackmapValue::dumpMeta):
32
        (JSC::B3::StackmapValue::StackmapValue):
33
        * b3/B3StackmapValue.h:
34
        * b3/air/AirCCallSpecial.cpp:
35
        (JSC::B3::Air::CCallSpecial::extraClobberedRegs):
36
        (JSC::B3::Air::CCallSpecial::extraEarlyClobberedRegs):
37
        (JSC::B3::Air::CCallSpecial::dumpImpl):
38
        * b3/air/AirCCallSpecial.h:
39
        * b3/air/AirInst.h:
40
        * b3/air/AirInstInlines.h:
41
        (JSC::B3::Air::Inst::extraClobberedRegs):
42
        (JSC::B3::Air::Inst::extraEarlyClobberedRegs):
43
        (JSC::B3::Air::Inst::forEachTmpWithExtraClobberedRegs):
44
        (JSC::B3::Air::Inst::reportUsedRegisters):
45
        (JSC::B3::Air::Inst::forEachDefAndExtraClobberedTmp): Deleted.
46
        * b3/air/AirIteratedRegisterCoalescing.cpp:
47
        (JSC::B3::Air::IteratedRegisterCoalescingAllocator::IteratedRegisterCoalescingAllocator):
48
        (JSC::B3::Air::IteratedRegisterCoalescingAllocator::build):
49
        (JSC::B3::Air::IteratedRegisterCoalescingAllocator::allocate):
50
        (JSC::B3::Air::IteratedRegisterCoalescingAllocator::initializeDegrees):
51
        (JSC::B3::Air::IteratedRegisterCoalescingAllocator::addEdges):
52
        (JSC::B3::Air::IteratedRegisterCoalescingAllocator::addEdge):
53
        (JSC::B3::Air::iteratedRegisterCoalescingOnType):
54
        (JSC::B3::Air::iteratedRegisterCoalescing):
55
        * b3/air/AirSpecial.h:
56
        * b3/air/AirSpillEverything.cpp:
57
        (JSC::B3::Air::spillEverything):
58
        * b3/testb3.cpp:
59
        (JSC::B3::testSimplePatchpointWithoutOuputClobbersGPArgs):
60
        (JSC::B3::testSimplePatchpointWithOuputClobbersGPArgs):
61
        (JSC::B3::testSimplePatchpointWithoutOuputClobbersFPArgs):
62
        (JSC::B3::testSimplePatchpointWithOuputClobbersFPArgs):
63
        (JSC::B3::testPatchpointWithEarlyClobber):
64
        (JSC::B3::testPatchpointCallArg):
65
        (JSC::B3::run):
66
        * dfg/DFGCommon.h:
67
1
2015-11-30  Mark Lam  <mark.lam@apple.com>
68
2015-11-30  Mark Lam  <mark.lam@apple.com>
2
69
3
        Snippefy op_div for the baseline JIT.
70
        Snippefy op_div for the baseline JIT.
- Source/JavaScriptCore/b3/B3StackmapSpecial.cpp -1 / +9 lines
Lines 60-66 const RegisterSet& StackmapSpecial::extr Source/JavaScriptCore/b3/B3StackmapSpecial.cpp_sec1
60
    StackmapValue* value = inst.origin->as<StackmapValue>();
60
    StackmapValue* value = inst.origin->as<StackmapValue>();
61
    ASSERT(value);
61
    ASSERT(value);
62
62
63
    return value->clobbered();
63
    return value->lateClobbered();
64
}
65
66
const RegisterSet& StackmapSpecial::extraEarlyClobberedRegs(Inst& inst)
67
{
68
    StackmapValue* value = inst.origin->as<StackmapValue>();
69
    ASSERT(value);
70
71
    return value->earlyClobbered();
64
}
72
}
65
73
66
void StackmapSpecial::forEachArgImpl(
74
void StackmapSpecial::forEachArgImpl(
- Source/JavaScriptCore/b3/B3StackmapSpecial.h +1 lines
Lines 48-53 public: Source/JavaScriptCore/b3/B3StackmapSpecial.h_sec1
48
protected:
48
protected:
49
    void reportUsedRegisters(Air::Inst&, const RegisterSet&) override;
49
    void reportUsedRegisters(Air::Inst&, const RegisterSet&) override;
50
    const RegisterSet& extraClobberedRegs(Air::Inst&) override;
50
    const RegisterSet& extraClobberedRegs(Air::Inst&) override;
51
    const RegisterSet& extraEarlyClobberedRegs(Air::Inst&) override;
51
52
52
    // Note that this does not override generate() or dumpImpl()/deepDumpImpl(). We have many some
53
    // Note that this does not override generate() or dumpImpl()/deepDumpImpl(). We have many some
53
    // subclasses that implement that.
54
    // subclasses that implement that.
- Source/JavaScriptCore/b3/B3StackmapValue.cpp -2 / +2 lines
Lines 79-86 void StackmapValue::dumpChildren(CommaPr Source/JavaScriptCore/b3/B3StackmapValue.cpp_sec1
79
void StackmapValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
79
void StackmapValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
80
{
80
{
81
    out.print(
81
    out.print(
82
        comma, "generator = ", RawPointer(m_generator.get()), ", clobbered = ", m_clobbered,
82
        comma, "generator = ", RawPointer(m_generator.get()), ", earlyClobbered = ", m_earlyClobbered,
83
        ", usedRegisters = ", m_usedRegisters);
83
        ", lateClobbered = ", m_lateClobbered, ", usedRegisters = ", m_usedRegisters);
84
}
84
}
85
85
86
StackmapValue::StackmapValue(unsigned index, CheckedOpcodeTag, Opcode opcode, Type type, Origin origin)
86
StackmapValue::StackmapValue(unsigned index, CheckedOpcodeTag, Opcode opcode, Type type, Origin origin)
- Source/JavaScriptCore/b3/B3StackmapValue.h -3 / +16 lines
Lines 83-94 public: Source/JavaScriptCore/b3/B3StackmapValue.h_sec1
83
83
84
    const Vector<ValueRep>& reps() const { return m_reps; }
84
    const Vector<ValueRep>& reps() const { return m_reps; }
85
85
86
    void clobberEarly(const RegisterSet& set)
87
    {
88
        m_earlyClobbered.merge(set);
89
    }
90
91
    void clobberLate(const RegisterSet& set)
92
    {
93
        m_lateClobbered.merge(set);
94
    }
95
86
    void clobber(const RegisterSet& set)
96
    void clobber(const RegisterSet& set)
87
    {
97
    {
88
        m_clobbered.merge(set);
98
        clobberEarly(set);
99
        clobberLate(set);
89
    }
100
    }
90
101
91
    const RegisterSet& clobbered() const { return m_clobbered; }
102
    const RegisterSet& earlyClobbered() const { return m_earlyClobbered; }
103
    const RegisterSet& lateClobbered() const { return m_lateClobbered; }
92
104
93
    void setGenerator(RefPtr<StackmapGenerator> generator)
105
    void setGenerator(RefPtr<StackmapGenerator> generator)
94
    {
106
    {
Lines 189-195 private: Source/JavaScriptCore/b3/B3StackmapValue.h_sec2
189
    
201
    
190
    Vector<ValueRep> m_reps;
202
    Vector<ValueRep> m_reps;
191
    RefPtr<StackmapGenerator> m_generator;
203
    RefPtr<StackmapGenerator> m_generator;
192
    RegisterSet m_clobbered;
204
    RegisterSet m_earlyClobbered;
205
    RegisterSet m_lateClobbered;
193
    RegisterSet m_usedRegisters; // Stackmaps could be further duplicated by Air, but that's unlikely, so we just merge the used registers sets if that were to happen.
206
    RegisterSet m_usedRegisters; // Stackmaps could be further duplicated by Air, but that's unlikely, so we just merge the used registers sets if that were to happen.
194
};
207
};
195
208
- Source/JavaScriptCore/b3/testb3.cpp -4 / +41 lines
Lines 3206-3212 void testSimplePatchpointWithoutOuputClo Source/JavaScriptCore/b3/testb3.cpp_sec1
3206
    Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
3206
    Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
3207
3207
3208
    PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3208
    PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3209
    patchpoint->clobber(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1));
3209
    patchpoint->clobberLate(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1));
3210
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3210
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3211
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3211
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3212
    patchpoint->setGenerator(
3212
    patchpoint->setGenerator(
Lines 3249-3255 void testSimplePatchpointWithOuputClobbe Source/JavaScriptCore/b3/testb3.cpp_sec2
3249
    clobberAll.exclude(RegisterSet::stackRegisters());
3249
    clobberAll.exclude(RegisterSet::stackRegisters());
3250
    clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
3250
    clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
3251
    clobberAll.clear(GPRInfo::argumentGPR2);
3251
    clobberAll.clear(GPRInfo::argumentGPR2);
3252
    patchpoint->clobber(clobberAll);
3252
    patchpoint->clobberLate(clobberAll);
3253
3253
3254
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3254
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3255
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3255
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
Lines 3286-3292 void testSimplePatchpointWithoutOuputClo Source/JavaScriptCore/b3/testb3.cpp_sec3
3286
    Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
3286
    Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
3287
3287
3288
    PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3288
    PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
3289
    patchpoint->clobber(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1));
3289
    patchpoint->clobberLate(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1));
3290
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3290
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3291
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3291
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3292
    patchpoint->setGenerator(
3292
    patchpoint->setGenerator(
Lines 3322-3328 void testSimplePatchpointWithOuputClobbe Source/JavaScriptCore/b3/testb3.cpp_sec4
3322
    clobberAll.exclude(RegisterSet::stackRegisters());
3322
    clobberAll.exclude(RegisterSet::stackRegisters());
3323
    clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
3323
    clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
3324
    clobberAll.clear(FPRInfo::argumentFPR2);
3324
    clobberAll.clear(FPRInfo::argumentFPR2);
3325
    patchpoint->clobber(clobberAll);
3325
    patchpoint->clobberLate(clobberAll);
3326
3326
3327
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3327
    patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
3328
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
3328
    patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
Lines 3348-3353 void testSimplePatchpointWithOuputClobbe Source/JavaScriptCore/b3/testb3.cpp_sec5
3348
    CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
3348
    CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
3349
}
3349
}
3350
3350
3351
void testPatchpointWithEarlyClobber()
3352
{
3353
    auto test = [] (GPRReg registerToClobber, bool arg1InArgGPR, bool arg2InArgGPR) {
3354
        Procedure proc;
3355
        BasicBlock* root = proc.addBlock();
3356
        Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3357
        Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3358
        
3359
        PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
3360
        patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
3361
        patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
3362
        patchpoint->clobberEarly(RegisterSet(registerToClobber));
3363
        patchpoint->setGenerator(
3364
            [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
3365
                CHECK((params.reps[1].gpr() == GPRInfo::argumentGPR0) == arg1InArgGPR);
3366
                CHECK((params.reps[2].gpr() == GPRInfo::argumentGPR1) == arg2InArgGPR);
3367
3368
                if (params.reps[0].gpr() == params.reps[2].gpr()) {
3369
                    jit.move(params.reps[2].gpr(), params.reps[0].gpr());
3370
                    jit.add32(params.reps[1].gpr(), params.reps[0].gpr());
3371
                } else {
3372
                    jit.move(params.reps[1].gpr(), params.reps[0].gpr());
3373
                    jit.add32(params.reps[2].gpr(), params.reps[0].gpr());
3374
                }
3375
            });
3376
3377
        root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint);
3378
3379
        CHECK(compileAndRun<int>(proc, 1, 2) == 3);
3380
    };
3381
3382
    test(GPRInfo::nonArgGPR0, true, true);
3383
    test(GPRInfo::argumentGPR0, false, true);
3384
    test(GPRInfo::argumentGPR1, true, false);
3385
}
3386
3351
void testPatchpointCallArg()
3387
void testPatchpointCallArg()
3352
{
3388
{
3353
    Procedure proc;
3389
    Procedure proc;
Lines 5717-5722 void run(const char* filter) Source/JavaScriptCore/b3/testb3.cpp_sec6
5717
    RUN(testSimplePatchpointWithOuputClobbersGPArgs());
5753
    RUN(testSimplePatchpointWithOuputClobbersGPArgs());
5718
    RUN(testSimplePatchpointWithoutOuputClobbersFPArgs());
5754
    RUN(testSimplePatchpointWithoutOuputClobbersFPArgs());
5719
    RUN(testSimplePatchpointWithOuputClobbersFPArgs());
5755
    RUN(testSimplePatchpointWithOuputClobbersFPArgs());
5756
    RUN(testPatchpointWithEarlyClobber());
5720
    RUN(testPatchpointCallArg());
5757
    RUN(testPatchpointCallArg());
5721
    RUN(testPatchpointFixedRegister());
5758
    RUN(testPatchpointFixedRegister());
5722
    RUN(testPatchpointAny());
5759
    RUN(testPatchpointAny());
- Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp +5 lines
Lines 143-148 const RegisterSet& CCallSpecial::extraCl Source/JavaScriptCore/b3/air/AirCCallSpecial.cpp_sec1
143
    return m_clobberedRegs;
143
    return m_clobberedRegs;
144
}
144
}
145
145
146
const RegisterSet& CCallSpecial::extraEarlyClobberedRegs(Inst&)
147
{
148
    return m_emptyRegs;
149
}
150
146
void CCallSpecial::dumpImpl(PrintStream& out) const
151
void CCallSpecial::dumpImpl(PrintStream& out) const
147
{
152
{
148
    out.print("CCall");
153
    out.print("CCall");
- Source/JavaScriptCore/b3/air/AirCCallSpecial.h +2 lines
Lines 59-64 protected: Source/JavaScriptCore/b3/air/AirCCallSpecial.h_sec1
59
    void reportUsedRegisters(Inst&, const RegisterSet&) override;
59
    void reportUsedRegisters(Inst&, const RegisterSet&) override;
60
    CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&) override;
60
    CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&) override;
61
    const RegisterSet& extraClobberedRegs(Inst&) override;
61
    const RegisterSet& extraClobberedRegs(Inst&) override;
62
    const RegisterSet& extraEarlyClobberedRegs(Inst&) override;
62
63
63
    void dumpImpl(PrintStream&) const override;
64
    void dumpImpl(PrintStream&) const override;
64
    void deepDumpImpl(PrintStream&) const override;
65
    void deepDumpImpl(PrintStream&) const override;
Lines 76-81 private: Source/JavaScriptCore/b3/air/AirCCallSpecial.h_sec2
76
        numSpecialArgs + numCalleeArgs + numReturnGPArgs + numReturnFPArgs;
77
        numSpecialArgs + numCalleeArgs + numReturnGPArgs + numReturnFPArgs;
77
    
78
    
78
    RegisterSet m_clobberedRegs;
79
    RegisterSet m_clobberedRegs;
80
    RegisterSet m_emptyRegs;
79
};
81
};
80
82
81
} } } // namespace JSC::B3::Air
83
} } } // namespace JSC::B3::Air
- Source/JavaScriptCore/b3/air/AirInst.h -2 / +4 lines
Lines 125-134 public: Source/JavaScriptCore/b3/air/AirInst.h_sec1
125
    // Reports any additional registers clobbered by this operation. Note that for efficiency,
125
    // Reports any additional registers clobbered by this operation. Note that for efficiency,
126
    // extraClobberedRegs() only works if hasSpecial() returns true.
126
    // extraClobberedRegs() only works if hasSpecial() returns true.
127
    const RegisterSet& extraClobberedRegs();
127
    const RegisterSet& extraClobberedRegs();
128
    const RegisterSet& extraEarlyClobberedRegs();
128
129
129
    // Iterate over the Defs and the extra clobbered registers.
130
    // Iterate over the Defs and the extra clobbered registers. You must supply the next instruction if
131
    // there is one.
130
    template<typename Functor>
132
    template<typename Functor>
131
    void forEachDefAndExtraClobberedTmp(Arg::Type, const Functor& functor);
133
    void forEachTmpWithExtraClobberedRegs(Inst* nextInst, const Functor& functor);
132
134
133
    // Use this to report which registers are live. This should be done just before codegen. Note
135
    // Use this to report which registers are live. This should be done just before codegen. Note
134
    // that for efficiency, reportUsedRegisters() only works if hasSpecial() returns true.
136
    // that for efficiency, reportUsedRegisters() only works if hasSpecial() returns true.
- Source/JavaScriptCore/b3/air/AirInstInlines.h -16 / +21 lines
Lines 89-112 inline const RegisterSet& Inst::extraClo Source/JavaScriptCore/b3/air/AirInstInlines.h_sec1
89
    return args[0].special()->extraClobberedRegs(*this);
89
    return args[0].special()->extraClobberedRegs(*this);
90
}
90
}
91
91
92
inline const RegisterSet& Inst::extraEarlyClobberedRegs()
93
{
94
    ASSERT(hasSpecial());
95
    return args[0].special()->extraEarlyClobberedRegs(*this);
96
}
97
92
template<typename Functor>
98
template<typename Functor>
93
inline void Inst::forEachDefAndExtraClobberedTmp(Arg::Type type, const Functor& functor)
99
inline void Inst::forEachTmpWithExtraClobberedRegs(Inst* nextInst, const Functor& functor)
94
{
100
{
95
    forEachTmp([&] (Tmp& tmpArg, Arg::Role role, Arg::Type argType) {
101
    forEachTmp(
96
        if (argType == type && Arg::isDef(role))
102
        [&] (Tmp& tmpArg, Arg::Role role, Arg::Type argType) {
97
            functor(tmpArg);
103
            functor(tmpArg, role, argType);
98
    });
104
        });
99
105
100
    if (!hasSpecial())
106
    auto reportReg = [&] (Reg reg) {
101
        return;
107
        functor(Tmp(reg), Arg::Def, reg.isGPR() ? Arg::GP : Arg::FP);
102
108
    };
103
    const RegisterSet& clobberedRegisters = extraClobberedRegs();
109
104
    clobberedRegisters.forEach([functor, type] (Reg reg) {
110
    if (hasSpecial())
105
        if (reg.isGPR() == (type == Arg::GP)) {
111
        extraClobberedRegs().forEach(reportReg);
106
            Tmp registerTmp(reg);
112
107
            functor(registerTmp);
113
    if (nextInst && nextInst->hasSpecial())
108
        }
114
        nextInst->extraEarlyClobberedRegs().forEach(reportReg);
109
    });
110
}
115
}
111
116
112
inline void Inst::reportUsedRegisters(const RegisterSet& usedRegisters)
117
inline void Inst::reportUsedRegisters(const RegisterSet& usedRegisters)
- Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp -22 / +43 lines
Lines 145-164 public: Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp_sec1
145
        m_isOnSelectStack.ensureSize(tmpArraySize);
145
        m_isOnSelectStack.ensureSize(tmpArraySize);
146
    }
146
    }
147
147
148
    void build(Inst& inst, const Liveness<Tmp>::LocalCalc& localCalc)
148
    void build(Inst& inst, Inst* nextInst, const Liveness<Tmp>::LocalCalc& localCalc)
149
    {
149
    {
150
        inst.forEachDefAndExtraClobberedTmp(type, [&] (Tmp& arg) {
150
        inst.forEachTmpWithExtraClobberedRegs(
151
            // All the Def()s interfere with each other and with all the extra clobbered Tmps.
151
            nextInst,
152
            // We should not use forEachDefAndExtraClobberedTmp() here since colored Tmps
152
            [&] (const Tmp& arg, Arg::Role role, Arg::Type argType) {
153
            // do not need interference edges in our implementation.
153
                if (!Arg::isDef(role) || argType != type)
154
            inst.forEachTmp([&] (Tmp& otherArg, Arg::Role role, Arg::Type otherArgType) {
155
                if (otherArgType != type)
156
                    return;
154
                    return;
157
155
                
158
                if (Arg::isDef(role))
156
                // All the Def()s interfere with each other and with all the extra clobbered Tmps.
159
                    addEdge(arg, otherArg);
157
                // We should not use forEachDefAndExtraClobberedTmp() here since colored Tmps
158
                // do not need interference edges in our implementation.
159
                inst.forEachTmp([&] (Tmp& otherArg, Arg::Role role, Arg::Type argType) {
160
                        if (!Arg::isDef(role) || argType != type)
161
                            return;
162
                        
163
                        addEdge(arg, otherArg);
164
                    });
160
            });
165
            });
161
        });
162
166
163
        if (MoveInstHelper<type>::mayBeCoalescable(inst)) {
167
        if (MoveInstHelper<type>::mayBeCoalescable(inst)) {
164
            // We do not want the Use() of this move to interfere with the Def(), even if it is live
168
            // We do not want the Use() of this move to interfere with the Def(), even if it is live
Lines 195-202 public: Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp_sec2
195
                if (liveTmp != useTmp && liveTmp.isGP() == (type == Arg::GP))
199
                if (liveTmp != useTmp && liveTmp.isGP() == (type == Arg::GP))
196
                    addEdge(defTmp, liveTmp);
200
                    addEdge(defTmp, liveTmp);
197
            }
201
            }
202
203
            // The next instruction could have early clobbers. We need to consider those now.
204
            if (nextInst && nextInst->hasSpecial()) {
205
                nextInst->extraEarlyClobberedRegs().forEach(
206
                    [&] (Reg reg) {
207
                        for (const Tmp& liveTmp : localCalc.live()) {
208
                            addEdge(Tmp(reg), liveTmp);
209
                        }
210
                    });
211
            }
198
        } else
212
        } else
199
            addEdges(inst, localCalc.live());
213
            addEdges(inst, nextInst, localCalc.live());
200
    }
214
    }
201
215
202
    void allocate()
216
    void allocate()
Lines 296-310 private: Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp_sec3
296
        bzero(m_degrees.data() + firstNonRegIndex, (tmpArraySize - firstNonRegIndex) * sizeof(unsigned));
310
        bzero(m_degrees.data() + firstNonRegIndex, (tmpArraySize - firstNonRegIndex) * sizeof(unsigned));
297
    }
311
    }
298
312
299
    void addEdges(Inst& inst, const HashSet<Tmp>& liveTmp)
313
    void addEdges(Inst& inst, Inst* nextInst, const HashSet<Tmp>& liveTmp)
300
    {
314
    {
301
        // All the Def()s interfere with everthing live.
315
        // All the Def()s interfere with everthing live.
302
        inst.forEachDefAndExtraClobberedTmp(type, [&] (Tmp& arg) {
316
        inst.forEachTmpWithExtraClobberedRegs(
303
            for (const Tmp& liveTmp : liveTmp) {
317
            nextInst,
304
                if (liveTmp.isGP() == (type == Arg::GP))
318
            [&] (const Tmp& arg, Arg::Role role, Arg::Type argType) {
305
                    addEdge(arg, liveTmp);
319
                if (!Arg::isDef(role) || argType != type)
306
            }
320
                    return;
307
        });
321
                
322
                for (const Tmp& liveTmp : liveTmp) {
323
                    if (liveTmp.isGP() == (type == Arg::GP))
324
                        addEdge(arg, liveTmp);
325
                }
326
            });
308
    }
327
    }
309
328
310
    void addEdge(const Tmp& a, const Tmp& b)
329
    void addEdge(const Tmp& a, const Tmp& b)
Lines 1030-1036 static void iteratedRegisterCoalescingOn Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp_sec4
1030
            Liveness<Tmp>::LocalCalc localCalc(liveness, block);
1049
            Liveness<Tmp>::LocalCalc localCalc(liveness, block);
1031
            for (unsigned instIndex = block->size(); instIndex--;) {
1050
            for (unsigned instIndex = block->size(); instIndex--;) {
1032
                Inst& inst = block->at(instIndex);
1051
                Inst& inst = block->at(instIndex);
1033
                allocator.build(inst, localCalc);
1052
                Inst* nextInst = instIndex + 1 < block->size() ? &block->at(instIndex + 1) : nullptr;
1053
                allocator.build(inst, nextInst, localCalc);
1034
                localCalc.execute(instIndex);
1054
                localCalc.execute(instIndex);
1035
            }
1055
            }
1036
        }
1056
        }
Lines 1068-1076 void iteratedRegisterCoalescing(Code& co Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp_sec5
1068
            Liveness<Tmp>::LocalCalc localCalc(liveness, block);
1088
            Liveness<Tmp>::LocalCalc localCalc(liveness, block);
1069
            for (unsigned instIndex = block->size(); instIndex--;) {
1089
            for (unsigned instIndex = block->size(); instIndex--;) {
1070
                Inst& inst = block->at(instIndex);
1090
                Inst& inst = block->at(instIndex);
1091
                Inst* nextInst = instIndex + 1 < block->size() ? &block->at(instIndex + 1) : nullptr;
1071
1092
1072
                gpAllocator.build(inst, localCalc);
1093
                gpAllocator.build(inst, nextInst, localCalc);
1073
                fpAllocator.build(inst, localCalc);
1094
                fpAllocator.build(inst, nextInst, localCalc);
1074
1095
1075
                localCalc.execute(instIndex);
1096
                localCalc.execute(instIndex);
1076
            }
1097
            }
- Source/JavaScriptCore/b3/air/AirSpecial.h +1 lines
Lines 84-89 public: Source/JavaScriptCore/b3/air/AirSpecial.h_sec1
84
    virtual CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&) = 0;
84
    virtual CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&) = 0;
85
85
86
    virtual const RegisterSet& extraClobberedRegs(Inst&) = 0;
86
    virtual const RegisterSet& extraClobberedRegs(Inst&) = 0;
87
    virtual const RegisterSet& extraEarlyClobberedRegs(Inst&) = 0;
87
88
88
    // By default, this returns true.
89
    // By default, this returns true.
89
    virtual bool hasNonArgNonControlEffects();
90
    virtual bool hasNonArgNonControlEffects();
- Source/JavaScriptCore/b3/air/AirSpillEverything.cpp -6 / +6 lines
Lines 58-69 void spillEverything(Code& code) Source/JavaScriptCore/b3/air/AirSpillEverything.cpp_sec1
58
58
59
            // Gotta account for dead assignments to registers. These may happen because the input
59
            // Gotta account for dead assignments to registers. These may happen because the input
60
            // code is suboptimal.
60
            // code is suboptimal.
61
            auto updateRegisterSet = [&registerSet] (const Tmp& tmp) {
61
            inst.forEachTmpWithExtraClobberedRegs(
62
                if (tmp.isReg())
62
                index < block->size() ? &block->at(index) : nullptr,
63
                    registerSet.set(tmp.reg());
63
                [&registerSet] (const Tmp& tmp, Arg::Role role, Arg::Type) {
64
            };
64
                    if (tmp.isReg() && Arg::isDef(role))
65
            inst.forEachDefAndExtraClobberedTmp(Arg::GP, updateRegisterSet);
65
                        registerSet.set(tmp.reg());
66
            inst.forEachDefAndExtraClobberedTmp(Arg::FP, updateRegisterSet);
66
                });
67
        };
67
        };
68
68
69
        for (unsigned instIndex = block->size(); instIndex--;) {
69
        for (unsigned instIndex = block->size(); instIndex--;) {
- Source/JavaScriptCore/dfg/DFGCommon.h -1 / +1 lines
Lines 38-44 namespace JSC { namespace DFG { Source/JavaScriptCore/dfg/DFGCommon.h_sec1
38
// We are in the middle of an experimental transition from LLVM to B3 as the backend for the FTL. We don't
38
// We are in the middle of an experimental transition from LLVM to B3 as the backend for the FTL. We don't
39
// yet know how it will turn out. For now, this flag will control whether FTL uses B3. Remember to set this
39
// yet know how it will turn out. For now, this flag will control whether FTL uses B3. Remember to set this
40
// to 0 before committing!
40
// to 0 before committing!
41
#define FTL_USES_B3 1
41
#define FTL_USES_B3 0
42
42
43
struct Node;
43
struct Node;
44
44

Return to Bug 151668