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