Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (227873 => 227874)
--- trunk/Source/_javascript_Core/ChangeLog 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,3 +1,130 @@
+2018-01-30 Mark Lam <[email protected]>
+
+ Apply poisoning to TypedArray vector pointers.
+ https://bugs.webkit.org/show_bug.cgi?id=182155
+ <rdar://problem/36286266>
+
+ Reviewed by JF Bastien.
+
+ 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.
+
+ 2. 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.
+
+ 3. 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.
+
+ 2. 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.
+
+ 3. DFG::SpeculativeJIT::compileGetTypedArrayByteOffset() already has a
+ m_poisonedVector null check.
+
+ 4. 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.
+
+ 5. 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.
+
+ 6. FTL's compileGetTypedArrayByteOffset() already has a m_poisonedVector null check.
+
+ 7. 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.
+
+ 8. FTL's speculateTypedArrayIsNotNeutered() does not need a
+ m_poisonedVector null check because the function is a null check.
+
+ 9. IntrinsicGetterAccessCase::emitIntrinsicGetter()'s TypedArrayByteOffsetIntrinsic
+ case needs a null check so that it does not try to unpoison a null vector.
+
+ 10. JIT::emitIntTypedArrayGetByVal() does not need a vector null check because
+ we already do a length check even before loading the vector.
+
+ 11. JIT::emitFloatTypedArrayGetByVal() does not need a vector null check because
+ we already do a length check even before loading the vector.
+
+ 12. JIT::emitIntTypedArrayPutByVal() does not need a vector null check because
+ we already do a length check even before loading the vector.
+
+ 13. JIT::emitFloatTypedArrayPutByVal() does not need a vector null check because
+ we already do a length check even before loading the vector.
+
+ 14. 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:
+
2018-01-30 Fujii Hironori <[email protected]>
[Win] Warning fix.
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -2870,6 +2870,7 @@
m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
}
+ ASSERT(arrayMode.type() == Array::String || arrayMode.typedArrayType() != NotTypedArray);
return m_insertionSet.insertNode(
m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -2845,7 +2845,7 @@
JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
MacroAssembler::Zero,
- MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
+ MacroAssembler::Address(base, JSArrayBufferView::offsetOfPoisonedVector()));
speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
notWasteful.link(&m_jit);
}
@@ -6354,9 +6354,13 @@
break;
default:
- ASSERT(isTypedView(node->arrayMode().typedArrayType()));
+ auto typedArrayType = node->arrayMode().typedArrayType();
+ ASSERT_UNUSED(typedArrayType, isTypedView(typedArrayType));
- m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfVector()), storageReg);
+ m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfPoisonedVector()), storageReg);
+#if ENABLE(POISON)
+ m_jit.xorPtr(JITCompiler::TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), storageReg);
+#endif
cageTypedArrayStorage(storageReg);
break;
}
@@ -6373,22 +6377,45 @@
GPRReg baseGPR = base.gpr();
GPRReg vectorGPR = vector.gpr();
GPRReg dataGPR = data.gpr();
-
+ ASSERT(baseGPR != vectorGPR);
+ ASSERT(baseGPR != dataGPR);
+ ASSERT(vectorGPR != dataGPR);
+
+#if ENABLE(POISON)
+ GPRTemporary poison(this);
+ GPRTemporary index(this);
+ GPRReg poisonGPR = poison.gpr();
+ GPRReg indexGPR = index.gpr();
+ GPRReg arrayBufferGPR = poisonGPR;
+#else
+ GPRReg arrayBufferGPR = dataGPR;
+#endif
+
JITCompiler::Jump emptyByteOffset = m_jit.branch32(
MacroAssembler::NotEqual,
MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
TrustedImm32(WastefulTypedArray));
+ m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfPoisonedVector()), vectorGPR);
+ JITCompiler::Jump nullVector = m_jit.branchTestPtr(JITCompiler::Zero, vectorGPR);
+
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
m_jit.cage(Gigacage::JSValue, dataGPR);
- m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
- JITCompiler::Jump nullVector = m_jit.branchTestPtr(JITCompiler::Zero, vectorGPR);
+
+#if ENABLE(POISON)
+ m_jit.load8(JITCompiler::Address(baseGPR, JSCell::typeInfoTypeOffset()), indexGPR);
+ m_jit.move(JITCompiler::TrustedImmPtr(&g_typedArrayPoisons), poisonGPR);
+ m_jit.sub32(JITCompiler::TrustedImm32(FirstTypedArrayType), indexGPR);
+ m_jit.and32(JITCompiler::TrustedImm32(TypedArrayPoisonIndexMask), indexGPR);
+ m_jit.loadPtr(JITCompiler::BaseIndex(poisonGPR, indexGPR, JITCompiler::timesPtr()), poisonGPR);
+ m_jit.xorPtr(poisonGPR, vectorGPR);
+#endif
cageTypedArrayStorage(vectorGPR);
- m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), dataGPR);
+ m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), arrayBufferGPR);
// FIXME: This needs caging.
// https://bugs.webkit.org/show_bug.cgi?id=175515
- m_jit.loadPtr(MacroAssembler::Address(dataGPR, ArrayBuffer::offsetOfData()), dataGPR);
+ m_jit.loadPtr(MacroAssembler::Address(arrayBufferGPR, ArrayBuffer::offsetOfData()), dataGPR);
m_jit.subPtr(dataGPR, vectorGPR);
JITCompiler::Jump done = m_jit.jump();
@@ -9025,8 +9052,7 @@
m_jit.emitAllocateVariableSized(
storageGPR, m_jit.vm()->primitiveGigacageAuxiliarySpace, scratchGPR, scratchGPR,
scratchGPR2, slowCases);
-
- MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, sizeGPR);
+
m_jit.move(sizeGPR, scratchGPR);
if (elementSize(typedArrayType) != 4) {
if (elementSize(typedArrayType) > 4)
@@ -9044,7 +9070,6 @@
TrustedImm32(0),
MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesFour));
m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
- done.link(&m_jit);
auto butterfly = TrustedImmPtr(nullptr);
m_jit.emitComputeButterflyIndexingMask(sizeGPR, scratchGPR, indexingMaskGPR);
@@ -9052,9 +9077,17 @@
resultGPR, TrustedImmPtr(structure), butterfly, indexingMaskGPR, scratchGPR, scratchGPR2,
slowCases);
+#if ENABLE(POISON)
+ m_jit.move(storageGPR, scratchGPR);
+ m_jit.xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), scratchGPR);
m_jit.storePtr(
+ scratchGPR,
+ MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfPoisonedVector()));
+#else
+ m_jit.storePtr(
storageGPR,
- MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector()));
+ MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfPoisonedVector()));
+#endif
m_jit.store32(
sizeGPR,
MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));
Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (227873 => 227874)
--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -59,7 +59,7 @@
macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
- macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
+ macro(JSArrayBufferView_poisonedVector, JSArrayBufferView::offsetOfPoisonedVector()) \
macro(JSCell_cellState, JSCell::cellStateOffset()) \
macro(JSCell_header, 0) \
macro(JSCell_indexingTypeAndMisc, JSCell::indexingTypeAndMiscOffset()) \
@@ -149,7 +149,8 @@
macro(variables, 0, sizeof(Register)) \
macro(HasOwnPropertyCache, 0, sizeof(HasOwnPropertyCache::Entry)) \
macro(JSFixedArray_buffer, JSFixedArray::offsetOfData(), sizeof(EncodedJSValue)) \
-
+ macro(TypedArrayPoisons, 0, sizeof(uintptr_t)) \
+
#define FOR_EACH_NUMBERED_ABSTRACT_HEAP(macro) \
macro(properties)
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -3473,7 +3473,14 @@
}
DFG_ASSERT(m_graph, m_node, isTypedView(m_node->arrayMode().typedArrayType()));
- setStorage(caged(Gigacage::Primitive, m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector)));
+ LValue poisonedVector = m_out.loadPtr(cell, m_heaps.JSArrayBufferView_poisonedVector);
+#if ENABLE(POISON)
+ auto typedArrayType = m_node->arrayMode().typedArrayType();
+ LValue vector = m_out.bitXor(m_out.constIntPtr(JSArrayBufferView::poisonFor(typedArrayType)), poisonedVector);
+#else
+ LValue vector = poisonedVector;
+#endif
+ setStorage(caged(Gigacage::Primitive, vector));
}
void compileCheckArray()
@@ -3495,6 +3502,7 @@
LBasicBlock simpleCase = m_out.newBlock();
LBasicBlock wastefulCase = m_out.newBlock();
+ LBasicBlock notNull = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();
LValue mode = m_out.load32(basePtr, m_heaps.JSArrayBufferView_mode);
@@ -3508,13 +3516,27 @@
m_out.jump(continuation);
- m_out.appendTo(wastefulCase, continuation);
+ m_out.appendTo(wastefulCase, notNull);
- LValue vectorPtr = cagedMayBeNull(
- Gigacage::Primitive,
- m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector));
+ LValue poisonedVector = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_poisonedVector);
+ ValueFromBlock nullVectorOut = m_out.anchor(poisonedVector);
+ m_out.branch(poisonedVector, unsure(notNull), unsure(continuation));
+
+ m_out.appendTo(notNull, continuation);
+
LValue butterflyPtr = caged(Gigacage::JSValue, m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly));
LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
+
+#if ENABLE(POISON)
+ LValue jsType = m_out.load8ZeroExt32(basePtr, m_heaps.JSCell_typeInfoType);
+ LValue typeIndex = m_out.sub(jsType, m_out.constInt32(FirstTypedArrayType));
+ LValue maskedTypeIndex = m_out.zeroExtPtr(m_out.bitAnd(typeIndex, m_out.constInt32(TypedArrayPoisonIndexMask)));
+ LValue poisonsBasePtr = m_out.constIntPtr(&g_typedArrayPoisons);
+ LValue poison = m_out.loadPtr(m_out.baseIndex(m_heaps.TypedArrayPoisons, poisonsBasePtr, maskedTypeIndex));
+ poisonedVector = m_out.bitXor(poisonedVector, poison);
+#endif
+ LValue vectorPtr = caged(Gigacage::Primitive, poisonedVector);
+
// FIXME: This needs caging.
// https://bugs.webkit.org/show_bug.cgi?id=175515
LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
@@ -3524,7 +3546,7 @@
m_out.jump(continuation);
m_out.appendTo(continuation, lastNext);
- setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, wastefulOut)));
+ setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, nullVectorOut, wastefulOut)));
}
void compileGetPrototypeOf()
@@ -5637,7 +5659,10 @@
LValue fastResultValue =
allocateObject<JSArrayBufferView>(structure, m_out.intPtrZero, indexingMask, slowCase);
- m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
+#if ENABLE(POISON)
+ storage = m_out.bitXor(m_out.constIntPtr(JSArrayBufferView::poisonFor(typedArrayType)), storage);
+#endif
+ m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_poisonedVector);
m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
@@ -12796,24 +12821,6 @@
return m_out.opaque(result);
}
- LValue cagedMayBeNull(Gigacage::Kind kind, LValue ptr)
- {
- LBasicBlock notNull = m_out.newBlock();
- LBasicBlock continuation = m_out.newBlock();
-
- LBasicBlock lastNext = m_out.insertNewBlocksBefore(notNull);
-
- ValueFromBlock nullResult = m_out.anchor(ptr);
- m_out.branch(ptr, unsure(notNull), unsure(continuation));
-
- m_out.appendTo(notNull, continuation);
- ValueFromBlock notNullResult = m_out.anchor(caged(kind, ptr));
- m_out.jump(continuation);
-
- m_out.appendTo(continuation, lastNext);
- return m_out.phi(pointerType(), nullResult, notNullResult);
- }
-
void buildSwitch(SwitchData* data, LType type, LValue switchValue)
{
ASSERT(type == pointerType() || type == Int32);
@@ -15015,7 +15022,7 @@
unsure(isWasteful), unsure(continuation));
LBasicBlock lastNext = m_out.appendTo(isWasteful, continuation);
- LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_vector);
+ LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_poisonedVector);
speculate(Uncountable, jsValueValue(vector), m_node, m_out.isZero64(vector));
m_out.jump(continuation);
Modified: trunk/Source/_javascript_Core/jit/IntrinsicEmitter.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/jit/IntrinsicEmitter.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/jit/IntrinsicEmitter.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -107,22 +107,31 @@
case TypedArrayByteOffsetIntrinsic: {
GPRReg scratchGPR = state.scratchGPR;
- CCallHelpers::Jump emptyByteOffset = jit.branch32(
- MacroAssembler::NotEqual,
+ CCallHelpers::Jump notEmptyByteOffset = jit.branch32(
+ MacroAssembler::Equal,
MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
TrustedImm32(WastefulTypedArray));
+ jit.move(TrustedImmPtr(0), valueGPR);
+ CCallHelpers::Jump done = jit.jump();
+
+ notEmptyByteOffset.link(&jit);
+
+ // We need to load the butterfly before the vector because baseGPR and valueGPR
+ // can be the same register.
jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
- jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), valueGPR);
+ jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfPoisonedVector()), valueGPR);
+ CCallHelpers::Jump nullVector = jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
+
+#if ENABLE(POISON)
+ auto typedArrayType = structure()->classInfo()->typedArrayStorageType;
+ jit.xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), valueGPR);
+#endif
jit.loadPtr(MacroAssembler::Address(scratchGPR, Butterfly::offsetOfArrayBuffer()), scratchGPR);
jit.loadPtr(MacroAssembler::Address(scratchGPR, ArrayBuffer::offsetOfData()), scratchGPR);
jit.subPtr(scratchGPR, valueGPR);
- CCallHelpers::Jump done = jit.jump();
-
- emptyByteOffset.link(&jit);
- jit.move(TrustedImmPtr(0), valueGPR);
-
+ nullVector.link(&jit);
done.link(&jit);
jit.boxInt32(valueGPR, valueRegs);
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1457,9 +1457,9 @@
return slowCases;
}
-JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType typeArrayType)
{
- ASSERT(isInt(type));
+ ASSERT(isInt(typeArrayType));
// The best way to test the array type is to use the classInfo. We need to do so without
// clobbering the register that holds the indexing type, base, and property.
@@ -1480,22 +1480,26 @@
#endif
JumpList slowCases;
-
+ JSType jsType = typeForTypedArrayType(typeArrayType);
+
load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
- badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
+ badType = patchableBranch32(NotEqual, scratch, TrustedImm32(jsType));
slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
- loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
+ loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), scratch);
+#if ENABLE(POISON)
+ xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), scratch);
+#endif
cageConditionally(Gigacage::Primitive, scratch, scratch2);
- switch (elementSize(type)) {
+ switch (elementSize(typeArrayType)) {
case 1:
- if (JSC::isSigned(type))
+ if (JSC::isSigned(typeArrayType))
load8SignedExtendTo32(BaseIndex(scratch, property, TimesOne), resultPayload);
else
load8(BaseIndex(scratch, property, TimesOne), resultPayload);
break;
case 2:
- if (JSC::isSigned(type))
+ if (JSC::isSigned(typeArrayType))
load16SignedExtendTo32(BaseIndex(scratch, property, TimesTwo), resultPayload);
else
load16(BaseIndex(scratch, property, TimesTwo), resultPayload);
@@ -1508,7 +1512,7 @@
}
Jump done;
- if (type == TypeUint32) {
+ if (typeArrayType == TypeUint32) {
Jump canBeInt = branch32(GreaterThanOrEqual, resultPayload, TrustedImm32(0));
convertInt32ToDouble(resultPayload, fpRegT0);
@@ -1534,9 +1538,9 @@
return slowCases;
}
-JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType typeArrayType)
{
- ASSERT(isFloat(type));
+ ASSERT(isFloat(typeArrayType));
#if USE(JSVALUE64)
RegisterID base = regT0;
@@ -1554,14 +1558,18 @@
#endif
JumpList slowCases;
+ JSType jsType = typeForTypedArrayType(typeArrayType);
load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
- badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
+ badType = patchableBranch32(NotEqual, scratch, TrustedImm32(jsType));
slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
- loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
+ loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), scratch);
+#if ENABLE(POISON)
+ xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), scratch);
+#endif
cageConditionally(Gigacage::Primitive, scratch, scratch2);
- switch (elementSize(type)) {
+ switch (elementSize(typeArrayType)) {
case 4:
loadFloat(BaseIndex(scratch, property, TimesFour), fpRegT0);
convertFloatToDouble(fpRegT0, fpRegT0);
@@ -1588,10 +1596,10 @@
return slowCases;
}
-JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType typeArrayType)
{
ArrayProfile* profile = ""
- ASSERT(isInt(type));
+ ASSERT(isInt(typeArrayType));
int value = currentInstruction[3].u.operand;
@@ -1610,9 +1618,10 @@
#endif
JumpList slowCases;
-
+ JSType jsType = typeForTypedArrayType(typeArrayType);
+
load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
- badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
+ badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(jsType));
Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
emitArrayProfileOutOfBoundsSpecialCase(profile);
slowCases.append(jump());
@@ -1628,12 +1637,15 @@
// We would be loading this into base as in get_by_val, except that the slow
// path expects the base to be unclobbered.
- loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
+ loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), lateScratch);
+#if ENABLE(POISON)
+ xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), lateScratch);
+#endif
cageConditionally(Gigacage::Primitive, lateScratch, lateScratch2);
- if (isClamped(type)) {
- ASSERT(elementSize(type) == 1);
- ASSERT(!JSC::isSigned(type));
+ if (isClamped(typeArrayType)) {
+ ASSERT(elementSize(typeArrayType) == 1);
+ ASSERT(!JSC::isSigned(typeArrayType));
Jump inBounds = branch32(BelowOrEqual, earlyScratch, TrustedImm32(0xff));
Jump tooBig = branch32(GreaterThan, earlyScratch, TrustedImm32(0xff));
xor32(earlyScratch, earlyScratch);
@@ -1644,7 +1656,7 @@
inBounds.link(this);
}
- switch (elementSize(type)) {
+ switch (elementSize(typeArrayType)) {
case 1:
store8(earlyScratch, BaseIndex(lateScratch, property, TimesOne));
break;
@@ -1661,10 +1673,10 @@
return slowCases;
}
-JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType typeArrayType)
{
ArrayProfile* profile = ""
- ASSERT(isFloat(type));
+ ASSERT(isFloat(typeArrayType));
int value = currentInstruction[3].u.operand;
@@ -1683,9 +1695,10 @@
#endif
JumpList slowCases;
-
+ JSType jsType = typeForTypedArrayType(typeArrayType);
+
load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
- badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
+ badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(jsType));
Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
emitArrayProfileOutOfBoundsSpecialCase(profile);
slowCases.append(jump());
@@ -1714,10 +1727,13 @@
// We would be loading this into base as in get_by_val, except that the slow
// path expects the base to be unclobbered.
- loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
+ loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), lateScratch);
+#if ENABLE(POISON)
+ xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), lateScratch);
+#endif
cageConditionally(Gigacage::Primitive, lateScratch, lateScratch2);
- switch (elementSize(type)) {
+ switch (elementSize(typeArrayType)) {
case 4:
convertDoubleToFloat(fpRegT0, fpRegT0);
storeFloat(fpRegT0, BaseIndex(lateScratch, property, TimesFour));
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (227873 => 227874)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2018-01-31 05:23:52 UTC (rev 227874)
@@ -394,6 +394,7 @@
const FirstArrayType = constexpr FirstTypedArrayType
const NumberOfTypedArrayTypesExcludingDataView = constexpr NumberOfTypedArrayTypesExcludingDataView
+const TypedArrayPoisonIndexMask = constexpr TypedArrayPoisonIndexMask
# Type flags constants.
const MasqueradesAsUndefined = constexpr MasqueradesAsUndefined
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (227873 => 227874)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2018-01-31 05:23:52 UTC (rev 227874)
@@ -376,17 +376,34 @@
end)
end
-macro loadCaged(basePtr, mask, source, dest, scratch)
- loadp source, dest
+macro uncage(basePtr, mask, ptr, scratch)
if GIGACAGE_ENABLED and not C_LOOP
loadp basePtr, scratch
btpz scratch, .done
- andp mask, dest
- addp scratch, dest
+ andp mask, ptr
+ addp scratch, ptr
.done:
end
end
+macro loadCaged(basePtr, mask, source, dest, scratch)
+ loadp source, dest
+ uncage(basePtr, mask, dest, scratch)
+end
+
+macro loadTypedArrayCaged(basePtr, mask, source, typeIndex, dest, scratch)
+ if POISON
+ andp TypedArrayPoisonIndexMask, typeIndex
+ leap _g_typedArrayPoisons, dest
+ loadp [dest, typeIndex, 8], dest
+ loadp source, scratch
+ xorp scratch, dest
+ else
+ loadp source, dest
+ end
+ uncage(basePtr, mask, dest, scratch)
+end
+
macro loadVariable(operand, value)
loadisFromInstruction(operand, value)
loadq [cfr, value, 8], value
@@ -1541,9 +1558,9 @@
biaeq t2, NumberOfTypedArrayTypesExcludingDataView, .opGetByValSlow
# Sweet, now we know that we have a typed array. Do some basic things now.
- loadCaged(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr PRIMITIVE_GIGACAGE_MASK, JSArrayBufferView::m_vector[t0], t3, t5)
biaeq t1, JSArrayBufferView::m_length[t0], .opGetByValSlow
-
+ loadTypedArrayCaged(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr PRIMITIVE_GIGACAGE_MASK, JSArrayBufferView::m_poisonedVector[t0], t2, t3, t5)
+
# Now bisect through the various types:
# Int8ArrayType,
# Uint8ArrayType,
Modified: trunk/Source/_javascript_Core/offlineasm/arm64.rb (227873 => 227874)
--- trunk/Source/_javascript_Core/offlineasm/arm64.rb 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/offlineasm/arm64.rb 2018-01-31 05:23:52 UTC (rev 227874)
@@ -275,6 +275,13 @@
else
newList << node
end
+ when "leai", "leap", "leaq"
+ labelRef = node.operands[0]
+ if labelRef.is_a? LabelReference
+ newList << Instruction.new(codeOrigin, "globaladdr", [LabelReference.new(node.codeOrigin, labelRef.label), node.operands[1]])
+ else
+ newList << node
+ end
else
newList << node
end
Modified: trunk/Source/_javascript_Core/offlineasm/x86.rb (227873 => 227874)
--- trunk/Source/_javascript_Core/offlineasm/x86.rb 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/offlineasm/x86.rb 2018-01-31 05:23:52 UTC (rev 227874)
@@ -468,6 +468,11 @@
$asm.puts "movq #{asmLabel}@GOTPCREL(%rip), #{dst.x86Operand(:ptr)}"
"#{offset}(#{dst.x86Operand(kind)})"
end
+ def x86AddressOperand(addressKind)
+ # FIXME: Implement this on platforms that aren't Mach-O.
+ # https://bugs.webkit.org/show_bug.cgi?id=175104
+ "#{asmLabel}@GOTPCREL(%rip)"
+ end
end
class LocalLabelReference
@@ -582,6 +587,15 @@
end
end
+ def emitX86Lea(src, dst, kind)
+ if src.is_a? LabelReference
+ $asm.puts "movq #{src.asmLabel}@GOTPCREL(%rip), #{dst.x86Operand(:ptr)}"
+ $asm.puts "mov#{x86Suffix(kind)} #{orderOperands(dst.x86Operand(kind), dst.x86Operand(kind))}"
+ else
+ $asm.puts "lea#{x86Suffix(kind)} #{orderOperands(src.x86AddressOperand(kind), dst.x86Operand(kind))}"
+ end
+ end
+
def getImplicitOperandString
isIntelSyntax ? "st(0), " : ""
end
@@ -1542,9 +1556,9 @@
when "bnz"
$asm.puts "jnz #{operands[0].asmLabel}"
when "leai"
- $asm.puts "lea#{x86Suffix(:int)} #{orderOperands(operands[0].x86AddressOperand(:int), operands[1].x86Operand(:int))}"
+ emitX86Lea(operands[0], operands[1], :int)
when "leap"
- $asm.puts "lea#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86AddressOperand(:ptr), operands[1].x86Operand(:ptr))}"
+ emitX86Lea(operands[0], operands[1], :ptr)
when "memfence"
sp = RegisterID.new(nil, "sp")
if isIntelSyntax
Modified: trunk/Source/_javascript_Core/runtime/CagedBarrierPtr.h (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/CagedBarrierPtr.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/CagedBarrierPtr.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,8 +26,15 @@
#pragma once
#include "AuxiliaryBarrier.h"
+#include <type_traits>
#include <wtf/CagedPtr.h>
+namespace WTF {
+
+template<typename Poison, typename T> struct PoisonedPtrTraits;
+
+} // namespace WTF
+
namespace JSC {
class JSCell;
@@ -35,7 +42,7 @@
// This is a convenient combo of AuxiliaryBarrier and CagedPtr.
-template<Gigacage::Kind passedKind, typename T>
+template<Gigacage::Kind passedKind, typename T, typename PtrTraits = WTF::DumbPtrTraits<T>>
class CagedBarrierPtr {
public:
static constexpr Gigacage::Kind kind = passedKind;
@@ -85,11 +92,11 @@
T& operator[](IndexType index) const { return get()[index]; }
private:
- AuxiliaryBarrier<CagedPtr<kind, T>> m_barrier;
+ AuxiliaryBarrier<CagedPtr<kind, T, PtrTraits>> m_barrier;
};
-template<Gigacage::Kind passedKind>
-class CagedBarrierPtr<passedKind, void> {
+template<Gigacage::Kind passedKind, typename PtrTraits>
+class CagedBarrierPtr<passedKind, void, PtrTraits> {
public:
static constexpr Gigacage::Kind kind = passedKind;
typedef void Type;
@@ -132,7 +139,10 @@
void setWithoutBarrier(U&& value) { m_barrier.setWithoutBarrier(std::forward<U>(value)); }
private:
- AuxiliaryBarrier<CagedPtr<kind, void>> m_barrier;
+ AuxiliaryBarrier<CagedPtr<kind, void, PtrTraits>> m_barrier;
};
+template<typename Poison, Gigacage::Kind passedKind, typename T>
+using PoisonedCagedBarrierPtr = CagedBarrierPtr<passedKind, T, WTF::PoisonedPtrTraits<Poison, T>>;
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferView.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/JSArrayBufferView.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferView.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -132,7 +132,7 @@
, m_mode(context.mode())
{
setButterflyWithIndexingMask(vm, context.butterfly(), WTF::computeIndexingMask(length()));
- m_vector.setWithoutBarrier(context.vector());
+ m_poisonedVector.setWithoutBarrier(context.vector());
}
void JSArrayBufferView::finishCreation(VM& vm)
@@ -193,7 +193,7 @@
JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell);
ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray);
if (thisObject->m_mode == OversizeTypedArray)
- Gigacage::free(Gigacage::Primitive, thisObject->m_vector.get());
+ Gigacage::free(Gigacage::Primitive, thisObject->m_poisonedVector.get());
}
JSArrayBuffer* JSArrayBufferView::unsharedJSBuffer(ExecState* exec)
@@ -211,7 +211,7 @@
RELEASE_ASSERT(hasArrayBuffer());
RELEASE_ASSERT(!isShared());
m_length = 0;
- m_vector.clear();
+ m_poisonedVector.clear();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,12 +26,22 @@
#pragma once
#include "AuxiliaryBarrier.h"
+#include "CagedBarrierPtr.h"
+#include "JSCPoison.h"
#include "JSObject.h"
+#include "TypedArrayType.h"
+#include <wtf/MathExtras.h>
namespace JSC {
class LLIntOffsetsExtractor;
+// Since we'll be indexing into the g_typedArrayPoisons array based on the TypedArray type,
+// we'll index mask the index value and round up to the array size to the next power of 2 to
+// ensure that we'll never be able to access beyond the bounds of this array.
+static constexpr uint32_t NumberOfTypedArrayPoisons = WTF::roundUpToPowerOfTwo(NumberOfTypedArrayTypes);
+static constexpr uint32_t TypedArrayPoisonIndexMask = NumberOfTypedArrayPoisons - 1;
+
// This class serves two purposes:
//
// 1) It provides those parts of JSGenericTypedArrayView that don't depend
@@ -167,7 +177,7 @@
bool isNeutered() { return hasArrayBuffer() && !vector(); }
void neuter();
- void* vector() const { return m_vector.getMayBeNull(); }
+ void* vector() const { return m_poisonedVector.getMayBeNull(); }
unsigned byteOffset();
unsigned length() const { return m_length; }
@@ -174,12 +184,23 @@
DECLARE_EXPORT_INFO;
- static ptrdiff_t offsetOfVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_vector); }
+ static ptrdiff_t offsetOfPoisonedVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_poisonedVector); }
static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(JSArrayBufferView, m_length); }
static ptrdiff_t offsetOfMode() { return OBJECT_OFFSETOF(JSArrayBufferView, m_mode); }
static RefPtr<ArrayBufferView> toWrapped(VM&, JSValue);
+ static uintptr_t poisonFor(JSType type)
+ {
+ return g_typedArrayPoisons[(type - FirstTypedArrayType) & TypedArrayPoisonIndexMask];
+ }
+
+ static uintptr_t poisonFor(TypedArrayType typedArrayType)
+ {
+ ASSERT(isTypedView(typedArrayType));
+ return poisonFor(typeForTypedArrayType(typedArrayType));
+ }
+
private:
static void finalize(JSCell*);
@@ -190,7 +211,19 @@
static String toStringName(const JSObject*, ExecState*);
- CagedBarrierPtr<Gigacage::Primitive, void> m_vector;
+ class Poison {
+ public:
+ template<typename PoisonedType>
+ inline static uintptr_t key(const PoisonedType* poisonedPtr)
+ {
+ uintptr_t poisonedVectorAddress = bitwise_cast<uintptr_t>(poisonedPtr);
+ uintptr_t baseAddress = poisonedVectorAddress - OBJECT_OFFSETOF(JSArrayBufferView, m_poisonedVector);
+ JSArrayBufferView* thisObject = bitwise_cast<JSArrayBufferView*>(baseAddress);
+ return poisonFor(thisObject->type());
+ }
+ };
+
+ PoisonedCagedBarrierPtr<Poison, Gigacage::Primitive, void> m_poisonedVector;
uint32_t m_length;
TypedArrayMode m_mode;
};
Modified: trunk/Source/_javascript_Core/runtime/JSCPoison.cpp (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/JSCPoison.cpp 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/JSCPoison.cpp 2018-01-31 05:23:52 UTC (rev 227874)
@@ -26,6 +26,7 @@
#include "config.h"
#include "JSCPoison.h"
+#include "JSArrayBufferView.h"
#include "Options.h"
#include <mutex>
#include <wtf/HashSet.h>
@@ -36,6 +37,8 @@
uintptr_t POISON_KEY_NAME(poisonID);
FOR_EACH_JSC_POISON(DEFINE_POISON)
+uintptr_t g_typedArrayPoisons[NumberOfTypedArrayPoisons];
+
void initializePoison()
{
static std::once_flag initializeOnceFlag;
@@ -47,6 +50,9 @@
POISON_KEY_NAME(poisonID) = makePoison();
FOR_EACH_JSC_POISON(INITIALIZE_POISON)
+
+ for (uint32_t i = 0; i < NumberOfTypedArrayPoisons; ++i)
+ g_typedArrayPoisons[i] = makePoison();
});
}
Modified: trunk/Source/_javascript_Core/runtime/JSCPoison.h (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/JSCPoison.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/JSCPoison.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -64,6 +64,8 @@
FOR_EACH_JSC_POISON(DECLARE_POISON)
#undef DECLARE_POISON
+extern "C" JS_EXPORTDATA uintptr_t g_typedArrayPoisons[];
+
struct ClassInfo;
using PoisonedClassInfoPtr = Poisoned<GlobalDataPoison, const ClassInfo*>;
Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -504,7 +504,7 @@
if (thisObject->m_mode == OversizeTypedArray)
return Base::estimatedSize(thisObject) + thisObject->byteSize();
- if (thisObject->m_mode == FastTypedArray && thisObject->m_vector)
+ if (thisObject->m_mode == FastTypedArray && thisObject->m_poisonedVector)
return Base::estimatedSize(thisObject) + thisObject->byteSize();
return Base::estimatedSize(thisObject);
@@ -517,7 +517,7 @@
switch (thisObject->m_mode) {
case FastTypedArray: {
- if (void* vector = thisObject->m_vector.getMayBeNull())
+ if (void* vector = thisObject->m_poisonedVector.getMayBeNull())
visitor.markAuxiliary(vector);
break;
}
@@ -585,7 +585,7 @@
}
thisObject->butterfly()->indexingHeader()->setArrayBuffer(buffer.get());
- thisObject->m_vector.setWithoutBarrier(buffer->data());
+ thisObject->m_poisonedVector.setWithoutBarrier(buffer->data());
WTF::storeStoreFence();
thisObject->m_mode = WastefulTypedArray;
heap->addReference(thisObject, buffer.get());
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (227873 => 227874)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -24,9 +24,9 @@
#include "ArrayConventions.h"
#include "ArrayStorage.h"
+#include "AuxiliaryBarrier.h"
#include "Butterfly.h"
#include "CPU.h"
-#include "CagedBarrierPtr.h"
#include "CallFrame.h"
#include "ClassInfo.h"
#include "CustomGetterSetter.h"
Modified: trunk/Source/WTF/ChangeLog (227873 => 227874)
--- trunk/Source/WTF/ChangeLog 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/WTF/ChangeLog 2018-01-31 05:23:52 UTC (rev 227874)
@@ -1,3 +1,22 @@
+2018-01-30 Mark Lam <[email protected]>
+
+ Apply poisoning to TypedArray vector pointers.
+ https://bugs.webkit.org/show_bug.cgi?id=182155
+ <rdar://problem/36286266>
+
+ Reviewed by JF Bastien.
+
+ 1. Added the ability to poison a CagedPtr.
+
+ 2. 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=):
+
2018-01-30 Fujii Hironori <[email protected]>
[Win] Warning fix.
Modified: trunk/Source/WTF/wtf/CagedPtr.h (227873 => 227874)
--- trunk/Source/WTF/wtf/CagedPtr.h 2018-01-31 05:15:59 UTC (rev 227873)
+++ trunk/Source/WTF/wtf/CagedPtr.h 2018-01-31 05:23:52 UTC (rev 227874)
@@ -25,16 +25,20 @@
#pragma once
+#include <wtf/DumbPtrTraits.h>
#include <wtf/Gigacage.h>
namespace WTF {
-template<Gigacage::Kind passedKind, typename T>
+template<Gigacage::Kind passedKind, typename T, typename PtrTraits = DumbPtrTraits<T>>
class CagedPtr {
public:
static constexpr Gigacage::Kind kind = passedKind;
-
- CagedPtr(T* ptr = nullptr)
+
+ CagedPtr() : CagedPtr(nullptr) { }
+ CagedPtr(std::nullptr_t) : m_ptr(nullptr) { }
+
+ explicit CagedPtr(T* ptr)
: m_ptr(ptr)
{
}
@@ -42,7 +46,7 @@
T* get() const
{
ASSERT(m_ptr);
- return Gigacage::caged(kind, m_ptr);
+ return Gigacage::caged(kind, PtrTraits::unwrap(m_ptr));
}
T* getMayBeNull() const
@@ -51,7 +55,19 @@
return nullptr;
return get();
}
-
+
+ CagedPtr& operator=(T* ptr)
+ {
+ m_ptr = ptr;
+ return *this;
+ }
+
+ CagedPtr& operator=(T*&& ptr)
+ {
+ m_ptr = WTFMove(ptr);
+ return *this;
+ }
+
bool operator==(const CagedPtr& other) const
{
return getMayBeNull() == other.getMayBeNull();
@@ -74,15 +90,18 @@
T& operator[](IndexType index) const { return get()[index]; }
protected:
- T* m_ptr;
+ typename PtrTraits::StorageType m_ptr;
};
-template<Gigacage::Kind passedKind>
-class CagedPtr<passedKind, void> {
+template<Gigacage::Kind passedKind, typename PtrTraits>
+class CagedPtr<passedKind, void, PtrTraits> {
public:
static constexpr Gigacage::Kind kind = passedKind;
-
- CagedPtr(void* ptr = nullptr)
+
+ CagedPtr() : CagedPtr(nullptr) { }
+ CagedPtr(std::nullptr_t) : m_ptr(nullptr) { }
+
+ explicit CagedPtr(void* ptr)
: m_ptr(ptr)
{
}
@@ -90,7 +109,7 @@
void* get() const
{
ASSERT(m_ptr);
- return Gigacage::caged(kind, m_ptr);
+ return Gigacage::caged(kind, PtrTraits::unwrap(m_ptr));
}
void* getMayBeNull() const
@@ -99,7 +118,13 @@
return nullptr;
return get();
}
-
+
+ CagedPtr& operator=(void* ptr)
+ {
+ m_ptr = ptr;
+ return *this;
+ }
+
bool operator==(const CagedPtr& other) const
{
return getMayBeNull() == other.getMayBeNull();
@@ -116,7 +141,7 @@
}
protected:
- void* m_ptr;
+ typename PtrTraits::StorageType m_ptr;
};
} // namespace WTF