COMMIT_MESSAGE

 1memory-wast-js
 2

Source/JavaScriptCore/ChangeLog

 12017-03-17 JF Bastien <jfbastien@apple.com>
 2
 3 WebAssembly: spec-tests/memory.wast.js fails in debug
 4 https://bugs.webkit.org/show_bug.cgi?id=169794
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 The failure was due to empty memories (with maximum size 0). Those
 9 only occur in tests and in code that's trying to trip us. This
 10 patch adds memory mode "none" which represents no memory. It can
 11 work with either bounds checked or signaling code because it never
 12 contains loads and stores.
 13
 14 The spec tests which were failing did the following:
 15 > (module (memory (data)) (func (export "memsize") (result i32) (current_memory)))
 16 > (assert_return (invoke "memsize") (i32.const 0))
 17 > (module (memory (data "")) (func (export "memsize") (result i32) (current_memory)))
 18 > (assert_return (invoke "memsize") (i32.const 0))
 19 > (module (memory (data "x")) (func (export "memsize") (result i32) (current_memory)))
 20 > (assert_return (invoke "memsize") (i32.const 1))
 21
 22 * wasm/WasmB3IRGenerator.cpp:
 23 (JSC::Wasm::B3IRGenerator::memoryKind):
 24 * wasm/WasmMemory.cpp:
 25 (JSC::Wasm::tryGetFastMemory):
 26 (JSC::Wasm::releaseFastMemory):
 27 (JSC::Wasm::Memory::Memory):
 28 (JSC::Wasm::Memory::createImpl):
 29 (JSC::Wasm::Memory::create):
 30 (JSC::Wasm::Memory::grow):
 31 (JSC::Wasm::Memory::makeString):
 32 * wasm/WasmMemory.h:
 33 * wasm/WasmMemoryInformation.cpp:
 34 (JSC::Wasm::MemoryInformation::MemoryInformation):
 35 * wasm/js/JSWebAssemblyCodeBlock.cpp:
 36 (JSC::JSWebAssemblyCodeBlock::isSafeToRun):
 37 * wasm/js/JSWebAssemblyModule.cpp:
 38 (JSC::JSWebAssemblyModule::codeBlock):
 39 (JSC::JSWebAssemblyModule::finishCreation):
 40 * wasm/js/JSWebAssemblyModule.h:
 41 (JSC::JSWebAssemblyModule::codeBlock):
 42 (JSC::JSWebAssemblyModule::codeBlockFor):
 43 * wasm/js/WebAssemblyInstanceConstructor.cpp:
 44 (JSC::WebAssemblyInstanceConstructor::createInstance):
 45 * wasm/js/WebAssemblyMemoryConstructor.cpp:
 46 (JSC::constructJSWebAssemblyMemory):
 47
1482017-03-17 Michael Saboff <msaboff@apple.com>
249
350 Use USE_INTERNAL_SDK to compute ENABLE_FAST_JIT_PERMISSIONS instead of HAVE_INTERNAL_SDK

Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h

@@public:
4444 typedef JSCell Base;
4545 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
4646
47  static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
 47 static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
4848 {
4949 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);
5050 result->finishCreation(vm);

@@public:
5757 }
5858
5959 unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
60  Wasm::Memory::Mode mode() const { return m_mode; }
 60 Wasm::MemoryMode mode() const { return m_mode; }
6161 JSWebAssemblyModule* module() const { return m_module.get(); }
6262 bool isSafeToRun(JSWebAssemblyMemory*);
6363

@@public:
101101 }
102102
103103private:
104  JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
 104 JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::MemoryMode, unsigned calleeCount);
105105 DECLARE_EXPORT_INFO;
106106 static const bool needsDestruction = true;
107107 static void destroy(JSCell*);

@@private:
125125 UnconditionalFinalizer m_unconditionalFinalizer;
126126 Bag<CallLinkInfo> m_callLinkInfos;
127127 Vector<Wasm::WasmExitStubs> m_wasmExitStubs;
128  Wasm::Memory::Mode m_mode;
 128 Wasm::MemoryMode m_mode;
