FTL B3 should have basic GetById support
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Dec 2015 03:50:07 +0000 (03:50 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Dec 2015 03:50:07 +0000 (03:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152035

Reviewed by Saam Barati.

Source/JavaScriptCore:

Adds basic GetById support. This was so easy to do. Unlike the LLVM code for this, the B3 code is
entirely self-contained within the getById() method in LowerDFG.

I discovered that we weren't folding Check(NotEqual(x, 0)) to Check(x). This was preventing us
from generating good code for Check(NotEqual(BitAnd(x, tagMask), 0)), since the BitAnd was
concealed. This was an easy strength reduction rule to add.

Finally, I found it easier to say append(value, rep) than append(ConstrainedValue(value, rep)), so
I added that API. The old ConstrainedValue form is still super useful in other places, like
compileCallOrConstruct(), where the two-argument form would be awkward. It's great to have both
APIs to pick from.

* b3/B3ReduceStrength.cpp:
* b3/B3StackmapValue.cpp:
(JSC::B3::StackmapValue::~StackmapValue):
(JSC::B3::StackmapValue::append):
* b3/B3StackmapValue.h:
* dfg/DFGCommon.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::getById):

Source/WTF:

When dealing with shared task lambdas, you often want to force a value to be allocated so that it
has reference semantics, but you still want the lambda to execute OK when we pop stack. In PL we
usually call this a "box". This is easy to do if the value that happened to be stack-allocated
is also RefCounted, but that's rare, since stack-allocated values often have copy semantics. So,
I've added a Box type to WTF. Behind the scenes, it allocates your object with fast malloc inside
a ThreadSAfeRefCounted. When you pass Box<T>, you're passing the reference. This makes it a lot
easier to work with by-reference capture.

* WTF.xcodeproj/project.pbxproj:
* wtf/Box.h: Added.
(WTF::Box::Box):
(WTF::Box::create):
(WTF::Box::get):
(WTF::Box::operator*):
(WTF::Box::operator->):
(WTF::Box::operator bool):
(WTF::Box::Data::Data):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@193890 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/b3/B3ReduceStrength.cpp
Source/JavaScriptCore/b3/B3StackmapValue.cpp
Source/JavaScriptCore/b3/B3StackmapValue.h
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/Box.h [new file with mode: 0644]

index 62061b0..8481dfe 100644 (file)
@@ -1,3 +1,31 @@
+2015-12-08  Filip Pizlo  <fpizlo@apple.com>
+
+        FTL B3 should have basic GetById support
+        https://bugs.webkit.org/show_bug.cgi?id=152035
+
+        Reviewed by Saam Barati.
+
+        Adds basic GetById support. This was so easy to do. Unlike the LLVM code for this, the B3 code is
+        entirely self-contained within the getById() method in LowerDFG.
+
+        I discovered that we weren't folding Check(NotEqual(x, 0)) to Check(x). This was preventing us
+        from generating good code for Check(NotEqual(BitAnd(x, tagMask), 0)), since the BitAnd was
+        concealed. This was an easy strength reduction rule to add.
+
+        Finally, I found it easier to say append(value, rep) than append(ConstrainedValue(value, rep)), so
+        I added that API. The old ConstrainedValue form is still super useful in other places, like
+        compileCallOrConstruct(), where the two-argument form would be awkward. It's great to have both
+        APIs to pick from.
+
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3StackmapValue.cpp:
+        (JSC::B3::StackmapValue::~StackmapValue):
+        (JSC::B3::StackmapValue::append):
+        * b3/B3StackmapValue.h:
+        * dfg/DFGCommon.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::getById):
+
 2015-12-09  Saam barati  <sbarati@apple.com>
 
         Update generators' features.json to indicate that we have a spec compliant implementation
 2015-12-09  Saam barati  <sbarati@apple.com>
 
         Update generators' features.json to indicate that we have a spec compliant implementation
index 5c0bb92..b82e091 100644 (file)
@@ -861,6 +861,12 @@ private:
                 m_changed = true;
                 break;
             }
                 m_changed = true;
                 break;
             }
