Title: [214380] trunk/Source/_javascript_Core
Revision
214380
Author
[email protected]
Date
2017-03-24 15:09:15 -0700 (Fri, 24 Mar 2017)

Log Message

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):

Modified Paths

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
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to