Bug 1541404 part 21 - Interpreter DebugTrapHandler changes. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 10 May 2019 09:54:04 +0000
changeset 473371 6fabc0c9c2cde56f6921056d3e98500f0f7a47e3
parent 473370 aa7e1ffb96b957caa99207ebcb4052049af3703c
child 473372 b84d8c19fdea4022e92173ae3cb8b1ab284cf7af
push id35996
push userdvarga@mozilla.com
push dateFri, 10 May 2019 21:46:48 +0000
treeherdermozilla-central@362df4629f8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1541404
milestone68.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 1541404 part 21 - Interpreter DebugTrapHandler changes. r=nbp Differential Revision: https://phabricator.services.mozilla.com/D29804
js/src/jit/BaselineCompiler.cpp
js/src/jit/Ion.cpp
js/src/jit/JitRealm.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1395,17 +1395,18 @@ bool BaselineCompiler::emitDebugTrap() {
   // Flush any pending constant pools to prevent incorrect
   // PCMappingEntry offsets. See Bug 1446819.
   masm.flush();
   // Fix up the PCMappingEntry to avoid any constant pool.
   pcMappingEntries_.back().nativeOffset = masm.currentOffset();
 #endif
 
   // Emit patchable call to debug trap handler.
-  JitCode* handlerCode = cx->runtime()->jitRuntime()->debugTrapHandler(cx);
+  JitCode* handlerCode = cx->runtime()->jitRuntime()->debugTrapHandler(
+      cx, DebugTrapHandlerKind::Compiler);
   if (!handlerCode) {
     return false;
   }
   mozilla::DebugOnly<CodeOffset> offset =
       masm.toggledCall(handlerCode, enabled);
 
 #ifdef DEBUG
   // Patchable call offset has to match the pc mapping offset.
@@ -6610,26 +6611,44 @@ MethodStatus BaselineCompiler::emitBody(
     prevpc = handler.pc();
 #endif
   }
 
   MOZ_ASSERT(JSOp(*prevpc) == JSOP_RETRVAL);
   return Method_Compiled;
 }
 
