Bug 1618198 part 26 - Support Debugger and Instrumentation* ops. r=iain
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 25 Mar 2020 06:57:18 +0000
changeset 520332 6eddc9bce7b1fe9e07d59a79918d2386a94ddd01
parent 520331 7172c878c66e6b997d823ce37c6f9491e856bbae
child 520333 e46d85e1e43994d66cc5f4d78fd6b401570e2f94
push id37248
push userbtara@mozilla.com
push dateWed, 25 Mar 2020 16:40:49 +0000
treeherdermozilla-central@c5112a7573ac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersiain
bugs1618198
milestone76.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 1618198 part 26 - Support Debugger and Instrumentation* ops. r=iain Note that the resumeAt in IonBuilder for JSOp::Debugger made little sense: MDebugger bails out if an onDebuggerStatement hook is active but that uses the previous resume point and not the one attached there. Strictly speaking MDebugger isn't effectful at all so it doesn't need a resume point, but changing getAliasSet is probably not worth it. Unfortunately the instrumentation callback can be nursery allocated. For now WarpOracle aborts compilation in this case, I think that's fine considering the instrumentation machinery isn't really used anymore. Finally, maybe in the future WarpOracle should allocate WarpScriptSnapshot upfront so we don't need a constructor with many parameters. Differential Revision: https://phabricator.services.mozilla.com/D68004
js/src/jit/IonBuilder.cpp
js/src/jit/WarpBuilder.cpp
js/src/jit/WarpBuilder.h
js/src/jit/WarpOracle.cpp
js/src/jit/WarpOracle.h
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -12702,23 +12702,21 @@ AbortReasonOr<Ok> IonBuilder::jsop_insta
 
   current->add(ins);
   current->push(ins);
 
   return resumeAfter(ins);
 }
 
 AbortReasonOr<Ok> IonBuilder::jsop_debugger() {
+  // The |debugger;| statement will bail out to Baseline if the realm is a
+  // debuggee realm with an onDebuggerStatement hook.
   MDebugger* debugger = MDebugger::New(alloc());
   current->add(debugger);
-
-  // The |debugger;| statement will always bail out to baseline if
-  // cx->compartment()->isDebuggee(). Resume in-place and have baseline
-  // handle the details.
-  return resumeAt(debugger, pc);
+  return resumeAfter(debugger);
 }
 
 AbortReasonOr<Ok> IonBuilder::jsop_implicitthis(PropertyName* name) {
   MOZ_ASSERT(usesEnvironmentChain());
 
   MImplicitThis* implicitThis =
       MImplicitThis::New(alloc(), current->environmentChain(), name);
   current->add(implicitThis);
--- a/js/src/jit/WarpBuilder.cpp
+++ b/js/src/jit/WarpBuilder.cpp
@@ -2355,8 +2355,34 @@ bool WarpBuilder::build_SpreadSuperCall(
 bool WarpBuilder::build_OptimizeSpreadCall(BytecodeLocation loc) {
   // TODO: like IonBuilder's slow path always deoptimize for now. Consider using
   // an IC for this so that we can optimize by inlining Baseline's CacheIR.
   MDefinition* arr = current->peek(-1);
   arr->setImplicitlyUsedUnchecked();
   pushConstant(BooleanValue(false));
   return true;
 }
+
+bool WarpBuilder::build_Debugger(BytecodeLocation loc) {
+  // The |debugger;| statement will bail out to Baseline if the realm is a
+  // debuggee realm with an onDebuggerStatement hook.
+  MDebugger* debugger = MDebugger::New(alloc());
+  current->add(debugger);
+  return resumeAfter(debugger, loc);
+}
+
+bool WarpBuilder::build_InstrumentationActive(BytecodeLocation) {
+  bool active = snapshot_.script()->instrumentationActive();
+  pushConstant(BooleanValue(active));
+  return true;
+}
+
+bool WarpBuilder::build_InstrumentationCallback(BytecodeLocation) {
+  JSObject* callback = snapshot_.script()->instrumentationCallback();
+  pushConstant(ObjectValue(*callback));
+  return true;
+}
+
+bool WarpBuilder::build_InstrumentationScriptId(BytecodeLocation) {
+  int32_t scriptId = snapshot_.script()->instrumentationScriptId();
+  pushConstant(Int32Value(scriptId));
+  return true;
+}
--- a/js/src/jit/WarpBuilder.h
+++ b/js/src/jit/WarpBuilder.h
@@ -12,209 +12,213 @@
 #include "jit/MIRBuilderShared.h"
 #include "jit/WarpOracle.h"
 
 namespace js {
 namespace jit {
 
 // JS bytecode ops supported by WarpBuilder. Once we support most opcodes
 // this should be replaced with the FOR_EACH_OPCODE macro.
-#define WARP_OPCODE_LIST(_) \
-  _(Nop)                    \
-  _(NopDestructuring)       \
-  _(TryDestructuring)       \
-  _(Lineno)                 \
-  _(DebugLeaveLexicalEnv)   \
-  _(Undefined)              \
-  _(Void)                   \
-  _(Null)                   \
-  _(Hole)                   \
-  _(Uninitialized)          \
-  _(IsConstructing)         \
-  _(False)                  \
-  _(True)                   \
-  _(Zero)                   \
-  _(One)                    \
-  _(Int8)                   \
-  _(Uint16)                 \
-  _(Uint24)                 \
-  _(Int32)                  \
-  _(Double)                 \
-  _(ResumeIndex)            \
-  _(BigInt)                 \
-  _(String)                 \
-  _(Symbol)                 \
-  _(RegExp)                 \
-  _(Pop)                    \
-  _(PopN)                   \
-  _(Dup)                    \
-  _(Dup2)                   \
-  _(DupAt)                  \
-  _(Swap)                   \
-  _(Pick)                   \
-  _(Unpick)                 \
-  _(GetLocal)               \
-  _(SetLocal)               \
-  _(InitLexical)            \
-  _(GetArg)                 \
-  _(SetArg)                 \
-  _(ToNumeric)              \
-  _(Inc)                    \
-  _(Dec)                    \
-  _(Neg)                    \
-  _(BitNot)                 \
-  _(Add)                    \
-  _(Sub)                    \
-  _(Mul)                    \
-  _(Div)                    \
-  _(Mod)                    \
-  _(Pow)                    \
-  _(BitAnd)                 \
-  _(BitOr)                  \
-  _(BitXor)                 \
-  _(Lsh)                    \
-  _(Rsh)                    \
-  _(Ursh)                   \
-  _(Eq)                     \
-  _(Ne)                     \
-  _(Lt)                     \
-  _(Le)                     \
-  _(Gt)                     \
-  _(Ge)                     \
-  _(StrictEq)               \
-  _(StrictNe)               \
-  _(JumpTarget)             \
-  _(LoopHead)               \
-  _(IfEq)                   \
-  _(IfNe)                   \
-  _(And)                    \
-  _(Or)                     \
-  _(Case)                   \
-  _(Default)                \
-  _(Coalesce)               \
-  _(Goto)                   \
-  _(DebugCheckSelfHosted)   \
-  _(DynamicImport)          \
-  _(Not)                    \
-  _(ToString)               \
-  _(DefVar)                 \
-  _(DefLet)                 \
-  _(DefConst)               \
-  _(DefFun)                 \
-  _(BindVar)                \
-  _(MutateProto)            \
-  _(Callee)                 \
-  _(ClassConstructor)       \
-  _(DerivedConstructor)     \
-  _(ToAsyncIter)            \
-  _(ToId)                   \
-  _(Typeof)                 \
-  _(TypeofExpr)             \
-  _(Arguments)              \
-  _(ObjWithProto)           \
-  _(GetAliasedVar)          \
-  _(SetAliasedVar)          \
-  _(InitAliasedLexical)     \
-  _(EnvCallee)              \
-  _(Iter)                   \
-  _(IterNext)               \
-  _(MoreIter)               \
-  _(EndIter)                \
-  _(IsNoIter)               \
-  _(Call)                   \
-  _(CallIgnoresRv)          \
-  _(CallIter)               \
-  _(FunCall)                \
-  _(FunApply)               \
-  _(New)                    \
-  _(SuperCall)              \
-  _(FunctionThis)           \
-  _(GlobalThis)             \
-  _(GetName)                \
-  _(GetGName)               \
-  _(BindName)               \
-  _(BindGName)              \
-  _(GetProp)                \
-  _(CallProp)               \
-  _(Length)                 \
-  _(GetElem)                \
-  _(CallElem)               \
-  _(SetProp)                \
-  _(StrictSetProp)          \
-  _(SetName)                \
-  _(StrictSetName)          \
-  _(SetGName)               \
-  _(StrictSetGName)         \
-  _(InitGLexical)           \
-  _(SetElem)                \
-  _(StrictSetElem)          \
-  _(DelProp)                \
-  _(StrictDelProp)          \
-  _(DelElem)                \
-  _(StrictDelElem)          \
-  _(SetFunName)             \
-  _(PushLexicalEnv)         \
-  _(PopLexicalEnv)          \
-  _(FreshenLexicalEnv)      \
-  _(RecreateLexicalEnv)     \
-  _(ImplicitThis)           \
-  _(GImplicitThis)          \
-  _(CheckClassHeritage)     \
-  _(CheckThis)              \
-  _(CheckThisReinit)        \
-  _(CheckReturn)            \
-  _(CheckLexical)           \
-  _(CheckAliasedLexical)    \
-  _(InitHomeObject)         \
-  _(SuperBase)              \
-  _(SuperFun)               \
-  _(BuiltinProto)           \
-  _(GetIntrinsic)           \
-  _(ImportMeta)             \
-  _(CallSiteObj)            \
-  _(NewArray)               \
-  _(NewArrayCopyOnWrite)    \
-  _(NewObject)              \
-  _(NewObjectWithGroup)     \
-  _(NewInit)                \
-  _(Object)                 \
-  _(InitPropGetter)         \
-  _(InitPropSetter)         \
-  _(InitHiddenPropGetter)   \
-  _(InitHiddenPropSetter)   \
-  _(InitElemGetter)         \
-  _(InitElemSetter)         \
-  _(InitHiddenElemGetter)   \
-  _(InitHiddenElemSetter)   \
-  _(In)                     \
-  _(HasOwn)                 \
-  _(Instanceof)             \
-  _(NewTarget)              \
-  _(CheckIsObj)             \
-  _(CheckIsCallable)        \
-  _(CheckObjCoercible)      \
-  _(GetImport)              \
-  _(GetPropSuper)           \
-  _(GetElemSuper)           \
-  _(InitProp)               \
-  _(InitLockedProp)         \
-  _(InitHiddenProp)         \
-  _(InitElem)               \
-  _(InitHiddenElem)         \
-  _(InitElemArray)          \
-  _(InitElemInc)            \
-  _(Lambda)                 \
-  _(LambdaArrow)            \
-  _(FunWithProto)           \
-  _(SpreadCall)             \
-  _(SpreadNew)              \
-  _(SpreadSuperCall)        \
-  _(OptimizeSpreadCall)     \
-  _(SetRval)                \
-  _(Return)                 \
+#define WARP_OPCODE_LIST(_)  \
+  _(Nop)                     \
+  _(NopDestructuring)        \
+  _(TryDestructuring)        \
+  _(Lineno)                  \
+  _(DebugLeaveLexicalEnv)    \
+  _(Undefined)               \
+  _(Void)                    \
+  _(Null)                    \
+  _(Hole)                    \
+  _(Uninitialized)           \
+  _(IsConstructing)          \
+  _(False)                   \
+  _(True)                    \
+  _(Zero)                    \
+  _(One)                     \
+  _(Int8)                    \
+  _(Uint16)                  \
+  _(Uint24)                  \
+  _(Int32)                   \
+  _(Double)                  \
+  _(ResumeIndex)             \
+  _(BigInt)                  \
+  _(String)                  \
+  _(Symbol)                  \
+  _(RegExp)                  \
+  _(Pop)                     \
+  _(PopN)                    \
+  _(Dup)                     \
+  _(Dup2)                    \
+  _(DupAt)                   \
+  _(Swap)                    \
+  _(Pick)                    \
+  _(Unpick)                  \
+  _(GetLocal)                \
+  _(SetLocal)                \
+  _(InitLexical)             \
+  _(GetArg)                  \
+  _(SetArg)                  \
+  _(ToNumeric)               \
+  _(Inc)                     \
+  _(Dec)                     \
+  _(Neg)                     \
+  _(BitNot)                  \
+  _(Add)                     \
+  _(Sub)                     \
+  _(Mul)                     \
+  _(Div)                     \
+  _(Mod)                     \
+  _(Pow)                     \
+  _(BitAnd)                  \
+  _(BitOr)                   \
+  _(BitXor)                  \
+  _(Lsh)                     \
+  _(Rsh)                     \
+  _(Ursh)                    \
+  _(Eq)                      \
+  _(Ne)                      \
+  _(Lt)                      \
+  _(Le)                      \
+  _(Gt)                      \
+  _(Ge)                      \
+  _(StrictEq)                \
+  _(StrictNe)                \
+  _(JumpTarget)              \
+  _(LoopHead)                \
+  _(IfEq)                    \
+  _(IfNe)                    \
+  _(And)                     \
+  _(Or)                      \
+  _(Case)                    \
+  _(Default)                 \
+  _(Coalesce)                \
+  _(Goto)                    \
+  _(DebugCheckSelfHosted)    \
+  _(DynamicImport)           \
+  _(Not)                     \
+  _(ToString)                \
+  _(DefVar)                  \
+  _(DefLet)                  \
+  _(DefConst)                \
+  _(DefFun)                  \
+  _(BindVar)                 \
+  _(MutateProto)             \
+  _(Callee)                  \
+  _(ClassConstructor)        \
+  _(DerivedConstructor)      \
+  _(ToAsyncIter)             \
+  _(ToId)                    \
+  _(Typeof)                  \
+  _(TypeofExpr)              \
+  _(Arguments)               \
+  _(ObjWithProto)            \
+  _(GetAliasedVar)           \
+  _(SetAliasedVar)           \
+  _(InitAliasedLexical)      \
+  _(EnvCallee)               \
+  _(Iter)                    \
+  _(IterNext)                \
+  _(MoreIter)                \
+  _(EndIter)                 \
+  _(IsNoIter)                \
+  _(Call)                    \
+  _(CallIgnoresRv)           \
+  _(CallIter)                \
+  _(FunCall)                 \
+  _(FunApply)                \
+  _(New)                     \
+  _(SuperCall)               \
+  _(FunctionThis)            \
+  _(GlobalThis)              \
+  _(GetName)                 \
+  _(GetGName)                \
+  _(BindName)                \
+  _(BindGName)               \
+  _(GetProp)                 \
+  _(CallProp)                \
+  _(Length)                  \
+  _(GetElem)                 \
+  _(CallElem)                \
+  _(SetProp)                 \
+  _(StrictSetProp)           \
+  _(SetName)                 \
+  _(StrictSetName)           \
+  _(SetGName)                \
+  _(StrictSetGName)          \
+  _(InitGLexical)            \
+  _(SetElem)                 \
+  _(StrictSetElem)           \
+  _(DelProp)                 \
+  _(StrictDelProp)           \
+  _(DelElem)                 \
+  _(StrictDelElem)           \
+  _(SetFunName)              \
+  _(PushLexicalEnv)          \
+  _(PopLexicalEnv)           \
+  _(FreshenLexicalEnv)       \
+  _(RecreateLexicalEnv)      \
+  _(ImplicitThis)            \
+  _(GImplicitThis)           \
+  _(CheckClassHeritage)      \
+  _(CheckThis)               \
+  _(CheckThisReinit)         \
+  _(CheckReturn)             \
+  _(CheckLexical)            \
+  _(CheckAliasedLexical)     \
+  _(InitHomeObject)          \
+  _(SuperBase)               \
+  _(SuperFun)                \
+  _(BuiltinProto)            \
+  _(GetIntrinsic)            \
+  _(ImportMeta)              \
+  _(CallSiteObj)             \
+  _(NewArray)                \
+  _(NewArrayCopyOnWrite)     \
+  _(NewObject)               \
+  _(NewObjectWithGroup)      \
+  _(NewInit)                 \
+  _(Object)                  \
+  _(InitPropGetter)          \
+  _(InitPropSetter)          \
+  _(InitHiddenPropGetter)    \
+  _(InitHiddenPropSetter)    \
+  _(InitElemGetter)          \
+  _(InitElemSetter)          \
+  _(InitHiddenElemGetter)    \
+  _(InitHiddenElemSetter)    \
+  _(In)                      \
+  _(HasOwn)                  \
+  _(Instanceof)              \
+  _(NewTarget)               \
+  _(CheckIsObj)              \
+  _(CheckIsCallable)         \
+  _(CheckObjCoercible)       \
+  _(GetImport)               \
+  _(GetPropSuper)            \
+  _(GetElemSuper)            \
+  _(InitProp)                \
+  _(InitLockedProp)          \
+  _(InitHiddenProp)          \
+  _(InitElem)                \
+  _(InitHiddenElem)          \
+  _(InitElemArray)           \
+  _(InitElemInc)             \
+  _(Lambda)                  \
+  _(LambdaArrow)             \
+  _(FunWithProto)            \
+  _(SpreadCall)              \
+  _(SpreadNew)               \
+  _(SpreadSuperCall)         \
+  _(OptimizeSpreadCall)      \
+  _(Debugger)                \
+  _(InstrumentationActive)   \
+  _(InstrumentationCallback) \
+  _(InstrumentationScriptId) \
+  _(SetRval)                 \
+  _(Return)                  \
   _(RetRval)
 
 class MIRGenerator;
 class MIRGraph;
 class WarpSnapshot;
 
 // WarpBuilder builds a MIR graph from WarpSnapshot. Unlike WarpOracle,
 // WarpBuilder can run off-thread.
--- a/js/src/jit/WarpOracle.cpp
+++ b/js/src/jit/WarpOracle.cpp
@@ -8,16 +8,17 @@
 
 #include "mozilla/ScopeExit.h"
 
 #include "jit/JitScript.h"
 #include "jit/MIRGenerator.h"
 #include "jit/WarpBuilder.h"
 #include "vm/BytecodeIterator.h"
 #include "vm/BytecodeLocation.h"
+#include "vm/Instrumentation.h"
 
 #include "vm/BytecodeIterator-inl.h"
 #include "vm/BytecodeLocation-inl.h"
 #include "vm/EnvironmentObject-inl.h"
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 using namespace js::jit;
@@ -144,24 +145,29 @@ AbortReasonOr<WarpEnvironment> WarpOracl
     }
     namedLambdaTemplate = &templateEnv->as<LexicalEnvironmentObject>();
   }
 
   env.initFunction(callObjectTemplate, namedLambdaTemplate);
   return env;
 }
 
-WarpScriptSnapshot::WarpScriptSnapshot(JSScript* script,
-                                       const WarpEnvironment& env,
-                                       WarpOpSnapshotList&& opSnapshots,
-                                       ModuleObject* moduleObject)
+WarpScriptSnapshot::WarpScriptSnapshot(
+    JSScript* script, const WarpEnvironment& env,
+    WarpOpSnapshotList&& opSnapshots, ModuleObject* moduleObject,
+    JSObject* instrumentationCallback,
+    mozilla::Maybe<int32_t> instrumentationScriptId,
+    mozilla::Maybe<bool> instrumentationActive)
     : script_(script),
       environment_(env),
       opSnapshots_(std::move(opSnapshots)),
       moduleObject_(moduleObject),
+      instrumentationCallback_(instrumentationCallback),
+      instrumentationScriptId_(instrumentationScriptId),
+      instrumentationActive_(instrumentationActive),
       isArrowFunction_(script->isFunction() && script->function()->isArrow()) {}
 
 AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
     HandleScript script) {
   MOZ_ASSERT(script->hasJitScript());
 
   if (!script->jitScript()->ensureHasCachedIonData(cx_, script)) {
     return abort(AbortReason::Error);
@@ -173,16 +179,20 @@ AbortReasonOr<WarpScriptSnapshot*> WarpO
   // Unfortunately LinkedList<> asserts the list is empty in its destructor.
   // Clear the list if we abort compilation.
   WarpOpSnapshotList opSnapshots;
   auto autoClearOpSnapshots =
       mozilla::MakeScopeExit([&] { opSnapshots.clear(); });
 
   ModuleObject* moduleObject = nullptr;
 
+  mozilla::Maybe<bool> instrumentationActive;
+  mozilla::Maybe<int32_t> instrumentationScriptId;
+  JSObject* instrumentationCallback = nullptr;
+
   // Analyze the bytecode to look for opcodes we can't compile yet. Eventually
   // this loop will also be responsible for copying IC data.
   for (BytecodeLocation loc : AllBytecodesIterable(script)) {
     JSOp op = loc.getOp();
     switch (op) {
 #define OP_CASE(OP) case JSOp::OP:
       WARP_OPCODE_LIST(OP_CASE)
 #undef OP_CASE
@@ -335,23 +345,63 @@ AbortReasonOr<WarpScriptSnapshot*> WarpO
         if (mirGen_.instrumentedProfiling()) {
           return abort(AbortReason::Disable,
                        "GetElemSuper with profiling is not supported on x86");
         }
 #endif
         break;
       }
 
+      case JSOp::InstrumentationActive: {
+        // All IonScripts in the realm are discarded when instrumentation
+        // activity changes, so we can treat the value we get as a constant.
+        if (instrumentationActive.isNothing()) {
+          bool active = RealmInstrumentation::isActive(cx_->global());
+          instrumentationActive.emplace(active);
+        }
+        break;
+      }
+
+      case JSOp::InstrumentationCallback: {
+        if (!instrumentationCallback) {
+          JSObject* obj = RealmInstrumentation::getCallback(cx_->global());
+          if (IsInsideNursery(obj)) {
+            // Unfortunately the callback can be nursery allocated. If this
+            // becomes an issue we should consider triggering a minor GC after
+            // installing it.
+            return abort(AbortReason::Disable,
+                         "Nursery-allocated instrumentation callback");
+          }
+          instrumentationCallback = obj;
+        }
+        break;
+      }
+
+      case JSOp::InstrumentationScriptId: {
+        // Getting the script ID requires interacting with the Debugger used for
+        // instrumentation, but cannot run script.
+        if (instrumentationScriptId.isNothing()) {
+          int32_t id = 0;
+          if (!RealmInstrumentation::getScriptId(cx_, cx_->global(), script,
+                                                 &id)) {
+            return abort(AbortReason::Error);
+          }
+          instrumentationScriptId.emplace(id);
+        }
+        break;
+      }
+
       default:
         break;
     }
   }
 
   auto* scriptSnapshot = new (alloc_.fallible()) WarpScriptSnapshot(
-      script, environment, std::move(opSnapshots), moduleObject);
+      script, environment, std::move(opSnapshots), moduleObject,
+      instrumentationCallback, instrumentationScriptId, instrumentationActive);
   if (!scriptSnapshot) {
     return abort(AbortReason::Alloc);
   }
 
   autoClearOpSnapshots.release();
 
   return scriptSnapshot;
 }