129129 unsigned m_calleeCount;
130130};
131131

Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@auto B3IRGenerator::setGlobal(uint32_t index, ExpressionType value) -> PartialRe
458458inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
459459{
460460 ASSERT(m_memoryBaseGPR);
461  if (m_info.memory.mode() == Memory::Mode::BoundsChecking) {
 461 if (m_info.memory.mode() == MemoryMode::BoundsChecking) {
462462 ASSERT(m_memorySizeGPR);
463463 ASSERT(sizeOfOperation + offset > offset);
464464 m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);

@@inline uint32_t sizeOfLoadOp(LoadOpType op)
494494
495495inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp)
496496{
497  if (m_info.memory.mode() == Memory::Signaling)
 497 if (m_info.memory.mode() == MemoryMode::Signaling)
498498 return trapping(memoryOp);
499499 return memoryOp;
500500}

Source/JavaScriptCore/wasm/WasmMemory.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@inline bool mmapBytes(size_t bytes, void*& memory)
5656 return true;
5757}
5858
 59const char* makeString(MemoryMode mode)
 60{
 61 switch (mode) {
 62 case MemoryMode::BoundsChecking: return "BoundsChecking";
 63 case MemoryMode::Signaling: return "Signaling";
 64 case MemoryMode::NumberOfMemoryModes: break;
 65 }
 66 RELEASE_ASSERT_NOT_REACHED();
 67 return "";
 68}
 69
5970// We use this as a heuristic to guess what mode a memory import will be. Most of the time we expect users to
6071// allocate the memory they are going to pass to all their modules right before compilation.
61 static Memory::Mode lastAllocatedMemoryMode { Memory::Mode::Signaling };
 72static MemoryMode lastAllocatedMemoryMode { MemoryMode::Signaling };
6273
63 Memory::Mode Memory::lastAllocatedMode()
 74MemoryMode Memory::lastAllocatedMode()
6475{
6576 return lastAllocatedMemoryMode;
6677}

@@const HashSet<void*>& viewActiveFastMemories(const AbstractLocker& locker)
8596 return activeFastMemories(locker);
8697}
8798
88 inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memory::Mode& mode)
 99inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, MemoryMode& mode)
89100{
90101 // We might GC here so we should be holding the API lock.
91102 // FIXME: We should be able to syncronously trigger the GC from another thread.

@@inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memo
106117 auto result = activeFastMemories(locker).add(memory);
107118 ASSERT_UNUSED(result, result.isNewEntry);
108119 mappedCapacity = fastMemoryMappedBytes;
109  mode = Memory::Signaling;
 120 mode = MemoryMode::Signaling;
110121 return true;
111122 }
112123 return false;

@@inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memo
125136
126137 if (mmapBytes(fastMemoryMappedBytes, memory)) {
127138 mappedCapacity = fastMemoryMappedBytes;
128  mode = Memory::Signaling;
 139 mode = MemoryMode::Signaling;
129140 LockHolder locker(memoryLock);
130141 allocatedFastMemories++;
131142 auto result = activeFastMemories(locker).add(memory);

@@inline bool tryGetFastMemory(VM& vm, void*& memory, size_t& mappedCapacity, Memo
134145 return memory;
135146}
136147
137 inline void releaseFastMemory(void*& memory, size_t writableSize, size_t mappedCapacity, Memory::Mode mode)
 148inline void releaseFastMemory(void*& memory, size_t writableSize, size_t mappedCapacity, MemoryMode mode)
138149{
139  if (mode != Memory::Signaling || !memory)
 150 if (mode != MemoryMode::Signaling || !memory)
140151 return;
141152
142153 RELEASE_ASSERT(memory && mappedCapacity == fastMemoryMappedBytes);

@@inline void releaseFastMemory(void*& memory, size_t writableSize, size_t mappedC
157168Memory::Memory(PageCount initial, PageCount maximum)
158169 : m_initial(initial)
159170 , m_maximum(maximum)
 171 , m_mode(MemoryMode::BoundsChecking)
160172{
161173 ASSERT(!initial.bytes());
 174 dataLogLnIf(verbose, "Memory::Memory allocating ", *this);
162175}
163176
164 Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode mode)
 177Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode mode)
165178 : m_memory(memory)
166179 , m_size(initial.bytes())
167180 , m_initial(initial)

@@Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mapped
172185 dataLogLnIf(verbose, "Memory::Memory allocating ", *this);
173186}
174187
175 RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode)
 188RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> requiredMode)
