Bug 1528320 - Ensure correct record/replay progress flag after XDR-decoding a script, r=tcampbell.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 21 Feb 2019 17:32:59 -1000
changeset 460703 241d2964ae968a01928f5e8e4d734781fad1a546
parent 460559 31404c0c060e9ee2c46b56a199369a3e42d668e4
child 460704 b42cb063ba27b92ec36a8d9b0f98391a22be5be7
push id35597
push userrmaries@mozilla.com
push dateSat, 23 Feb 2019 04:15:57 +0000
treeherdermozilla-central@6924dd16f7b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1528320
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 1528320 - Ensure correct record/replay progress flag after XDR-decoding a script, r=tcampbell.
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineCompiler.h
js/src/jit/CompileInfo.h
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1546,16 +1546,27 @@ MOZ_MUST_USE bool BaselineCompilerCodeGe
   if (handler.script()->hasFlag(flag) == value) {
     return emit();
   }
   return true;
 }
 
 template <>
 template <typename F>
+MOZ_MUST_USE bool BaselineCompilerCodeGen::emitTestScriptFlag(
+    JSScript::MutableFlags flag, bool value, const F& emit,
+    Register scratch) {
+  if (handler.script()->hasFlag(flag) == value) {
+    return emit();
+  }
+  return true;
+}
+
+template <>
+template <typename F>
 MOZ_MUST_USE bool BaselineInterpreterCodeGen::emitTestScriptFlag(
     JSScript::ImmutableFlags flag, bool value, const F& emit,
     Register scratch) {
   Label done;
   loadScript(scratch);
   masm.branchTest32(value ? Assembler::Zero : Assembler::NonZero,
                     Address(scratch, JSScript::offsetOfImmutableFlags()),
                     Imm32(uint32_t(flag)), &done);
@@ -1564,16 +1575,36 @@ MOZ_MUST_USE bool BaselineInterpreterCod
       return false;
     }
   }
 
   masm.bind(&done);
   return true;
 }
 
+template <>
+template <typename F>
+MOZ_MUST_USE bool BaselineInterpreterCodeGen::emitTestScriptFlag(
+    JSScript::MutableFlags flag, bool value, const F& emit,
+    Register scratch) {
+  Label done;
+  loadScript(scratch);
+  masm.branchTest32(value ? Assembler::Zero : Assembler::NonZero,
+                    Address(scratch, JSScript::offsetOfMutableFlags()),
+                    Imm32(uint32_t(flag)), &done);
+  {
+    if (!emit()) {
+      return false;
+    }
+  }
+
+  masm.bind(&done);
+  return true;
+}
+
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_GOTO() {
   frame.syncStack(0);
   emitJump();
   return true;
 }
 
 template <typename Handler>
@@ -1717,17 +1748,17 @@ bool BaselineCodeGen<Handler>::emit_JSOP
     return false;
   }
 
   auto incCounter = [this]() {
     masm.inc64(
         AbsoluteAddress(mozilla::recordreplay::ExecutionProgressCounter()));
     return true;
   };
-  return emitTestScriptFlag(JSScript::ImmutableFlags::TrackRecordReplayProgress,
+  return emitTestScriptFlag(JSScript::MutableFlags::TrackRecordReplayProgress,
                             true, incCounter, R2.scratchReg());
 }
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_VOID() {
   frame.pop();
   frame.push(UndefinedValue());
   return true;
@@ -5850,17 +5881,17 @@ bool BaselineCodeGen<Handler>::emitProlo
   // on a bogus EnvironmentChain value in the frame.
   emitPreInitEnvironmentChain(R1.scratchReg());
 
   auto incCounter = [this]() {
     masm.inc64(
         AbsoluteAddress(mozilla::recordreplay::ExecutionProgressCounter()));
     return true;
   };
-  if (!emitTestScriptFlag(JSScript::ImmutableFlags::TrackRecordReplayProgress,
+  if (!emitTestScriptFlag(JSScript::MutableFlags::TrackRecordReplayProgress,
                           true, incCounter, R2.scratchReg())) {
     return false;
   }
 
   // Functions with a large number of locals require two stack checks.
   // The VMCall for a fallible stack check can only occur after the
   // env chain has been initialized, as that is required for proper
   // exception handling if the VMCall returns false.  The env chain
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -374,16 +374,20 @@ class BaselineCodeGen {
                                        const F1& ifSet, const F2& ifNotSet,
                                        Register scratch);
 
   // If |script->hasFlag(flag) == value|, execute the code emitted by |emit|.
   template <typename F>
   MOZ_MUST_USE bool emitTestScriptFlag(JSScript::ImmutableFlags flag,
                                        bool value, const F& emit,
                                        Register scratch);
+  template <typename F>
+  MOZ_MUST_USE bool emitTestScriptFlag(JSScript::MutableFlags flag,
+                                       bool value, const F& emit,
+                                       Register scratch);
 
   MOZ_MUST_USE bool emitCheckThis(ValueOperand val, bool reinit = false);
   void emitLoadReturnValue(ValueOperand val);
 
   MOZ_MUST_USE bool emitNextIC();
   MOZ_MUST_USE bool emitInterruptCheck();
   MOZ_MUST_USE bool emitWarmUpCounterIncrement();
   MOZ_MUST_USE bool emitTraceLoggerResume(Register script,
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -178,16 +178,17 @@ class CompileInfo {
       : script_(script),
         fun_(fun),
         osrPc_(osrPc),
         analysisMode_(analysisMode),
         scriptNeedsArgsObj_(scriptNeedsArgsObj),
         hadOverflowBailout_(script->hadOverflowBailout()),
         hadFrequentBailouts_(script->hadFrequentBailouts()),
         mayReadFrameArgsDirectly_(script->mayReadFrameArgsDirectly()),
+        trackRecordReplayProgress_(script->trackRecordReplayProgress()),
         inlineScriptTree_(inlineScriptTree) {
     MOZ_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
 
     // The function here can flow in from anywhere so look up the canonical
     // function to ensure that we do not try to embed a nursery pointer in
     // jit-code. Precisely because it can flow in from anywhere, it's not
     // guaranteed to be non-lazy. Hence, don't access its script!
     if (fun_) {
@@ -238,16 +239,17 @@ class CompileInfo {
       : script_(nullptr),
         fun_(nullptr),
         osrPc_(nullptr),
         analysisMode_(Analysis_None),
         scriptNeedsArgsObj_(false),
         hadOverflowBailout_(false),
         hadFrequentBailouts_(false),
         mayReadFrameArgsDirectly_(false),
+        trackRecordReplayProgress_(false),
         inlineScriptTree_(nullptr),
         needsBodyEnvironmentObject_(false),
         funNeedsSomeEnvironmentObject_(false) {
     nimplicit_ = 0;
     nargs_ = 0;
     nlocals_ = nlocals;
     nstack_ = 1; /* For FunctionCompiler::pushPhiInput/popPhiOutput */
     nslots_ = nlocals_ + nstack_;
@@ -494,16 +496,17 @@ class CompileInfo {
     return true;
   }
 
   // Check previous bailout states to prevent doing the same bailout in the
   // next compilation.
   bool hadOverflowBailout() const { return hadOverflowBailout_; }
   bool hadFrequentBailouts() const { return hadFrequentBailouts_; }
   bool mayReadFrameArgsDirectly() const { return mayReadFrameArgsDirectly_; }
+  bool trackRecordReplayProgress() const { return trackRecordReplayProgress_; }
 
  private:
   unsigned nimplicit_;
   unsigned nargs_;
   unsigned nlocals_;
   unsigned nstack_;
   unsigned nslots_;
   mozilla::Maybe<unsigned> thisSlotForDerivedClassConstructor_;
@@ -518,16 +521,17 @@ class CompileInfo {
   bool scriptNeedsArgsObj_;
 
   // Record the state of previous bailouts in order to prevent compiling the
   // same function identically the next time.
   bool hadOverflowBailout_;
   bool hadFrequentBailouts_;
 
   bool mayReadFrameArgsDirectly_;
+  bool trackRecordReplayProgress_;
 
   InlineScriptTree* inlineScriptTree_;
 
   // Whether a script needs environments within its body. This informs us
   // that the environment chain is not easy to reconstruct.
   bool needsBodyEnvironmentObject_;
   bool funNeedsSomeEnvironmentObject_;
 };
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -116,17 +116,17 @@ bool CodeGeneratorShared::generateProlog
   masm.pushReturnAddress();
 #endif
 
   // If profiling, save the current frame pointer to a per-thread global field.
   if (isProfilerInstrumentationEnabled()) {
     masm.profilerEnterFrame(masm.getStackPointer(), CallTempReg0);
   }
 
-  if (gen->info().script()->trackRecordReplayProgress()) {
+  if (gen->info().trackRecordReplayProgress()) {
     masm.inc64(
         AbsoluteAddress(mozilla::recordreplay::ExecutionProgressCounter()));
   }
 
   // Ensure that the Ion frame is properly aligned.
   masm.assertStackAlignment(JitStackAlignment, 0);
 
   // Note that this automatically sets MacroAssembler::framePushed().
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3269,17 +3269,17 @@ static bool ShouldTrackRecordReplayProgr
 
   // Record compile options that get checked at runtime.
   script->setFlag(ImmutableFlags::NoScriptRval, options.noScriptRval);
   script->setFlag(ImmutableFlags::SelfHosted, options.selfHostingMode);
   script->setFlag(ImmutableFlags::TreatAsRunOnce, options.isRunOnce);
   script->setFlag(MutableFlags::HideScriptFromDebugger,
                   options.hideScriptFromDebugger);
 
-  script->setFlag(ImmutableFlags::TrackRecordReplayProgress,
+  script->setFlag(MutableFlags::TrackRecordReplayProgress,
                   ShouldTrackRecordReplayProgress(script));
 
   if (cx->runtime()->lcovOutput().isEnabled()) {
     if (!script->initScriptName(cx)) {
       return nullptr;
     }
   }
 
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -1720,25 +1720,21 @@ class JSScript : public js::gc::TenuredC
     HasRest = 1 << 20,
 
     // See comments below.
     ArgsHasVarBinding = 1 << 21,
 
     // Script came from eval().
     IsForEval = 1 << 22,
 
-    // Whether the record/replay execution progress counter (see RecordReplay.h)
-    // should be updated as this script runs.
-    TrackRecordReplayProgress = 1 << 23,
-
     // Whether this is a top-level module script.
-    IsModule = 1 << 24,
+    IsModule = 1 << 23,
 
     // Whether this function needs a call object or named lambda environment.
-    NeedsFunctionEnvironmentObjects = 1 << 25,
+    NeedsFunctionEnvironmentObjects = 1 << 24,
   };
 
  private:
   // Note: don't make this a bitfield! It makes it hard to read these flags
   // from JIT code.
   uint32_t immutableFlags_ = 0;
 
   // Mutable flags typically store information about runtime or deoptimization
@@ -1749,17 +1745,21 @@ class JSScript : public js::gc::TenuredC
     WarnedAboutUndefinedProp = 1 << 0,
 
     // If treatAsRunOnce, whether script has executed.
     HasRunOnce = 1 << 1,
 
     // Script has been reused for a clone.
     HasBeenCloned = 1 << 2,
 
-    // (1 << 3) and (1 << 4) are unused.
+    // Whether the record/replay execution progress counter (see RecordReplay.h)
+    // should be updated as this script runs.
+    TrackRecordReplayProgress = 1 << 3,
+
+    // (1 << 4) is unused.
 
     // Script has an entry in Realm::scriptCountsMap.
     HasScriptCounts = 1 << 5,
 
     // Script has an entry in Realm::debugScriptMap.
     HasDebugScript = 1 << 6,
 
     // (1 << 7) and (1 << 8) are unused.
@@ -1891,16 +1891,17 @@ class JSScript : public js::gc::TenuredC
   // Initialize the Function.prototype script.
   static bool initFunctionPrototype(JSContext* cx, js::HandleScript script,
                                     JS::HandleFunction functionProto);
 
 #ifdef DEBUG
  private:
   // Assert that jump targets are within the code array of the script.
   void assertValidJumpTargets() const;
+ public:
 #endif
 
   // MutableFlags accessors.
 
   MOZ_MUST_USE bool hasFlag(MutableFlags flag) const {
     return mutableFlags_ & uint32_t(flag);
   }
   void setFlag(MutableFlags flag) { mutableFlags_ |= uint32_t(flag); }
@@ -2795,17 +2796,17 @@ class JSScript : public js::gc::TenuredC
     explicit operator bool() const { return script_; }
 
    private:
     void holdScript(JS::HandleFunction fun);
     void dropScript();
   };
 
   bool trackRecordReplayProgress() const {
-    return hasFlag(ImmutableFlags::TrackRecordReplayProgress);
+    return hasFlag(MutableFlags::TrackRecordReplayProgress);
   }
 };
 
 /* If this fails, add/remove padding within JSScript. */
 static_assert(
     sizeof(JSScript) % js::gc::CellAlignBytes == 0,
     "Size of JSScript must be an integral multiple of js::gc::CellAlignBytes");