Diff
Modified: branches/safari-605-branch/JSTests/ChangeLog (226686 => 226687)
--- branches/safari-605-branch/JSTests/ChangeLog 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/JSTests/ChangeLog 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,3 +1,20 @@
+2018-01-09 Jason Marcell <[email protected]>
+
+ Cherry-pick r226615. rdar://problem/36392328
+
+ 2018-01-08 JF Bastien <[email protected]>
+
+ WebAssembly: mask indexed accesses to Table
+ https://bugs.webkit.org/show_bug.cgi?id=181412
+ <rdar://problem/36363236>
+
+ Reviewed by Saam Barati.
+
+ Update error messages.
+
+ * wasm/js-api/table.js:
+ (assert.throws.WebAssembly.Table.prototype.grow):
+
2018-01-06 Yusuke Suzuki <[email protected]>
Object.getOwnPropertyNames includes "arguments" and "caller" for bound functions
Modified: branches/safari-605-branch/JSTests/wasm/js-api/table.js (226686 => 226687)
--- branches/safari-605-branch/JSTests/wasm/js-api/table.js 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/JSTests/wasm/js-api/table.js 2018-01-10 04:31:37 UTC (rev 226687)
@@ -243,7 +243,7 @@
{
const table = new WebAssembly.Table({element: "anyfunc", initial: 20});
- assert.throws(() => table.get(20), RangeError, "WebAssembly.Table.prototype.get expects an integer less than the size of the table");
+ assert.throws(() => table.get(20), RangeError, "WebAssembly.Table.prototype.get expects an integer less than the length of the table");
for (let i = 0; i < 20; i++)
assert.eq(table.get(i), null);
}
@@ -250,7 +250,7 @@
{
const table = new WebAssembly.Table({element: "anyfunc", initial: 20});
- assert.throws(() => table.set(20, null), RangeError, "WebAssembly.Table.prototype.set expects an integer less than the size of the table");
+ assert.throws(() => table.set(20, null), RangeError, "WebAssembly.Table.prototype.set expects an integer less than the length of the table");
for (let i = 0; i < 20; i++)
table.set(i, null);
}
Modified: branches/safari-605-branch/Source/_javascript_Core/ChangeLog (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/ChangeLog 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/ChangeLog 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,72 @@
2018-01-09 Jason Marcell <[email protected]>
+ Cherry-pick r226615. rdar://problem/36392328
+
+ 2018-01-08 JF Bastien <[email protected]>
+
+ WebAssembly: mask indexed accesses to Table
+ https://bugs.webkit.org/show_bug.cgi?id=181412
+ <rdar://problem/36363236>
+
+ Reviewed by Saam Barati.
+
+ WebAssembly Table indexed accesses are user-controlled and
+ bounds-checked. Force allocations of Table data to be a
+ power-of-two, and explicitly mask accesses after bounds-check
+ branches.
+
+ Rename misleading usage of "size" when "length" of a Table was
+ intended.
+
+ Rename the Spectre option from "disable" to "enable".
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::SpeculativeJIT):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::LowerDFGToB3):
+ * jit/JIT.cpp:
+ (JSC::JIT::JIT):
+ * runtime/Options.h:
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
+ (JSC::Wasm::B3IRGenerator::addCallIndirect):
+ * wasm/WasmTable.cpp:
+ (JSC::Wasm::Table::allocatedLength):
+ (JSC::Wasm::Table::setLength):
+ (JSC::Wasm::Table::create):
+ (JSC::Wasm::Table::Table):
+ (JSC::Wasm::Table::grow):
+ (JSC::Wasm::Table::clearFunction):
+ (JSC::Wasm::Table::setFunction):
+ * wasm/WasmTable.h:
+ (JSC::Wasm::Table::length const):
+ (JSC::Wasm::Table::offsetOfLength):
+ (JSC::Wasm::Table::offsetOfMask):
+ (JSC::Wasm::Table::mask const):
+ (JSC::Wasm::Table::isValidLength):
+ * wasm/js/JSWebAssemblyInstance.cpp:
+ (JSC::JSWebAssemblyInstance::create):
+ * wasm/js/JSWebAssemblyTable.cpp:
+ (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
+ (JSC::JSWebAssemblyTable::visitChildren):
+ (JSC::JSWebAssemblyTable::grow):
+ (JSC::JSWebAssemblyTable::getFunction):
+ (JSC::JSWebAssemblyTable::clearFunction):
+ (JSC::JSWebAssemblyTable::setFunction):
+ * wasm/js/JSWebAssemblyTable.h:
+ (JSC::JSWebAssemblyTable::isValidLength):
+ (JSC::JSWebAssemblyTable::length const):
+ (JSC::JSWebAssemblyTable::allocatedLength const):
+ * wasm/js/WebAssemblyModuleRecord.cpp:
+ (JSC::WebAssemblyModuleRecord::evaluate):
+ * wasm/js/WebAssemblyTablePrototype.cpp:
+ (JSC::webAssemblyTableProtoFuncLength):
+ (JSC::webAssemblyTableProtoFuncGrow):
+ (JSC::webAssemblyTableProtoFuncGet):
+ (JSC::webAssemblyTableProtoFuncSet):
+
+2018-01-09 Jason Marcell <[email protected]>
+
Cherry-pick r226556. rdar://problem/36392331
2018-01-08 Mark Lam <[email protected]>
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-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
@@ -74,7 +74,7 @@
, m_currentNode(0)
, m_lastGeneratedNode(LastNodeType)
, m_indexInBlock(0)
- , m_indexMaskingMode(Options::disableSpectreMitigations() ? IndexMaskingDisabled : IndexMaskingEnabled)
+ , m_indexMaskingMode(Options::enableSpectreMitigations() ? IndexMaskingEnabled : IndexMaskingDisabled)
, m_generationInfo(m_jit.graph().frameRegisterCount())
, m_state(m_jit.graph())
, m_interpreter(m_jit.graph(), m_state)
Modified: branches/safari-605-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -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
@@ -149,7 +149,7 @@
, m_availabilityCalculator(m_graph)
, m_state(state.graph)
, m_interpreter(state.graph, m_state)
- , m_indexMaskingMode(Options::disableSpectreMitigations() ? IndexMaskingDisabled : IndexMaskingEnabled)
+ , m_indexMaskingMode(Options::enableSpectreMitigations() ? IndexMaskingEnabled : IndexMaskingDisabled)
{
}
Modified: branches/safari-605-branch/Source/_javascript_Core/jit/JIT.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/jit/JIT.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/jit/JIT.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -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
@@ -84,7 +84,7 @@
, m_pcToCodeOriginMapBuilder(*vm)
, m_canBeOptimized(false)
, m_shouldEmitProfiling(false)
- , m_shouldUseIndexMasking(Options::disableSpectreMitigations() ? false : true)
+ , m_shouldUseIndexMasking(Options::enableSpectreMitigations())
, m_loopOSREntryBytecodeOffset(loopOSREntryBytecodeOffset)
{
}
Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/Options.h (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/runtime/Options.h 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/Options.h 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-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
@@ -458,7 +458,7 @@
\
v(bool, useWebAssembly, true, Normal, "Expose the WebAssembly global object.") \
\
- v(bool, disableSpectreMitigations, false, Restricted, "Disable Spectre mitigations.") \
+ v(bool, enableSpectreMitigations, true, Restricted, "Enable Spectre mitigations.") \
\
v(bool, useAsyncIterator, enableAsyncIteration, Normal, "Allow to use Async Iterator in JS.") \
\
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-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
@@ -650,7 +650,7 @@
// 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);
- GPRReg indexingMask = (shouldMask == ShouldMask::Yes && !Options::disableSpectreMitigations()) ? m_indexingMaskGPR : InvalidGPRReg;
+ GPRReg indexingMask = (shouldMask == ShouldMask::Yes && Options::enableSpectreMitigations()) ? m_indexingMaskGPR : InvalidGPRReg;
m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, origin(), m_memorySizeGPR, indexingMask, pointer, sizeOfOperation + offset - 1);
break;
}
@@ -1200,7 +1200,8 @@
ExpressionType callableFunctionBuffer;
ExpressionType instancesBuffer;
- ExpressionType callableFunctionBufferSize;
+ ExpressionType callableFunctionBufferLength;
+ ExpressionType mask;
{
ExpressionType table = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
instanceValue(), safeCast<int32_t>(Instance::offsetOfTable()));
@@ -1208,14 +1209,17 @@
table, safeCast<int32_t>(Table::offsetOfFunctions()));
instancesBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
table, safeCast<int32_t>(Table::offsetOfInstances()));
- callableFunctionBufferSize = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(),
- table, safeCast<int32_t>(Table::offsetOfSize()));
+ callableFunctionBufferLength = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(),
+ table, safeCast<int32_t>(Table::offsetOfLength()));
+ mask = m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin(),
+ m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(),
+ table, safeCast<int32_t>(Table::offsetOfMask())));
}
// Check the index we are looking for is valid.
{
CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
- m_currentBlock->appendNew<Value>(m_proc, AboveEqual, origin(), calleeIndex, callableFunctionBufferSize));
+ m_currentBlock->appendNew<Value>(m_proc, AboveEqual, origin(), calleeIndex, callableFunctionBufferLength));
check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsCallIndirect);
@@ -1222,43 +1226,49 @@
});
}
- // Compute the offset in the table index space we are looking for.
- ExpressionType offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
- m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin(), calleeIndex),
- constant(pointerType(), sizeof(CallableFunction)));
- ExpressionType callableFunction = m_currentBlock->appendNew<Value>(m_proc, Add, origin(), callableFunctionBuffer, offset);
+ calleeIndex = m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin(), calleeIndex);
- // Check that the CallableFunction is initialized. We trap if it isn't. An "invalid" SignatureIndex indicates it's not initialized.
- // FIXME: when we have trap handlers, we can just let the call fail because Signature::invalidIndex is 0. https://bugs.webkit.org/show_bug.cgi?id=177210
- static_assert(sizeof(CallableFunction::signatureIndex) == sizeof(uint32_t), "Load codegen assumes i32");
- ExpressionType calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), callableFunction, safeCast<int32_t>(OBJECT_OFFSETOF(CallableFunction, signatureIndex)));
+ if (Options::enableSpectreMitigations())
+ calleeIndex = m_currentBlock->appendNew<Value>(m_proc, BitAnd, origin(), mask, calleeIndex);
+
+ ExpressionType callableFunction;
{
- CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
- m_currentBlock->appendNew<Value>(m_proc, Equal, origin(),
- calleeSignatureIndex,
- m_currentBlock->appendNew<Const32Value>(m_proc, origin(), Signature::invalidIndex)));
+ // Compute the offset in the table index space we are looking for.
+ ExpressionType offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
+ calleeIndex, constant(pointerType(), sizeof(CallableFunction)));
+ callableFunction = m_currentBlock->appendNew<Value>(m_proc, Add, origin(), callableFunctionBuffer, offset);
- check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
- this->emitExceptionCheck(jit, ExceptionType::NullTableEntry);
- });
- }
+ // Check that the CallableFunction is initialized. We trap if it isn't. An "invalid" SignatureIndex indicates it's not initialized.
+ // FIXME: when we have trap handlers, we can just let the call fail because Signature::invalidIndex is 0. https://bugs.webkit.org/show_bug.cgi?id=177210
+ static_assert(sizeof(CallableFunction::signatureIndex) == sizeof(uint32_t), "Load codegen assumes i32");
+ ExpressionType calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), callableFunction, safeCast<int32_t>(OBJECT_OFFSETOF(CallableFunction, signatureIndex)));
+ {
+ CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
+ m_currentBlock->appendNew<Value>(m_proc, Equal, origin(),
+ calleeSignatureIndex,
+ m_currentBlock->appendNew<Const32Value>(m_proc, origin(), Signature::invalidIndex)));
- // Check the signature matches the value we expect.
- {
- ExpressionType expectedSignatureIndex = m_currentBlock->appendNew<Const32Value>(m_proc, origin(), SignatureInformation::get(signature));
- CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
- m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), calleeSignatureIndex, expectedSignatureIndex));
+ check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ this->emitExceptionCheck(jit, ExceptionType::NullTableEntry);
+ });
+ }
- check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
- this->emitExceptionCheck(jit, ExceptionType::BadSignature);
- });
+ // Check the signature matches the value we expect.
+ {
+ ExpressionType expectedSignatureIndex = m_currentBlock->appendNew<Const32Value>(m_proc, origin(), SignatureInformation::get(signature));
+ CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
+ m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), calleeSignatureIndex, expectedSignatureIndex));
+
+ check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ this->emitExceptionCheck(jit, ExceptionType::BadSignature);
+ });
+ }
}
// Do a context switch if needed.
{
Value* offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
- m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin(), calleeIndex),
- constant(pointerType(), sizeof(Instance*)));
+ calleeIndex, constant(pointerType(), sizeof(Instance*)));
Value* newContextInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
m_currentBlock->appendNew<Value>(m_proc, Add, origin(), instancesBuffer, offset));
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/WasmTable.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/WasmTable.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/WasmTable.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -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
@@ -34,9 +34,22 @@
namespace JSC { namespace Wasm {
+uint32_t Table::allocatedLength(uint32_t length)
+{
+ return WTF::roundUpToPowerOfTwo(length);
+}
+
+void Table::setLength(uint32_t length)
+{
+ m_length = length;
+ m_mask = WTF::maskForSize(length);
+ ASSERT(isValidLength(length));
+ ASSERT(m_mask == WTF::maskForSize(allocatedLength(length)));
+}
+
RefPtr<Table> Table::create(uint32_t initial, std::optional<uint32_t> maximum)
{
- if (!isValidSize(initial))
+ if (!isValidLength(initial))
return nullptr;
return adoptRef(new (NotNull, fastMalloc(sizeof(Table))) Table(initial, maximum));
}
@@ -47,16 +60,16 @@
Table::Table(uint32_t initial, std::optional<uint32_t> maximum)
{
- m_size = initial;
+ setLength(initial);
m_maximum = maximum;
- ASSERT(isValidSize(m_size));
- ASSERT(!m_maximum || *m_maximum >= m_size);
+ ASSERT(!m_maximum || *m_maximum >= m_length);
// FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
// But for now, we're not doing that.
- m_functions = MallocPtr<Wasm::CallableFunction>::malloc((sizeof(Wasm::CallableFunction) * Checked<size_t>(size())).unsafeGet());
- m_instances = MallocPtr<Instance*>::malloc((sizeof(Instance*) * Checked<size_t>(size())).unsafeGet());
- for (uint32_t i = 0; i < size(); ++i) {
+ m_functions = MallocPtr<Wasm::CallableFunction>::malloc((sizeof(Wasm::CallableFunction) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
+ // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
+ m_instances = MallocPtr<Instance*>::malloc((sizeof(Instance*) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
+ for (uint32_t i = 0; i < allocatedLength(m_length); ++i) {
new (&m_functions.get()[i]) CallableFunction();
ASSERT(m_functions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
m_instances.get()[i] = nullptr;
@@ -66,28 +79,31 @@
std::optional<uint32_t> Table::grow(uint32_t delta)
{
if (delta == 0)
- return size();
+ return length();
using Checked = Checked<uint32_t, RecordOverflow>;
- Checked newSizeChecked = size();
- newSizeChecked += delta;
- uint32_t newSize;
- if (newSizeChecked.safeGet(newSize) == CheckedState::DidOverflow)
+ Checked newLengthChecked = length();
+ newLengthChecked += delta;
+ uint32_t newLength;
+ if (newLengthChecked.safeGet(newLength) == CheckedState::DidOverflow)
return std::nullopt;
- if (maximum() && newSize > *maximum())
+ if (maximum() && newLength > *maximum())
return std::nullopt;
- if (!isValidSize(newSize))
+ if (!isValidLength(newLength))
return std::nullopt;
auto checkedGrow = [&] (auto& container) {
- Checked reallocSizeChecked = newSizeChecked;
- reallocSizeChecked *= sizeof(*container.get());
- uint32_t reallocSize;
- if (reallocSizeChecked.safeGet(reallocSize) == CheckedState::DidOverflow)
- return false;
- container.realloc(reallocSize);
- for (uint32_t i = m_size; i < newSize; ++i)
+ if (newLengthChecked.unsafeGet() > allocatedLength(m_length)) {
+ Checked reallocSizeChecked = allocatedLength(newLengthChecked.unsafeGet());
+ reallocSizeChecked *= sizeof(*container.get());
+ uint32_t reallocSize;
+ if (reallocSizeChecked.safeGet(reallocSize) == CheckedState::DidOverflow)
+ return false;
+ // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
+ container.realloc(reallocSize);
+ }
+ for (uint32_t i = m_length; i < allocatedLength(newLength); ++i)
new (&container.get()[i]) std::remove_reference_t<decltype(*container.get())>();
return true;
};
@@ -97,24 +113,24 @@
if (!checkedGrow(m_instances))
return std::nullopt;
- m_size = newSize;
+ setLength(newLength);
- return newSize;
+ return newLength;
}
void Table::clearFunction(uint32_t index)
{
- RELEASE_ASSERT(index < size());
- m_functions.get()[index] = Wasm::CallableFunction();
- ASSERT(m_functions.get()[index].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
- m_instances.get()[index] = nullptr;
+ RELEASE_ASSERT(index < length());
+ m_functions.get()[index & m_mask] = Wasm::CallableFunction();
+ ASSERT(m_functions.get()[index & m_mask].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
+ m_instances.get()[index & m_mask] = nullptr;
}
void Table::setFunction(uint32_t index, CallableFunction function, Instance* instance)
{
- RELEASE_ASSERT(index < size());
- m_functions.get()[index] = function;
- m_instances.get()[index] = instance;
+ RELEASE_ASSERT(index < length());
+ m_functions.get()[index & m_mask] = function;
+ m_instances.get()[index & m_mask] = instance;
}
} } // namespace JSC::Table
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/WasmTable.h (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/WasmTable.h 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/WasmTable.h 2018-01-10 04:31:37 UTC (rev 226687)
@@ -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
@@ -45,25 +45,31 @@
JS_EXPORT_PRIVATE ~Table();
std::optional<uint32_t> maximum() const { return m_maximum; }
- uint32_t size() const { return m_size; }
+ uint32_t length() const { return m_length; }
std::optional<uint32_t> grow(uint32_t delta) WARN_UNUSED_RETURN;
void clearFunction(uint32_t);
void setFunction(uint32_t, CallableFunction, Instance*);
- static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Table, m_size); }
static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(Table, m_functions); }
static ptrdiff_t offsetOfInstances() { return OBJECT_OFFSETOF(Table, m_instances); }
+ static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(Table, m_length); }
+ static ptrdiff_t offsetOfMask() { return OBJECT_OFFSETOF(Table, m_mask); }
- static bool isValidSize(uint32_t size) { return size < maxTableEntries; }
+ static uint32_t allocatedLength(uint32_t length);
+ uint32_t mask() const { return m_mask; }
+ static bool isValidLength(uint32_t length) { return length < maxTableEntries; }
private:
Table(uint32_t initial, std::optional<uint32_t> maximum);
- std::optional<uint32_t> m_maximum;
- uint32_t m_size;
+ void setLength(uint32_t);
+
MallocPtr<CallableFunction> m_functions;
// call_indirect needs to do an Instance check to potentially context switch when calling a function to another instance. We can hold raw pointers to Instance here because the embedder ensures that Table keeps all the instances alive. We couldn't hold a Ref here because it would cause cycles.
MallocPtr<Instance*> m_instances;
+ uint32_t m_length;
+ uint32_t m_mask;
+ std::optional<uint32_t> m_maximum;
};
} } // namespace JSC::Wasm
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-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
@@ -251,7 +251,7 @@
return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "Table import", "is not an instance of WebAssembly.Table")));
uint32_t expectedInitial = moduleInformation.tableInformation.initial();
- uint32_t actualInitial = table->size();
+ uint32_t actualInitial = table->length();
if (actualInitial < expectedInitial)
return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "Table import", "provided an 'initial' that is too small")));
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-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
@@ -62,8 +62,9 @@
{
// FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
// But for now, we're not doing that.
- m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(size())).unsafeGet());
- for (uint32_t i = 0; i < size(); ++i)
+ // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
+ m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(allocatedLength())).unsafeGet());
+ for (uint32_t i = 0; i < allocatedLength(); ++i)
new(&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
}
@@ -85,7 +86,7 @@
Base::visitChildren(thisObject, visitor);
- for (unsigned i = 0; i < thisObject->size(); ++i)
+ for (unsigned i = 0; i < thisObject->length(); ++i)
visitor.append(thisObject->m_jsFunctions.get()[i]);
}
@@ -94,16 +95,18 @@
if (delta == 0)
return true;
- size_t oldSize = size();
+ size_t oldLength = length();
auto grew = m_table->grow(delta);
if (!grew)
return false;
- size_t newSize = grew.value();
- m_jsFunctions.realloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(newSize)).unsafeGet());
+ size_t newLength = grew.value();
+ if (newLength > m_table->allocatedLength(oldLength))
+ // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
+ m_jsFunctions.realloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(m_table->allocatedLength(newLength))).unsafeGet());
- for (size_t i = oldSize; i < newSize; ++i)
+ for (size_t i = oldLength; i < m_table->allocatedLength(newLength); ++i)
new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
return true;
@@ -111,26 +114,26 @@
JSObject* JSWebAssemblyTable::getFunction(uint32_t index)
{
- RELEASE_ASSERT(index < size());
- return m_jsFunctions.get()[index].get();
+ RELEASE_ASSERT(index < length());
+ return m_jsFunctions.get()[index & m_table->mask()].get();
}
void JSWebAssemblyTable::clearFunction(uint32_t index)
{
m_table->clearFunction(index);
- m_jsFunctions.get()[index] = WriteBarrier<JSObject>();
+ m_jsFunctions.get()[index & m_table->mask()] = WriteBarrier<JSObject>();
}
void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyFunction* function)
{
m_table->setFunction(index, function->callableFunction(), &function->instance()->instance());
- m_jsFunctions.get()[index].set(vm, this, function);
+ m_jsFunctions.get()[index & m_table->mask()].set(vm, this, function);
}
void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyWrapperFunction* function)
{
m_table->setFunction(index, function->callableFunction(), &function->instance()->instance());
- m_jsFunctions.get()[index].set(vm, this, function);
+ m_jsFunctions.get()[index & m_table->mask()].set(vm, this, function);
}
} // namespace JSC
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h 2018-01-10 04:31:37 UTC (rev 226687)
@@ -48,9 +48,10 @@
DECLARE_INFO;
- static bool isValidSize(uint32_t size) { return Wasm::Table::isValidSize(size); }
+ static bool isValidLength(uint32_t length) { return Wasm::Table::isValidLength(length); }
std::optional<uint32_t> maximum() const { return m_table->maximum(); }
- uint32_t size() const { return m_table->size(); }
+ uint32_t length() const { return m_table->length(); }
+ uint32_t allocatedLength() const { return m_table->allocatedLength(length()); }
bool grow(uint32_t delta) WARN_UNUSED_RETURN;
JSObject* getFunction(uint32_t);
void clearFunction(uint32_t);
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-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
@@ -268,7 +268,7 @@
// Validation of all element ranges comes before all Table and Memory initialization.
forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex) {
uint64_t lastWrittenIndex = static_cast<uint64_t>(tableIndex) + static_cast<uint64_t>(element.functionIndices.size()) - 1;
- if (UNLIKELY(lastWrittenIndex >= table->size()))
+ if (UNLIKELY(lastWrittenIndex >= table->length()))
exception = JSValue(throwException(exec, scope, createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Element is trying to set an out of bounds table index"))));
});
Modified: branches/safari-605-branch/Source/_javascript_Core/wasm/js/WebAssemblyTablePrototype.cpp (226686 => 226687)
--- branches/safari-605-branch/Source/_javascript_Core/wasm/js/WebAssemblyTablePrototype.cpp 2018-01-10 04:31:33 UTC (rev 226686)
+++ branches/safari-605-branch/Source/_javascript_Core/wasm/js/WebAssemblyTablePrototype.cpp 2018-01-10 04:31:37 UTC (rev 226687)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-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
@@ -74,7 +74,7 @@
JSWebAssemblyTable* table = getTable(exec, vm, exec->thisValue());
RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- return JSValue::encode(jsNumber(table->size()));
+ return JSValue::encode(jsNumber(table->length()));
}
static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGrow(ExecState* exec)
@@ -88,12 +88,12 @@
uint32_t delta = toNonWrappingUint32(exec, exec->argument(0));
RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- uint32_t oldSize = table->size();
+ uint32_t oldLength = table->length();
if (!table->grow(delta))
return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, ASCIILiteral("WebAssembly.Table.prototype.grow could not grow the table"))));
- return JSValue::encode(jsNumber(oldSize));
+ return JSValue::encode(jsNumber(oldLength));
}
static EncodedJSValue JSC_HOST_CALL webAssemblyTableProtoFuncGet(ExecState* exec)
@@ -106,8 +106,8 @@
uint32_t index = toNonWrappingUint32(exec, exec->argument(0));
RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- if (index >= table->size())
- return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, ASCIILiteral("WebAssembly.Table.prototype.get expects an integer less than the size of the table"))));
+ if (index >= table->length())
+ return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, ASCIILiteral("WebAssembly.Table.prototype.get expects an integer less than the length of the table"))));
if (JSObject* result = table->getFunction(index))
return JSValue::encode(result);
@@ -131,8 +131,8 @@
uint32_t index = toNonWrappingUint32(exec, exec->argument(0));
RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- if (index >= table->size())
- return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, ASCIILiteral("WebAssembly.Table.prototype.set expects an integer less than the size of the table"))));
+ if (index >= table->length())
+ return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, ASCIILiteral("WebAssembly.Table.prototype.set expects an integer less than the length of the table"))));
if (value.isNull())
table->clearFunction(index);