1/* 2 * Copyright (C) 2012 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#ifndef LazyOperandValueProfile_h 27#define LazyOperandValueProfile_h 28 29#include <wtf/Platform.h> 30 31#if ENABLE(VALUE_PROFILER) 32 33#include "ValueProfile.h" 34#include <wtf/HashMap.h> 35#include <wtf/Noncopyable.h> 36#include <wtf/OwnPtr.h> 37#include <wtf/SegmentedVector.h> 38 39namespace JSC { 40 41class ScriptExecutable; 42 43class LazyOperandValueProfileKey { 44public: 45 LazyOperandValueProfileKey() 46 : m_bytecodeOffset(0) // 0 = empty value 47 , m_operand(-1) // not a valid operand index in our current scheme 48 { 49 } 50 51 LazyOperandValueProfileKey(WTF::HashTableDeletedValueType) 52 : m_bytecodeOffset(1) // 1 = deleted value 53 , m_operand(-1) // not a valid operand index in our current scheme 54 { 55 } 56 57 LazyOperandValueProfileKey(unsigned bytecodeOffset, int operand) 58 : m_bytecodeOffset(bytecodeOffset) 59 , m_operand(operand) 60 { 61 ASSERT(operand != -1); 62 } 63 64 bool operator!() const 65 { 66 return m_operand == -1; 67 } 68 69 bool operator==(const LazyOperandValueProfileKey& other) const 70 { 71 return m_bytecodeOffset == other.m_bytecodeOffset 72 && m_operand == other.m_operand; 73 } 74 75 unsigned hash() const 76 { 77 return WTF::intHash(m_bytecodeOffset) + m_operand; 78 } 79 80 unsigned bytecodeOffset() const 81 { 82 ASSERT(!!*this); 83 return m_bytecodeOffset; 84 } 85 int operand() const 86 { 87 ASSERT(!!*this); 88 return m_operand; 89 } 90 91 bool isHashTableDeletedValue() const 92 { 93 return m_operand == -1 && m_bytecodeOffset; 94 } 95private: 96 unsigned m_bytecodeOffset; 97 int m_operand; 98}; 99 100struct LazyOperandValueProfileKeyHash { 101 static unsigned hash(const LazyOperandValueProfileKey& key) { return key.hash(); } 102 static bool equal( 103 const LazyOperandValueProfileKey& a, 104 const LazyOperandValueProfileKey& b) { return a == b; } 105 static const bool safeToCompareToEmptyOrDeleted = true; 106}; 107 108} // namespace JSC 109 110namespace WTF { 111 112template<typename T> struct DefaultHash; 113template<> struct DefaultHash<JSC::LazyOperandValueProfileKey> { 114 typedef JSC::LazyOperandValueProfileKeyHash Hash; 115}; 116 117template<typename T> struct HashTraits; 118template<> struct HashTraits<JSC::LazyOperandValueProfileKey> : public GenericHashTraits<JSC::LazyOperandValueProfileKey> { 119 static void constructDeletedValue(JSC::LazyOperandValueProfileKey& slot) { new (NotNull, &slot) JSC::LazyOperandValueProfileKey(HashTableDeletedValue); } 120 static bool isDeletedValue(const JSC::LazyOperandValueProfileKey& value) { return value.isHashTableDeletedValue(); } 121}; 122 123} // namespace WTF 124 125namespace JSC { 126 127struct LazyOperandValueProfile : public MinimalValueProfile { 128 LazyOperandValueProfile() 129 : MinimalValueProfile() 130 , m_operand(-1) 131 { 132 } 133 134 explicit LazyOperandValueProfile(const LazyOperandValueProfileKey& key) 135 : MinimalValueProfile(key.bytecodeOffset()) 136 , m_operand(key.operand()) 137 { 138 } 139 140 LazyOperandValueProfileKey key() const 141 { 142 return LazyOperandValueProfileKey(m_bytecodeOffset, m_operand); 143 } 144 145 int m_operand; 146 147 typedef SegmentedVector<LazyOperandValueProfile, 8> List; 148}; 149 150class LazyOperandValueProfileParser; 151 152class CompressedLazyOperandValueProfileHolder { 153 WTF_MAKE_NONCOPYABLE(CompressedLazyOperandValueProfileHolder); 154public: 155 CompressedLazyOperandValueProfileHolder(); 156 ~CompressedLazyOperandValueProfileHolder(); 157 158 void computeUpdatedPredictions(OperationInProgress); 159 160 LazyOperandValueProfile* add(const LazyOperandValueProfileKey& key); 161 162private: 163 friend class LazyOperandValueProfileParser; 164 OwnPtr<LazyOperandValueProfile::List> m_data; 165}; 166 167class LazyOperandValueProfileParser { 168 WTF_MAKE_NONCOPYABLE(LazyOperandValueProfileParser); 169public: 170 explicit LazyOperandValueProfileParser( 171 CompressedLazyOperandValueProfileHolder& holder); 172 ~LazyOperandValueProfileParser(); 173 174 LazyOperandValueProfile* getIfPresent( 175 const LazyOperandValueProfileKey& key) const; 176 177 SpeculatedType prediction(const LazyOperandValueProfileKey& key) const; 178private: 179 CompressedLazyOperandValueProfileHolder& m_holder; 180 HashMap<LazyOperandValueProfileKey, LazyOperandValueProfile*> m_map; 181}; 182 183} // namespace JSC 184 185#endif // ENABLE(VALUE_PROFILER) 186 187#endif // LazyOperandValueProfile_h 188 189 190