1 /* 2 * Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk (at) post.com) 4 * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved. 5 * 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. 10 * 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. 15 * 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. 20 * 21 */ 22 23 #ifndef JSCell_h 24 #define JSCell_h 25 26 #include "Collector.h" 27 #include "JSImmediate.h" 28 #include "JSValue.h" 29 #include "MarkStack.h" 30 #include "Structure.h" 31 #include <wtf/Noncopyable.h> 32 33 namespace JSC { 34 35 class JSCell : public NoncopyableCustomAllocated { 36 friend class GetterSetter; 37 friend class Heap; 38 friend class JIT; 39 friend class JSNumberCell; 40 friend class JSObject; 41 friend class JSPropertyNameIterator; 42 friend class JSString; 43 friend class JSValue; 44 friend class JSAPIValueWrapper; 45 friend class JSZombie; 46 friend class JSGlobalData; 47 48 private: 49 explicit JSCell(Structure*); 50 virtual ~JSCell(); 51 52 public: 53 static PassRefPtr<Structure> createDummyStructure() 54 { 55 return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount); 56 } 57 58 // Querying the type. 59 #if USE(JSVALUE32) 60 bool isNumber() const; 61 #endif 62 bool isString() const; 63 bool isObject() const; 64 virtual bool isGetterSetter() const; 65 bool inherits(const ClassInfo*) const; 66 virtual bool isAPIValueWrapper() const { return false; } 67 virtual bool isPropertyNameIterator() const { return false; } 68 69 Structure* structure() const; 70 71 // Extracting the value. 72 bool getString(ExecState* exec, UString&) const; 73 UString getString(ExecState* exec) const; // null string if not a string 74 JSObject* getObject(); // NULL if not an object 75 const JSObject* getObject() const; // NULL if not an object 76 77 virtual CallType getCallData(CallData&); 78 virtual ConstructType getConstructData(ConstructData&); 79 80 // Extracting integer values. 81 // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*. 82 virtual bool getUInt32(uint32_t&) const; 83 84 // Basic conversions. 85 virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; 86 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&); 87 virtual bool toBoolean(ExecState*) const; 88 virtual double toNumber(ExecState*) const; 89 virtual UString toString(ExecState*) const; 90 virtual JSObject* toObject(ExecState*) const; 91 92 // Garbage collection. 93 void* operator new(size_t, ExecState*); 94 void* operator new(size_t, JSGlobalData*); 95 void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; } 96 97 virtual void markChildren(MarkStack&); 98 #if ENABLE(JSC_ZOMBIES) 99 virtual bool isZombie() const { return false; } 100 #endif 101 102 // Object operations, with the toObject operation included. 103 virtual const ClassInfo* classInfo() const; 104 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); 105 virtual void put(ExecState*, unsigned propertyName, JSValue); 106 virtual bool deleteProperty(ExecState*, const Identifier& propertyName); 107 virtual bool deleteProperty(ExecState*, unsigned propertyName); 108 109 virtual JSObject* toThisObject(ExecState*) const; 110 virtual UString toThisString(ExecState*) const; 111 virtual JSString* toThisJSString(ExecState*); 112 virtual JSValue getJSNumber(); 113 void* vptr() { return *reinterpret_cast<void**>(this); } 114 void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; } 115 116 protected: 117 static const unsigned AnonymousSlotCount = 0; 118 119 private: 120 // Base implementation; for non-object classes implements getPropertySlot. 121 bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); 122 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); 123 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); 124 125 Structure* m_structure; 126 }; 127 128 inline JSCell::JSCell(Structure* structure) 129 : m_structure(structure) 130 { 131 } 132 133 inline JSCell::~JSCell() 134 { 135 } 136 137 #if USE(JSVALUE32) 138 inline bool JSCell::isNumber() const 139 { 140 return m_structure->typeInfo().type() == NumberType; 141 } 142 #endif 143 144 inline bool JSCell::isObject() const 145 { 146 return m_structure->typeInfo().type() == ObjectType; 147 } 148 149 inline bool JSCell::isString() const 150 { 151 return m_structure->typeInfo().type() == StringType; 152 } 153 154 inline Structure* JSCell::structure() const 155 { 156 return m_structure; 157 } 158 159 inline void JSCell::markChildren(MarkStack&) 160 { 161 } 162 163 inline void* JSCell::operator new(size_t size, JSGlobalData* globalData) 164 { 165 return globalData->heap.allocate(size); 166 } 167 168 inline void* JSCell::operator new(size_t size, ExecState* exec) 169 { 170 return exec->heap()->allocate(size); 171 } 172 173 // --- JSValue inlines ---------------------------- 174 175 inline bool JSValue::isString() const 176 { 177 return isCell() && asCell()->isString(); 178 } 179 180 inline bool JSValue::isGetterSetter() const 181 { 182 return isCell() && asCell()->isGetterSetter(); 183 } 184 185 inline bool JSValue::isObject() const 186 { 187 return isCell() && asCell()->isObject(); 188 } 189 190 inline bool JSValue::getString(ExecState* exec, UString& s) const 191 { 192 return isCell() && asCell()->getString(exec, s); 193 } 194 195 inline UString JSValue::getString(ExecState* exec) const 196 { 197 return isCell() ? asCell()->getString(exec) : UString(); 198 } 199 200 inline JSObject* JSValue::getObject() const 201 { 202 return isCell() ? asCell()->getObject() : 0; 203 } 204 205 inline CallType JSValue::getCallData(CallData& callData) 206 { 207 return isCell() ? asCell()->getCallData(callData) : CallTypeNone; 208 } 209 210 inline ConstructType JSValue::getConstructData(ConstructData& constructData) 211 { 212 return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone; 213 } 214 215 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const 216 { 217 if (isInt32()) { 218 int32_t i = asInt32(); 219 v = static_cast<uint32_t>(i); 220 return i >= 0; 221 } 222 if (isDouble()) { 223 double d = asDouble(); 224 v = static_cast<uint32_t>(d); 225 return v == d; 226 } 227 return false; 228 } 229 230 #if !USE(JSVALUE32_64) 231 ALWAYS_INLINE JSCell* JSValue::asCell() const 232 { 233 ASSERT(isCell()); 234 return m_ptr; 235 } 236 #endif // !USE(JSVALUE32_64) 237 238 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const 239 { 240 return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue(); 241 } 242 243 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) 244 { 245 if (isInt32()) { 246 number = asInt32(); 247 value = *this; 248 return true; 249 } 250 if (isDouble()) { 251 number = asDouble(); 252 value = *this; 253 return true; 254 } 255 if (isCell()) 256 return asCell()->getPrimitiveNumber(exec, number, value); 257 if (isTrue()) { 258 number = 1.0; 259 value = *this; 260 return true; 261 } 262 if (isFalse() || isNull()) { 263 number = 0.0; 264 value = *this; 265 return true; 266 } 267 ASSERT(isUndefined()); 268 number = nonInlineNaN(); 269 value = *this; 270 return true; 271 } 272 273 inline bool JSValue::toBoolean(ExecState* exec) const 274 { 275 if (isInt32()) 276 return asInt32() != 0; 277 if (isDouble()) 278 return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN 279 if (isCell()) 280 return asCell()->toBoolean(exec); 281 return isTrue(); // false, null, and undefined all convert to false. 282 } 283 284 ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const 285 { 286 if (isInt32()) 287 return asInt32(); 288 if (isDouble()) 289 return asDouble(); 290 if (isCell()) 291 return asCell()->toNumber(exec); 292 if (isTrue()) 293 return 1.0; 294 return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0. 295 } 296 297 inline bool JSValue::needsThisConversion() const 298 { 299 if (UNLIKELY(!isCell())) 300 return true; 301 return asCell()->structure()->typeInfo().needsThisConversion(); 302 } 303 304 inline UString JSValue::toThisString(ExecState* exec) const 305 { 306 return isCell() ? asCell()->toThisString(exec) : toString(exec); 307 } 308 309 inline JSValue JSValue::getJSNumber() 310 { 311 if (isInt32() || isDouble()) 312 return *this; 313 if (isCell()) 314 return asCell()->getJSNumber(); 315 return JSValue(); 316 } 317 318 inline JSObject* JSValue::toObject(ExecState* exec) const 319 { 320 return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec); 321 } 322 323 inline JSObject* JSValue::toThisObject(ExecState* exec) const 324 { 325 return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); 326 } 327 328 ALWAYS_INLINE void MarkStack::append(JSCell* cell) 329 { 330 ASSERT(!m_isCheckingForDefaultMarkViolation); 331 ASSERT(cell); 332 if (Heap::isCellMarked(cell)) 333 return; 334 Heap::markCell(cell); 335 if (cell->structure()->typeInfo().type() >= CompoundType) 336 m_values.append(cell); 337 } 338 339 ALWAYS_INLINE void MarkStack::append(JSValue value) 340 { 341 ASSERT(value); 342 if (value.isCell()) 343 append(value.asCell()); 344 } 345 346 inline Heap* Heap::heap(JSValue v) 347 { 348 if (!v.isCell()) 349 return 0; 350 return heap(v.asCell()); 351 } 352 353 inline Heap* Heap::heap(JSCell* c) 354 { 355 return cellBlock(c)->heap; 356 } 357 358 #if ENABLE(JSC_ZOMBIES) 359 inline bool JSValue::isZombie() const 360 { 361 return isCell() && asCell() && asCell()->isZombie(); 362 } 363 #endif 364 } // namespace JSC 365 366 #endif // JSCell_h 367