/ bytecode / DFGExitProfile.cpp
DFGExitProfile.cpp
  1  /*
  2   * Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
  3   *
  4   * Redistribution and use in source and binary forms, with or without
  5   * modification, are permitted provided that the following conditions
  6   * are met:
  7   * 1. Redistributions of source code must retain the above copyright
  8   *    notice, this list of conditions and the following disclaimer.
  9   * 2. Redistributions in binary form must reproduce the above copyright
 10   *    notice, this list of conditions and the following disclaimer in the
 11   *    documentation and/or other materials provided with the distribution.
 12   *
 13   * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 24   */
 25  
 26  #include "config.h"
 27  #include "DFGExitProfile.h"
 28  
 29  #if ENABLE(DFG_JIT)
 30  
 31  #include "CodeBlock.h"
 32  #include "VMInlines.h"
 33  
 34  namespace JSC { namespace DFG {
 35  
 36  void FrequentExitSite::dump(PrintStream& out) const
 37  {
 38      out.print(m_bytecodeIndex, ": ", m_kind, "/", m_jitType, "/", m_inlineKind);
 39  }
 40  
 41  ExitProfile::ExitProfile() { }
 42  ExitProfile::~ExitProfile() { }
 43  
 44  bool ExitProfile::add(CodeBlock* owner, const FrequentExitSite& site)
 45  {
 46      RELEASE_ASSERT(site.jitType() != ExitFromAnything);
 47      RELEASE_ASSERT(site.inlineKind() != ExitFromAnyInlineKind);
 48  
 49      ConcurrentJSLocker locker(owner->unlinkedCodeBlock()->m_lock);
 50  
 51      CODEBLOCK_LOG_EVENT(owner, "frequentExit", (site));
 52      
 53      dataLogLnIf(Options::verboseExitProfile(), pointerDump(owner), ": Adding exit site: ", site);
 54  
 55      ExitProfile& profile = owner->unlinkedCodeBlock()->exitProfile();
 56      
 57      // If we've never seen any frequent exits then create the list and put this site
 58      // into it.
 59      if (!profile.m_frequentExitSites) {
 60          profile.m_frequentExitSites = makeUnique<Vector<FrequentExitSite>>();
 61          profile.m_frequentExitSites->append(site);
 62          return true;
 63      }
 64      
 65      // Don't add it if it's already there. This is O(n), but that's OK, because we
 66      // know that the total number of places where code exits tends to not be large,
 67      // and this code is only used when recompilation is triggered.
 68      for (unsigned i = 0; i < profile.m_frequentExitSites->size(); ++i) {
 69          if (profile.m_frequentExitSites->at(i) == site)
 70              return false;
 71      }
 72      
 73      profile.m_frequentExitSites->append(site);
 74      return true;
 75  }
 76  
 77  Vector<FrequentExitSite> ExitProfile::exitSitesFor(BytecodeIndex bytecodeIndex)
 78  {
 79      Vector<FrequentExitSite> result;
 80      
 81      if (!m_frequentExitSites)
 82          return result;
 83      
 84      for (unsigned i = 0; i < m_frequentExitSites->size(); ++i) {
 85          if (m_frequentExitSites->at(i).bytecodeIndex() == bytecodeIndex)
 86              result.append(m_frequentExitSites->at(i));
 87      }
 88      
 89      return result;
 90  }
 91  
 92  bool ExitProfile::hasExitSite(const ConcurrentJSLocker&, const FrequentExitSite& site) const
 93  {
 94      if (!m_frequentExitSites)
 95          return false;
 96      
 97      for (unsigned i = m_frequentExitSites->size(); i--;) {
 98          if (site.subsumes(m_frequentExitSites->at(i)))
 99              return true;
100      }
101      return false;
102  }
103  
104  QueryableExitProfile::QueryableExitProfile() { }
105  QueryableExitProfile::~QueryableExitProfile() { }
106  
107  void QueryableExitProfile::initialize(UnlinkedCodeBlock* unlinkedCodeBlock)
108  {
109      ConcurrentJSLocker locker(unlinkedCodeBlock->m_lock);
110      const ExitProfile& profile = unlinkedCodeBlock->exitProfile();
111      if (!profile.m_frequentExitSites)
112          return;
113      
114      for (unsigned i = 0; i < profile.m_frequentExitSites->size(); ++i)
115          m_frequentExitSites.add(profile.m_frequentExitSites->at(i));
116  }
117  
118  } } // namespace JSC::DFG
119  
120  #endif