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