Bug 1541404 part 8 - Add ICEntry::isForPrologue and use it instead of ICEntry::isForOp. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 10 Apr 2019 16:28:07 +0000
changeset 468953 b5bcfc2617667e3fc7a095b262b80377b2542446
parent 468952 1df3239c094dbfcbb217328020937cb8089e5865
child 468954 0b4aefa9f91cb941071c1fdb1c520188522bf710
child 468955 95d45fef28b9ef661ea775b0e5eedcd47614f665
push id112762
push useraciure@mozilla.com
push dateThu, 11 Apr 2019 09:57:48 +0000
treeherdermozilla-inbound@0b4aefa9f91c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1541404
milestone68.0a1
first release with
nightly linux32
b5bcfc261766 / 68.0a1 / 20190411095057 / files
nightly linux64
b5bcfc261766 / 68.0a1 / 20190411095057 / files
nightly mac
b5bcfc261766 / 68.0a1 / 20190411095057 / files
nightly win32
b5bcfc261766 / 68.0a1 / 20190411095057 / files
nightly win64
b5bcfc261766 / 68.0a1 / 20190411095057 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1541404 part 8 - Add ICEntry::isForPrologue and use it instead of ICEntry::isForOp. r=tcampbell Depends on D26677 Differential Revision: https://phabricator.services.mozilla.com/D26912
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineDebugModeOSR.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/BaselineInspector.cpp
js/src/jit/BaselineJIT.cpp
js/src/jit/BaselineJIT.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -527,23 +527,24 @@ bool BaselineCompilerCodeGen::emitNextIC
   // to loop until we find an ICEntry for the current pc.
   const ICEntry* entry;
   do {
     entry = &script->icScript()->icEntry(handler.icEntryIndex());
     handler.moveToNextICEntry();
   } while (entry->pcOffset() < pcOffset);
 
   MOZ_RELEASE_ASSERT(entry->pcOffset() == pcOffset);
-  MOZ_ASSERT_IF(entry->isForOp(), BytecodeOpHasIC(JSOp(*handler.pc())));
+  MOZ_ASSERT_IF(!entry->isForPrologue(), BytecodeOpHasIC(JSOp(*handler.pc())));
 
   CodeOffset callOffset;
   EmitCallIC(masm, entry, &callOffset);
 
