Bug 1317319: Factor out Table section decoding; r=luke
authorBenjamin Bouvier <benj@benj.me>
Mon, 14 Nov 2016 16:44:21 +0100
changeset 323049 75b417fb952fb20d3dec91949e653d015600015e
parent 323048 49305a317143402c791b71d667c0b1ca9c512e0b
child 323050 5b9544a7f1d8598f37cbe9f8b7302b84f775c82d
push id30967
push userphilringnalda@gmail.com
push dateFri, 18 Nov 2016 03:21:38 +0000
treeherdermozilla-central@8e476f8bd52d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1317319
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1317319: Factor out Table section decoding; r=luke MozReview-Commit-ID: LGioDvK655t
js/src/wasm/WasmBinaryFormat.cpp
js/src/wasm/WasmBinaryFormat.h
js/src/wasm/WasmBinaryToAST.cpp
js/src/wasm/WasmCompile.cpp
--- a/js/src/wasm/WasmBinaryFormat.cpp
+++ b/js/src/wasm/WasmBinaryFormat.cpp
@@ -168,30 +168,63 @@ DecodeSignatureIndex(Decoder& d, const S
         return d.fail("expected signature index");
 
     if (*sigIndex >= sigs.length())
         return d.fail("signature index out of range");
 
     return true;
 }
 
-bool
-wasm::DecodeTableLimits(Decoder& d, TableDescVector* tables)
+static bool
+DecodeLimits(Decoder& d, Limits* limits)
+{
+    uint32_t flags;
+    if (!d.readVarU32(&flags))
+        return d.fail("expected flags");
+
+    if (flags & ~uint32_t(0x1))
+        return d.fail("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x1)));
+
+    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;
+}
+
+static bool
+DecodeTableLimits(Decoder& d, TableDescVector* tables)
 {
     uint32_t elementType;
     if (!d.readVarU32(&elementType))
         return d.fail("expected table element type");
 
     if (elementType != uint32_t(TypeCode::AnyFunc))
         return d.fail("expected 'anyfunc' element type");
 
     Limits limits;
     if (!DecodeLimits(d, &limits))
         return false;
 
+    if (limits.initial > MaxTableElems)
+        return d.fail("too many table elements");
+
     if (tables->length())
         return d.fail("already have default table");
 
     return tables->emplaceBack(TableKind::AnyFunction, limits);
 }
 
 bool
 wasm::GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable)
@@ -211,16 +244,44 @@ wasm::GlobalIsJSCompatible(Decoder& d, V
 
     if (isMutable)
         return d.fail("can't import/export mutable globals in the MVP");
 
     return true;
 }
 
 static bool
