Ignore:
Timestamp:
Jan 29, 2014, 11:30:24 PM (11 years ago)
Author:
[email protected]
Message:

Merge final changesets from the jsCStack branch (r162969, r162975, r162992, r163004, r163069).

2014-01-29 Filip Pizlo <[email protected]>


DFG ArrayPop double array mishandles the NaN hole installation
https://bugs.webkit.org/show_bug.cgi?id=127813


Reviewed by Mark Rowe.


Our object model for arrays inferred double dictates that we use quiet NaN (QNaN) to
mark holes. Holes, in this context, are any entries in the allocated array buffer
(i.e. from index 0 up to the vectorLength) that don't currently hold a value. Popping
creates a hole, since it deletes the value at publicLength - 1.


But, because of some sloppy copy-and-paste, we were storing (int64_t)0 when creating
the hole, instead of storing QNaN. That's likely because for other kinds of arrays,
64-bit zero is the hole marker, instead of QNaN.


The attached test case illustrates the problem. In the LLInt and Baseline JIT, the
result returned from foo() is "1.5,2.54.5", since array.pop() removes 3.5 and
replaces it with a hole and then the assignment "array[3] = 4.5" creates an element
just beyond that hole. But, once we tier-up to the DFG, the result previously became
"1.5,2.5,0,4.5", which is wrong. The 0 appeared because the IEEE double
interpretation of 64-bit zero is simply zero.


This patch fixes that problem. Now the DFG agrees with the other engines.


This patch also fixes style. For some reason that copy-pasted code wasn't even
indented correctly.


  • dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile):
  • tests/stress/array-pop-double-hole.js: Added. (foo):


2014-01-28 Filip Pizlo <[email protected]>


FTL should support ArrayPush
https://bugs.webkit.org/show_bug.cgi?id=127748


Not reviewed, remove some debug code.


  • ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileArrayPush):


2014-01-27 Filip Pizlo <[email protected]>


FTL should support ArrayPush
https://bugs.webkit.org/show_bug.cgi?id=127748