+
+            if (m_value->child(0)->opcode() == NotEqual && m_value->child(0)->child(1)->isInt(0)) {
+                m_value->child(0) = m_value->child(0)->child(0);
+                m_changed = true;
+                break;
+            }
             break;
 
         case Branch: {
             break;
 
         case Branch: {
index 9247c45..746a17e 100644 (file)
@@ -34,18 +34,18 @@ StackmapValue::~StackmapValue()
 {
 }
 
 {
 }
 
-void StackmapValue::append(const ConstrainedValue& constrainedValue)
+void StackmapValue::append(Value* value, const ValueRep& rep)
 {
 {
-    if (constrainedValue.rep() == ValueRep::ColdAny) {
-        children().append(constrainedValue.value());
+    if (rep == ValueRep::ColdAny) {
+        children().append(value);
         return;
     }
 
     while (m_reps.size() < numChildren())
         m_reps.append(ValueRep::ColdAny);
 
         return;
     }
 
     while (m_reps.size() < numChildren())
         m_reps.append(ValueRep::ColdAny);
 
-    children().append(constrainedValue.value());
-    m_reps.append(constrainedValue.rep());
+    children().append(value);
+    m_reps.append(rep);
 }
 
 void StackmapValue::appendSomeRegister(Value* value)
 }
 
 void StackmapValue::appendSomeRegister(Value* value)
index 97cf027..009fdb4 100644 (file)
@@ -63,7 +63,12 @@ public:
 
     // Use this to add children. Note that you could also add children by doing
     // children().append(). That will work fine, but it's not recommended.
 
     // Use this to add children. Note that you could also add children by doing
     // children().append(). That will work fine, but it's not recommended.
-    void append(const ConstrainedValue&);
+    void append(const ConstrainedValue& value)
+    {
+        append(value.value(), value.rep());
+    }
+
+    void append(Value*, const ValueRep&);
 
     template<typename VectorType>
     void appendVector(const VectorType& vector)
 
     template<typename VectorType>
     void appendVector(const VectorType& vector)
index ace10b1..49572c1 100644 (file)
@@ -63,6 +63,7 @@
 #include <dlfcn.h>
 #include <llvm/InitializeLLVM.h>
 #include <unordered_set>
 #include <dlfcn.h>
 #include <llvm/InitializeLLVM.h>
 #include <unordered_set>
+#include <wtf/Box.h>
 #include <wtf/ProcessID.h>
 
 namespace JSC { namespace FTL {
 #include <wtf/ProcessID.h>
 
 namespace JSC { namespace FTL {
@@ -6720,15 +6721,57 @@ private:
     
     LValue getById(LValue base)
     {
     
     LValue getById(LValue base)
     {
+        Node* node = m_node;
+        UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
+
 #if FTL_USES_B3
 #if FTL_USES_B3
-        UNUSED_PARAM(base);
+        // FIXME: Make this do exceptions.
+        // https://bugs.webkit.org/show_bug.cgi?id=151686
+        
+        B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
+        patchpoint->append(base, ValueRep::SomeRegister);
+        patchpoint->clobber(RegisterSet::macroScratchRegisters());
 
 
-        if (verboseCompilationEnabled() || !verboseCompilationEnabled())
-            CRASH();
-        return nullptr;
-#else
-        auto uid = m_graph.identifiers()[m_node->identifierNumber()];
+        State* state = &m_ftlState;
+        patchpoint->setGenerator(
+            [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+
+                auto generator = Box<JITGetByIdGenerator>::create(
+                    jit.codeBlock(), node->origin.semantic,
+                    state->jitCode->common.addUniqueCallSiteIndex(node->origin.semantic),
+                    params.usedRegisters(), JSValueRegs(params[1].gpr()), JSValueRegs(params[0].gpr()));
+
+                generator->generateFastPath(jit);
+                CCallHelpers::Label done = jit.label();
+
+                params.addLatePath(
+                    [=] (CCallHelpers& jit) {
+                        AllowMacroScratchRegisterUsage allowScratch(jit);
+                        
+                        // FIXME: Make this do something.
+                        CCallHelpers::JumpList exceptions;
+
+                        generator->slowPathJump().link(&jit);
+                        CCallHelpers::Label slowPathBegin = jit.label();
+                        CCallHelpers::Call slowPathCall = callOperation(
+                            *state, params.usedRegisters(), jit, node->origin.semantic, &exceptions,
+                            operationGetByIdOptimize, params[0].gpr(),
+                            CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(),
+                            CCallHelpers::TrustedImmPtr(uid)).call();
+                        jit.jump().linkTo(done, &jit);
+
+                        generator->reportSlowPathCall(slowPathBegin, slowPathCall);
 
 
+                        jit.addLinkTask(
+                            [=] (LinkBuffer& linkBuffer) {
+                                generator->finalize(linkBuffer);
+                            });
+                    });
+            });
+
+        return patchpoint;
+#else
         // Arguments: id, bytes, target, numArgs, args...
         unsigned stackmapID = m_stackmapIDs++;
         
         // Arguments: id, bytes, target, numArgs, args...
         unsigned stackmapID = m_stackmapIDs++;
         
@@ -6748,7 +6791,7 @@ private:
         LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments);
         setInstructionCallingConvention(call, LLVMAnyRegCallConv);
         
         LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments);
         setInstructionCallingConvention(call, LLVMAnyRegCallConv);
         
-        m_ftlState.getByIds.append(GetByIdDescriptor(stackmapID, m_node->origin.semantic, uid));
+        m_ftlState.getByIds.append(GetByIdDescriptor(stackmapID, node->origin.semantic, uid));
         
         return call;
 #endif
         
         return call;
 #endif
index 4d1edab..30e8547 100644 (file)
@@ -1,3 +1,28 @@
+2015-12-08  Filip Pizlo  <fpizlo@apple.com>
+
+        FTL B3 should have basic GetById support
+        https://bugs.webkit.org/show_bug.cgi?id=152035
+
+        Reviewed by Saam Barati.
+
+        When dealing with shared task lambdas, you often want to force a value to be allocated so that it
+        has reference semantics, but you still want the lambda to execute OK when we pop stack. In PL we
+        usually call this a "box". This is easy to do if the value that happened to be stack-allocated
+        is also RefCounted, but that's rare, since stack-allocated values often have copy semantics. So,
+        I've added a Box type to WTF. Behind the scenes, it allocates your object with fast malloc inside
+        a ThreadSAfeRefCounted. When you pass Box<T>, you're passing the reference. This makes it a lot
+        easier to work with by-reference capture.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/Box.h: Added.
+        (WTF::Box::Box):
+        (WTF::Box::create):
+        (WTF::Box::get):
+        (WTF::Box::operator*):
+        (WTF::Box::operator->):
+        (WTF::Box::operator bool):
+        (WTF::Box::Data::Data):
+
 2015-12-09  Andreas Kling  <akling@apple.com>
 
         [iOS] ResourceUsageOverlay should work on iOS.
 2015-12-09  Andreas Kling  <akling@apple.com>
 
         [iOS] ResourceUsageOverlay should work on iOS.
index 0615faf..ac3c71a 100644 (file)
@@ -34,6 +34,7 @@
                0F8F2B91172E00FC007DBDA5 /* CompilationThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */; };
                0F8F2B92172E0103007DBDA5 /* CompilationThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */; };
                0F8F2B9C172F2596007DBDA5 /* ConversionMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B9B172F2594007DBDA5 /* ConversionMode.h */; };
                0F8F2B91172E00FC007DBDA5 /* CompilationThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */; };
                0F8F2B92172E0103007DBDA5 /* CompilationThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */; };
                0F8F2B9C172F2596007DBDA5 /* ConversionMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B9B172F2594007DBDA5 /* ConversionMode.h */; };
