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