--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -2645,17 +2645,17 @@ class MOZ_STACK_CLASS FunctionValidator
bool init(PropertyName* name, unsigned line) {
if (!locals_.init() || !breakLabels_.init() || !continueLabels_.init())
return false;
if (!m_.mg().startFuncDef(line, &fg_))
return false;
- encoder_.emplace(fg_.bytecode());
+ encoder_.emplace(fg_.bytes());
return true;
}
bool finish(uint32_t funcIndex, unsigned generateTime) {
return m_.mg().finishFuncDef(funcIndex, generateTime, &fg_);
}
bool fail(ParseNode* pn, const char* str) {
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -1260,20 +1260,20 @@ DecodeFunctionBody(JSContext* cx, Decode
}
if (!CheckType(f, type, f.sig().ret()))
return false;
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;
return mg.finishFuncDef(funcIndex, generateTime, &fg);
}
static bool
--- a/js/src/asmjs/WasmBinary.h
+++ b/js/src/asmjs/WasmBinary.h
@@ -14,25 +14,21 @@
* 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_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;
static const char SignaturesId[] = "signatures";
static const char ImportTableId[] = "import_table";
static const char FunctionSignaturesId[] = "function_signatures";
static const char FunctionTableId[] = "function_table";
static const char MemoryId[] = "memory";
@@ -323,40 +319,39 @@ enum class ExprType
F32x4 = uint8_t(ValType::F32x4),
B32x4 = uint8_t(ValType::B32x4),
Limit
};
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>
MOZ_WARN_UNUSED_RESULT bool writeVarU(UInt i) {
do {
uint8_t byte = i & 0x7F;
i >>= 7;
if (i != 0)
byte |= 0x80;
- if (!bytecode_.append(byte))
+ if (!bytes_.append(byte))
return false;
} while(i != 0);
return true;
}
template <class T>
MOZ_WARN_UNUSED_RESULT bool writeEnum(T v) {
static_assert(uint32_t(T::Limit) <= UINT32_MAX, "fits");
@@ -369,52 +364,52 @@ class Encoder
uint8_t assertByte = assertBits & 0x7f;
uint8_t patchByte = patchBits & 0x7f;
assertBits >>= 7;
patchBits >>= 7;
if (assertBits != 0) {
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;
}
static const uint32_t EnumSentinel = 0x3fff;
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);
}
template <class T>
void patchEnum(size_t offset, T v) {
static_assert(uint32_t(T::Limit) <= UINT32_MAX, "fits");
MOZ_ASSERT(uint32_t(v) < uint32_t(T::Limit));
return patchVarU32(offset, uint32_t(v), EnumSentinel);
}
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
// attempting to align).
MOZ_WARN_UNUSED_RESULT bool writeFixedU32(uint32_t i) {
return write<uint32_t>(i);
}
@@ -447,25 +442,25 @@ class Encoder
}
MOZ_WARN_UNUSED_RESULT bool writeExprType(ExprType type) {
return writeEnum(type);
}
// 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) {
return patchVarU32(offset, patchBits, UINT32_MAX);
}
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) {
MOZ_ASSERT(patchBits < 0x80);
return patchU8(offset, patchBits);
}
MOZ_WARN_UNUSED_RESULT bool writePatchableExpr(size_t* offset) {
@@ -474,20 +469,20 @@ class Encoder
void patchExpr(size_t offset, Expr expr) {
patchEnum(offset, expr);
}
// C-strings are written in UTF8 and null-terminated while raw data can
// 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
// that it may be trivially skipped without examining the contents. Sections
// require backpatching since the size of the section is only known at the
// end while the size's uint32 must be stored at the beginning. Immediately
// after the section length is the string id of the section.
@@ -495,32 +490,32 @@ class Encoder
MOZ_WARN_UNUSED_RESULT bool startSection(const char (&id)[IdSizeWith0], size_t* offset) {
static const size_t IdSize = IdSizeWith0 - 1;
MOZ_ASSERT(id[IdSize] == '\0');
return writePatchableVarU32(offset) &&
writeVarU32(IdSize) &&
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
// conversion to wasm:
MOZ_WARN_UNUSED_RESULT bool writeU8(uint8_t i) {
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;
}
};
// The Decoder class decodes the bytes in the range it is given during
// construction. The client is responsible for keeping the byte range alive as
// long as the Decoder is used.
class Decoder
@@ -594,20 +589,20 @@ class Decoder
public:
Decoder(const uint8_t* begin, const uint8_t* end)
: beg_(begin),
end_(end),
cur_(begin)
{
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 {
MOZ_ASSERT(cur_ <= end_);
return cur_ == end_;
}
uintptr_t bytesRemain() const {
@@ -615,19 +610,16 @@ class Decoder
return uintptr_t(end_ - cur_);
}
const uint8_t* currentPosition() const {
return cur_;
}
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).
MOZ_WARN_UNUSED_RESULT bool readFixedU32(uint32_t* u = nullptr) {
return read<uint32_t>(u);
}
MOZ_WARN_UNUSED_RESULT bool readFixedF32(float* f = nullptr) {
@@ -701,17 +693,17 @@ class Decoder
if (!readVarU32(&idSize))
goto backup;
if (bytesRemain() < idSize)
return false;
if (idSize != IdSize || !!memcmp(cur_, id, IdSize))
goto backup;
cur_ += IdSize;
*startOffset = before - beg_;
- return true;
+ return true;
backup:
cur_ = before;
*startOffset = NotStarted;
return true;
}
MOZ_WARN_UNUSED_RESULT bool finishSection(uint32_t startOffset) {
uint32_t currentOffset = cur_ - beg_;
cur_ = beg_ + startOffset;
@@ -730,17 +722,17 @@ class Decoder
return false;
if (uint32_t(cur_ - begin) > size)
return false;
cur_ = begin + size;
return true;
}
// 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() {
return uncheckedRead<uint32_t>();
}
float uncheckedReadFixedF32() {
return uncheckedRead<float>();
}
@@ -785,19 +777,16 @@ class Decoder
}
// Temporary encoding forms which should be removed as part of the
// conversion to wasm:
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>();
}
};
// Reusable macro encoding/decoding functions reused by both the two
// encoders (AsmJS/WasmText) and decoders (Wasm/WasmIonCompile).
--- a/js/src/asmjs/WasmGenerator.cpp
+++ b/js/src/asmjs/WasmGenerator.cpp
@@ -296,17 +296,17 @@ ModuleGenerator::convertOutOfRangeBranch
masm_.clearJumpSites();
return true;
}
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
// function's body might go out of range, patch these to thunks which have
// full range.
if ((masm_.size() - startOfUnpatchedBranches_) + results.masm().size() > JumpRange()) {
startOfUnpatchedBranches_ = masm_.size();
if (!convertOutOfRangeBranchesToThunks())
@@ -777,44 +777,36 @@ ModuleGenerator::startFuncDef(uint32_t l
MOZ_ASSERT(!activeFunc_);
MOZ_ASSERT(!finishedFuncs_);
if (freeTasks_.empty() && !finishOutstandingTask())
return false;
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;
activeFunc_ = fg;
return true;
}
bool
ModuleGenerator::finishFuncDef(uint32_t funcIndex, unsigned generateTime, FunctionGenerator* fg)
{
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;
fg->task_->init(Move(func));
if (parallel_) {
if (!StartOffThreadWasmCompile(cx_, fg->task_))
return false;
--- a/js/src/asmjs/WasmGenerator.h
+++ b/js/src/asmjs/WasmGenerator.h
@@ -46,17 +46,17 @@ struct SlowFunction
};
typedef Vector<SlowFunction> SlowFunctionVector;
// The ModuleGeneratorData holds all the state shared between the
// ModuleGenerator and ModuleGeneratorThreadView. The ModuleGeneratorData
// 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
{
uint32_t globalDataOffset;
uint32_t numElems;
Uint32Vector elemFuncIndices;
@@ -197,18 +197,18 @@ class MOZ_STACK_CLASS ModuleGenerator
// Parallel compilation
bool parallel_;
uint32_t outstanding_;
UniqueModuleGeneratorThreadView threadView_;
Vector<IonCompileTask> tasks_;
Vector<IonCompileTask*> freeTasks_;
// Assertions
- DebugOnly<FunctionGenerator*> activeFunc_;
- DebugOnly<bool> finishedFuncs_;
+ FunctionGenerator* activeFunc_;
+ bool finishedFuncs_;
bool finishOutstandingTask();
bool funcIsDefined(uint32_t funcIndex) const;
uint32_t funcEntry(uint32_t funcIndex) const;
bool convertOutOfRangeBranchesToThunks();
bool finishTask(IonCompileTask* task);
bool finishCodegen(StaticLinkData* link);
bool finishStaticLinkData(uint8_t* code, uint32_t codeBytes, StaticLinkData* link);
@@ -283,33 +283,33 @@ class MOZ_STACK_CLASS ModuleGenerator
// 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_;
+ 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_;
public:
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);
}
};
} // namespace wasm
} // namespace js
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -35,17 +35,17 @@ typedef Vector<MBasicBlock*, 8, SystemAl
// MIR graph.
class FunctionCompiler
{
private:
typedef Vector<BlockVector, 0, SystemAllocPolicy> BlocksVector;
ModuleGeneratorThreadView& mg_;
Decoder& decoder_;
- const FuncBytecode& func_;
+ const FuncBytes& func_;
const ValTypeVector& locals_;
size_t lastReadCallSite_;
TempAllocator& alloc_;
MIRGraph& graph_;
const CompileInfo& info_;
MIRGenerator& mirGen_;
@@ -55,17 +55,17 @@ class FunctionCompiler
uint32_t blockDepth_;
BlocksVector targets_;
FuncCompileResults& compileResults_;
public:
FunctionCompiler(ModuleGeneratorThreadView& mg,
Decoder& decoder,
- const FuncBytecode& func,
+ const FuncBytes& func,
const ValTypeVector& locals,
MIRGenerator& mirGen,
FuncCompileResults& compileResults)
: mg_(mg),
decoder_(decoder),
func_(func),
locals_(locals),
lastReadCallSite_(0),
@@ -148,17 +148,17 @@ class FunctionCompiler
MOZ_ASSERT(loopDepth_ == 0);
MOZ_ASSERT(blockDepth_ == 0);
#ifdef DEBUG
for (BlockVector& vec : targets_) {
MOZ_ASSERT(vec.empty());
}
#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_);
}
/************************* Read-only interface (after local scope setup) */
MIRGenerator& mirGen() const { return mirGen_; }
MIRGraph& mirGraph() const { return graph_; }
const CompileInfo& info() const { return info_; }
@@ -3043,20 +3043,20 @@ EmitExpr(FunctionCompiler& f, MDefinitio
MOZ_CRASH("unexpected wasm opcode");
}
bool
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.
ValTypeVector locals;
if (!locals.appendAll(func.sig().args()))
return false;
if (!DecodeLocalEntries(d, &locals))
return false;
--- a/js/src/asmjs/WasmIonCompile.h
+++ b/js/src/asmjs/WasmIonCompile.h
@@ -26,62 +26,58 @@ namespace js {
namespace wasm {
class ModuleGeneratorThreadView;
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_); }
-
+ Bytes& bytes() { return bytes_; }
+ const Bytes& bytes() const { return bytes_; }
+ uint32_t index() const { return index_; }
+ const DeclaredSig& sig() const { return sig_; }
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
- uint32_t index() const { return index_; }
- const DeclaredSig& sig() const { return sig_; }
- const Bytecode& bytecode() const { return *bytecode_; }
unsigned generateTime() const { return generateTime_; }
};
-typedef UniquePtr<FuncBytecode> UniqueFuncBytecode;
+typedef UniquePtr<FuncBytes> UniqueFuncBytes;
-// The FuncCompileResults contains the results of compiling a single function
-// body, ready to be merged into the whole-module MacroAssembler.
+// The FuncCompileResults class contains the results of compiling a single
+// function body, ready to be merged into the whole-module MacroAssembler.
+
class FuncCompileResults
{
jit::TempAllocator alloc_;
jit::MacroAssembler masm_;
FuncOffsets offsets_;
unsigned compileTime_;
FuncCompileResults(const FuncCompileResults&) = delete;
@@ -103,23 +99,24 @@ class FuncCompileResults
};
// An IonCompileTask represents the task of compiling a single function body. An
// IonCompileTask is filled with the wasm code to be compiled on the main
// validation thread, sent off to an Ion compilation helper thread which creates
// 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;
public:
IonCompileTask(JSRuntime* rt, ModuleGeneratorThreadView& mg, size_t defaultChunkSize)
: runtime_(rt), mg_(mg), lifo_(defaultChunkSize), func_(nullptr)
{}
@@ -127,31 +124,31 @@ class IonCompileTask
return runtime_;
}
LifoAlloc& lifo() {
return lifo_;
}
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();
}
};
bool
IonCompileFunction(IonCompileTask* task);
--- a/js/src/asmjs/WasmText.cpp
+++ b/js/src/asmjs/WasmText.cpp
@@ -4019,65 +4019,61 @@ EncodeDataSegments(Encoder& e, WasmAstMo
if (!EncodeDataSegment(e, *segment))
return false;
}
e.finishSection(offset);
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 Move(bytecode);
+ return false;
+
+ 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 EncodeModule(*module);
+ return false;
+
+ return EncodeModule(*module, bytes);
}
--- a/js/src/asmjs/WasmText.h
+++ b/js/src/asmjs/WasmText.h
@@ -21,18 +21,18 @@
#include "asmjs/WasmBinary.h"
#include "js/Utility.h"
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
#endif // wasm_text_h
--- a/js/src/asmjs/WasmTypes.h
+++ b/js/src/asmjs/WasmTypes.h
@@ -16,16 +16,17 @@
* limitations under the License.
*/
#ifndef wasm_types_h
#define wasm_types_h
#include "mozilla/EnumeratedArray.h"
#include "mozilla/HashFunctions.h"
+#include "mozilla/Maybe.h"
#include "mozilla/Move.h"
#include "NamespaceImports.h"
#include "asmjs/WasmBinary.h"
#include "ds/LifoAlloc.h"
#include "jit/IonTypes.h"
#include "js/UniquePtr.h"
@@ -34,16 +35,17 @@
namespace js {
class PropertyName;
namespace wasm {
using mozilla::EnumeratedArray;
+using mozilla::Maybe;
using mozilla::Move;
using mozilla::MallocSizeOf;
typedef Vector<uint32_t, 0, SystemAllocPolicy> Uint32Vector;
// ValType/ExprType utilities
static inline bool
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -520,29 +520,29 @@ WasmTextToBinary(JSContext* cx, unsigned
ReportUsageError(cx, callee, "First argument must be a String");
return false;
}
AutoStableStringChars twoByteChars(cx);
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;
}
static bool
IsLazyFunction(JSContext* cx, unsigned argc, Value* vp)
{
--- a/js/src/jsapi-tests/testWasmLEB128.cpp
+++ b/js/src/jsapi-tests/testWasmLEB128.cpp
@@ -38,73 +38,73 @@ static bool WriteValidBytes(js::wasm::En
return true;
}
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))
return false;
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)
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);
CHECK(decoder.readVarU32(&value) && value == 0x1);
CHECK(decoder.readVarU32(&value) && value == 0x42);
CHECK(decoder.readVarU32(&value) && value == 0x80);
CHECK(decoder.readVarU32(&value) && value == 0x180);
CHECK(decoder.done());
}
{
// Infallible decoding
- Decoder decoder(bc);
+ Decoder decoder(bytes);
uint32_t value;
value = decoder.uncheckedReadVarU32();
CHECK(value == 0x0);
value = decoder.uncheckedReadVarU32();
CHECK(value == 0x1);
value = decoder.uncheckedReadVarU32();
CHECK(value == 0x42);
@@ -119,48 +119,48 @@ BEGIN_TEST(testWasmLEB128_valid_decoding
}
END_TEST(testWasmLEB128_valid_decoding)
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));
CHECK(decoder.done());
}
{
- Decoder decoder(bc);
+ Decoder decoder(bytes);
uint32_t value = decoder.uncheckedReadVarU32();
CHECK(value == uint32_t(i << 28));
CHECK(decoder.done());
}
}
// 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));
}
return true;
}
END_TEST(testWasmLEB128_invalid_decoding)