diff options
Diffstat (limited to 'js/src/wasm/WasmGenerator.h')
-rw-r--r-- | js/src/wasm/WasmGenerator.h | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/js/src/wasm/WasmGenerator.h b/js/src/wasm/WasmGenerator.h new file mode 100644 index 000000000..d1badf679 --- /dev/null +++ b/js/src/wasm/WasmGenerator.h @@ -0,0 +1,252 @@ +/* -*- 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_generator_h +#define wasm_generator_h + +#include "jit/MacroAssembler.h" +#include "wasm/WasmCompile.h" +#include "wasm/WasmModule.h" + +namespace js { +namespace wasm { + +class FunctionGenerator; + +// The ModuleGeneratorData holds all the state shared between the +// ModuleGenerator thread and background compile threads. The background +// threads are given a read-only view of the ModuleGeneratorData and the +// ModuleGenerator is careful to initialize, and never subsequently mutate, +// any given datum before being read by a background thread. In particular, +// once created, the Vectors are never resized. + +struct ModuleGeneratorData +{ + ModuleKind kind; + MemoryUsage memoryUsage; + mozilla::Atomic<uint32_t> minMemoryLength; + Maybe<uint32_t> maxMemoryLength; + + SigWithIdVector sigs; + SigWithIdPtrVector funcSigs; + Uint32Vector funcImportGlobalDataOffsets; + GlobalDescVector globals; + TableDescVector tables; + Uint32Vector asmJSSigToTableIndex; + + explicit ModuleGeneratorData(ModuleKind kind = ModuleKind::Wasm) + : kind(kind), + memoryUsage(MemoryUsage::None), + minMemoryLength(0) + {} + + bool isAsmJS() const { + return kind == ModuleKind::AsmJS; + } + bool funcIsImport(uint32_t funcIndex) const { + return funcIndex < funcImportGlobalDataOffsets.length(); + } +}; + +typedef UniquePtr<ModuleGeneratorData> UniqueModuleGeneratorData; + +// A ModuleGenerator encapsulates the creation of a wasm module. During the +// lifetime of a ModuleGenerator, a sequence of FunctionGenerators are created +// and destroyed to compile the individual function bodies. After generating all +// functions, ModuleGenerator::finish() must be called to complete the +// compilation and extract the resulting wasm module. + +class MOZ_STACK_CLASS ModuleGenerator +{ + typedef HashSet<uint32_t, DefaultHasher<uint32_t>, SystemAllocPolicy> Uint32Set; + typedef Vector<IonCompileTask, 0, SystemAllocPolicy> IonCompileTaskVector; + typedef Vector<IonCompileTask*, 0, SystemAllocPolicy> IonCompileTaskPtrVector; + typedef EnumeratedArray<Trap, Trap::Limit, ProfilingOffsets> TrapExitOffsetArray; + + // Constant parameters + bool alwaysBaseline_; + + // Data that is moved into the result of finish() + Assumptions assumptions_; + LinkData linkData_; + MutableMetadata metadata_; + ExportVector exports_; + ImportVector imports_; + DataSegmentVector dataSegments_; + ElemSegmentVector elemSegments_; + + // Data scoped to the ModuleGenerator's lifetime + UniqueModuleGeneratorData shared_; + uint32_t numSigs_; + uint32_t numTables_; + LifoAlloc lifo_; + jit::JitContext jcx_; + jit::TempAllocator masmAlloc_; + jit::MacroAssembler masm_; + Uint32Vector funcToCodeRange_; + Uint32Set exportedFuncs_; + uint32_t lastPatchedCallsite_; + uint32_t startOfUnpatchedCallsites_; + + // Parallel compilation + bool parallel_; + uint32_t outstanding_; + IonCompileTaskVector tasks_; + IonCompileTaskPtrVector freeTasks_; + + // Assertions + DebugOnly<FunctionGenerator*> activeFuncDef_; + DebugOnly<bool> startedFuncDefs_; + DebugOnly<bool> finishedFuncDefs_; + DebugOnly<uint32_t> numFinishedFuncDefs_; + + bool funcIsCompiled(uint32_t funcIndex) const; + const CodeRange& funcCodeRange(uint32_t funcIndex) const; + MOZ_MUST_USE bool patchCallSites(TrapExitOffsetArray* maybeTrapExits = nullptr); + MOZ_MUST_USE bool patchFarJumps(const TrapExitOffsetArray& trapExits); + MOZ_MUST_USE bool finishTask(IonCompileTask* task); + MOZ_MUST_USE bool finishOutstandingTask(); + MOZ_MUST_USE bool finishFuncExports(); + MOZ_MUST_USE bool finishCodegen(); + MOZ_MUST_USE bool finishLinkData(Bytes& code); + MOZ_MUST_USE bool addFuncImport(const Sig& sig, uint32_t globalDataOffset); + MOZ_MUST_USE bool allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOff); + MOZ_MUST_USE bool allocateGlobal(GlobalDesc* global); + + public: + explicit ModuleGenerator(ImportVector&& imports); + ~ModuleGenerator(); + + MOZ_MUST_USE bool init(UniqueModuleGeneratorData shared, const CompileArgs& args, + Metadata* maybeAsmJSMetadata = nullptr); + + bool isAsmJS() const { return metadata_->kind == ModuleKind::AsmJS; } + jit::MacroAssembler& masm() { return masm_; } + + // Memory: + bool usesMemory() const { return UsesMemory(shared_->memoryUsage); } + uint32_t minMemoryLength() const { return shared_->minMemoryLength; } + + // Tables: + uint32_t numTables() const { return numTables_; } + const TableDescVector& tables() const { return shared_->tables; } + + // Signatures: + uint32_t numSigs() const { return numSigs_; } + const SigWithId& sig(uint32_t sigIndex) const; + const SigWithId& funcSig(uint32_t funcIndex) const; + + // Globals: + const GlobalDescVector& globals() const { return shared_->globals; } + + // Functions declarations: + uint32_t numFuncImports() const; + uint32_t numFuncDefs() const; + uint32_t numFuncs() const; + + // Exports: + MOZ_MUST_USE bool addFuncExport(UniqueChars fieldName, uint32_t funcIndex); + MOZ_MUST_USE bool addTableExport(UniqueChars fieldName); + MOZ_MUST_USE bool addMemoryExport(UniqueChars fieldName); + MOZ_MUST_USE bool addGlobalExport(UniqueChars fieldName, uint32_t globalIndex); + + // Function definitions: + MOZ_MUST_USE bool startFuncDefs(); + MOZ_MUST_USE bool startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg); + MOZ_MUST_USE bool finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg); + MOZ_MUST_USE bool finishFuncDefs(); + + // Start function: + bool setStartFunction(uint32_t funcIndex); + + // Segments: + void setDataSegments(DataSegmentVector&& segments); + MOZ_MUST_USE bool addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices); + + // Function names: + void setFuncNames(NameInBytecodeVector&& funcNames); + + // asm.js lazy initialization: + void initSig(uint32_t sigIndex, Sig&& sig); + void initFuncSig(uint32_t funcIndex, uint32_t sigIndex); + MOZ_MUST_USE bool initImport(uint32_t funcIndex, uint32_t sigIndex); + MOZ_MUST_USE bool initSigTableLength(uint32_t sigIndex, uint32_t length); + MOZ_MUST_USE bool initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices); + void initMemoryUsage(MemoryUsage memoryUsage); + void bumpMinMemoryLength(uint32_t newMinMemoryLength); + MOZ_MUST_USE bool addGlobal(ValType type, bool isConst, uint32_t* index); + + // Finish compilation, provided the list of imports and source bytecode. + // Both these Vectors may be empty (viz., b/c asm.js does different things + // for imports and source). + SharedModule finish(const ShareableBytes& bytecode); +}; + +// A FunctionGenerator encapsulates the generation of a single function body. +// ModuleGenerator::startFunc must be called after construction and before doing +// anything else. After the body is complete, ModuleGenerator::finishFunc must +// be called before the FunctionGenerator is destroyed and the next function is +// started. + +class MOZ_STACK_CLASS FunctionGenerator +{ + friend class ModuleGenerator; + + ModuleGenerator* m_; + IonCompileTask* task_; + bool usesSimd_; + bool usesAtomics_; + + // Data created during function generation, then handed over to the + // FuncBytes in ModuleGenerator::finishFunc(). + Bytes bytes_; + Uint32Vector callSiteLineNums_; + + uint32_t lineOrBytecode_; + + public: + FunctionGenerator() + : m_(nullptr), task_(nullptr), usesSimd_(false), usesAtomics_(false), lineOrBytecode_(0) + {} + + bool usesSimd() const { + return usesSimd_; + } + void setUsesSimd() { + usesSimd_ = true; + } + + bool usesAtomics() const { + return usesAtomics_; + } + void setUsesAtomics() { + usesAtomics_ = true; + } + + Bytes& bytes() { + return bytes_; + } + MOZ_MUST_USE bool addCallSiteLineNum(uint32_t lineno) { + return callSiteLineNums_.append(lineno); + } +}; + +} // namespace wasm +} // namespace js + +#endif // wasm_generator_h |