Permalink
Browse files

[MERGE #5794 @pleath] Share types of CrossSiteObject<ScriptFunction> …

…objects

Merge pull request #5794 from pleath:sharecrosssitefunctypes-m

Designated a cross-site DeferredTypeHandler type and PathTypeHandler type (if appropriate) for each FunctionProxy.
  • Loading branch information...
pleath committed Nov 8, 2018
2 parents ffebc17 + 61b61fd commit 93752a1fa83bd9c43520b992d49d9f7c0763fbeb
@@ -388,6 +388,7 @@ PHASE(All)
PHASE(ShareTypesWithAttributes)
PHASE(ShareAccessorTypes)
PHASE(ShareFuncTypes)
PHASE(ShareCrossSiteFuncTypes)
PHASE(ConditionalCompilation)
PHASE(InterpreterProfile)
PHASE(InterpreterAutoProfile)
@@ -1484,6 +1484,8 @@ namespace Js
#define CopyDeferParseField(field) other->field = this->field;
CopyDeferParseField(flags);
CopyDeferParseField(crossSiteDeferredFunctionType);
CopyDeferParseField(crossSiteUndeferredFunctionType);
CopyDeferParseField(m_isDeclaration);
CopyDeferParseField(m_isAccessor);
CopyDeferParseField(m_isStrictMode);
@@ -1598,6 +1600,8 @@ namespace Js
LocalFunctionId functionId, Utf8SourceInfo* sourceInfo, ScriptContext* scriptContext, uint functionNumber,
const char16* displayName, uint displayNameLength, uint displayShortNameOffset, FunctionInfo::Attributes attributes, FunctionBodyFlags flags) :
FunctionProxy(scriptContext, sourceInfo, functionNumber),
crossSiteDeferredFunctionType(nullptr),
crossSiteUndeferredFunctionType(nullptr),
#if DYNAMIC_INTERPRETER_THUNK
m_dynamicInterpreterThunk(nullptr),
#endif
@@ -2085,6 +2089,28 @@ namespace Js
undeferredFunctionType = type;
}
ScriptFunctionType * FunctionProxy::GetCrossSiteDeferredFunctionType() const
{
return HasParseableInfo() ? GetParseableFunctionInfo()->GetCrossSiteDeferredFunctionType() : nullptr;
}
void FunctionProxy::SetCrossSiteDeferredFunctionType(ScriptFunctionType * type)
{
Assert(HasParseableInfo());
GetParseableFunctionInfo()->SetCrossSiteDeferredFunctionType(type);
}
ScriptFunctionType * FunctionProxy::GetCrossSiteUndeferredFunctionType() const
{
return HasParseableInfo() ? GetParseableFunctionInfo()->GetCrossSiteUndeferredFunctionType() : nullptr;
}
void FunctionProxy::SetCrossSiteUndeferredFunctionType(ScriptFunctionType * type)
{
Assert(HasParseableInfo());
GetParseableFunctionInfo()->SetCrossSiteUndeferredFunctionType(type);
}
JavascriptMethod FunctionProxy::GetDirectEntryPoint(ProxyEntryPointInfo* entryPoint) const
{
Assert(entryPoint->jsMethod != nullptr);
@@ -4984,6 +5010,14 @@ namespace Js
this->undeferredFunctionType->SetEntryPoint(this->GetDefaultEntryPointInfo()->jsMethod);
this->undeferredFunctionType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
if (this->crossSiteDeferredFunctionType)
{
this->crossSiteDeferredFunctionType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
if (this->crossSiteUndeferredFunctionType)
{
this->crossSiteUndeferredFunctionType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
#if DBG
if (!this->HasValidEntryPoint())
@@ -5275,7 +5309,7 @@ namespace Js
if (this->deferredPrototypeType)
{
// Update old entry points on the deferred prototype type,
// as they may point to old native code gen regions which age gone now.
// as they may point to old native code gen regions which are gone now.
this->deferredPrototypeType->SetEntryPoint(this->GetDefaultEntryPointInfo()->jsMethod);
this->deferredPrototypeType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
@@ -5284,6 +5318,14 @@ namespace Js
this->undeferredFunctionType->SetEntryPoint(this->GetDefaultEntryPointInfo()->jsMethod);
this->undeferredFunctionType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
if (this->crossSiteDeferredFunctionType)
{
this->crossSiteDeferredFunctionType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
if (this->crossSiteUndeferredFunctionType)
{
this->crossSiteUndeferredFunctionType->SetEntryPointInfo(this->GetDefaultEntryPointInfo());
}
ReinitializeExecutionModeAndLimits();
}
@@ -1022,6 +1022,7 @@ namespace Js
void SetEnclosedByGlobalFunc();
bool CanBeDeferred() const;
BOOL IsDeferredDeserializeFunction() const;
BOOL HasParseableInfo() const;
BOOL IsDeferredParseFunction() const;
FunctionInfo::Attributes GetAttributes() const;
void SetAttributes(FunctionInfo::Attributes attributes);
@@ -1057,6 +1058,10 @@ namespace Js
ScriptFunctionType * EnsureDeferredPrototypeType();
ScriptFunctionType * GetUndeferredFunctionType() const;
void SetUndeferredFunctionType(ScriptFunctionType * type);
ScriptFunctionType * GetCrossSiteDeferredFunctionType() const;
void SetCrossSiteDeferredFunctionType(ScriptFunctionType * type);
ScriptFunctionType * GetCrossSiteUndeferredFunctionType() const;
void SetCrossSiteUndeferredFunctionType(ScriptFunctionType * type);
JavascriptMethod GetDirectEntryPoint(ProxyEntryPointInfo* entryPoint) const;
// Function object type list methods
@@ -1302,6 +1307,13 @@ namespace Js
return GetFunctionInfo()->IsDeferredDeserializeFunction();
}
inline BOOL FunctionProxy::HasParseableInfo() const
{
Assert(GetFunctionInfo());
Assert(GetFunctionInfo()->GetFunctionProxy() == this);
return GetFunctionInfo()->HasParseableInfo();
}
inline BOOL FunctionProxy::IsDeferredParseFunction() const
{
Assert(GetFunctionInfo());
@@ -1578,6 +1590,11 @@ namespace Js
uint32 GetGrfscr() const;
void SetGrfscr(uint32 grfscr);
ScriptFunctionType * GetCrossSiteDeferredFunctionType() const { return crossSiteDeferredFunctionType; }
void SetCrossSiteDeferredFunctionType(ScriptFunctionType * type) { Assert(!crossSiteDeferredFunctionType); crossSiteDeferredFunctionType = type; }
ScriptFunctionType * GetCrossSiteUndeferredFunctionType() const { return crossSiteUndeferredFunctionType; }
void SetCrossSiteUndeferredFunctionType(ScriptFunctionType * type) { Assert(!crossSiteUndeferredFunctionType); crossSiteUndeferredFunctionType = type; }
///----------------------------------------------------------------------------
///
/// ParseableFunctionInfo::GetInParamsCount
@@ -1807,6 +1824,9 @@ namespace Js
#if DYNAMIC_INTERPRETER_THUNK
FieldNoBarrier(void*) m_dynamicInterpreterThunk; // Unique 'thunk' for every interpreted function - used for ETW symbol decoding.
#endif
FieldWithBarrier(ScriptFunctionType*) crossSiteDeferredFunctionType;
FieldWithBarrier(ScriptFunctionType*) crossSiteUndeferredFunctionType;
FieldWithBarrier(uint) m_cbStartOffset; // pUtf8Source is this many bytes from the start of the scriptContext's source buffer.
// This is generally the same as m_cchStartOffset unless the buffer has a BOM or other non-ascii characters
FieldWithBarrier(uint) m_cbStartPrintOffset; // pUtf8Source is this many bytes from the start of the toString-relevant part of the scriptContext's source buffer.
@@ -583,7 +583,7 @@ namespace Js
functionWithPrototypeTypeHandler->SetHasKnownSlot0();
externalFunctionWithDeferredPrototypeType = CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptExternalFunction::ExternalFunctionThunk, true /*isShared*/);
externalFunctionWithLengthAndDeferredPrototypeType = CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptExternalFunction::ExternalFunctionThunk, true /*isShared*/, /* isLengthAvailable */ true);
externalFunctionWithLengthAndDeferredPrototypeType = CreateDeferredLengthPrototypeFunctionTypeNoProfileThunk(JavascriptExternalFunction::ExternalFunctionThunk, true /*isShared*/);
wrappedFunctionWithDeferredPrototypeType = CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptExternalFunction::WrappedFunctionThunk, true /*isShared*/);
stdCallFunctionWithDeferredPrototypeType = CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptExternalFunction::StdCallExternalFunctionThunk, true /*isShared*/);
idMappedFunctionWithPrototypeType = DynamicType::New(scriptContext, TypeIds_Function, functionPrototype, JavascriptExternalFunction::ExternalFunctionThunk,
@@ -595,6 +595,8 @@ namespace Js
boundFunctionType = DynamicType::New(scriptContext, TypeIds_Function, functionPrototype, BoundFunction::NewInstance,
GetDeferredFunctionTypeHandler(), true, true);
crossSiteDeferredFunctionType = CreateDeferredFunctionTypeNoProfileThunk(
scriptContext->CurrentCrossSiteThunk, true /*isShared*/);
crossSiteDeferredPrototypeFunctionType = CreateDeferredPrototypeFunctionTypeNoProfileThunk(
scriptContext->CurrentCrossSiteThunk, true /*isShared*/);
crossSiteIdMappedFunctionWithPrototypeType = DynamicType::New(scriptContext, TypeIds_Function, functionPrototype, scriptContext->CurrentCrossSiteThunk,
@@ -1022,20 +1024,51 @@ namespace Js
isAnonymousFunction ? GetDeferredAnonymousPrototypeAsyncFunctionTypeHandler() : GetDeferredPrototypeAsyncFunctionTypeHandler(scriptContext), isShared, isShared);
}
DynamicType * JavascriptLibrary::CreateDeferredFunctionType(JavascriptMethod entrypoint)
{
return CreateDeferredFunctionTypeNoProfileThunk(this->inDispatchProfileMode ? ProfileEntryThunk : entrypoint);
}
DynamicType * JavascriptLibrary::CreateDeferredPrototypeFunctionType(JavascriptMethod entrypoint)
{
return CreateDeferredPrototypeFunctionTypeNoProfileThunk(this->inDispatchProfileMode ? ProfileEntryThunk : entrypoint);
}
DynamicType * JavascriptLibrary::CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptMethod entrypoint, bool isShared, bool isLengthAvailable)
DynamicType * JavascriptLibrary::CreateDeferredFunctionTypeNoProfileThunk(JavascriptMethod entryPoint, bool isShared)
{
return CreateDeferredFunctionTypeNoProfileThunk_Internal<false, false>(entryPoint, isShared);
}
DynamicType * JavascriptLibrary::CreateDeferredLengthFunctionTypeNoProfileThunk(JavascriptMethod entryPoint, bool isShared)
{
return CreateDeferredFunctionTypeNoProfileThunk_Internal<true, false>(entryPoint, isShared);
}
DynamicType * JavascriptLibrary::CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptMethod entryPoint, bool isShared)
{
return CreateDeferredFunctionTypeNoProfileThunk_Internal<false, true>(entryPoint, isShared);
}
DynamicType * JavascriptLibrary::CreateDeferredLengthPrototypeFunctionTypeNoProfileThunk(JavascriptMethod entryPoint, bool isShared)
{
return CreateDeferredFunctionTypeNoProfileThunk_Internal<true, true>(entryPoint, isShared);
}
template<bool isLengthAvailable, bool isPrototypeAvailable>
DynamicType * JavascriptLibrary::CreateDeferredFunctionTypeNoProfileThunk_Internal(JavascriptMethod entrypoint, bool isShared)
{
// Note: the lack of TypeHandler switching here based on the isAnonymousFunction flag is intentional.
// We can't switch shared typeHandlers and RuntimeFunctions do not produce script code for us to know if a function is Anonymous.
// As a result we may have an issue where hasProperty would say you have a name property but getProperty returns undefined
return DynamicType::New(scriptContext, TypeIds_Function, functionPrototype, entrypoint,
isLengthAvailable ? GetDeferredPrototypeFunctionWithLengthTypeHandler(scriptContext) : GetDeferredPrototypeFunctionTypeHandler(scriptContext),
isShared, isShared);
DynamicTypeHandler * typeHandler =
isLengthAvailable ?
(isPrototypeAvailable ?
GetDeferredPrototypeFunctionWithLengthTypeHandler(scriptContext) : GetDeferredFunctionWithLengthTypeHandler()) :
(isPrototypeAvailable ?
GetDeferredPrototypeFunctionTypeHandler(scriptContext) : GetDeferredFunctionTypeHandler());
return DynamicType::New(scriptContext, TypeIds_Function, functionPrototype, entrypoint, typeHandler, isShared, isShared);
}
DynamicType * JavascriptLibrary::CreateFunctionType(JavascriptMethod entrypoint, RecyclableObject* prototype)
{
if (prototype == nullptr)
@@ -5243,11 +5276,7 @@ namespace Js
{
Assert(function->GetDynamicType()->GetIsLocked());
if (VarIs<ScriptFunction>(function))
{
this->SetCrossSiteForLockedNonBuiltInFunctionType(function);
}
else if (VarIs<BoundFunction>(function))
if (VarIs<ScriptFunction>(function) || VarIs<BoundFunction>(function))
{
this->SetCrossSiteForLockedNonBuiltInFunctionType(function);
}
@@ -5259,6 +5288,11 @@ namespace Js
{
function->ReplaceType(crossSiteDeferredPrototypeFunctionType);
}
else if (typeHandler == JavascriptLibrary::GetDeferredFunctionTypeHandler()
|| typeHandler == JavascriptLibrary::GetDeferredFunctionWithLengthTypeHandler())
{
function->ReplaceType(crossSiteDeferredFunctionType);
}
else if (typeHandler == Js::DeferredTypeHandler<Js::JavascriptExternalFunction::DeferredConstructorInitializer>::GetDefaultInstance())
{
function->ReplaceType(crossSiteExternalConstructFunctionWithPrototypeType);
@@ -5276,16 +5310,58 @@ namespace Js
void JavascriptLibrary::SetCrossSiteForLockedNonBuiltInFunctionType(JavascriptFunction * function)
{
FunctionProxy * functionProxy = function->GetFunctionProxy();
DynamicTypeHandler *typeHandler = function->GetTypeHandler();
if (typeHandler->IsPathTypeHandler())
if (typeHandler->IsDeferredTypeHandler())
{
PathTypeHandlerBase::FromTypeHandler(typeHandler)->ConvertToNonShareableTypeHandler(function);
if (functionProxy && functionProxy->GetCrossSiteDeferredFunctionType())
{
function->ReplaceType(functionProxy->GetCrossSiteDeferredFunctionType());
}
else
{
function->ChangeType();
function->SetEntryPoint(scriptContext->CurrentCrossSiteThunk);
if (functionProxy && !PHASE_OFF1(ShareCrossSiteFuncTypesPhase))
{
function->ShareType();
functionProxy->SetCrossSiteDeferredFunctionType(UnsafeVarTo<ScriptFunction>(function)->GetScriptFunctionType());
}
}
}
else
else
{
function->ChangeType();
if (functionProxy && functionProxy->GetCrossSiteUndeferredFunctionType())
{
function->ReplaceType(functionProxy->GetCrossSiteUndeferredFunctionType());
}
else
{
if (typeHandler->IsPathTypeHandler())
{
if (!PHASE_OFF1(ShareCrossSiteFuncTypesPhase))
{
DynamicType *type = function->DuplicateType();
PathTypeHandlerBase::FromTypeHandler(typeHandler)->BuildPathTypeFromNewRoot(function, &type);
function->ReplaceType(type);
}
else
{
PathTypeHandlerBase::FromTypeHandler(typeHandler)->ConvertToNonShareableTypeHandler(function);
}
}
else
{
function->ChangeType();
}
function->SetEntryPoint(scriptContext->CurrentCrossSiteThunk);
if (functionProxy && function->GetTypeHandler()->GetMayBecomeShared() && !PHASE_OFF1(ShareCrossSiteFuncTypesPhase))
{
function->ShareType();
functionProxy->SetCrossSiteUndeferredFunctionType(UnsafeVarTo<ScriptFunction>(function)->GetScriptFunctionType());
}
}
}
function->SetEntryPoint(scriptContext->CurrentCrossSiteThunk);
}
JavascriptExternalFunction*
@@ -300,6 +300,7 @@ namespace Js
Field(DynamicType *) defaultExternalConstructorFunctionWithDeferredPrototypeType;
Field(DynamicType *) boundFunctionType;
Field(DynamicType *) regexConstructorType;
Field(DynamicType *) crossSiteDeferredFunctionType;
Field(DynamicType *) crossSiteDeferredPrototypeFunctionType;
Field(DynamicType *) crossSiteIdMappedFunctionWithPrototypeType;
Field(DynamicType *) crossSiteExternalConstructFunctionWithPrototypeType;
@@ -912,8 +913,13 @@ namespace Js
template<bool isNameAvailable>
static DynamicTypeHandler * GetDeferredAsyncFunctionTypeHandlerBase();
DynamicType * CreateDeferredFunctionType(JavascriptMethod entrypoint);
DynamicType * CreateDeferredPrototypeFunctionType(JavascriptMethod entrypoint);
DynamicType * CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptMethod entrypoint, bool isShared = false, bool isLengthAvailable = false);
DynamicType * CreateDeferredPrototypeFunctionTypeNoProfileThunk(JavascriptMethod entrypoint, bool isShared = false);
DynamicType * CreateDeferredFunctionTypeNoProfileThunk(JavascriptMethod entrypoint, bool isShared = false);
DynamicType * CreateDeferredLengthPrototypeFunctionTypeNoProfileThunk(JavascriptMethod entrypoint, bool isShared = false);
DynamicType * CreateDeferredLengthFunctionTypeNoProfileThunk(JavascriptMethod entrypoint, bool isShared = false);
template<bool isLengthAvailable, bool isPrototypeAvailable> DynamicType * CreateDeferredFunctionTypeNoProfileThunk_Internal(JavascriptMethod entrypoint, bool isShared);
DynamicType * CreateFunctionType(JavascriptMethod entrypoint, RecyclableObject* prototype = nullptr);
DynamicType * CreateFunctionWithConfigurableLengthType(FunctionInfo * functionInfo);
DynamicType * CreateFunctionWithLengthType(FunctionInfo * functionInfo);
Oops, something went wrong.

0 comments on commit 93752a1

Please sign in to comment.