+DecodeMemoryLimits(Decoder& d, bool hasMemory, Limits* memory)
+{
+    if (hasMemory)
+        return d.fail("already have default memory");
+
+    if (!DecodeLimits(d, memory))
+        return false;
+
+    CheckedInt<uint32_t> initialBytes = memory->initial;
+    initialBytes *= PageSize;
+    if (!initialBytes.isValid() || initialBytes.value() > uint32_t(INT32_MAX))
+        return d.fail("initial memory size too big");
+
+    memory->initial = initialBytes.value();
+
+    if (memory->maximum) {
+        CheckedInt<uint32_t> maximumBytes = *memory->maximum;
+        maximumBytes *= PageSize;
+        if (!maximumBytes.isValid())
+            return d.fail("maximum memory size too big");
+
+        memory->maximum = Some(maximumBytes.value());
+    }
+
+    return true;
+}
+
+static bool
 DecodeImport(Decoder& d, const SigWithIdVector& sigs, Uint32Vector* funcSigIndices,
              GlobalDescVector* globals, TableDescVector* tables, Maybe<Limits>* memory,
              ImportVector* imports)
 {
     UniqueChars moduleName = DecodeName(d);
     if (!moduleName)
         return d.fail("expected valid import module name");
 
@@ -332,16 +393,70 @@ wasm::DecodeFunctionSection(Decoder& d, 
 
     if (!d.finishSection(sectionStart, sectionSize, "function"))
         return false;
 
     return true;
 }
 
 bool
+wasm::DecodeTableSection(Decoder& d, TableDescVector* tables)
+{
+    uint32_t sectionStart, sectionSize;
+    if (!d.startSection(SectionId::Table, &sectionStart, &sectionSize, "table"))
+        return false;
+    if (sectionStart == Decoder::NotStarted)
+        return true;
+
+    uint32_t numTables;
+    if (!d.readVarU32(&numTables))
+        return d.fail("failed to read number of tables");
+
+    if (numTables != 1)
+        return d.fail("the number of tables must be exactly one");
+
+    if (!DecodeTableLimits(d, tables))
+        return false;
+
+    if (!d.finishSection(sectionStart, sectionSize, "table"))
+        return false;
+
+    return true;
+}
+
+bool
+wasm::DecodeMemorySection(Decoder& d, bool hasMemory, Limits* memory, bool *present)
+{
+    *present = false;
+
+    uint32_t sectionStart, sectionSize;
+    if (!d.startSection(SectionId::Memory, &sectionStart, &sectionSize, "memory"))
+        return false;
+    if (sectionStart == Decoder::NotStarted)
+        return true;
+
+    *present = true;
+
+    uint32_t numMemories;
+    if (!d.readVarU32(&numMemories))
+        return d.fail("failed to read number of memories");
+
+    if (numMemories != 1)
+        return d.fail("the number of memories must be exactly one");
+
+    if (!DecodeMemoryLimits(d, hasMemory, memory))
+        return false;
+
+    if (!d.finishSection(sectionStart, sectionSize, "memory"))
+        return false;
+
+    return true;
+}
+
+bool
 wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals)
 {
     uint32_t numLocalEntries = 0;
     ValType prev = ValType(TypeCode::Limit);
     for (ValType t : locals) {
         if (t != prev) {
             numLocalEntries++;
             prev = t;
@@ -475,46 +590,16 @@ wasm::DecodeInitializerExpression(Decode
     uint16_t end;
     if (!d.readOp(&end) || end != uint16_t(Op::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");
-
-    if (flags & ~uint32_t(0x1))
-        return d.fail("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x1)));
-
-    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::DecodeDataSection(Decoder& d, bool usesMemory, uint32_t minMemoryByteLength,
                         const GlobalDescVector& globals, DataSegmentVector* segments)
 {
     uint32_t sectionStart, sectionSize;
     if (!d.startSection(SectionId::Data, &sectionStart, &sectionSize, "data"))
         return false;
     if (sectionStart == Decoder::NotStarted)
         return true;
@@ -555,73 +640,16 @@ wasm::DecodeDataSection(Decoder& d, bool
 
     if (!d.finishSection(sectionStart, sectionSize, "data"))
         return false;
 
     return true;
 }
 
 bool
-wasm::DecodeMemoryLimits(Decoder& d, bool hasMemory, Limits* memory)
-{
-    if (hasMemory)
-        return d.fail("already have default memory");
-
-    if (!DecodeLimits(d, memory))
-        return false;
-
-    CheckedInt<uint32_t> initialBytes = memory->initial;
-    initialBytes *= PageSize;
-    if (!initialBytes.isValid() || initialBytes.value() > uint32_t(INT32_MAX))
-        return d.fail("initial memory size too big");
-
-    memory->initial = initialBytes.value();
-
-    if (memory->maximum) {
-        CheckedInt<uint32_t> maximumBytes = *memory->maximum;
-        maximumBytes *= PageSize;
-        if (!maximumBytes.isValid())
-            return d.fail("maximum memory size too big");
-
-        memory->maximum = Some(maximumBytes.value());
-    }
-
-    return true;
-}
-
-bool
-wasm::DecodeMemorySection(Decoder& d, bool hasMemory, Limits* memory, bool *present)
-{
-    *present = false;
-
-    uint32_t sectionStart, sectionSize;
-    if (!d.startSection(SectionId::Memory, &sectionStart, &sectionSize, "memory"))
-        return false;
-    if (sectionStart == Decoder::NotStarted)
-        return true;
-
-    *present = true;
-
-    uint32_t numMemories;
-    if (!d.readVarU32(&numMemories))
-        return d.fail("failed to read number of memories");
-
-    if (numMemories != 1)
-        return d.fail("the number of memories must be exactly one");
-
-    if (!DecodeMemoryLimits(d, hasMemory, memory))
-        return false;
-
-    if (!d.finishSection(sectionStart, sectionSize, "memory"))
-        return false;
-
-    return true;
-}
-
-bool
 wasm::DecodeUnknownSections(Decoder& d)
 {
     while (!d.done()) {
         if (!d.skipUserDefinedSection())
             return false;
     }
 
     return true;
--- a/js/src/wasm/WasmBinaryFormat.h
+++ b/js/src/wasm/WasmBinaryFormat.h
@@ -623,40 +623,31 @@ class Decoder
 // (WasmCompile/WasmIonCompile/WasmBaselineCompile/WasmBinaryToText).
 
 // Misc helpers.
 
 UniqueChars
 DecodeName(Decoder& d);
 
 MOZ_MUST_USE bool
-DecodeTableLimits(Decoder& d, TableDescVector* tables);
-
-MOZ_MUST_USE bool
 GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable);
 
 MOZ_MUST_USE bool
 EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
 
 MOZ_MUST_USE bool
 DecodeLocalEntries(Decoder& d, ModuleKind kind, 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
-DecodeMemoryLimits(Decoder& d, bool hasMemory, Limits* memory);
-
 // Section macros.
 
 MOZ_MUST_USE bool
 DecodePreamble(Decoder& d);
 
 MOZ_MUST_USE bool
 DecodeTypeSection(Decoder& d, SigWithIdVector* sigs);
 
@@ -665,21 +656,24 @@ DecodeImportSection(Decoder& d, const Si
                     GlobalDescVector* globals, TableDescVector* tables, Maybe<Limits>* memory,
                     ImportVector* imports);
 
 MOZ_MUST_USE bool
 DecodeFunctionSection(Decoder& d, const SigWithIdVector& sigs, size_t numImportedFunc,
                       Uint32Vector* funcSigIndexes);
 
 MOZ_MUST_USE bool
+DecodeTableSection(Decoder& d, TableDescVector* tables);
+
+MOZ_MUST_USE bool
+DecodeMemorySection(Decoder& d, bool hasMemory, Limits* memory, bool* present);
+
+MOZ_MUST_USE bool
 DecodeUnknownSections(Decoder& d);
 
 MOZ_MUST_USE bool
 DecodeDataSection(Decoder& d, bool usesMemory, uint32_t minMemoryByteLength,
                   const GlobalDescVector& globals, DataSegmentVector* segments);
 
-MOZ_MUST_USE bool
-DecodeMemorySection(Decoder& d, bool hasMemory, Limits* memory, bool* present);
-
 } // namespace wasm
 } // namespace js
 
 #endif // wasm_binary_format_h
--- a/js/src/wasm/WasmBinaryToAST.cpp
+++ b/js/src/wasm/WasmBinaryToAST.cpp
@@ -1465,24 +1465,23 @@ ToAstName(AstDecodeContext& c, const Uni
 
     for (size_t i = 0; i < len; i++)
         buffer[i] = name.get()[i];
 
     return AstName(buffer, len);
 }
 
 static bool
-AstDecodeImportSection(AstDecodeContext& c, const SigWithIdVector& sigs)
+AstDecodeImportSection(AstDecodeContext& c, const SigWithIdVector& sigs, TableDescVector* tables)
 {
     Uint32Vector funcSigIndices;
     GlobalDescVector globals;
-    TableDescVector tables;
     Maybe<Limits> memory;
     ImportVector imports;
-    if (!DecodeImportSection(c.d, sigs, &funcSigIndices, &globals, &tables, &memory, &imports))
+    if (!DecodeImportSection(c.d, sigs, &funcSigIndices, &globals, tables, &memory, &imports))
         return false;
 
     size_t lastFunc = 0;
     size_t lastGlobal = 0;
     size_t lastTable = 0;
     size_t lastMemory = 0;
 
     for (size_t importIndex = 0; importIndex < imports.length(); importIndex++) {
@@ -1524,17 +1523,17 @@ AstDecodeImportSection(AstDecodeContext&
             break;
           }
           case DefinitionKind::Table: {
             AstName importName;
             if (!GenerateName(c, AstName(u"table"), lastTable, &importName))
                 return false;
 
             ast = new(c.lifo) AstImport(importName, moduleName, fieldName, DefinitionKind::Table,
-                                        tables[lastTable].limits);
+                                        (*tables)[lastTable].limits);
             lastTable++;
             break;
           }
           case DefinitionKind::Memory: {
             AstName importName;
             if (!GenerateName(c, AstName(u"memory"), lastMemory, &importName))
                 return false;
 
@@ -1558,57 +1557,33 @@ AstDecodeFunctionSection(AstDecodeContex
     Uint32Vector funcSigIndexes;
     if (!DecodeFunctionSection(c.d, sigs, c.module().numFuncImports(), &funcSigIndexes))
         return false;
 
     return c.funcDefSigs().appendAll(funcSigIndexes);
 }
 
 static bool
-AstDecodeTableSection(AstDecodeContext& c)
+AstDecodeTableSection(AstDecodeContext& c, TableDescVector* tables)
 {
-    uint32_t sectionStart, sectionSize;
-    if (!c.d.startSection(SectionId::Table, &sectionStart, &sectionSize, "table"))
+    size_t numImported = tables->length();
+    if (!DecodeTableSection(c.d, tables))
         return false;
-    if (sectionStart == Decoder::NotStarted)
+
+    if (tables->length() == numImported)
         return true;
 
-    uint32_t numTables;
-    if (!c.d.readVarU32(&numTables))
-        return c.d.fail("failed to read number of tables");
-
-    if (numTables != 1)
-        return c.d.fail("the number of tables must be exactly one");
-
-    uint32_t typeConstructorValue;
-    if (!c.d.readVarU32(&typeConstructorValue))
-        return c.d.fail("expected type constructor kind");
-
-    if (typeConstructorValue != uint32_t(TypeCode::AnyFunc))
-        return c.d.fail("unknown type constructor kind");
+    for (size_t i = 0; i < tables->length(); i++) {
+        AstName name;
+        if (!GenerateName(c, AstName(u"table"), i, &name))
+            return false;
 
-    Limits table;
-    if (!DecodeLimits(c.d, &table))
-        return false;
-
-    if (table.initial > MaxTableElems)
-        return c.d.fail("too many table elements");
-
-    if (c.module().hasTable())
-        return c.d.fail("already have a table");
-
-    AstName name;
-    if (!GenerateName(c, AstName(u"table"), c.module().tables().length(), &name))
-        return false;
-
-    if (!c.module().addTable(name, table))
-        return false;
-
-    if (!c.d.finishSection(sectionStart, sectionSize, "table"))
-        return false;
+        if (!c.module().addTable(name, (*tables)[i].limits))
+            return false;
+    }
 
     return true;
 }
 
 static bool
 AstDecodeName(AstDecodeContext& c, AstName* name)
 {
     uint32_t length;
@@ -2032,21 +2007,22 @@ wasm::BinaryToAst(JSContext* cx, const u
     if (!result->init())
         return false;
 
     UniqueChars error;
     Decoder d(bytes, bytes + length, &error);
     AstDecodeContext c(cx, lifo, d, *result, true);
 
     SigWithIdVector sigs;
+    TableDescVector tables;
     if (!DecodePreamble(d) ||
         !AstDecodeTypeSection(c, &sigs) ||
-        !AstDecodeImportSection(c, sigs) ||
+        !AstDecodeImportSection(c, sigs, &tables) ||
         !AstDecodeFunctionSection(c, sigs) ||
-        !AstDecodeTableSection(c) ||
+        !AstDecodeTableSection(c, &tables) ||
         !AstDecodeMemorySection(c) ||
         !AstDecodeGlobalSection(c) ||
         !AstDecodeExportSection(c) ||
         !AstDecodeStartSection(c) ||
         !AstDecodeElemSection(c) ||
         !AstDecodeCodeSection(c) ||
         !AstDecodeDataSection(c) ||
         !DecodeUnknownSections(c.d))
--- a/js/src/wasm/WasmCompile.cpp
+++ b/js/src/wasm/WasmCompile.cpp
@@ -449,41 +449,16 @@ DecodeFunctionSection(Decoder& d, Module
 
     for (uint32_t sigIndex : funcSigIndexes)
         init->funcSigs.infallibleAppend(&init->sigs[sigIndex]);
 
     return true;
 }
 
 static bool
-DecodeTableSection(Decoder& d, ModuleGeneratorData* init)
-{
-    uint32_t sectionStart, sectionSize;
-    if (!d.startSection(SectionId::Table, &sectionStart, &sectionSize, "table"))
-        return false;
-    if (sectionStart == Decoder::NotStarted)
-        return true;
-
-    uint32_t numTables;
-    if (!d.readVarU32(&numTables))
-        return d.fail("failed to read number of tables");
-
-    if (numTables != 1)
-        return d.fail("the number of tables must be exactly one");
-
-    if (!DecodeTableLimits(d, &init->tables))
-        return false;
-
-    if (!d.finishSection(sectionStart, sectionSize, "table"))
-        return false;
-
-    return true;
-}
-
-static bool
 DecodeMemorySection(Decoder& d, ModuleGeneratorData* init)
 {
     bool present;
     Limits memory;
     if (!DecodeMemorySection(d, UsesMemory(init->memoryUsage), &memory, &present))
         return false;
 
     if (present) {
@@ -917,17 +892,17 @@ wasm::Compile(const ShareableBytes& byte
 
     ImportVector imports;
     if (!::DecodeImportSection(d, init.get(), &imports))
         return nullptr;
 
     if (!::DecodeFunctionSection(d, init.get()))
         return nullptr;
 
-    if (!DecodeTableSection(d, init.get()))
+    if (!DecodeTableSection(d, &init->tables))
         return nullptr;
 
     if (!::DecodeMemorySection(d, init.get()))
         return nullptr;
 
     if (!DecodeGlobalSection(d, init.get()))
         return nullptr;