зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1253137 - Baldr: pass around Bytes instead of Bytecode/UniqueBytecode (r=sunfish)
MozReview-Commit-ID: 5RzN8IwDc7C
This commit is contained in:
Родитель
a1da5ec894
Коммит
c4ff9aece7
|
@ -2650,7 +2650,7 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
if (!m_.mg().startFuncDef(line, &fg_))
|
||||
return false;
|
||||
|
||||
encoder_.emplace(fg_.bytecode());
|
||||
encoder_.emplace(fg_.bytes());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1265,10 +1265,10 @@ DecodeFunctionBody(JSContext* cx, Decoder& d, ModuleGenerator& mg, uint32_t func
|
|||
if (d.currentPosition() != bodyEnd)
|
||||
return Fail(cx, d, "function body length mismatch");
|
||||
|
||||
if (!fg.bytecode().resize(bodySize))
|
||||
if (!fg.bytes().resize(bodySize))
|
||||
return false;
|
||||
|
||||
memcpy(fg.bytecode().begin(), bodyBegin, bodySize);
|
||||
memcpy(fg.bytes().begin(), bodyBegin, bodySize);
|
||||
|
||||
int64_t after = PRMJ_Now();
|
||||
unsigned generateTime = (after - before) / PRMJ_USEC_PER_MSEC;
|
||||
|
|
|
@ -19,15 +19,11 @@
|
|||
#ifndef wasm_binary_h
|
||||
#define wasm_binary_h
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "builtin/SIMD.h"
|
||||
|
||||
namespace js {
|
||||
namespace wasm {
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
static const uint32_t MagicNumber = 0x6d736100; // "\0asm"
|
||||
static const uint32_t EncodingVersion = 0xa;
|
||||
|
||||
|
@ -328,20 +324,19 @@ enum class ExprType
|
|||
|
||||
typedef int32_t I32x4[4];
|
||||
typedef float F32x4[4];
|
||||
typedef Vector<uint8_t, 0, SystemAllocPolicy> Bytecode;
|
||||
typedef UniquePtr<Bytecode> UniqueBytecode;
|
||||
typedef Vector<uint8_t, 0, SystemAllocPolicy> Bytes;
|
||||
|
||||
// The Encoder class appends bytes to the Bytecode object it is given during
|
||||
// construction. The client is responsible for the Bytecode's lifetime and must
|
||||
// keep the Bytecode alive as long as the Encoder is used.
|
||||
// The Encoder class appends bytes to the Bytes object it is given during
|
||||
// construction. The client is responsible for the Bytes's lifetime and must
|
||||
// keep the Bytes alive as long as the Encoder is used.
|
||||
|
||||
class Encoder
|
||||
{
|
||||
Bytecode& bytecode_;
|
||||
Bytes& bytes_;
|
||||
|
||||
template <class T>
|
||||
MOZ_WARN_UNUSED_RESULT bool write(const T& v) {
|
||||
return bytecode_.append(reinterpret_cast<const uint8_t*>(&v), sizeof(T));
|
||||
return bytes_.append(reinterpret_cast<const uint8_t*>(&v), sizeof(T));
|
||||
}
|
||||
|
||||
template <typename UInt>
|
||||
|
@ -351,7 +346,7 @@ class Encoder
|
|||
i >>= 7;
|
||||
if (i != 0)
|
||||
byte |= 0x80;
|
||||
if (!bytecode_.append(byte))
|
||||
if (!bytes_.append(byte))
|
||||
return false;
|
||||
} while(i != 0);
|
||||
return true;
|
||||
|
@ -374,15 +369,15 @@ class Encoder
|
|||
assertByte |= 0x80;
|
||||
patchByte |= 0x80;
|
||||
}
|
||||
MOZ_ASSERT(assertByte == bytecode_[offset]);
|
||||
bytecode_[offset] = patchByte;
|
||||
MOZ_ASSERT(assertByte == bytes_[offset]);
|
||||
bytes_[offset] = patchByte;
|
||||
offset++;
|
||||
} while(assertBits != 0);
|
||||
}
|
||||
|
||||
uint32_t varU32ByteLength(size_t offset) const {
|
||||
size_t start = offset;
|
||||
while (bytecode_[offset] & 0x80)
|
||||
while (bytes_[offset] & 0x80)
|
||||
offset++;
|
||||
return offset - start + 1;
|
||||
}
|
||||
|
@ -391,7 +386,7 @@ class Encoder
|
|||
template <class T>
|
||||
MOZ_WARN_UNUSED_RESULT bool writePatchableEnum(size_t* offset) {
|
||||
static_assert(uint32_t(T::Limit) <= EnumSentinel, "reserve enough bits");
|
||||
*offset = bytecode_.length();
|
||||
*offset = bytes_.length();
|
||||
return writeVarU32(EnumSentinel);
|
||||
}
|
||||
|
||||
|
@ -403,13 +398,13 @@ class Encoder
|
|||
}
|
||||
|
||||
public:
|
||||
explicit Encoder(Bytecode& bytecode)
|
||||
: bytecode_(bytecode)
|
||||
explicit Encoder(Bytes& bytes)
|
||||
: bytes_(bytes)
|
||||
{
|
||||
MOZ_ASSERT(empty());
|
||||
}
|
||||
|
||||
size_t currentOffset() const { return bytecode_.length(); }
|
||||
size_t currentOffset() const { return bytes_.length(); }
|
||||
bool empty() const { return currentOffset() == 0; }
|
||||
|
||||
// Fixed-size encoding operations simply copy the literal bytes (without
|
||||
|
@ -452,7 +447,7 @@ class Encoder
|
|||
// Variable-length encodings that allow back-patching.
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool writePatchableVarU32(size_t* offset) {
|
||||
*offset = bytecode_.length();
|
||||
*offset = bytes_.length();
|
||||
return writeVarU32(UINT32_MAX);
|
||||
}
|
||||
void patchVarU32(size_t offset, uint32_t patchBits) {
|
||||
|
@ -460,7 +455,7 @@ class Encoder
|
|||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool writePatchableVarU8(size_t* offset) {
|
||||
*offset = bytecode_.length();
|
||||
*offset = bytes_.length();
|
||||
return writeU8(UINT8_MAX);
|
||||
}
|
||||
void patchVarU8(size_t offset, uint8_t patchBits) {
|
||||
|
@ -479,10 +474,10 @@ class Encoder
|
|||
// contain nulls and instead has an explicit byte length.
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool writeCString(const char* cstr) {
|
||||
return bytecode_.append(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr) + 1);
|
||||
return bytes_.append(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr) + 1);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT bool writeRawData(const uint8_t* bytes, uint32_t numBytes) {
|
||||
return bytecode_.append(bytes, numBytes);
|
||||
return bytes_.append(bytes, numBytes);
|
||||
}
|
||||
|
||||
// A "section" is a contiguous range of bytes that stores its own size so
|
||||
|
@ -500,7 +495,7 @@ class Encoder
|
|||
writeRawData(reinterpret_cast<const uint8_t*>(id), IdSize);
|
||||
}
|
||||
void finishSection(size_t offset) {
|
||||
return patchVarU32(offset, bytecode_.length() - offset - varU32ByteLength(offset));
|
||||
return patchVarU32(offset, bytes_.length() - offset - varU32ByteLength(offset));
|
||||
}
|
||||
|
||||
// Temporary encoding forms which should be removed as part of the
|
||||
|
@ -510,12 +505,12 @@ class Encoder
|
|||
return write<uint8_t>(i);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT bool writePatchableU8(size_t* offset) {
|
||||
*offset = bytecode_.length();
|
||||
return bytecode_.append(0xff);
|
||||
*offset = bytes_.length();
|
||||
return bytes_.append(0xff);
|
||||
}
|
||||
void patchU8(size_t offset, uint8_t i) {
|
||||
MOZ_ASSERT(bytecode_[offset] == 0xff);
|
||||
bytecode_[offset] = i;
|
||||
MOZ_ASSERT(bytes_[offset] == 0xff);
|
||||
bytes_[offset] = i;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -599,10 +594,10 @@ class Decoder
|
|||
{
|
||||
MOZ_ASSERT(begin <= end);
|
||||
}
|
||||
explicit Decoder(const Bytecode& bytecode)
|
||||
: beg_(bytecode.begin()),
|
||||
end_(bytecode.end()),
|
||||
cur_(bytecode.begin())
|
||||
explicit Decoder(const Bytes& bytes)
|
||||
: beg_(bytes.begin()),
|
||||
end_(bytes.end()),
|
||||
cur_(bytes.begin())
|
||||
{}
|
||||
|
||||
bool done() const {
|
||||
|
@ -620,9 +615,6 @@ class Decoder
|
|||
size_t currentOffset() const {
|
||||
return cur_ - beg_;
|
||||
}
|
||||
void assertCurrentIs(const DebugOnly<size_t> offset) const {
|
||||
MOZ_ASSERT(currentOffset() == offset);
|
||||
}
|
||||
|
||||
// Fixed-size encoding operations simply copy the literal bytes (without
|
||||
// attempting to align).
|
||||
|
@ -706,7 +698,7 @@ class Decoder
|
|||
goto backup;
|
||||
cur_ += IdSize;
|
||||
*startOffset = before - beg_;
|
||||
return true;
|
||||
return true;
|
||||
backup:
|
||||
cur_ = before;
|
||||
*startOffset = NotStarted;
|
||||
|
@ -735,7 +727,7 @@ class Decoder
|
|||
}
|
||||
|
||||
// The infallible "unchecked" decoding functions can be used when we are
|
||||
// sure that the bytecode is well-formed (by construction or due to previous
|
||||
// sure that the bytes are well-formed (by construction or due to previous
|
||||
// validation).
|
||||
|
||||
uint32_t uncheckedReadFixedU32() {
|
||||
|
@ -790,9 +782,6 @@ class Decoder
|
|||
MOZ_WARN_UNUSED_RESULT bool readFixedU8(uint8_t* i = nullptr) {
|
||||
return read<uint8_t>(i);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT bool readFixedI32(int32_t* i = nullptr) {
|
||||
return read<int32_t>(i);
|
||||
}
|
||||
uint8_t uncheckedReadFixedU8() {
|
||||
return uncheckedRead<uint8_t>();
|
||||
}
|
||||
|
|
|
@ -301,7 +301,7 @@ ModuleGenerator::convertOutOfRangeBranchesToThunks()
|
|||
bool
|
||||
ModuleGenerator::finishTask(IonCompileTask* task)
|
||||
{
|
||||
const FuncBytecode& func = task->func();
|
||||
const FuncBytes& func = task->func();
|
||||
FuncCompileResults& results = task->results();
|
||||
|
||||
// Before merging in the new function's code, if jumps/calls in a previous
|
||||
|
@ -782,15 +782,8 @@ ModuleGenerator::startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg)
|
|||
|
||||
IonCompileTask* task = freeTasks_.popCopy();
|
||||
|
||||
task->reset(&fg->bytecode_);
|
||||
if (fg->bytecode_) {
|
||||
fg->bytecode_->clear();
|
||||
} else {
|
||||
fg->bytecode_ = MakeUnique<Bytecode>();
|
||||
if (!fg->bytecode_)
|
||||
return false;
|
||||
}
|
||||
|
||||
task->reset(&fg->bytes_);
|
||||
fg->bytes_.clear();
|
||||
fg->lineOrBytecode_ = lineOrBytecode;
|
||||
fg->m_ = this;
|
||||
fg->task_ = task;
|
||||
|
@ -803,13 +796,12 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, unsigned generateTime, Functi
|
|||
{
|
||||
MOZ_ASSERT(activeFunc_ == fg);
|
||||
|
||||
UniqueFuncBytecode func =
|
||||
js::MakeUnique<FuncBytecode>(funcIndex,
|
||||
funcSig(funcIndex),
|
||||
Move(fg->bytecode_),
|
||||
fg->lineOrBytecode_,
|
||||
Move(fg->callSiteLineNums_),
|
||||
generateTime);
|
||||
auto func = js::MakeUnique<FuncBytes>(Move(fg->bytes_),
|
||||
funcIndex,
|
||||
funcSig(funcIndex),
|
||||
fg->lineOrBytecode_,
|
||||
Move(fg->callSiteLineNums_),
|
||||
generateTime);
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef Vector<SlowFunction> SlowFunctionVector;
|
|||
// is encapsulated by ModuleGenerator/ModuleGeneratorThreadView classes which
|
||||
// present a race-free interface to the code in each thread assuming any given
|
||||
// element is initialized by the ModuleGenerator thread before an index to that
|
||||
// element is written to Bytecode sent to a ModuleGeneratorThreadView thread.
|
||||
// element is written to Bytes sent to a ModuleGeneratorThreadView thread.
|
||||
// Once created, the Vectors are never resized.
|
||||
|
||||
struct TableModuleGeneratorData
|
||||
|
@ -202,8 +202,8 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
Vector<IonCompileTask*> freeTasks_;
|
||||
|
||||
// Assertions
|
||||
DebugOnly<FunctionGenerator*> activeFunc_;
|
||||
DebugOnly<bool> finishedFuncs_;
|
||||
FunctionGenerator* activeFunc_;
|
||||
bool finishedFuncs_;
|
||||
|
||||
bool finishOutstandingTask();
|
||||
bool funcIsDefined(uint32_t funcIndex) const;
|
||||
|
@ -288,13 +288,13 @@ class MOZ_STACK_CLASS FunctionGenerator
|
|||
{
|
||||
friend class ModuleGenerator;
|
||||
|
||||
ModuleGenerator* m_;
|
||||
IonCompileTask* task_;
|
||||
ModuleGenerator* m_;
|
||||
IonCompileTask* task_;
|
||||
|
||||
// Data created during function generation, then handed over to the
|
||||
// FuncBytecode in ModuleGenerator::finishFunc().
|
||||
UniqueBytecode bytecode_;
|
||||
Uint32Vector callSiteLineNums_;
|
||||
// FuncBytes in ModuleGenerator::finishFunc().
|
||||
Bytes bytes_;
|
||||
Uint32Vector callSiteLineNums_;
|
||||
|
||||
uint32_t lineOrBytecode_;
|
||||
|
||||
|
@ -303,8 +303,8 @@ class MOZ_STACK_CLASS FunctionGenerator
|
|||
: m_(nullptr), task_(nullptr), lineOrBytecode_(0)
|
||||
{}
|
||||
|
||||
Bytecode& bytecode() const {
|
||||
return *bytecode_;
|
||||
Bytes& bytes() {
|
||||
return bytes_;
|
||||
}
|
||||
bool addCallSiteLineNum(uint32_t lineno) {
|
||||
return callSiteLineNums_.append(lineno);
|
||||
|
|
|
@ -40,7 +40,7 @@ class FunctionCompiler
|
|||
|
||||
ModuleGeneratorThreadView& mg_;
|
||||
Decoder& decoder_;
|
||||
const FuncBytecode& func_;
|
||||
const FuncBytes& func_;
|
||||
const ValTypeVector& locals_;
|
||||
size_t lastReadCallSite_;
|
||||
|
||||
|
@ -60,7 +60,7 @@ class FunctionCompiler
|
|||
public:
|
||||
FunctionCompiler(ModuleGeneratorThreadView& mg,
|
||||
Decoder& decoder,
|
||||
const FuncBytecode& func,
|
||||
const FuncBytes& func,
|
||||
const ValTypeVector& locals,
|
||||
MIRGenerator& mirGen,
|
||||
FuncCompileResults& compileResults)
|
||||
|
@ -153,7 +153,7 @@ class FunctionCompiler
|
|||
}
|
||||
#endif
|
||||
MOZ_ASSERT(inDeadCode());
|
||||
MOZ_ASSERT(decoder_.done(), "all bytecode must be consumed");
|
||||
MOZ_ASSERT(decoder_.done(), "all bytes must be consumed");
|
||||
MOZ_ASSERT(func_.callSiteLineNums().length() == lastReadCallSite_);
|
||||
}
|
||||
|
||||
|
@ -3048,10 +3048,10 @@ wasm::IonCompileFunction(IonCompileTask* task)
|
|||
{
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
const FuncBytecode& func = task->func();
|
||||
const FuncBytes& func = task->func();
|
||||
FuncCompileResults& results = task->results();
|
||||
|
||||
Decoder d(func.bytecode());
|
||||
Decoder d(func.bytes());
|
||||
|
||||
// Build the local types vector.
|
||||
|
||||
|
|
|
@ -31,52 +31,48 @@ typedef Vector<jit::MIRType, 8, SystemAllocPolicy> MIRTypeVector;
|
|||
typedef jit::ABIArgIter<MIRTypeVector> ABIArgMIRTypeIter;
|
||||
typedef jit::ABIArgIter<ValTypeVector> ABIArgValTypeIter;
|
||||
|
||||
// The FuncBytecode class contains the intermediate representation of a
|
||||
// parsed/decoded and validated asm.js/WebAssembly function. The FuncBytecode
|
||||
// lives only until it is fully compiled.
|
||||
// The FuncBytes class represents a single, concurrently-compilable function.
|
||||
// A FuncBytes object is composed of the wasm function body bytes along with the
|
||||
// ambient metadata describing the function necessary to compile it.
|
||||
|
||||
class FuncBytecode
|
||||
class FuncBytes
|
||||
{
|
||||
// Function metadata
|
||||
Bytes bytes_;
|
||||
uint32_t index_;
|
||||
const DeclaredSig& sig_;
|
||||
uint32_t lineOrBytecode_;
|
||||
Uint32Vector callSiteLineNums_;
|
||||
|
||||
// Compilation bookkeeping
|
||||
uint32_t index_;
|
||||
unsigned generateTime_;
|
||||
|
||||
UniqueBytecode bytecode_;
|
||||
uint32_t lineOrBytecode_;
|
||||
Uint32Vector callSiteLineNums_;
|
||||
unsigned generateTime_;
|
||||
|
||||
public:
|
||||
FuncBytecode(uint32_t index,
|
||||
const DeclaredSig& sig,
|
||||
UniqueBytecode bytecode,
|
||||
uint32_t lineOrBytecode,
|
||||
Uint32Vector&& callSiteLineNums,
|
||||
unsigned generateTime)
|
||||
: sig_(sig),
|
||||
FuncBytes(Bytes&& bytes,
|
||||
uint32_t index,
|
||||
const DeclaredSig& sig,
|
||||
uint32_t lineOrBytecode,
|
||||
Uint32Vector&& callSiteLineNums,
|
||||
unsigned generateTime)
|
||||
: bytes_(Move(bytes)),
|
||||
index_(index),
|
||||
sig_(sig),
|
||||
lineOrBytecode_(lineOrBytecode),
|
||||
callSiteLineNums_(Move(callSiteLineNums)),
|
||||
index_(index),
|
||||
generateTime_(generateTime),
|
||||
bytecode_(Move(bytecode))
|
||||
generateTime_(generateTime)
|
||||
{}
|
||||
|
||||
UniqueBytecode recycleBytecode() { return Move(bytecode_); }
|
||||
|
||||
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
|
||||
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
|
||||
Bytes& bytes() { return bytes_; }
|
||||
const Bytes& bytes() const { return bytes_; }
|
||||
uint32_t index() const { return index_; }
|
||||
const DeclaredSig& sig() const { return sig_; }
|
||||
const Bytecode& bytecode() const { return *bytecode_; }
|
||||
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
|
||||
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
|
||||
unsigned generateTime() const { return generateTime_; }
|
||||
};
|
||||
|
||||
typedef UniquePtr<FuncBytecode> UniqueFuncBytecode;
|
||||
typedef UniquePtr<FuncBytes> UniqueFuncBytes;
|
||||
|
||||
// The FuncCompileResults class contains the results of compiling a single
|
||||
// function body, ready to be merged into the whole-module MacroAssembler.
|
||||
|
||||
// The FuncCompileResults contains the results of compiling a single function
|
||||
// body, ready to be merged into the whole-module MacroAssembler.
|
||||
class FuncCompileResults
|
||||
{
|
||||
jit::TempAllocator alloc_;
|
||||
|
@ -108,13 +104,14 @@ class FuncCompileResults
|
|||
// the FuncCompileResults, and finally sent back to the validation thread. To
|
||||
// save time allocating and freeing memory, IonCompileTasks are reset() and
|
||||
// reused.
|
||||
|
||||
class IonCompileTask
|
||||
{
|
||||
JSRuntime* const runtime_;
|
||||
JSRuntime* const runtime_;
|
||||
ModuleGeneratorThreadView& mg_;
|
||||
LifoAlloc lifo_;
|
||||
UniqueFuncBytecode func_;
|
||||
mozilla::Maybe<FuncCompileResults> results_;
|
||||
LifoAlloc lifo_;
|
||||
UniqueFuncBytes func_;
|
||||
Maybe<FuncCompileResults> results_;
|
||||
|
||||
IonCompileTask(const IonCompileTask&) = delete;
|
||||
IonCompileTask& operator=(const IonCompileTask&) = delete;
|
||||
|
@ -132,21 +129,21 @@ class IonCompileTask
|
|||
ModuleGeneratorThreadView& mg() const {
|
||||
return mg_;
|
||||
}
|
||||
void init(UniqueFuncBytecode func) {
|
||||
void init(UniqueFuncBytes func) {
|
||||
MOZ_ASSERT(!func_);
|
||||
func_ = mozilla::Move(func);
|
||||
func_ = Move(func);
|
||||
results_.emplace(lifo_);
|
||||
}
|
||||
const FuncBytecode& func() const {
|
||||
const FuncBytes& func() const {
|
||||
MOZ_ASSERT(func_);
|
||||
return *func_;
|
||||
}
|
||||
FuncCompileResults& results() {
|
||||
return *results_;
|
||||
}
|
||||
void reset(UniqueBytecode* recycled) {
|
||||
void reset(Bytes* recycled) {
|
||||
if (func_)
|
||||
*recycled = func_->recycleBytecode();
|
||||
*recycled = Move(func_->bytes());
|
||||
func_.reset(nullptr);
|
||||
results_.reset();
|
||||
lifo_.releaseAll();
|
||||
|
|
|
@ -4024,60 +4024,56 @@ EncodeDataSegments(Encoder& e, WasmAstModule& module)
|
|||
return true;
|
||||
}
|
||||
|
||||
static UniqueBytecode
|
||||
EncodeModule(WasmAstModule& module)
|
||||
static bool
|
||||
EncodeModule(WasmAstModule& module, Bytes* bytes)
|
||||
{
|
||||
UniqueBytecode bytecode = MakeUnique<Bytecode>();
|
||||
if (!bytecode)
|
||||
return nullptr;
|
||||
|
||||
Encoder e(*bytecode);
|
||||
Encoder e(*bytes);
|
||||
|
||||
if (!e.writeFixedU32(MagicNumber))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!e.writeFixedU32(EncodingVersion))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeSignatures(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeImportTable(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeFunctionSignatures(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeFunctionTable(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeMemory(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeExportTable(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeFunctionBodies(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!EncodeDataSegments(e, module))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
return Move(bytecode);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
UniqueBytecode
|
||||
wasm::TextToBinary(const char16_t* text, UniqueChars* error)
|
||||
bool
|
||||
wasm::TextToBinary(const char16_t* text, Bytes* bytes, UniqueChars* error)
|
||||
{
|
||||
LifoAlloc lifo(AST_LIFO_DEFAULT_CHUNK_SIZE);
|
||||
WasmAstModule* module = ParseModule(text, lifo, error);
|
||||
if (!module)
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
if (!ResolveModule(lifo, module, error))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
return EncodeModule(*module);
|
||||
return EncodeModule(*module, bytes);
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace js {
|
|||
namespace wasm {
|
||||
|
||||
// Translate the textual representation of a wasm module (given by a
|
||||
// null-terminated char16_t array) into a Bytecode object. If there is an error
|
||||
// null-terminated char16_t array) into serialized bytes. If there is an error
|
||||
// other than out-of-memory an error message string will be stored in 'error'.
|
||||
|
||||
extern UniqueBytecode
|
||||
TextToBinary(const char16_t* text, UniqueChars* error);
|
||||
extern bool
|
||||
TextToBinary(const char16_t* text, Bytes* bytes, UniqueChars* error);
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
#include "NamespaceImports.h"
|
||||
|
@ -39,6 +40,7 @@ class PropertyName;
|
|||
namespace wasm {
|
||||
|
||||
using mozilla::EnumeratedArray;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::Move;
|
||||
using mozilla::MallocSizeOf;
|
||||
|
||||
|
|
|
@ -525,19 +525,19 @@ WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!twoByteChars.initTwoByte(cx, args[0].toString()))
|
||||
return false;
|
||||
|
||||
wasm::Bytes bytes;
|
||||
UniqueChars error;
|
||||
wasm::UniqueBytecode bytes = wasm::TextToBinary(twoByteChars.twoByteChars(), &error);
|
||||
if (!bytes) {
|
||||
if (!wasm::TextToBinary(twoByteChars.twoByteChars(), &bytes, &error)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_TEXT_FAIL,
|
||||
error.get() ? error.get() : "out of memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, JS_NewUint8Array(cx, bytes->length()));
|
||||
RootedObject obj(cx, JS_NewUint8Array(cx, bytes.length()));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
memcpy(obj->as<TypedArrayObject>().viewDataUnshared(), bytes->begin(), bytes->length());
|
||||
memcpy(obj->as<TypedArrayObject>().viewDataUnshared(), bytes.begin(), bytes.length());
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
|
|
|
@ -43,8 +43,8 @@ BEGIN_TEST(testWasmLEB128_encoding)
|
|||
using namespace js;
|
||||
using namespace wasm;
|
||||
|
||||
Bytecode bc;
|
||||
Encoder encoder(bc);
|
||||
Bytes bytes;
|
||||
Encoder encoder(bytes);
|
||||
|
||||
bool passed;
|
||||
if (!WriteValidBytes(encoder, &passed))
|
||||
|
@ -52,18 +52,18 @@ BEGIN_TEST(testWasmLEB128_encoding)
|
|||
CHECK(passed);
|
||||
|
||||
size_t i = 0;
|
||||
CHECK(bc[i++] == 0x0);
|
||||
CHECK(bc[i++] == 0x1);
|
||||
CHECK(bc[i++] == 0x42);
|
||||
CHECK(bytes[i++] == 0x0);
|
||||
CHECK(bytes[i++] == 0x1);
|
||||
CHECK(bytes[i++] == 0x42);
|
||||
|
||||
CHECK(bc[i++] == 0x80);
|
||||
CHECK(bc[i++] == 0x01);
|
||||
CHECK(bytes[i++] == 0x80);
|
||||
CHECK(bytes[i++] == 0x01);
|
||||
|
||||
CHECK(bc[i++] == 0x80);
|
||||
CHECK(bc[i++] == 0x03);
|
||||
CHECK(bytes[i++] == 0x80);
|
||||
CHECK(bytes[i++] == 0x03);
|
||||
|
||||
if (i + 1 < bc.length())
|
||||
CHECK(bc[i++] == 0x00);
|
||||
if (i + 1 < bytes.length())
|
||||
CHECK(bytes[i++] == 0x00);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testWasmLEB128_encoding)
|
||||
|
@ -73,19 +73,19 @@ BEGIN_TEST(testWasmLEB128_valid_decoding)
|
|||
using namespace js;
|
||||
using namespace wasm;
|
||||
|
||||
Bytecode bc;
|
||||
if (!bc.append(0x0) || !bc.append(0x1) || !bc.append(0x42))
|
||||
Bytes bytes;
|
||||
if (!bytes.append(0x0) || !bytes.append(0x1) || !bytes.append(0x42))
|
||||
return false;
|
||||
|
||||
if (!bc.append(0x80) || !bc.append(0x01))
|
||||
if (!bytes.append(0x80) || !bytes.append(0x01))
|
||||
return false;
|
||||
|
||||
if (!bc.append(0x80) || !bc.append(0x03))
|
||||
if (!bytes.append(0x80) || !bytes.append(0x03))
|
||||
return false;
|
||||
|
||||
{
|
||||
// Fallible decoding
|
||||
Decoder decoder(bc);
|
||||
Decoder decoder(bytes);
|
||||
uint32_t value;
|
||||
|
||||
CHECK(decoder.readVarU32(&value) && value == 0x0);
|
||||
|
@ -99,7 +99,7 @@ BEGIN_TEST(testWasmLEB128_valid_decoding)
|
|||
|
||||
{
|
||||
// Infallible decoding
|
||||
Decoder decoder(bc);
|
||||
Decoder decoder(bytes);
|
||||
uint32_t value;
|
||||
|
||||
value = decoder.uncheckedReadVarU32();
|
||||
|
@ -124,20 +124,20 @@ BEGIN_TEST(testWasmLEB128_invalid_decoding)
|
|||
using namespace js;
|
||||
using namespace wasm;
|
||||
|
||||
Bytecode bc;
|
||||
Bytes bytes;
|
||||
// Fill bits as per 28 encoded bits
|
||||
if (!bc.append(0x80) || !bc.append(0x80) || !bc.append(0x80) || !bc.append(0x80))
|
||||
if (!bytes.append(0x80) || !bytes.append(0x80) || !bytes.append(0x80) || !bytes.append(0x80))
|
||||
return false;
|
||||
|
||||
// Test last valid values
|
||||
if (!bc.append(0x00))
|
||||
if (!bytes.append(0x00))
|
||||
return false;
|
||||
|
||||
for (uint8_t i = 0; i < 0x0F; i++) {
|
||||
bc[4] = i;
|
||||
bytes[4] = i;
|
||||
|
||||
{
|
||||
Decoder decoder(bc);
|
||||
Decoder decoder(bytes);
|
||||
uint32_t value;
|
||||
CHECK(decoder.readVarU32(&value));
|
||||
CHECK(value == uint32_t(i << 28));
|
||||
|
@ -145,7 +145,7 @@ BEGIN_TEST(testWasmLEB128_invalid_decoding)
|
|||
}
|
||||
|
||||
{
|
||||
Decoder decoder(bc);
|
||||
Decoder decoder(bytes);
|
||||
uint32_t value = decoder.uncheckedReadVarU32();
|
||||
CHECK(value == uint32_t(i << 28));
|
||||
CHECK(decoder.done());
|
||||
|
@ -154,9 +154,9 @@ BEGIN_TEST(testWasmLEB128_invalid_decoding)
|
|||
|
||||
// Test all invalid values of the same size
|
||||
for (uint8_t i = 0x10; i < 0xF0; i++) {
|
||||
bc[4] = i;
|
||||
bytes[4] = i;
|
||||
|
||||
Decoder decoder(bc);
|
||||
Decoder decoder(bytes);
|
||||
uint32_t value;
|
||||
CHECK(!decoder.readVarU32(&value));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче