diff --git a/js/src/asmjs/AsmJS.cpp b/js/src/asmjs/AsmJS.cpp index d62a216e86a2..532157c87803 100644 --- a/js/src/asmjs/AsmJS.cpp +++ b/js/src/asmjs/AsmJS.cpp @@ -29,6 +29,7 @@ #include "jswrapper.h" +#include "asmjs/WasmBinaryFormat.h" #include "asmjs/WasmGenerator.h" #include "asmjs/WasmInstance.h" #include "asmjs/WasmJS.h" diff --git a/js/src/asmjs/WasmAST.h b/js/src/asmjs/WasmAST.h index a33f8f547bbf..3bc925869cf2 100644 --- a/js/src/asmjs/WasmAST.h +++ b/js/src/asmjs/WasmAST.h @@ -595,21 +595,21 @@ class AstFunc : public AstNode class AstGlobal : public AstNode { AstName name_; - uint32_t flags_; + bool isMutable_; ValType type_; Maybe init_; public: - AstGlobal() : flags_(0), type_(ValType::Limit) + AstGlobal() : isMutable_(false), type_(ValType::Limit) {} - explicit AstGlobal(AstName name, ValType type, uint32_t flags, + explicit AstGlobal(AstName name, ValType type, bool isMutable, Maybe init = Maybe()) - : name_(name), flags_(flags), type_(type), init_(init) + : name_(name), isMutable_(isMutable), type_(type), init_(init) {} AstName name() const { return name_; } - uint32_t flags() const { return flags_; } + bool isMutable() const { return isMutable_; } ValType type() const { return type_; } bool hasInit() const { return !!init_; } diff --git a/js/src/asmjs/WasmBaselineCompile.cpp b/js/src/asmjs/WasmBaselineCompile.cpp index 75519e2a4f0e..6766c4e5c82a 100644 --- a/js/src/asmjs/WasmBaselineCompile.cpp +++ b/js/src/asmjs/WasmBaselineCompile.cpp @@ -94,6 +94,7 @@ #include "mozilla/MathAlgorithms.h" +#include "asmjs/WasmBinaryFormat.h" #include "asmjs/WasmBinaryIterator.h" #include "asmjs/WasmGenerator.h" #include "asmjs/WasmSignalHandlers.h" diff --git a/js/src/asmjs/WasmBinary.cpp b/js/src/asmjs/WasmBinary.cpp index c14ad19dbc87..83f5cdcd1638 100644 --- a/js/src/asmjs/WasmBinary.cpp +++ b/js/src/asmjs/WasmBinary.cpp @@ -41,146 +41,10 @@ Decoder::fail(const char* msg, ...) { bool Decoder::fail(UniqueChars msg) { MOZ_ASSERT(error_); - UniqueChars strWithOffset(JS_smprintf("at offset %" PRIuSIZE ": %s", - currentOffset(), msg.get())); + UniqueChars strWithOffset(JS_smprintf("at offset %" PRIuSIZE ": %s", currentOffset(), msg.get())); if (!strWithOffset) return false; *error_ = Move(strWithOffset); return false; } - -bool -wasm::DecodePreamble(Decoder& d) -{ - uint32_t u32; - if (!d.readFixedU32(&u32) || u32 != MagicNumber) - return d.fail("failed to match magic number"); - - if (!d.readFixedU32(&u32) || u32 != EncodingVersion) - return d.fail("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32, - u32, EncodingVersion); - - return true; -} - -bool -wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals) -{ - uint32_t numLocalEntries = 0; - ValType prev = ValType::Limit; - for (ValType t : locals) { - if (t != prev) { - numLocalEntries++; - prev = t; - } - } - - if (!e.writeVarU32(numLocalEntries)) - return false; - - if (numLocalEntries) { - prev = locals[0]; - uint32_t count = 1; - for (uint32_t i = 1; i < locals.length(); i++, count++) { - if (prev != locals[i]) { - if (!e.writeVarU32(count)) - return false; - if (!e.writeValType(prev)) - return false; - prev = locals[i]; - count = 0; - } - } - if (!e.writeVarU32(count)) - return false; - if (!e.writeValType(prev)) - return false; - } - - return true; -} - -bool -wasm::DecodeLocalEntries(Decoder& d, ValTypeVector* locals) -{ - uint32_t numLocalEntries; - if (!d.readVarU32(&numLocalEntries)) - return false; - - for (uint32_t i = 0; i < numLocalEntries; i++) { - uint32_t count; - if (!d.readVarU32(&count)) - return false; - - if (MaxLocals - locals->length() < count) - return false; - - ValType type; - if (!d.readValType(&type)) - return false; - - if (!locals->appendN(type, count)) - return false; - } - - return true; -} - -bool -wasm::DecodeGlobalType(Decoder& d, ValType* type, uint32_t* flags) -{ - if (!d.readValType(type)) - return d.fail("bad global type"); - - if (!d.readVarU32(flags)) - return d.fail("expected global flags"); - - if (*flags & ~uint32_t(GlobalFlags::AllowedMask)) - return d.fail("unexpected bits set in global flags"); - - return true; -} - -bool -wasm::DecodeLimits(Decoder& d, Limits* limits) -{ - uint32_t flags; - if (!d.readVarU32(&flags)) - return d.fail("expected flags"); - - // TODO (bug 1310149): tighten this check (s/3/1) when the AngryBots demo - // gets updated. - if (flags & ~uint32_t(0x3)) - return d.fail("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x3))); - - if (!d.readVarU32(&limits->initial)) - return d.fail("expected initial length"); - - if (flags & 0x1) { - uint32_t maximum; - if (!d.readVarU32(&maximum)) - return d.fail("expected maximum length"); - - if (limits->initial > maximum) { - return d.fail("memory size minimum must not be greater than maximum; " - "maximum length %" PRIu32 " is less than initial length %" PRIu32 , - maximum, limits->initial); - } - - limits->maximum.emplace(maximum); - } - - return true; -} - -bool -wasm::DecodeUnknownSections(Decoder& d) -{ - while (!d.done()) { - if (!d.skipUserDefinedSection()) - return false; - } - - return true; -} diff --git a/js/src/asmjs/WasmBinary.h b/js/src/asmjs/WasmBinary.h index 40ad205f73f3..8771eff95d39 100644 --- a/js/src/asmjs/WasmBinary.h +++ b/js/src/asmjs/WasmBinary.h @@ -109,6 +109,8 @@ enum class ValType Limit }; +typedef Vector ValTypeVector; + enum class TypeConstructor { AnyFunc = 0x20, @@ -1072,31 +1074,6 @@ class Decoder } }; -// Reusable macro encoding/decoding functions reused by both the two -// encoders (AsmJS/WasmText) and decoders (Wasm/WasmIonCompile). - -typedef Vector ValTypeVector; - -MOZ_MUST_USE bool -DecodePreamble(Decoder& d); - -MOZ_MUST_USE bool -EncodeLocalEntries(Encoder& d, const ValTypeVector& locals); - -MOZ_MUST_USE bool -DecodeLocalEntries(Decoder& d, ValTypeVector* locals); - -MOZ_MUST_USE bool -DecodeGlobalType(Decoder& d, ValType* type, uint32_t* flags); - -struct Limits; - -MOZ_MUST_USE bool -DecodeLimits(Decoder& d, Limits* limits); - -MOZ_MUST_USE bool -DecodeUnknownSections(Decoder& d); - } // namespace wasm } // namespace js diff --git a/js/src/asmjs/WasmBinaryFormat.cpp b/js/src/asmjs/WasmBinaryFormat.cpp new file mode 100644 index 000000000000..c88b70821431 --- /dev/null +++ b/js/src/asmjs/WasmBinaryFormat.cpp @@ -0,0 +1,222 @@ +/* -*- 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 2016 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. + */ + +#include "asmjs/WasmBinaryFormat.h" + +using namespace js; +using namespace js::wasm; + +bool +wasm::DecodePreamble(Decoder& d) +{ + uint32_t u32; + if (!d.readFixedU32(&u32) || u32 != MagicNumber) + return d.fail("failed to match magic number"); + + if (!d.readFixedU32(&u32) || u32 != EncodingVersion) + return d.fail("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32, + u32, EncodingVersion); + + return true; +} + +bool +wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals) +{ + uint32_t numLocalEntries = 0; + ValType prev = ValType::Limit; + for (ValType t : locals) { + if (t != prev) { + numLocalEntries++; + prev = t; + } + } + + if (!e.writeVarU32(numLocalEntries)) + return false; + + if (numLocalEntries) { + prev = locals[0]; + uint32_t count = 1; + for (uint32_t i = 1; i < locals.length(); i++, count++) { + if (prev != locals[i]) { + if (!e.writeVarU32(count)) + return false; + if (!e.writeValType(prev)) + return false; + prev = locals[i]; + count = 0; + } + } + if (!e.writeVarU32(count)) + return false; + if (!e.writeValType(prev)) + return false; + } + + return true; +} + +bool +wasm::DecodeLocalEntries(Decoder& d, ValTypeVector* locals) +{ + uint32_t numLocalEntries; + if (!d.readVarU32(&numLocalEntries)) + return false; + + for (uint32_t i = 0; i < numLocalEntries; i++) { + uint32_t count; + if (!d.readVarU32(&count)) + return false; + + if (MaxLocals - locals->length() < count) + return false; + + ValType type; + if (!d.readValType(&type)) + return false; + + if (!locals->appendN(type, count)) + return false; + } + + return true; +} + +bool +wasm::DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable) +{ + if (!d.readValType(type)) + return d.fail("bad global type"); + + uint32_t flags; + if (!d.readVarU32(&flags)) + return d.fail("expected global flags"); + + if (flags & ~uint32_t(GlobalFlags::AllowedMask)) + return d.fail("unexpected bits set in global flags"); + + *isMutable = flags & uint32_t(GlobalFlags::IsMutable); + return true; +} + +bool +wasm::DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected, + InitExpr* init) +{ + Expr expr; + if (!d.readExpr(&expr)) + return d.fail("failed to read initializer type"); + + switch (expr) { + case Expr::I32Const: { + int32_t i32; + if (!d.readVarS32(&i32)) + return d.fail("failed to read initializer i32 expression"); + *init = InitExpr(Val(uint32_t(i32))); + break; + } + case Expr::I64Const: { + int64_t i64; + if (!d.readVarS64(&i64)) + return d.fail("failed to read initializer i64 expression"); + *init = InitExpr(Val(uint64_t(i64))); + break; + } + case Expr::F32Const: { + RawF32 f32; + if (!d.readFixedF32(&f32)) + return d.fail("failed to read initializer f32 expression"); + *init = InitExpr(Val(f32)); + break; + } + case Expr::F64Const: { + RawF64 f64; + if (!d.readFixedF64(&f64)) + return d.fail("failed to read initializer f64 expression"); + *init = InitExpr(Val(f64)); + break; + } + case Expr::GetGlobal: { + uint32_t i; + if (!d.readVarU32(&i)) + return d.fail("failed to read get_global index in initializer expression"); + if (i >= globals.length()) + return d.fail("global index out of range in initializer expression"); + if (!globals[i].isImport() || globals[i].isMutable()) + return d.fail("initializer expression must reference a global immutable import"); + *init = InitExpr(i, globals[i].type()); + break; + } + default: { + return d.fail("unexpected initializer expression"); + } + } + + if (expected != init->type()) + return d.fail("type mismatch: initializer type and expected type don't match"); + + Expr end; + if (!d.readExpr(&end) || end != Expr::End) + return d.fail("failed to read end of initializer expression"); + + return true; +} + +bool +wasm::DecodeLimits(Decoder& d, Limits* limits) +{ + uint32_t flags; + if (!d.readVarU32(&flags)) + return d.fail("expected flags"); + + // TODO (bug 1310149): tighten this check (s/3/1) when the AngryBots demo + // gets updated. + if (flags & ~uint32_t(0x3)) + return d.fail("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x3))); + + if (!d.readVarU32(&limits->initial)) + return d.fail("expected initial length"); + + if (flags & 0x1) { + uint32_t maximum; + if (!d.readVarU32(&maximum)) + return d.fail("expected maximum length"); + + if (limits->initial > maximum) { + return d.fail("memory size minimum must not be greater than maximum; " + "maximum length %" PRIu32 " is less than initial length %" PRIu32, + maximum, limits->initial); + } + + limits->maximum.emplace(maximum); + } + + return true; +} + +bool +wasm::DecodeUnknownSections(Decoder& d) +{ + while (!d.done()) { + if (!d.skipUserDefinedSection()) + return false; + } + + return true; +} diff --git a/js/src/asmjs/WasmBinaryFormat.h b/js/src/asmjs/WasmBinaryFormat.h new file mode 100644 index 000000000000..33ff94abf3cb --- /dev/null +++ b/js/src/asmjs/WasmBinaryFormat.h @@ -0,0 +1,57 @@ +/* -*- 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 2016 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_binary_format_h +#define wasm_binary_format_h + +#include "asmjs/WasmBinary.h" +#include "asmjs/WasmTypes.h" + +namespace js { +namespace wasm { + +// Reusable macro encoding/decoding functions reused by both the two +// encoders (AsmJS/WasmTextToBinary) and all the decoders +// (WasmCompile/WasmIonCompile/WasmBaselineCompile/WasmBinaryToText). + +MOZ_MUST_USE bool +DecodePreamble(Decoder& d); + +MOZ_MUST_USE bool +EncodeLocalEntries(Encoder& d, const ValTypeVector& locals); + +MOZ_MUST_USE bool +DecodeLocalEntries(Decoder& d, ValTypeVector* locals); + +MOZ_MUST_USE bool +DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable); + +MOZ_MUST_USE bool +DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected, + InitExpr* init); + +MOZ_MUST_USE bool +DecodeLimits(Decoder& d, Limits* limits); + +MOZ_MUST_USE bool +DecodeUnknownSections(Decoder& d); + +} // namespace wasm +} // namespace js + +#endif // wasm_binary_format_h diff --git a/js/src/asmjs/WasmBinaryToAST.cpp b/js/src/asmjs/WasmBinaryToAST.cpp index 1569d3f8fc1a..01ba7e68f7ec 100644 --- a/js/src/asmjs/WasmBinaryToAST.cpp +++ b/js/src/asmjs/WasmBinaryToAST.cpp @@ -24,6 +24,7 @@ #include "jscntxt.h" +#include "asmjs/WasmBinaryFormat.h" #include "asmjs/WasmBinaryIterator.h" using namespace js; @@ -1599,15 +1600,12 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import) } case uint32_t(DefinitionKind::Global): { ValType type; - if (!c.d.readValType(&type)) - return false; - - uint32_t flags; - if (!c.d.readVarU32(&flags)) + bool isMutable; + if (!DecodeGlobalType(c.d, &type, &isMutable)) return false; *import = new(c.lifo) AstImport(importName, moduleName, fieldName, - AstGlobal(importName, type, flags)); + AstGlobal(importName, type, isMutable)); break; } case uint32_t(DefinitionKind::Table): { @@ -1768,15 +1766,15 @@ AstDecodeGlobal(AstDecodeContext& c, uint32_t i, AstGlobal* global) return false; ValType type; - uint32_t flags; - if (!DecodeGlobalType(c.d, &type, &flags)) + bool isMutable; + if (!DecodeGlobalType(c.d, &type, &isMutable)) return false; AstExpr* init; if (!AstDecodeInitializerExpression(c, &init, type)) return c.d.fail("missing initializer expression"); - *global = AstGlobal(name, type, flags, Some(init)); + *global = AstGlobal(name, type, isMutable, Some(init)); return true; } diff --git a/js/src/asmjs/WasmCompile.cpp b/js/src/asmjs/WasmCompile.cpp index 3579035051e1..e541fd1ebbd5 100644 --- a/js/src/asmjs/WasmCompile.cpp +++ b/js/src/asmjs/WasmCompile.cpp @@ -22,6 +22,7 @@ #include "jsprf.h" +#include "asmjs/WasmBinaryFormat.h" #include "asmjs/WasmBinaryIterator.h" #include "asmjs/WasmGenerator.h" #include "asmjs/WasmSignalHandlers.h" @@ -712,10 +713,9 @@ DecodeImport(Decoder& d, ModuleGeneratorData* init, ImportVector* imports) } case DefinitionKind::Global: { ValType type; - uint32_t flags; - if (!DecodeGlobalType(d, &type, &flags)) + bool isMutable; + if (!DecodeGlobalType(d, &type, &isMutable)) return false; - bool isMutable = flags & uint32_t(GlobalFlags::IsMutable); if (!GlobalIsJSCompatible(d, type, isMutable)) return false; if (!init->globals.append(GlobalDesc(type, isMutable, init->globals.length()))) @@ -806,69 +806,6 @@ DecodeMemorySection(Decoder& d, ModuleGeneratorData* init, bool* exported) return true; } -static bool -DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected, - InitExpr* init) -{ - Expr expr; - if (!d.readExpr(&expr)) - return d.fail("failed to read initializer type"); - - switch (expr) { - case Expr::I32Const: { - int32_t i32; - if (!d.readVarS32(&i32)) - return d.fail("failed to read initializer i32 expression"); - *init = InitExpr(Val(uint32_t(i32))); - break; - } - case Expr::I64Const: { - int64_t i64; - if (!d.readVarS64(&i64)) - return d.fail("failed to read initializer i64 expression"); - *init = InitExpr(Val(uint64_t(i64))); - break; - } - case Expr::F32Const: { - RawF32 f32; - if (!d.readFixedF32(&f32)) - return d.fail("failed to read initializer f32 expression"); - *init = InitExpr(Val(f32)); - break; - } - case Expr::F64Const: { - RawF64 f64; - if (!d.readFixedF64(&f64)) - return d.fail("failed to read initializer f64 expression"); - *init = InitExpr(Val(f64)); - break; - } - case Expr::GetGlobal: { - uint32_t i; - if (!d.readVarU32(&i)) - return d.fail("failed to read get_global index in initializer expression"); - if (i >= globals.length()) - return d.fail("global index out of range in initializer expression"); - if (!globals[i].isImport() || globals[i].isMutable()) - return d.fail("initializer expression must reference a global immutable import"); - *init = InitExpr(i, globals[i].type()); - break; - } - default: { - return d.fail("unexpected initializer expression"); - } - } - - if (expected != init->type()) - return d.fail("type mismatch: initializer type and expected type don't match"); - - Expr end; - if (!d.readExpr(&end) || end != Expr::End) - return d.fail("failed to read end of initializer expression"); - - return true; -} - static bool DecodeGlobalSection(Decoder& d, ModuleGeneratorData* init) { @@ -887,15 +824,14 @@ DecodeGlobalSection(Decoder& d, ModuleGeneratorData* init) for (uint32_t i = 0; i < numGlobals; i++) { ValType type; - uint32_t flags; - if (!DecodeGlobalType(d, &type, &flags)) + bool isMutable; + if (!DecodeGlobalType(d, &type, &isMutable)) return false; InitExpr initializer; if (!DecodeInitializerExpression(d, init->globals, type, &initializer)) return false; - bool isMutable = flags & uint32_t(GlobalFlags::IsMutable); if (!init->globals.append(GlobalDesc(initializer, isMutable))) return false; } diff --git a/js/src/asmjs/WasmIonCompile.cpp b/js/src/asmjs/WasmIonCompile.cpp index d8d9b57dc400..29a59db8eee0 100644 --- a/js/src/asmjs/WasmIonCompile.cpp +++ b/js/src/asmjs/WasmIonCompile.cpp @@ -21,6 +21,7 @@ #include "mozilla/MathAlgorithms.h" #include "asmjs/WasmBaselineCompile.h" +#include "asmjs/WasmBinaryFormat.h" #include "asmjs/WasmBinaryIterator.h" #include "asmjs/WasmGenerator.h" #include "asmjs/WasmSignalHandlers.h" diff --git a/js/src/asmjs/WasmTextToBinary.cpp b/js/src/asmjs/WasmTextToBinary.cpp index 6ac574544680..5b02b95b44ee 100644 --- a/js/src/asmjs/WasmTextToBinary.cpp +++ b/js/src/asmjs/WasmTextToBinary.cpp @@ -28,7 +28,7 @@ #include "jsstr.h" #include "asmjs/WasmAST.h" -#include "asmjs/WasmBinary.h" +#include "asmjs/WasmBinaryFormat.h" #include "asmjs/WasmTypes.h" #include "ds/LifoAlloc.h" #include "js/CharacterEncoding.h" @@ -2844,12 +2844,14 @@ ParseStartFunc(WasmParseContext& c, WasmToken token, AstModule* module) } static bool -ParseGlobalType(WasmParseContext& c, WasmToken* typeToken, uint32_t* flags) +ParseGlobalType(WasmParseContext& c, WasmToken* typeToken, bool* isMutable) { + *isMutable = false; + // Either (mut i32) or i32. if (c.ts.getIf(WasmToken::OpenParen)) { // Immutable by default. - *flags = c.ts.getIf(WasmToken::Mutable) ? 0x1 : 0x0; + *isMutable = c.ts.getIf(WasmToken::Mutable); if (!c.ts.match(WasmToken::ValueType, typeToken, c.error)) return false; if (!c.ts.match(WasmToken::CloseParen, c.error)) @@ -2919,14 +2921,14 @@ ParseImport(WasmParseContext& c, AstModule* module) name = c.ts.getIfName(); WasmToken typeToken; - uint32_t flags = 0; - if (!ParseGlobalType(c, &typeToken, &flags)) + bool isMutable; + if (!ParseGlobalType(c, &typeToken, &isMutable)) return nullptr; if (!c.ts.match(WasmToken::CloseParen, c.error)) return nullptr; return new(c.lifo) AstImport(name, moduleName.text(), fieldName.text(), - AstGlobal(AstName(), typeToken.valueType(), flags)); + AstGlobal(AstName(), typeToken.valueType(), isMutable)); } if (c.ts.getIf(WasmToken::Func)) { if (name.empty()) @@ -3156,7 +3158,7 @@ ParseGlobal(WasmParseContext& c, AstModule* module) AstName name = c.ts.getIfName(); WasmToken typeToken; - uint32_t flags = 0; + bool isMutable; WasmToken openParen; if (c.ts.getIf(WasmToken::OpenParen, &openParen)) { @@ -3172,11 +3174,12 @@ ParseGlobal(WasmParseContext& c, AstModule* module) if (!c.ts.match(WasmToken::CloseParen, c.error)) return false; - if (!ParseGlobalType(c, &typeToken, &flags)) + if (!ParseGlobalType(c, &typeToken, &isMutable)) return false; auto* imp = new(c.lifo) AstImport(name, names.module.text(), names.field.text(), - AstGlobal(AstName(), typeToken.valueType(), flags)); + AstGlobal(AstName(), typeToken.valueType(), + isMutable)); return imp && module->append(imp); } @@ -3193,14 +3196,14 @@ ParseGlobal(WasmParseContext& c, AstModule* module) } } - if (!ParseGlobalType(c, &typeToken, &flags)) + if (!ParseGlobalType(c, &typeToken, &isMutable)) return false; AstExpr* init = ParseExpr(c, true); if (!init) return false; - auto* glob = new(c.lifo) AstGlobal(name, typeToken.valueType(), flags, Some(init)); + auto* glob = new(c.lifo) AstGlobal(name, typeToken.valueType(), isMutable, Some(init)); return glob && module->append(glob); } @@ -4310,6 +4313,13 @@ EncodeTableLimits(Encoder& e, const Limits& limits) return EncodeLimits(e, limits); } +static bool +EncodeGlobalType(Encoder& e, const AstGlobal* global) +{ + return e.writeValType(global->type()) && + e.writeVarU32(global->isMutable() ? uint32_t(GlobalFlags::IsMutable) : 0); +} + static bool EncodeImport(Encoder& e, AstImport& imp) { @@ -4329,9 +4339,7 @@ EncodeImport(Encoder& e, AstImport& imp) break; case DefinitionKind::Global: MOZ_ASSERT(!imp.global().hasInit()); - if (!e.writeValType(imp.global().type())) - return false; - if (!e.writeVarU32(imp.global().flags())) + if (!EncodeGlobalType(e, &imp.global())) return false; break; case DefinitionKind::Table: @@ -4406,9 +4414,7 @@ EncodeGlobalSection(Encoder& e, AstModule& module) for (const AstGlobal* global : globals) { MOZ_ASSERT(global->hasInit()); - if (!e.writeValType(global->type())) - return false; - if (!e.writeVarU32(global->flags())) + if (!EncodeGlobalType(e, global)) return false; if (!EncodeExpr(e, global->init())) return false; diff --git a/js/src/moz.build b/js/src/moz.build index 546a396753a7..4e0e6e6f5c40 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -157,6 +157,7 @@ UNIFIED_SOURCES += [ 'asmjs/AsmJS.cpp', 'asmjs/WasmBaselineCompile.cpp', 'asmjs/WasmBinary.cpp', + 'asmjs/WasmBinaryFormat.cpp', 'asmjs/WasmBinaryIterator.cpp', 'asmjs/WasmBinaryToAST.cpp', 'asmjs/WasmBinaryToExperimentalText.cpp',