FTL should support NewArrayBuffer
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Nov 2013 00:42:05 +0000 (00:42 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Nov 2013 00:42:05 +0000 (00:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=124067

Reviewed by Michael Saboff.

This expanded coverage and revealed some bugs.

This revealed a bug in FTL::OSRExitCompiler where it was assuming that it could save
the framePointer in regT3 even though DFG::reifyInlinedCallFrames() would clobber it.
It turns out that this can be fixed by just completely restoring the stack prior to
doing reifyInlineCallFrames().

I used this as an opportunity to simplify NewArray. That revealed a bug; whenever we say
lowJSValue() in there we need to use ManualOperandSpeculation since we're using it to
rebox values even when we also have to do some speculations. The speculations are done
at the top of compileNewArray().

This also revealed a bug in StringCharAt() for the OOB case.

* ftl/FTLAbstractHeapRepository.h:
(JSC::FTL::AbstractHeapRepository::forIndexingType):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileNewArray):
(JSC::FTL::LowerDFGToLLVM::compileNewArrayBuffer):
(JSC::FTL::LowerDFGToLLVM::compileStringCharAt):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp

index 2d8ef34..f91bdbd 100644 (file)
@@ -1,5 +1,39 @@
 2013-11-08  Filip Pizlo  <fpizlo@apple.com>
 
+        FTL should support NewArrayBuffer
+        https://bugs.webkit.org/show_bug.cgi?id=124067
+
+        Reviewed by Michael Saboff.
+        
+        This expanded coverage and revealed some bugs.
+        
+        This revealed a bug in FTL::OSRExitCompiler where it was assuming that it could save
+        the framePointer in regT3 even though DFG::reifyInlinedCallFrames() would clobber it.
+        It turns out that this can be fixed by just completely restoring the stack prior to
+        doing reifyInlineCallFrames().
+        
+        I used this as an opportunity to simplify NewArray. That revealed a bug; whenever we say
+        lowJSValue() in there we need to use ManualOperandSpeculation since we're using it to
+        rebox values even when we also have to do some speculations. The speculations are done
+        at the top of compileNewArray().
+        
+        This also revealed a bug in StringCharAt() for the OOB case.
+
+        * ftl/FTLAbstractHeapRepository.h:
+        (JSC::FTL::AbstractHeapRepository::forIndexingType):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileNewArray):
+        (JSC::FTL::LowerDFGToLLVM::compileNewArrayBuffer):
+        (JSC::FTL::LowerDFGToLLVM::compileStringCharAt):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileStub):
+
+2013-11-08  Filip Pizlo  <fpizlo@apple.com>
+
         It should be easy to disable blinding on a per-architecture basis
         https://bugs.webkit.org/show_bug.cgi?id=124083
 
index 07bf728..1aa6918 100644 (file)
@@ -31,6 +31,7 @@
 #if ENABLE(FTL_JIT)
 
 #include "FTLAbstractHeap.h"
