Foo::s_info should be Foo::info(), so that you can change how the s_info is actually...
[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 "Handle.h"
31 #include "JSCell.h"
32 #include "JSObject.h"
33 #include "JSString.h"
34 #include "Structure.h"
35 #include <wtf/CompilationThread.h>
36
37 namespace JSC {
38
39 inline JSCell::JSCell(CreatingEarlyCellTag)
40 {
41     ASSERT(!isCompilationThread());
42 }
43
44 inline JSCell::JSCell(VM& vm, Structure* structure)
45     : m_structure(vm, this, structure)
46 {
47     ASSERT(!isCompilationThread());
48 }
49
50 inline void JSCell::finishCreation(VM& vm)
51 {
52 #if ENABLE(GC_VALIDATION)
53     ASSERT(vm.isInitializingObject());
54     vm.setInitializingObjectClass(0);
55 #else
56     UNUSED_PARAM(vm);
57 #endif
58     ASSERT(m_structure);
59 }
60
61 inline void JSCell::finishCreation(VM& vm, Structure* structure, CreatingEarlyCellTag)
62 {
63 #if ENABLE(GC_VALIDATION)
64     ASSERT(vm.isInitializingObject());
65     vm.setInitializingObjectClass(0);
66     if (structure)
67 #endif
68         m_structure.setEarlyValue(vm, this, structure);
69     // Very first set of allocations won't have a real structure.
70     ASSERT(m_structure || !vm.structureStructure);
71 }
72
73 inline Structure* JSCell::structure() const
74 {
75     return m_structure.get();
76 }
77
78 inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
79 {
80     MARK_LOG_PARENT(visitor, cell);
81
82     visitor.append(&cell->m_structure);
83 }
84
85 template<typename T>
86 void* allocateCell(Heap& heap, size_t size)
87 {
88     ASSERT(size >= sizeof(T));
89 #if ENABLE(GC_VALIDATION)
90     ASSERT(!heap.vm()->isInitializingObject());
91     heap.vm()->setInitializingObjectClass(T::info());
92 #endif
93     JSCell* result = 0;
94     if (T::needsDestruction && T::hasImmortalStructure)
95         result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
96     else if (T::needsDestruction)
97         result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
98     else 
99         result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size));
100     result->clearStructure();
101     return result;
102 }
103     
104 template<typename T>
105 void* allocateCell(Heap& heap)
106 {
107     return allocateCell<T>(heap, sizeof(T));
108 }
109     
110 inline bool isZapped(const JSCell* cell)
111 {
112     return cell->isZapped();
113 }
114
115 inline bool JSCell::isObject() const
116 {
117     return m_structure->isObject();
118 }
119
120 inline bool JSCell::isString() const
121 {
122     return m_structure->typeInfo().type() == StringType;
123 }
124
125 inline bool JSCell::isGetterSetter() const
126 {
127     return m_structure->typeInfo().type() == GetterSetterType;
128 }
129
130 inline bool JSCell::isProxy() const
131 {
132     return structure()->typeInfo().type() == ProxyType;
133 }
134
135 inline bool JSCell::isAPIValueWrapper() const
136 {
137     return m_structure->typeInfo().type() == APIValueWrapperType;
138 }
139
140 inline void JSCell::setStructure(VM& vm, Structure* structure)
141 {
142     ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren());
143     ASSERT(structure->classInfo() == m_structure->classInfo());
144     ASSERT(!m_structure
145         || m_structure->transitionWatchpointSetHasBeenInvalidated()
146         || m_structure.get() == structure);
147     m_structure.set(vm, this, structure);
148 }
149
150 inline const MethodTable* JSCell::methodTableForDestruction() const
151 {
152     return &classInfo()->methodTable;
153 }
154
155 inline const MethodTable* JSCell::methodTable() const
156 {
157     if (Structure* rootStructure = m_structure->structure())
158         RELEASE_ASSERT(rootStructure == rootStructure->structure());
159
160     return &classInfo()->methodTable;
161 }
162
163 inline bool JSCell::inherits(const ClassInfo* info) const
164 {
165     return classInfo()->isSubClassOf(info);
166 }
167
168 // Fast call to get a property where we may not yet have converted the string to an
169 // identifier. The first time we perform a property access with a given string, try
170 // performing the property map lookup without forming an identifier. We detect this
171 // case by checking whether the hash has yet been set for this string.
172 ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const String& name)
173 {
174     if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) {
175         PropertyOffset offset = name.impl()->hasHash()
176             ? structure()->get(exec->vm(), Identifier(exec, name))
177             : structure()->get(exec->vm(), name);
178         if (offset != invalidOffset)
179             return asObject(this)->locationForOffset(offset)->get();
180     }
181     return JSValue();
182 }
183
184 inline bool JSCell::toBoolean(ExecState* exec) const
185 {
186     if (isString()) 
187         return static_cast<const JSString*>(this)->toBoolean();
188     return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
189 }
190
191 inline TriState JSCell::pureToBoolean() const
192 {
193     if (isString()) 
194         return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
195     return MixedTriState;
196 }
197
198 } // namespace JSC
199
200 #endif // JSCellInlines_h