Title: [170736] branches/ftlopt/Source/_javascript_Core

Diff

Modified: branches/ftlopt/Source/_javascript_Core/ChangeLog (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ChangeLog	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ChangeLog	2014-07-02 23:41:08 UTC (rev 170736)
@@ -271,6 +271,36 @@
         (foo):
         (test):
 
+2014-07-01  Matthew Mirman  <mmir...@apple.com>
+
+        Added an implementation of the "in" check to FTL.
+        https://bugs.webkit.org/show_bug.cgi?id=134508
+
+        Reviewed by Filip Pizlo.
+
+        * ftl/FTLCapabilities.cpp: enabled compilation for "in"
+        (JSC::FTL::canCompile): ditto
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::generateCheckInICFastPath): added.
+        (JSC::FTL::fixFunctionBasedOnStackMaps): added case for CheckIn descriptors.
+        * ftl/FTLInlineCacheDescriptor.h:
+        (JSC::FTL::CheckInGenerator::CheckInGenerator): added.
+        (JSC::FTL::CheckInDescriptor::CheckInDescriptor): added.
+        * ftl/FTLInlineCacheSize.cpp: 
+        (JSC::FTL::sizeOfCheckIn): added. Currently larger than necessary.
+        * ftl/FTLInlineCacheSize.h: ditto
+        * ftl/FTLIntrinsicRepository.h: Added function type for operationInGeneric
+        * ftl/FTLLowerDFGToLLVM.cpp: 
+        (JSC::FTL::LowerDFGToLLVM::compileNode): added case for In.
+        (JSC::FTL::LowerDFGToLLVM::compileIn): added.
+        * ftl/FTLSlowPathCall.cpp: Added a callOperation for operationIn
+        (JSC::FTL::callOperation): ditto
+        * ftl/FTLSlowPathCall.h: ditto
+        * ftl/FTLState.h: Added a vector to hold CheckIn descriptors.
+        * jit/JITOperations.h: made operationIns internal.
+        * tests/stress/ftl-checkin.js: Added.
+        * tests/stress/ftl-checkin-variable.js: Added.
+
 2014-06-30  Mark Hahnenberg  <mhahnenb...@apple.com>
 
         Merge r169121 from trunk.

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLCapabilities.cpp (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2014-07-02 23:41:08 UTC (rev 170736)
@@ -165,6 +165,10 @@
         // case because it would prevent us from catching bugs where the FTL backend
         // pipeline failed to optimize out an Identity.
         break;
+    case In:
+        if (node->child2().useKind() == CellUse)
+            break;
+        return CannotCompile;
     case PutByIdDirect:
     case PutById:
         if (node->child1().useKind() == CellUse)

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLCompile.cpp (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLCompile.cpp	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLCompile.cpp	2014-07-02 23:41:08 UTC (rev 170736)
@@ -166,6 +166,68 @@
     }
 }
 
+static void generateCheckInICFastPath(
+    State& state, CodeBlock* codeBlock, GeneratedFunction generatedFunction,
+    StackMaps::RecordMap& recordMap, CheckInDescriptor& ic, size_t sizeOfIC)
+{
+    VM& vm = state.graph.m_vm;
+
+    StackMaps::RecordMap::iterator iter = recordMap.find(ic.stackmapID());
+    if (iter == recordMap.end()) {
+        // It was optimized out.
+        return;
+    }
+    
+    Vector<StackMaps::Record>& records = iter->value;
+    
+    RELEASE_ASSERT(records.size() == ic.m_generators.size());
+
+    for (unsigned i = records.size(); i--;) {
+        StackMaps::Record& record = records[i];
+        auto generator = ic.m_generators[i];
+
+        StructureStubInfo& stubInfo = *generator.m_stub;
+        auto call = generator.m_slowCall;
+        auto slowPathBegin = generator.m_beginLabel;
+
+        CCallHelpers fastPathJIT(&vm, codeBlock);
+        
+        auto jump = fastPathJIT.patchableJump();
+        auto done = fastPathJIT.label();
+
+        char* startOfIC =
+            bitwise_cast<char*>(generatedFunction) + record.instructionOffset;
+        
+        LinkBuffer fastPath(vm, &fastPathJIT, startOfIC, sizeOfIC);
+        LinkBuffer& slowPath = *state.finalizer->sideCodeLinkBuffer;
+        // Note: we could handle the !isValid() case. We just don't appear to have a
+        // reason to do so, yet.
+        RELEASE_ASSERT(fastPath.isValid());
+
+        MacroAssembler::AssemblerType_T::fillNops(
+            startOfIC + fastPath.size(), sizeOfIC - fastPath.size());
+        
+        state.finalizer->sideCodeLinkBuffer->link(
+            ic.m_slowPathDone[i], CodeLocationLabel(startOfIC + sizeOfIC));
+        
+        CodeLocationLabel slowPathBeginLoc = slowPath.locationOf(slowPathBegin);
+        fastPath.link(jump, slowPathBeginLoc);
+
+        CodeLocationCall callReturnLocation = fastPath.locationOf(call);
+
+        stubInfo.patch.deltaCallToDone = MacroAssembler::differenceBetweenCodePtr(
+            callReturnLocation, fastPath.locationOf(done));
+
+        stubInfo.patch.deltaCallToJump = MacroAssembler::differenceBetweenCodePtr(
+            callReturnLocation, fastPath.locationOf(jump));
+        stubInfo.callReturnLocation = callReturnLocation;
+        stubInfo.patch.deltaCallToSlowCase = MacroAssembler::differenceBetweenCodePtr(
+            callReturnLocation, slowPathBeginLoc);
+        
+    }
+}
+
+
 static RegisterSet usedRegistersFor(const StackMaps::Record& record)
 {
     if (Options::assumeAllRegsInFTLICAreLive())
@@ -290,7 +352,7 @@
         state.finalizer->exitThunksLinkBuffer = linkBuffer.release();
     }
 
