]>
Commit | Line | Data |
---|---|---|
93a37866 | 1 | /* |
ed1e77d3 | 2 | * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. |
93a37866 A |
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 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
81345200 | 13 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of |
93a37866 A |
14 | * its contributors may be used to endorse or promote products derived |
15 | * from this software without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #include "config.h" | |
30 | #include "SymbolTable.h" | |
31 | ||
81345200 A |
32 | #include "JSDestructibleObject.h" |
33 | #include "JSCInlines.h" | |
34 | #include "SlotVisitorInlines.h" | |
ed1e77d3 | 35 | #include "TypeProfiler.h" |
81345200 | 36 | |
93a37866 A |
37 | namespace JSC { |
38 | ||
ed1e77d3 | 39 | const ClassInfo SymbolTable::s_info = { "SymbolTable", 0, 0, CREATE_METHOD_TABLE(SymbolTable) }; |
93a37866 A |
40 | |
41 | SymbolTableEntry& SymbolTableEntry::copySlow(const SymbolTableEntry& other) | |
42 | { | |
43 | ASSERT(other.isFat()); | |
44 | FatEntry* newFatEntry = new FatEntry(*other.fatEntry()); | |
45 | freeFatEntry(); | |
46 | m_bits = bitwise_cast<intptr_t>(newFatEntry); | |
47 | return *this; | |
48 | } | |
49 | ||
81345200 | 50 | void SymbolTable::destroy(JSCell* cell) |
93a37866 | 51 | { |
81345200 A |
52 | SymbolTable* thisObject = jsCast<SymbolTable*>(cell); |
53 | thisObject->SymbolTable::~SymbolTable(); | |
93a37866 A |
54 | } |
55 | ||
56 | void SymbolTableEntry::freeFatEntrySlow() | |
57 | { | |
58 | ASSERT(isFat()); | |
59 | delete fatEntry(); | |
60 | } | |
61 | ||
ed1e77d3 | 62 | void SymbolTableEntry::prepareToWatch() |
93a37866 | 63 | { |
ed1e77d3 A |
64 | if (!isWatchable()) |
65 | return; | |
93a37866 | 66 | FatEntry* entry = inflate(); |
81345200 A |
67 | if (entry->m_watchpoints) |
68 | return; | |
ed1e77d3 | 69 | entry->m_watchpoints = adoptRef(new WatchpointSet(ClearWatchpoint)); |
93a37866 A |
70 | } |
71 | ||
72 | void SymbolTableEntry::addWatchpoint(Watchpoint* watchpoint) | |
73 | { | |
93a37866 A |
74 | fatEntry()->m_watchpoints->add(watchpoint); |
75 | } | |
76 | ||
93a37866 A |
77 | SymbolTableEntry::FatEntry* SymbolTableEntry::inflateSlow() |
78 | { | |
79 | FatEntry* entry = new FatEntry(m_bits); | |
80 | m_bits = bitwise_cast<intptr_t>(entry); | |
81 | return entry; | |
82 | } | |
83 | ||
81345200 A |
84 | SymbolTable::SymbolTable(VM& vm) |
85 | : JSCell(vm, vm.symbolTableStructure.get()) | |
81345200 | 86 | , m_usesNonStrictEval(false) |
81345200 A |
87 | { |
88 | } | |
89 | ||
90 | SymbolTable::~SymbolTable() { } | |
91 | ||
ed1e77d3 A |
92 | void SymbolTable::finishCreation(VM& vm) |
93 | { | |
94 | Base::finishCreation(vm); | |
95 | m_singletonScope.set(vm, this, InferredValue::create(vm)); | |
96 | } | |
97 | ||
81345200 A |
98 | void SymbolTable::visitChildren(JSCell* thisCell, SlotVisitor& visitor) |
99 | { | |
100 | SymbolTable* thisSymbolTable = jsCast<SymbolTable*>(thisCell); | |
81345200 | 101 | |
ed1e77d3 A |
102 | visitor.append(&thisSymbolTable->m_arguments); |
103 | visitor.append(&thisSymbolTable->m_singletonScope); | |
104 | ||
105 | // Save some memory. This is O(n) to rebuild and we do so on the fly. | |
106 | ConcurrentJITLocker locker(thisSymbolTable->m_lock); | |
107 | thisSymbolTable->m_localToEntry = nullptr; | |
81345200 A |
108 | } |
109 | ||
ed1e77d3 | 110 | const SymbolTable::LocalToEntryVec& SymbolTable::localToEntry(const ConcurrentJITLocker&) |
81345200 | 111 | { |
ed1e77d3 A |
112 | if (UNLIKELY(!m_localToEntry)) { |
113 | unsigned size = 0; | |
114 | for (auto& entry : m_map) { | |
115 | VarOffset offset = entry.value.varOffset(); | |
116 | if (offset.isScope()) | |
117 | size = std::max(size, offset.scopeOffset().offset() + 1); | |
118 | } | |
119 | ||
120 | m_localToEntry = std::make_unique<LocalToEntryVec>(size, nullptr); | |
121 | for (auto& entry : m_map) { | |
122 | VarOffset offset = entry.value.varOffset(); | |
123 | if (offset.isScope()) | |
124 | m_localToEntry->at(offset.scopeOffset().offset()) = &entry.value; | |
125 | } | |
126 | } | |
127 | ||
128 | return *m_localToEntry; | |
81345200 A |
129 | } |
130 | ||
ed1e77d3 | 131 | SymbolTableEntry* SymbolTable::entryFor(const ConcurrentJITLocker& locker, ScopeOffset offset) |
81345200 | 132 | { |
ed1e77d3 A |
133 | auto& toEntryVector = localToEntry(locker); |
134 | if (offset.offset() >= toEntryVector.size()) | |
135 | return nullptr; | |
136 | return toEntryVector[offset.offset()]; | |
81345200 A |
137 | } |
138 | ||
ed1e77d3 | 139 | SymbolTable* SymbolTable::cloneScopePart(VM& vm) |
81345200 A |
140 | { |
141 | SymbolTable* result = SymbolTable::create(vm); | |
142 | ||
81345200 | 143 | result->m_usesNonStrictEval = m_usesNonStrictEval; |
81345200 A |
144 | |
145 | for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { | |
ed1e77d3 | 146 | if (!iter->value.varOffset().isScope()) |
81345200 A |
147 | continue; |
148 | result->m_map.add( | |
149 | iter->key, | |
ed1e77d3 | 150 | SymbolTableEntry(iter->value.varOffset(), iter->value.getAttributes())); |
81345200 A |
151 | } |
152 | ||
ed1e77d3 A |
153 | result->m_maxScopeOffset = m_maxScopeOffset; |
154 | ||
155 | if (ScopedArgumentsTable* arguments = this->arguments()) | |
156 | result->m_arguments.set(vm, result, arguments); | |
157 | ||
158 | if (m_typeProfilingRareData) { | |
159 | result->m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>(); | |
160 | ||
161 | { | |
162 | auto iter = m_typeProfilingRareData->m_uniqueIDMap.begin(); | |
163 | auto end = m_typeProfilingRareData->m_uniqueIDMap.end(); | |
164 | for (; iter != end; ++iter) | |
165 | result->m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, iter->value); | |
166 | } | |
167 | ||
168 | { | |
169 | auto iter = m_typeProfilingRareData->m_offsetToVariableMap.begin(); | |
170 | auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); | |
171 | for (; iter != end; ++iter) | |
172 | result->m_typeProfilingRareData->m_offsetToVariableMap.set(iter->key, iter->value); | |
173 | } | |
174 | ||
175 | { | |
176 | auto iter = m_typeProfilingRareData->m_uniqueTypeSetMap.begin(); | |
177 | auto end = m_typeProfilingRareData->m_uniqueTypeSetMap.end(); | |
178 | for (; iter != end; ++iter) | |
179 | result->m_typeProfilingRareData->m_uniqueTypeSetMap.set(iter->key, iter->value); | |
180 | } | |
81345200 A |
181 | } |
182 | ||
183 | return result; | |
184 | } | |
185 | ||
ed1e77d3 A |
186 | void SymbolTable::prepareForTypeProfiling(const ConcurrentJITLocker&) |
187 | { | |
188 | if (m_typeProfilingRareData) | |
189 | return; | |
190 | ||
191 | m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>(); | |
192 | ||
193 | for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { | |
194 | m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, TypeProfilerNeedsUniqueIDGeneration); | |
195 | m_typeProfilingRareData->m_offsetToVariableMap.set(iter->value.varOffset(), iter->key); | |
196 | } | |
197 | } | |
198 | ||
199 | GlobalVariableID SymbolTable::uniqueIDForVariable(const ConcurrentJITLocker&, UniquedStringImpl* key, VM& vm) | |
200 | { | |
201 | RELEASE_ASSERT(m_typeProfilingRareData); | |
202 | ||
203 | auto iter = m_typeProfilingRareData->m_uniqueIDMap.find(key); | |
204 | auto end = m_typeProfilingRareData->m_uniqueIDMap.end(); | |
205 | if (iter == end) | |
206 | return TypeProfilerNoGlobalIDExists; | |
207 | ||
208 | GlobalVariableID id = iter->value; | |
209 | if (id == TypeProfilerNeedsUniqueIDGeneration) { | |
210 | id = vm.typeProfiler()->getNextUniqueVariableID(); | |
211 | m_typeProfilingRareData->m_uniqueIDMap.set(key, id); | |
212 | m_typeProfilingRareData->m_uniqueTypeSetMap.set(key, TypeSet::create()); // Make a new global typeset for this corresponding ID. | |
213 | } | |
214 | ||
215 | return id; | |
216 | } | |
217 | ||
218 | GlobalVariableID SymbolTable::uniqueIDForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm) | |
219 | { | |
220 | RELEASE_ASSERT(m_typeProfilingRareData); | |
221 | ||
222 | auto iter = m_typeProfilingRareData->m_offsetToVariableMap.find(offset); | |
223 | auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); | |
224 | if (iter == end) | |
225 | return TypeProfilerNoGlobalIDExists; | |
226 | ||
227 | return uniqueIDForVariable(locker, iter->value.get(), vm); | |
228 | } | |
229 | ||
230 | RefPtr<TypeSet> SymbolTable::globalTypeSetForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm) | |
231 | { | |
232 | RELEASE_ASSERT(m_typeProfilingRareData); | |
233 | ||
234 | uniqueIDForOffset(locker, offset, vm); // Lazily create the TypeSet if necessary. | |
235 | ||
236 | auto iter = m_typeProfilingRareData->m_offsetToVariableMap.find(offset); | |
237 | auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); | |
238 | if (iter == end) | |
239 | return nullptr; | |
240 | ||
241 | return globalTypeSetForVariable(locker, iter->value.get(), vm); | |
242 | } | |
243 | ||
244 | RefPtr<TypeSet> SymbolTable::globalTypeSetForVariable(const ConcurrentJITLocker& locker, UniquedStringImpl* key, VM& vm) | |
245 | { | |
246 | RELEASE_ASSERT(m_typeProfilingRareData); | |
247 | ||
248 | uniqueIDForVariable(locker, key, vm); // Lazily create the TypeSet if necessary. | |
249 | ||
250 | auto iter = m_typeProfilingRareData->m_uniqueTypeSetMap.find(key); | |
251 | auto end = m_typeProfilingRareData->m_uniqueTypeSetMap.end(); | |
252 | if (iter == end) | |
253 | return nullptr; | |
254 | ||
255 | return iter->value; | |
256 | } | |
257 | ||
93a37866 A |
258 | } // namespace JSC |
259 |