We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / runtime / GetPutInfo.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. ``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 <wtf/text/UniquedStringImpl.h>
29
30 namespace JSC {
31
32 class Structure;
33 class WatchpointSet;
34 class JSLexicalEnvironment;
35
36 enum ResolveMode {
37     ThrowIfNotFound,
38     DoNotThrowIfNotFound
39 };
40
41 enum ResolveType {
42     // Lexical scope guaranteed a certain type of variable access.
43     GlobalProperty,
44     GlobalVar,
45     GlobalLexicalVar,
46     ClosureVar,
47     LocalClosureVar,
48     ModuleVar,
49
50     // Ditto, but at least one intervening scope used non-strict eval, which
51     // can inject an intercepting var delcaration at runtime.
52     GlobalPropertyWithVarInjectionChecks,
53     GlobalVarWithVarInjectionChecks,
54     GlobalLexicalVarWithVarInjectionChecks,
55     ClosureVarWithVarInjectionChecks,
56
57     // We haven't found which scope this belongs to, and we also
58     // haven't ruled out the possibility of it being cached. Ideally,
59     // we want to transition this to GlobalVar/GlobalLexicalVar/GlobalProperty <with/without injection>
60     UnresolvedProperty,
61     UnresolvedPropertyWithVarInjectionChecks,
62
63     // Lexical scope didn't prove anything -- probably because of a 'with' scope.
64     Dynamic
65 };
66
67 enum class InitializationMode : unsigned {
68     Initialization,      // "let x = 20;"
69     ConstInitialization, // "const x = 20;"
70     NotInitialization    // "x = 20;"
71 };
72
73 ALWAYS_INLINE const char* resolveModeName(ResolveMode resolveMode)
74 {
75     static const char* const names[] = {
76         "ThrowIfNotFound",
77         "DoNotThrowIfNotFound"
78     };
79     return names[resolveMode];
80 }
81
82 ALWAYS_INLINE const char* resolveTypeName(ResolveType type)
83 {
84     static const char* const names[] = {
85         "GlobalProperty",
86         "GlobalVar",
87         "GlobalLexicalVar",
88         "ClosureVar",
89         "LocalClosureVar",
90         "ModuleVar",
91         "GlobalPropertyWithVarInjectionChecks",
92         "GlobalVarWithVarInjectionChecks",
93         "GlobalLexicalVarWithVarInjectionChecks",
94         "ClosureVarWithVarInjectionChecks",
95         "UnresolvedProperty",
96         "UnresolvedPropertyWithVarInjectionChecks",
97         "Dynamic"
98     };
99     return names[type];
100 }
101
102 ALWAYS_INLINE const char* initializationModeName(InitializationMode initializationMode)
103 {
104     static const char* const names[] = {
105         "Initialization",
106         "ConstInitialization",
107         "NotInitialization"
108     };
109     return names[static_cast<unsigned>(initializationMode)];
110 }
111
112 ALWAYS_INLINE bool isInitialization(InitializationMode initializationMode)
113 {
114     switch (initializationMode) {
115     case InitializationMode::Initialization:
116     case InitializationMode::ConstInitialization:
117         return true;
118     case InitializationMode::NotInitialization:
119         return false;
120     }
121     ASSERT_NOT_REACHED();
122     return false;
123 }
124
125 ALWAYS_INLINE ResolveType makeType(ResolveType type, bool needsVarInjectionChecks)
126 {
127     if (!needsVarInjectionChecks)
128         return type;
129
130     switch (type) {
131     case GlobalProperty:
132         return GlobalPropertyWithVarInjectionChecks;
133     case GlobalVar:
134         return GlobalVarWithVarInjectionChecks;
135     case GlobalLexicalVar:
136         return GlobalLexicalVarWithVarInjectionChecks;
137     case ClosureVar:
138     case LocalClosureVar:
139         return ClosureVarWithVarInjectionChecks;
140     case UnresolvedProperty:
141         return UnresolvedPropertyWithVarInjectionChecks;
142     case ModuleVar:
143     case GlobalPropertyWithVarInjectionChecks:
144     case GlobalVarWithVarInjectionChecks:
145     case GlobalLexicalVarWithVarInjectionChecks:
146     case ClosureVarWithVarInjectionChecks:
147     case UnresolvedPropertyWithVarInjectionChecks:
148     case Dynamic:
149         return type;
150     }
151
152     RELEASE_ASSERT_NOT_REACHED();
153     return type;
154 }
155
156 ALWAYS_INLINE bool needsVarInjectionChecks(ResolveType type)
157 {
158     switch (type) {
159     case GlobalProperty:
160     case GlobalVar:
161     case GlobalLexicalVar:
162     case ClosureVar:
163     case LocalClosureVar:
164     case ModuleVar:
165     case UnresolvedProperty:
166         return false;
167     case GlobalPropertyWithVarInjectionChecks:
168     case GlobalVarWithVarInjectionChecks:
169     case GlobalLexicalVarWithVarInjectionChecks:
170     case ClosureVarWithVarInjectionChecks:
171     case UnresolvedPropertyWithVarInjectionChecks:
172     case Dynamic:
173         return true;
174     default:
175         RELEASE_ASSERT_NOT_REACHED();
176         return true;
177     }
178 }
179
180 struct ResolveOp {
181     ResolveOp(ResolveType type, size_t depth, Structure* structure, JSLexicalEnvironment* lexicalEnvironment, WatchpointSet* watchpointSet, uintptr_t operand, UniquedStringImpl* importedName = nullptr)
182         : type(type)
183         , depth(depth)
184         , structure(structure)
185         , lexicalEnvironment(lexicalEnvironment)
186         , watchpointSet(watchpointSet)
187         , operand(operand)
188         , importedName(importedName)
189     {
190     }
191
192     ResolveType type;
193     size_t depth;
194     Structure* structure;
195     JSLexicalEnvironment* lexicalEnvironment;
196     WatchpointSet* watchpointSet;
197     uintptr_t operand;
198     RefPtr<UniquedStringImpl> importedName;
199 };
200
201 class GetPutInfo {
202     typedef unsigned Operand;
203 public:
204     // Give each field 10 bits for simplicity.
205     static_assert(sizeof(Operand) * 8 > 30, "Not enough bits for GetPutInfo");
206     static const unsigned modeShift = 20;
207     static const unsigned initializationShift = 10;
208     static const unsigned typeBits = (1 << initializationShift) - 1;
209     static const unsigned initializationBits = ((1 << modeShift) - 1) & ~typeBits;
210     static const unsigned modeBits = ((1 << 30) - 1) & ~initializationBits & ~typeBits;
211     static_assert((modeBits & initializationBits & typeBits) == 0x0, "There should be no intersection between ResolveMode ResolveType and InitializationMode");
212
213     GetPutInfo(ResolveMode resolveMode, ResolveType resolveType, InitializationMode initializationMode)
214         : m_operand((resolveMode << modeShift) | (static_cast<unsigned>(initializationMode) << initializationShift) | resolveType)
215     {
216     }
217
218     explicit GetPutInfo(unsigned operand)
219         : m_operand(operand)
220     {
221     }
222
223     ResolveType resolveType() const { return static_cast<ResolveType>(m_operand & typeBits); }
224     InitializationMode initializationMode() const { return static_cast<InitializationMode>((m_operand & initializationBits) >> initializationShift); }
225     ResolveMode resolveMode() const { return static_cast<ResolveMode>((m_operand & modeBits) >> modeShift); }
226     unsigned operand() { return m_operand; }
227
228 private:
229     Operand m_operand;
230 };
231
232 enum GetOrPut { Get, Put };
233
234 } // namespace JSC