-    if (!state.getByIds.isEmpty() || !state.putByIds.isEmpty()) {
+    if (!state.getByIds.isEmpty() || !state.putByIds.isEmpty() || !state.checkIns.isEmpty()) {
         CCallHelpers slowPathJIT(&vm, codeBlock);
         
         CCallHelpers::JumpList exceptionTarget;
@@ -320,13 +382,13 @@
                     JSValueRegs(result), NeedToSpill);
                 
                 MacroAssembler::Label begin = slowPathJIT.label();
-                
+
                 MacroAssembler::Call call = callOperation(
                     state, usedRegisters, slowPathJIT, getById.codeOrigin(), &exceptionTarget,
                     operationGetByIdOptimize, result, gen.stubInfo(), base, getById.uid());
-                
+
                 gen.reportSlowPathCall(begin, call);
-                
+
                 getById.m_slowPathDone.append(slowPathJIT.jump());
                 getById.m_generators.append(gen);
             }
@@ -369,6 +431,44 @@
                 putById.m_generators.append(gen);
             }
         }
+
+
+        for (unsigned i = state.checkIns.size(); i--;) {
+            CheckInDescriptor& checkIn = state.checkIns[i];
+            
+            if (verboseCompilationEnabled())
+                dataLog("Handling checkIn stackmap #", checkIn.stackmapID(), "\n");
+            
+            iter = recordMap.find(checkIn.stackmapID());
+            if (iter == recordMap.end()) {
+                // It was optimized out.
+                continue;
+            }
+            
+            for (unsigned i = 0; i < iter->value.size(); ++i) {
+                StackMaps::Record& record = iter->value[i];
+                RegisterSet usedRegisters = usedRegistersFor(record);
+                GPRReg result = record.locations[0].directGPR();
+                GPRReg obj = record.locations[1].directGPR();
+                StructureStubInfo* stubInfo = codeBlock->addStubInfo(); 
+                stubInfo->codeOrigin = checkIn.codeOrigin();
+                stubInfo->patch.baseGPR = static_cast<int8_t>(obj);
+                stubInfo->patch.valueGPR = static_cast<int8_t>(result);
+                stubInfo->patch.usedRegisters = usedRegisters;
+                stubInfo->patch.spillMode = NeedToSpill;
+
+                MacroAssembler::Label begin = slowPathJIT.label();
+
+                MacroAssembler::Call slowCall = callOperation(
+                    state, usedRegisters, slowPathJIT, checkIn.codeOrigin(), &exceptionTarget,
+                    operationInOptimize, result, stubInfo, obj, checkIn.m_id);
+
+                checkIn.m_slowPathDone.append(slowPathJIT.jump());
+                
+                checkIn.m_generators.append(CheckInGenerator(stubInfo, slowCall, begin));
+            }
+        }
+
         
         exceptionTarget.link(&slowPathJIT);
         MacroAssembler::Jump exceptionJump = slowPathJIT.jump();
@@ -388,6 +488,12 @@
                 state, codeBlock, generatedFunction, recordMap, state.putByIds[i],
                 sizeOfPutById());
         }
