Title: [207163] trunk/Source/_javascript_Core
Revision
207163
Author
[email protected]
Date
2016-10-11 13:37:51 -0700 (Tue, 11 Oct 2016)

Log Message

B3->Air lowering needs the same defenses in effectiveAddr() that it has in tryAppendLea()
https://bugs.webkit.org/show_bug.cgi?id=163264

Reviewed by Mark Lam.
        
When writing the lea patch (r207039), I was very careful about how I convert a Shl into a
BaseIndex scale. But I forgot to check if the older code for creating BaseIndexes for
effectiveAddr() got this right. It turns out that the older code missed the <<32 corner
case.
        
It's sad that the two paths can't share all of their code, but it's somewhat inevitable due
to how matching an address and matching a lea have to do very different things. Matching a
lea means creating an instruction that is distinct from other instructions to do multiple
math operations at once. Matching an address means making some instruction do extra work
for free. Also, address matching can take advantage of the fact that the offset is already
associated with the memory operation by strength reduction - lea matching can't do this; it
has to figure out Add(@value, $const) on its own. This change makes the situation slightly
more sane by adding a scaleForShl() helper that handles this weird case. It's based on the
new Shl handling from r207039, and exposes it as an API for effectiveAddr() to use.
        
The testLoadBaseIndexShift32() used to crash. I don't think that this case affects JS
content, since <<32 is such a bizarre outlier. I don't think we even have a path along
which the FTL would emit a 64-bit <<32. It probably won't even affect WebAssembly since
that uses 32-bit pointers, so we won't see 64-bit <<32 in effectiveAddr() there.

* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::scaleForShl):
(JSC::B3::Air::LowerToAir::effectiveAddr):
(JSC::B3::Air::LowerToAir::tryAppendLea):
(JSC::B3::Air::LowerToAir::crossesInterference): Deleted.
* b3/testb3.cpp:
(JSC::B3::testLoadBaseIndexShift2):
(JSC::B3::testLoadBaseIndexShift32):
(JSC::B3::run):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (207162 => 207163)


--- trunk/Source/_javascript_Core/ChangeLog	2016-10-11 20:27:39 UTC (rev 207162)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-10-11 20:37:51 UTC (rev 207163)
@@ -1,3 +1,40 @@
+2016-10-11  Filip Pizlo  <[email protected]>
+
+        B3->Air lowering needs the same defenses in effectiveAddr() that it has in tryAppendLea()
+        https://bugs.webkit.org/show_bug.cgi?id=163264
+
+        Reviewed by Mark Lam.
+        
+        When writing the lea patch (r207039), I was very careful about how I convert a Shl into a
+        BaseIndex scale. But I forgot to check if the older code for creating BaseIndexes for
+        effectiveAddr() got this right. It turns out that the older code missed the <<32 corner
+        case.
+        
+        It's sad that the two paths can't share all of their code, but it's somewhat inevitable due
+        to how matching an address and matching a lea have to do very different things. Matching a
+        lea means creating an instruction that is distinct from other instructions to do multiple
+        math operations at once. Matching an address means making some instruction do extra work
+        for free. Also, address matching can take advantage of the fact that the offset is already
+        associated with the memory operation by strength reduction - lea matching can't do this; it
+        has to figure out Add(@value, $const) on its own. This change makes the situation slightly
+        more sane by adding a scaleForShl() helper that handles this weird case. It's based on the
+        new Shl handling from r207039, and exposes it as an API for effectiveAddr() to use.
+        
+        The testLoadBaseIndexShift32() used to crash. I don't think that this case affects JS
+        content, since <<32 is such a bizarre outlier. I don't think we even have a path along
+        which the FTL would emit a 64-bit <<32. It probably won't even affect WebAssembly since
+        that uses 32-bit pointers, so we won't see 64-bit <<32 in effectiveAddr() there.
+
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::scaleForShl):
+        (JSC::B3::Air::LowerToAir::effectiveAddr):
+        (JSC::B3::Air::LowerToAir::tryAppendLea):
+        (JSC::B3::Air::LowerToAir::crossesInterference): Deleted.
+        * b3/testb3.cpp:
+        (JSC::B3::testLoadBaseIndexShift2):
+        (JSC::B3::testLoadBaseIndexShift32):
+        (JSC::B3::run):
+
 2016-10-11  Saam Barati  <[email protected]>
 
         ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (207162 => 207163)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-10-11 20:27:39 UTC (rev 207162)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-10-11 20:37:51 UTC (rev 207163)
@@ -425,6 +425,28 @@
         ASSERT_NOT_REACHED();
         return true;
     }
+    
+    Optional<unsigned> scaleForShl(Value* shl, int32_t offset, Optional<Arg::Width> width = Nullopt)
+    {
+        if (shl->opcode() != Shl)
+            return Nullopt;
+        if (!shl->child(1)->hasInt32())
+            return Nullopt;
+        unsigned logScale = shl->child(1)->asInt32();
+        if (shl->type() == Int32)
+            logScale &= 31;
+        else
+            logScale &= 63;
+        // Use 64-bit math to perform the shift so that <<32 does the right thing, but then switch
+        // to signed since that's what all of our APIs want.
+        int64_t bigScale = static_cast<uint64_t>(1) << static_cast<uint64_t>(logScale);
+        if (!isRepresentableAs<int32_t>(bigScale))
+            return Nullopt;
+        unsigned scale = static_cast<int32_t>(bigScale);
+        if (!Arg::isValidIndexForm(scale, offset, width))
+            return Nullopt;
+        return scale;
+    }
 
     // This turns the given operand into an address.
     Arg effectiveAddr(Value* address, int32_t offset, Arg::Width width)
