Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (214379 => 214380)
--- trunk/Source/_javascript_Core/ChangeLog 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-03-24 22:09:15 UTC (rev 214380)
@@ -1,3 +1,46 @@
+2017-03-24 JF Bastien <[email protected]>
+
+ WebAssembly: spec-tests/memory.wast.js fails in debug
+ https://bugs.webkit.org/show_bug.cgi?id=169794
+
+ Reviewed by Keith Miller.
+
+ The failure was due to empty memories (with maximum size 0). Those
+ only occur in tests and in code that's trying to trip us. This
+ patch adds memory mode "none" which represents no memory. It can
+ work with either bounds checked or signaling code because it never
+ contains loads and stores.
+
+ The spec tests which were failing did the following:
+ > (module (memory (data)) (func (export "memsize") (result i32) (current_memory)))
+ > (assert_return (invoke "memsize") (i32.const 0))
+ > (module (memory (data "")) (func (export "memsize") (result i32) (current_memory)))
+ > (assert_return (invoke "memsize") (i32.const 0))
+ > (module (memory (data "x")) (func (export "memsize") (result i32) (current_memory)))
+ > (assert_return (invoke "memsize") (i32.const 1))
+
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::memoryKind):
+ * wasm/WasmMemory.cpp:
+ (JSC::Wasm::tryGetFastMemory):
+ (JSC::Wasm::releaseFastMemory):
+ (JSC::Wasm::Memory::Memory):
+ (JSC::Wasm::Memory::createImpl):
+ (JSC::Wasm::Memory::create):
+ (JSC::Wasm::Memory::grow):
+ (JSC::Wasm::Memory::makeString):
+ * wasm/WasmMemory.h:
+ * wasm/WasmMemoryInformation.cpp:
+ (JSC::Wasm::MemoryInformation::MemoryInformation):
+ * wasm/js/JSWebAssemblyCodeBlock.cpp:
+ (JSC::JSWebAssemblyCodeBlock::isSafeToRun):
+ * wasm/js/JSWebAssemblyModule.cpp:
+ (JSC::JSWebAssemblyModule::codeBlock):
+ (JSC::JSWebAssemblyModule::finishCreation):
+ * wasm/js/JSWebAssemblyModule.h:
+ (JSC::JSWebAssemblyModule::codeBlock):
+ (JSC::JSWebAssemblyModule::codeBlockFor):
+
2017-03-24 Mark Lam <[email protected]>
Array memcpy'ing fast paths should check if we're having a bad time if they cannot handle it.
Modified: trunk/Source/_javascript_Core/wasm/JSWebAssemblyCodeBlock.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/JSWebAssemblyCodeBlock.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/JSWebAssemblyCodeBlock.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -44,7 +44,7 @@
typedef JSCell Base;
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
- static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
+ static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
{
auto* result = new (NotNull, allocateCell<JSWebAssemblyCodeBlock>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmExitStubs>>(exitStubs), mode, calleeCount);
result->finishCreation(vm);
@@ -57,7 +57,7 @@
}
unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
- Wasm::Memory::Mode mode() const { return m_mode; }
+ Wasm::MemoryMode mode() const { return m_mode; }
JSWebAssemblyModule* module() const { return m_module.get(); }
bool isSafeToRun(JSWebAssemblyMemory*);
@@ -101,7 +101,7 @@
}
private:
- JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
+ JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::MemoryMode, unsigned calleeCount);
DECLARE_EXPORT_INFO;
static const bool needsDestruction = true;
static void destroy(JSCell*);
@@ -125,7 +125,7 @@
UnconditionalFinalizer m_unconditionalFinalizer;
Bag<CallLinkInfo> m_callLinkInfos;
Vector<Wasm::WasmExitStubs> m_wasmExitStubs;
- Wasm::Memory::Mode m_mode;
+ Wasm::MemoryMode m_mode;
unsigned m_calleeCount;
};
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2017-03-24 22:09:15 UTC (rev 214380)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 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 @@
inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
{
ASSERT(m_memoryBaseGPR);
- if (m_info.memory.mode() == Memory::Mode::BoundsChecking) {
+ if (m_info.memory.mode() == MemoryMode::BoundsChecking) {
ASSERT(m_memorySizeGPR);
ASSERT(sizeOfOperation + offset > offset);
m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
@@ -494,7 +494,7 @@
inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp)
{
- if (m_info.memory.mode() == Memory::Signaling)
+ if (m_info.memory.mode() == MemoryMode::Signaling)
return trapping(memoryOp);
return memoryOp;
}
Modified: trunk/Source/_javascript_Core/wasm/WasmMemory.cpp (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmMemory.cpp 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmMemory.cpp 2017-03-24 22:09:15 UTC (rev 214380)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -56,11 +56,22 @@
return true;
}
+const char* makeString(MemoryMode mode)
+{
+ switch (mode) {
+ case MemoryMode::BoundsChecking: return "BoundsChecking";
+ case MemoryMode::Signaling: return "Signaling";
+ case MemoryMode::NumberOfMemoryModes: break;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return "";
+}
+
// We use this as a heuristic to guess what mode a memory import will be. Most of the time we expect users to
// allocate the memory they are going to pass to all their modules right before compilation.
-static Memory::Mode lastAllocatedMemoryMode { Memory::Mode::Signaling };
+static MemoryMode lastAllocatedMemoryMode { MemoryMode::Signaling };
-Memory::Mode Memory::lastAllocatedMode()
+MemoryMode Memory::lastAllocatedMode()
{
return lastAllocatedMemoryMode;
}
@@ -85,7 +96,7 @@
return activeFastMemories(locker);
}
-inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memory::Mode& mode)
+inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, MemoryMode& mode)
{
// We might GC here so we should be holding the API lock.
// FIXME: We should be able to syncronously trigger the GC from another thread.
@@ -106,7 +117,7 @@
auto result = activeFastMemories(locker).add(memory);
ASSERT_UNUSED(result, result.isNewEntry);
mappedCapacity = fastMemoryMappedBytes;
- mode = Memory::Signaling;
+ mode = MemoryMode::Signaling;
return true;
}
return false;
@@ -125,7 +136,7 @@
if (mmapBytes(fastMemoryMappedBytes, memory)) {
mappedCapacity = fastMemoryMappedBytes;
- mode = Memory::Signaling;
+ mode = MemoryMode::Signaling;
LockHolder locker(memoryLock);
allocatedFastMemories++;
auto result = activeFastMemories(locker).add(memory);
@@ -134,9 +145,9 @@
return memory;
}
-inline void releaseFastMemory(void*& memory, size_t writableSize, size_t mappedCapacity, Memory::Mode mode)
+inline void releaseFastMemory(void*& memory, size_t writableSize, size_t mappedCapacity, MemoryMode mode)
{
- if (mode != Memory::Signaling || !memory)
+ if (mode != MemoryMode::Signaling || !memory)
return;
RELEASE_ASSERT(memory && mappedCapacity == fastMemoryMappedBytes);
@@ -159,9 +170,11 @@
, m_maximum(maximum)
{
ASSERT(!initial.bytes());
+ ASSERT(m_mode == MemoryMode::BoundsChecking);
+ dataLogLnIf(verbose, "Memory::Memory allocating ", *this);
}
-Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode mode)
+Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode mode)
: m_memory(memory)
, m_size(initial.bytes())
, m_initial(initial)
@@ -172,20 +185,20 @@
dataLogLnIf(verbose, "Memory::Memory allocating ", *this);
}
-RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode)
+RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> requiredMode)
{
RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
- Mode mode = requiredMode ? *requiredMode : BoundsChecking;
+ MemoryMode mode = requiredMode ? *requiredMode : MemoryMode::BoundsChecking;
const size_t size = initial.bytes();
size_t mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
void* memory = nullptr;
auto makeEmptyMemory = [&] () -> RefPtr<Memory> {
- if (mode == Signaling)
+ if (mode == MemoryMode::Signaling)
return nullptr;
- lastAllocatedMemoryMode = BoundsChecking;
+ lastAllocatedMemoryMode = MemoryMode::BoundsChecking;
return adoptRef(new Memory(initial, maximum));
};
@@ -196,9 +209,9 @@
return makeEmptyMemory();
}
- bool canUseFastMemory = !requiredMode || requiredMode == Signaling;
+ bool canUseFastMemory = !requiredMode || requiredMode == MemoryMode::Signaling;
if (!canUseFastMemory || !tryGetFastMemory(vm, memory, mappedCapacity, mode)) {
- if (mode == Signaling)
+ if (mode == MemoryMode::Signaling)
return nullptr;
if (Options::simulateWebAssemblyLowMemory() ? true : !mmapBytes(mappedCapacity, memory)) {
@@ -219,6 +232,7 @@
ASSERT(memory && size <= mappedCapacity);
if (mprotect(memory, size, PROT_READ | PROT_WRITE)) {
+ // FIXME: should this ever occur? https://bugs.webkit.org/show_bug.cgi?id=169890
dataLogLnIf(verbose, "Memory::create mprotect failed");
releaseFastMemory(memory, 0, mappedCapacity, mode);
if (memory) {
@@ -227,22 +241,21 @@
}
return nullptr;
}
-
+
lastAllocatedMemoryMode = mode;
dataLogLnIf(verbose, "Memory::create mmap succeeded");
return adoptRef(new Memory(memory, initial, maximum, mappedCapacity, mode));
}
-RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> mode)
+RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> mode)
{
RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
RefPtr<Memory> result = createImpl(vm, initial, maximum, mode);
if (result) {
- if (result->mode() == Signaling)
+ if (result->mode() == MemoryMode::Signaling)
RELEASE_ASSERT(result->m_mappedCapacity == fastMemoryMappedBytes);
if (mode)
ASSERT(*mode == result->mode());
- ASSERT(lastAllocatedMemoryMode == result->mode());
}
return result;
}
@@ -268,8 +281,21 @@
size_t desiredSize = newSize.bytes();
+ switch (mode()) {
+ case MemoryMode::BoundsChecking:
+ RELEASE_ASSERT(maximum().bytes() != 0);
+ break;
+ case MemoryMode::Signaling:
+ // Signaling memory must have been pre-allocated virtually.
+ RELEASE_ASSERT(m_memory);
+ break;
+ case MemoryMode::NumberOfMemoryModes:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
if (m_memory && desiredSize <= m_mappedCapacity) {
if (mprotect(static_cast<uint8_t*>(m_memory) + m_size, static_cast<size_t>(desiredSize - m_size), PROT_READ | PROT_WRITE)) {
+ // FIXME: should this ever occur? https://bugs.webkit.org/show_bug.cgi?id=169890
dataLogLnIf(verbose, "Memory::grow in-place failed ", *this);
return false;
}
@@ -279,8 +305,11 @@
return true;
}
- ASSERT(mode() != Signaling);
+ // Signaling memory can't grow past its already-mapped size.
+ RELEASE_ASSERT(mode() != MemoryMode::Signaling);
+
// Otherwise, let's try to make some new memory.
+ // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (newMemory == MAP_FAILED)
return false;
@@ -303,17 +332,6 @@
out.print("Memory at ", RawPointer(m_memory), ", size ", m_size, "B capacity ", m_mappedCapacity, "B, initial ", m_initial, " maximum ", m_maximum, " mode ", makeString(m_mode));
}
-const char* Memory::makeString(Mode mode) const
-{
- switch (mode) {
- case Mode::BoundsChecking: return "BoundsChecking";
- case Mode::Signaling: return "Signaling";
- case Mode::NumberOfModes: break;
- }
- RELEASE_ASSERT_NOT_REACHED();
- return "";
-}
-
} // namespace JSC
} // namespace Wasm
Modified: trunk/Source/_javascript_Core/wasm/WasmMemory.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmMemory.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmMemory.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,6 +44,15 @@
namespace Wasm {
+// FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
+enum class MemoryMode {
+ BoundsChecking,
+ Signaling,
+ NumberOfMemoryModes
+};
+static constexpr size_t NumberOfMemoryModes = static_cast<size_t>(MemoryMode::NumberOfMemoryModes);
+const char* makeString(MemoryMode);
+
class Memory : public RefCounted<Memory> {
WTF_MAKE_NONCOPYABLE(Memory);
WTF_MAKE_FAST_ALLOCATED;
@@ -50,17 +59,9 @@
public:
void dump(WTF::PrintStream&) const;
- // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
- enum Mode {
- BoundsChecking,
- Signaling,
- NumberOfModes
- };
- const char* makeString(Mode) const;
-
explicit operator bool() const { return !!m_memory; }
- static RefPtr<Memory> create(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt);
+ static RefPtr<Memory> create(VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode> requiredMode = std::nullopt);
Memory() = default;
~Memory();
@@ -72,8 +73,8 @@
PageCount initial() const { return m_initial; }
PageCount maximum() const { return m_maximum; }
- static Mode lastAllocatedMode();
- Mode mode() const { return m_mode; }
+ static MemoryMode lastAllocatedMode();
+ MemoryMode mode() const { return m_mode; }
// grow() should only be called from the JSWebAssemblyMemory object since that object needs to update internal
// pointers with the current base and size.
@@ -81,8 +82,8 @@
void check() { ASSERT(!deletionHasBegun()); }
private:
- static RefPtr<Memory> createImpl(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt);
- Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode);
+ static RefPtr<Memory> createImpl(VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode> requiredMode = std::nullopt);
+ Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode);
Memory(PageCount initial, PageCount maximum);
// FIXME: we should move these to the instance to avoid a load on instance->instance calls.
@@ -91,7 +92,7 @@
PageCount m_initial;
PageCount m_maximum;
size_t m_mappedCapacity { 0 };
- Mode m_mode { Mode::BoundsChecking };
+ MemoryMode m_mode { MemoryMode::BoundsChecking };
};
static_assert(sizeof(uint64_t) == sizeof(size_t), "We rely on allowing the maximum size of Memory we map to be 2^33 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold.");
Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp 2017-03-24 22:09:15 UTC (rev 214380)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 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 @@
{
}
-MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximum, std::optional<Memory::Mode> recompileMode, bool isImport)
+MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> recompileMode, bool isImport)
: m_initial(initial)
, m_maximum(maximum)
, m_isImport(isImport)
@@ -85,7 +85,16 @@
if (!recompileMode) {
if (!isImport) {
- m_reservedMemory = Memory::create(vm, initial, maximum, Memory::Signaling);
+ if (maximum && maximum.bytes() == 0) {
+ m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::BoundsChecking);
+ RELEASE_ASSERT(m_reservedMemory);
+ RELEASE_ASSERT(m_reservedMemory->maximum());
+ RELEASE_ASSERT(m_reservedMemory->maximum().bytes() == 0);
+ m_mode = m_reservedMemory->mode();
+ return;
+ }
+
+ m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::Signaling);
if (m_reservedMemory) {
ASSERT(!!*m_reservedMemory);
m_mode = m_reservedMemory->mode();
Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -54,13 +54,13 @@
ASSERT(!*this);
}
- MemoryInformation(VM&, PageCount initial, PageCount maximum, std::optional<Memory::Mode>, bool isImport);
+ MemoryInformation(VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode>, bool isImport);
PageCount initial() const { return m_initial; }
PageCount maximum() const { return m_maximum; }
bool hasReservedMemory() const { return m_reservedMemory; }
RefPtr<Memory> takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); }
- Memory::Mode mode() const { return m_mode; }
+ MemoryMode mode() const { return m_mode; }
bool isImport() const { return m_isImport; }
explicit operator bool() const { return !!m_initial; }
@@ -69,7 +69,7 @@
RefPtr<Memory> m_reservedMemory;
PageCount m_initial { };
PageCount m_maximum { };
- Memory::Mode m_mode { Memory::Mode::BoundsChecking };
+ MemoryMode m_mode { MemoryMode::BoundsChecking };
bool m_isImport { false };
};
Modified: trunk/Source/_javascript_Core/wasm/WasmModuleParser.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmModuleParser.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmModuleParser.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -44,7 +44,7 @@
class ModuleParser : public Parser<ModuleParserResult> {
public:
- ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional<Memory::Mode> mode)
+ ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional<MemoryMode> mode)
: Parser(vm, sourceBuffer, sourceLength)
, m_mode(mode)
{
@@ -66,7 +66,7 @@
PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
ModuleParserResult m_result;
- std::optional<Memory::Mode> m_mode { std::nullopt };
+ std::optional<MemoryMode> m_mode { std::nullopt };
bool m_hasTable { false };
};
Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.cpp (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmPlan.cpp 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.cpp 2017-03-24 22:09:15 UTC (rev 214380)
@@ -63,7 +63,7 @@
{
}
-bool Plan::parseAndValidateModule(std::optional<Memory::Mode> recompileMode)
+bool Plan::parseAndValidateModule(std::optional<MemoryMode> recompileMode)
{
MonotonicTime startTime;
if (verbose || Options::reportCompileTimes())
@@ -111,7 +111,7 @@
// The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
// that could touch its stack are done executing.
SUPPRESS_ASAN
-void Plan::run(std::optional<Memory::Mode> recompileMode)
+void Plan::run(std::optional<MemoryMode> recompileMode)
{
if (!parseAndValidateModule(recompileMode))
return;
Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/WasmPlan.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -49,9 +49,9 @@
JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
JS_EXPORT_PRIVATE ~Plan();
- bool parseAndValidateModule(std::optional<Memory::Mode> = std::nullopt);
+ bool parseAndValidateModule(std::optional<MemoryMode> = std::nullopt);
- JS_EXPORT_PRIVATE void run(std::optional<Memory::Mode> = std::nullopt);
+ JS_EXPORT_PRIVATE void run(std::optional<MemoryMode> = std::nullopt);
JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>);
@@ -92,7 +92,7 @@
return WTFMove(m_wasmExitStubs);
}
- Memory::Mode mode() const { return m_moduleInformation->memory.mode(); }
+ MemoryMode mode() const { return m_moduleInformation->memory.mode(); }
private:
std::unique_ptr<ModuleInformation> m_moduleInformation;
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.cpp (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.cpp 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyCodeBlock.cpp 2017-03-24 22:09:15 UTC (rev 214380)
@@ -36,7 +36,7 @@
const ClassInfo JSWebAssemblyCodeBlock::s_info = { "WebAssemblyCodeBlock", nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) };
-JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
+JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
: Base(vm, vm.webAssemblyCodeBlockStructure.get())
, m_callLinkInfos(WTFMove(callLinkInfos))
, m_wasmExitStubs(WTFMove(wasmExitStubs))
@@ -54,9 +54,21 @@
bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory)
{
- if (mode() == Wasm::Memory::Signaling)
- return memory->memory().mode() == mode();
- return true;
+ Wasm::MemoryMode codeMode = mode();
+ Wasm::MemoryMode memoryMode = memory->memory().mode();
+ switch (codeMode) {
+ case Wasm::MemoryMode::BoundsChecking:
+ return true;
+ case Wasm::MemoryMode::Signaling:
+ // Code being in Signaling mode means that it performs no bounds checks.
+ // Its memory, even if empty, absolutely must also be in Signaling mode
+ // because the page protection detects out-of-bounds accesses.
+ return memoryMode == Wasm::MemoryMode::Signaling;
+ case Wasm::MemoryMode::NumberOfMemoryModes:
+ break;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return false;
}
void JSWebAssemblyCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -79,7 +79,7 @@
JSWebAssemblyMemory* memory() { return m_memory.get(); }
// Calling this might trigger a recompile.
void setMemory(VM&, ExecState*, JSWebAssemblyMemory*);
- Wasm::Memory::Mode memoryMode() { return memory()->memory().mode(); }
+ Wasm::MemoryMode memoryMode() { return memory()->memory().mode(); }
JSWebAssemblyTable* table() { return m_table.get(); }
void setTable(VM& vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp 2017-03-24 22:09:15 UTC (rev 214380)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,7 +42,7 @@
const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
-JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan& plan, std::optional<Wasm::Memory::Mode> mode)
+JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan& plan, std::optional<Wasm::MemoryMode> mode)
{
auto scope = DECLARE_THROW_SCOPE(vm);
// On failure, a new WebAssembly.CompileError is thrown.
@@ -85,14 +85,14 @@
JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM& vm, ExecState* exec, JSWebAssemblyMemory* memory)
{
- Wasm::Memory::Mode mode = memory->memory().mode();
+ Wasm::MemoryMode mode = memory->memory().mode();
- for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i) {
+ for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; ++i) {
if (m_codeBlocks[i] && m_codeBlocks[i]->isSafeToRun(memory))
return m_codeBlocks[i].get();
}
- ASSERT(!m_codeBlocks[mode]);
+ ASSERT(!codeBlockFor(mode));
auto scope = DECLARE_THROW_SCOPE(vm);
// We don't have a code block for this mode, we need to recompile...
Wasm::Plan plan(&vm, static_cast<uint8_t*>(m_sourceBuffer->data()), m_sourceBuffer->byteLength());
@@ -107,7 +107,7 @@
}
ASSERT(mode == codeBlock->mode());
- m_codeBlocks[mode].set(vm, this, codeBlock);
+ codeBlockFor(mode).set(vm, this, codeBlock);
return codeBlock;
}
@@ -132,7 +132,7 @@
m_sourceBuffer = ArrayBuffer::create(source, byteSize);
m_moduleInformation = plan.takeModuleInformation();
m_exportSymbolTable.set(vm, this, exportSymbolTable);
- m_codeBlocks[codeBlock->mode()].set(vm, this, codeBlock);
+ codeBlockFor(codeBlock->mode()).set(vm, this, codeBlock);
}
void JSWebAssemblyModule::destroy(JSCell* cell)
@@ -147,7 +147,7 @@
Base::visitChildren(thisObject, visitor);
visitor.append(thisObject->m_exportSymbolTable);
- for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i)
+ for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; ++i)
visitor.append(thisObject->m_codeBlocks[i]);
}
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h (214379 => 214380)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h 2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h 2017-03-24 22:09:15 UTC (rev 214380)
@@ -62,12 +62,13 @@
}
// Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
- JSWebAssemblyCodeBlock* codeBlock() { return m_codeBlocks[m_moduleInformation->memory.mode()].get(); }
+ JSWebAssemblyCodeBlock* codeBlock() { return codeBlockFor(m_moduleInformation->memory.mode()).get(); }
// Returns the appropriate code block for the given memory, possibly triggering a recompile.
JSWebAssemblyCodeBlock* codeBlock(VM&, ExecState*, JSWebAssemblyMemory*);
private:
- JSWebAssemblyCodeBlock* buildCodeBlock(VM&, ExecState*, Wasm::Plan&, std::optional<Wasm::Memory::Mode> mode = std::nullopt);
+ WriteBarrier<JSWebAssemblyCodeBlock>& codeBlockFor(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast<size_t>(mode)]; }
+ JSWebAssemblyCodeBlock* buildCodeBlock(VM&, ExecState*, Wasm::Plan&, std::optional<Wasm::MemoryMode> mode = std::nullopt);
JSWebAssemblyModule(VM&, Structure*);
void finishCreation(VM&, ExecState*, uint8_t* source, size_t byteSize);
@@ -77,7 +78,7 @@
RefPtr<ArrayBuffer> m_sourceBuffer;
std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
WriteBarrier<SymbolTable> m_exportSymbolTable;
- WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::Memory::NumberOfModes];
+ WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes];
};
} // namespace JSC