Diff
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/ChangeLog (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/ChangeLog 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/ChangeLog 2017-12-19 23:01:00 UTC (rev 226145)
@@ -1,5 +1,77 @@
2017-12-18 Jason Marcell <[email protected]>
+ Apply patch. rdar://problem/36112003
+
+ 2017-12-17 Keith Miller <[email protected]>
+
+ Use index masking for TypedArrays and and Wasm.
+ https://bugs.webkit.org/show_bug.cgi?id=180920
+
+ Reviewed by Filip Pizlo.
+
+ We should have index masking for our TypedArray code in the
+ DFG/FTL and for Wasm when doing bounds checking. Index masking for
+ Wasm is added to the WasmBoundsCheckValue. Since we don't CSE any
+ WasmBoundsCheckValues we don't need to worry about combining a
+ bounds check for a load and a store. I went with fusing the
+ pointer masking in the WasmBoundsCheckValue since it should reduce
+ additional compiler overhead.
+
+ * b3/B3LowerToAir.cpp:
+ * b3/B3Validate.cpp:
+ * b3/B3WasmBoundsCheckValue.cpp:
+ (JSC::B3::WasmBoundsCheckValue::WasmBoundsCheckValue):
+ (JSC::B3::WasmBoundsCheckValue::dumpMeta const):
+ * b3/B3WasmBoundsCheckValue.h:
+ (JSC::B3::WasmBoundsCheckValue::pinnedIndexingMask const):
+ * b3/air/AirCustom.h:
+ (JSC::B3::Air::WasmBoundsCheckCustom::generate):
+ * b3/testb3.cpp:
+ (JSC::B3::testWasmBoundsCheck):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::loadFromIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileNewTypedArray):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLAbstractHeapRepository.h:
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileAtomicsReadModifyWrite):
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
+ (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
+ (JSC::FTL::DFG::LowerDFGToB3::pointerIntoTypedArray):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::emitComputeButterflyIndexingMask):
+ * runtime/Butterfly.h:
+ * runtime/JSArrayBufferView.cpp:
+ (JSC::JSArrayBufferView::JSArrayBufferView):
+ * runtime/JSArrayBufferView.h:
+ (JSC::JSArrayBufferView::offsetOfIndexingMask):
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+ (JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
+ (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
+ (JSC::Wasm::B3IRGenerator::load):
+ (JSC::Wasm::B3IRGenerator::store):
+ (JSC::Wasm::B3IRGenerator::addCallIndirect):
+ * wasm/WasmBinding.cpp:
+ (JSC::Wasm::wasmToWasm):
+ * wasm/WasmMemory.cpp:
+ (JSC::Wasm::Memory::Memory):
+ * wasm/WasmMemory.h:
+ (JSC::Wasm::Memory::offsetOfIndexingMask):
+ * wasm/WasmMemoryInformation.cpp:
+ (JSC::Wasm::PinnedRegisterInfo::get):
+ (JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):
+ * wasm/WasmMemoryInformation.h:
+ (JSC::Wasm::PinnedRegisterInfo::toSave const):
+ * wasm/js/JSToWasm.cpp:
+ (JSC::Wasm::createJSToWasmWrapper):
+
+2017-12-18 Jason Marcell <[email protected]>
+
Cherry-pick r226068. rdar://problem/36112028
2017-12-16 Filip Pizlo <[email protected]>
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3LowerToAir.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3LowerToAir.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3LowerToAir.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -3210,9 +3210,10 @@
WasmBoundsCheckValue* value = m_value->as<WasmBoundsCheckValue>();
Value* ptr = value->child(0);
+ Tmp pointer = tmp(ptr);
Arg ptrPlusImm = m_code.newTmp(GP);
- append(Inst(Move32, value, tmp(ptr), ptrPlusImm));
+ append(Inst(Move32, value, pointer, ptrPlusImm));
if (value->offset()) {
if (imm(value->offset()))
append(Add64, imm(value->offset()), ptrPlusImm);
@@ -3226,7 +3227,7 @@
Arg limit;
switch (value->boundsType()) {
case WasmBoundsCheckValue::Type::Pinned:
- limit = Arg(value->bounds().pinned);
+ limit = Arg(value->bounds().pinnedSize);
break;
case WasmBoundsCheckValue::Type::Maximum:
@@ -3239,6 +3240,10 @@
}
append(Inst(Air::WasmBoundsCheck, value, ptrPlusImm, limit));
+ // Hypothetically, this could write to the pointer value. Which we didn't claim we did but since we assume the indexing mask
+ // should not actually change the value of the pointer we should be OK.
+ if (value->pinnedIndexingMask() != InvalidGPRReg)
+ append(And32, Arg(value->pinnedIndexingMask()), pointer, pointer);
return;
}
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3Validate.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3Validate.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3Validate.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -472,11 +472,14 @@
VALIDATE(value->child(0)->type() == Int32, ("At ", *value));
switch (value->as<WasmBoundsCheckValue>()->boundsType()) {
case WasmBoundsCheckValue::Type::Pinned:
- VALIDATE(m_procedure.code().isPinned(value->as<WasmBoundsCheckValue>()->bounds().pinned), ("At ", *value));
+ VALIDATE(m_procedure.code().isPinned(value->as<WasmBoundsCheckValue>()->bounds().pinnedSize), ("At ", *value));
+
break;
case WasmBoundsCheckValue::Type::Maximum:
break;
}
+ if (value->as<WasmBoundsCheckValue>()->pinnedIndexingMask() != InvalidGPRReg)
+ VALIDATE(m_procedure.code().isPinned(value->as<WasmBoundsCheckValue>()->pinnedIndexingMask()), ("At ", *value));
VALIDATE(m_procedure.code().wasmBoundsCheckGenerator(), ("At ", *value));
break;
case Upsilon:
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3WasmBoundsCheckValue.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3WasmBoundsCheckValue.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3WasmBoundsCheckValue.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -35,12 +35,13 @@
{
}
-WasmBoundsCheckValue::WasmBoundsCheckValue(Origin origin, GPRReg pinnedGPR, Value* ptr, unsigned offset)
+WasmBoundsCheckValue::WasmBoundsCheckValue(Origin origin, GPRReg pinnedSize, GPRReg pinnedIndexingMask, Value* ptr, unsigned offset)
: Value(CheckedOpcode, WasmBoundsCheck, origin, ptr)
, m_offset(offset)
, m_boundsType(Type::Pinned)
+ , m_pinnedIndexingMask(pinnedIndexingMask)
{
- m_bounds.pinned = pinnedGPR;
+ m_bounds.pinnedSize = pinnedSize;
}
WasmBoundsCheckValue::WasmBoundsCheckValue(Origin origin, Value* ptr, unsigned offset, size_t maximum)
@@ -64,10 +65,10 @@
{
switch (m_boundsType) {
case Type::Pinned:
- out.print(comma, "offset = ", m_offset, ", pinned = ", m_bounds.pinned);
+ out.print(comma, "offset = ", m_offset, comma, "pinnedSize = ", m_bounds.pinnedSize, comma, "pinnedMask", m_pinnedIndexingMask);
break;
case Type::Maximum:
- out.print(comma, "offset = ", m_offset, ", maximum = ", m_bounds.maximum);
+ out.print(comma, "offset = ", m_offset, comma, "maximum = ", m_bounds.maximum);
break;
}
}
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3WasmBoundsCheckValue.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3WasmBoundsCheckValue.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/b3/B3WasmBoundsCheckValue.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -52,7 +52,7 @@
};
union Bounds {
- GPRReg pinned;
+ GPRReg pinnedSize;
size_t maximum;
};
@@ -59,6 +59,7 @@
unsigned offset() const { return m_offset; }
Type boundsType() const { return m_boundsType; }
Bounds bounds() const { return m_bounds; }
+ GPRReg pinnedIndexingMask() const { return m_pinnedIndexingMask; };
protected:
void dumpMeta(CommaPrinter&, PrintStream&) const override;
@@ -68,12 +69,14 @@
private:
friend class Procedure;
- JS_EXPORT_PRIVATE WasmBoundsCheckValue(Origin, GPRReg pinnedGPR, Value* ptr, unsigned offset);
+ JS_EXPORT_PRIVATE WasmBoundsCheckValue(Origin, GPRReg pinnedGPR, GPRReg pinnedIndexingMask, Value* ptr, unsigned offset);
JS_EXPORT_PRIVATE WasmBoundsCheckValue(Origin, Value* ptr, unsigned offset, size_t maximum);
unsigned m_offset;
Type m_boundsType;
Bounds m_bounds;
+ GPRReg m_pinnedIndexingMask { InvalidGPRReg };
+
};
} } // namespace JSC::B3
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/b3/air/AirCustom.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/b3/air/AirCustom.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/b3/air/AirCustom.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -343,7 +343,7 @@
outOfBounds.link(&jit);
switch (value->boundsType()) {
case WasmBoundsCheckValue::Type::Pinned:
- context.code->wasmBoundsCheckGenerator()->run(jit, value->bounds().pinned);
+ context.code->wasmBoundsCheckGenerator()->run(jit, value->bounds().pinnedSize);
break;
case WasmBoundsCheckValue::Type::Maximum:
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/b3/testb3.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/b3/testb3.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/b3/testb3.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -15326,7 +15326,7 @@
Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
if (pointerType() != Int32)
left = root->appendNew<Value>(proc, Trunc, Origin(), left);
- root->appendNew<WasmBoundsCheckValue>(proc, Origin(), pinned, left, offset);
+ root->appendNew<WasmBoundsCheckValue>(proc, Origin(), pinned, InvalidGPRReg, left, offset);
Value* result = root->appendNew<Const32Value>(proc, Origin(), 0x42);
root->appendNewControlValue(proc, Return, Origin(), result);
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -2727,8 +2727,9 @@
return done;
}
-void SpeculativeJIT::loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType type)
+void SpeculativeJIT::loadFromIntTypedArray(GPRReg baseReg, GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType type)
{
+ m_jit.and32(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfIndexingMask()), propertyReg);
switch (elementSize(type)) {
case 1:
if (isSigned(type))
@@ -2798,7 +2799,7 @@
ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
- loadFromIntTypedArray(storageReg, propertyReg, resultReg, type);
+ loadFromIntTypedArray(baseReg, storageReg, propertyReg, resultReg, type);
bool canSpeculate = true;
setIntTypedArrayLoadResult(node, resultReg, type, canSpeculate);
}
@@ -3030,6 +3031,7 @@
FPRTemporary result(this);
FPRReg resultReg = result.fpr();
emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
+ m_jit.and32(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfIndexingMask()), propertyReg);
switch (elementSize(type)) {
case 4:
m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
@@ -8509,7 +8511,8 @@
emitAllocateJSObject<JSArrayBufferView>(
resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR, scratchGPR2,
slowCases);
-
+
+ m_jit.emitComputeButterflyIndexingMask(sizeGPR, scratchGPR, scratchGPR2);
m_jit.storePtr(
storageGPR,
MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector()));
@@ -8517,6 +8520,9 @@
sizeGPR,
MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));
m_jit.store32(
+ scratchGPR2,
+ MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfIndexingMask()));
+ m_jit.store32(
TrustedImm32(FastTypedArray),
MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfMode()));
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -2826,7 +2826,7 @@
GPRTemporary& valueTag,
#endif
Edge valueUse, JITCompiler::JumpList& slowPathCases, bool isClamped = false);
- void loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType);
+ void loadFromIntTypedArray(GPRReg baseReg, GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType);
void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate = false);
template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*, ptrdiff_t, ptrdiff_t, ptrdiff_t);
void compileNewFunction(Node*);
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -3284,7 +3284,7 @@
JITCompiler::Label loop = m_jit.label();
- loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
+ loadFromIntTypedArray(baseGPR, storageGPR, indexGPR, oldValueGPR, type);
m_jit.move(oldValueGPR, newValueGPR);
m_jit.move(oldValueGPR, resultGPR);
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -57,6 +57,7 @@
macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \
macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
+ macro(JSArrayBufferView_indexingMask, JSArrayBufferView::offsetOfIndexingMask()) \
macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
macro(JSCell_cellState, JSCell::cellStateOffset()) \
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -3022,9 +3022,10 @@
LValue args[2];
for (unsigned i = numExtraArgs; i--;)
args[i] = getIntTypedArrayStoreOperand(argEdges[i]);
+ LValue base = lowCell(baseEdge);
LValue storage = lowStorage(storageEdge);
-
- TypedPointer pointer = pointerIntoTypedArray(storage, index, type);
+
+ TypedPointer pointer = pointerIntoTypedArray(base, storage, index, type);
Width width = widthForBytes(elementSize(type));
LValue atomicValue;
@@ -3658,6 +3659,7 @@
}
default: {
+ LValue base = lowCell(m_node->child1());
LValue index = lowInt32(m_node->child2());
LValue storage = lowStorage(m_node->child3());
@@ -3664,7 +3666,7 @@
TypedArrayType type = m_node->arrayMode().typedArrayType();
if (isTypedView(type)) {
- TypedPointer pointer = pointerIntoTypedArray(storage, index, type);
+ TypedPointer pointer = pointerIntoTypedArray(base, storage, index, type);
if (isInt(type)) {
LValue result = loadFromIntTypedArray(pointer, type);
@@ -5091,8 +5093,10 @@
LValue fastResultValue =
allocateObject<JSArrayBufferView>(structure, m_out.intPtrZero, slowCase);
+ LValue indexingMask = m_out.castToInt32(m_out.lShr(m_out.zeroExt(m_out.constInt32(-1), Int64), m_out.ctlz32(size)));
m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
+ m_out.store32(indexingMask, fastResultValue, m_heaps.JSArrayBufferView_indexingMask);
m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
mutatorFence();
@@ -12098,14 +12102,15 @@
functor(TypeofType::Undefined);
}
- TypedPointer pointerIntoTypedArray(LValue storage, LValue index, TypedArrayType type)
+ TypedPointer pointerIntoTypedArray(LValue base, LValue storage, LValue index, TypedArrayType type)
{
+ LValue mask = m_out.load32(base, m_heaps.JSArrayBufferView_indexingMask);
return TypedPointer(
m_heaps.typedArrayProperties,
m_out.add(
storage,
m_out.shl(
- m_out.zeroExtPtr(index),
+ m_out.zeroExtPtr(m_out.bitAnd(index, mask)),
m_out.constIntPtr(logElementSize(type)))));
}
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/jit/AssemblyHelpers.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/jit/AssemblyHelpers.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/jit/AssemblyHelpers.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -1440,6 +1440,14 @@
void emitRandomThunk(VM&, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result);
#endif
+ void emitComputeButterflyIndexingMask(GPRReg vectorLengthGPR, GPRReg scratchGPR, GPRReg resultGPR)
+ {
+ // If vectorLength == 0 then clz will return 32 on both ARM and x86. On 64-bit systems, we can then do a 64-bit right shift on a 32-bit -1 to get a 0 mask for zero vectorLength. On 32-bit ARM, shift masks with 0xff, which means it will still create a 0 mask.
+ countLeadingZeros32(vectorLengthGPR, scratchGPR);
+ move(TrustedImm32(-1), resultGPR);
+ urshift64(scratchGPR, resultGPR);
+ }
+
// Call this if you know that the value held in allocatorGPR is non-null. This DOES NOT mean
// that allocator is non-null; allocator can be null as a signal that we don't know what the
// value of allocatorGPR is.
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/Butterfly.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/Butterfly.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/Butterfly.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -123,7 +123,7 @@
uint32_t vectorLength() { return indexingHeader()->vectorLength(); }
void setPublicLength(uint32_t value) { indexingHeader()->setPublicLength(value); }
void setVectorLength(uint32_t value) { indexingHeader()->setVectorLength(value); }
-
+
template<typename T>
T* indexingPayload() { return reinterpret_cast_ptr<T*>(this); }
ArrayStorage* arrayStorage() { return indexingPayload<ArrayStorage>(); }
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/JSArrayBufferView.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/JSArrayBufferView.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/JSArrayBufferView.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -129,6 +129,7 @@
JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context)
: Base(vm, context.structure(), context.butterfly())
, m_length(context.length())
+ , m_indexingMask(WTF::computeIndexingMask(context.length()))
, m_mode(context.mode())
{
m_vector.setWithoutBarrier(context.vector());
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/JSArrayBufferView.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/JSArrayBufferView.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/runtime/JSArrayBufferView.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -176,6 +176,7 @@
static ptrdiff_t offsetOfVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_vector); }
static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(JSArrayBufferView, m_length); }
+ static ptrdiff_t offsetOfIndexingMask() { return OBJECT_OFFSETOF(JSArrayBufferView, m_indexingMask); }
static ptrdiff_t offsetOfMode() { return OBJECT_OFFSETOF(JSArrayBufferView, m_mode); }
static RefPtr<ArrayBufferView> toWrapped(VM&, JSValue);
@@ -192,6 +193,7 @@
AuxiliaryBarrier<void*> m_vector;
uint32_t m_length;
+ uint32_t m_indexingMask;
TypedArrayMode m_mode;
};
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -233,7 +233,8 @@
void emitTierUpCheck(uint32_t decrementCount, Origin);
- ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
+ enum class ShouldMask { Yes, No };
+ ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp, ShouldMask);
B3::Kind memoryKind(B3::Opcode memoryOp);
ExpressionType emitLoadOp(LoadOpType, ExpressionType pointer, uint32_t offset);
void emitStoreOp(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
@@ -266,6 +267,7 @@
InsertionSet m_constantInsertionValues;
GPRReg m_memoryBaseGPR;
GPRReg m_memorySizeGPR { InvalidGPRReg };
+ GPRReg m_indexingMaskGPR { InvalidGPRReg };
GPRReg m_wasmContextGPR;
Value* m_instanceValue; // FIXME: make this lazy https://bugs.webkit.org/show_bug.cgi?id=169792
bool m_makesCalls { false };
@@ -360,6 +362,8 @@
if (mode != MemoryMode::Signaling) {
ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
+ m_indexingMaskGPR = pinnedRegs.indexingMask;
+ m_proc.pinRegister(pinnedRegs.indexingMask);
m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
m_proc.pinRegister(regInfo.sizeRegister);
@@ -444,6 +448,7 @@
const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
RegisterSet clobbers;
clobbers.set(pinnedRegs->baseMemoryPointer);
+ clobbers.set(pinnedRegs->indexingMask);
for (auto info : pinnedRegs->sizeRegisters)
clobbers.set(info.sizeRegister);
@@ -463,6 +468,7 @@
ASSERT(sizeRegs.size() >= 1);
ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
+ jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfIndexingMask()), pinnedRegs->indexingMask);
jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory);
for (unsigned i = 1; i < sizeRegs.size(); ++i)
jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
@@ -609,19 +615,21 @@
return { };
}
-inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
+inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation, ShouldMask shouldMask)
{
ASSERT(m_memoryBaseGPR);
switch (m_mode) {
- case MemoryMode::BoundsChecking:
+ case MemoryMode::BoundsChecking: {
// We're not using signal handling at all, we must therefore check that no memory access exceeds the current memory size.
ASSERT(m_memorySizeGPR);
ASSERT(sizeOfOperation + offset > offset);
- m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, origin(), m_memorySizeGPR, pointer, sizeOfOperation + offset - 1);
+ GPRReg indexingMask = shouldMask == ShouldMask::Yes ? m_indexingMaskGPR : InvalidGPRReg;
+ m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, origin(), m_memorySizeGPR, indexingMask, pointer, sizeOfOperation + offset - 1);
break;
+ }
- case MemoryMode::Signaling:
+ case MemoryMode::Signaling: {
// We've virtually mapped 4GiB+redzone for this memory. Only the user-allocated pages are addressable, contiguously in range [0, current],
// and everything above is mapped PROT_NONE. We don't need to perform any explicit bounds check in the 4GiB range because WebAssembly register
// memory accesses are 32-bit. However WebAssembly register + offset accesses perform the addition in 64-bit which can push an access above
@@ -641,6 +649,8 @@
case MemoryMode::NumberOfMemoryModes:
RELEASE_ASSERT_NOT_REACHED();
}
+ }
+
pointer = m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin(), pointer);
return m_currentBlock->appendNew<WasmAddressValue>(m_proc, origin(), pointer, m_memoryBaseGPR);
}
@@ -790,7 +800,7 @@
}
} else
- result = emitLoadOp(op, emitCheckAndPreparePointer(pointer, offset, sizeOfLoadOp(op)), offset);
+ result = emitLoadOp(op, emitCheckAndPreparePointer(pointer, offset, sizeOfLoadOp(op), ShouldMask::Yes), offset);
return { };
}
@@ -863,7 +873,7 @@
this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsMemoryAccess);
});
} else
- emitStoreOp(op, emitCheckAndPreparePointer(pointer, offset, sizeOfStoreOp(op)), value, offset);
+ emitStoreOp(op, emitCheckAndPreparePointer(pointer, offset, sizeOfStoreOp(op), ShouldMask::No), value, offset);
return { };
}
@@ -1264,6 +1274,7 @@
ASSERT(sizeRegs[0].sizeRegister != baseMemory);
ASSERT(sizeRegs[0].sizeRegister != newContext);
ASSERT(!sizeRegs[0].sizeOffset);
+ jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfIndexingMask()), pinnedRegs.indexingMask); // Indexing mask.
jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister); // Memory size.
jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory); // WasmMemory::void*.
});
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmBinding.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmBinding.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmBinding.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -649,6 +649,7 @@
// Set up the callee's baseMemory register as well as the memory size registers.
jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory); // JSWebAssemblyMemory*.
ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
+ jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyMemory::offsetOfIndexingMask()), pinnedRegs.indexingMask); // Indexing mask.
jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister); // Memory size.
jit.loadPtr(JIT::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory); // WasmMemory::void*.
for (unsigned i = 1; i < sizeRegs.size(); ++i) {
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemory.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemory.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemory.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -359,6 +359,7 @@
Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode mode)
: m_memory(memory)
, m_size(initial.bytes())
+ , m_indexingMask(WTF::computeIndexingMask(initial.bytes()))
, m_initial(initial)
, m_maximum(maximum)
, m_mappedCapacity(mappedCapacity)
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemory.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemory.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemory.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -72,6 +72,7 @@
void* memory() const { return m_memory; }
size_t size() const { return m_size; }
+ size_t indexingMask() const { return m_indexingMask; }
PageCount sizeInPages() const { return PageCount::fromBytes(m_size); }
PageCount initial() const { return m_initial; }
@@ -84,6 +85,9 @@
bool grow(PageCount);
void check() { ASSERT(!deletionHasBegun()); }
+
+ static ptrdiff_t offsetOfIndexingMask() { return OBJECT_OFFSETOF(Memory, m_indexingMask); }
+
private:
Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode);
Memory(PageCount initial, PageCount maximum);
@@ -91,6 +95,7 @@
// FIXME: we should move these to the instance to avoid a load on instance->instance calls.
void* m_memory { nullptr };
size_t m_size { 0 };
+ size_t m_indexingMask { 0 };
PageCount m_initial;
PageCount m_maximum;
size_t m_mappedCapacity { 0 };
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -58,6 +58,7 @@
Vector<PinnedSizeRegisterInfo> sizeRegisters;
GPRReg baseMemoryPointer = InvalidGPRReg;
GPRReg wasmContextPointer = InvalidGPRReg;
+ GPRReg indexingMask = InvalidGPRReg;
// FIXME: We should support more than one memory size register, and we should allow different
// WebAssembly.Instance to have different pins. Right now we take a vector with only one entry.
@@ -64,12 +65,13 @@
// If we have more than one size register, we can have one for each load size class.
// see: https://bugs.webkit.org/show_bug.cgi?id=162952
Vector<unsigned> pinnedSizes = { 0 };
- unsigned numberOfPinnedRegisters = pinnedSizes.size() + 1;
+ unsigned numberOfPinnedRegisters = pinnedSizes.size() + 2;
if (!useFastTLSForContext())
++numberOfPinnedRegisters;
Vector<GPRReg> pinnedRegs = getPinnedRegisters(numberOfPinnedRegisters);
baseMemoryPointer = pinnedRegs.takeLast();
+ indexingMask = pinnedRegs.takeLast();
if (!useFastTLSForContext())
wasmContextPointer = pinnedRegs.takeLast();
@@ -76,15 +78,16 @@
ASSERT(pinnedSizes.size() == pinnedRegs.size());
for (unsigned i = 0; i < pinnedSizes.size(); ++i)
sizeRegisters.append({ pinnedRegs[i], pinnedSizes[i] });
- staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer, wasmContextPointer);
+ staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer, indexingMask, wasmContextPointer);
});
return staticPinnedRegisterInfo.get();
}
-PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegisters, GPRReg baseMemoryPointer, GPRReg wasmContextPointer)
+PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegisters, GPRReg baseMemoryPointer, GPRReg indexingMask, GPRReg wasmContextPointer)
: sizeRegisters(WTFMove(sizeRegisters))
, baseMemoryPointer(baseMemoryPointer)
+ , indexingMask(indexingMask)
, wasmContextPointer(wasmContextPointer)
{
}
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemoryInformation.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemoryInformation.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/WasmMemoryInformation.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -44,9 +44,10 @@
struct PinnedRegisterInfo {
Vector<PinnedSizeRegisterInfo> sizeRegisters;
GPRReg baseMemoryPointer;
+ GPRReg indexingMask;
GPRReg wasmContextPointer;
static const PinnedRegisterInfo& get();
- PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg);
+ PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg, GPRReg);
RegisterSet toSave(MemoryMode mode) const
{
@@ -55,6 +56,7 @@
if (wasmContextPointer != InvalidGPRReg)
result.set(wasmContextPointer);
if (mode != MemoryMode::Signaling) {
+ result.set(indexingMask);
for (const auto& info : sizeRegisters)
result.set(info.sizeRegister);
}
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyMemory.cpp (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyMemory.cpp 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyMemory.cpp 2017-12-19 23:01:00 UTC (rev 226145)
@@ -68,6 +68,7 @@
ASSERT(m_memory->refCount() == 1);
m_memoryBase = m_memory->memory();
m_memorySize = m_memory->size();
+ m_indexingMask = m_memory->indexingMask();
}
JSArrayBuffer* JSWebAssemblyMemory::buffer(VM& vm, JSGlobalObject* globalObject)
@@ -116,6 +117,7 @@
}
m_memoryBase = memory().memory();
m_memorySize = memory().size();
+ m_memorySize = memory().indexingMask();
}
// We need to clear out the old array buffer because it might now be pointing
Modified: branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyMemory.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyMemory.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyMemory.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -52,6 +52,7 @@
static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memoryBase); }
static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_memorySize); }
+ static ptrdiff_t offsetOfIndexingMask() { return OBJECT_OFFSETOF(JSWebAssemblyMemory, m_indexingMask); }
private:
JSWebAssemblyMemory(VM&, Structure*, Ref<Wasm::Memory>&&);
@@ -61,6 +62,7 @@
void* m_memoryBase;
size_t m_memorySize;
+ size_t m_indexingMask;
Ref<Wasm::Memory> m_memory;
WriteBarrier<JSArrayBuffer> m_bufferWrapper;
RefPtr<ArrayBuffer> m_buffer;
Modified: branches/safari-604.5.100-branch/Source/WTF/ChangeLog (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/WTF/ChangeLog 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/WTF/ChangeLog 2017-12-19 23:01:00 UTC (rev 226145)
@@ -1,5 +1,23 @@
2017-12-18 Jason Marcell <[email protected]>
+ Apply patch. rdar://problem/36112003
+
+ 2017-12-17 Keith Miller <[email protected]>
+
+ Use index masking for TypedArrays and and Wasm.
+ https://bugs.webkit.org/show_bug.cgi?id=180920
+
+ Reviewed by Filip Pizlo.
+
+ Copy things from ToT that we will need for a branch.
+
+ * wtf/MathExtras.h:
+ (WTF::computeIndexingMask):
+ * wtf/StdLibExtras.h:
+ (std::clz):
+
+2017-12-18 Jason Marcell <[email protected]>
+
Cherry-pick r226068. rdar://problem/36112028
2017-12-16 Filip Pizlo <[email protected]>
Modified: branches/safari-604.5.100-branch/Source/WTF/wtf/MathExtras.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/WTF/wtf/MathExtras.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/WTF/wtf/MathExtras.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -495,6 +495,11 @@
return nonEmptyRangesOverlap(leftMin, leftMax, rightMin, rightMax);
}
+inline uint32_t computeIndexingMask(uint32_t size)
+{
+ return static_cast<uint64_t>(static_cast<uint32_t>(-1)) >> std::clz(size);
+}
+
} // namespace WTF
#endif // #ifndef WTF_MathExtras_h
Modified: branches/safari-604.5.100-branch/Source/WTF/wtf/StdLibExtras.h (226144 => 226145)
--- branches/safari-604.5.100-branch/Source/WTF/wtf/StdLibExtras.h 2017-12-19 23:00:51 UTC (rev 226144)
+++ branches/safari-604.5.100-branch/Source/WTF/wtf/StdLibExtras.h 2017-12-19 23:01:00 UTC (rev 226145)
@@ -519,6 +519,23 @@
template<class... _Args> struct conjunction : wtf_conjunction_impl<_Args...> { };
#endif
+enum class ZeroStatus {
+ MayBeZero,
+ NonZero
+};
+
+constexpr size_t clz(uint32_t value, ZeroStatus mightBeZero = ZeroStatus::MayBeZero)
+{
+ if (mightBeZero == ZeroStatus::MayBeZero && value) {
+#if COMPILER(MSVC)
+ return __lzcnt(value);
+#else
+ return __builtin_clz(value);
+#endif
+ }
+ return 32;
+}
+
} // namespace std
#define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)