2  * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   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. 
  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.  
  26 #ifndef DFGExitProfile_h 
  27 #define DFGExitProfile_h 
  30 #include <wtf/HashSet.h> 
  31 #include <wtf/OwnPtr.h> 
  32 #include <wtf/Vector.h> 
  34 namespace JSC 
{ namespace DFG 
{ 
  36 class FrequentExitSite 
{ 
  39         : m_bytecodeOffset(0) // 0 = empty value 
  40         , m_kind(ExitKindUnset
) 
  44     FrequentExitSite(WTF::HashTableDeletedValueType
) 
  45         : m_bytecodeOffset(1) // 1 = deleted value 
  46         , m_kind(ExitKindUnset
) 
  50     explicit FrequentExitSite(unsigned bytecodeOffset
, ExitKind kind
) 
  51         : m_bytecodeOffset(bytecodeOffset
) 
  54         ASSERT(exitKindIsCountable(kind
)); 
  57     // Use this constructor if you wish for the exit site to be counted globally within its 
  59     explicit FrequentExitSite(ExitKind kind
) 
  63         ASSERT(exitKindIsCountable(kind
)); 
  66     bool operator!() const 
  68         return m_kind 
== ExitKindUnset
; 
  71     bool operator==(const FrequentExitSite
& other
) const 
  73         return m_bytecodeOffset 
== other
.m_bytecodeOffset
 
  74             && m_kind 
== other
.m_kind
; 
  79         return WTF::intHash(m_bytecodeOffset
) + m_kind
; 
  82     unsigned bytecodeOffset() const { return m_bytecodeOffset
; } 
  83     ExitKind 
kind() const { return m_kind
; } 
  85     bool isHashTableDeletedValue() const 
  87         return m_kind 
== ExitKindUnset 
&& m_bytecodeOffset
; 
  91     unsigned m_bytecodeOffset
; 
  95 struct FrequentExitSiteHash 
{ 
  96     static unsigned hash(const FrequentExitSite
& key
) { return key
.hash(); } 
  97     static bool equal(const FrequentExitSite
& a
, const FrequentExitSite
& b
) { return a 
== b
; } 
  98     static const bool safeToCompareToEmptyOrDeleted 
= true; 
 101 } } // namespace JSC::DFG 
 105 template<typename T
> struct DefaultHash
; 
 106 template<> struct DefaultHash
<JSC::DFG::FrequentExitSite
> { 
 107     typedef JSC::DFG::FrequentExitSiteHash Hash
; 
 110 template<typename T
> struct HashTraits
; 
 111 template<> struct HashTraits
<JSC::DFG::FrequentExitSite
> : SimpleClassHashTraits
<JSC::DFG::FrequentExitSite
> { }; 
 115 namespace JSC 
{ namespace DFG 
{ 
 117 class QueryableExitProfile
; 
 124     // Add a new frequent exit site. Return true if this is a new one, or false 
 125     // if we already knew about it. This is an O(n) operation, because it errs 
 126     // on the side of keeping the data structure compact. Also, this will only 
 127     // be called a fixed number of times per recompilation. Recompilation is 
 128     // rare to begin with, and implies doing O(n) operations on the CodeBlock 
 130     bool add(const FrequentExitSite
&); 
 132     // Get the frequent exit sites for a bytecode index. This is O(n), and is 
 133     // meant to only be used from debugging/profiling code. 
 134     Vector
<FrequentExitSite
> exitSitesFor(unsigned bytecodeIndex
); 
 136     // This is O(n) and should be called on less-frequently executed code paths 
 137     // in the compiler. It should be strictly cheaper than building a 
 138     // QueryableExitProfile, if you really expect this to be called infrequently 
 139     // and you believe that there are few exit sites. 
 140     bool hasExitSite(const FrequentExitSite
&) const; 
 141     bool hasExitSite(ExitKind kind
) const 
 143         return hasExitSite(FrequentExitSite(kind
)); 
 145     bool hasExitSite(unsigned bytecodeIndex
, ExitKind kind
) const 
 147         return hasExitSite(FrequentExitSite(bytecodeIndex
, kind
)); 
 151     friend class QueryableExitProfile
; 
 153     OwnPtr
<Vector
<FrequentExitSite
> > m_frequentExitSites
; 
 156 class QueryableExitProfile 
{ 
 158     explicit QueryableExitProfile(const ExitProfile
&); 
 159     ~QueryableExitProfile(); 
 161     bool hasExitSite(const FrequentExitSite
& site
) const 
 163         return m_frequentExitSites
.find(site
) != m_frequentExitSites
.end(); 
 166     bool hasExitSite(ExitKind kind
) const 
 168         return hasExitSite(FrequentExitSite(kind
)); 
 171     bool hasExitSite(unsigned bytecodeIndex
, ExitKind kind
) const 
 173         return hasExitSite(FrequentExitSite(bytecodeIndex
, kind
)); 
 176     HashSet
<FrequentExitSite
> m_frequentExitSites
; 
 179 } } // namespace JSC::DFG 
 181 #endif // DFGExitProfile_h