176189{
177190 RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
178191
179  Mode mode = requiredMode ? *requiredMode : BoundsChecking;
 192 MemoryMode mode = requiredMode ? *requiredMode : MemoryMode::BoundsChecking;
180193 const size_t size = initial.bytes();
181194 size_t mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
182195 void* memory = nullptr;
183196
184197 auto makeEmptyMemory = [&] () -> RefPtr<Memory> {
185  if (mode == Signaling)
 198 if (mode == MemoryMode::Signaling)
186199 return nullptr;
187200
188  lastAllocatedMemoryMode = BoundsChecking;
 201 lastAllocatedMemoryMode = MemoryMode::BoundsChecking;
189202 return adoptRef(new Memory(initial, maximum));
190203 };
191204

@@RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum,
196209 return makeEmptyMemory();
197210 }
198211
199  bool canUseFastMemory = !requiredMode || requiredMode == Signaling;
 212 bool canUseFastMemory = !requiredMode || requiredMode == MemoryMode::Signaling;
200213 if (!canUseFastMemory || !tryGetFastMemory(vm, memory, mappedCapacity, mode)) {
201  if (mode == Signaling)
 214 if (mode == MemoryMode::Signaling)
202215 return nullptr;
203216
204217 if (Options::simulateWebAssemblyLowMemory() ? true : !mmapBytes(mappedCapacity, memory)) {

@@RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum,
219232
220233 ASSERT(memory && size <= mappedCapacity);
221234 if (mprotect(memory, size, PROT_READ | PROT_WRITE)) {
 235 // FIXME: should this ever occur? https://bugs.webkit.org/show_bug.cgi?id=169890
222236 dataLogLnIf(verbose, "Memory::create mprotect failed");
223237 releaseFastMemory(memory, 0, mappedCapacity, mode);
224238 if (memory) {

@@RefPtr<Memory> Memory::createImpl(VM& vm, PageCount initial, PageCount maximum,
227241 }
228242 return nullptr;
229243 }
230 
 244
231245 lastAllocatedMemoryMode = mode;
232246 dataLogLnIf(verbose, "Memory::create mmap succeeded");
233247 return adoptRef(new Memory(memory, initial, maximum, mappedCapacity, mode));
234248}
235249
236 RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum, std::optional<Mode> mode)
 250RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> mode)
237251{
238252 RELEASE_ASSERT(!maximum || maximum >= initial); // This should be guaranteed by our caller.
239253 RefPtr<Memory> result = createImpl(vm, initial, maximum, mode);
240254 if (result) {
241  if (result->mode() == Signaling)
 255 if (result->mode() == MemoryMode::Signaling)
242256 RELEASE_ASSERT(result->m_mappedCapacity == fastMemoryMappedBytes);
243257 if (mode)
244258 ASSERT(*mode == result->mode());
245  ASSERT(lastAllocatedMemoryMode == result->mode());
246259 }
247260 return result;
248261}

@@bool Memory::grow(PageCount newSize)
268281
269282 size_t desiredSize = newSize.bytes();
270283
 284 switch (mode()) {
 285 case MemoryMode::BoundsChecking:
 286 RELEASE_ASSERT(maximum().bytes() != 0);
 287 break;
 288 case MemoryMode::Signaling:
 289 // Signaling memory must have been pre-allocated virtually.
 290 RELEASE_ASSERT(m_memory);
 291 break;
 292 case MemoryMode::NumberOfMemoryModes:
 293 RELEASE_ASSERT_NOT_REACHED();
 294 }
 295
271296 if (m_memory && desiredSize <= m_mappedCapacity) {
272297 if (mprotect(static_cast<uint8_t*>(m_memory) + m_size, static_cast<size_t>(desiredSize - m_size), PROT_READ | PROT_WRITE)) {
 298 // FIXME: should this ever occur? https://bugs.webkit.org/show_bug.cgi?id=169890
273299 dataLogLnIf(verbose, "Memory::grow in-place failed ", *this);
274300 return false;
275301 }

@@bool Memory::grow(PageCount newSize)
279305 return true;
280306 }
281307
282  ASSERT(mode() != Signaling);
 308 // Signaling memory can't grow past its already-mapped size.
 309 RELEASE_ASSERT(mode() != MemoryMode::Signaling);
 310
283311 // Otherwise, let's try to make some new memory.
 312 // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
284313 void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
285314 if (newMemory == MAP_FAILED)
286315 return false;

@@void Memory::dump(PrintStream& out) const
303332 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));
304333}
305334
306 const char* Memory::makeString(Mode mode) const
307 {
308  switch (mode) {
309  case Mode::BoundsChecking: return "BoundsChecking";
310  case Mode::Signaling: return "Signaling";
311  case Mode::NumberOfModes: break;
312  }
313  RELEASE_ASSERT_NOT_REACHED();
314  return "";
315 }
316 
317335} // namespace JSC
318336
319337} // namespace Wasm

