Implement ES6 Symbol
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSCellInlines.h
1 /*
2  * Copyright (C) 2012, 2013 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 #ifndef JSCellInlines_h
27 #define JSCellInlines_h
28
29 #include "CallFrame.h"
30 #include "DeferGC.h"
31 #include "Handle.h"
32 #include "JSCell.h"
33 #include "JSDestructibleObject.h"
34 #include "JSObject.h"
35 #include "JSString.h"
36 #include "MarkedBlock.h"
37 #include "Structure.h"
38 #include "Symbol.h"
39 #include <wtf/CompilationThread.h>
40
41 namespace JSC {
42
43 inline JSCell::JSCell(CreatingEarlyCellTag)
44     : m_gcData(NotMarked)
45 {
46     ASSERT(!isCompilationThread());
47 }
48
49 inline JSCell::JSCell(VM&, Structure* structure)
50     : m_structureID(structure->id())
51     , m_indexingType(structure->indexingType())
52     , m_type(structure->typeInfo().type())
53     , m_flags(structure->typeInfo().inlineTypeFlags())
54     , m_gcData(NotMarked)
55 {
56     ASSERT(!isCompilationThread());
57 }
58
59 inline void JSCell::finishCreation(VM& vm)
60 {
61 #if ENABLE(GC_VALIDATION)
62     ASSERT(vm.isInitializingObject());
63     vm.setInitializingObjectClass(0);
64 #else
65     UNUSED_PARAM(vm);
66 #endif
67     ASSERT(m_structureID);
68 }
69
70 inline void JSCell::finishCreation(VM& vm, Structure* structure, CreatingEarlyCellTag)
71 {
72 #if ENABLE(GC_VALIDATION)
73     ASSERT(vm.isInitializingObject());
74     vm.setInitializingObjectClass(0);
75     if (structure) {
76 #endif
77         m_structureID = structure->id();
78         m_indexingType = structure->indexingType();
79         m_type = structure->typeInfo().type();
80         m_flags = structure->typeInfo().inlineTypeFlags();
81 #if ENABLE(GC_VALIDATION)
82     }
83 #else
84     UNUSED_PARAM(vm);
85 #endif
86     // Very first set of allocations won't have a real structure.
87     ASSERT(m_structureID || !vm.structureStructure);
88 }
89
90 inline JSType JSCell::type() const
91 {
92     return m_type;
93 }
94
95 inline IndexingType JSCell::indexingType() const
96 {
97     return m_indexingType;
98 }
99
100 inline Structure* JSCell::structure() const
101 {
102     return Heap::heap(this)->structureIDTable().get(m_structureID);
103 }
104
105 inline Structure* JSCell::structure(VM& vm) const
106 {
107     return vm.heap.structureIDTable().get(m_structureID);
108 }
109
110 inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
111 {
112     Structure* structure = cell->structure(visitor.vm());
113     visitor.appendUnbarrieredPointer(&structure);
114 }
115
116 inline VM* JSCell::vm() const
117 {
118     return MarkedBlock::blockFor(this)->vm();
119 }
120
121 inline VM& ExecState::vm() const
122 {
123     ASSERT(callee()->vm());
124     return *callee()->vm();
125 }
126
127 template<typename T>
128 void* allocateCell(Heap& heap, size_t size)
129 {
130     ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
131     ASSERT(size >= sizeof(T));
132     JSCell* result = 0;
133     if (T::needsDestruction && T::hasImmortalStructure)
134         result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
135     else if (T::needsDestruction)
136         result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
137     else 
138         result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size));
139 #if ENABLE(GC_VALIDATION)
140     ASSERT(!heap.vm()->isInitializingObject());
141     heap.vm()->setInitializingObjectClass(T::info());
142 #endif
143     result->clearStructure();
144     return result;
145 }
146     
147 template<typename T>
148 void* allocateCell(Heap& heap)
149 {
150     return allocateCell<T>(heap, sizeof(T));
151 }
152     
153 inline bool isZapped(const JSCell* cell)
154 {
155     return cell->isZapped();
156 }
157
158 inline bool JSCell::isObject() const
159 {
160     return TypeInfo::isObject(m_type);
161 }
162
163 inline bool JSCell::isString() const
164 {
165     return m_type == StringType;
166 }
167
168 inline bool JSCell::isSymbol() const
169 {
170     return m_type == SymbolType;
171 }
172
173 inline bool JSCell::isGetterSetter() const
174 {
175     return m_type == GetterSetterType;
176 }
177
178 inline bool JSCell::isCustomGetterSetter() const
179 {
180     return m_type == CustomGetterSetterType;
181 }
182
183 inline bool JSCell::isProxy() const
184 {
185     return m_type == ImpureProxyType || m_type == PureForwardingProxyType;
186 }
187
188 inline bool JSCell::isAPIValueWrapper() const
189 {
190     return m_type == APIValueWrapperType;
191 }
192
193 inline void JSCell::setStructure(VM& vm, Structure* structure)
194 {
195     ASSERT(structure->classInfo() == this->structure()->classInfo());
196     ASSERT(!this->structure()
197         || this->structure()->transitionWatchpointSetHasBeenInvalidated()
198         || Heap::heap(this)->structureIDTable().get(structure->id()) == structure);
199     vm.heap.writeBarrier(this, structure);
200     m_structureID = structure->id();
201     m_flags = structure->typeInfo().inlineTypeFlags();
202     m_type = structure->typeInfo().type();
203     m_indexingType = structure->indexingType();
204 }
205
206 inline const MethodTable* JSCell::methodTable() const
207 {
208     VM& vm = *Heap::heap(this)->vm();
209     Structure* structure = this->structure(vm);
210     if (Structure* rootStructure = structure->structure(vm))
211         RELEASE_ASSERT(rootStructure == rootStructure->structure(vm));
212
213     return &structure->classInfo()->methodTable;
214 }
215
216 inline const MethodTable* JSCell::methodTable(VM& vm) const
217 {
218     Structure* structure = this->structure(vm);
219     if (Structure* rootStructure = structure->structure(vm))
220         RELEASE_ASSERT(rootStructure == rootStructure->structure(vm));
221
222     return &structure->classInfo()->methodTable;
223 }
224
225 inline bool JSCell::inherits(const ClassInfo* info) const
226 {
227     return classInfo()->isSubClassOf(info);
228 }
229
230 ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, PropertyName name)
231 {
232     ASSERT(canUseFastGetOwnProperty(structure));
233     PropertyOffset offset = structure.get(vm, name);
234     if (offset != invalidOffset)
235         return asObject(this)->locationForOffset(offset)->get();
236     return JSValue();
237 }
238
239 inline bool JSCell::canUseFastGetOwnProperty(const Structure& structure)
240 {
241     return !structure.hasGetterSetterProperties() 
242         && !structure.hasCustomGetterSetterProperties()
243         && !structure.typeInfo().overridesGetOwnPropertySlot();
244 }
245
246 inline const ClassInfo* JSCell::classInfo() const
247 {
248     MarkedBlock* block = MarkedBlock::blockFor(this);
249     if (block->destructorType() == MarkedBlock::Normal)
250         return static_cast<const JSDestructibleObject*>(this)->classInfo();
251     return structure(*block->vm())->classInfo();
252 }
253
254 inline bool JSCell::toBoolean(ExecState* exec) const
255 {
256     if (isString())
257         return static_cast<const JSString*>(this)->toBoolean();
258     if (isSymbol())
259         return static_cast<const Symbol*>(this)->toBoolean();
260     return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
261 }
262
263 inline TriState JSCell::pureToBoolean() const
264 {
265     if (isString())
266         return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
267     if (isSymbol())
268         return static_cast<const Symbol*>(this)->toBoolean() ? TrueTriState : FalseTriState;
269     return MixedTriState;
270 }
271
272 } // namespace JSC
273
274 #endif // JSCellInlines_h