+               0F93274B1C17F4B700CF6564 /* Box.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93274A1C17F4B700CF6564 /* Box.h */; };
                0F9D3360165DBA73005AD387 /* FilePrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */; };
                0F9D3361165DBA73005AD387 /* FilePrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D335C165DBA73005AD387 /* FilePrintStream.h */; };
                0F9D3362165DBA73005AD387 /* PrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D335D165DBA73005AD387 /* PrintStream.cpp */; };
                0F9D3360165DBA73005AD387 /* FilePrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */; };
                0F9D3361165DBA73005AD387 /* FilePrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D335C165DBA73005AD387 /* FilePrintStream.h */; };
                0F9D3362165DBA73005AD387 /* PrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D335D165DBA73005AD387 /* PrintStream.cpp */; };
                0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompilationThread.cpp; sourceTree = "<group>"; };
                0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompilationThread.h; sourceTree = "<group>"; };
                0F8F2B9B172F2594007DBDA5 /* ConversionMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConversionMode.h; sourceTree = "<group>"; };
                0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompilationThread.cpp; sourceTree = "<group>"; };
                0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompilationThread.h; sourceTree = "<group>"; };
                0F8F2B9B172F2594007DBDA5 /* ConversionMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConversionMode.h; sourceTree = "<group>"; };
+               0F93274A1C17F4B700CF6564 /* Box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box.h; sourceTree = "<group>"; };
                0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilePrintStream.cpp; sourceTree = "<group>"; };
                0F9D335C165DBA73005AD387 /* FilePrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilePrintStream.h; sourceTree = "<group>"; };
                0F9D335D165DBA73005AD387 /* PrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintStream.cpp; sourceTree = "<group>"; };
                0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilePrintStream.cpp; sourceTree = "<group>"; };
                0F9D335C165DBA73005AD387 /* FilePrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilePrintStream.h; sourceTree = "<group>"; };
                0F9D335D165DBA73005AD387 /* PrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintStream.cpp; sourceTree = "<group>"; };
                                A8A47261151A825A004123FF /* BitVector.h */,
                                A8A47264151A825A004123FF /* BlockStack.h */,
                                A8A47265151A825A004123FF /* BloomFilter.h */,
                                A8A47261151A825A004123FF /* BitVector.h */,
                                A8A47264151A825A004123FF /* BlockStack.h */,
                                A8A47265151A825A004123FF /* BloomFilter.h */,
