Skip to content

Commit

Permalink
[MERGE #1063] ES6hasInstance
Browse files Browse the repository at this point in the history
Merge pull request #1063 from suwc:build/suwc/buddy
Recuperate perf loss from existing ES6hasInstance implementation.
Perf-neutral with vs. without -es6hasinstance switch.
Add inline-cache-invalidation for user-defined Symbol.hasInstance property in function constructor.
Revamp unit tests for ES6hasInstance.

Related ECMA262 spec sections:
6.1.5.1 Well-Known Symbols
7.3.19 OrdinaryHasInstance (C, O)
12.10.4 Runtime Semantics: InstanceofOperator(O, C)
19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
  • Loading branch information
Suwei Chen committed Jun 9, 2016
2 parents 6f760f8 + 49fdae3 commit 9aafb18
Show file tree
Hide file tree
Showing 7 changed files with 395 additions and 107 deletions.
2 changes: 1 addition & 1 deletion lib/Common/ConfigFlagsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ FLAGPR (Boolean, ES6, ES6Unscopables , "Enable ES6 With Statem
FLAGPR (Boolean, ES6, ES6RegExSticky , "Enable ES6 RegEx sticky flag" , DEFAULT_CONFIG_ES6RegExSticky)
FLAGPR_REGOVR_EXP(Boolean, ES6, ES6RegExPrototypeProperties, "Enable ES6 properties on the RegEx prototype" , DEFAULT_CONFIG_ES6RegExPrototypeProperties)
FLAGPR_REGOVR_EXP(Boolean, ES6, ES6RegExSymbols , "Enable ES6 RegExp symbols" , DEFAULT_CONFIG_ES6RegExSymbols)
FLAGPR (Boolean, ES6, ES6HasInstance , "Enable ES6 @@hasInstance symbol" , DEFAULT_CONFIG_ES6HasInstanceOf)
FLAGPR_REGOVR_EXP(Boolean, ES6, ES6HasInstance , "Enable ES6 @@hasInstance symbol" , DEFAULT_CONFIG_ES6HasInstanceOf)
FLAGPR (Boolean, ES6, ES6Verbose , "Enable ES6 verbose trace" , DEFAULT_CONFIG_ES6Verbose)
FLAGPR_REGOVR_EXP(Boolean, ES6, ArrayBufferTransfer , "Enable ArrayBuffer.transfer" , DEFAULT_CONFIG_ArrayBufferTransfer)
// /ES6 (BLUE+1) features/flags
Expand Down
3 changes: 2 additions & 1 deletion lib/Runtime/Language/JavascriptOperators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6998,7 +6998,8 @@ namespace Js
if (scriptContext->GetConfig()->IsES6HasInstanceEnabled())
{
Var instOfHandler = JavascriptOperators::GetProperty(constructor, PropertyIds::_symbolHasInstance, scriptContext);
if (JavascriptOperators::IsUndefinedObject(instOfHandler))
if (JavascriptOperators::IsUndefinedObject(instOfHandler)
|| instOfHandler == scriptContext->GetBuiltInLibraryFunction(JavascriptFunction::EntryInfo::SymbolHasInstance.GetOriginalEntryPoint()))
{
return JavascriptBoolean::ToVar(constructor->HasInstance(instance, scriptContext, inlineCache), scriptContext);
}
Expand Down
16 changes: 6 additions & 10 deletions lib/Runtime/Library/JavascriptFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2697,7 +2697,7 @@ namespace Js

BOOL result = DynamicObject::SetProperty(propertyId, value, flags, info);

if (propertyId == PropertyIds::prototype)
if (propertyId == PropertyIds::prototype || propertyId == PropertyIds::_symbolHasInstance)
{
PropertyValueInfo::SetNoCache(info, this);
InvalidateConstructorCacheOnPrototypeChange();
Expand All @@ -2711,7 +2711,7 @@ namespace Js
{
BOOL result = __super::SetPropertyWithAttributes(propertyId, value, attributes, info, flags, possibleSideEffects);

if (propertyId == PropertyIds::prototype)
if (propertyId == PropertyIds::prototype || propertyId == PropertyIds::_symbolHasInstance)
{
PropertyValueInfo::SetNoCache(info, this);
InvalidateConstructorCacheOnPrototypeChange();
Expand Down Expand Up @@ -2759,7 +2759,7 @@ namespace Js

BOOL result = DynamicObject::DeleteProperty(propertyId, flags);

if (result && propertyId == PropertyIds::prototype)
if (result && propertyId == PropertyIds::prototype || propertyId == PropertyIds::_symbolHasInstance)
{
InvalidateConstructorCacheOnPrototypeChange();
this->GetScriptContext()->GetThreadContext()->InvalidateIsInstInlineCachesForFunction(this);
Expand Down Expand Up @@ -2976,18 +2976,14 @@ namespace Js

Assert(!(callInfo.Flags & CallFlags_New));

if (args.Info.Count < 2)
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedObject, _u("Function[Symbol.hasInstance]"));
}

RecyclableObject * constructor = RecyclableObject::FromVar(args[0]);
Var instance = args[1];
if (!JavascriptConversion::IsCallable(constructor))
if (!JavascriptConversion::IsCallable(constructor) || args.Info.Count < 2)
{
return JavascriptBoolean::ToVar(FALSE, scriptContext);
}

Var instance = args[1];

Assert(JavascriptProxy::Is(constructor) || JavascriptFunction::Is(constructor));
return JavascriptBoolean::ToVar(constructor->HasInstance(instance, scriptContext, NULL), scriptContext);
}
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Library/JavascriptLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2547,6 +2547,7 @@ namespace Js
library->AddFunctionToLibraryObjectWithName(functionPrototype, PropertyIds::_symbolHasInstance, PropertyIds::_RuntimeFunctionNameId_hasInstance,
&JavascriptFunction::EntryInfo::SymbolHasInstance, 1));
functionPrototype->SetWritable(PropertyIds::_symbolHasInstance, false);
functionPrototype->SetConfigurable(PropertyIds::_symbolHasInstance, false);
}

DebugOnly(CheckRegisteredBuiltIns(builtinFuncs, scriptContext));
Expand Down
19 changes: 0 additions & 19 deletions test/es6/es6HasInstance.baseline

This file was deleted.

Loading

0 comments on commit 9aafb18

Please sign in to comment.