+
+        for (unsigned i = state.checkIns.size(); i--;) {
+            generateCheckInICFastPath(
+                state, codeBlock, generatedFunction, recordMap, state.checkIns[i],
+                sizeOfCheckIn()); 
+        } 
     }
     
     // Handling JS calls is weird: we need to ensure that we sort them by the PC in LLVM

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h	2014-07-02 23:41:08 UTC (rev 170736)
@@ -94,6 +94,35 @@
     PutKind m_putKind;
 };
 
+struct CheckInGenerator {
+    StructureStubInfo* m_stub;
+    MacroAssembler::Call m_slowCall;
+    MacroAssembler::Label m_beginLabel;
+
+    CheckInGenerator(StructureStubInfo* stub, MacroAssembler::Call slowCall, MacroAssembler::Label beginLabel)
+        : m_stub(stub) 
+        , m_slowCall(slowCall)
+        , m_beginLabel(beginLabel)
+    {
+    }
+};
+
+class CheckInDescriptor : public InlineCacheDescriptor {
+public:
+    CheckInDescriptor() { }
+    
+    CheckInDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const StringImpl* id)
+        : InlineCacheDescriptor(stackmapID, codeOrigin, nullptr)
+        , m_id(id)
+    {
+    }
+
+    
+    const StringImpl* m_id;
+    Vector<CheckInGenerator> m_generators;
+};
+
+
 } } // namespace JSC::FTL
 
 #endif // ENABLE(FTL_JIT)

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp	2014-07-02 23:41:08 UTC (rev 170736)
@@ -61,6 +61,16 @@
 #endif
 }
 
+size_t sizeOfCheckIn()
+{
+#if CPU(ARM64)
+    return 4;
+#else
+    return 5; 
+#endif
+}
+
+
 size_t sizeOfCall()
 {
 #if CPU(ARM64)

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheSize.h (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheSize.h	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLInlineCacheSize.h	2014-07-02 23:41:08 UTC (rev 170736)
@@ -33,6 +33,7 @@
 size_t sizeOfGetById();
 size_t sizeOfPutById();
 size_t sizeOfCall();
+size_t sizeOfCheckIn();
 
 } } // namespace JSC::FTL
 

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2014-07-02 23:41:08 UTC (rev 170736)
@@ -63,6 +63,7 @@
     macro(J_JITOperation_E, functionType(int64, intPtr)) \
     macro(J_JITOperation_EA, functionType(int64, intPtr, intPtr)) \
     macro(J_JITOperation_EAZ, functionType(int64, intPtr, intPtr, int32)) \
+    macro(J_JITOperation_ECJ, functionType(int64, intPtr, intPtr, int64)) \
     macro(J_JITOperation_EDA, functionType(int64, intPtr, doubleType, intPtr)) \
     macro(J_JITOperation_EJ, functionType(int64, intPtr, int64)) \
     macro(J_JITOperation_EJA, functionType(int64, intPtr, int64, intPtr)) \

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2014-07-02 23:41:08 UTC (rev 170736)
@@ -478,6 +478,9 @@
             compileGetById();
             break;
         case PutByIdDirect:
+        case In:
+            compileIn();
+            break;
         case PutById:
             compilePutById();
             break;
@@ -3930,6 +3933,33 @@
         setBoolean(m_out.notNull(pointerResult));
     }
     
