Changeset 227874 in webkit


Ignore:
Timestamp:
Jan 30, 2018, 9:23:52 PM (7 years ago)
Author:
mark.lam@apple.com
Message:

Apply poisoning to TypedArray vector pointers.
https://bugs.webkit.org/show_bug.cgi?id=182155
<rdar://problem/36286266>

Reviewed by JF Bastien.

Source/JavaScriptCore:

The TypeArray's vector pointer is now poisoned. The poison value is chosen based
on a TypeArray's jsType. The JSType must be between FirstTypedArrayType and
LastTypedArrayType. At runtime, we enforce that the index is well-behaved by
masking it against TypedArrayPoisonIndexMask. TypedArrayPoisonIndexMask (16) is
the number of TypedArray types (10) rounded up to the next power of 2.
Accordingly, we reserve an array of TypedArrayPoisonIndexMask poisons so that we
can use index masking on the index, and be guaranteed that the masked index will
be within bounds of the poisons array.

  1. Fixed both DFG and FTL versions of compileGetTypedArrayByteOffset() to not do any unnecessary work if the TypedArray vector is null.

FTL's cagedMayBeNull() is no longer needed because it is only used by
compileGetTypedArrayByteOffset(), and we need to enhance it to handle unpoisoning
in a TypedArray specific way. So, might as well do the work inline in
compileGetTypedArrayByteOffset() instead.

  1. Removed an unnecessary null-check in DFGSpeculativeJIT's compileNewTypedArrayWithSize() because there's already a null check above it that ensures that sizeGPR is never null.
  1. In LLInt's _llint_op_get_by_val, move the TypedArray length check before the loading of the vector for unpoisoning and uncaging. We don't need the vector if the length is 0.

Implementation notes on the need to null check the TypeArray vector:

  1. DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds() does not need a m_poisonedVector null check because the function is a null check.
  1. DFG::SpeculativeJIT::compileGetIndexedPropertyStorage() does not need a m_poisonedVector null check because it is followed by a call to cageTypedArrayStorage() which assumes that storageReg cannot be null.
  1. DFG::SpeculativeJIT::compileGetTypedArrayByteOffset() already has a m_poisonedVector null check.
  1. DFG::SpeculativeJIT::compileNewTypedArrayWithSize() does not need a vector null check because the poisoning code is preceded by a sizeGPR null check, which ensures that the storageGPR (vector to be poisoned) is not null.
  1. FTL's compileGetIndexedPropertyStorage() does not need a m_poisonedVector null check because it is followed by a call to caged() which assumes that the vector cannot be null.
  1. FTL's compileGetTypedArrayByteOffset() already has a m_poisonedVector null check.
  1. FTL's compileNewTypedArray() does not need a vector null check because the poisoning code is preceded by a size null check, which ensures that the storage (vector to be poisoned) is not null.
  1. FTL's speculateTypedArrayIsNotNeutered() does not need a m_poisonedVector null check because the function is a null check.
  1. IntrinsicGetterAccessCase::emitIntrinsicGetter()'s TypedArrayByteOffsetIntrinsic case needs a null check so that it does not try to unpoison a null vector.
  1. JIT::emitIntTypedArrayGetByVal() does not need a vector null check because

we already do a length check even before loading the vector.

  1. JIT::emitFloatTypedArrayGetByVal() does not need a vector null check because

we already do a length check even before loading the vector.

  1. JIT::emitIntTypedArrayPutByVal() does not need a vector null check because

we already do a length check even before loading the vector.

  1. JIT::emitFloatTypedArrayPutByVal() does not need a vector null check because

we already do a length check even before loading the vector.

  1. LLInt's loadTypedArrayCaged() does not need a vector null check because its

client will do a TypedArray length check before calling it.

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::checkArray):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasArrayMode):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
(JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
(JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize):

  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileGetIndexedPropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffset):
(JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
(JSC::FTL::DFG::LowerDFGToB3::speculateTypedArrayIsNotNeutered):
(JSC::FTL::DFG::LowerDFGToB3::cagedMayBeNull): Deleted.

  • jit/IntrinsicEmitter.cpp:

(JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitIntTypedArrayGetByVal):
(JSC::JIT::emitFloatTypedArrayGetByVal):
(JSC::JIT::emitIntTypedArrayPutByVal):
(JSC::JIT::emitFloatTypedArrayPutByVal):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter64.asm:
  • offlineasm/arm64.rb:
  • offlineasm/x86.rb:
  • runtime/CagedBarrierPtr.h:
  • runtime/JSArrayBufferView.cpp:

(JSC::JSArrayBufferView::JSArrayBufferView):
(JSC::JSArrayBufferView::finalize):
(JSC::JSArrayBufferView::neuter):

  • runtime/JSArrayBufferView.h:

(JSC::JSArrayBufferView::vector const):
(JSC::JSArrayBufferView::offsetOfPoisonedVector):
(JSC::JSArrayBufferView::poisonFor):
(JSC::JSArrayBufferView::Poison::key):
(JSC::JSArrayBufferView::offsetOfVector): Deleted.

  • runtime/JSCPoison.cpp:

(JSC::initializePoison):

  • runtime/JSCPoison.h:
  • runtime/JSGenericTypedArrayViewInlines.h:

(JSC::JSGenericTypedArrayView<Adaptor>::estimatedSize):
(JSC::JSGenericTypedArrayView<Adaptor>::visitChildren):
(JSC::JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory):

  • runtime/JSObject.h:

Source/WTF:

  1. Added the ability to poison a CagedPtr.
  1. Prevent CagedPtr from being implicitly instantiated, and add operator= methods instead. This is because implicitly instantiated CagedPtrs with a poisoned trait may silently use a wrong poison value.
  • wtf/CagedPtr.h:

(WTF::CagedPtr::CagedPtr):
(WTF::CagedPtr::get const):
(WTF::CagedPtr::operator=):

Location:
trunk/Source
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r227872 r227874  
     12018-01-30  Mark Lam  <mark.lam@apple.com>
     2
     3        Apply poisoning to TypedArray vector pointers.
     4        https://bugs.webkit.org/show_bug.cgi?id=182155
     5        <rdar://problem/36286266>
     6
     7        Reviewed by JF Bastien.
     8
     9        The TypeArray's vector pointer is now poisoned.  The poison value is chosen based
     10        on a TypeArray's jsType.  The JSType must be between FirstTypedArrayType and
     11        LastTypedArrayType.  At runtime, we enforce that the index is well-behaved by
     12        masking it against TypedArrayPoisonIndexMask.  TypedArrayPoisonIndexMask (16) is
     13        the number of TypedArray types (10) rounded up to the next power of 2.
     14        Accordingly, we reserve an array of TypedArrayPoisonIndexMask poisons so that we
     15        can use index masking on the index, and be guaranteed that the masked index will
     16        be within bounds of the poisons array.
     17
     18        1. Fixed both DFG and FTL versions of compileGetTypedArrayByteOffset() to not
     19           do any unnecessary work if the TypedArray vector is null.
     20
     21           FTL's cagedMayBeNull() is no longer needed because it is only used by
     22           compileGetTypedArrayByteOffset(), and we need to enhance it to handle unpoisoning
     23           in a TypedArray specific way.  So, might as well do the work inline in
     24           compileGetTypedArrayByteOffset() instead.
     25
     26        2. Removed an unnecessary null-check in DFGSpeculativeJIT's compileNewTypedArrayWithSize()
     27           because there's already a null check above it that ensures that sizeGPR is
     28           never null.
     29
     30        3. In LLInt's _llint_op_get_by_val, move the TypedArray length check before the
     31           loading of the vector for unpoisoning and uncaging.  We don't need the vector
     32           if the length is 0.
     33
     34        Implementation notes on the need to null check the TypeArray vector:
     35
     36        1. DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds() does not need a
     37           m_poisonedVector null check because the function is a null check.
     38
     39        2. DFG::SpeculativeJIT::compileGetIndexedPropertyStorage() does not need a
     40           m_poisonedVector null check because it is followed by a call to
     41           cageTypedArrayStorage() which assumes that storageReg cannot be null.
     42
     43        3. DFG::SpeculativeJIT::compileGetTypedArrayByteOffset() already has a
     44           m_poisonedVector null check.
     45
     46        4. DFG::SpeculativeJIT::compileNewTypedArrayWithSize() does not need a vector null
     47           check because the poisoning code is preceded by a sizeGPR null check, which
     48           ensures that the storageGPR (vector to be poisoned) is not null.
     49
     50        5. FTL's compileGetIndexedPropertyStorage() does not need a m_poisonedVector null
     51           check because it is followed by a call to caged() which assumes that the
     52           vector cannot be null.
     53
     54        6. FTL's compileGetTypedArrayByteOffset() already has a m_poisonedVector null check.
     55
     56        7. FTL's compileNewTypedArray() does not need a vector null check because the
     57           poisoning code is preceded by a size null check, which ensures that the
     58           storage (vector to be poisoned) is not null.
     59
     60        8. FTL's speculateTypedArrayIsNotNeutered() does not need a
     61           m_poisonedVector null check because the function is a null check.
     62
     63        9. IntrinsicGetterAccessCase::emitIntrinsicGetter()'s TypedArrayByteOffsetIntrinsic
     64           case needs a null check so that it does not try to unpoison a null vector.
     65
     66        10. JIT::emitIntTypedArrayGetByVal() does not need a vector null check because
     67            we already do a length check even before loading the vector.
     68
     69        11. JIT::emitFloatTypedArrayGetByVal() does not need a vector null check because
     70            we already do a length check even before loading the vector.
     71
     72        12. JIT::emitIntTypedArrayPutByVal() does not need a vector null check because
     73            we already do a length check even before loading the vector.
     74
     75        13. JIT::emitFloatTypedArrayPutByVal() does not need a vector null check because
     76            we already do a length check even before loading the vector.
     77
     78        14. LLInt's loadTypedArrayCaged() does not need a vector null check because its
     79            client will do a TypedArray length check before calling it.
     80
     81        * dfg/DFGFixupPhase.cpp:
     82        (JSC::DFG::FixupPhase::checkArray):
     83        * dfg/DFGNode.h:
     84        (JSC::DFG::Node::hasArrayMode):
     85        * dfg/DFGSpeculativeJIT.cpp:
     86        (JSC::DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds):
     87        (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
     88        (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
     89        (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize):
     90        * ftl/FTLAbstractHeapRepository.h:
     91        * ftl/FTLLowerDFGToB3.cpp:
     92        (JSC::FTL::DFG::LowerDFGToB3::compileGetIndexedPropertyStorage):
     93        (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffset):
     94        (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
     95        (JSC::FTL::DFG::LowerDFGToB3::speculateTypedArrayIsNotNeutered):
     96        (JSC::FTL::DFG::LowerDFGToB3::cagedMayBeNull): Deleted.
     97        * jit/IntrinsicEmitter.cpp:
     98        (JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter):
     99        * jit/JITPropertyAccess.cpp:
     100        (JSC::JIT::emitIntTypedArrayGetByVal):
     101        (JSC::JIT::emitFloatTypedArrayGetByVal):
     102        (JSC::JIT::emitIntTypedArrayPutByVal):
     103        (JSC::JIT::emitFloatTypedArrayPutByVal):
     104        * llint/LowLevelInterpreter.asm:
     105        * llint/LowLevelInterpreter64.asm:
     106        * offlineasm/arm64.rb:
     107        * offlineasm/x86.rb:
     108        * runtime/CagedBarrierPtr.h:
     109        * runtime/JSArrayBufferView.cpp:
     110        (JSC::JSArrayBufferView::JSArrayBufferView):
     111        (JSC::JSArrayBufferView::finalize):
     112        (JSC::JSArrayBufferView::neuter):
     113        * runtime/JSArrayBufferView.h:
     114        (JSC::JSArrayBufferView::vector const):
     115        (JSC::JSArrayBufferView::offsetOfPoisonedVector):
     116        (JSC::JSArrayBufferView::poisonFor):
     117        (JSC::JSArrayBufferView::Poison::key):
     118        (JSC::JSArrayBufferView::offsetOfVector): Deleted.
     119        * runtime/JSCPoison.cpp:
     120        (JSC::initializePoison):
     121        * runtime/JSCPoison.h:
     122        * runtime/JSGenericTypedArrayViewInlines.h:
     123        (JSC::JSGenericTypedArrayView<Adaptor>::estimatedSize):
     124        (JSC::JSGenericTypedArrayView<Adaptor>::visitChildren):
     125        (JSC::JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory):
     126        * runtime/JSObject.h:
     127
    11282018-01-30  Fujii Hironori  <Hironori.Fujii@sony.com>
    2129
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r227723 r227874  
    11/*
    2  * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    28712871        }
    28722872       
     2873        ASSERT(arrayMode.type() == Array::String || arrayMode.typedArrayType() != NotTypedArray);
    28732874        return m_insertionSet.insertNode(
    28742875            m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r227723 r227874  
    28462846            JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
    28472847                MacroAssembler::Zero,
    2848                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
     2848                MacroAssembler::Address(base, JSArrayBufferView::offsetOfPoisonedVector()));
    28492849            speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
    28502850            notWasteful.link(&m_jit);
     
    63556355       
    63566356    default:
    6357         ASSERT(isTypedView(node->arrayMode().typedArrayType()));
    6358 
    6359         m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfVector()), storageReg);
     6357        auto typedArrayType = node->arrayMode().typedArrayType();
     6358        ASSERT_UNUSED(typedArrayType, isTypedView(typedArrayType));
     6359
     6360        m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfPoisonedVector()), storageReg);
     6361#if ENABLE(POISON)
     6362        m_jit.xorPtr(JITCompiler::TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), storageReg);
     6363#endif
    63606364        cageTypedArrayStorage(storageReg);
    63616365        break;
     
    63746378    GPRReg vectorGPR = vector.gpr();
    63756379    GPRReg dataGPR = data.gpr();
    6376    
     6380    ASSERT(baseGPR != vectorGPR);
     6381    ASSERT(baseGPR != dataGPR);
     6382    ASSERT(vectorGPR != dataGPR);
     6383
     6384#if ENABLE(POISON)
     6385    GPRTemporary poison(this);
     6386    GPRTemporary index(this);
     6387    GPRReg poisonGPR = poison.gpr();
     6388    GPRReg indexGPR = index.gpr();
     6389    GPRReg arrayBufferGPR = poisonGPR;
     6390#else
     6391    GPRReg arrayBufferGPR = dataGPR;
     6392#endif
     6393
    63776394    JITCompiler::Jump emptyByteOffset = m_jit.branch32(
    63786395        MacroAssembler::NotEqual,
     
    63806397        TrustedImm32(WastefulTypedArray));
    63816398
     6399    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfPoisonedVector()), vectorGPR);
     6400    JITCompiler::Jump nullVector = m_jit.branchTestPtr(JITCompiler::Zero, vectorGPR);
     6401
    63826402    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
    63836403    m_jit.cage(Gigacage::JSValue, dataGPR);
    6384     m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
    6385     JITCompiler::Jump nullVector = m_jit.branchTestPtr(JITCompiler::Zero, vectorGPR);
     6404
     6405#if ENABLE(POISON)
     6406    m_jit.load8(JITCompiler::Address(baseGPR, JSCell::typeInfoTypeOffset()), indexGPR);
     6407    m_jit.move(JITCompiler::TrustedImmPtr(&g_typedArrayPoisons), poisonGPR);
     6408    m_jit.sub32(JITCompiler::TrustedImm32(FirstTypedArrayType), indexGPR);
     6409    m_jit.and32(JITCompiler::TrustedImm32(TypedArrayPoisonIndexMask), indexGPR);
     6410    m_jit.loadPtr(JITCompiler::BaseIndex(poisonGPR, indexGPR, JITCompiler::timesPtr()), poisonGPR);
     6411    m_jit.xorPtr(poisonGPR, vectorGPR);
     6412#endif
    63866413    cageTypedArrayStorage(vectorGPR);
    63876414
    6388     m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), dataGPR);
     6415    m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), arrayBufferGPR);
    63896416    // FIXME: This needs caging.
    63906417    // https://bugs.webkit.org/show_bug.cgi?id=175515
    6391     m_jit.loadPtr(MacroAssembler::Address(dataGPR, ArrayBuffer::offsetOfData()), dataGPR);
     6418    m_jit.loadPtr(MacroAssembler::Address(arrayBufferGPR, ArrayBuffer::offsetOfData()), dataGPR);
    63926419    m_jit.subPtr(dataGPR, vectorGPR);
    63936420   
     
    90269053        storageGPR, m_jit.vm()->primitiveGigacageAuxiliarySpace, scratchGPR, scratchGPR,
    90279054        scratchGPR2, slowCases);
    9028    
    9029     MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, sizeGPR);
     9055
    90309056    m_jit.move(sizeGPR, scratchGPR);
    90319057    if (elementSize(typedArrayType) != 4) {
     
    90459071        MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesFour));
    90469072    m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
    9047     done.link(&m_jit);
    90489073
    90499074    auto butterfly = TrustedImmPtr(nullptr);
     
    90539078        slowCases);
    90549079
     9080#if ENABLE(POISON)
     9081    m_jit.move(storageGPR, scratchGPR);
     9082    m_jit.xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), scratchGPR);
     9083    m_jit.storePtr(
     9084        scratchGPR,
     9085        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfPoisonedVector()));
     9086#else
    90559087    m_jit.storePtr(
    90569088        storageGPR,
    9057         MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector()));
     9089        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfPoisonedVector()));
     9090#endif
    90589091    m_jit.store32(
    90599092        sizeGPR,
  • trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

    r227617 r227874  
    6060    macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
    6161    macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
    62     macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
     62    macro(JSArrayBufferView_poisonedVector, JSArrayBufferView::offsetOfPoisonedVector()) \
    6363    macro(JSCell_cellState, JSCell::cellStateOffset()) \
    6464    macro(JSCell_header, 0) \
     
    150150    macro(HasOwnPropertyCache, 0, sizeof(HasOwnPropertyCache::Entry)) \
    151151    macro(JSFixedArray_buffer, JSFixedArray::offsetOfData(), sizeof(EncodedJSValue)) \
    152    
     152    macro(TypedArrayPoisons, 0, sizeof(uintptr_t)) \
     153
    153154#define FOR_EACH_NUMBERED_ABSTRACT_HEAP(macro) \
    154155    macro(properties)
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r227723 r227874  
    34743474
    34753475        DFG_ASSERT(m_graph, m_node, isTypedView(m_node->arrayMode().typedArrayType()));
    3476         setStorage(caged(Gigacage::Primitive, m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector)));
     3476        LValue poisonedVector = m_out.loadPtr(cell, m_heaps.JSArrayBufferView_poisonedVector);
     3477#if ENABLE(POISON)
     3478        auto typedArrayType = m_node->arrayMode().typedArrayType();
     3479        LValue vector = m_out.bitXor(m_out.constIntPtr(JSArrayBufferView::poisonFor(typedArrayType)), poisonedVector);
     3480#else
     3481        LValue vector = poisonedVector;
     3482#endif
     3483        setStorage(caged(Gigacage::Primitive, vector));
    34773484    }
    34783485   
     
    34963503        LBasicBlock simpleCase = m_out.newBlock();
    34973504        LBasicBlock wastefulCase = m_out.newBlock();
     3505        LBasicBlock notNull = m_out.newBlock();
    34983506        LBasicBlock continuation = m_out.newBlock();
    34993507       
     
    35093517        m_out.jump(continuation);
    35103518
    3511         m_out.appendTo(wastefulCase, continuation);
    3512 
    3513         LValue vectorPtr = cagedMayBeNull(
    3514             Gigacage::Primitive,
    3515             m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector));
     3519        m_out.appendTo(wastefulCase, notNull);
     3520
     3521        LValue poisonedVector = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_poisonedVector);
     3522        ValueFromBlock nullVectorOut = m_out.anchor(poisonedVector);
     3523        m_out.branch(poisonedVector, unsure(notNull), unsure(continuation));
     3524
     3525        m_out.appendTo(notNull, continuation);
     3526
    35163527        LValue butterflyPtr = caged(Gigacage::JSValue, m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly));
    35173528        LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
     3529
     3530#if ENABLE(POISON)
     3531        LValue jsType = m_out.load8ZeroExt32(basePtr, m_heaps.JSCell_typeInfoType);
     3532        LValue typeIndex = m_out.sub(jsType, m_out.constInt32(FirstTypedArrayType));
     3533        LValue maskedTypeIndex = m_out.zeroExtPtr(m_out.bitAnd(typeIndex, m_out.constInt32(TypedArrayPoisonIndexMask)));
     3534        LValue poisonsBasePtr = m_out.constIntPtr(&g_typedArrayPoisons);
     3535        LValue poison = m_out.loadPtr(m_out.baseIndex(m_heaps.TypedArrayPoisons, poisonsBasePtr, maskedTypeIndex));
     3536        poisonedVector = m_out.bitXor(poisonedVector, poison);
     3537#endif
     3538        LValue vectorPtr = caged(Gigacage::Primitive, poisonedVector);
     3539
    35183540        // FIXME: This needs caging.
    35193541        // https://bugs.webkit.org/show_bug.cgi?id=175515
     
    35253547        m_out.appendTo(continuation, lastNext);
    35263548
    3527         setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, wastefulOut)));
     3549        setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, nullVectorOut, wastefulOut)));
    35283550    }
    35293551
     
    56385660                allocateObject<JSArrayBufferView>(structure, m_out.intPtrZero, indexingMask, slowCase);
    56395661
    5640             m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
     5662#if ENABLE(POISON)
     5663            storage = m_out.bitXor(m_out.constIntPtr(JSArrayBufferView::poisonFor(typedArrayType)), storage);
     5664#endif
     5665            m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_poisonedVector);
    56415666            m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
    56425667            m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
     
    1279512820        // https://bugs.webkit.org/show_bug.cgi?id=175493
    1279612821        return m_out.opaque(result);
    12797     }
    12798    
    12799     LValue cagedMayBeNull(Gigacage::Kind kind, LValue ptr)
    12800     {
    12801         LBasicBlock notNull = m_out.newBlock();
    12802         LBasicBlock continuation = m_out.newBlock();
    12803        
    12804         LBasicBlock lastNext = m_out.insertNewBlocksBefore(notNull);
    12805        
    12806         ValueFromBlock nullResult = m_out.anchor(ptr);
    12807         m_out.branch(ptr, unsure(notNull), unsure(continuation));
    12808        
    12809         m_out.appendTo(notNull, continuation);
    12810         ValueFromBlock notNullResult = m_out.anchor(caged(kind, ptr));
    12811         m_out.jump(continuation);
    12812        
    12813         m_out.appendTo(continuation, lastNext);
    12814         return m_out.phi(pointerType(), nullResult, notNullResult);
    1281512822    }
    1281612823   
     
    1501615023
    1501715024        LBasicBlock lastNext = m_out.appendTo(isWasteful, continuation);
    15018         LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_vector);
     15025        LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_poisonedVector);
    1501915026        speculate(Uncountable, jsValueValue(vector), m_node, m_out.isZero64(vector));
    1502015027        m_out.jump(continuation);
  • trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp

    r225071 r227874  
    11/*
    2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    108108        GPRReg scratchGPR = state.scratchGPR;
    109109
    110         CCallHelpers::Jump emptyByteOffset = jit.branch32(
    111             MacroAssembler::NotEqual,
     110        CCallHelpers::Jump notEmptyByteOffset = jit.branch32(
     111            MacroAssembler::Equal,
    112112            MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
    113113            TrustedImm32(WastefulTypedArray));
    114114
     115        jit.move(TrustedImmPtr(0), valueGPR);
     116        CCallHelpers::Jump done = jit.jump();
     117
     118        notEmptyByteOffset.link(&jit);
     119
     120        // We need to load the butterfly before the vector because baseGPR and valueGPR
     121        // can be the same register.
    115122        jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
    116         jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), valueGPR);
     123        jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfPoisonedVector()), valueGPR);
     124        CCallHelpers::Jump nullVector = jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
     125
     126#if ENABLE(POISON)
     127        auto typedArrayType = structure()->classInfo()->typedArrayStorageType;
     128        jit.xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), valueGPR);
     129#endif
    117130        jit.loadPtr(MacroAssembler::Address(scratchGPR, Butterfly::offsetOfArrayBuffer()), scratchGPR);
    118131        jit.loadPtr(MacroAssembler::Address(scratchGPR, ArrayBuffer::offsetOfData()), scratchGPR);
    119132        jit.subPtr(scratchGPR, valueGPR);
    120133
    121         CCallHelpers::Jump done = jit.jump();
    122        
    123         emptyByteOffset.link(&jit);
    124         jit.move(TrustedImmPtr(0), valueGPR);
    125        
     134        nullVector.link(&jit);
    126135        done.link(&jit);
    127136       
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r227643 r227874  
    11/*
    2  * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    14581458}
    14591459
    1460 JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType type)
    1461 {
    1462     ASSERT(isInt(type));
     1460JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType typeArrayType)
     1461{
     1462    ASSERT(isInt(typeArrayType));
    14631463   
    14641464    // The best way to test the array type is to use the classInfo. We need to do so without
     
    14811481   
    14821482    JumpList slowCases;
    1483    
     1483    JSType jsType = typeForTypedArrayType(typeArrayType);
     1484
    14841485    load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
    1485     badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
     1486    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(jsType));
    14861487    slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
    1487     loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
     1488    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), scratch);
     1489#if ENABLE(POISON)
     1490    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), scratch);
     1491#endif
    14881492    cageConditionally(Gigacage::Primitive, scratch, scratch2);
    14891493
    1490     switch (elementSize(type)) {
     1494    switch (elementSize(typeArrayType)) {
    14911495    case 1:
    1492         if (JSC::isSigned(type))
     1496        if (JSC::isSigned(typeArrayType))
    14931497            load8SignedExtendTo32(BaseIndex(scratch, property, TimesOne), resultPayload);
    14941498        else
     
    14961500        break;
    14971501    case 2:
    1498         if (JSC::isSigned(type))
     1502        if (JSC::isSigned(typeArrayType))
    14991503            load16SignedExtendTo32(BaseIndex(scratch, property, TimesTwo), resultPayload);
    15001504        else
     
    15091513   
    15101514    Jump done;
    1511     if (type == TypeUint32) {
     1515    if (typeArrayType == TypeUint32) {
    15121516        Jump canBeInt = branch32(GreaterThanOrEqual, resultPayload, TrustedImm32(0));
    15131517       
     
    15351539}
    15361540
    1537 JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType type)
    1538 {
    1539     ASSERT(isFloat(type));
     1541JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType typeArrayType)
     1542{
     1543    ASSERT(isFloat(typeArrayType));
    15401544   
    15411545#if USE(JSVALUE64)
     
    15551559   
    15561560    JumpList slowCases;
     1561    JSType jsType = typeForTypedArrayType(typeArrayType);
    15571562
    15581563    load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
    1559     badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
     1564    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(jsType));
    15601565    slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
    1561     loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
     1566    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), scratch);
     1567#if ENABLE(POISON)
     1568    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), scratch);
     1569#endif
    15621570    cageConditionally(Gigacage::Primitive, scratch, scratch2);
    15631571   
    1564     switch (elementSize(type)) {
     1572    switch (elementSize(typeArrayType)) {
    15651573    case 4:
    15661574        loadFloat(BaseIndex(scratch, property, TimesFour), fpRegT0);
     
    15891597}
    15901598
    1591 JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType type)
     1599JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType typeArrayType)
    15921600{
    15931601    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
    1594     ASSERT(isInt(type));
     1602    ASSERT(isInt(typeArrayType));
    15951603   
    15961604    int value = currentInstruction[3].u.operand;
     
    16111619   
    16121620    JumpList slowCases;
    1613    
     1621    JSType jsType = typeForTypedArrayType(typeArrayType);
     1622
    16141623    load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
    1615     badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
     1624    badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(jsType));
    16161625    Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
    16171626    emitArrayProfileOutOfBoundsSpecialCase(profile);
     
    16291638    // We would be loading this into base as in get_by_val, except that the slow
    16301639    // path expects the base to be unclobbered.
    1631     loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
     1640    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), lateScratch);
     1641#if ENABLE(POISON)
     1642    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), lateScratch);
     1643#endif
    16321644    cageConditionally(Gigacage::Primitive, lateScratch, lateScratch2);
    16331645   
    1634     if (isClamped(type)) {
    1635         ASSERT(elementSize(type) == 1);
    1636         ASSERT(!JSC::isSigned(type));
     1646    if (isClamped(typeArrayType)) {
     1647        ASSERT(elementSize(typeArrayType) == 1);
     1648        ASSERT(!JSC::isSigned(typeArrayType));
    16371649        Jump inBounds = branch32(BelowOrEqual, earlyScratch, TrustedImm32(0xff));
    16381650        Jump tooBig = branch32(GreaterThan, earlyScratch, TrustedImm32(0xff));
     
    16451657    }
    16461658   
    1647     switch (elementSize(type)) {
     1659    switch (elementSize(typeArrayType)) {
    16481660    case 1:
    16491661        store8(earlyScratch, BaseIndex(lateScratch, property, TimesOne));
     
    16621674}
    16631675
    1664 JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType type)
     1676JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType typeArrayType)
    16651677{
    16661678    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
    1667     ASSERT(isFloat(type));
     1679    ASSERT(isFloat(typeArrayType));
    16681680   
    16691681    int value = currentInstruction[3].u.operand;
     
    16841696   
    16851697    JumpList slowCases;
    1686    
     1698    JSType jsType = typeForTypedArrayType(typeArrayType);
     1699
    16871700    load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
    1688     badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
     1701    badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(jsType));
    16891702    Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
    16901703    emitArrayProfileOutOfBoundsSpecialCase(profile);
     
    17151728    // We would be loading this into base as in get_by_val, except that the slow
    17161729    // path expects the base to be unclobbered.
    1717     loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
     1730    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), lateScratch);
     1731#if ENABLE(POISON)
     1732    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), lateScratch);
     1733#endif
    17181734    cageConditionally(Gigacage::Primitive, lateScratch, lateScratch2);
    17191735   
    1720     switch (elementSize(type)) {
     1736    switch (elementSize(typeArrayType)) {
    17211737    case 4:
    17221738        convertDoubleToFloat(fpRegT0, fpRegT0);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r227717 r227874  
    395395const FirstArrayType = constexpr FirstTypedArrayType
    396396const NumberOfTypedArrayTypesExcludingDataView = constexpr NumberOfTypedArrayTypesExcludingDataView
     397const TypedArrayPoisonIndexMask = constexpr TypedArrayPoisonIndexMask
    397398
    398399# Type flags constants.
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r227717 r227874  
    377377end
    378378
    379 macro loadCaged(basePtr, mask, source, dest, scratch)
    380     loadp source, dest
     379macro uncage(basePtr, mask, ptr, scratch)
    381380    if GIGACAGE_ENABLED and not C_LOOP
    382381        loadp basePtr, scratch
    383382        btpz scratch, .done
    384         andp mask, dest
    385         addp scratch, dest
     383        andp mask, ptr
     384        addp scratch, ptr
    386385    .done:
    387386    end
     387end
     388
     389macro loadCaged(basePtr, mask, source, dest, scratch)
     390    loadp source, dest
     391    uncage(basePtr, mask, dest, scratch)
     392end
     393
     394macro loadTypedArrayCaged(basePtr, mask, source, typeIndex, dest, scratch)
     395    if POISON
     396        andp TypedArrayPoisonIndexMask, typeIndex
     397        leap _g_typedArrayPoisons, dest
     398        loadp [dest, typeIndex, 8], dest
     399        loadp source, scratch
     400        xorp scratch, dest
     401    else
     402        loadp source, dest
     403    end
     404    uncage(basePtr, mask, dest, scratch)
    388405end
    389406
     
    15421559   
    15431560    # Sweet, now we know that we have a typed array. Do some basic things now.
    1544     loadCaged(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr PRIMITIVE_GIGACAGE_MASK, JSArrayBufferView::m_vector[t0], t3, t5)
    15451561    biaeq t1, JSArrayBufferView::m_length[t0], .opGetByValSlow
    1546    
     1562    loadTypedArrayCaged(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr PRIMITIVE_GIGACAGE_MASK, JSArrayBufferView::m_poisonedVector[t0], t2, t3, t5)
     1563
    15471564    # Now bisect through the various types:
    15481565    #    Int8ArrayType,
  • trunk/Source/JavaScriptCore/offlineasm/arm64.rb

    r224171 r227874  
    273273                    newList << Instruction.new(codeOrigin, "globaladdr", [LabelReference.new(node.codeOrigin, labelRef.label), tmp])
    274274                    newList << Instruction.new(codeOrigin, node.opcode, [Address.new(node.codeOrigin, tmp, Immediate.new(node.codeOrigin, labelRef.offset)), node.operands[1]])
     275                else
     276                    newList << node
     277                end
     278            when "leai", "leap", "leaq"
     279                labelRef = node.operands[0]
     280                if labelRef.is_a? LabelReference
     281                    newList << Instruction.new(codeOrigin, "globaladdr", [LabelReference.new(node.codeOrigin, labelRef.label), node.operands[1]])
    275282                else
    276283                    newList << node
  • trunk/Source/JavaScriptCore/offlineasm/x86.rb

    r222549 r227874  
    469469        "#{offset}(#{dst.x86Operand(kind)})"
    470470    end
     471    def x86AddressOperand(addressKind)
     472        # FIXME: Implement this on platforms that aren't Mach-O.
     473        # https://bugs.webkit.org/show_bug.cgi?id=175104
     474        "#{asmLabel}@GOTPCREL(%rip)"
     475    end
    471476end
    472477
     
    580585        else
    581586            raise
     587        end
     588    end
     589
     590    def emitX86Lea(src, dst, kind)
     591        if src.is_a? LabelReference
     592            $asm.puts "movq #{src.asmLabel}@GOTPCREL(%rip), #{dst.x86Operand(:ptr)}"
     593            $asm.puts "mov#{x86Suffix(kind)} #{orderOperands(dst.x86Operand(kind), dst.x86Operand(kind))}"
     594        else
     595            $asm.puts "lea#{x86Suffix(kind)} #{orderOperands(src.x86AddressOperand(kind), dst.x86Operand(kind))}"
    582596        end
    583597    end
     
    15431557            $asm.puts "jnz #{operands[0].asmLabel}"
    15441558        when "leai"
    1545             $asm.puts "lea#{x86Suffix(:int)} #{orderOperands(operands[0].x86AddressOperand(:int), operands[1].x86Operand(:int))}"
     1559            emitX86Lea(operands[0], operands[1], :int)
    15461560        when "leap"
    1547             $asm.puts "lea#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86AddressOperand(:ptr), operands[1].x86Operand(:ptr))}"
     1561            emitX86Lea(operands[0], operands[1], :ptr)
    15481562        when "memfence"
    15491563            sp = RegisterID.new(nil, "sp")
  • trunk/Source/JavaScriptCore/runtime/CagedBarrierPtr.h

    r221439 r227874  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727
    2828#include "AuxiliaryBarrier.h"
     29#include <type_traits>
    2930#include <wtf/CagedPtr.h>
     31
     32namespace WTF {
     33
     34template<typename Poison, typename T> struct PoisonedPtrTraits;
     35
     36} // namespace WTF
    3037
    3138namespace JSC {
     
    3643// This is a convenient combo of AuxiliaryBarrier and CagedPtr.
    3744
    38 template<Gigacage::Kind passedKind, typename T>
     45template<Gigacage::Kind passedKind, typename T, typename PtrTraits = WTF::DumbPtrTraits<T>>
    3946class CagedBarrierPtr {
    4047public:
     
    8693   
    8794private:
    88     AuxiliaryBarrier<CagedPtr<kind, T>> m_barrier;
     95    AuxiliaryBarrier<CagedPtr<kind, T, PtrTraits>> m_barrier;
    8996};
    9097
    91 template<Gigacage::Kind passedKind>
    92 class CagedBarrierPtr<passedKind, void> {
     98template<Gigacage::Kind passedKind, typename PtrTraits>
     99class CagedBarrierPtr<passedKind, void, PtrTraits> {
    93100public:
    94101    static constexpr Gigacage::Kind kind = passedKind;
     
    133140   
    134141private:
    135     AuxiliaryBarrier<CagedPtr<kind, void>> m_barrier;
     142    AuxiliaryBarrier<CagedPtr<kind, void, PtrTraits>> m_barrier;
    136143};
    137144
     145template<typename Poison, Gigacage::Kind passedKind, typename T>
     146using PoisonedCagedBarrierPtr = CagedBarrierPtr<passedKind, T, WTF::PoisonedPtrTraits<Poison, T>>;
     147
    138148} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp

    r227617 r227874  
    11/*
    2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    133133{
    134134    setButterflyWithIndexingMask(vm, context.butterfly(), WTF::computeIndexingMask(length()));
    135     m_vector.setWithoutBarrier(context.vector());
     135    m_poisonedVector.setWithoutBarrier(context.vector());
    136136}
    137137
     
    194194    ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray);
    195195    if (thisObject->m_mode == OversizeTypedArray)
    196         Gigacage::free(Gigacage::Primitive, thisObject->m_vector.get());
     196        Gigacage::free(Gigacage::Primitive, thisObject->m_poisonedVector.get());
    197197}
    198198
     
    212212    RELEASE_ASSERT(!isShared());
    213213    m_length = 0;
    214     m_vector.clear();
     214    m_poisonedVector.clear();
    215215}
    216216
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h

    r221439 r227874  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727
    2828#include "AuxiliaryBarrier.h"
     29#include "CagedBarrierPtr.h"
     30#include "JSCPoison.h"
    2931#include "JSObject.h"
     32#include "TypedArrayType.h"
     33#include <wtf/MathExtras.h>
    3034
    3135namespace JSC {
    3236
    3337class LLIntOffsetsExtractor;
     38
     39// Since we'll be indexing into the g_typedArrayPoisons array based on the TypedArray type,
     40// we'll index mask the index value and round up to the array size to the next power of 2 to
     41// ensure that we'll never be able to access beyond the bounds of this array.
     42static constexpr uint32_t NumberOfTypedArrayPoisons = WTF::roundUpToPowerOfTwo(NumberOfTypedArrayTypes);
     43static constexpr uint32_t TypedArrayPoisonIndexMask = NumberOfTypedArrayPoisons - 1;
    3444
    3545// This class serves two purposes:
     
    168178    void neuter();
    169179   
    170     void* vector() const { return m_vector.getMayBeNull(); }
     180    void* vector() const { return m_poisonedVector.getMayBeNull(); }
    171181   
    172182    unsigned byteOffset();
     
    175185    DECLARE_EXPORT_INFO;
    176186   
    177     static ptrdiff_t offsetOfVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_vector); }
     187    static ptrdiff_t offsetOfPoisonedVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_poisonedVector); }
    178188    static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(JSArrayBufferView, m_length); }
    179189    static ptrdiff_t offsetOfMode() { return OBJECT_OFFSETOF(JSArrayBufferView, m_mode); }
     
    181191    static RefPtr<ArrayBufferView> toWrapped(VM&, JSValue);
    182192
     193    static uintptr_t poisonFor(JSType type)
     194    {
     195        return g_typedArrayPoisons[(type - FirstTypedArrayType) & TypedArrayPoisonIndexMask];
     196    }
     197
     198    static uintptr_t poisonFor(TypedArrayType typedArrayType)
     199    {
     200        ASSERT(isTypedView(typedArrayType));
     201        return poisonFor(typeForTypedArrayType(typedArrayType));
     202    }
     203
    183204private:
    184205    static void finalize(JSCell*);
     
    191212    static String toStringName(const JSObject*, ExecState*);
    192213
    193     CagedBarrierPtr<Gigacage::Primitive, void> m_vector;
     214    class Poison {
     215    public:
     216        template<typename PoisonedType>
     217        inline static uintptr_t key(const PoisonedType* poisonedPtr)
     218        {
     219            uintptr_t poisonedVectorAddress = bitwise_cast<uintptr_t>(poisonedPtr);
     220            uintptr_t baseAddress = poisonedVectorAddress - OBJECT_OFFSETOF(JSArrayBufferView, m_poisonedVector);
     221            JSArrayBufferView* thisObject = bitwise_cast<JSArrayBufferView*>(baseAddress);
     222            return poisonFor(thisObject->type());
     223        }
     224    };
     225
     226    PoisonedCagedBarrierPtr<Poison, Gigacage::Primitive, void> m_poisonedVector;
    194227    uint32_t m_length;
    195228    TypedArrayMode m_mode;
  • trunk/Source/JavaScriptCore/runtime/JSCPoison.cpp

    r227527 r227874  
    2727#include "JSCPoison.h"
    2828
     29#include "JSArrayBufferView.h"
    2930#include "Options.h"
    3031#include <mutex>
     
    3637    uintptr_t POISON_KEY_NAME(poisonID);
    3738FOR_EACH_JSC_POISON(DEFINE_POISON)
     39
     40uintptr_t g_typedArrayPoisons[NumberOfTypedArrayPoisons];
    3841
    3942void initializePoison()
     
    4851
    4952        FOR_EACH_JSC_POISON(INITIALIZE_POISON)
     53
     54        for (uint32_t i = 0; i < NumberOfTypedArrayPoisons; ++i)
     55            g_typedArrayPoisons[i] = makePoison();
    5056    });
    5157}
  • trunk/Source/JavaScriptCore/runtime/JSCPoison.h

    r227527 r227874  
    6565#undef DECLARE_POISON
    6666
     67extern "C" JS_EXPORTDATA uintptr_t g_typedArrayPoisons[];
     68
    6769struct ClassInfo;
    6870
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h

    r226461 r227874  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    505505    if (thisObject->m_mode == OversizeTypedArray)
    506506        return Base::estimatedSize(thisObject) + thisObject->byteSize();
    507     if (thisObject->m_mode == FastTypedArray && thisObject->m_vector)
     507    if (thisObject->m_mode == FastTypedArray && thisObject->m_poisonedVector)
    508508        return Base::estimatedSize(thisObject) + thisObject->byteSize();
    509509
     
    518518    switch (thisObject->m_mode) {
    519519    case FastTypedArray: {
    520         if (void* vector = thisObject->m_vector.getMayBeNull())
     520        if (void* vector = thisObject->m_poisonedVector.getMayBeNull())
    521521            visitor.markAuxiliary(vector);
    522522        break;
     
    586586
    587587    thisObject->butterfly()->indexingHeader()->setArrayBuffer(buffer.get());
    588     thisObject->m_vector.setWithoutBarrier(buffer->data());
     588    thisObject->m_poisonedVector.setWithoutBarrier(buffer->data());
    589589    WTF::storeStoreFence();
    590590    thisObject->m_mode = WastefulTypedArray;
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r226000 r227874  
    2525#include "ArrayConventions.h"
    2626#include "ArrayStorage.h"
     27#include "AuxiliaryBarrier.h"
    2728#include "Butterfly.h"
    2829#include "CPU.h"
    29 #include "CagedBarrierPtr.h"
    3030#include "CallFrame.h"
    3131#include "ClassInfo.h"
  • trunk/Source/WTF/ChangeLog

    r227872 r227874  
     12018-01-30  Mark Lam  <mark.lam@apple.com>
     2
     3        Apply poisoning to TypedArray vector pointers.
     4        https://bugs.webkit.org/show_bug.cgi?id=182155
     5        <rdar://problem/36286266>
     6
     7        Reviewed by JF Bastien.
     8
     9        1. Added the ability to poison a CagedPtr.
     10
     11        2. Prevent CagedPtr from being implicitly instantiated, and add operator= methods
     12           instead.  This is because implicitly instantiated CagedPtrs with a poisoned
     13           trait may silently use a wrong poison value.
     14
     15        * wtf/CagedPtr.h:
     16        (WTF::CagedPtr::CagedPtr):
     17        (WTF::CagedPtr::get const):
     18        (WTF::CagedPtr::operator=):
     19
    1202018-01-30  Fujii Hironori  <Hironori.Fujii@sony.com>
    221
  • trunk/Source/WTF/wtf/CagedPtr.h

    r221439 r227874  
    2626#pragma once
    2727
     28#include <wtf/DumbPtrTraits.h>
    2829#include <wtf/Gigacage.h>
    2930
    3031namespace WTF {
    3132
    32 template<Gigacage::Kind passedKind, typename T>
     33template<Gigacage::Kind passedKind, typename T, typename PtrTraits = DumbPtrTraits<T>>
    3334class CagedPtr {
    3435public:
    3536    static constexpr Gigacage::Kind kind = passedKind;
    36    
    37     CagedPtr(T* ptr = nullptr)
     37
     38    CagedPtr() : CagedPtr(nullptr) { }
     39    CagedPtr(std::nullptr_t) : m_ptr(nullptr) { }
     40
     41    explicit CagedPtr(T* ptr)
    3842        : m_ptr(ptr)
    3943    {
     
    4347    {
    4448        ASSERT(m_ptr);
    45         return Gigacage::caged(kind, m_ptr);
     49        return Gigacage::caged(kind, PtrTraits::unwrap(m_ptr));
    4650    }
    4751   
     
    5256        return get();
    5357    }
    54    
     58
     59    CagedPtr& operator=(T* ptr)
     60    {
     61        m_ptr = ptr;
     62        return *this;
     63    }
     64
     65    CagedPtr& operator=(T*&& ptr)
     66    {
     67        m_ptr = WTFMove(ptr);
     68        return *this;
     69    }
     70
    5571    bool operator==(const CagedPtr& other) const
    5672    {
     
    7591   
    7692protected:
    77     T* m_ptr;
     93    typename PtrTraits::StorageType m_ptr;
    7894};
    7995
    80 template<Gigacage::Kind passedKind>
    81 class CagedPtr<passedKind, void> {
     96template<Gigacage::Kind passedKind, typename PtrTraits>
     97class CagedPtr<passedKind, void, PtrTraits> {
    8298public:
    8399    static constexpr Gigacage::Kind kind = passedKind;
    84    
    85     CagedPtr(void* ptr = nullptr)
     100
     101    CagedPtr() : CagedPtr(nullptr) { }
     102    CagedPtr(std::nullptr_t) : m_ptr(nullptr) { }
     103
     104    explicit CagedPtr(void* ptr)
    86105        : m_ptr(ptr)
    87106    {
     
    91110    {
    92111        ASSERT(m_ptr);
    93         return Gigacage::caged(kind, m_ptr);
     112        return Gigacage::caged(kind, PtrTraits::unwrap(m_ptr));
    94113    }
    95114   
     
    100119        return get();
    101120    }
    102    
     121
     122    CagedPtr& operator=(void* ptr)
     123    {
     124        m_ptr = ptr;
     125        return *this;
     126    }
     127
    103128    bool operator==(const CagedPtr& other) const
    104129    {
     
    117142   
    118143protected:
    119     void* m_ptr;
     144    typename PtrTraits::StorageType m_ptr;
    120145};
    121146
Note: See TracChangeset for help on using the changeset viewer.