-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
base: master
Are you sure you want to change the base?
Conversation
@@ -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)); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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);
}
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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.
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.