Source/JavaScriptCore/wasm/WasmMemory.h

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@class VM;
4444
4545namespace Wasm {
4646
 47// FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
 48enum class MemoryMode {
 49 BoundsChecking,
 50 Signaling,
 51 NumberOfMemoryModes
 52};
 53static constexpr size_t NumberOfMemoryModes = static_cast<size_t>(MemoryMode::NumberOfMemoryModes);
 54const char* makeString(MemoryMode);
 55
4756class Memory : public RefCounted<Memory> {
4857 WTF_MAKE_NONCOPYABLE(Memory);
4958 WTF_MAKE_FAST_ALLOCATED;
5059public:
5160 void dump(WTF::PrintStream&) const;
5261
53  // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
54  enum Mode {
55  BoundsChecking,
56  Signaling,
57  NumberOfModes
58  };
59  const char* makeString(Mode) const;
60 
6162 explicit operator bool() const { return !!m_memory; }
6263
63  static RefPtr<Memory> create(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt);
 64 static RefPtr<Memory> create(VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode> requiredMode = std::nullopt);
6465
6566 Memory() = default;
6667 ~Memory();

@@public:
7273 PageCount initial() const { return m_initial; }
7374 PageCount maximum() const { return m_maximum; }
7475
75  static Mode lastAllocatedMode();
76  Mode mode() const { return m_mode; }
 76 static MemoryMode lastAllocatedMode();
 77 MemoryMode mode() const { return m_mode; }
7778
7879 // grow() should only be called from the JSWebAssemblyMemory object since that object needs to update internal
7980 // pointers with the current base and size.

@@public:
8182
8283 void check() { ASSERT(!deletionHasBegun()); }
8384private:
84  static RefPtr<Memory> createImpl(VM&, PageCount initial, PageCount maximum, std::optional<Mode> requiredMode = std::nullopt);
85  Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode);
 85 static RefPtr<Memory> createImpl(VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode> requiredMode = std::nullopt);
 86 Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode);
8687 Memory(PageCount initial, PageCount maximum);
8788
8889 // FIXME: we should move these to the instance to avoid a load on instance->instance calls.

@@private:
9192 PageCount m_initial;
9293 PageCount m_maximum;
9394 size_t m_mappedCapacity { 0 };
94  Mode m_mode { Mode::BoundsChecking };
 95 MemoryMode m_mode { MemoryMode::BoundsChecking };
9596};
9697
9798static_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.");

Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegi
7474{
7575}
7676
77 MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximum, std::optional<Memory::Mode> recompileMode, bool isImport)
 77MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> recompileMode, bool isImport)
7878 : m_initial(initial)
7979 , m_maximum(maximum)
8080 , m_isImport(isImport)

@@MemoryInformation::MemoryInformation(VM& vm, PageCount initial, PageCount maximu
8585
8686 if (!recompileMode) {
8787 if (!isImport) {
88  m_reservedMemory = Memory::create(vm, initial, maximum, Memory::Signaling);
 88 if (maximum && maximum.bytes() == 0) {
 89 m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::BoundsChecking);
 90 RELEASE_ASSERT(m_reservedMemory);
 91 RELEASE_ASSERT(m_reservedMemory->maximum());
 92 RELEASE_ASSERT(m_reservedMemory->maximum().bytes() == 0);
 93 m_mode = m_reservedMemory->mode();
 94 return;
 95 }
 96
 97 m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::Signaling);
8998 if (m_reservedMemory) {
9099 ASSERT(!!*m_reservedMemory);
91100 m_mode = m_reservedMemory->mode();

Source/JavaScriptCore/wasm/WasmMemoryInformation.h

@@public:
5454 ASSERT(!*this);
5555 }
5656
57  MemoryInformation(VM&, PageCount initial, PageCount maximum, std::optional<Memory::Mode>, bool isImport);
 57 MemoryInformation(VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode>, bool isImport);
5858
5959 PageCount initial() const { return m_initial; }
6060 PageCount maximum() const { return m_maximum; }
6161 bool hasReservedMemory() const { return m_reservedMemory; }
6262 RefPtr<Memory> takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); }
63  Memory::Mode mode() const { return m_mode; }
 63 MemoryMode mode() const { return m_mode; }
6464 bool isImport() const { return m_isImport; }
6565
6666 explicit operator bool() const { return !!m_initial; }