Reviewed by Oliver Hunt.


  • ftl/FTLAbstractHeapRepository.h: (JSC::FTL::AbstractHeapRepository::forArrayType):
  • ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile):
  • ftl/FTLIntrinsicRepository.h:
  • ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileNode): (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
  • tests/stress/array-push-contiguous.js: Added. (foo):
  • tests/stress/array-push-double.js: Added. (foo):


2014-01-28 Filip Pizlo <[email protected]>


FTL should support ArrayPop
https://bugs.webkit.org/show_bug.cgi?id=127749


Reviewed by Geoffrey Garen.


  • ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile):
  • ftl/FTLIntrinsicRepository.h:
  • ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileNode): (JSC::FTL::LowerDFGToLLVM::compileArrayPush): (JSC::FTL::LowerDFGToLLVM::compileArrayPop):
  • tests/stress/array-pop-contiguous.js: Added. (foo):
  • tests/stress/array-pop-double.js: Added. (foo):
  • tests/stress/array-pop-int32.js: Added. (foo):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r163027 r163070  
    416416        case PutByValDirect:
    417417            compilePutByVal();
     418            break;
     419        case ArrayPush:
     420            compileArrayPush();
     421            break;
     422        case ArrayPop:
     423            compileArrayPop();
    418424            break;
    419425        case NewObject:
     
    21822188    }
    21832189   
     2190    void compileArrayPush()
     2191    {
     2192        LValue base = lowCell(m_node->child1());
     2193        LValue storage = lowStorage(m_node->child3());
     2194       
     2195        switch (m_node->arrayMode().type()) {
     2196        case Array::Int32:
     2197        case Array::Contiguous:
     2198        case Array::Double: {
     2199            LValue value;
     2200            LType refType;
     2201           
     2202            if (m_node->arrayMode().type() != Array::Double) {
     2203                value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
     2204                if (m_node->arrayMode().type() == Array::Int32) {
     2205                    FTL_TYPE_CHECK(
     2206                        jsValueValue(value), m_node->child2(), SpecInt32, isNotInt32(value));
     2207                }
     2208                refType = m_out.ref64;
     2209            } else {
     2210                value = lowDouble(m_node->child2());
     2211                FTL_TYPE_CHECK(
     2212                    doubleValue(value), m_node->child2(), SpecFullRealNumber,
     2213                    m_out.doubleNotEqualOrUnordered(value, value));
     2214                refType = m_out.refDouble;
     2215            }
     2216           
     2217            IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
     2218
     2219            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
     2220           
     2221            LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("ArrayPush fast path"));
     2222            LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("ArrayPush slow path"));
     2223            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPush continuation"));
     2224           
     2225            m_out.branch(
     2226                m_out.aboveOrEqual(
     2227                    prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
     2228                slowPath, fastPath);
     2229           
     2230            LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
     2231            m_out.store(
     2232                value,
     2233                m_out.baseIndex(heap, storage, m_out.zeroExt(prevLength, m_out.intPtr)),
     2234                refType);
     2235            LValue newLength = m_out.add(prevLength, m_out.int32One);
     2236            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
     2237           
     2238            ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
     2239            m_out.jump(continuation);
     2240           
     2241            m_out.appendTo(slowPath, continuation);
     2242            LValue operation;
     2243            if (m_node->arrayMode().type() != Array::Double)
     2244                operation = m_out.operation(operationArrayPush);
     2245            else
     2246                operation = m_out.operation(operationArrayPushDouble);
     2247            ValueFromBlock slowResult = m_out.anchor(
     2248                vmCall(operation, m_callFrame, value, base));
     2249            m_out.jump(continuation);
     2250           
     2251            m_out.appendTo(continuation, lastNext);
     2252            setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
     2253            return;
     2254        }
     2255           
     2256        default:
     2257            RELEASE_ASSERT_NOT_REACHED();
     2258            return;
     2259        }
     2260    }
     2261   
     2262    void compileArrayPop()
     2263    {
     2264        LValue base = lowCell(m_node->child1());
     2265        LValue storage = lowStorage(m_node->child2());
     2266       
     2267        switch (m_node->arrayMode().type()) {
     2268        case Array::Int32:
     2269        case Array::Double:
     2270        case Array::Contiguous: {
     2271            IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
     2272           
     2273            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("ArrayPop fast case"));
     2274            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArrayPop slow case"));
     2275            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPop continuation"));
     2276           
     2277            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
     2278           
     2279            Vector<ValueFromBlock, 3> results;
     2280            results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
     2281            m_out.branch(m_out.isZero32(prevLength), continuation, fastCase);
     2282           
     2283            LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
     2284            LValue newLength = m_out.sub(prevLength, m_out.int32One);
     2285            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
     2286            TypedPointer pointer = m_out.baseIndex(
     2287                heap, storage, m_out.zeroExt(newLength, m_out.intPtr));
     2288            if (m_node->arrayMode().type() != Array::Double) {
     2289                LValue result = m_out.load64(pointer);
     2290                m_out.store64(m_out.int64Zero, pointer);
     2291                results.append(m_out.anchor(result));
     2292                m_out.branch(m_out.notZero64(result), continuation, slowCase);
     2293            } else {
     2294                LValue result = m_out.loadDouble(pointer);
     2295                m_out.store64(m_out.constInt64(bitwise_cast<int64_t>(QNaN)), pointer);
     2296                results.append(m_out.anchor(boxDouble(result)));
     2297                m_out.branch(m_out.doubleEqual(result, result), continuation, slowCase);
     2298            }
     2299           
     2300            m_out.appendTo(slowCase, continuation);
     2301            results.append(m_out.anchor(vmCall(
     2302                m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
     2303            m_out.jump(continuation);
     2304           
     2305            m_out.appendTo(continuation, lastNext);
     2306            setJSValue(m_out.phi(m_out.int64, results));
     2307            return;
     2308        }
     2309
     2310        default:
     2311            RELEASE_ASSERT_NOT_REACHED();
     2312            return;
     2313        }
     2314    }
     2315   
    21842316    void compileNewObject()
    21852317    {
Note: See TracChangeset for help on using the changeset viewer.