Skip to content

Commit 323ad28

Browse files
author
Mark Lam
committed
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. 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: Source/WTF: 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=): Canonical link: https://commits.webkit.org/198124@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@227874 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 1fe51b2 commit 323ad28

20 files changed

Lines changed: 448 additions & 120 deletions

Source/JavaScriptCore/ChangeLog

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,130 @@
1+
2018-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+
1128
2018-01-30 Fujii Hironori <Hironori.Fujii@sony.com>
2129

3130
[Win] Warning fix.

Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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
55
* modification, are permitted provided that the following conditions
@@ -2870,6 +2870,7 @@ class FixupPhase : public Phase {
28702870
m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
28712871
}
28722872

2873+
ASSERT(arrayMode.type() == Array::String || arrayMode.typedArrayType() != NotTypedArray);
28732874
return m_insertionSet.insertNode(
28742875
m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
28752876
OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,7 +2845,7 @@ JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds(Node*
28452845

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);
28512851
}
@@ -6354,9 +6354,13 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node* node)
63546354
break;
63556355

63566356
default:
6357-
ASSERT(isTypedView(node->arrayMode().typedArrayType()));
6357+
auto typedArrayType = node->arrayMode().typedArrayType();
6358+
ASSERT_UNUSED(typedArrayType, isTypedView(typedArrayType));
63586359

6359-
m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfVector()), storageReg);
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;
63626366
}
@@ -6373,22 +6377,45 @@ void SpeculativeJIT::compileGetTypedArrayByteOffset(Node* node)
63736377
GPRReg baseGPR = base.gpr();
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,
63796396
MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
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

63946421
JITCompiler::Jump done = m_jit.jump();
@@ -9025,8 +9052,7 @@ void SpeculativeJIT::compileNewTypedArrayWithSize(Node* node)
90259052
m_jit.emitAllocateVariableSized(
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) {
90329058
if (elementSize(typedArrayType) > 4)
@@ -9044,17 +9070,24 @@ void SpeculativeJIT::compileNewTypedArrayWithSize(Node* node)
90449070
TrustedImm32(0),
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);
90509075
m_jit.emitComputeButterflyIndexingMask(sizeGPR, scratchGPR, indexingMaskGPR);
90519076
emitAllocateJSObject<JSArrayBufferView>(
90529077
resultGPR, TrustedImmPtr(structure), butterfly, indexingMaskGPR, scratchGPR, scratchGPR2,
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,
90609093
MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));

Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ namespace JSC { namespace FTL {
5959
macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
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) \
6565
macro(JSCell_indexingTypeAndMisc, JSCell::indexingTypeAndMiscOffset()) \
@@ -149,7 +149,8 @@ namespace JSC { namespace FTL {
149149
macro(variables, 0, sizeof(Register)) \
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)
155156

Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,7 +3473,14 @@ class LowerDFGToB3 {
34733473
}
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

34793486
void compileCheckArray()
@@ -3495,6 +3502,7 @@ class LowerDFGToB3 {
34953502

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

35003508
LValue mode = m_out.load32(basePtr, m_heaps.JSArrayBufferView_mode);
@@ -3508,13 +3516,27 @@ class LowerDFGToB3 {
35083516

35093517
m_out.jump(continuation);
35103518

3511-
m_out.appendTo(wastefulCase, continuation);
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);
35123526

3513-
LValue vectorPtr = cagedMayBeNull(
3514-
Gigacage::Primitive,
3515-
m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector));
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
35203542
LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
@@ -3524,7 +3546,7 @@ class LowerDFGToB3 {
35243546
m_out.jump(continuation);
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

35303552
void compileGetPrototypeOf()
@@ -5637,7 +5659,10 @@ class LowerDFGToB3 {
56375659
LValue fastResultValue =
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);
56435668

@@ -12796,24 +12821,6 @@ class LowerDFGToB3 {
1279612821
return m_out.opaque(result);
1279712822
}
1279812823

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);
12815-
}
12816-
1281712824
void buildSwitch(SwitchData* data, LType type, LValue switchValue)
1281812825
{
1281912826
ASSERT(type == pointerType() || type == Int32);
@@ -15015,7 +15022,7 @@ class LowerDFGToB3 {
1501515022
unsure(isWasteful), unsure(continuation));
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);
1502115028

0 commit comments

Comments
 (0)