Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue in setting accessor in PathTypeHandlerWithAttr #6300

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

akroshg
Copy link
Contributor

@akroshg akroshg commented Oct 4, 2019

When the property is deleted (say when we are in SimpleTypeHandler) and then later
if we create an accessor on the same property we have converted the type handler to PathTypeHandlerWithAttr.
But during setting the accessor on that slot we haven't removed the is_deleted attribute.
So when we try to get the property - we don't get that from the PathTypeHandlerWithAttr handler.
Fixed that by removing that attribute when we do SetAccessor.

@akroshg
Copy link
Contributor Author

akroshg commented Oct 4, 2019

Please review commit 88f537b

fixes : #6271

@@ -1196,7 +1196,7 @@ namespace Js
}
}

SetAttributesHelper(instance, propertyId, propertyIndex, attributes, (ObjectSlotAttributes)(attr | ObjectSlotAttr_Accessor));
SetAttributesHelper(instance, propertyId, propertyIndex, attributes, (ObjectSlotAttributes)((attr & ~ObjectSlotAttr_Deleted) | ObjectSlotAttr_Accessor));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be:

attr ^ ObjectSlotAttr_Deleted | ObjectSlotAttr_Accessor

?

Also, any idea why the already-merge commits are showing up in this PR? Maybe rebase?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real problem here seems to be that we were able to create a property on a PathTypeHandler with the deleted attribute. That shouldn't be possible. Can you see how it happened?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The object has SimpleTypeHandler<3> type handler (which has proto, length and name). Once we delete the length, we mark the attribute for that slot as deleted.
Around the time when we are about to add the accessor - we converted that handler to pathtypehandlerwithattr with the deleted property attribute for the 'length'.
At the time of adding the accessor - we didn't remove that attribute.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    template<size_t size>
    BOOL SimpleTypeHandler<size>::SetAccessors(DynamicObject* instance, PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags)
    {
        if (DoConvertToPathType(instance->GetDynamicType()))
        {
            return ConvertToPathType(instance)->SetAccessors(instance, propertyId, getter, setter, flags);
        }
        else
        {
            // Don't attempt to share cross-site function types
            return ConvertToDictionaryType(instance)->SetAccessors(instance, propertyId, getter, setter, flags);
        }
    }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm saying that setting a property on a path type handler with the deleted attribute shouldn't work, since path type handlers don't support deleted properties. It should have forced conversion to some sort of dictionary type handler. If there's a simple type with a deleted property, and we convert to path type without re-adding the deleted property, we'll have trouble even with the fix you're proposing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the Pathtypehandler supports deleted property. In many of the function in pathtypehandler.cpp you can see there are checks for attr & ObjectSlotAttr_Deleted
you can find that in HasProperty/SetProperty/GetProperty/DeleteProperty functions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It definitely doesn't. Those lines are there to prepare for support, but it's not there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, that is strange.
I can try looking into converting to DictionaryType at the time we are adding an accessor to simple type. Do you know if we marked something on the simple type that any property got deleted? DoConvertToPathType does not have that information.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If simple type does support deleted properties, then "deleted" must be recorded in the property's attributes.

@@ -956,7 +973,7 @@ namespace Js
template<size_t size>
BOOL SimpleTypeHandler<size>::SetAccessors(DynamicObject* instance, PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags)
{
if (DoConvertToPathType(instance->GetDynamicType()))
if (DoConvertToPathType(instance->GetDynamicType()) && !HasAnyPropertyDeleted())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other usages of DoConvertToPathPath (see SimpleTypeHandler::AddProperty). Should they also be checking for deleted properties? If so, would it make sense to move this "has deleted properties" check into that function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other places where DoConvertToPathType is used, but they are used inside GetIsLocked() check. And it seems, from the comment I read in SetAttribute, that GetIsLocked returns false if any property got deleted.
However I meant to put that in AddProperty - thanks for catching that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a weaker solution than the one we discussed offline. Converting to a new type handler is equivalent to evolving the type from scratch. In this case it needs to be able to handle any situation that simple types can handle and path types can't. Deleted properties may not be the only one. We need an API that tries to convert to path type but may return some kind of dictionary type handler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why create path type (and spent unnecessary cycles to create and throw away) when we are sure we are going to create dictionary type? Right now I only know for deleted property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also on other places we don't follow the same rule

        if (propertyCount >= sizeof(descriptors)/sizeof(SimplePropertyDescriptor))
        {
            Assert(propertyId != Constants::NoProperty);
            if (DoConvertToPathType(instance->GetDynamicType()))
            {
                return ConvertToPathType(instance)->SetPropertyWithAttributes(instance, propertyId, value, attributes, info, flags);
            }
            else
            {
                PropertyRecord const* propertyRecord = scriptContext->GetPropertyName(propertyId);
                return ConvertToSimpleDictionaryType(instance)->AddProperty(instance, propertyRecord, value, attributes, info, flags, possibleSideEffects);
            }
        }

we decide based on certain condition that we need to create path type or dictionary type.

@@ -172,9 +172,26 @@ namespace Js
return newTypeHandler;
}

template<size_t size>
bool SimpleTypeHandler<size>::HasAnyPropertyDeleted()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: HasDeletedProperties will read a bit better.

When the property is deleted (say when we are in SimpleTypeHandler) and then later
if we create an accessor on the same property we have converted the type handler to PathTypeHandlerWithAttr.
Since a property got deleted and PathTypeHandler should not handle that deleted property we need to convert this to
Dictionary type.
In order to fix that When we add the accessor on any property we need to check if any property deleted upon that we need
to convert to Dictionary type instead of type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants