summaryrefslogtreecommitdiffstats
path: root/js/src/wasm/WasmModule.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/wasm/WasmModule.h')
-rw-r--r--js/src/wasm/WasmModule.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/js/src/wasm/WasmModule.h b/js/src/wasm/WasmModule.h
new file mode 100644
index 000000000..40c920708
--- /dev/null
+++ b/js/src/wasm/WasmModule.h
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ *
+ * 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/TypeDecls.h"
+
+#include "wasm/WasmCode.h"
+#include "wasm/WasmTable.h"
+
+namespace js {
+namespace wasm {
+
+// LinkData contains all the metadata necessary to patch all the locations
+// that depend on the absolute address of a CodeSegment.
+//
+// LinkData is built incrementing by ModuleGenerator and then stored immutably
+// in Module.
+
+struct LinkDataCacheablePod
+{
+ uint32_t functionCodeLength;
+ uint32_t globalDataLength;
+ uint32_t interruptOffset;
+ uint32_t outOfBoundsOffset;
+ uint32_t unalignedAccessOffset;
+
+ LinkDataCacheablePod() { mozilla::PodZero(this); }
+};
+
+struct LinkData : LinkDataCacheablePod
+{
+ LinkDataCacheablePod& pod() { return *this; }
+ const LinkDataCacheablePod& pod() const { return *this; }
+
+ struct InternalLink {
+ enum Kind {
+ RawPointer,
+ CodeLabel,
+ InstructionImmediate
+ };
+ MOZ_INIT_OUTSIDE_CTOR uint32_t patchAtOffset;
+ MOZ_INIT_OUTSIDE_CTOR uint32_t targetOffset;
+
+ InternalLink() = default;
+ explicit InternalLink(Kind kind);
+ bool isRawPointerPatch();
+ };
+ typedef Vector<InternalLink, 0, SystemAllocPolicy> InternalLinkVector;
+
+ struct SymbolicLinkArray : EnumeratedArray<SymbolicAddress, SymbolicAddress::Limit, Uint32Vector> {
+ WASM_DECLARE_SERIALIZABLE(SymbolicLinkArray)
+ };
+
+ InternalLinkVector internalLinks;
+ SymbolicLinkArray symbolicLinks;
+
+ WASM_DECLARE_SERIALIZABLE(LinkData)
+};
+
+typedef UniquePtr<LinkData> UniqueLinkData;
+typedef UniquePtr<const LinkData> UniqueConstLinkData;
+
+// Export describes the export of a definition in a Module to a field in the
+// export object. For functions, Export stores an index into the
+// FuncExportVector in Metadata. For memory and table exports, there is
+// at most one (default) memory/table so no index is needed. Note: a single
+// definition can be exported by multiple Exports in the ExportVector.
+//
+// ExportVector is built incrementally by ModuleGenerator and then stored
+// immutably by Module.
+
+class Export
+{
+ CacheableChars fieldName_;
+ struct CacheablePod {
+ DefinitionKind kind_;
+ uint32_t index_;
+ } pod;
+
+ public:
+ Export() = default;
+ explicit Export(UniqueChars fieldName, uint32_t index, DefinitionKind kind);
+ explicit Export(UniqueChars fieldName, DefinitionKind kind);
+
+ const char* fieldName() const { return fieldName_.get(); }
+
+ DefinitionKind kind() const { return pod.kind_; }
+ uint32_t funcIndex() const;
+ uint32_t globalIndex() const;
+
+ WASM_DECLARE_SERIALIZABLE(Export)
+};
+
+typedef Vector<Export, 0, SystemAllocPolicy> ExportVector;
+
+// ElemSegment represents an element segment in the module where each element
+// describes both its function index and its code range.
+
+struct ElemSegment
+{
+ uint32_t tableIndex;
+ InitExpr offset;
+ Uint32Vector elemFuncIndices;
+ Uint32Vector elemCodeRangeIndices;
+
+ ElemSegment() = default;
+ ElemSegment(uint32_t tableIndex, InitExpr offset, Uint32Vector&& elemFuncIndices)
+ : tableIndex(tableIndex), offset(offset), elemFuncIndices(Move(elemFuncIndices))
+ {}
+
+ WASM_DECLARE_SERIALIZABLE(ElemSegment)
+};
+
+typedef Vector<ElemSegment, 0, SystemAllocPolicy> ElemSegmentVector;
+
+// Module represents a compiled wasm module and primarily provides two
+// operations: instantiation and serialization. A Module can be instantiated any
+// number of times to produce new Instance objects. A Module can be serialized
+// any number of times such that the serialized bytes can be deserialized later
+// to produce a new, equivalent Module.
+//
+// Since fully linked-and-instantiated code (represented by CodeSegment) cannot
+// be shared between instances, Module stores an unlinked, uninstantiated copy
+// of the code (represented by the Bytes) and creates a new CodeSegment each
+// time it is instantiated. In the future, Module will store a shareable,
+// immutable CodeSegment that can be shared by all its instances.
+
+class Module : public JS::WasmModule
+{
+ const Assumptions assumptions_;
+ const Bytes code_;
+ const LinkData linkData_;
+ const ImportVector imports_;
+ const ExportVector exports_;
+ const DataSegmentVector dataSegments_;
+ const ElemSegmentVector elemSegments_;
+ const SharedMetadata metadata_;
+ const SharedBytes bytecode_;
+
+ bool instantiateFunctions(JSContext* cx, Handle<FunctionVector> funcImports) const;
+ bool instantiateMemory(JSContext* cx, MutableHandleWasmMemoryObject memory) const;
+ bool instantiateTable(JSContext* cx,
+ MutableHandleWasmTableObject table,
+ SharedTableVector* tables) const;
+ bool initSegments(JSContext* cx,
+ HandleWasmInstanceObject instance,
+ Handle<FunctionVector> funcImports,
+ HandleWasmMemoryObject memory,
+ const ValVector& globalImports) const;
+
+ public:
+ Module(Assumptions&& assumptions,
+ Bytes&& code,
+ LinkData&& linkData,
+ ImportVector&& imports,
+ ExportVector&& exports,
+ DataSegmentVector&& dataSegments,
+ ElemSegmentVector&& elemSegments,
+ const Metadata& metadata,
+ const ShareableBytes& bytecode)
+ : assumptions_(Move(assumptions)),
+ code_(Move(code)),
+ linkData_(Move(linkData)),
+ imports_(Move(imports)),
+ exports_(Move(exports)),
+ dataSegments_(Move(dataSegments)),
+ elemSegments_(Move(elemSegments)),
+ metadata_(&metadata),
+ bytecode_(&bytecode)
+ {}
+ ~Module() override { /* Note: can be called on any thread */ }
+
+ const Metadata& metadata() const { return *metadata_; }
+ const ImportVector& imports() const { return imports_; }
+ const ExportVector& exports() const { return exports_; }
+
+ // Instantiate this module with the given imports:
+
+ bool instantiate(JSContext* cx,
+ Handle<FunctionVector> funcImports,
+ HandleWasmTableObject tableImport,
+ HandleWasmMemoryObject memoryImport,
+ const ValVector& globalImports,
+ HandleObject instanceProto,
+ MutableHandleWasmInstanceObject instanceObj) const;
+
+ // Structured clone support:
+
+ void serializedSize(size_t* maybeBytecodeSize, size_t* maybeCompiledSize) const override;
+ void serialize(uint8_t* maybeBytecodeBegin, size_t maybeBytecodeSize,
+ uint8_t* maybeCompiledBegin, size_t maybeCompiledSize) const override;
+ static bool assumptionsMatch(const Assumptions& current, const uint8_t* compiledBegin,
+ size_t compiledSize);
+ static RefPtr<Module> deserialize(const uint8_t* bytecodeBegin, size_t bytecodeSize,
+ const uint8_t* compiledBegin, size_t compiledSize,
+ Metadata* maybeMetadata = nullptr);
+ JSObject* createObject(JSContext* cx) override;
+
+ // about:memory reporting:
+
+ void addSizeOfMisc(MallocSizeOf mallocSizeOf,
+ Metadata::SeenSet* seenMetadata,
+ ShareableBytes::SeenSet* seenBytes,
+ size_t* code, size_t* data) const;
+
+ // Generated code analysis support:
+
+ bool extractCode(JSContext* cx, MutableHandleValue vp);
+};
+
+typedef RefPtr<Module> SharedModule;
+
+// JS API implementations:
+
+bool
+CompiledModuleAssumptionsMatch(PRFileDesc* compiled, JS::BuildIdCharVector&& buildId);
+
+SharedModule
+DeserializeModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled, JS::BuildIdCharVector&& buildId,
+ UniqueChars filename, unsigned line, unsigned column);
+
+} // namespace wasm
+} // namespace js
+
+#endif // wasm_module_h