]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSSymbolTableObject.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / JSSymbolTableObject.h
1 /*
2 * Copyright (C) 2012, 2014, 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 *
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.
13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
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 #ifndef JSSymbolTableObject_h
30 #define JSSymbolTableObject_h
31
32 #include "JSScope.h"
33 #include "PropertyDescriptor.h"
34 #include "SymbolTable.h"
35 #include "VariableWriteFireDetail.h"
36
37 namespace JSC {
38
39 class JSSymbolTableObject;
40
41 class JSSymbolTableObject : public JSScope {
42 public:
43 typedef JSScope Base;
44 static const unsigned StructureFlags = Base::StructureFlags | IsEnvironmentRecord | OverridesGetPropertyNames;
45
46 SymbolTable* symbolTable() const { return m_symbolTable.get(); }
47
48 JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
49 JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
50
51 static ptrdiff_t offsetOfSymbolTable() { return OBJECT_OFFSETOF(JSSymbolTableObject, m_symbolTable); }
52
53 protected:
54 JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope)
55 : Base(vm, structure, scope)
56 {
57 }
58
59 JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope, SymbolTable* symbolTable)
60 : Base(vm, structure, scope)
61 {
62 ASSERT(symbolTable);
63 setSymbolTable(vm, symbolTable);
64 }
65
66 void setSymbolTable(VM& vm, SymbolTable* symbolTable)
67 {
68 ASSERT(!m_symbolTable);
69 symbolTable->singletonScope()->notifyWrite(vm, this, "Allocated a scope");
70 m_symbolTable.set(vm, this, symbolTable);
71 }
72
73 static void visitChildren(JSCell*, SlotVisitor&);
74
75 private:
76 WriteBarrier<SymbolTable> m_symbolTable;
77 };
78
79 template<typename SymbolTableObjectType>
80 inline bool symbolTableGet(
81 SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot)
82 {
83 SymbolTable& symbolTable = *object->symbolTable();
84 ConcurrentJITLocker locker(symbolTable.m_lock);
85 SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
86 if (iter == symbolTable.end(locker))
87 return false;
88 SymbolTableEntry::Fast entry = iter->value;
89 ASSERT(!entry.isNull());
90 slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(entry.scopeOffset()).get());
91 return true;
92 }
93
94 template<typename SymbolTableObjectType>
95 inline bool symbolTableGet(
96 SymbolTableObjectType* object, PropertyName propertyName, PropertyDescriptor& descriptor)
97 {
98 SymbolTable& symbolTable = *object->symbolTable();
99 ConcurrentJITLocker locker(symbolTable.m_lock);
100 SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
101 if (iter == symbolTable.end(locker))
102 return false;
103 SymbolTableEntry::Fast entry = iter->value;
104 ASSERT(!entry.isNull());
105 descriptor.setDescriptor(
106 object->variableAt(entry.scopeOffset()).get(), entry.getAttributes() | DontDelete);
107 return true;
108 }
109
110 template<typename SymbolTableObjectType>
111 inline bool symbolTableGet(
112 SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot,
113 bool& slotIsWriteable)
114 {
115 SymbolTable& symbolTable = *object->symbolTable();
116 ConcurrentJITLocker locker(symbolTable.m_lock);
117 SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
118 if (iter == symbolTable.end(locker))
119 return false;
120 SymbolTableEntry::Fast entry = iter->value;
121 ASSERT(!entry.isNull());
122 slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(entry.scopeOffset()).get());
123 slotIsWriteable = !entry.isReadOnly();
124 return true;
125 }
126
127 template<typename SymbolTableObjectType>
128 inline bool symbolTablePut(
129 SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value,
130 bool shouldThrow)
131 {
132 VM& vm = exec->vm();
133 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
134
135 WriteBarrierBase<Unknown>* reg;
136 WatchpointSet* set;
137 {
138 SymbolTable& symbolTable = *object->symbolTable();
139 // FIXME: This is very suspicious. We shouldn't need a GC-safe lock here.
140 // https://bugs.webkit.org/show_bug.cgi?id=134601
141 GCSafeConcurrentJITLocker locker(symbolTable.m_lock, exec->vm().heap);
142 SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
143 if (iter == symbolTable.end(locker))
144 return false;
145 bool wasFat;
146 SymbolTableEntry::Fast fastEntry = iter->value.getFast(wasFat);
147 ASSERT(!fastEntry.isNull());
148 if (fastEntry.isReadOnly()) {
149 if (shouldThrow)
150 throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
151 return true;
152 }
153 set = iter->value.watchpointSet();
154 reg = &object->variableAt(fastEntry.scopeOffset());
155 }
156 // I'd prefer we not hold lock while executing barriers, since I prefer to reserve
157 // the right for barriers to be able to trigger GC. And I don't want to hold VM
158 // locks while GC'ing.
159 reg->set(vm, object, value);
160 if (set)
161 VariableWriteFireDetail::touch(set, object, propertyName);
162 return true;
163 }
164
165 template<typename SymbolTableObjectType>
166 inline bool symbolTablePutWithAttributes(
167 SymbolTableObjectType* object, VM& vm, PropertyName propertyName,
168 JSValue value, unsigned attributes)
169 {
170 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
171
172 WriteBarrierBase<Unknown>* reg;
173 WatchpointSet* set;
174 {
175 SymbolTable& symbolTable = *object->symbolTable();
176 ConcurrentJITLocker locker(symbolTable.m_lock);
177 SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
178 if (iter == symbolTable.end(locker))
179 return false;
180 SymbolTableEntry& entry = iter->value;
181 ASSERT(!entry.isNull());
182 set = entry.watchpointSet();
183 entry.setAttributes(attributes);
184 reg = &object->variableAt(entry.scopeOffset());
185 }
186 reg->set(vm, object, value);
187 if (set)
188 VariableWriteFireDetail::touch(set, object, propertyName);
189 return true;
190 }
191
192 } // namespace JSC
193
194 #endif // JSSymbolTableObject_h
195