#ifndef wasm_generator_h
#define wasm_generator_h
#include "mozilla/MemoryReporting.h"
#include "jit/MacroAssembler.h"
#include "wasm/WasmCompile.h"
#include "wasm/WasmModule.h"
#include "wasm/WasmValidate.h"
namespace js {
namespace wasm {
struct CompileTask;
typedef Vector<CompileTask*, 0, SystemAllocPolicy> CompileTaskPtrVector;
struct FuncCompileInput {
const uint8_t* begin;
const uint8_t* end;
uint32_t index;
uint32_t lineOrBytecode;
Uint32Vector callSiteLineNums;
FuncCompileInput(uint32_t index, uint32_t lineOrBytecode,
const uint8_t* begin, const uint8_t* end,
Uint32Vector&& callSiteLineNums)
: begin(begin),
end(end),
index(index),
lineOrBytecode(lineOrBytecode),
callSiteLineNums(std::move(callSiteLineNums)) {}
};
typedef Vector<FuncCompileInput, 8, SystemAllocPolicy> FuncCompileInputVector;
struct CompiledCode {
Bytes bytes;
CodeRangeVector codeRanges;
CallSiteVector callSites;
CallSiteTargetVector callSiteTargets;
TrapSiteVectorArray trapSites;
CallFarJumpVector callFarJumps;
SymbolicAccessVector symbolicAccesses;
jit::CodeLabelVector codeLabels;
StackMaps stackMaps;
MOZ_MUST_USE bool swap(jit::MacroAssembler& masm);
void clear() {
bytes.clear();
codeRanges.clear();
callSites.clear();
callSiteTargets.clear();
trapSites.clear();
callFarJumps.clear();
symbolicAccesses.clear();
codeLabels.clear();
stackMaps.clear();
MOZ_ASSERT(empty());
}
bool empty() {
return bytes.empty() && codeRanges.empty() && callSites.empty() &&
callSiteTargets.empty() && trapSites.empty() &&
callFarJumps.empty() && symbolicAccesses.empty() &&
codeLabels.empty() && stackMaps.empty();
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
};
struct CompileTaskState {
CompileTaskPtrVector finished;
uint32_t numFailed;
UniqueChars errorMessage;
CompileTaskState() : numFailed(0) {}
~CompileTaskState() {
MOZ_ASSERT(finished.empty());
MOZ_ASSERT(!numFailed);
}
};
typedef ExclusiveWaitableData<CompileTaskState> ExclusiveCompileTaskState;
struct CompileTask {
const ModuleEnvironment& env;
ExclusiveCompileTaskState& state;
LifoAlloc lifo;
FuncCompileInputVector inputs;
CompiledCode output;
CompileTask(const ModuleEnvironment& env, ExclusiveCompileTaskState& state,
size_t defaultChunkSize)
: env(env), state(state), lifo(defaultChunkSize) {}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
};
class MOZ_STACK_CLASS ModuleGenerator {
typedef Vector<CompileTask, 0, SystemAllocPolicy> CompileTaskVector;
typedef Vector<jit::CodeOffset, 0, SystemAllocPolicy> CodeOffsetVector;
SharedCompileArgs const compileArgs_;
UniqueChars* const error_;
const Atomic<bool>* const cancelled_;
ModuleEnvironment* const env_;
UniqueLinkData linkData_;
UniqueMetadataTier metadataTier_;
MutableMetadata metadata_;
ExclusiveCompileTaskState taskState_;
LifoAlloc lifo_;
jit::JitContext jcx_;
jit::TempAllocator masmAlloc_;
jit::WasmMacroAssembler masm_;
Uint32Vector funcToCodeRange_;
uint32_t debugTrapCodeOffset_;
CallFarJumpVector callFarJumps_;
CallSiteTargetVector callSiteTargets_;
uint32_t lastPatchedCallSite_;
uint32_t startOfUnpatchedCallsites_;
CodeOffsetVector debugTrapFarJumps_;
bool parallel_;
uint32_t outstanding_;
CompileTaskVector tasks_;
CompileTaskPtrVector freeTasks_;
CompileTask* currentTask_;
uint32_t batchedBytecode_;
DebugOnly<bool> finishedFuncDefs_;
bool allocateGlobalBytes(uint32_t bytes, uint32_t align,
uint32_t* globalDataOff);
bool funcIsCompiled(uint32_t funcIndex) const;
const CodeRange& funcCodeRange(uint32_t funcIndex) const;
bool linkCallSites();
void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange);
bool linkCompiledCode(CompiledCode& code);
bool locallyCompileCurrentTask();
bool finishTask(CompileTask* task);
bool launchBatchCompile();
bool finishOutstandingTask();
bool finishCodegen();
bool finishMetadataTier();
UniqueCodeTier finishCodeTier();
SharedMetadata finishMetadata(const Bytes& bytecode);
bool isAsmJS() const { return env_->isAsmJS(); }
Tier tier() const { return env_->tier(); }
CompileMode mode() const { return env_->mode(); }
bool debugEnabled() const { return env_->debugEnabled(); }
public:
ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env,
const Atomic<bool>* cancelled, UniqueChars* error);
~ModuleGenerator();
MOZ_MUST_USE bool init(Metadata* maybeAsmJSMetadata = nullptr);
MOZ_MUST_USE bool compileFuncDef(
uint32_t funcIndex, uint32_t lineOrBytecode, const uint8_t* begin,
const uint8_t* end, Uint32Vector&& callSiteLineNums = Uint32Vector());
MOZ_MUST_USE bool finishFuncDefs();
SharedModule finishModule(
const ShareableBytes& bytecode,
JS::OptimizedEncodingListener* maybeTier2Listener = nullptr);
MOZ_MUST_USE bool finishTier2(const Module& module);
};
} }
#endif