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

Share SimpleTypeHandler types on function objects. #4748

Merged
merged 1 commit into from
Mar 14, 2018

Conversation

pleath
Copy link
Contributor

@pleath pleath commented Feb 27, 2018

Currently when we transition from DeferredTypeHandler to SimpleTypeHandler on first access to a function object's properties, we don't share the new type we create. Track an undeferred type along with the deferredPrototypeType on FunctionProxy and re-use it whenever possible for multiple instances of the same function. (This is a first step in broader sharing of function object types.)

typeHandler->SetInstanceTypeHandler(instance);
if (functionProxy && typeHandler->GetMayBecomeShared())
{
functionProxy->SetUndeferredFunctionType(ScriptFunction::FromVar(instance)->GetScriptFunctionType());
Copy link
Contributor

Choose a reason for hiding this comment

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

ScriptFunction::FromVar(instance) [](start = 57, length = 33)

How do we know that instance is a ScriptFunction? (Not saying it's wrong, I'm just curious.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ScriptFunction's are the only JavascriptFunction's with non-null FunctionProxy.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could use ScriptFunction::UnsafeFromVar.


In reply to: 171357540 [](ancestors = 171357540)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Thanks.

Copy link
Contributor

@sethbrenith sethbrenith left a comment

Choose a reason for hiding this comment

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

:shipit:

@@ -67,15 +67,8 @@ namespace Js

friend class JavascriptArray; // for xplat offsetof field access
friend class JavascriptNativeArray; // for xplat offsetof field access
friend class JavascriptOperators; // for ReplaceType
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the xplat builds are failing because JavascriptOperators is trying to access a protected member function DynamicObject::BoxStackInstance, so this friend wasn't just for ReplaceType

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True. So the different compilers are enforcing different rules?

this->functionInfo = newFunctionInfo->GetFunctionInfo();

if (type->GetIsShared())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@curtisman If we're allowing shared types on function objects with non-default state, then we can't revert to the deferredPrototypeType here. I think we want to go ahead and change the entry point on the current shared type. Is there a reason we can't?

Copy link
Contributor

Choose a reason for hiding this comment

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

My guess here is because originally, we would have swiitch out the functionInfo reference with the the undeferred function body in the scriptFunction. So undeferring would only be fully done for one script function but not the other instance. (Thus can't change the shared entry point)

Since you have changed it that the switching is done in the function proxy, it's probably OK to do.

But I wonder whether we need the line above any more as well. Shouldn't this->functionInfo should equals to newFunctionInfo->GetFunctionInfo() always?


In reply to: 171666256 [](ancestors = 171666256)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you're right. I've replaced the copy with an assert. I think the only other thing we need to do is to copy the deferredPrototypeType and undeferredFunctionType pointers on un-defer/re-defer now that we don't make new types for the new FunctionProxy.

if (undeferredFunctionType)
{
Assert(undeferredFunctionType->GetIsShared());
instance->ReplaceType(undeferredFunctionType);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should assert that undeferredFunctionType->GetTypeHandler() == typeHandler?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we can do that. JavascriptLibrary::ConvertFunction calls this function with the shared SimpleTypeHandler from the library. That won't match the PathTypeHandler pointed to by undeferredFunctionType if we've done that conversion already.

@@ -2055,6 +2067,10 @@ namespace Js
{
func(this->deferredPrototypeType);
}
if (this->undeferredFunctionType)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is a path type, we should be able to enumerate those by walking that tree, instead of registering it to the functionObjectTypeList.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change isn't making the undeferredFunctionType into a path type. It's still a simple type. In any case, it will get registered as a function object type when we create it, so we probably don't need these lines.

@pleath
Copy link
Contributor Author

pleath commented Mar 2, 2018

@dotnet-bot test OSX static_osx_osx_debug

DynamicObject *protoObject = javascriptLibrary->CreateConstructorPrototypeObject(function);
if (scriptFunction && scriptFunction->GetFunctionInfo()->IsClassConstructor())
{
function->SetPropertyWithAttributes(PropertyIds::prototype, protoObject, PropertyNone, nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

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

SetPropertyWithAttributes [](start = 26, length = 25)

Unless I'm misreading something, isn't this changing the semantics? Previously we were only setting writable to false, now we'll be setting enumerable and configurable to false as well, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We've always set the attributes this way for the prototype property of a class constructor. (See the class member defaults.)

@rajatd
Copy link
Contributor

rajatd commented Mar 12, 2018

:shipit:

@pleath pleath force-pushed the sharesimpletypes branch 2 times, most recently from 88f006e to 2ad5e2b Compare March 13, 2018 00:36
…transition from DeferredTypeHandler to SimpleTypeHandler on first access to a function object's properties, we don't share the new type we create. Track an undeferred type along with the deferredPrototypeType on FunctionProxy and re-use it whenever possible for multiple instances of the same function. (This is a first step in broader sharing of function object types.)
@chakrabot chakrabot merged commit b748a70 into chakra-core:master Mar 14, 2018
chakrabot pushed a commit that referenced this pull request Mar 14, 2018
Merge pull request #4748 from pleath:sharesimpletypes

Currently when we transition from DeferredTypeHandler to SimpleTypeHandler on first access to a function object's properties, we don't share the new type we create. Track an undeferred type along with the deferredPrototypeType on FunctionProxy and re-use it whenever possible for multiple instances of the same function. (This is a first step in broader sharing of function object types.)
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.

7 participants