- Source/JavaScriptCore/ChangeLog +30 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2013-06-26  Filip Pizlo  <fpizlo@apple.com>
2
3
        fourthTier: FTL should support hole/OOB PutByVal's
4
        https://bugs.webkit.org/show_bug.cgi?id=118112
5
6
        Reviewed by NOBODY (OOPS!).
7
        
8
        Added a common code generator the out-of-bounds case that is reused by all
9
        contiguous-like arrays (Int32, Double, Contiguous).
10
        
11
        This is relatively straight-forward, except that it's the first time that
12
        the FTL has to call DFG operations that take more than two arguments.
13
14
        * ftl/FTLAbbreviations.h:
15
        (JSC::FTL::functionType):
16
        (JSC::FTL::buildCall):
17
        * ftl/FTLAbstractHeapRepository.h:
18
        (FTL):
19
        * ftl/FTLCapabilities.cpp:
20
        (JSC::FTL::canCompile):
21
        * ftl/FTLIntrinsicRepository.h:
22
        (FTL):
23
        * ftl/FTLLowerDFGToLLVM.cpp:
24
        (JSC::FTL::LowerDFGToLLVM::compilePutByVal):
25
        (LowerDFGToLLVM):
26
        (JSC::FTL::LowerDFGToLLVM::contiguousPutByValOutOfBounds):
27
        (JSC::FTL::LowerDFGToLLVM::vmCall):
28
        * ftl/FTLOutput.h:
29
        (JSC::FTL::Output::call):
30
1
2013-06-26  Filip Pizlo  <fpizlo@apple.com>
31
2013-06-26  Filip Pizlo  <fpizlo@apple.com>
2
32
3
        fourthTier: FTL::canCompile(Graph&) should not consider nodes that won't be compiled
33
        fourthTier: FTL::canCompile(Graph&) should not consider nodes that won't be compiled
- Source/JavaScriptCore/ftl/FTLAbbreviations.h +20 lines
Lines 98-103 static inline LType functionType(LType r Source/JavaScriptCore/ftl/FTLAbbreviations.h_sec1
98
    LType paramTypes[] = { param1, param2 };
98
    LType paramTypes[] = { param1, param2 };
99
    return functionType(returnType, paramTypes, 2, variadicity);
99
    return functionType(returnType, paramTypes, 2, variadicity);
100
}
100
}
101
static inline LType functionType(LType returnType, LType param1, LType param2, LType param3, Variadicity variadicity = NotVariadic)
102
{
103
    LType paramTypes[] = { param1, param2, param3 };
104
    return functionType(returnType, paramTypes, 3, variadicity);
105
}
106
static inline LType functionType(LType returnType, LType param1, LType param2, LType param3, LType param4, Variadicity variadicity = NotVariadic)
107
{
108
    LType paramTypes[] = { param1, param2, param3, param4 };
109
    return functionType(returnType, paramTypes, 4, variadicity);
110
}
101
111
102
static inline LType typeOf(LValue value) { return LLVMTypeOf(value); }
112
static inline LType typeOf(LValue value) { return LLVMTypeOf(value); }
103
113
Lines 222-227 static inline LValue buildCall(LBuilder Source/JavaScriptCore/ftl/FTLAbbreviations.h_sec2
222
    LValue args[] = { arg1, arg2 };
232
    LValue args[] = { arg1, arg2 };
223
    return buildCall(builder, function, args, 2);
233
    return buildCall(builder, function, args, 2);
224
}
234
}
235
static inline LValue buildCall(LBuilder builder, LValue function, LValue arg1, LValue arg2, LValue arg3)
236
{
237
    LValue args[] = { arg1, arg2, arg3 };
238
    return buildCall(builder, function, args, 3);
239
}
240
static inline LValue buildCall(LBuilder builder, LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4)
241
{
242
    LValue args[] = { arg1, arg2, arg3, arg4 };
243
    return buildCall(builder, function, args, 4);
244
}
225
enum TailCallMode { IsNotTailCall, IsTailCall };
245
enum TailCallMode { IsNotTailCall, IsTailCall };
226
static inline void setTailCall(LValue call, TailCallMode mode) { LLVMSetTailCall(call, mode == IsTailCall); }
246
static inline void setTailCall(LValue call, TailCallMode mode) { LLVMSetTailCall(call, mode == IsTailCall); }
227
static inline LValue buildExtractValue(LBuilder builder, LValue aggVal, unsigned index) { return LLVMBuildExtractValue(builder, aggVal, index, ""); }
247
static inline LValue buildExtractValue(LBuilder builder, LValue aggVal, unsigned index) { return LLVMBuildExtractValue(builder, aggVal, index, ""); }
- Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h +1 lines
Lines 40-45 namespace JSC { namespace FTL { Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h_sec1
40
40
41
#define FOR_EACH_ABSTRACT_FIELD(macro) \
41
#define FOR_EACH_ABSTRACT_FIELD(macro) \
42
    macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
42
    macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
43
    macro(Butterfly_vectorLength, Butterfly::offsetOfVectorLength()) \
43
    macro(JSCell_structure, JSCell::structureOffset()) \
44
    macro(JSCell_structure, JSCell::structureOffset()) \
44
    macro(JSObject_butterfly, JSObject::butterflyOffset()) \
45
    macro(JSObject_butterfly, JSObject::butterflyOffset()) \
45
    macro(JSString_length, JSString::offsetOfLength()) \
46
    macro(JSString_length, JSString::offsetOfLength()) \
- Source/JavaScriptCore/ftl/FTLCapabilities.cpp -7 lines
Lines 125-137 inline bool canCompile(Node* node) Source/JavaScriptCore/ftl/FTLCapabilities.cpp_sec1
125
        default:
125
        default:
126
            return false;
126
            return false;
127
        }
127
        }