@@ -447,18 +469,12 @@
             Value* right = address->child(1);
 
             auto tryIndex = [&] (Value* index, Value* base) -> Arg {
-                if (index->opcode() != Shl)
+                Optional<unsigned> scale = scaleForShl(index, offset, width);
+                if (!scale)
                     return Arg();
                 if (m_locked.contains(index->child(0)) || m_locked.contains(base))
                     return Arg();
-                if (!index->child(1)->hasInt32())
-                    return Arg();
-                
-                unsigned scale = 1 << (index->child(1)->asInt32() & 31);
-                if (!Arg::isValidIndexForm(scale, offset, width))
-                    return Arg();
-
-                return Arg::index(tmp(base), tmp(index->child(0)), scale, offset);
+                return Arg::index(tmp(base), tmp(index->child(0)), *scale, offset);
             };
 
             if (Arg result = tryIndex(left, right))
@@ -1898,29 +1914,16 @@
         }
         
         auto tryShl = [&] (Value* shl, Value* other) -> bool {
-            if (shl->opcode() != Shl)
+            Optional<unsigned> scale = scaleForShl(shl, offset);
+            if (!scale)
                 return false;
             if (!canBeInternal(shl))
                 return false;
-            if (!shl->child(1)->hasInt32())
-                return false;
-            unsigned logScale = shl->child(1)->asInt32();
-            if (m_value->type() == Int32)
-                logScale &= 31;
-            else
-                logScale &= 63;
-            // Use 64-bit math to perform the shift so that <<32 does the right thing.
-            int64_t bigScale = static_cast<uint64_t>(1) << static_cast<uint64_t>(logScale);
-            if (!isRepresentableAs<int32_t>(bigScale))
-                return false;
-            unsigned scale = static_cast<int32_t>(bigScale);
-            if (!Arg::isValidIndexForm(scale, offset))
-                return false;
             
             ASSERT(!m_locked.contains(shl->child(0)));
             ASSERT(!m_locked.contains(other));
             
-            append(leaOpcode, Arg::index(tmp(other), tmp(shl->child(0)), scale, offset), tmp(m_value));
+            append(leaOpcode, Arg::index(tmp(other), tmp(shl->child(0)), *scale, offset), tmp(m_value));
             commitInternal(innerAdd);
             commitInternal(shl);
             return true;

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (207162 => 207163)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2016-10-11 20:27:39 UTC (rev 207162)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2016-10-11 20:37:51 UTC (rev 207163)
@@ -13659,6 +13659,52 @@
         (root->last()->child(0)->child(0)->child(0) == arg2 && root->last()->child(0)->child(0)->child(1) == arg1));
 }
 
+void testLoadBaseIndexShift2()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<Value>(
+        proc, Return, Origin(),
+        root->appendNew<MemoryValue>(
+            proc, Load, Int32, Origin(),
+            root->appendNew<Value>(
+                proc, Add, Origin(),
+                root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
+                root->appendNew<Value>(
+                    proc, Shl, Origin(),
+                    root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
+                    root->appendNew<Const32Value>(proc, Origin(), 2)))));
+    auto code = compile(proc);
+    if (isX86())
+        checkUsesInstruction(*code, "(%rdi,%rsi,4)");
+    int32_t value = 12341234;
+    char* ptr = bitwise_cast<char*>(&value);
+    for (unsigned i = 0; i < 10; ++i)
+        CHECK_EQ(invoke<int32_t>(*code, ptr - (static_cast<intptr_t>(1) << static_cast<intptr_t>(2)) * i, i), 12341234);
+}
+
+void testLoadBaseIndexShift32()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<Value>(
+        proc, Return, Origin(),
+        root->appendNew<MemoryValue>(
+            proc, Load, Int32, Origin(),
+            root->appendNew<Value>(
+                proc, Add, Origin(),
+                root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
+                root->appendNew<Value>(
+                    proc, Shl, Origin(),
+                    root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
+                    root->appendNew<Const32Value>(proc, Origin(), 32)))));
+    auto code = compile(proc);
+    int32_t value = 12341234;
+    char* ptr = bitwise_cast<char*>(&value);
+    for (unsigned i = 0; i < 10; ++i)
+        CHECK_EQ(invoke<int32_t>(*code, ptr - (static_cast<intptr_t>(1) << static_cast<intptr_t>(32)) * i, i), 12341234);
+}
+
 // Make sure the compiler does not try to optimize anything out.
 NEVER_INLINE double zero()
 {
@@ -15095,6 +15141,8 @@
     RUN(testAddShl32());
     RUN(testAddShl64());
     RUN(testAddShl65());
+    RUN(testLoadBaseIndexShift2());
+    RUN(testLoadBaseIndexShift32());
     
     if (isX86()) {
         RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to