bool JSGlobalObject::arrayPrototypeChainIsSane() { return !hasIndexedProperties(m_arrayPrototype->structure()->indexingType()) && m_arrayPrototype->prototype() == m_objectPrototype.get() && !hasIndexedProperties(m_objectPrototype->structure()->indexingType()) && m_objectPrototype->prototype().isNull(); }
Structure* PrototypeMap::emptyStructureForPrototypeFromBaseStructure(JSGlobalObject* globalObject, JSObject* prototype, Structure* baseStructure) { // We currently do not have inline capacity static analysis for subclasses and all internal function constructors have a default inline capacity of 0. IndexingType indexingType = baseStructure->indexingType(); if (prototype->structure()->anyObjectInChainMayInterceptIndexedAccesses() && hasIndexedProperties(indexingType)) indexingType = (indexingType & ~IndexingShapeMask) | SlowPutArrayStorageShape; return createEmptyStructure(globalObject, prototype, baseStructure->typeInfo(), baseStructure->classInfo(), indexingType, 0); }
inline void StorageStatistics::operator()(JSCell* cell) { if (!cell->isObject()) return; JSObject* object = jsCast<JSObject*>(cell); if (hasIndexedProperties(object->structure()->indexingType())) return; if (object->structure()->isUncacheableDictionary()) return; ++m_objectCount; if (!object->hasInlineStorage()) ++m_objectWithOutOfLineStorageCount; m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>); m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>); }
void ObjectInitializationScope::verifyPropertiesAreInitialized(JSObject* object) { Butterfly* butterfly = object->butterfly(); Structure* structure = object->structure(m_vm); IndexingType indexingType = structure->indexingType(); unsigned vectorLength = butterfly->vectorLength(); if (UNLIKELY(hasUndecided(indexingType)) || !hasIndexedProperties(indexingType)) { // Nothing to verify. } else if (LIKELY(!hasAnyArrayStorage(indexingType))) { auto data = butterfly->contiguous().data(); for (unsigned i = 0; i < vectorLength; ++i) { if (isScribbledValue(data[i].get())) { dataLogLn("Found scribbled value at i = ", i); ASSERT_NOT_REACHED(); } } } else { ArrayStorage* storage = butterfly->arrayStorage(); for (unsigned i = 0; i < vectorLength; ++i) { if (isScribbledValue(storage->m_vector[i].get())) { dataLogLn("Found scribbled value at i = ", i); ASSERT_NOT_REACHED(); } } } auto isSafeEmptyValueForGCScanning = [] (JSValue value) { #if USE(JSVALUE64) return !value; #else return !value || !JSValue::encode(value); #endif }; for (int64_t i = 0; i < static_cast<int64_t>(structure->outOfLineCapacity()); i++) { // We rely on properties past the last offset be zero for concurrent GC. if (i + firstOutOfLineOffset > structure->lastOffset()) ASSERT(isSafeEmptyValueForGCScanning(butterfly->propertyStorage()[-i - 1].get())); else if (isScribbledValue(butterfly->propertyStorage()[-i - 1].get())) { dataLogLn("Found scribbled property at i = ", -i - 1); ASSERT_NOT_REACHED(); } } }
JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o) { ASSERT(!o->structure()->enumerationCache() || o->structure()->enumerationCache()->cachedStructure() != o->structure() || o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec)); VM& vm = exec->vm(); PropertyNameArray propertyNames(exec); o->methodTable()->getPropertyNames(o, exec, propertyNames, ExcludeDontEnumProperties); size_t numCacheableSlots = 0; if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasGetterSetterProperties() && !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames()) numCacheableSlots = propertyNames.numCacheableSlots(); JSPropertyNameIterator* jsPropertyNameIterator = new (NotNull, allocateCell<JSPropertyNameIterator>(vm.heap)) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots); jsPropertyNameIterator->finishCreation(vm, propertyNames.data(), o); if (o->structure()->isDictionary()) return jsPropertyNameIterator; if (o->structure()->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; if (hasIndexedProperties(o->indexingType())) return jsPropertyNameIterator; size_t count = normalizePrototypeChain(exec, o); StructureChain* structureChain = o->structure()->prototypeChain(exec); WriteBarrier<Structure>* structure = structureChain->head(); for (size_t i = 0; i < count; ++i) { if (structure[i]->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; } jsPropertyNameIterator->setCachedPrototypeChain(vm, structureChain); jsPropertyNameIterator->setCachedStructure(vm, o->structure()); o->structure()->setEnumerationCache(vm, jsPropertyNameIterator); return jsPropertyNameIterator; }
EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec) { // 1. If Type(O) is not Object throw a TypeError exception. JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.freeze can only be called on Objects."))); JSObject* object = asObject(obj); if (isJSFinalObject(object) && !hasIndexedProperties(object->structure()->indexingType())) { object->freeze(exec->vm()); return JSValue::encode(obj); } // 2. For each named own property name P of O, PropertyNameArray properties(exec); object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties); PropertyNameArray::const_iterator end = properties.end(); for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) { // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P. PropertyDescriptor desc; if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc)) continue; // b. If IsDataDescriptor(desc) is true, then // i. If desc.[[Writable]] is true, set desc.[[Writable]] to false. if (desc.isDataDescriptor()) desc.setWritable(false); // c. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false. desc.setConfigurable(false); // d. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments. object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true); if (exec->hadException()) return JSValue::encode(obj); } // 3. Set the [[Extensible]] internal property of O to false. object->preventExtensions(exec->vm()); // 4. Return O. return JSValue::encode(obj); }
bool JSGlobalObject::stringPrototypeChainIsSane() { return !hasIndexedProperties(m_stringPrototype->structure()->indexingType()) && m_stringPrototype->prototype() == m_objectPrototype.get() && objectPrototypeIsSane(); }
bool JSGlobalObject::objectPrototypeIsSane() { return !hasIndexedProperties(m_objectPrototype->structure()->indexingType()) && m_objectPrototype->prototype().isNull(); }