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>
40 class PropertyDescriptor;
41 class PropertyNameArray;
43 enum EnumerationMode {
44 ExcludeDontEnumProperties,
45 IncludeDontEnumProperties
62 friend class MarkedBlock;
65 enum CreatingEarlyCellTag { CreatingEarlyCell };
66 JSCell(CreatingEarlyCellTag);
68 enum VPtrStealingHackType { VPtrStealingHack };
69 explicit JSCell(VPtrStealingHackType) { }
72 void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; } // Used for initialization after GC allocation.
75 JSCell(JSGlobalData&, Structure*);
76 virtual ~JSCell(); // Invoked by GC finalization.
80 bool isString() const;
81 bool isObject() const;
82 bool isGetterSetter() const;
83 bool inherits(const ClassInfo*) const;
84 bool isAPIValueWrapper() const;
86 Structure* structure() const;
87 void setStructure(JSGlobalData&, Structure*);
88 void clearStructure() { m_structure.clear(); }
90 // Extracting the value.
91 bool getString(ExecState* exec, UString&) const;
92 UString getString(ExecState* exec) const; // null string if not a string
93 JSObject* getObject(); // NULL if not an object
94 const JSObject* getObject() const; // NULL if not an object
96 static CallType getCallData(JSCell*, CallData&);
97 static ConstructType getConstructData(JSCell*, ConstructData&);
100 JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
101 bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
102 bool toBoolean(ExecState*) const;
103 double toNumber(ExecState*) const;
104 UString toString(ExecState*) const;
105 JSObject* toObject(ExecState*, JSGlobalObject*) const;
107 static void visitChildren(JSCell*, SlotVisitor&);
109 // Object operations, with the toObject operation included.
110 const ClassInfo* classInfo() const;
111 const MethodTable* methodTable() const;
112 static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
113 static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
115 static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
116 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
118 static JSObject* toThisObject(JSCell*, ExecState*);
120 void* vptr() const { ASSERT(!isZapped()); return *reinterpret_cast<void* const*>(this); }
121 void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; ASSERT(!isZapped()); }
122 void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
123 bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
125 // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
126 // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
127 // call this function, not its slower virtual counterpart. (For integer
128 // property names, we want a similar interface with appropriate optimizations.)
129 bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
130 JSValue fastGetOwnProperty(ExecState*, const UString&);
132 static ptrdiff_t structureOffset()
134 return OBJECT_OFFSETOF(JSCell, m_structure);
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 NO_RETURN_DUE_TO_ASSERT void defineGetter(JSObject*, ExecState*, const Identifier&, JSObject*, unsigned);
158 static NO_RETURN_DUE_TO_ASSERT void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
159 static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
160 static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
161 static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
162 static UString className(const JSObject*);
163 static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
164 static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
165 static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
166 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
169 WriteBarrier<Structure> m_structure;
172 inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
173 : m_structure(globalData, this, structure)
177 inline JSCell::JSCell(CreatingEarlyCellTag)
181 inline void JSCell::finishCreation(JSGlobalData& globalData)
183 #if ENABLE(GC_VALIDATION)
184 ASSERT(globalData.isInitializingObject());
185 globalData.setInitializingObject(false);
187 UNUSED_PARAM(globalData);
192 inline void JSCell::finishCreation(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
194 #if ENABLE(GC_VALIDATION)
195 ASSERT(globalData.isInitializingObject());
196 globalData.setInitializingObject(false);
199 m_structure.setEarlyValue(globalData, this, structure);
200 // Very first set of allocations won't have a real structure.
201 ASSERT(m_structure || !globalData.structureStructure);
204 inline JSCell::~JSCell()
208 inline Structure* JSCell::structure() const
210 return m_structure.get();
213 inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
215 visitor.append(&cell->m_structure);
218 // --- JSValue inlines ----------------------------
220 inline bool JSValue::isString() const
222 return isCell() && asCell()->isString();
225 inline bool JSValue::isPrimitive() const
227 return !isCell() || asCell()->isString();
230 inline bool JSValue::isGetterSetter() const
232 return isCell() && asCell()->isGetterSetter();
235 inline bool JSValue::isObject() const
237 return isCell() && asCell()->isObject();
240 inline bool JSValue::getString(ExecState* exec, UString& s) const
242 return isCell() && asCell()->getString(exec, s);
245 inline UString JSValue::getString(ExecState* exec) const
247 return isCell() ? asCell()->getString(exec) : UString();
250 template <typename Base> UString HandleConverter<Base, Unknown>::getString(ExecState* exec) const
252 return jsValue().getString(exec);
255 inline JSObject* JSValue::getObject() const
257 return isCell() ? asCell()->getObject() : 0;
260 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
263 int32_t i = asInt32();
264 v = static_cast<uint32_t>(i);
268 double d = asDouble();
269 v = static_cast<uint32_t>(d);
275 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
277 return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
280 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
293 return asCell()->getPrimitiveNumber(exec, number, value);
299 if (isFalse() || isNull()) {
304 ASSERT(isUndefined());
305 number = std::numeric_limits<double>::quiet_NaN();
310 ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
316 return toNumberSlowCase(exec);
319 inline JSObject* JSValue::toObject(ExecState* exec) const
321 return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
324 inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
326 return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
329 template <typename T> void* allocateCell(Heap& heap)
331 #if ENABLE(GC_VALIDATION)
332 ASSERT(sizeof(T) == T::s_info.cellSize);
333 ASSERT(!heap.globalData()->isInitializingObject());
334 heap.globalData()->setInitializingObject(true);
336 JSCell* result = static_cast<JSCell*>(heap.allocate(sizeof(T)));
337 result->clearStructure();
341 inline bool isZapped(const JSCell* cell)
343 return cell->isZapped();
346 template<typename To, typename From>
347 inline To jsCast(From* from)
349 ASSERT(from->inherits(&WTF::RemovePointer<To>::Type::s_info));
350 return static_cast<To>(from);
353 template<typename To, typename From>
354 inline To jsDynamicCast(From* from)
356 return from->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from) : 0;