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