2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
27 #include "CallFrame.h"
28 #include "ConstructData.h"
31 #include "JSValueInlineMethods.h"
32 #include "SlotVisitor.h"
33 #include "WriteBarrier.h"
34 #include <wtf/Noncopyable.h>
39 class LLIntOffsetsExtractor
;
40 class PropertyDescriptor
;
41 class PropertyNameArray
;
44 enum EnumerationMode
{
45 ExcludeDontEnumProperties
,
46 IncludeDontEnumProperties
55 TypedArrayUint8Clamped
,
64 friend class MarkedBlock
;
65 template<typename T
> friend void* allocateCell(Heap
&);
68 enum CreatingEarlyCellTag
{ CreatingEarlyCell
};
69 JSCell(CreatingEarlyCellTag
);
72 JSCell(JSGlobalData
&, Structure
*);
73 JS_EXPORT_PRIVATE
static void destroy(JSCell
*);
77 bool isString() const;
78 bool isObject() const;
79 bool isGetterSetter() const;
80 bool inherits(const ClassInfo
*) const;
81 bool isAPIValueWrapper() const;
83 Structure
* structure() const;
84 void setStructure(JSGlobalData
&, Structure
*);
85 void clearStructure() { m_structure
.clear(); }
87 // Extracting the value.
88 JS_EXPORT_PRIVATE
bool getString(ExecState
* exec
, UString
&) const;
89 JS_EXPORT_PRIVATE UString
getString(ExecState
* exec
) const; // null string if not a string
90 JS_EXPORT_PRIVATE JSObject
* getObject(); // NULL if not an object
91 const JSObject
* getObject() const; // NULL if not an object
93 JS_EXPORT_PRIVATE
static CallType
getCallData(JSCell
*, CallData
&);
94 JS_EXPORT_PRIVATE
static ConstructType
getConstructData(JSCell
*, ConstructData
&);
97 JS_EXPORT_PRIVATE JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
) const;
98 bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
&) const;
99 bool toBoolean(ExecState
*) const;
100 JS_EXPORT_PRIVATE
double toNumber(ExecState
*) const;
101 JS_EXPORT_PRIVATE JSObject
* toObject(ExecState
*, JSGlobalObject
*) const;
103 static void visitChildren(JSCell
*, SlotVisitor
&);
105 // Object operations, with the toObject operation included.
106 const ClassInfo
* classInfo() const;
107 const ClassInfo
* validatedClassInfo() const;
108 const MethodTable
* methodTable() const;
109 static void put(JSCell
*, ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
110 static void putByIndex(JSCell
*, ExecState
*, unsigned propertyName
, JSValue
, bool shouldThrow
);
112 static bool deleteProperty(JSCell
*, ExecState
*, const Identifier
& propertyName
);
113 static bool deletePropertyByIndex(JSCell
*, ExecState
*, unsigned propertyName
);
115 static JSObject
* toThisObject(JSCell
*, ExecState
*);
117 void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
118 bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
120 // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
121 // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
122 // call this function, not its slower virtual counterpart. (For integer
123 // property names, we want a similar interface with appropriate optimizations.)
124 bool fastGetOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
125 JSValue
fastGetOwnProperty(ExecState
*, const UString
&);
127 static ptrdiff_t structureOffset()
129 return OBJECT_OFFSETOF(JSCell
, m_structure
);
132 static ptrdiff_t classInfoOffset()
134 return OBJECT_OFFSETOF(JSCell
, m_classInfo
);
137 void* structureAddress()
142 #if ENABLE(GC_VALIDATION)
143 Structure
* unvalidatedStructure() { return m_structure
.unvalidatedGet(); }
146 static const TypedArrayType TypedArrayStorageType
= TypedArrayNone
;
149 void finishCreation(JSGlobalData
&);
150 void finishCreation(JSGlobalData
&, Structure
*, CreatingEarlyCellTag
);
152 // Base implementation; for non-object classes implements getPropertySlot.
153 static bool getOwnPropertySlot(JSCell
*, ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
154 static bool getOwnPropertySlotByIndex(JSCell
*, ExecState
*, unsigned propertyName
, PropertySlot
&);
156 // Dummy implementations of override-able static functions for classes to put in their MethodTable
157 static JSValue
defaultValue(const JSObject
*, ExecState
*, PreferredPrimitiveType
);
158 static NO_RETURN_DUE_TO_ASSERT
void getOwnPropertyNames(JSObject
*, ExecState
*, PropertyNameArray
&, EnumerationMode
);
159 static NO_RETURN_DUE_TO_ASSERT
void getPropertyNames(JSObject
*, ExecState
*, PropertyNameArray
&, EnumerationMode
);
160 static UString
className(const JSObject
*);
161 static bool hasInstance(JSObject
*, ExecState
*, JSValue
, JSValue prototypeProperty
);
162 static NO_RETURN_DUE_TO_ASSERT
void putDirectVirtual(JSObject
*, ExecState
*, const Identifier
& propertyName
, JSValue
, unsigned attributes
);
163 static bool defineOwnProperty(JSObject
*, ExecState
*, const Identifier
& propertyName
, PropertyDescriptor
&, bool shouldThrow
);
164 static bool getOwnPropertyDescriptor(JSObject
*, ExecState
*, const Identifier
&, PropertyDescriptor
&);
167 friend class LLIntOffsetsExtractor
;
169 const ClassInfo
* m_classInfo
;
170 WriteBarrier
<Structure
> m_structure
;
173 inline JSCell::JSCell(CreatingEarlyCellTag
)
177 inline void JSCell::finishCreation(JSGlobalData
& globalData
)
179 #if ENABLE(GC_VALIDATION)
180 ASSERT(globalData
.isInitializingObject());
181 globalData
.setInitializingObjectClass(0);
183 UNUSED_PARAM(globalData
);
188 inline Structure
* JSCell::structure() const
190 return m_structure
.get();
193 inline const ClassInfo
* JSCell::classInfo() const
198 inline void JSCell::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
200 visitor
.append(&cell
->m_structure
);
203 // --- JSValue inlines ----------------------------
205 inline bool JSValue::isString() const
207 return isCell() && asCell()->isString();
210 inline bool JSValue::isPrimitive() const
212 return !isCell() || asCell()->isString();
215 inline bool JSValue::isGetterSetter() const
217 return isCell() && asCell()->isGetterSetter();
220 inline bool JSValue::isObject() const
222 return isCell() && asCell()->isObject();
225 inline bool JSValue::getString(ExecState
* exec
, UString
& s
) const
227 return isCell() && asCell()->getString(exec
, s
);
230 inline UString
JSValue::getString(ExecState
* exec
) const
232 return isCell() ? asCell()->getString(exec
) : UString();
235 template <typename Base
> UString HandleConverter
<Base
, Unknown
>::getString(ExecState
* exec
) const
237 return jsValue().getString(exec
);
240 inline JSObject
* JSValue::getObject() const
242 return isCell() ? asCell()->getObject() : 0;
245 ALWAYS_INLINE
bool JSValue::getUInt32(uint32_t& v
) const
248 int32_t i
= asInt32();
249 v
= static_cast<uint32_t>(i
);
253 double d
= asDouble();
254 v
= static_cast<uint32_t>(d
);
260 inline JSValue
JSValue::toPrimitive(ExecState
* exec
, PreferredPrimitiveType preferredType
) const
262 return isCell() ? asCell()->toPrimitive(exec
, preferredType
) : asValue();
265 inline bool JSValue::getPrimitiveNumber(ExecState
* exec
, double& number
, JSValue
& value
)
278 return asCell()->getPrimitiveNumber(exec
, number
, value
);
284 if (isFalse() || isNull()) {
289 ASSERT(isUndefined());
290 number
= std::numeric_limits
<double>::quiet_NaN();
295 ALWAYS_INLINE
double JSValue::toNumber(ExecState
* exec
) const
301 return toNumberSlowCase(exec
);
304 inline JSObject
* JSValue::toObject(ExecState
* exec
) const
306 return isCell() ? asCell()->toObject(exec
, exec
->lexicalGlobalObject()) : toObjectSlowCase(exec
, exec
->lexicalGlobalObject());
309 inline JSObject
* JSValue::toObject(ExecState
* exec
, JSGlobalObject
* globalObject
) const
311 return isCell() ? asCell()->toObject(exec
, globalObject
) : toObjectSlowCase(exec
, globalObject
);
316 struct NeedsDestructor
{
317 static const bool value
= !__has_trivial_destructor(T
);
320 // Write manual specializations for this struct template if you care about non-clang compilers.
322 struct NeedsDestructor
{
323 static const bool value
= true;
328 void* allocateCell(Heap
& heap
)
330 #if ENABLE(GC_VALIDATION)
331 ASSERT(!heap
.globalData()->isInitializingObject());
332 heap
.globalData()->setInitializingObjectClass(&T::s_info
);
335 if (NeedsDestructor
<T
>::value
)
336 result
= static_cast<JSCell
*>(heap
.allocateWithDestructor(sizeof(T
)));
338 ASSERT(T::s_info
.methodTable
.destroy
== JSCell::destroy
);
339 result
= static_cast<JSCell
*>(heap
.allocateWithoutDestructor(sizeof(T
)));
341 result
->clearStructure();
345 inline bool isZapped(const JSCell
* cell
)
347 return cell
->isZapped();
350 template<typename To
, typename From
>
351 inline To
jsCast(From
* from
)
353 ASSERT(!from
|| from
->JSCell::inherits(&WTF::RemovePointer
<To
>::Type::s_info
));
354 return static_cast<To
>(from
);
357 template<typename To
>
358 inline To
jsCast(JSValue from
)
360 ASSERT(from
.isCell() && from
.asCell()->JSCell::inherits(&WTF::RemovePointer
<To
>::Type::s_info
));
361 return static_cast<To
>(from
.asCell());
364 template<typename To
, typename From
>
365 inline To
jsDynamicCast(From
* from
)
367 return from
->inherits(&WTF::RemovePointer
<To
>::Type::s_info
) ? static_cast<To
>(from
) : 0;
370 template<typename To
>
371 inline To
jsDynamicCast(JSValue from
)
373 return from
.isCell() && from
.asCell()->inherits(&WTF::RemovePointer
<To
>::Type::s_info
) ? static_cast<To
>(from
.asCell()) : 0;