]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecode/BytecodeKills.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecode / BytecodeKills.h
CommitLineData
ed1e77d3
A
1/*
2 * Copyright (C) 2015 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef BytecodeKills_h
27#define BytecodeKills_h
28
29#include "CodeBlock.h"
30#include <wtf/FastBitVector.h>
31
32namespace JSC {
33
34class BytecodeLivenessAnalysis;
35
36class BytecodeKills {
37public:
38 BytecodeKills()
39 : m_codeBlock(nullptr)
40 {
41 }
42
43 // By convention, we say that non-local operands are never killed.
44 bool operandIsKilled(unsigned bytecodeIndex, int operand) const
45 {
46 ASSERT_WITH_SECURITY_IMPLICATION(bytecodeIndex < m_codeBlock->instructions().size());
47 VirtualRegister reg(operand);
48 if (reg.isLocal())
49 return m_killSets[bytecodeIndex].contains(operand);
50 return false;
51 }
52
53 bool operandIsKilled(Instruction* instruction, int operand) const
54 {
55 return operandIsKilled(instruction - m_codeBlock->instructions().begin(), operand);
56 }
57
58 template<typename Functor>
59 void forEachOperandKilledAt(unsigned bytecodeIndex, const Functor& functor) const
60 {
61 ASSERT_WITH_SECURITY_IMPLICATION(bytecodeIndex < m_codeBlock->instructions().size());
62 m_killSets[bytecodeIndex].forEachLocal(
63 [&] (unsigned local) {
64 functor(virtualRegisterForLocal(local));
65 });
66 }
67
68 template<typename Functor>
69 void forEachOperandKilledAt(Instruction* pc, const Functor& functor) const
70 {
71 forEachOperandKilledAt(pc - m_codeBlock->instructions().begin(), functor);
72 }
73
74private:
75 friend class BytecodeLivenessAnalysis;
76
77 class KillSet {
78 public:
79 KillSet()
80 : m_word(0)
81 {
82 }
83
84 ~KillSet()
85 {
86 if (hasVector())
87 delete vector();
88 }
89
90 void add(unsigned local)
91 {
92 if (isEmpty()) {
93 setOneItem(local);
94 return;
95 }
96 if (hasOneItem()) {
97 ASSERT(oneItem() != local);
98 Vector<unsigned>* vector = new Vector<unsigned>();
99 vector->append(oneItem());
100 vector->append(local);
101 setVector(vector);
102 return;
103 }
104 ASSERT(!vector()->contains(local));
105 vector()->append(local);
106 }
107
108 template<typename Functor>
109 void forEachLocal(const Functor& functor)
110 {
111 if (isEmpty())
112 return;
113 if (hasOneItem()) {
114 functor(oneItem());
115 return;
116 }
117 for (unsigned local : *vector())
118 functor(local);
119 }
120
121 bool contains(unsigned expectedLocal)
122 {
123 if (isEmpty())
124 return false;
125 if (hasOneItem())
126 return oneItem() == expectedLocal;
127 for (unsigned local : *vector()) {
128 if (local == expectedLocal)
129 return true;
130 }
131 return false;
132 }
133
134 private:
135 bool isEmpty() const
136 {
137 return !m_word;
138 }
139
140 bool hasOneItem() const
141 {
142 return m_word & 1;
143 }
144
145 unsigned oneItem() const
146 {
147 return m_word >> 1;
148 }
149
150 void setOneItem(unsigned value)
151 {
152 m_word = (value << 1) | 1;
153 }
154
155 bool hasVector() const
156 {
157 return !isEmpty() && !hasOneItem();
158 }
159
160 Vector<unsigned>* vector()
161 {
162 return bitwise_cast<Vector<unsigned>*>(m_word);
163 }
164
165 void setVector(Vector<unsigned>* value)
166 {
167 m_word = bitwise_cast<uintptr_t>(value);
168 }
169
170 uintptr_t m_word;
171 };
172
173 CodeBlock* m_codeBlock;
174 std::unique_ptr<KillSet[]> m_killSets;
175};
176
177} // namespace JSC
178
179#endif // BytecodeKills_h
180