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