Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / bytecode / BytecodeKills.h
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 #pragma once
27
28 #include "CodeBlock.h"
29
30 namespace JSC {
31
32 class BytecodeLivenessAnalysis;
33
34 class BytecodeKills {
35     WTF_MAKE_FAST_ALLOCATED;
36 public:
37     BytecodeKills()
38         : m_codeBlock(nullptr)
39     {
40     }
41     
42     // By convention, we say that non-local operands are never killed.
43     bool operandIsKilled(unsigned bytecodeIndex, int operand) const
44     {
45         ASSERT_WITH_SECURITY_IMPLICATION(bytecodeIndex < m_codeBlock->instructions().size());
46         VirtualRegister reg(operand);
47         if (reg.isLocal())
48             return m_killSets[bytecodeIndex].contains(operand);
49         return false;
50     }
51     
52     bool operandIsKilled(Instruction* instruction, int operand) const
53     {
54         return operandIsKilled(instruction - m_codeBlock->instructions().begin(), operand);
55     }
56     
57     template<typename Functor>
58     void forEachOperandKilledAt(unsigned bytecodeIndex, const Functor& functor) const
59     {
60         ASSERT_WITH_SECURITY_IMPLICATION(bytecodeIndex < m_codeBlock->instructions().size());
61         m_killSets[bytecodeIndex].forEachLocal(
62             [&] (unsigned local) {
63                 functor(virtualRegisterForLocal(local));
64             });
65     }
66     
67     template<typename Functor>
68     void forEachOperandKilledAt(Instruction* pc, const Functor& functor) const
69     {
70         forEachOperandKilledAt(pc - m_codeBlock->instructions().begin(), functor);
71     }
72     
73 private:
74     friend class BytecodeLivenessAnalysis;
75
76     class KillSet {
77     public:
78         KillSet()
79             : m_word(0)
80         {
81         }
82
83         ~KillSet()
84         {
85             if (hasVector())
86                 delete vector();
87         }
88         
89         void add(unsigned local)
90         {
91             if (isEmpty()) {
92                 setOneItem(local);
93                 return;
94             }
95             if (hasOneItem()) {
96                 ASSERT(oneItem() != local);
97                 Vector<unsigned>* vector = new Vector<unsigned>();
98                 vector->append(oneItem());
99                 vector->append(local);
100                 setVector(vector);
101                 return;
102             }
103             ASSERT(!vector()->contains(local));
104             vector()->append(local);
105         }
106         
107         template<typename Functor>
108         void forEachLocal(const Functor& functor)
109         {
110             if (isEmpty())
111                 return;
112             if (hasOneItem()) {
113                 functor(oneItem());
114                 return;
115             }
116             for (unsigned local : *vector())
117                 functor(local);
118         }
119         
120         bool contains(unsigned expectedLocal)
121         {
122             if (isEmpty())
123                 return false;
124             if (hasOneItem())
125                 return oneItem() == expectedLocal;
126             for (unsigned local : *vector()) {
127                 if (local == expectedLocal)
128                     return true;
129             }
130             return false;
131         }
132         
133     private:
134         bool isEmpty() const
135         {
136             return !m_word;
137         }
138         
139         bool hasOneItem() const
140         {
141             return m_word & 1;
142         }
143         
144         unsigned oneItem() const
145         {
146             return m_word >> 1;
147         }
148         
149         void setOneItem(unsigned value)
150         {
151             m_word = (value << 1) | 1;
152         }
153         
154         bool hasVector() const
155         {
156             return !isEmpty() && !hasOneItem();
157         }
158         
159         Vector<unsigned>* vector()
160         {
161             return bitwise_cast<Vector<unsigned>*>(m_word);
162         }
163         
164         void setVector(Vector<unsigned>* value)
165         {
166             m_word = bitwise_cast<uintptr_t>(value);
167         }
168         
169         uintptr_t m_word;
170     };
171     
172     CodeBlock* m_codeBlock;
173     std::unique_ptr<KillSet[]> m_killSets;
174 };
175
176 } // namespace JSC