Bug 1520931 - Baldr: another follow-up simplification from asm.js caching removal (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Mon, 18 Feb 2019 17:12:31 -0600
changeset 459828 10030bd8ac3dd4d0333aae3a44ecfbbe5bb75bec
parent 459827 2c2e488c86cedcdc12ece404440669a992e2ce14
child 459829 e772a34b885e0f84118d347cd822265d5ed66810
push id35575
push usercbrindusan@mozilla.com
push dateTue, 19 Feb 2019 04:40:03 +0000
treeherdermozilla-central@ee6e77950205 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1520931
milestone67.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 1520931 - Baldr: another follow-up simplification from asm.js caching removal (r=bbouvier)
js/src/wasm/AsmJS.cpp
js/src/wasm/WasmCompile.cpp
js/src/wasm/WasmCompile.h
js/src/wasm/WasmGenerator.cpp
js/src/wasm/WasmGenerator.h
js/src/wasm/WasmJS.cpp
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -2069,17 +2069,17 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED Modu
   }
 
   // Error handling.
   bool failCurrentOffset(const char* str) {
     return failOffset(tokenStream().anyCharsAccess().currentToken().pos.begin,
                       str);
   }
 
-  SharedModule finish(UniqueLinkData* linkData) {
+  SharedModule finish() {
     MOZ_ASSERT(env_.funcTypes.empty());
     if (!env_.funcTypes.resize(funcImportMap_.count() + funcDefs_.length())) {
       return nullptr;
     }
     for (FuncImportMap::Range r = funcImportMap_.all(); !r.empty();
          r.popFront()) {
       uint32_t funcIndex = r.front().value();
       MOZ_ASSERT(!env_.funcTypes[funcIndex]);
@@ -2162,17 +2162,17 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED Modu
         return nullptr;
       }
     }
 
     if (!mg.finishFuncDefs()) {
       return nullptr;
     }
 
-    return mg.finishModule(*bytes, nullptr, linkData);
+    return mg.finishModule(*bytes);
   }
 };
 
 /*****************************************************************************/
 // Numeric literal utilities
 
 static bool IsNumericNonFloatLiteral(ParseNode* pn) {
   // Note: '-' is never rolled into the number; numbers are always positive
@@ -6345,18 +6345,17 @@ static bool CheckModuleEnd(ModuleValidat
   }
 
   m.parser().tokenStream.anyCharsAccess().ungetToken();
   return true;
 }
 
 template <typename Unit>
 static SharedModule CheckModule(JSContext* cx, AsmJSParser<Unit>& parser,
-                                ParseNode* stmtList, UniqueLinkData* linkData,
-                                unsigned* time) {
+                                ParseNode* stmtList, unsigned* time) {
   int64_t before = PRMJ_Now();
 
   FunctionNode* moduleFunctionNode = parser.pc->functionBox()->functionNode;
 
   ModuleValidator<Unit> m(cx, parser, moduleFunctionNode);
   if (!m.init()) {
     return nullptr;
   }
@@ -6396,17 +6395,17 @@ static SharedModule CheckModule(JSContex
   if (!CheckModuleReturn(m)) {
     return nullptr;
   }
 
   if (!CheckModuleEnd(m)) {
     return nullptr;
   }
 
-  SharedModule module = m.finish(linkData);
+  SharedModule module = m.finish();
   if (!module) {
     return nullptr;
   }
 
   *time = (PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC;
   return module;
 }
 
@@ -7063,28 +7062,22 @@ static bool DoCompileAsmJS(JSContext* cx
                            ParseNode* stmtList, bool* validated) {
   *validated = false;
 
   // Various conditions disable asm.js optimizations.
   if (!EstablishPreconditions(cx, parser)) {
     return NoExceptionPending(cx);
   }
 
-  // Validate and generate code in a single linear pass over the chars of the
-  // asm.js module.
-  SharedModule module;
+  // "Checking" parses, validates and compiles, producing a fully compiled
+  // WasmModuleObject as result.
   unsigned time;
-  {
-    // "Checking" parses, validates and compiles, producing a fully compiled
-    // WasmModuleObject as result.
-    UniqueLinkData linkData;
-    module = CheckModule(cx, parser, stmtList, &linkData, &time);
-    if (!module) {
-      return NoExceptionPending(cx);
-    }
+  SharedModule module = CheckModule(cx, parser, stmtList, &time);
+  if (!module) {
+    return NoExceptionPending(cx);
   }
 
   // Hand over ownership to a GC object wrapper which can then be referenced
   // from the module function.
   Rooted<WasmModuleObject*> moduleObj(cx,
                                       WasmModuleObject::create(cx, *module));
   if (!moduleObj) {
     return false;
--- a/js/src/wasm/WasmCompile.cpp
+++ b/js/src/wasm/WasmCompile.cpp
@@ -546,17 +546,17 @@ static bool DecodeCodeSection(const Modu
 
   return mg.finishFuncDefs();
 }
 
 SharedModule wasm::CompileBuffer(const CompileArgs& args,
                                  const ShareableBytes& bytecode,
                                  UniqueChars* error,
                                  UniqueCharsVector* warnings,
-                                 UniqueLinkData* maybeLinkData) {
+                                 JS::OptimizedEncodingListener* listener) {
   Decoder d(bytecode.bytes, 0, error, warnings);
 
   CompilerEnvironment compilerEnv(args);
   ModuleEnvironment env(
       args.gcEnabled, &compilerEnv,
       args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
   if (!DecodeModuleEnvironment(d, &env)) {
     return nullptr;
@@ -570,17 +570,17 @@ SharedModule wasm::CompileBuffer(const C
   if (!DecodeCodeSection(env, d, mg)) {
     return nullptr;
   }
 
   if (!DecodeModuleTail(d, &env)) {
     return nullptr;
   }
 
-  return mg.finishModule(bytecode, nullptr, maybeLinkData);
+  return mg.finishModule(bytecode, listener);
 }
 
 void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
                         const Module& module, Atomic<bool>* cancelled) {
   UniqueChars error;
   Decoder d(bytecode, 0, &error);
 
   bool gcTypesConfigured = false;  // No optimized backend support yet
--- a/js/src/wasm/WasmCompile.h
+++ b/js/src/wasm/WasmCompile.h
@@ -90,17 +90,17 @@ double EstimateCompiledCodeSize(Tier tie
 // wasm::Module. On success, the Module is returned. On failure, the returned
 // SharedModule pointer is null and either:
 //  - *error points to a string description of the error
 //  - *error is null and the caller should report out-of-memory.
 
 SharedModule CompileBuffer(const CompileArgs& args,
                            const ShareableBytes& bytecode, UniqueChars* error,
                            UniqueCharsVector* warnings,
-                           UniqueLinkData* maybeLinkData = nullptr);
+                           JS::OptimizedEncodingListener* listener = nullptr);
 
 // Attempt to compile the second tier of the given wasm::Module.
 
 void CompileTier2(const CompileArgs& args, const Bytes& bytecode,
                   const Module& module, Atomic<bool>* cancelled);
 
 // Compile the given WebAssembly module which has been broken into three
 // partitions:
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -1089,18 +1089,17 @@ SharedMetadata ModuleGenerator::finishMe
   // Metadata shouldn't be mutably modified after finishMetadata().
   SharedMetadata metadata = metadata_;
   metadata_ = nullptr;
   return metadata;
 }
 
 SharedModule ModuleGenerator::finishModule(
     const ShareableBytes& bytecode,
-    JS::OptimizedEncodingListener* maybeTier2Listener,
-    UniqueLinkData* maybeLinkData) {
+    JS::OptimizedEncodingListener* maybeTier2Listener) {
   MOZ_ASSERT(mode() == CompileMode::Once || mode() == CompileMode::Tier1);
 
   UniqueCodeTier codeTier = finishCodeTier();
   if (!codeTier) {
     return nullptr;
   }
 
   JumpTables jumpTables;
@@ -1208,21 +1207,16 @@ SharedModule ModuleGenerator::finishModu
   }
 
   if (mode() == CompileMode::Tier1) {
     module->startTier2(*compileArgs_, bytecode, maybeTier2Listener);
   } else if (tier() == Tier::Serialized && maybeTier2Listener) {
     module->serialize(*linkData_, *maybeTier2Listener);
   }
 
-  if (maybeLinkData) {
-    MOZ_ASSERT(!env_->debugEnabled());
-    *maybeLinkData = std::move(linkData_);
-  }
-
   return module;
 }
 
 bool ModuleGenerator::finishTier2(const Module& module) {
   MOZ_ASSERT(mode() == CompileMode::Tier2);
   MOZ_ASSERT(tier() == Tier::Optimized);
   MOZ_ASSERT(!env_->debugEnabled());
 
--- a/js/src/wasm/WasmGenerator.h
+++ b/js/src/wasm/WasmGenerator.h
@@ -215,17 +215,16 @@ class MOZ_STACK_CLASS ModuleGenerator {
   MOZ_MUST_USE bool finishFuncDefs();
 
   // If env->mode is Once or Tier1, finishModule() must be called to generate
   // a new Module. Otherwise, if env->mode is Tier2, finishTier2() must be
   // called to augment the given Module with tier 2 code.
 
   SharedModule finishModule(
       const ShareableBytes& bytecode,
-      JS::OptimizedEncodingListener* maybeTier2Listener = nullptr,
-      UniqueLinkData* maybeLinkData = nullptr);
+      JS::OptimizedEncodingListener* maybeTier2Listener = nullptr);
   MOZ_MUST_USE bool finishTier2(const Module& module);
 };
 
 }  // namespace wasm
 }  // namespace js
 
 #endif  // wasm_generator_h
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -447,45 +447,61 @@ bool wasm::Eval(JSContext* cx, Handle<Ty
                   globalObjs.get(), &globals)) {
     return false;
   }
 
   return module->instantiate(cx, funcs, tables.get(), memory, globals,
                              globalObjs.get(), nullptr, instanceObj);
 }
 
+struct MOZ_STACK_CLASS SerializeListener : JS::OptimizedEncodingListener {
+  // MOZ_STACK_CLASS means these can be nops.
+  MozExternalRefCountType MOZ_XPCOM_ABI AddRef() override { return 0; }
+  MozExternalRefCountType MOZ_XPCOM_ABI Release() override { return 0; }
+
+  DebugOnly<bool> called = false;
+  Bytes* serialized;
+  SerializeListener(Bytes* serialized) : serialized(serialized) {}
+
+  void storeOptimizedEncoding(const uint8_t* bytes, size_t length) override {
+    MOZ_ASSERT(!called);
+    called = true;
+    if (serialized->resize(length)) {
+      memcpy(serialized->begin(), bytes, length);
+    }
+  }
+};
+
 bool wasm::CompileAndSerialize(const ShareableBytes& bytecode,
                                Bytes* serialized) {
   MutableCompileArgs compileArgs = js_new<CompileArgs>(ScriptedCaller());
   if (!compileArgs) {
     return false;
   }
 
-  // The caller has ensured HasCachingSupport().
+  // The caller has ensured HasCachingSupport(). Moreover, we want to ensure
+  // we go straight to tier-2 so that we synchronously call
+  // JS::OptimizedEncodingListener::storeOptimizedEncoding().
+  compileArgs->baselineEnabled = false;
   compileArgs->ionEnabled = true;
 
+  SerializeListener listener(serialized);
+
   UniqueChars error;
   UniqueCharsVector warnings;
-  UniqueLinkData linkData;
   SharedModule module =
-      CompileBuffer(*compileArgs, bytecode, &error, &warnings, &linkData);
+      CompileBuffer(*compileArgs, bytecode, &error, &warnings, &listener);
   if (!module) {
     fprintf(stderr, "Compilation error: %s\n", error ? error.get() : "oom");
     return false;
   }
 
   MOZ_ASSERT(module->code().hasTier(Tier::Serialized));
-
-  size_t serializedSize = module->serializedSize(*linkData);
-  if (!serialized->resize(serializedSize)) {
-    return false;
-  }
-
-  module->serialize(*linkData, serialized->begin(), serialized->length());
-  return true;
+  MOZ_ASSERT(listener.called);
+  return !listener.serialized->empty();
 }
 
 bool wasm::DeserializeModule(JSContext* cx, const Bytes& serialized,
                              MutableHandleObject moduleObj) {
   MutableModule module =
       Module::deserialize(serialized.begin(), serialized.length());
   if (!module) {
     ReportOutOfMemory(cx);