+    void compileIn()
+    {
+        Edge base = m_node->child2();
+        LValue cell = lowCell(base);
+        speculateObject(base, cell);
+        if (JSString* string = m_node->child1()->dynamicCastConstant<JSString*>()) {
+            if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
+
+                const StringImpl* str = string->tryGetValueImpl();
+                unsigned stackmapID = m_stackmapIDs++;
+            
+                LValue call = m_out.call(
+                    m_out.patchpointInt64Intrinsic(),
+                    m_out.constInt64(stackmapID), m_out.constInt32(sizeOfCheckIn()),
+                    constNull(m_out.ref8), m_out.constInt32(1), cell);
+
+                setInstructionCallingConvention(call, LLVMAnyRegCallConv);
+
+                m_ftlState.checkIns.append(CheckInDescriptor(stackmapID, m_node->origin.semantic, str));
+                setJSValue(call);
+                return;
+            }
+        } 
+
+        setJSValue(vmCall(m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1())));
+    }
+
     void compileCheckHasInstance()
     {
         speculate(

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLSlowPathCall.cpp (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLSlowPathCall.cpp	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLSlowPathCall.cpp	2014-07-02 23:41:08 UTC (rev 170736)
@@ -176,6 +176,19 @@
 MacroAssembler::Call callOperation(
     State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
     CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
+    J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo,
+    GPRReg object, const StringImpl* uid)
+{
+    storeCodeOrigin(state, jit, codeOrigin);
+    CallContext context(state, usedRegisters, jit, 4, result);
+    jit.setupArgumentsWithExecState(
+        CCallHelpers::TrustedImmPtr(stubInfo), object, CCallHelpers::TrustedImmPtr(uid));
+    return context.makeCall(bitwise_cast<void*>(operation), exceptionTarget);
+}
+
+MacroAssembler::Call callOperation(
+    State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
+    CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
     J_JITOperation_ESsiJI operation, GPRReg result, StructureStubInfo* stubInfo,
     GPRReg object, StringImpl* uid)
 {

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLSlowPathCall.h (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLSlowPathCall.h	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLSlowPathCall.h	2014-07-02 23:41:08 UTC (rev 170736)
@@ -59,6 +59,10 @@
 
 MacroAssembler::Call callOperation(
     State&, const RegisterSet&, CCallHelpers&, CodeOrigin, CCallHelpers::JumpList*,
+    J_JITOperation_ESsiCI, GPRReg, StructureStubInfo*, GPRReg,
+    const StringImpl*);
+MacroAssembler::Call callOperation(
+    State&, const RegisterSet&, CCallHelpers&, CodeOrigin, CCallHelpers::JumpList*,
     J_JITOperation_ESsiJI, GPRReg result, StructureStubInfo*, GPRReg object,
     StringImpl* uid);
 MacroAssembler::Call callOperation(

Modified: branches/ftlopt/Source/_javascript_Core/ftl/FTLState.h (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/ftl/FTLState.h	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/ftl/FTLState.h	2014-07-02 23:41:08 UTC (rev 170736)
@@ -73,6 +73,7 @@
     unsigned capturedStackmapID;
     SegmentedVector<GetByIdDescriptor> getByIds;
     SegmentedVector<PutByIdDescriptor> putByIds;
+    SegmentedVector<CheckInDescriptor> checkIns;
     Vector<JSCall> jsCalls;
     Vector<CString> codeSectionNames;
     Vector<CString> dataSectionNames;

Modified: branches/ftlopt/Source/_javascript_Core/jit/JITOperations.h (170735 => 170736)


--- branches/ftlopt/Source/_javascript_Core/jit/JITOperations.h	2014-07-02 23:02:45 UTC (rev 170735)
+++ branches/ftlopt/Source/_javascript_Core/jit/JITOperations.h	2014-07-02 23:41:08 UTC (rev 170736)
@@ -201,9 +201,9 @@
 EncodedJSValue JIT_OPERATION operationGetById(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, StringImpl*);
-EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, StringImpl*);
-EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue);
+EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
 void JIT_OPERATION operationPutByIdStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl*) WTF_INTERNAL;
 void JIT_OPERATION operationPutByIdNonStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl*) WTF_INTERNAL;

Added: branches/ftlopt/Source/_javascript_Core/tests/stress/ftl-checkin-variable.js (0 => 170736)


--- branches/ftlopt/Source/_javascript_Core/tests/stress/ftl-checkin-variable.js	                        (rev 0)
+++ branches/ftlopt/Source/_javascript_Core/tests/stress/ftl-checkin-variable.js	2014-07-02 23:41:08 UTC (rev 170736)
@@ -0,0 +1,17 @@
+function foo(l,x){
+    var t = l in x; 
+    return t;
+}
+
+noInline(foo);
+
+var r;
+for (var i = 0; i < 1000000; ++i) {
+    var z = { 'y' : i, 's' : i + 1 };
+    z.s = 10;
+    r = foo("s",z);
+}
+
+if (!r) {
+    print ("Error: " + r);
+}

Added: branches/ftlopt/Source/_javascript_Core/tests/stress/ftl-checkin.js (0 => 170736)


--- branches/ftlopt/Source/_javascript_Core/tests/stress/ftl-checkin.js	                        (rev 0)
+++ branches/ftlopt/Source/_javascript_Core/tests/stress/ftl-checkin.js	2014-07-02 23:41:08 UTC (rev 170736)
@@ -0,0 +1,17 @@
+function foo(x){
+    var t = "s" in x; 
+    return t;
+}
+
+noInline(foo);
+
+var r;
+for (var i = 0; i < 1000000; ++i) {
+    var z = { 'y' : i, 's' : i + 1 };
+    z.s = 10;
+    r = foo(z);
+}
+
+if (!r) {
+    print ("Error: " + r);
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to