1/*
2 * Copyright (C) 2012, 2013, 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 * 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
41namespace JSC {
42
43inline JSCell::JSCell(CreatingEarlyCellTag)
44 : m_cellState(CellState::NewWhite)
45{
46 ASSERT(!isCompilationThread());
47}
48
49inline 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_cellState(CellState::NewWhite)
55{
56 ASSERT(!isCompilationThread());
57}
58
59inline 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
70inline 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
90inline JSType JSCell::type() const
91{
92 return m_type;
93}
94
95inline IndexingType JSCell::indexingType() const
96{
97 return m_indexingType;
98}
99
100inline Structure* JSCell::structure() const
101{
102 return Heap::heap(this)->structureIDTable().get(m_structureID);
103}
104
105inline Structure* JSCell::structure(VM& vm) const
106{
107 return vm.heap.structureIDTable().get(m_structureID);
108}
109
110inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
111{
112 Structure* structure = cell->structure(visitor.vm());
113 visitor.appendUnbarrieredPointer(&structure);
114}
115
116inline VM* JSCell::vm() const
117{
118 return MarkedBlock::blockFor(this)->vm();
119}
120
121inline VM& ExecState::vm() const
122{
123 ASSERT(callee());
124 ASSERT(callee()->vm());
125 return *calleeAsValue().asCell()->vm();
126}
127
128template<typename T>
129void* allocateCell(Heap& heap, size_t size)
130{
131 ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
132 ASSERT(size >= sizeof(T));
133 JSCell* result = static_cast<JSCell*>(heap.allocateObjectOfType<T>(size));
134#if ENABLE(GC_VALIDATION)
135 ASSERT(!heap.vm()->isInitializingObject());
136 heap.vm()->setInitializingObjectClass(T::info());
137#endif
138 result->clearStructure();
139 return result;
140}
141
142template<typename T>
143void* allocateCell(Heap& heap)
144{
145 return allocateCell<T>(heap, sizeof(T));
146}
147
148inline bool isZapped(const JSCell* cell)
149{
150 return cell->isZapped();
151}
152
153inline bool JSCell::isObject() const
154{
155 return TypeInfo::isObject(m_type);
156}
157
158inline bool JSCell::isString() const
159{
160 return m_type == StringType;
161}
162
163inline bool JSCell::isSymbol() const
164{
165 return m_type == SymbolType;
166}
167
168inline bool JSCell::isGetterSetter() const
169{
170 return m_type == GetterSetterType;
171}
172
173inline bool JSCell::isCustomGetterSetter() const
174{
175 return m_type == CustomGetterSetterType;
176}
177
178inline bool JSCell::isProxy() const
179{
180 return m_type == ImpureProxyType || m_type == PureForwardingProxyType;
181}
182
183inline bool JSCell::isAPIValueWrapper() const
184{
185 return m_type == APIValueWrapperType;
186}
187
188inline void JSCell::setStructure(VM& vm, Structure* structure)
189{
190 ASSERT(structure->classInfo() == this->structure()->classInfo());
191 ASSERT(!this->structure()
192 || this->structure()->transitionWatchpointSetHasBeenInvalidated()
193 || Heap::heap(this)->structureIDTable().get(structure->id()) == structure);
194 vm.heap.writeBarrier(this, structure);
195 m_structureID = structure->id();
196 m_flags = structure->typeInfo().inlineTypeFlags();
197 m_type = structure->typeInfo().type();
198 m_indexingType = structure->indexingType();
199}
200
201inline const MethodTable* JSCell::methodTable() const
202{
203 VM& vm = *Heap::heap(this)->vm();
204 Structure* structure = this->structure(vm);
205 if (Structure* rootStructure = structure->structure(vm))
206 RELEASE_ASSERT(rootStructure == rootStructure->structure(vm));
207
208 return &structure->classInfo()->methodTable;
209}
210
211inline const MethodTable* JSCell::methodTable(VM& vm) const
212{
213 Structure* structure = this->structure(vm);
214 if (Structure* rootStructure = structure->structure(vm))
215 RELEASE_ASSERT(rootStructure == rootStructure->structure(vm));
216
217 return &structure->classInfo()->methodTable;
218}
219
220inline bool JSCell::inherits(const ClassInfo* info) const
221{
222 return classInfo()->isSubClassOf(info);
223}
224
225ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, PropertyName name)
226{
227 ASSERT(canUseFastGetOwnProperty(structure));
228 PropertyOffset offset = structure.get(vm, name);
229 if (offset != invalidOffset)
230 return asObject(this)->locationForOffset(offset)->get();
231 return JSValue();
232}
233
234inline bool JSCell::canUseFastGetOwnProperty(const Structure& structure)
235{
236 return !structure.hasGetterSetterProperties()
237 && !structure.hasCustomGetterSetterProperties()
238 && !structure.typeInfo().overridesGetOwnPropertySlot();
239}
240
241inline const ClassInfo* JSCell::classInfo() const
242{
243 MarkedBlock* block = MarkedBlock::blockFor(this);
244 if (block->needsDestruction() && !(inlineTypeFlags() & StructureIsImmortal))
245 return static_cast<const JSDestructibleObject*>(this)->classInfo();
246 return structure(*block->vm())->classInfo();
247}
248
249inline bool JSCell::toBoolean(ExecState* exec) const
250{
251 if (isString())
252 return static_cast<const JSString*>(this)->toBoolean();
253 return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
254}
255
256inline TriState JSCell::pureToBoolean() const
257{
258 if (isString())
259 return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
260 if (isSymbol())
261 return TrueTriState;
262 return MixedTriState;
263}
264
265} // namespace JSC
266
267#endif // JSCellInlines_h
268