--- a/js/src/jit/WarpOracle.h
+++ b/js/src/jit/WarpOracle.h
@@ -232,28 +232,45 @@ class WarpScriptSnapshot : public TempOb
   JSScript* script_;
   WarpEnvironment environment_;
   WarpOpSnapshotList opSnapshots_;
 
   // If the script has a JSOp::ImportMeta op, this is the module to bake in.
   // TODO: trace this
   ModuleObject* moduleObject_;
 
+  // Constants pushed by JSOp::Instrumentation* ops in the script.
+  // TODO: trace this
+  JSObject* instrumentationCallback_;
+  mozilla::Maybe<int32_t> instrumentationScriptId_;
+  mozilla::Maybe<bool> instrumentationActive_;
+
   // Whether this script is for an arrow function.
   bool isArrowFunction_;
 
  public:
   WarpScriptSnapshot(JSScript* script, const WarpEnvironment& env,
                      WarpOpSnapshotList&& opSnapshots,
-                     ModuleObject* moduleObject);
+                     ModuleObject* moduleObject,
+                     JSObject* instrumentationCallback,
+                     mozilla::Maybe<int32_t> instrumentationScriptId,
+                     mozilla::Maybe<bool> instrumentationActive);
 
   JSScript* script() const { return script_; }
   const WarpEnvironment& environment() const { return environment_; }
   const WarpOpSnapshotList& opSnapshots() const { return opSnapshots_; }
   ModuleObject* moduleObject() const { return moduleObject_; }
+
+  JSObject* instrumentationCallback() const {
+    MOZ_ASSERT(instrumentationCallback_);
+    return instrumentationCallback_;
+  }
+  int32_t instrumentationScriptId() const { return *instrumentationScriptId_; }
+  bool instrumentationActive() const { return *instrumentationActive_; }
+
   bool isArrowFunction() const { return isArrowFunction_; }
 };
 
 // Data allocated by WarpOracle on the main thread that's used off-thread by
 // WarpBuilder to build the MIR graph.
 //
 // TODO: trace op snapshots in IonCompileTask::trace (like MRootList for
 // non-Warp).