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 "JSObject.h" 34#include "JSString.h" 35#include "Structure.h" 36#include <wtf/CompilationThread.h> 37 38namespace JSC { 39 40inline JSCell::JSCell(CreatingEarlyCellTag) 41 : m_gcData(NotMarked) 42{ 43 ASSERT(!isCompilationThread()); 44} 45 46inline JSCell::JSCell(VM&, Structure* structure) 47 : m_structureID(structure->id()) 48 , m_indexingType(structure->indexingType()) 49 , m_type(structure->typeInfo().type()) 50 , m_flags(structure->typeInfo().inlineTypeFlags()) 51 , m_gcData(NotMarked) 52{ 53 ASSERT(!isCompilationThread()); 54} 55 56inline void JSCell::finishCreation(VM& vm) 57{ 58#if ENABLE(GC_VALIDATION) 59 ASSERT(vm.isInitializingObject()); 60 vm.setInitializingObjectClass(0); 61#else 62 UNUSED_PARAM(vm); 63#endif 64 ASSERT(m_structureID); 65} 66 67inline void JSCell::finishCreation(VM& vm, Structure* structure, CreatingEarlyCellTag) 68{ 69#if ENABLE(GC_VALIDATION) 70 ASSERT(vm.isInitializingObject()); 71 vm.setInitializingObjectClass(0); 72 if (structure) { 73#endif 74 m_structureID = structure->id(); 75 m_indexingType = structure->indexingType(); 76 m_type = structure->typeInfo().type(); 77 m_flags = structure->typeInfo().inlineTypeFlags(); 78#if ENABLE(GC_VALIDATION) 79 } 80#else 81 UNUSED_PARAM(vm); 82#endif 83 // Very first set of allocations won't have a real structure. 84 ASSERT(m_structureID || !vm.structureStructure); 85} 86 87inline JSType JSCell::type() const 88{ 89 return m_type; 90} 91 92inline IndexingType JSCell::indexingType() const 93{ 94 return m_indexingType; 95} 96 97inline Structure* JSCell::structure() const 98{ 99 return Heap::heap(this)->structureIDTable().get(m_structureID); 100} 101 102inline Structure* JSCell::structure(VM& vm) const 103{ 104 return vm.heap.structureIDTable().get(m_structureID); 105} 106 107inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor) 108{ 109 Structure* structure = cell->structure(visitor.vm()); 110 visitor.appendUnbarrieredPointer(&structure); 111} 112 113template<typename T> 114void* allocateCell(Heap& heap, size_t size) 115{ 116 ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread()); 117 ASSERT(size >= sizeof(T)); 118 JSCell* result = 0; 119 if (T::needsDestruction && T::hasImmortalStructure) 120 result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size)); 121 else if (T::needsDestruction) 122 result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size)); 123 else 124 result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size)); 125#if ENABLE(GC_VALIDATION) 126 ASSERT(!heap.vm()->isInitializingObject()); 127 heap.vm()->setInitializingObjectClass(T::info()); 128#endif 129 result->clearStructure(); 130 return result; 131} 132 133template<typename T> 134void* allocateCell(Heap& heap) 135{ 136 return allocateCell<T>(heap, sizeof(T)); 137} 138 139inline bool isZapped(const JSCell* cell) 140{ 141 return cell->isZapped(); 142} 143 144inline bool JSCell::isObject() const 145{ 146 return TypeInfo::isObject(m_type); 147} 148 149inline bool JSCell::isString() const 150{ 151 return m_type == StringType; 152} 153 154inline bool JSCell::isGetterSetter() const 155{ 156 return m_type == GetterSetterType; 157} 158 159inline bool JSCell::isCustomGetterSetter() const 160{ 161 return m_type == CustomGetterSetterType; 162} 163 164inline bool JSCell::isProxy() const 165{ 166 return m_type == ImpureProxyType || m_type == PureForwardingProxyType; 167} 168 169inline bool JSCell::isAPIValueWrapper() const 170{ 171 return m_type == APIValueWrapperType; 172} 173 174inline void JSCell::setStructure(VM& vm, Structure* structure) 175{ 176 ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren()); 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 188inline 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 198inline 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 207inline bool JSCell::inherits(const ClassInfo* info) const 208{ 209 return classInfo()->isSubClassOf(info); 210} 211 212// Fast call to get a property where we may not yet have converted the string to an 213// identifier. The first time we perform a property access with a given string, try 214// performing the property map lookup without forming an identifier. We detect this 215// case by checking whether the hash has yet been set for this string. 216ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, const String& name) 217{ 218 ASSERT(canUseFastGetOwnProperty(structure)); 219 PropertyOffset offset = name.impl()->hasHash() 220 ? structure.get(vm, Identifier(&vm, name)) 221 : structure.get(vm, name); 222 if (offset != invalidOffset) 223 return asObject(this)->locationForOffset(offset)->get(); 224 return JSValue(); 225} 226 227inline bool JSCell::canUseFastGetOwnProperty(const Structure& structure) 228{ 229 return !structure.hasGetterSetterProperties() 230 && !structure.hasCustomGetterSetterProperties() 231 && !structure.typeInfo().overridesGetOwnPropertySlot(); 232} 233 234inline bool JSCell::toBoolean(ExecState* exec) const 235{ 236 if (isString()) 237 return static_cast<const JSString*>(this)->toBoolean(); 238 return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject()); 239} 240 241inline TriState JSCell::pureToBoolean() const 242{ 243 if (isString()) 244 return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState; 245 return MixedTriState; 246} 247 248} // namespace JSC 249 250#endif // JSCellInlines_h 251