+                               0F93274A1C17F4B700CF6564 /* Box.h */,
                                0F4570441BE834410062A629 /* BubbleSort.h */,
                                A8A47267151A825A004123FF /* BumpPointerAllocator.h */,
                                EB95E1EF161A72410089A2F5 /* ByteOrder.h */,
                                0F4570441BE834410062A629 /* BubbleSort.h */,
                                A8A47267151A825A004123FF /* BumpPointerAllocator.h */,
                                EB95E1EF161A72410089A2F5 /* ByteOrder.h */,
                                A8A4743D151A825B004123FF /* StringBuilder.h in Headers */,
                                430B47891AAAAC1A001223DA /* StringCommon.h in Headers */,
                                A8A4743E151A825B004123FF /* StringConcatenate.h in Headers */,
                                A8A4743D151A825B004123FF /* StringBuilder.h in Headers */,
                                430B47891AAAAC1A001223DA /* StringCommon.h in Headers */,
                                A8A4743E151A825B004123FF /* StringConcatenate.h in Headers */,
+                               0F93274B1C17F4B700CF6564 /* Box.h in Headers */,
                                A8A4742C151A825B004123FF /* StringExtras.h in Headers */,
                                A8A4743F151A825B004123FF /* StringHash.h in Headers */,
                                A748745417A0BDAE00FA04CB /* StringHashDumpContext.h in Headers */,
                                A8A4742C151A825B004123FF /* StringExtras.h in Headers */,
                                A8A4743F151A825B004123FF /* StringHash.h in Headers */,
                                A748745417A0BDAE00FA04CB /* StringHashDumpContext.h in Headers */,
diff --git a/Source/WTF/wtf/Box.h b/Source/WTF/wtf/Box.h
new file mode 100644 (file)
index 0000000..ad9d5c5
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef WTF_Box_h
+#define WTF_Box_h
+
+#include <wtf/RefPtr.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WTF {
+
+// Box<T> is a reference-counted pointer to T that allocates T using FastMalloc and prepends a reference
+// count to it.
+template<typename T>
+class Box {
+public:
+    Box()
+    {
+    }
+
+    template<typename... Arguments>
+    static Box create(Arguments&&... arguments)
+    {
+        Box result;
+        result.m_data = adoptRef(new Data(std::forward<Arguments>(arguments)...));
+        return result;
+    }
+
+    T* get() const { return &m_data->value; }
+
+    T& operator*() const { return m_data->value; }
+    T* operator->() const { return &m_data->value; }
+
+    explicit operator bool() { return m_data; }
+    
+private:
+    struct Data : ThreadSafeRefCounted<Data> {
+        template<typename... Arguments>
+        Data(Arguments&&... arguments)
+            : value(std::forward<Arguments>(arguments)...)
+        {
+        }
+        
+        T value;
+    };
+
+    RefPtr<Data> m_data;
+};
+
+} // namespace WTF
+
+using WTF::Box;
+
+#endif // WTF_Box_h
+