128
        switch (node->arrayMode().speculation()) {
129
        case Array::SaneChain:
130
        case Array::InBounds:
131
            break;
132
        default:
133
            return false;
134
        }
135
        break;
128
        break;
136
    case CompareEq:
129
    case CompareEq:
137
    case CompareStrictEq:
130
    case CompareStrictEq:
- Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h -1 / +3 lines
Lines 44-50 namespace JSC { namespace FTL { Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h_sec1
44
44
45
#define FOR_EACH_FUNCTION_TYPE(macro) \
45
#define FOR_EACH_FUNCTION_TYPE(macro) \
46
    macro(I_DFGOperation_EJss, functionType(intPtr, intPtr, intPtr)) \
46
    macro(I_DFGOperation_EJss, functionType(intPtr, intPtr, intPtr)) \
47
    macro(P_DFGOperation_EC, functionType(intPtr, intPtr, intPtr))
47
    macro(P_DFGOperation_EC, functionType(intPtr, intPtr, intPtr)) \
48
    macro(V_DFGOperation_EOZD, functionType(voidType, intPtr, intPtr, int32, doubleType)) \
49
    macro(V_DFGOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64))
48
50
49
class IntrinsicRepository : public CommonValues {
51
class IntrinsicRepository : public CommonValues {
50
public:
52
public:
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -25 / +89 lines
Lines 1311-1319 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
1311
        Edge child3 = m_graph.varArgChild(m_node, 2);
1311
        Edge child3 = m_graph.varArgChild(m_node, 2);
1312
        Edge child4 = m_graph.varArgChild(m_node, 3);
1312
        Edge child4 = m_graph.varArgChild(m_node, 3);
1313
1313
1314
        LValue base = lowCell(child1);
1314
        LValue index = lowInt32(child2);
1315
        LValue index = lowInt32(child2);
1315
        LValue storage = lowStorage(child4);
1316
        LValue storage = lowStorage(child4);
1316
        
1317
        
1318
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
1319
        LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
1320
            
1317
        switch (m_node->arrayMode().type()) {
1321
        switch (m_node->arrayMode().type()) {
1318
        case Array::Int32:
1322
        case Array::Int32:
1319
        case Array::Contiguous: {
1323
        case Array::Contiguous: {
Lines 1330-1351 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
1330
            
1334
            
1331
            if (m_node->op() == PutByValAlias) {
1335
            if (m_node->op() == PutByValAlias) {
1332
                m_out.store64(value, elementPointer);
1336
                m_out.store64(value, elementPointer);
1333
                return;
1337
                break;
1334
            }
1338
            }
1335
            
1339
            
1336
            if (m_node->arrayMode().isInBounds()) {
1340
            contiguousPutByValOutOfBounds(
1337
                speculate(
1341
                codeBlock()->isStrictMode()
1338
                    StoreToHoleOrOutOfBounds, noValue(), 0,
1342
                    ? operationPutByValBeyondArrayBoundsStrict
1339
                    m_out.aboveOrEqual(
1343
                    : operationPutByValBeyondArrayBoundsNonStrict,
1340
                        index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1344
                base, storage, index, value, continuation);
1341
            } else {
1342
                // FIXME: Implement hole/OOB stores in the FTL.
1343
                // https://bugs.webkit.org/show_bug.cgi?id=118077
1344
                RELEASE_ASSERT_NOT_REACHED();
1345
            }
1346
            
1345
            
1347
            m_out.store64(value, elementPointer);
1346
            m_out.store64(value, elementPointer);
1348
            return;
1347
            break;
1349
        }
1348
        }
1350
            
1349
            
1351
        case Array::Double: {
1350
        case Array::Double: {
Lines 1362-1389 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
1362
1361
1363
            if (m_node->op() == PutByValAlias) {
1362
            if (m_node->op() == PutByValAlias) {
1364
                m_out.storeDouble(value, elementPointer);
1363
                m_out.storeDouble(value, elementPointer);
1365
                return;
1364
                break;
1366
            }
1365
            }
1367
            
1366
            
1368
            if (m_node->arrayMode().isInBounds()) {
1367
            contiguousPutByValOutOfBounds(
1369
                speculate(
1368
                codeBlock()->isStrictMode()
1370
                    StoreToHoleOrOutOfBounds, noValue(), 0,
1369
                    ? operationPutDoubleByValBeyondArrayBoundsStrict
1371
                    m_out.aboveOrEqual(
1370
                    : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1372
                        index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1371
                base, storage, index, value, continuation);
1373
            } else {
1374
                // FIXME: Implement hole/OOB stores in the FTL.
1375
                // https://bugs.webkit.org/show_bug.cgi?id=118077
1376
                RELEASE_ASSERT_NOT_REACHED();
1377
            }
1378
            
1372
            
1379
            m_out.storeDouble(value, elementPointer);
1373
            m_out.storeDouble(value, elementPointer);
1380
            return;
1374
            break;
1381
        }
1375
        }
1382
            
1376
            
1383
        default:
1377
        default:
1384
            RELEASE_ASSERT_NOT_REACHED();
1378
            RELEASE_ASSERT_NOT_REACHED();
1385
            return;
1379
            break;
1386
        }
1380
        }
1381
1382
        m_out.jump(continuation);
1383
        m_out.appendTo(continuation, outerLastNext);
1387
    }
1384
    }
1388
    
1385
    
1389
    void compileGetByOffset()
1386
    void compileGetByOffset()
Lines 1868-1873 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
1868
        return m_out.phi(m_out.boolean, results);
1865
        return m_out.phi(m_out.boolean, results);
1869
    }
1866
    }
1870
    
1867
    
1868
    template<typename FunctionType>
1869
    void contiguousPutByValOutOfBounds(
1870
        FunctionType slowPathFunction,
1871
        LValue base, LValue storage, LValue index, LValue value,
1872
        LBasicBlock continuation)
1873
    {
1874
        LValue isNotInBounds = m_out.aboveOrEqual(
1875
            index, m_out.load32(storage, m_heaps.Butterfly_publicLength));
1876
        if (m_node->arrayMode().isInBounds())
1877
            speculate(StoreToHoleOrOutOfBounds, noValue(), 0, isNotInBounds);
1878
        else {
1879
            LBasicBlock notInBoundsCase =
1880
                FTL_NEW_BLOCK(m_out, ("PutByVal not in bounds"));
1881
            LBasicBlock performStore =
1882
                FTL_NEW_BLOCK(m_out, ("PutByVal perform store"));
1883
                
1884
            m_out.branch(isNotInBounds, notInBoundsCase, performStore);
1885
                
1886
            LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
1887
                
1888
            LValue isOutOfBounds = m_out.aboveOrEqual(
1889
                index, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
1890
                
1891
            if (!m_node->arrayMode().isOutOfBounds())
1892
                speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
1893
            else {
1894
                LBasicBlock outOfBoundsCase =
1895
                    FTL_NEW_BLOCK(m_out, ("PutByVal out of bounds"));
1896
                LBasicBlock holeCase =
1897
                    FTL_NEW_BLOCK(m_out, ("PutByVal hole case"));
1898
                    
1899
                m_out.branch(isOutOfBounds, outOfBoundsCase, holeCase);
1900
                    
1901
                LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase);
1902
                    
1903
                vmCall(
1904
                    m_out.operation(slowPathFunction),
1905
                    m_callFrame, base, index, value);
1906
                    
1907
                m_out.jump(continuation);
1908
                    
1909
                m_out.appendTo(holeCase, innerLastNext);
1910
            }
1911
            
1912
            m_out.store32(
1913
                m_out.add(index, m_out.int32One),
1914
                storage, m_heaps.Butterfly_publicLength);
1915
                
1916
            m_out.jump(performStore);
1917
            m_out.appendTo(performStore, lastNext);
1918
        }
1919
    }
1920
    
1871
    void buildSwitch(SwitchData* data, LType type, LValue switchValue)
1921
    void buildSwitch(SwitchData* data, LType type, LValue switchValue)
1872
    {
1922
    {
1873
        Vector<SwitchCase> cases;
1923
        Vector<SwitchCase> cases;
Lines 2331-2336 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
2331
        callCheck(mode);
2381
        callCheck(mode);
2332
        return result;
2382
        return result;
2333
    }
2383
    }
2384
    LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, ExceptionCheckMode mode = CheckExceptions)
2385
    {
2386
        callPreflight();
2387
        LValue result = m_out.call(function, arg1, arg2, arg3);
2388
        callCheck(mode);
2389
        return result;
2390
    }
2391
    LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, ExceptionCheckMode mode = CheckExceptions)
2392
    {
2393
        callPreflight();
2394
        LValue result = m_out.call(function, arg1, arg2, arg3, arg4);
2395
        callCheck(mode);
2396
        return result;
2397
    }
2334
    
2398
    
2335
    void callPreflight(CodeOrigin codeOrigin)
2399
    void callPreflight(CodeOrigin codeOrigin)
2336
    {
2400
    {
- Source/JavaScriptCore/ftl/FTLOutput.h +2 lines
Lines 324-329 public: Source/JavaScriptCore/ftl/FTLOutput.h_sec1
324
    LValue call(LValue function) { return buildCall(m_builder, function); }
324
    LValue call(LValue function) { return buildCall(m_builder, function); }
325
    LValue call(LValue function, LValue arg1) { return buildCall(m_builder, function, arg1); }
325
    LValue call(LValue function, LValue arg1) { return buildCall(m_builder, function, arg1); }
326
    LValue call(LValue function, LValue arg1, LValue arg2) { return buildCall(m_builder, function, arg1, arg2); }
326
    LValue call(LValue function, LValue arg1, LValue arg2) { return buildCall(m_builder, function, arg1, arg2); }
327
    LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3) { return buildCall(m_builder, function, arg1, arg2, arg3); }
328
    LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4); }
327
    
329
    
328
    template<typename FunctionType>
330
    template<typename FunctionType>
329
    LValue operation(FunctionType function)
331
    LValue operation(FunctionType function)

Return to Bug 118112