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