@@private:
6969 RefPtr<Memory> m_reservedMemory;
7070 PageCount m_initial { };
7171 PageCount m_maximum { };
72  Memory::Mode m_mode { Memory::Mode::BoundsChecking };
 72 MemoryMode m_mode { MemoryMode::BoundsChecking };
7373 bool m_isImport { false };
7474};
7575

Source/JavaScriptCore/wasm/WasmModuleParser.h

@@struct ModuleParserResult {
4444class ModuleParser : public Parser<ModuleParserResult> {
4545public:
4646
47  ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional<Memory::Mode> mode)
 47 ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional<MemoryMode> mode)
4848 : Parser(vm, sourceBuffer, sourceLength)
4949 , m_mode(mode)
5050 {

@@private:
6666 PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
6767
6868 ModuleParserResult m_result;
69  std::optional<Memory::Mode> m_mode { std::nullopt };
 69 std::optional<MemoryMode> m_mode { std::nullopt };
7070 bool m_hasTable { false };
7171};
7272

Source/JavaScriptCore/wasm/WasmPlan.cpp

@@Plan::Plan(VM* vm, const uint8_t* source, size_t sourceLength)
6363{
6464}
6565
66 bool Plan::parseAndValidateModule(std::optional<Memory::Mode> recompileMode)
 66bool Plan::parseAndValidateModule(std::optional<MemoryMode> recompileMode)
6767{
6868 MonotonicTime startTime;
6969 if (verbose || Options::reportCompileTimes())

@@bool Plan::parseAndValidateModule(std::optional<Memory::Mode> recompileMode)
111111// The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
112112// that could touch its stack are done executing.
113113SUPPRESS_ASAN
114 void Plan::run(std::optional<Memory::Mode> recompileMode)
 114void Plan::run(std::optional<MemoryMode> recompileMode)
115115{
116116 if (!parseAndValidateModule(recompileMode))
117117 return;

Source/JavaScriptCore/wasm/WasmPlan.h

@@public:
4949 JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
5050 JS_EXPORT_PRIVATE ~Plan();
5151
52  bool parseAndValidateModule(std::optional<Memory::Mode> = std::nullopt);
 52 bool parseAndValidateModule(std::optional<MemoryMode> = std::nullopt);
5353
54  JS_EXPORT_PRIVATE void run(std::optional<Memory::Mode> = std::nullopt);
 54 JS_EXPORT_PRIVATE void run(std::optional<MemoryMode> = std::nullopt);
5555
5656 JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>);
5757

@@public:
9292 return WTFMove(m_wasmExitStubs);
9393 }
9494
95  Memory::Mode mode() const { return m_moduleInformation->memory.mode(); }
 95 MemoryMode mode() const { return m_moduleInformation->memory.mode(); }
9696
9797private:
9898 std::unique_ptr<ModuleInformation> m_moduleInformation;

Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp

@@namespace JSC {
3636
3737const ClassInfo JSWebAssemblyCodeBlock::s_info = { "WebAssemblyCodeBlock", nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) };
3838
39 JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
 39JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
4040 : Base(vm, vm.webAssemblyCodeBlockStructure.get())
4141 , m_callLinkInfos(WTFMove(callLinkInfos))
4242 , m_wasmExitStubs(WTFMove(wasmExitStubs))

@@void JSWebAssemblyCodeBlock::destroy(JSCell* cell)
5454
5555bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory)
5656{
57  if (mode() == Wasm::Memory::Signaling)
58  return memory->memory().mode() == mode();
59  return true;
 57 Wasm::MemoryMode codeMode = mode();
 58 Wasm::MemoryMode memoryMode = memory->memory().mode();
 59 switch (codeMode) {
 60 case Wasm::MemoryMode::BoundsChecking:
 61 return true;
 62 case Wasm::MemoryMode::Signaling:
 63 // Code being in Signaling mode means that it performs no bounds checks.
 64 // Its memory, even if empty, absolutely must also be in Signaling mode
 65 // because the page protection detect out-of-bounds accesses.
 66 return memoryMode == Wasm::MemoryMode::Signaling;
 67 case Wasm::MemoryMode::NumberOfMemoryModes:
 68 break;
 69 }
 70 RELEASE_ASSERT_NOT_REACHED();
 71 return false;
6072}
6173
6274void JSWebAssemblyCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)

Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h

