bool DynamicObjectPropertyEnumerator::CanUseJITFastPath() const { #if ENABLE_TTD TTDAssert(this->cachedData == nullptr || !this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode(), "We should always have cachedData null if we are in record or replay mode"); #endif return !this->IsNullEnumerator() && !GetEnumNonEnumerable() && this->cachedData != nullptr; }
void DynamicObjectPropertyEnumerator::Reset() { if (this->object) { enumeratedCount = 0; initialType = object->GetDynamicType(); objectIndex = Constants::NoBigSlot; initialPropertyCount = GetSnapShotSemantics() ? this->object->GetPropertyCount() : Constants::NoBigSlot; // Create the appropriate enumerator object. if (GetSnapShotSemantics() && this->initialType->PrepareForTypeSnapshotEnumeration()) { ScriptContext* scriptContext = this->object->GetScriptContext(); ThreadContext * threadContext = scriptContext->GetThreadContext(); CachedData * data = (CachedData *)threadContext->GetDynamicObjectEnumeratorCache(this->initialType); if (data == nullptr || data->scriptContext != this->requestContext || data->enumNonEnumerable != GetEnumNonEnumerable() || data->enumSymbols != GetEnumSymbols()) { data = RecyclerNewStructPlus(scriptContext->GetRecycler(), this->initialPropertyCount * sizeof(PropertyString *) + this->initialPropertyCount * sizeof(BigPropertyIndex) + this->initialPropertyCount * sizeof(PropertyAttributes), CachedData); data->scriptContext = requestContext; data->cachedCount = 0; data->strings = (PropertyString **)(data + 1); data->indexes = (BigPropertyIndex *)(data->strings + this->initialPropertyCount); data->attributes = (PropertyAttributes*)(data->indexes + this->initialPropertyCount); data->completed = false; data->enumNonEnumerable = GetEnumNonEnumerable(); data->enumSymbols = GetEnumSymbols(); threadContext->AddDynamicObjectEnumeratorCache(this->initialType, data); } this->cachedData = data; this->cachedDataType = this->initialType; } else { this->cachedData = nullptr; this->cachedDataType = nullptr; } } }
bool DynamicObjectPropertyEnumerator::Initialize(DynamicObject * object, EnumeratorFlags flags, ScriptContext * requestContext, ForInCache * forInCache) { this->scriptContext = requestContext; this->object = object; this->flags = flags; if (!object) { this->cachedData = nullptr; return true; } this->objectIndex = Constants::NoBigSlot; this->enumeratedCount = 0; if (!GetUseCache()) { if (!object->GetDynamicType()->GetTypeHandler()->EnsureObjectReady(object)) { return false; } Initialize(object->GetDynamicType(), nullptr, GetSnapShotSemantics() ? this->object->GetPropertyCount() : Constants::NoBigSlot); return true; } DynamicType * type = object->GetDynamicType(); CachedData * data; if (forInCache && type == forInCache->type) { // We shouldn't have a for in cache when asking to enum symbols Assert(!GetEnumSymbols()); data = (CachedData *)forInCache->data; Assert(data != nullptr); Assert(data->scriptContext == this->scriptContext); // The cache data script context should be the same as request context Assert(!data->enumSymbols); if (data->enumNonEnumerable == GetEnumNonEnumerable()) { Initialize(type, data, data->propertyCount); return true; } } data = (CachedData *)requestContext->GetThreadContext()->GetDynamicObjectEnumeratorCache(type); if (data != nullptr && data->scriptContext == this->scriptContext && data->enumNonEnumerable == GetEnumNonEnumerable() && data->enumSymbols == GetEnumSymbols()) { Initialize(type, data, data->propertyCount); if (forInCache) { forInCache->type = type; forInCache->data = data; } return true; } if (!object->GetDynamicType()->GetTypeHandler()->EnsureObjectReady(object)) { return false; } // Reload the type after EnsureObjecteReady type = object->GetDynamicType(); if (!type->PrepareForTypeSnapshotEnumeration()) { Initialize(type, nullptr, object->GetPropertyCount()); return true; } uint propertyCount = this->object->GetPropertyCount(); data = RecyclerNewStructPlus(requestContext->GetRecycler(), propertyCount * sizeof(Field(PropertyString*)) + propertyCount * sizeof(BigPropertyIndex) + propertyCount * sizeof(PropertyAttributes), CachedData); data->scriptContext = requestContext; data->cachedCount = 0; data->propertyCount = propertyCount; data->strings = reinterpret_cast<Field(PropertyString*)*>(data + 1); data->indexes = (BigPropertyIndex *)(data->strings + propertyCount); data->attributes = (PropertyAttributes*)(data->indexes + propertyCount); data->completed = false; data->enumNonEnumerable = GetEnumNonEnumerable(); data->enumSymbols = GetEnumSymbols(); requestContext->GetThreadContext()->AddDynamicObjectEnumeratorCache(type, data); Initialize(type, data, propertyCount); if (forInCache) { forInCache->type = type; forInCache->data = data; } return true; }