+#include "IndexingType.h"
 
 namespace JSC { namespace FTL {
 
@@ -102,6 +103,31 @@ public:
 #undef NUMBERED_ABSTRACT_HEAP_DECLARATION
 
     AbsoluteAbstractHeap absolute;
+    
+    IndexedAbstractHeap* forIndexingType(IndexingType indexingType)
+    {
+        switch (indexingType) {
+        case ALL_BLANK_INDEXING_TYPES:
+        case ALL_UNDECIDED_INDEXING_TYPES:
+            return 0;
+            
+        case ALL_INT32_INDEXING_TYPES:
+            return &indexedInt32Properties;
+            
+        case ALL_DOUBLE_INDEXING_TYPES:
+            return &indexedDoubleProperties;
+            
+        case ALL_CONTIGUOUS_INDEXING_TYPES:
+            return &indexedContiguousProperties;
+            
+        case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+            return &indexedArrayStorageProperties;
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return 0;
+        }
+    }
 
 private:
     friend class AbstractHeap;
index 85e7f52..52d751b 100644 (file)
@@ -64,6 +64,7 @@ inline CapabilityLevel canCompile(Node* node)
     case GetButterfly:
     case NewObject:
     case NewArray:
+    case NewArrayBuffer:
     case GetByOffset:
     case PutByOffset:
     case GetGlobalVar:
index 3563bb7..4b98fe0 100644 (file)
@@ -59,6 +59,7 @@ namespace JSC { namespace FTL {
     macro(P_JITOperation_EC, functionType(intPtr, intPtr, intPtr)) \
     macro(P_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \
     macro(P_JITOperation_EStPS, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
+    macro(P_JITOperation_EStSS, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
     macro(P_JITOperation_EStZ, functionType(intPtr, intPtr, intPtr, int32)) \
     macro(V_JITOperation_EOZD, functionType(voidType, intPtr, intPtr, int32, doubleType)) \
     macro(V_JITOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64)) \
index 44afc95..220adca 100644 (file)
@@ -374,6 +374,9 @@ private:
         case NewArray:
             compileNewArray();
             break;
+        case NewArrayBuffer:
+            compileNewArrayBuffer();
+            break;
         case StringCharAt:
             compileStringCharAt();
             break;
@@ -1786,12 +1789,6 @@ private:
         RELEASE_ASSERT(structure->indexingType() == m_node->indexingType());
         
         if (!globalObject->isHavingABadTime() && !hasArrayStorage(m_node->indexingType())) {
-            ASSERT(
-                hasUndecided(structure->indexingType())
-                || hasInt32(structure->indexingType())
-                || hasDouble(structure->indexingType())
-                || hasContiguous(structure->indexingType()));
-            
             unsigned numElements = m_node->numChildren();
             
             ArrayValues arrayValues = allocateJSArray(structure, numElements);
@@ -1812,16 +1809,11 @@ private:
                     break;
                     
                 case ALL_INT32_INDEXING_TYPES:
-                    m_out.store64(
-                        lowJSValue(edge),
-                        arrayValues.butterfly, m_heaps.indexedInt32Properties[operandIndex]);
-                    break;
-                    
                 case ALL_CONTIGUOUS_INDEXING_TYPES:
                     m_out.store64(
-                        lowJSValue(edge),
+                        lowJSValue(edge, ManualOperandSpeculation),
                         arrayValues.butterfly,
-                        m_heaps.indexedContiguousProperties[operandIndex]);
+                        m_heaps.forIndexingType(m_node->indexingType())->at(operandIndex));
                     break;
                     
                 default:
@@ -1847,7 +1839,9 @@ private:
         
         for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
             Edge edge = m_graph.varArgChild(m_node, operandIndex);
-            m_out.store64(lowJSValue(edge), m_out.absolute(buffer + operandIndex));
+            m_out.store64(
+                lowJSValue(edge, ManualOperandSpeculation),
+                m_out.absolute(buffer + operandIndex));
         }
         
         m_out.storePtr(
@@ -1863,6 +1857,43 @@ private:
         setJSValue(result);
     }
     
+    void compileNewArrayBuffer()
+    {
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->codeOrigin);
+        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
+            m_node->indexingType());
+        
+        RELEASE_ASSERT(structure->indexingType() == m_node->indexingType());
+        
+        if (!globalObject->isHavingABadTime() && !hasArrayStorage(m_node->indexingType())) {
+            unsigned numElements = m_node->numConstants();
+            
+            ArrayValues arrayValues = allocateJSArray(structure, numElements);
+            
+            JSValue* data = codeBlock()->constantBuffer(m_node->startConstant());
+            for (unsigned index = 0; index < m_node->numConstants(); ++index) {
+                int64_t value;
+                if (hasDouble(m_node->indexingType()))
+                    value = bitwise_cast<int64_t>(data[index].asNumber());
+                else
+                    value = JSValue::encode(data[index]);
+                
+                m_out.store64(
+                    m_out.constInt64(value),
+                    arrayValues.butterfly,
+                    m_heaps.forIndexingType(m_node->indexingType())->at(index));
+            }
+            
+            setJSValue(arrayValues.array);
+            return;
+        }
+        
+        setJSValue(vmCall(
+            m_out.operation(operationNewArrayBuffer), m_callFrame,
+            m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()),
+            m_out.constIntPtr(m_node->numConstants())));
+    }
+    
     void compileStringCharAt()
     {
         LValue base = lowCell(m_node->child1());
@@ -1950,7 +1981,7 @@ private:
             }
                 
             results.append(m_out.anchor(vmCall(
-                m_out.operation(operationGetByValStringInt), base, index)));
+                m_out.operation(operationGetByValStringInt), m_callFrame, base, index)));
         }
             
         m_out.jump(continuation);
index e012707..19bed6d 100644 (file)
@@ -153,18 +153,19 @@ static void compileStub(
         jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(static_cast<VirtualRegister>(operand), GPRInfo::regT4));
     }
     
-    // Save the current framePointer into regT3 for the epilogue.
-    // Put regT4 into callFrameRegister
-    jit.move(MacroAssembler::framePointerRegister, GPRInfo::regT3);
+    // Restore the old stack pointer and then put regT4 into callFrameRegister. The idea is
+    // that the FTL call frame is pushed onto the JS call frame and we can recover the old
+    // value of the stack pointer by popping the FTL call frame. We already know what the
+    // frame pointer in the JS call frame was because it would have been passed as an argument
+    // to the FTL call frame.
+    jit.move(MacroAssembler::framePointerRegister, MacroAssembler::stackPointerRegister);
+    jit.pop(GPRInfo::nonArgGPR0);
+    jit.pop(GPRInfo::nonArgGPR0);
     jit.move(GPRInfo::regT4, GPRInfo::callFrameRegister);
     
     handleExitCounts(jit, exit);
     reifyInlinedCallFrames(jit, exit);
     
-    jit.move(GPRInfo::regT3, MacroAssembler::stackPointerRegister);
-    jit.pop(GPRInfo::regT3); // ignore prior framePointer
-    jit.pop(GPRInfo::nonArgGPR0); // ignore the result.
-    
     if (exit.m_lastSetOperand.isValid()) {
         jit.load64(
             AssemblyHelpers::addressFor(exit.m_lastSetOperand), GPRInfo::cachedResultRegister);