Bug 1566607 - Add SelfHostedLazyScript type to hold trampoline pointer. r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Wed, 17 Jul 2019 13:37:52 +0000
changeset 483299 e4bf7a4c4bbfafdf2a973b8d541cba0c50308f43
parent 483298 3f2f72c37e4ee29bbfabb71a9cff72f05c8578e1
child 483300 b88fad4496c51d4e63a5ba14d1a3534bb2c8e31f
push id36313
push useropoprus@mozilla.com
push dateThu, 18 Jul 2019 21:50:51 +0000
treeherdermozilla-central@5fceb8c496bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1566607
milestone70.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 1566607 - Add SelfHostedLazyScript type to hold trampoline pointer. r=jandem A lazy self-hosted function has neither a JSScript nor a LazyScript. This patch adds a SelfHostedLazyScript type with a jitCodeRaw that allows these functions to called directly by JIT via the interpreter trampoline. Only one instance per Runtime is needed. Differential Revision: https://phabricator.services.mozilla.com/D38253
js/src/jit/Ion.cpp
js/src/jit/MacroAssembler.cpp
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -219,16 +219,21 @@ bool JitRuntime::initialize(JSContext* c
   if (!jitcodeGlobalTable_) {
     return false;
   }
 
   if (!GenerateBaselineInterpreter(cx, baselineInterpreter_)) {
     return false;
   }
 
+  // Initialize the jitCodeRaw of the Runtime's canonical SelfHostedLazyScript
+  // to point to the interpreter trampoline.
+  cx->runtime()->selfHostedLazyScript.ref().jitCodeRaw_ =
+      interpreterStub().value;
+
   return true;
 }
 
 bool JitRuntime::generateTrampolines(JSContext* cx) {
   StackMacroAssembler masm;
 
   Label bailoutTail;
   JitSpew(JitSpew_Codegen, "# Emitting bailout tail stub");
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1672,16 +1672,20 @@ void MacroAssembler::assertRectifierFram
   }
 #endif
 }
 
 void MacroAssembler::loadJitCodeRaw(Register func, Register dest) {
   static_assert(
       JSScript::offsetOfJitCodeRaw() == LazyScript::offsetOfJitCodeRaw(),
       "LazyScript and JSScript must use same layout for jitCodeRaw_");
+  static_assert(
+      JSScript::offsetOfJitCodeRaw() ==
+          SelfHostedLazyScript::offsetOfJitCodeRaw(),
+      "SelfHostedLazyScript and JSScript must use same layout for jitCodeRaw_");
   loadPtr(Address(func, JSFunction::offsetOfScript()), dest);
   loadPtr(Address(dest, JSScript::offsetOfJitCodeRaw()), dest);
 }
 
 void MacroAssembler::loadJitCodeNoArgCheck(Register func, Register dest) {
   loadPtr(Address(func, JSFunction::offsetOfScript()), dest);
   loadPtr(Address(dest, JSScript::offsetOfJitScript()), dest);
   loadPtr(Address(dest, JitScript::offsetOfJitCodeSkipArgCheck()), dest);
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -104,16 +104,17 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
       destroyRealmCallback(nullptr),
       realmNameCallback(nullptr),
       externalStringSizeofCallback(nullptr),
       securityCallbacks(&NullSecurityCallbacks),
       DOMcallbacks(nullptr),
       destroyPrincipals(nullptr),
       readPrincipals(nullptr),
       warningReporter(nullptr),
+      selfHostedLazyScript(),
       geckoProfiler_(thisFromCtor()),
       trustedPrincipals_(nullptr),
       wrapObjectCallbacks(&DefaultWrapObjectCallbacks),
       preserveWrapperCallback(nullptr),
       scriptEnvironmentPreparer(nullptr),
       ctypesActivityCallback(nullptr),
       windowProxyClass_(nullptr),
       scriptDataLock(mutexid::RuntimeScriptData),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -211,16 +211,33 @@ inline bool CanUseExtraThreads() {
 }
 
 void DisableExtraThreads();
 
 using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
 
 class AutoLockScriptData;
 
+// Self-hosted lazy functions do not maintain a LazyScript as we can compile
+// from the copy in the self-hosting zone. To allow these functions to be
+// called by the JITs, we need a minimal script object. There is one instance
+// per runtime.
+struct SelfHostedLazyScript {
+  SelfHostedLazyScript() = default;
+
+  // Pointer to interpreter trampoline. This field is stored at same location
+  // as in JSScript, allowing the JIT to directly call LazyScripts in the same
+  // way as JSScripts.
+  uint8_t* jitCodeRaw_ = nullptr;
+
+  static constexpr size_t offsetOfJitCodeRaw() {
+    return offsetof(SelfHostedLazyScript, jitCodeRaw_);
+  }
+};
+
 }  // namespace js
 
 struct JSRuntime : public js::MallocProvider<JSRuntime> {
  private:
   friend class js::Activation;
   friend class js::ActivationIterator;
   friend class js::jit::JitActivation;
   friend class js::jit::CompileRuntime;
@@ -379,16 +396,21 @@ struct JSRuntime : public js::MallocProv
   js::MainThreadData<const JSSecurityCallbacks*> securityCallbacks;
   js::MainThreadData<const js::DOMCallbacks*> DOMcallbacks;
   js::MainThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
   js::MainThreadData<JSReadPrincipalsOp> readPrincipals;
 
   /* Optional warning reporter. */
   js::MainThreadData<JS::WarningReporter> warningReporter;
 
+  // Lazy self-hosted functions use a shared SelfHostedLazyScript instead
+  // instead of a LazyScript. This contains the minimal trampolines for the
+  // scripts to perform direct calls.
+  js::UnprotectedData<js::SelfHostedLazyScript> selfHostedLazyScript;
+
  private:
   /* Gecko profiling metadata */
   js::UnprotectedData<js::GeckoProfilerRuntime> geckoProfiler_;
 
  public:
   js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); }
 
   // Heap GC roots for PersistentRooted pointers.