@@public:
7979 JSWebAssemblyMemory* memory() { return m_memory.get(); }
8080 // Calling this might trigger a recompile.
8181 void setMemory(VM&, ExecState*, JSWebAssemblyMemory*);
82  Wasm::Memory::Mode memoryMode() { return memory()->memory().mode(); }
 82 Wasm::MemoryMode memoryMode() { return memory()->memory().mode(); }
8383
8484 JSWebAssemblyTable* table() { return m_table.get(); }
8585 void setTable(VM& vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }

Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@namespace JSC {
4242
4343const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
4444
45 JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan& plan, std::optional<Wasm::Memory::Mode> mode)
 45JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan& plan, std::optional<Wasm::MemoryMode> mode)
4646{
4747 auto scope = DECLARE_THROW_SCOPE(vm);
4848 // On failure, a new WebAssembly.CompileError is thrown.

@@JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure)
8585
8686JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM& vm, ExecState* exec, JSWebAssemblyMemory* memory)
8787{
88  Wasm::Memory::Mode mode = memory->memory().mode();
 88 Wasm::MemoryMode mode = memory->memory().mode();
8989
90  for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i) {
 90 for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; ++i) {
9191 if (m_codeBlocks[i] && m_codeBlocks[i]->isSafeToRun(memory))
9292 return m_codeBlocks[i].get();
9393 }
9494
95  ASSERT(!m_codeBlocks[mode]);
 95 ASSERT(!codeBlockFor(mode));
9696 auto scope = DECLARE_THROW_SCOPE(vm);
9797 // We don't have a code block for this mode, we need to recompile...
9898 Wasm::Plan plan(&vm, static_cast<uint8_t*>(m_sourceBuffer->data()), m_sourceBuffer->byteLength());

@@JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM& vm, ExecState* exec,
107107 }
108108
109109 ASSERT(mode == codeBlock->mode());
110  m_codeBlocks[mode].set(vm, this, codeBlock);
 110 codeBlockFor(mode).set(vm, this, codeBlock);
111111 return codeBlock;
112112}
113113

@@void JSWebAssemblyModule::finishCreation(VM& vm, ExecState* exec, uint8_t* sourc
132132 m_sourceBuffer = ArrayBuffer::create(source, byteSize);
133133 m_moduleInformation = plan.takeModuleInformation();
134134 m_exportSymbolTable.set(vm, this, exportSymbolTable);
135  m_codeBlocks[codeBlock->mode()].set(vm, this, codeBlock);
 135 codeBlockFor(codeBlock->mode()).set(vm, this, codeBlock);
136136}
137137
138138void JSWebAssemblyModule::destroy(JSCell* cell)

@@void JSWebAssemblyModule::visitChildren(JSCell* cell, SlotVisitor& visitor)
147147
148148 Base::visitChildren(thisObject, visitor);
149149 visitor.append(thisObject->m_exportSymbolTable);
150  for (unsigned i = 0; i < Wasm::Memory::NumberOfModes; ++i)
 150 for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; ++i)
151151 visitor.append(thisObject->m_codeBlocks[i]);
152152}
153153

Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h

@@public:
6262 }
6363
6464 // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
65  JSWebAssemblyCodeBlock* codeBlock() { return m_codeBlocks[m_moduleInformation->memory.mode()].get(); }
 65 JSWebAssemblyCodeBlock* codeBlock() { return codeBlockFor(m_moduleInformation->memory.mode()).get(); }
6666 // Returns the appropriate code block for the given memory, possibly triggering a recompile.
6767 JSWebAssemblyCodeBlock* codeBlock(VM&, ExecState*, JSWebAssemblyMemory*);
6868
6969private:
70  JSWebAssemblyCodeBlock* buildCodeBlock(VM&, ExecState*, Wasm::Plan&, std::optional<Wasm::Memory::Mode> mode = std::nullopt);
 70 WriteBarrier<JSWebAssemblyCodeBlock>& codeBlockFor(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast<size_t>(mode)]; }
 71 JSWebAssemblyCodeBlock* buildCodeBlock(VM&, ExecState*, Wasm::Plan&, std::optional<Wasm::MemoryMode> mode = std::nullopt);
7172
7273 JSWebAssemblyModule(VM&, Structure*);
7374 void finishCreation(VM&, ExecState*, uint8_t* source, size_t byteSize);

@@private:
7778 RefPtr<ArrayBuffer> m_sourceBuffer;
7879 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
7980 WriteBarrier<SymbolTable> m_exportSymbolTable;
80  WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::Memory::NumberOfModes];
 81 WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes];
8182};
8283
8384} // namespace JSC

Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions