summaryrefslogtreecommitdiffstats
path: root/js/src/wasm/WasmModule.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/wasm/WasmModule.h
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/wasm/WasmModule.h')
-rw-r--r--js/src/wasm/WasmModule.h257
1 files changed, 257 insertions, 0 deletions
diff --git a/js/src/wasm/WasmModule.h b/js/src/wasm/WasmModule.h
new file mode 100644
index 0000000000..f670029f13
--- /dev/null
+++ b/js/src/wasm/WasmModule.h
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ *
+ * Copyright 2015 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_module_h
+#define wasm_module_h
+
+#include "js/WasmModule.h"
+#include "js/BuildId.h"
+
+#include "wasm/WasmCode.h"
+#include "wasm/WasmJS.h"
+#include "wasm/WasmTable.h"
+
+struct JSTelemetrySender;
+
+namespace js {
+namespace wasm {
+
+struct CompileArgs;
+
+// In the context of wasm, the OptimizedEncodingListener specifically is
+// listening for the completion of tier-2.
+
+using Tier2Listener = RefPtr<JS::OptimizedEncodingListener>;
+
+// A struct containing the typed, imported values that are harvested from the
+// import object and passed to Module::instantiate(). This struct must be
+// stored in a (Persistent)Rooted, not in the heap due to its use of TraceRoot()
+// and complete lack of barriers.
+
+struct ImportValues {
+ JSFunctionVector funcs;
+ WasmTableObjectVector tables;
+ WasmMemoryObject* memory;
+ WasmExceptionObjectVector exceptionObjs;
+ WasmGlobalObjectVector globalObjs;
+ ValVector globalValues;
+
+ ImportValues() : memory(nullptr) {}
+
+ void trace(JSTracer* trc) {
+ funcs.trace(trc);
+ tables.trace(trc);
+ if (memory) {
+ TraceRoot(trc, &memory, "import values memory");
+ }
+ exceptionObjs.trace(trc);
+ globalObjs.trace(trc);
+ globalValues.trace(trc);
+ }
+};
+
+// Module represents a compiled wasm module and primarily provides three
+// operations: instantiation, tiered compilation, serialization. A Module can be
+// instantiated any number of times to produce new Instance objects. A Module
+// can have a single tier-2 task initiated to augment a Module's code with a
+// higher tier. A Module can have its optimized code serialized at any point
+// where the LinkData is also available, which is primarily (1) at the end of
+// module generation, (2) at the end of tier-2 compilation.
+//
+// Fully linked-and-instantiated code (represented by Code and its owned
+// ModuleSegment) can be shared between instances, provided none of those
+// instances are being debugged. If patchable code is needed then each instance
+// must have its own Code. Module eagerly creates a new Code and gives it to the
+// first instance; it then instantiates new Code objects from a copy of the
+// unlinked code that it keeps around for that purpose.
+
+class Module : public JS::WasmModule {
+ const SharedCode code_;
+ const ImportVector imports_;
+ const ExportVector exports_;
+ const DataSegmentVector dataSegments_;
+ const ElemSegmentVector elemSegments_;
+ const CustomSectionVector customSections_;
+
+ // These fields are only meaningful when code_->metadata().debugEnabled.
+ // `debugCodeClaimed_` is set to false initially and then to true when
+ // `code_` is already being used for an instance and can't be shared because
+ // it may be patched by the debugger. Subsequent instances must then create
+ // copies by linking the `debugUnlinkedCode_` using `debugLinkData_`.
+ // This could all be removed if debugging didn't need to perform
+ // per-instance code patching.
+
+ mutable Atomic<bool> debugCodeClaimed_;
+ const UniqueConstBytes debugUnlinkedCode_;
+ const UniqueLinkData debugLinkData_;
+ const SharedBytes debugBytecode_;
+
+ // This field is set during tier-2 compilation and cleared on success or
+ // failure. These happen on different threads and are serialized by the
+ // control flow of helper tasks.
+
+ mutable Tier2Listener tier2Listener_;
+
+ // This flag is used for logging (and testing) purposes to indicate
+ // whether the module was deserialized (from a cache).
+
+ const bool loggingDeserialized_;
+
+ // This flag is only used for testing purposes and is cleared on success or
+ // failure. The field is racily polled from various threads.
+
+ mutable Atomic<bool> testingTier2Active_;
+
+ // Cached malloc allocation size for GC memory tracking.
+
+ size_t gcMallocBytesExcludingCode_;
+
+ bool instantiateFunctions(JSContext* cx,
+ const JSFunctionVector& funcImports) const;
+ bool instantiateMemory(JSContext* cx,
+ MutableHandleWasmMemoryObject memory) const;
+#ifdef ENABLE_WASM_EXCEPTIONS
+ bool instantiateImportedException(JSContext* cx,
+ Handle<WasmExceptionObject*> exnObj,
+ WasmExceptionObjectVector& exnObjs,
+ SharedExceptionTagVector* tags) const;
+ bool instantiateLocalException(JSContext* cx, const EventDesc& ed,
+ WasmExceptionObjectVector& exnObjs,
+ SharedExceptionTagVector* tags,
+ uint32_t exnIndex) const;
+ bool instantiateExceptions(JSContext* cx, WasmExceptionObjectVector& exnObjs,
+ SharedExceptionTagVector* tags) const;
+#endif
+ bool instantiateImportedTable(JSContext* cx, const TableDesc& td,
+ Handle<WasmTableObject*> table,
+ WasmTableObjectVector* tableObjs,
+ SharedTableVector* tables) const;
+ bool instantiateLocalTable(JSContext* cx, const TableDesc& td,
+ WasmTableObjectVector* tableObjs,
+ SharedTableVector* tables) const;
+ bool instantiateTables(JSContext* cx,
+ const WasmTableObjectVector& tableImports,
+ MutableHandle<WasmTableObjectVector> tableObjs,
+ SharedTableVector* tables) const;
+ bool instantiateGlobals(JSContext* cx, const ValVector& globalImportValues,
+ WasmGlobalObjectVector& globalObjs) const;
+ bool initSegments(JSContext* cx, HandleWasmInstanceObject instance,
+ HandleWasmMemoryObject memory,
+ const ValVector& globalImportValues) const;
+ SharedCode getDebugEnabledCode() const;
+
+ class Tier2GeneratorTaskImpl;
+
+ public:
+ Module(const Code& code, ImportVector&& imports, ExportVector&& exports,
+ DataSegmentVector&& dataSegments, ElemSegmentVector&& elemSegments,
+ CustomSectionVector&& customSections,
+ UniqueConstBytes debugUnlinkedCode = nullptr,
+ UniqueLinkData debugLinkData = nullptr,
+ const ShareableBytes* debugBytecode = nullptr,
+ bool loggingDeserialized = false)
+ : code_(&code),
+ imports_(std::move(imports)),
+ exports_(std::move(exports)),
+ dataSegments_(std::move(dataSegments)),
+ elemSegments_(std::move(elemSegments)),
+ customSections_(std::move(customSections)),
+ debugCodeClaimed_(false),
+ debugUnlinkedCode_(std::move(debugUnlinkedCode)),
+ debugLinkData_(std::move(debugLinkData)),
+ debugBytecode_(debugBytecode),
+ loggingDeserialized_(loggingDeserialized),
+ testingTier2Active_(false) {
+ MOZ_ASSERT_IF(metadata().debugEnabled,
+ debugUnlinkedCode_ && debugLinkData_);
+ initGCMallocBytesExcludingCode();
+ }
+ ~Module() override;
+
+ const Code& code() const { return *code_; }
+ const ModuleSegment& moduleSegment(Tier t) const { return code_->segment(t); }
+ const Metadata& metadata() const { return code_->metadata(); }
+ const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
+ const ImportVector& imports() const { return imports_; }
+ const ExportVector& exports() const { return exports_; }
+ const CustomSectionVector& customSections() const { return customSections_; }
+ const Bytes& debugBytecode() const { return debugBytecode_->bytes; }
+ uint32_t codeLength(Tier t) const { return code_->segment(t).length(); }
+
+ // Instantiate this module with the given imports:
+
+ bool instantiate(JSContext* cx, ImportValues& imports,
+ HandleObject instanceProto,
+ MutableHandleWasmInstanceObject instanceObj) const;
+
+ // Tier-2 compilation may be initiated after the Module is constructed at
+ // most once. When tier-2 compilation completes, ModuleGenerator calls
+ // finishTier2() from a helper thread, passing tier-variant data which will
+ // be installed and made visible.
+
+ void startTier2(const CompileArgs& args, const ShareableBytes& bytecode,
+ JS::OptimizedEncodingListener* listener,
+ JSTelemetrySender telemetrySender);
+ bool finishTier2(const LinkData& linkData2, UniqueCodeTier code2) const;
+
+ void testingBlockOnTier2Complete() const;
+ bool testingTier2Active() const { return testingTier2Active_; }
+
+ // Code caching support.
+
+ size_t serializedSize(const LinkData& linkData) const;
+ void serialize(const LinkData& linkData, uint8_t* begin, size_t size) const;
+ void serialize(const LinkData& linkData,
+ JS::OptimizedEncodingListener& listener) const;
+ static RefPtr<Module> deserialize(const uint8_t* begin, size_t size,
+ Metadata* maybeMetadata = nullptr);
+ bool loggingDeserialized() const { return loggingDeserialized_; }
+
+ // JS API and JS::WasmModule implementation:
+
+ JSObject* createObject(JSContext* cx) const override;
+ JSObject* createObjectForAsmJS(JSContext* cx) const override;
+
+ // about:memory reporting:
+
+ void addSizeOfMisc(MallocSizeOf mallocSizeOf, Metadata::SeenSet* seenMetadata,
+ Code::SeenSet* seenCode, size_t* code, size_t* data) const;
+
+ // GC malloc memory tracking:
+
+ void initGCMallocBytesExcludingCode();
+ size_t gcMallocBytesExcludingCode() const {
+ return gcMallocBytesExcludingCode_;
+ }
+
+ // Generated code analysis support:
+
+ bool extractCode(JSContext* cx, Tier tier, MutableHandleValue vp) const;
+};
+
+using MutableModule = RefPtr<Module>;
+using SharedModule = RefPtr<const Module>;
+
+// JS API implementations:
+
+[[nodiscard]] bool GetOptimizedEncodingBuildId(JS::BuildIdCharVector* buildId);
+
+} // namespace wasm
+} // namespace js
+
+#endif // wasm_module_h