diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSCellInlines.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSCellInlines.h | 172 |
1 files changed, 117 insertions, 55 deletions
diff --git a/Source/JavaScriptCore/runtime/JSCellInlines.h b/Source/JavaScriptCore/runtime/JSCellInlines.h index 1b2d13ada..4274c216f 100644 --- a/Source/JavaScriptCore/runtime/JSCellInlines.h +++ b/Source/JavaScriptCore/runtime/JSCellInlines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,22 +27,33 @@ #define JSCellInlines_h #include "CallFrame.h" +#include "DeferGC.h" #include "Handle.h" #include "JSCell.h" +#include "JSDestructibleObject.h" #include "JSObject.h" #include "JSString.h" +#include "MarkedBlock.h" #include "Structure.h" -#include "StructureInlines.h" +#include "Symbol.h" +#include <wtf/CompilationThread.h> namespace JSC { inline JSCell::JSCell(CreatingEarlyCellTag) + : m_cellState(CellState::NewWhite) { + ASSERT(!isCompilationThread()); } -inline JSCell::JSCell(VM& vm, Structure* structure) - : m_structure(vm, this, structure) +inline JSCell::JSCell(VM&, Structure* structure) + : m_structureID(structure->id()) + , m_indexingType(structure->indexingType()) + , m_type(structure->typeInfo().type()) + , m_flags(structure->typeInfo().inlineTypeFlags()) + , m_cellState(CellState::NewWhite) { + ASSERT(!isCompilationThread()); } inline void JSCell::finishCreation(VM& vm) @@ -53,7 +64,7 @@ inline void JSCell::finishCreation(VM& vm) #else UNUSED_PARAM(vm); #endif - ASSERT(m_structure); + ASSERT(m_structureID); } inline void JSCell::finishCreation(VM& vm, Structure* structure, CreatingEarlyCellTag) @@ -61,40 +72,69 @@ inline void JSCell::finishCreation(VM& vm, Structure* structure, CreatingEarlyCe #if ENABLE(GC_VALIDATION) ASSERT(vm.isInitializingObject()); vm.setInitializingObjectClass(0); - if (structure) + if (structure) { +#endif + m_structureID = structure->id(); + m_indexingType = structure->indexingType(); + m_type = structure->typeInfo().type(); + m_flags = structure->typeInfo().inlineTypeFlags(); +#if ENABLE(GC_VALIDATION) + } +#else + UNUSED_PARAM(vm); #endif - m_structure.setEarlyValue(vm, this, structure); // Very first set of allocations won't have a real structure. - ASSERT(m_structure || !vm.structureStructure); + ASSERT(m_structureID || !vm.structureStructure); +} + +inline JSType JSCell::type() const +{ + return m_type; +} + +inline IndexingType JSCell::indexingType() const +{ + return m_indexingType; } inline Structure* JSCell::structure() const { - return m_structure.get(); + return Heap::heap(this)->structureIDTable().get(m_structureID); +} + +inline Structure* JSCell::structure(VM& vm) const +{ + return vm.heap.structureIDTable().get(m_structureID); } inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor) { - MARK_LOG_PARENT(visitor, cell); + Structure* structure = cell->structure(visitor.vm()); + visitor.appendUnbarrieredPointer(&structure); +} + +inline VM* JSCell::vm() const +{ + return MarkedBlock::blockFor(this)->vm(); +} - visitor.append(&cell->m_structure); +inline VM& ExecState::vm() const +{ + ASSERT(callee()); + ASSERT(callee()->vm()); + return *calleeAsValue().asCell()->vm(); } template<typename T> void* allocateCell(Heap& heap, size_t size) { + ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread()); ASSERT(size >= sizeof(T)); + JSCell* result = static_cast<JSCell*>(heap.allocateObjectOfType<T>(size)); #if ENABLE(GC_VALIDATION) ASSERT(!heap.vm()->isInitializingObject()); - heap.vm()->setInitializingObjectClass(&T::s_info); + heap.vm()->setInitializingObjectClass(T::info()); #endif - JSCell* result = 0; - if (T::needsDestruction && T::hasImmortalStructure) - result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size)); - else if (T::needsDestruction) - result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size)); - else - result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size)); result->clearStructure(); return result; } @@ -112,50 +152,69 @@ inline bool isZapped(const JSCell* cell) inline bool JSCell::isObject() const { - return m_structure->isObject(); + return TypeInfo::isObject(m_type); } inline bool JSCell::isString() const { - return m_structure->typeInfo().type() == StringType; + return m_type == StringType; +} + +inline bool JSCell::isSymbol() const +{ + return m_type == SymbolType; } inline bool JSCell::isGetterSetter() const { - return m_structure->typeInfo().type() == GetterSetterType; + return m_type == GetterSetterType; +} + +inline bool JSCell::isCustomGetterSetter() const +{ + return m_type == CustomGetterSetterType; } inline bool JSCell::isProxy() const { - return structure()->typeInfo().type() == ProxyType; + return m_type == ImpureProxyType || m_type == PureForwardingProxyType; } inline bool JSCell::isAPIValueWrapper() const { - return m_structure->typeInfo().type() == APIValueWrapperType; + return m_type == APIValueWrapperType; } inline void JSCell::setStructure(VM& vm, Structure* structure) { - ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren()); - ASSERT(structure->classInfo() == m_structure->classInfo()); - ASSERT(!m_structure - || m_structure->transitionWatchpointSetHasBeenInvalidated() - || m_structure.get() == structure); - m_structure.set(vm, this, structure); + ASSERT(structure->classInfo() == this->structure()->classInfo()); + ASSERT(!this->structure() + || this->structure()->transitionWatchpointSetHasBeenInvalidated() + || Heap::heap(this)->structureIDTable().get(structure->id()) == structure); + vm.heap.writeBarrier(this, structure); + m_structureID = structure->id(); + m_flags = structure->typeInfo().inlineTypeFlags(); + m_type = structure->typeInfo().type(); + m_indexingType = structure->indexingType(); } -inline const MethodTable* JSCell::methodTableForDestruction() const +inline const MethodTable* JSCell::methodTable() const { - return &classInfo()->methodTable; + VM& vm = *Heap::heap(this)->vm(); + Structure* structure = this->structure(vm); + if (Structure* rootStructure = structure->structure(vm)) + RELEASE_ASSERT(rootStructure == rootStructure->structure(vm)); + + return &structure->classInfo()->methodTable; } -inline const MethodTable* JSCell::methodTable() const +inline const MethodTable* JSCell::methodTable(VM& vm) const { - if (Structure* rootStructure = m_structure->structure()) - RELEASE_ASSERT(rootStructure == rootStructure->structure()); + Structure* structure = this->structure(vm); + if (Structure* rootStructure = structure->structure(vm)) + RELEASE_ASSERT(rootStructure == rootStructure->structure(vm)); - return &classInfo()->methodTable; + return &structure->classInfo()->methodTable; } inline bool JSCell::inherits(const ClassInfo* info) const @@ -163,40 +222,43 @@ inline bool JSCell::inherits(const ClassInfo* info) const return classInfo()->isSubClassOf(info); } -ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) +ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, PropertyName name) { - if (!structure()->typeInfo().overridesGetOwnPropertySlot()) - return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); - return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot); + ASSERT(canUseFastGetOwnProperty(structure)); + PropertyOffset offset = structure.get(vm, name); + if (offset != invalidOffset) + return asObject(this)->locationForOffset(offset)->get(); + return JSValue(); } -// Fast call to get a property where we may not yet have converted the string to an -// identifier. The first time we perform a property access with a given string, try -// performing the property map lookup without forming an identifier. We detect this -// case by checking whether the hash has yet been set for this string. -ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const String& name) +inline bool JSCell::canUseFastGetOwnProperty(const Structure& structure) { - if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) { - PropertyOffset offset = name.impl()->hasHash() - ? structure()->get(exec->vm(), Identifier(exec, name)) - : structure()->get(exec->vm(), name); - if (offset != invalidOffset) - return asObject(this)->locationForOffset(offset)->get(); - } - return JSValue(); + return !structure.hasGetterSetterProperties() + && !structure.hasCustomGetterSetterProperties() + && !structure.typeInfo().overridesGetOwnPropertySlot(); +} + +inline const ClassInfo* JSCell::classInfo() const +{ + MarkedBlock* block = MarkedBlock::blockFor(this); + if (block->needsDestruction() && !(inlineTypeFlags() & StructureIsImmortal)) + return static_cast<const JSDestructibleObject*>(this)->classInfo(); + return structure(*block->vm())->classInfo(); } inline bool JSCell::toBoolean(ExecState* exec) const { - if (isString()) + if (isString()) return static_cast<const JSString*>(this)->toBoolean(); return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject()); } inline TriState JSCell::pureToBoolean() const { - if (isString()) + if (isString()) return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState; + if (isSymbol()) + return TrueTriState; return MixedTriState; } |