Bug 1486553 - Only set .external on the table if necessary. r=luke
authorLars T Hansen <lhansen@mozilla.com>
Mon, 27 Aug 2018 21:01:56 +0200
changeset 482176 24f835f7926dc9e789c9fd8d8e4675adb513d6ec
parent 482175 d87b294da56dc9f938f749c6d4b681083bc98f74
child 482177 9fcca8293f56756d32636b9cc36b4ffa9d0e3d0d
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewersluke
bugs1486553
milestone63.0a1
Bug 1486553 - Only set .external on the table if necessary. r=luke Previously we would unconditionally set the .external flag on a table if it had an element segment, but we should only do this if the table is initialized with an imported function and so may contain functions from multiple instances.
js/src/wasm/WasmTypes.h
js/src/wasm/WasmValidate.cpp
js/src/wasm/WasmValidate.h
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -1858,16 +1858,20 @@ struct Limits
 enum class TableKind
 {
     AnyFunction,
     TypedFunction
 };
 
 struct TableDesc
 {
+    // If a table is marked 'external' it is because it can contain functions
+    // from multiple instances; a table is therefore marked external if it is
+    // imported or exported or if it is initialized with an imported function.
+
     TableKind kind;
     bool external;
     uint32_t globalDataOffset;
     Limits limits;
 
     TableDesc() = default;
     TableDesc(TableKind kind, const Limits& limits)
      : kind(kind),
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -1812,17 +1812,17 @@ DecodeExport(Decoder& d, ModuleEnvironme
         uint32_t tableIndex;
         if (!d.readVarU32(&tableIndex))
             return d.fail("expected table index");
 
         if (tableIndex >= env->tables.length())
             return d.fail("exported table index out of bounds");
 
         MOZ_ASSERT(env->tables.length() == 1);
-        env->tables[0].external = true;
+        env->tables[tableIndex].external = true;
 
         return env->exports.emplaceBack(std::move(fieldName), DefinitionKind::Table);
       }
       case DefinitionKind::Memory: {
         uint32_t memoryIndex;
         if (!d.readVarU32(&memoryIndex))
             return d.fail("expected memory index");
 
@@ -1948,24 +1948,30 @@ DecodeElemSection(Decoder& d, ModuleEnvi
 
         Uint32Vector elemFuncIndices;
         if (!elemFuncIndices.resize(numElems))
             return false;
 
         for (uint32_t i = 0; i < numElems; i++) {
             if (!d.readVarU32(&elemFuncIndices[i]))
                 return d.fail("failed to read element function index");
-            if (elemFuncIndices[i] >= env->numFuncs())
+
+            uint32_t funcIndex = elemFuncIndices[i];
+            if (funcIndex >= env->numFuncs())
                 return d.fail("table element out of range");
+
+            // If a table element function value is imported then the table can
+            // contain functions from multiple instances and must be marked
+            // external.
+            if (env->funcIsImport(funcIndex))
+                env->tables[tableIndex].external = true;
         }
 
-        if (!env->elemSegments.emplaceBack(0, offset, std::move(elemFuncIndices)))
+        if (!env->elemSegments.emplaceBack(tableIndex, offset, std::move(elemFuncIndices)))
             return false;
-
-        env->tables[env->elemSegments.back().tableIndex].external = true;
     }
 
     return d.finishSection(*range, "elem");
 }
 
 bool
 wasm::StartsCodeSection(const uint8_t* begin, const uint8_t* end, SectionRange* codeSection)
 {
--- a/js/src/wasm/WasmValidate.h
+++ b/js/src/wasm/WasmValidate.h
@@ -72,20 +72,20 @@ struct ModuleEnvironment
     FuncTypeWithIdPtrVector   funcTypes;
     Uint32Vector              funcImportGlobalDataOffsets;
     GlobalDescVector          globals;
     TableDescVector           tables;
     Uint32Vector              asmJSSigToTableIndex;
     ImportVector              imports;
     ExportVector              exports;
     Maybe<uint32_t>           startFuncIndex;
+    ElemSegmentVector         elemSegments;
     MaybeSectionRange         codeSection;
 
     // Fields decoded as part of the wasm module tail:
-    ElemSegmentVector         elemSegments;
     DataSegmentVector         dataSegments;
     Maybe<NameInBytecode>     moduleName;
     NameInBytecodeVector      funcNames;
     CustomSectionVector       customSections;
 
     explicit ModuleEnvironment(CompileMode mode,
                                Tier tier,
                                DebugEnabled debug,