-JitCode* JitRuntime::generateDebugTrapHandler(JSContext* cx) {
+JitCode* JitRuntime::generateDebugTrapHandler(JSContext* cx,
+                                              DebugTrapHandlerKind kind) {
   StackMacroAssembler masm;
 
   AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
   regs.takeUnchecked(BaselineFrameReg);
   regs.takeUnchecked(ICStubReg);
+  regs.takeUnchecked(PCRegAtStart);
   Register scratch1 = regs.takeAny();
   Register scratch2 = regs.takeAny();
   Register scratch3 = regs.takeAny();
 
+  if (kind == DebugTrapHandlerKind::Interpreter) {
+    // The interpreter calls this for every script when debugging, so check if
+    // the script has any breakpoints or is in step mode before calling into
+    // C++.
+    Label hasDebugScript;
+    Address scriptAddr(BaselineFrameReg,
+                       BaselineFrame::reverseOffsetOfInterpreterScript());
+    masm.loadPtr(scriptAddr, scratch1);
+    masm.branchTest32(Assembler::NonZero,
+                      Address(scratch1, JSScript::offsetOfMutableFlags()),
+                      Imm32(int32_t(JSScript::MutableFlags::HasDebugScript)),
+                      &hasDebugScript);
+    masm.abiret();
+    masm.bind(&hasDebugScript);
+  }
+
   // Load the return address in scratch1.
   masm.loadAbiReturnAddress(scratch1);
 
   // Load BaselineFrame pointer in scratch2.
   masm.loadBaselineFramePtr(BaselineFrameReg, scratch2);
 
   // Enter a stub frame and call the HandleDebugTrap VM function. Ensure
   // the stub frame has a nullptr ICStub pointer, since this pointer is marked
@@ -6647,16 +6666,23 @@ JitCode* JitRuntime::generateDebugTrapHa
 
   EmitBaselineLeaveStubFrame(masm);
 
   // If the stub returns |true|, we have to perform a forced return
   // (return from the JS frame). If the stub returns |false|, just return
   // from the trap stub so that execution continues at the current pc.
   Label forcedReturn;
   masm.branchIfTrueBool(ReturnReg, &forcedReturn);
+
+  if (kind == DebugTrapHandlerKind::Interpreter) {
+    // We have to reload the bytecode pc register.
+    Address pcAddr(BaselineFrameReg,
+                   BaselineFrame::reverseOffsetOfInterpreterPC());
+    masm.loadPtr(pcAddr, PCRegAtStart);
+  }
   masm.abiret();
 
   masm.bind(&forcedReturn);
   masm.loadValue(
       Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfReturnValue()),
       JSReturnOperand);
   masm.moveToStackPtr(BaselineFrameReg);
   masm.pop(BaselineFrameReg);
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -159,17 +159,17 @@ JitRuntime::JitRuntime()
       enterJITOffset_(0),
       bailoutHandlerOffset_(0),
       argumentsRectifierOffset_(0),
       argumentsRectifierReturnOffset_(0),
       invalidatorOffset_(0),
       lazyLinkStubOffset_(0),
       interpreterStubOffset_(0),
       doubleToInt32ValueStubOffset_(0),
-      debugTrapHandler_(nullptr),
+      debugTrapHandlers_(),
       baselineDebugModeOSRHandler_(nullptr),
       baselineInterpreter_(),
       trampolineCode_(nullptr),
       jitcodeGlobalTable_(nullptr),
 #ifdef DEBUG
       ionBailAfter_(0),
 #endif
       numFinishedBuilders_(0),
@@ -325,24 +325,28 @@ bool JitRuntime::generateTrampolines(JSC
 #endif
 #ifdef MOZ_VTUNE
   vtune::MarkStub(trampolineCode_, "Trampolines");
 #endif
 
   return true;
 }
 
-JitCode* JitRuntime::debugTrapHandler(JSContext* cx) {
-  if (!debugTrapHandler_) {
+JitCode* JitRuntime::debugTrapHandler(JSContext* cx,
+                                      DebugTrapHandlerKind kind) {
+  if (!debugTrapHandlers_[kind]) {
     // JitRuntime code stubs are shared across compartments and have to
     // be allocated in the atoms zone.
-    AutoAllocInAtomsZone az(cx);
-    debugTrapHandler_ = generateDebugTrapHandler(cx);
+    mozilla::Maybe<AutoAllocInAtomsZone> az;
+    if (!cx->zone()->isAtomsZone()) {
+      az.emplace(cx);
+    }
+    debugTrapHandlers_[kind] = generateDebugTrapHandler(cx, kind);
   }
-  return debugTrapHandler_;
+  return debugTrapHandlers_[kind];
 }
 
 JitRuntime::IonBuilderList& JitRuntime::ionLazyLinkList(JSRuntime* rt) {
   MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt),
              "Should only be mutated by the main thread.");
   return ionLazyLinkList_.ref();
 }
 
--- a/js/src/jit/JitRealm.h
+++ b/js/src/jit/JitRealm.h
@@ -114,16 +114,18 @@ class BaselineICFallbackCode {
   TrampolinePtr addr(BaselineICFallbackKind kind) const {
     return TrampolinePtr(code_->raw() + offsets_[kind]);
   }
   uint8_t* bailoutReturnAddr(BailoutReturnKind kind) const {
     return code_->raw() + bailoutReturnOffsets_[kind];
   }
 };
 
+enum class DebugTrapHandlerKind { Interpreter, Compiler, Count };
+
 typedef void (*EnterJitCode)(void* code, unsigned argc, Value* argv,
                              InterpreterFrame* fp, CalleeToken calleeToken,
                              JSObject* envChain, size_t numStackValues,
                              Value* vp);
 
 class JitcodeGlobalTable;
 
 class JitRuntime {
@@ -185,17 +187,19 @@ class JitRuntime {
   // Thunk to enter the interpreter from JIT code.
   WriteOnceData<uint32_t> interpreterStubOffset_;
 
   // Thunk to convert the value in R0 to int32 if it's a double.
   // Note: this stub treats -0 as +0 and may clobber R1.scratchReg().
   WriteOnceData<uint32_t> doubleToInt32ValueStubOffset_;
 
   // Thunk used by the debugger for breakpoint and step mode.
-  WriteOnceData<JitCode*> debugTrapHandler_;
+  mozilla::EnumeratedArray<DebugTrapHandlerKind, DebugTrapHandlerKind::Count,
+                           WriteOnceData<JitCode*>>
+      debugTrapHandlers_;
 
   // Thunk used to fix up on-stack recompile of baseline scripts.
   WriteOnceData<JitCode*> baselineDebugModeOSRHandler_;
   WriteOnceData<void*> baselineDebugModeOSRHandlerNoFrameRegPopAddr_;
 
   // BaselineInterpreter state.
   BaselineInterpreter baselineInterpreter_;
 
@@ -259,17 +263,17 @@ class JitRuntime {
   BailoutTable generateBailoutTable(MacroAssembler& masm, Label* bailoutTail,
                                     uint32_t frameClass);
   void generateBailoutHandler(MacroAssembler& masm, Label* bailoutTail);
   void generateInvalidator(MacroAssembler& masm, Label* bailoutTail);
   uint32_t generatePreBarrier(JSContext* cx, MacroAssembler& masm,
                               MIRType type);
   void generateMallocStub(MacroAssembler& masm);
   void generateFreeStub(MacroAssembler& masm);
-  JitCode* generateDebugTrapHandler(JSContext* cx);
+  JitCode* generateDebugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
   JitCode* generateBaselineDebugModeOSRHandler(
       JSContext* cx, uint32_t* noFrameRegPopOffsetOut);
 
   bool generateVMWrapper(JSContext* cx, MacroAssembler& masm,
                          const VMFunctionData& f, void* nativeFun,
                          uint32_t* wrapperOffset);
 
   template <typename IdT>
@@ -321,17 +325,17 @@ class JitRuntime {
     MOZ_ASSERT(trampolineCode_);
     return trampolineCode(functionWrapperOffsets_[size_t(funId)]);
   }
   TrampolinePtr getVMWrapper(TailCallVMFunctionId funId) const {
     MOZ_ASSERT(trampolineCode_);
     return trampolineCode(tailCallFunctionWrapperOffsets_[size_t(funId)]);
   }
 
-  JitCode* debugTrapHandler(JSContext* cx);
+  JitCode* debugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
   JitCode* getBaselineDebugModeOSRHandler(JSContext* cx);
   void* getBaselineDebugModeOSRHandlerAddress(JSContext* cx, bool popFrameReg);
 
   BaselineInterpreter& baselineInterpreter() { return baselineInterpreter_; }
 
   TrampolinePtr getGenericBailoutHandler() const {
     return trampolineCode(bailoutHandlerOffset_);
   }