242 lines
8.4 KiB
C++
242 lines
8.4 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* 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
|