-  RetAddrEntry::Kind kind =
-      entry->isForOp() ? RetAddrEntry::Kind::IC : RetAddrEntry::Kind::NonOpIC;
+  RetAddrEntry::Kind kind = entry->isForPrologue()
+                                ? RetAddrEntry::Kind::PrologueIC
+                                : RetAddrEntry::Kind::IC;
 
   if (!handler.retAddrEntries().emplaceBack(pcOffset, kind, callOffset)) {
     ReportOutOfMemory(cx);
     return false;
   }
 
   return true;
 }
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -261,18 +261,18 @@ static bool CollectInterpreterStackScrip
   return true;
 }
 
 #ifdef JS_JITSPEW
 static const char* RetAddrEntryKindToString(RetAddrEntry::Kind kind) {
   switch (kind) {
     case RetAddrEntry::Kind::IC:
       return "IC";
-    case RetAddrEntry::Kind::NonOpIC:
-      return "non-op IC";
+    case RetAddrEntry::Kind::PrologueIC:
+      return "prologue IC";
     case RetAddrEntry::Kind::CallVM:
       return "callVM";
     case RetAddrEntry::Kind::WarmupCounter:
       return "warmup counter";
     case RetAddrEntry::Kind::StackCheck:
       return "stack check";
     case RetAddrEntry::Kind::DebugTrap:
       return "debug trap";
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -166,17 +166,17 @@ UniquePtr<ICScript> ICScript::create(JSC
 
   using Kind = BaselineICFallbackKind;
 
   auto addIC = [cx, &icEntries, script](jsbytecode* pc, ICStub* stub) {
     if (!stub) {
       MOZ_ASSERT(cx->isExceptionPending());
       return false;
     }
-    uint32_t offset = pc ? script->pcToOffset(pc) : ICEntry::NonOpPCOffset;
+    uint32_t offset = pc ? script->pcToOffset(pc) : ICEntry::ProloguePCOffset;
     if (!icEntries.emplaceBack(stub, offset)) {
       ReportOutOfMemory(cx);
       return false;
     }
     return true;
   };
 
   // Add ICEntries and fallback stubs for this/argument type checks.
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -215,61 +215,61 @@ void TypeFallbackICSpew(JSContext* cx, I
 #endif
 
 // An entry in the BaselineScript IC descriptor table. There's one ICEntry per
 // IC.
 class ICEntry {
   // A pointer to the first IC stub for this instruction.
   ICStub* firstStub_;
 
-  // The PC of this IC's bytecode op within the JSScript.
+  // The PC offset of this IC's bytecode op within the JSScript or
+  // ProloguePCOffset if this is a prologue IC.
   uint32_t pcOffset_;
 
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
 #ifdef JS_64BIT
   // On 64-bit architectures, we have 32 bits of alignment padding.
   // We fill it with a magic value, and check that value when tracing.
   static const uint32_t EXPECTED_TRACE_MAGIC = 0xdeaddead;
   uint32_t traceMagic_ = EXPECTED_TRACE_MAGIC;
 #endif
 #endif
 
  public:
-  // Non-op ICs are Baseline ICs used for function argument/this type
-  // monitoring in the script's prologue. All other ICs are "for op" ICs.
-  // Note: the last bytecode op in a script is always a return so UINT32_MAX
-  // is never a valid bytecode offset.
-  static constexpr uint32_t NonOpPCOffset = UINT32_MAX;
+  // Prologue ICs are Baseline ICs used for function argument/this type
+  // monitoring in the script's prologue. Note: the last bytecode op in a script
+  // is always a return so UINT32_MAX is never a valid bytecode offset.
+  static constexpr uint32_t ProloguePCOffset = UINT32_MAX;
 
   ICEntry(ICStub* firstStub, uint32_t pcOffset)
       : firstStub_(firstStub), pcOffset_(pcOffset) {}
 
   ICStub* firstStub() const {
     MOZ_ASSERT(firstStub_);
     return firstStub_;
   }
 
   ICFallbackStub* fallbackStub() const;
 
   void setFirstStub(ICStub* stub) { firstStub_ = stub; }
 
   uint32_t pcOffset() const {
-    return pcOffset_ == NonOpPCOffset ? 0 : pcOffset_;
+    return pcOffset_ == ProloguePCOffset ? 0 : pcOffset_;
   }
   jsbytecode* pc(JSScript* script) const {
     return script->offsetToPC(pcOffset());
   }
 
   static inline size_t offsetOfFirstStub() {
     return offsetof(ICEntry, firstStub_);
   }
 
   inline ICStub** addressOfFirstStub() { return &firstStub_; }
 
-  bool isForOp() const { return pcOffset_ != NonOpPCOffset; }
+  bool isForPrologue() const { return pcOffset_ == ProloguePCOffset; }
 
   void trace(JSTracer* trc);
 };
 
 // [SMDOC] ICScript
 //
 // ICScript contains IC data used by Baseline (Ion has its own IC chains, stored
 // in IonScript).
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -139,17 +139,17 @@ ICEntry* BaselineInspector::maybeICEntry
   MOZ_ASSERT(hasICScript());
   MOZ_ASSERT(isValidPC(pc));
   ICEntry* ent = icScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
                                                       prevLookedUpEntry);
   if (!ent) {
     return nullptr;
   }
 
-  MOZ_ASSERT(ent->isForOp());
+  MOZ_ASSERT(!ent->isForPrologue());
   prevLookedUpEntry = ent;
   return ent;
 }
 
 bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc,
                                                ReceiverVector& receivers) {
   // Return a list of the receivers seen by the baseline IC for the current
   // op. Empty lists indicate no receivers are known, or there was an
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -552,20 +552,20 @@ static bool ComputeBinarySearchMid(ICEnt
       [pcOffset](const ICEntry& entry) {
         uint32_t entryOffset = entry.pcOffset();
         if (pcOffset < entryOffset) {
           return -1;
         }
         if (entryOffset < pcOffset) {
           return 1;
         }
-        if (!entry.isForOp()) {
-          // Non-op ICEntries are used for prologue argument type checks. Ignore
-          // those entries and return 1 because these entries appear in the
-          // ICEntry list before the for-op ICEntry (if any) at offset 0.
+        if (entry.isForPrologue()) {
+          // Prologue ICEntries are used for function argument type checks.
+          // Ignore these entries and return 1 because these entries appear in
+          // the ICEntry list before the other ICEntry (if any) at offset 0.
           MOZ_ASSERT(entryOffset == 0);
           return 1;
         }
         return 0;
       },
       loc);
 }
 
@@ -586,27 +586,28 @@ static bool ComputeBinarySearchMid(RetAd
       loc);
 }
 
 uint8_t* BaselineScript::returnAddressForEntry(const RetAddrEntry& ent) {
   return method()->raw() + ent.returnOffset().offset();
 }
 
 ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
-  // Multiple IC entries can have the same PC offset, but this method only looks
-  // for those which have isForOp() set.
+  // This method ignores prologue IC entries. There can be at most one
+  // non-prologue IC per bytecode op.
+
   size_t mid;
   if (!ComputeBinarySearchMid(ICEntries(this), pcOffset, &mid)) {
     return nullptr;
   }
 
   MOZ_ASSERT(mid < numICEntries());
 
   ICEntry& entry = icEntry(mid);
-  MOZ_ASSERT(entry.isForOp());
+  MOZ_ASSERT(!entry.isForPrologue());
   MOZ_ASSERT(entry.pcOffset() == pcOffset);
   return &entry;
 }
 
 ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset) {
   ICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
   MOZ_RELEASE_ASSERT(entry);
   return *entry;
@@ -617,17 +618,17 @@ ICEntry* ICScript::maybeICEntryFromPCOff
   // Do a linear forward search from the last queried PC offset, or fallback to
   // a binary search if the last offset is too far away.
   if (prevLookedUpEntry && pcOffset >= prevLookedUpEntry->pcOffset() &&
       (pcOffset - prevLookedUpEntry->pcOffset()) <= 10) {
     ICEntry* firstEntry = &icEntry(0);
     ICEntry* lastEntry = &icEntry(numICEntries() - 1);
     ICEntry* curEntry = prevLookedUpEntry;
     while (curEntry >= firstEntry && curEntry <= lastEntry) {
-      if (curEntry->pcOffset() == pcOffset && curEntry->isForOp()) {
+      if (curEntry->pcOffset() == pcOffset && !curEntry->isForPrologue()) {
         return curEntry;
       }
       curEntry++;
     }
     return nullptr;
   }
 
   return maybeICEntryFromPCOffset(pcOffset);
@@ -641,26 +642,26 @@ ICEntry& ICScript::icEntryFromPCOffset(u
 }
 
 ICEntry* ICScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
   // We have to return the entry to store in BaselineFrame::interpreterICEntry
   // when resuming in the Baseline Interpreter at pcOffset. The bytecode op at
   // pcOffset does not necessarily have an ICEntry, so we want to return the
   // first ICEntry for which the following is true:
   //
-  //    entry.isForOp() && entry.pcOffset() >= pcOffset
+  //    !entry.isForPrologue() && entry.pcOffset() >= pcOffset
   //
   // Fortunately, ComputeBinarySearchMid returns exactly this entry.
 
   size_t mid;
   ComputeBinarySearchMid(ICEntries(this), pcOffset, &mid);
 
   if (mid < numICEntries()) {
     ICEntry& entry = icEntry(mid);
-    MOZ_ASSERT(entry.isForOp());
+    MOZ_ASSERT(!entry.isForPrologue());
     MOZ_ASSERT(entry.pcOffset() >= pcOffset);
     return &entry;
   }
 
   // Resuming at a pc after the last ICEntry. Just return nullptr:
   // BaselineFrame::interpreterICEntry will never be used in this case.
   return nullptr;
 }
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -132,21 +132,21 @@ class RetAddrEntry {
   // Offset from the start of the JIT code where call instruction is.
   uint32_t returnOffset_;
 
   // The offset of this bytecode op within the JSScript.
   uint32_t pcOffset_ : 28;
 
  public:
   enum class Kind : uint32_t {
-    // A for-op IC.
+    // An IC for a JOF_IC op.
     IC,
 
-    // A non-op IC.
-    NonOpIC,
+    // A prologue IC.
+    PrologueIC,
 
     // A callVM for an op.
     CallVM,
 
     // A callVM not for an op (e.g., in the prologue).
     NonOpCallVM,
 
     // A callVM for the warmup counter.
@@ -198,22 +198,16 @@ class RetAddrEntry {
   jsbytecode* pc(JSScript* script) const {
     return script->offsetToPC(pcOffset_);
   }
 
   Kind kind() const {
     MOZ_ASSERT(kind_ < uint32_t(Kind::Invalid));
     return Kind(kind_);
   }
-  bool isForOp() const { return kind() == Kind::IC; }
-
-  void setNonICKind(Kind kind) {
-    MOZ_ASSERT(kind != Kind::IC && kind != Kind::NonOpIC);
-    setKind(kind);
-  }
 };
 
 struct BaselineScript final {
  private:
   // Code pointer containing the actual method.
   HeapPtr<JitCode*> method_ = nullptr;
 
   // For functions with a call object, template objects to use for the call