Changeset 193974 in webkit


Ignore:
Timestamp:
Dec 11, 2015 1:43:45 PM (8 years ago)
Author:
keith_miller@apple.com
Message:

[ES6] Add support for Symbol.hasInstance
https://bugs.webkit.org/show_bug.cgi?id=151839

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch adds support for Symbol.hasInstance, unfortunately in order to prevent
regressions several new bytecodes and DFG IR nodes were necessary. Before, Symbol.hasInstance
when executing an instanceof expression we would emit three bytecodes: overrides_has_instance, get_by_id,
then instanceof. As the spec has changed, we emit a more complicated set of bytecodes in addition to some
new ones. First the role of overrides_has_instance and its corresponding DFG node have changed. Now it returns
a js-boolean indicating whether the RHS of the instanceof expression (from here on called the constructor for simplicity)
needs non-default behavior for resolving the expression. i.e. The constructor has a Symbol.hasInstance that differs from the one on
Function.prototype[Symbol.hasInstance] or is a bound/C-API function. Once we get to the DFG this node is generally eliminated as
we can prove the value of Symbol.hasInstance is a constant. The second new bytecode is instanceof_custom. insntanceof_custom, just
emits a call to slow path code that computes the result.

In the DFG, there is also a new node, CheckTypeInfoFlags, which checks the type info flags are consistent with the ones provided and
OSR exits if the flags are not. Additionally, we attempt to prove that the result of CheckHasValue will be a constant and transform
it into a CheckTypeInfoFlags followed by a JSConstant.

  • API/JSCallbackObject.h:
  • builtins/FunctionPrototype.js:

(symbolHasInstance):

  • bytecode/BytecodeBasicBlock.cpp:

(JSC::isBranch): Deleted.

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/ExitKind.cpp:

(JSC::exitKindToString):

  • bytecode/ExitKind.h:
  • bytecode/PreciseJumpTargets.cpp:

(JSC::getJumpTargetsForBytecodeOffset): Deleted.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitOverridesHasInstance):
(JSC::BytecodeGenerator::emitInstanceOfCustom):
(JSC::BytecodeGenerator::emitCheckHasInstance): Deleted.

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::InstanceOfNode::emitBytecode):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGHeapLocation.cpp:

(WTF::printInternal):

  • dfg/DFGHeapLocation.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasCellOperand):
(JSC::DFG::Node::hasTypeInfoOperand):
(JSC::DFG::Node::typeInfoOperand):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCheckTypeInfoFlags):
(JSC::DFG::SpeculativeJIT::compileInstanceOfCustom):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLIntrinsicRepository.h:
  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileOverridesHasInstance):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckTypeInfoFlags):
(JSC::FTL::DFG::LowerDFGToLLVM::compileInstanceOfCustom):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckHasInstance): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITInlines.h:

(JSC::JIT::callOperation):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_overrides_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emit_op_instanceof_custom):
(JSC::JIT::emitSlow_op_instanceof):
(JSC::JIT::emitSlow_op_instanceof_custom):
(JSC::JIT::emit_op_check_has_instance): Deleted.
(JSC::JIT::emitSlow_op_check_has_instance): Deleted.

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_overrides_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emit_op_instanceof_custom):
(JSC::JIT::emitSlow_op_instanceof_custom):
(JSC::JIT::emit_op_check_has_instance): Deleted.
(JSC::JIT::emitSlow_op_check_has_instance): Deleted.

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonIdentifiers.h:
  • runtime/ExceptionHelpers.cpp:

(JSC::invalidParameterInstanceofSourceAppender):
(JSC::invalidParameterInstanceofNotFunctionSourceAppender):
(JSC::invalidParameterInstanceofhasInstanceValueNotFunctionSourceAppender):
(JSC::createInvalidInstanceofParameterErrorNotFunction):
(JSC::createInvalidInstanceofParameterErrorhasInstanceValueNotFunction):
(JSC::createInvalidInstanceofParameterError): Deleted.

  • runtime/ExceptionHelpers.h:
  • runtime/FunctionPrototype.cpp:

(JSC::FunctionPrototype::addFunctionProperties):

  • runtime/FunctionPrototype.h:
  • runtime/JSBoundFunction.cpp:

(JSC::isBoundFunction):
(JSC::hasInstanceBoundFunction):

  • runtime/JSBoundFunction.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::functionProtoHasInstanceSymbolFunction):

  • runtime/JSObject.cpp:

(JSC::JSObject::hasInstance):
(JSC::objectPrivateFuncInstanceOf):

  • runtime/JSObject.h:
  • runtime/JSTypeInfo.h:

(JSC::TypeInfo::TypeInfo):
(JSC::TypeInfo::overridesHasInstance):

  • runtime/WriteBarrier.h:

(JSC::WriteBarrierBase<Unknown>::slot):

  • tests/es6.yaml:
  • tests/stress/instanceof-custom-hasinstancesymbol.js: Added.

(Constructor):
(value):
(instanceOf):
(body):

  • tests/stress/symbol-hasInstance.js: Added.

(Constructor):
(value):
(ObjectClass.Symbol.hasInstance):
(NumberClass.Symbol.hasInstance):

LayoutTests:

Fix tests to reflect the changes to instanceof in ES6.

Added a new regression test for bound functions in instanceof
as the perfomance on bound functions should, to some degree,
reflect the performance on C-API users.

  • js/Object-getOwnPropertyNames-expected.txt:
  • js/exception-for-nonobject-expected.txt:
  • js/exception-instanceof-expected.txt:
  • js/instance-of-immediates-expected.txt:
  • js/regress/instanceof-bound-expected.txt: Added.
  • js/regress/instanceof-bound.html: Added.
  • js/regress/script-tests/instanceof-bound.js: Added.

(Constructor):
(test):

  • js/script-tests/Object-getOwnPropertyNames.js:
Location:
trunk
Files:
5 added
64 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r193973 r193974  
     12015-12-11  Keith Miller  <keith_miller@apple.com>
     2
     3        [ES6] Add support for Symbol.hasInstance
     4        https://bugs.webkit.org/show_bug.cgi?id=151839
     5
     6        Reviewed by Saam Barati.
     7
     8        Fix tests to reflect the changes to instanceof in ES6.
     9
     10        Added a new regression test for bound functions in instanceof
     11        as the perfomance on bound functions should, to some degree,
     12        reflect the performance on C-API users.
     13
     14        * js/Object-getOwnPropertyNames-expected.txt:
     15        * js/exception-for-nonobject-expected.txt:
     16        * js/exception-instanceof-expected.txt:
     17        * js/instance-of-immediates-expected.txt:
     18        * js/regress/instanceof-bound-expected.txt: Added.
     19        * js/regress/instanceof-bound.html: Added.
     20        * js/regress/script-tests/instanceof-bound.js: Added.
     21        (Constructor):
     22        (test):
     23        * js/script-tests/Object-getOwnPropertyNames.js:
     24
    1252015-12-11  Ryan Haddad  <ryanhaddad@apple.com>
    226
  • trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt

    r191864 r193974  
    6262PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
    6363PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
    64 PASS getSortedOwnPropertyNames(Symbol) is ['for', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'toStringTag', 'unscopables']
     64PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'toStringTag', 'unscopables']
    6565PASS getSortedOwnPropertyNames(Symbol.prototype) is ['constructor', 'toString', 'valueOf']
    6666PASS globalPropertyNames.indexOf('NaN') != -1 is true
  • trunk/LayoutTests/js/exception-for-nonobject-expected.txt

    r181889 r193974  
    55
    66PASS new {}.undefined threw exception TypeError: undefined is not a constructor (evaluating 'new {}.undefined').
    7 PASS 1 instanceof {}.undefined threw exception TypeError: {}.undefined is not a function. (evaluating '1 instanceof {}.undefined').
     7PASS 1 instanceof {}.undefined threw exception TypeError: Right hand side of instanceof is not an object.
    88PASS successfullyParsed is true
    99
  • trunk/LayoutTests/js/exception-instanceof-expected.txt

    r181889 r193974  
    44
    55
    6 PASS 'instanceof' instanceof    'instanceof' threw exception TypeError: "instanceof" is not a function. (evaluating ''instanceof' instanceof    'instanceof'').
    7 PASS 20 instanceof     'hello'   threw exception TypeError: 'hello' is not a function. (evaluating '20 instanceof     'hello'').
     6PASS 'instanceof' instanceof    'instanceof' threw exception TypeError: Right hand side of instanceof is not an object.
     7PASS 20 instanceof     'hello'   threw exception TypeError: Right hand side of instanceof is not an object.
    88PASS 20 instanceof     {}   threw exception TypeError: {} is not a function. (evaluating '20 instanceof     {}').
    9 PASS 20 instanceof     {}.foo  threw exception TypeError: {}.foo is not a function. (evaluating '20 instanceof     {}.foo').
    10 PASS 20 instanceof     true       threw exception TypeError: true is not a function. (evaluating '20 instanceof     true').
     9PASS 20 instanceof     {}.foo  threw exception TypeError: Right hand side of instanceof is not an object.
     10PASS 20 instanceof     true       threw exception TypeError: Right hand side of instanceof is not an object.
    1111PASS successfullyParsed is true
    1212
  • trunk/LayoutTests/js/instance-of-immediates-expected.txt

    r181889 r193974  
    44
    55
    6 PASS (1 instanceof 1) threw exception TypeError: 1 is not a function. (evaluating '1 instanceof 1').
    7 PASS ({} instanceof 1) threw exception TypeError: 1 is not a function. (evaluating '{} instanceof 1').
    8 PASS (obj instanceof 1) threw exception TypeError: 1 is not a function. (evaluating 'obj instanceof 1').
     6PASS (1 instanceof 1) threw exception TypeError: Right hand side of instanceof is not an object.
     7PASS ({} instanceof 1) threw exception TypeError: Right hand side of instanceof is not an object.
     8PASS (obj instanceof 1) threw exception TypeError: Right hand side of instanceof is not an object.
    99PASS (1 instanceof {}) threw exception TypeError: {} is not a function. (evaluating '1 instanceof {}').
    1010PASS ({} instanceof {}) threw exception TypeError: {} is not a function. (evaluating '{} instanceof {}').
  • trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js

    r191864 r193974  
    7171    "Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']",
    7272    "JSON": "['parse', 'stringify']",
    73     "Symbol": "['for', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'toStringTag', 'unscopables']",
     73    "Symbol": "['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'toStringTag', 'unscopables']",
    7474    "Symbol.prototype": "['constructor', 'toString', 'valueOf']"
    7575};
  • trunk/Source/JavaScriptCore/API/JSCallbackObject.h

    r187587 r193974  
    128128public:
    129129    typedef Parent Base;
    130     static const unsigned StructureFlags = Base::StructureFlags | ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | OverridesHasInstance | OverridesGetPropertyNames | TypeOfShouldCallGetCallData;
     130    static const unsigned StructureFlags = Base::StructureFlags | ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | OverridesHasInstanceFlag | OverridesGetPropertyNames | TypeOfShouldCallGetCallData;
    131131
    132132    ~JSCallbackObject();
  • trunk/Source/JavaScriptCore/ChangeLog

    r193972 r193974  
     12015-12-11  Keith Miller  <keith_miller@apple.com>
     2
     3        [ES6] Add support for Symbol.hasInstance
     4        https://bugs.webkit.org/show_bug.cgi?id=151839
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch adds support for Symbol.hasInstance, unfortunately in order to prevent
     9        regressions several new bytecodes and DFG IR nodes were necessary. Before, Symbol.hasInstance
     10        when executing an instanceof expression we would emit three bytecodes: overrides_has_instance, get_by_id,
     11        then instanceof. As the spec has changed, we emit a more complicated set of bytecodes in addition to some
     12        new ones. First the role of overrides_has_instance and its corresponding DFG node have changed. Now it returns
     13        a js-boolean indicating whether the RHS of the instanceof expression (from here on called the constructor for simplicity)
     14        needs non-default behavior for resolving the expression. i.e. The constructor has a Symbol.hasInstance that differs from the one on
     15        Function.prototype[Symbol.hasInstance] or is a bound/C-API function. Once we get to the DFG this node is generally eliminated as
     16        we can prove the value of Symbol.hasInstance is a constant. The second new bytecode is instanceof_custom. insntanceof_custom, just
     17        emits a call to slow path code that computes the result.
     18
     19        In the DFG, there is also a new node, CheckTypeInfoFlags, which checks the type info flags are consistent with the ones provided and
     20        OSR exits if the flags are not. Additionally, we attempt to prove that the result of CheckHasValue will be a constant and transform
     21        it into a CheckTypeInfoFlags followed by a JSConstant.
     22
     23        * API/JSCallbackObject.h:
     24        * builtins/FunctionPrototype.js:
     25        (symbolHasInstance):
     26        * bytecode/BytecodeBasicBlock.cpp:
     27        (JSC::isBranch): Deleted.
     28        * bytecode/BytecodeList.json:
     29        * bytecode/BytecodeUseDef.h:
     30        (JSC::computeUsesForBytecodeOffset):
     31        (JSC::computeDefsForBytecodeOffset):
     32        * bytecode/CodeBlock.cpp:
     33        (JSC::CodeBlock::dumpBytecode):
     34        * bytecode/ExitKind.cpp:
     35        (JSC::exitKindToString):
     36        * bytecode/ExitKind.h:
     37        * bytecode/PreciseJumpTargets.cpp:
     38        (JSC::getJumpTargetsForBytecodeOffset): Deleted.
     39        * bytecompiler/BytecodeGenerator.cpp:
     40        (JSC::BytecodeGenerator::emitOverridesHasInstance):
     41        (JSC::BytecodeGenerator::emitInstanceOfCustom):
     42        (JSC::BytecodeGenerator::emitCheckHasInstance): Deleted.
     43        * bytecompiler/BytecodeGenerator.h:
     44        * bytecompiler/NodesCodegen.cpp:
     45        (JSC::InstanceOfNode::emitBytecode):
     46        * dfg/DFGAbstractInterpreterInlines.h:
     47        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     48        * dfg/DFGByteCodeParser.cpp:
     49        (JSC::DFG::ByteCodeParser::parseBlock):
     50        * dfg/DFGCapabilities.cpp:
     51        (JSC::DFG::capabilityLevel):
     52        * dfg/DFGClobberize.h:
     53        (JSC::DFG::clobberize):
     54        * dfg/DFGDoesGC.cpp:
     55        (JSC::DFG::doesGC):
     56        * dfg/DFGFixupPhase.cpp:
     57        (JSC::DFG::FixupPhase::fixupNode):
     58        * dfg/DFGHeapLocation.cpp:
     59        (WTF::printInternal):
     60        * dfg/DFGHeapLocation.h:
     61        * dfg/DFGNode.h:
     62        (JSC::DFG::Node::hasCellOperand):
     63        (JSC::DFG::Node::hasTypeInfoOperand):
     64        (JSC::DFG::Node::typeInfoOperand):
     65        * dfg/DFGNodeType.h:
     66        * dfg/DFGPredictionPropagationPhase.cpp:
     67        (JSC::DFG::PredictionPropagationPhase::propagate):
     68        * dfg/DFGSafeToExecute.h:
     69        (JSC::DFG::safeToExecute):
     70        * dfg/DFGSpeculativeJIT.cpp:
     71        (JSC::DFG::SpeculativeJIT::compileCheckTypeInfoFlags):
     72        (JSC::DFG::SpeculativeJIT::compileInstanceOfCustom):
     73        * dfg/DFGSpeculativeJIT.h:
     74        (JSC::DFG::SpeculativeJIT::callOperation):
     75        * dfg/DFGSpeculativeJIT32_64.cpp:
     76        (JSC::DFG::SpeculativeJIT::compile):
     77        * dfg/DFGSpeculativeJIT64.cpp:
     78        (JSC::DFG::SpeculativeJIT::compile):
     79        * ftl/FTLCapabilities.cpp:
     80        (JSC::FTL::canCompile):
     81        * ftl/FTLIntrinsicRepository.h:
     82        * ftl/FTLLowerDFGToLLVM.cpp:
     83        (JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
     84        (JSC::FTL::DFG::LowerDFGToLLVM::compileOverridesHasInstance):
     85        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckTypeInfoFlags):
     86        (JSC::FTL::DFG::LowerDFGToLLVM::compileInstanceOfCustom):
     87        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckHasInstance): Deleted.
     88        * jit/JIT.cpp:
     89        (JSC::JIT::privateCompileMainPass):
     90        (JSC::JIT::privateCompileSlowCases):
     91        * jit/JIT.h:
     92        * jit/JITInlines.h:
     93        (JSC::JIT::callOperation):
     94        * jit/JITOpcodes.cpp:
     95        (JSC::JIT::emit_op_overrides_has_instance):
     96        (JSC::JIT::emit_op_instanceof):
     97        (JSC::JIT::emit_op_instanceof_custom):
     98        (JSC::JIT::emitSlow_op_instanceof):
     99        (JSC::JIT::emitSlow_op_instanceof_custom):
     100        (JSC::JIT::emit_op_check_has_instance): Deleted.
     101        (JSC::JIT::emitSlow_op_check_has_instance): Deleted.
     102        * jit/JITOpcodes32_64.cpp:
     103        (JSC::JIT::emit_op_overrides_has_instance):
     104        (JSC::JIT::emit_op_instanceof):
     105        (JSC::JIT::emit_op_instanceof_custom):
     106        (JSC::JIT::emitSlow_op_instanceof_custom):
     107        (JSC::JIT::emit_op_check_has_instance): Deleted.
     108        (JSC::JIT::emitSlow_op_check_has_instance): Deleted.
     109        * jit/JITOperations.cpp:
     110        * jit/JITOperations.h:
     111        * llint/LLIntData.cpp:
     112        (JSC::LLInt::Data::performAssertions):
     113        * llint/LLIntSlowPaths.cpp:
     114        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     115        * llint/LLIntSlowPaths.h:
     116        * llint/LowLevelInterpreter32_64.asm:
     117        * llint/LowLevelInterpreter64.asm:
     118        * runtime/CommonIdentifiers.h:
     119        * runtime/ExceptionHelpers.cpp:
     120        (JSC::invalidParameterInstanceofSourceAppender):
     121        (JSC::invalidParameterInstanceofNotFunctionSourceAppender):
     122        (JSC::invalidParameterInstanceofhasInstanceValueNotFunctionSourceAppender):
     123        (JSC::createInvalidInstanceofParameterErrorNotFunction):
     124        (JSC::createInvalidInstanceofParameterErrorhasInstanceValueNotFunction):
     125        (JSC::createInvalidInstanceofParameterError): Deleted.
     126        * runtime/ExceptionHelpers.h:
     127        * runtime/FunctionPrototype.cpp:
     128        (JSC::FunctionPrototype::addFunctionProperties):
     129        * runtime/FunctionPrototype.h:
     130        * runtime/JSBoundFunction.cpp:
     131        (JSC::isBoundFunction):
     132        (JSC::hasInstanceBoundFunction):
     133        * runtime/JSBoundFunction.h:
     134        * runtime/JSGlobalObject.cpp:
     135        (JSC::JSGlobalObject::init):
     136        (JSC::JSGlobalObject::visitChildren):
     137        * runtime/JSGlobalObject.h:
     138        (JSC::JSGlobalObject::functionProtoHasInstanceSymbolFunction):
     139        * runtime/JSObject.cpp:
     140        (JSC::JSObject::hasInstance):
     141        (JSC::objectPrivateFuncInstanceOf):
     142        * runtime/JSObject.h:
     143        * runtime/JSTypeInfo.h:
     144        (JSC::TypeInfo::TypeInfo):
     145        (JSC::TypeInfo::overridesHasInstance):
     146        * runtime/WriteBarrier.h:
     147        (JSC::WriteBarrierBase<Unknown>::slot):
     148        * tests/es6.yaml:
     149        * tests/stress/instanceof-custom-hasinstancesymbol.js: Added.
     150        (Constructor):
     151        (value):
     152        (instanceOf):
     153        (body):
     154        * tests/stress/symbol-hasInstance.js: Added.
     155        (Constructor):
     156        (value):
     157        (ObjectClass.Symbol.hasInstance):
     158        (NumberClass.Symbol.hasInstance):
     159
    11602015-12-11  Joseph Pecoraro  <pecoraro@apple.com>
    2161
  • trunk/Source/JavaScriptCore/builtins/FunctionPrototype.js

    r192751 r193974  
    3737    return this.@apply(thisValue, argumentValues);
    3838}
     39
     40// FIXME: this should have a different name: https://bugs.webkit.org/show_bug.cgi?id=151363
     41function symbolHasInstance(value)
     42{
     43    "use strict";
     44
     45    if (typeof this !== "function")
     46        return false;
     47
     48    if (@isBoundFunction(this))
     49        return @hasInstanceBoundFunction(this, value);
     50
     51    let target = this.prototype;
     52    return @instanceOf(value, target);
     53}
  • trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp

    r192937 r193974  
    5959    case op_switch_char:
    6060    case op_switch_string:
    61     case op_check_has_instance:
    6261    case op_save:
    6362        return true;
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r193766 r193974  
    4646            { "name" : "op_bitxor", "length" : 5 },
    4747            { "name" : "op_bitor", "length" : 5 },
    48             { "name" : "op_check_has_instance", "length" : 5 },
     48            { "name" : "op_overrides_has_instance", "length" : 4 },
    4949            { "name" : "op_instanceof", "length" : 4 },
     50            { "name" : "op_instanceof_custom", "length" : 5 },
    5051            { "name" : "op_typeof", "length" : 3 },
    5152            { "name" : "op_is_undefined", "length" : 3 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r193766 r193974  
    170170    case op_in:
    171171    case op_instanceof:
    172     case op_check_has_instance:
    173172    case op_add:
    174173    case op_mul:
     
    196195        return;
    197196    }
     197    case op_overrides_has_instance:
     198    case op_instanceof_custom:
    198199    case op_has_structure_property:
    199200    case op_construct_varargs:
     
    351352    case op_get_by_id:
    352353    case op_get_array_length:
    353     case op_check_has_instance:
     354    case op_overrides_has_instance:
    354355    case op_instanceof:
     356    case op_instanceof_custom:
    355357    case op_get_by_val:
    356358    case op_typeof:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r193766 r193974  
    10141014            break;
    10151015        }
    1016         case op_check_has_instance: {
     1016        case op_overrides_has_instance: {
    10171017            int r0 = (++it)->u.operand;
    10181018            int r1 = (++it)->u.operand;
    10191019            int r2 = (++it)->u.operand;
    1020             int offset = (++it)->u.operand;
    1021             printLocationAndOp(out, exec, location, it, "check_has_instance");
    1022             out.printf("%s, %s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), offset, location + offset);
     1020            printLocationAndOp(out, exec, location, it, "overrides_has_instance");
     1021            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
    10231022            break;
    10241023        }
     
    10291028            printLocationAndOp(out, exec, location, it, "instanceof");
    10301029            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
     1030            break;
     1031        }
     1032        case op_instanceof_custom: {
     1033            int r0 = (++it)->u.operand;
     1034            int r1 = (++it)->u.operand;
     1035            int r2 = (++it)->u.operand;
     1036            int r3 = (++it)->u.operand;
     1037            printLocationAndOp(out, exec, location, it, "instanceof_custom");
     1038            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
    10311039            break;
    10321040        }
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp

    r188299 r193974  
    5151    case BadIndexingType:
    5252        return "BadIndexingType";
     53    case BadTypeInfoFlags:
     54        return "BadTypeInfoFlags";
    5355    case Overflow:
    5456        return "Overflow";
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.h

    r188299 r193974  
    3838    BadConstantCache, // We exited because a cache on a weak constant (usually a prototype) was wrong.
    3939    BadIndexingType, // We exited because an indexing type was wrong.
     40    BadTypeInfoFlags, // We exited because we made an incorrect assumption about what TypeInfo flags we would see.
    4041    Overflow, // We exited because of overflow.
    4142    NegativeZero, // We exited because we encountered negative zero.
  • trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp

    r192937 r193974  
    7575        break;
    7676    }
    77     case op_check_has_instance:
    78         out.append(bytecodeOffset + current[4].u.operand);
    79         break;
    8077    case op_loop_hint:
    8178        out.append(bytecodeOffset);
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r193842 r193974  
    21002100}
    21012101
    2102 void BytecodeGenerator::emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target)
    2103 {
    2104     size_t begin = instructions().size();
    2105     emitOpcode(op_check_has_instance);
     2102RegisterID* BytecodeGenerator::emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue)
     2103{
     2104    emitOpcode(op_overrides_has_instance);
    21062105    instructions().append(dst->index());
    2107     instructions().append(value->index());
    2108     instructions().append(base->index());
    2109     instructions().append(target->bind(begin, instructions().size()));
     2106    instructions().append(constructor->index());
     2107    instructions().append(hasInstanceValue->index());
     2108    return dst;
    21102109}
    21112110
     
    22712270    instructions().append(value->index());
    22722271    instructions().append(basePrototype->index());
     2272    return dst;
     2273}
     2274
     2275RegisterID* BytecodeGenerator::emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue)
     2276{
     2277    emitOpcode(op_instanceof_custom);
     2278    instructions().append(dst->index());
     2279    instructions().append(value->index());
     2280    instructions().append(constructor->index());
     2281    instructions().append(hasInstanceValue->index());
    22732282    return dst;
    22742283}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r193842 r193974  
    535535        RegisterID* emitDec(RegisterID* srcDst);
    536536
    537         void emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target);
     537        RegisterID* emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue);
    538538        RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
     539        RegisterID* emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue);
    539540        RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
    540541        RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r193766 r193974  
    16601660RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    16611661{
    1662     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    1663     RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
     1662    RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
     1663    RefPtr<RegisterID> isObject = generator.newTemporary();
     1664    RefPtr<RegisterID> isCustom = generator.newTemporary();
    16641665    RefPtr<RegisterID> prototype = generator.newTemporary();
    1665     RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
    1666     RefPtr<Label> target = generator.newLabel();
     1666    RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
     1667    RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
     1668    RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
     1669    RefPtr<Label> custom = generator.newLabel();
     1670    RefPtr<Label> done = generator.newLabel();
     1671    RefPtr<Label> typeError = generator.newLabel();
    16671672
    16681673    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1669     generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
     1674    generator.emitIsObject(isObject.get(), constructor.get());
     1675    generator.emitJumpIfFalse(isObject.get(), typeError.get());
    16701676
    16711677    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1672     generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
     1678    generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
    16731679
    16741680    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1675     RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
    1676     generator.emitLabel(target.get());
    1677     return result;
     1681    generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
     1682
     1683    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1684    generator.emitJumpIfTrue(isCustom.get(), custom.get());
     1685
     1686    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1687    generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
     1688
     1689    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1690    generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
     1691
     1692    generator.emitJump(done.get());
     1693
     1694    generator.emitLabel(typeError.get());
     1695    generator.emitThrowTypeError("Right hand side of instanceof is not an object");
     1696
     1697    generator.emitLabel(custom.get());
     1698
     1699    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1700    generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
     1701
     1702    generator.emitLabel(done.get());
     1703
     1704    return dstReg.get();
    16781705}
    16791706
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r193781 r193974  
    24492449        break;
    24502450           
    2451     case CheckHasInstance:
    2452         // Sadly, we don't propagate the fact that we've done CheckHasInstance
     2451    case OverridesHasInstance:
     2452        forNode(node).setType(SpecBoolean);
    24532453        break;
    24542454           
    24552455    case InstanceOf:
    2456         // Again, sadly, we don't propagate the fact that we've done InstanceOf
     2456        // Sadly, we don't propagate the fact that we've done InstanceOf
     2457        forNode(node).setType(SpecBoolean);
     2458        break;
     2459
     2460    case InstanceOfCustom:
     2461        clobberWorld(node->origin.semantic, clobberLimit);
    24572462        forNode(node).setType(SpecBoolean);
    24582463        break;
     
    25112516    case CheckTierUpInLoop:
    25122517    case CheckTierUpAtReturn:
     2518    case CheckTypeInfoFlags:
    25132519        break;
    25142520
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r193766 r193974  
    34983498        }
    34993499
    3500         case op_check_has_instance:
    3501             addToGraph(CheckHasInstance, get(VirtualRegister(currentInstruction[3].u.operand)));
    3502             NEXT_OPCODE(op_check_has_instance);
     3500        case op_overrides_has_instance: {
     3501            JSFunction* defaultHasInstanceSymbolFunction = m_inlineStackTop->m_codeBlock->globalObjectFor(currentCodeOrigin())->functionProtoHasInstanceSymbolFunction();
     3502
     3503            Node* constructor = get(VirtualRegister(currentInstruction[2].u.operand));
     3504            Node* hasInstanceValue = get(VirtualRegister(currentInstruction[3].u.operand));
     3505
     3506            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(OverridesHasInstance, OpInfo(m_graph.freeze(defaultHasInstanceSymbolFunction)), constructor, hasInstanceValue));
     3507            NEXT_OPCODE(op_overrides_has_instance);
     3508        }
    35033509
    35043510        case op_instanceof: {
     
    35083514            NEXT_OPCODE(op_instanceof);
    35093515        }
    3510            
     3516
     3517        case op_instanceof_custom: {
     3518            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
     3519            Node* constructor = get(VirtualRegister(currentInstruction[3].u.operand));
     3520            Node* hasInstanceValue = get(VirtualRegister(currentInstruction[4].u.operand));
     3521            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(InstanceOfCustom, value, constructor, hasInstanceValue));
     3522            NEXT_OPCODE(op_instanceof_custom);
     3523        }
     3524
    35113525        case op_is_undefined: {
    35123526            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r193766 r193974  
    129129    case op_profile_control_flow:
    130130    case op_mov:
    131     case op_check_has_instance:
     131    case op_overrides_has_instance:
    132132    case op_instanceof:
     133    case op_instanceof_custom:
    133134    case op_is_undefined:
    134135    case op_is_boolean:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r193781 r193974  
    728728        return;
    729729
    730     case CheckHasInstance:
     730    case CheckTypeInfoFlags:
    731731        read(JSCell_typeInfoFlags);
    732         def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
     732        def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
     733        return;
     734
     735    case OverridesHasInstance:
     736        read(JSCell_typeInfoFlags);
     737        def(HeapLocation(OverridesHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
    733738        return;
    734739
     
    736741        read(JSCell_structureID);
    737742        def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), LazyNode(node));
     743        return;
     744
     745    case InstanceOfCustom:
     746        read(World);
     747        write(Heap);
    738748        return;
    739749
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r193766 r193974  
    142142    case ProfileType:
    143143    case ProfileControlFlow:
    144     case CheckHasInstance:
     144    case OverridesHasInstance:
    145145    case InstanceOf:
     146    case InstanceOfCustom:
    146147    case IsUndefined:
    147148    case IsBoolean:
     
    181182    case ConstantStoragePointer:
    182183    case Check:
     184    case CheckTypeInfoFlags:
    183185    case MultiGetByOffset:
    184186    case ValueRep:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r193781 r193974  
    11011101            break;
    11021102        }
     1103
     1104        case OverridesHasInstance: {
     1105            if (node->child2().node()->isCellConstant()) {
     1106                if (node->child2().node()->asCell() != m_graph.globalObjectFor(node->origin.semantic)->functionProtoHasInstanceSymbolFunction()) {
     1107
     1108                    m_graph.convertToConstant(node, jsBoolean(true));
     1109                    break;
     1110                }
     1111
     1112                if (!m_graph.hasExitSite(node->origin.semantic, BadTypeInfoFlags)) {
     1113                    // Here we optimistically assume that we will not see an bound/C-API function here.
     1114                    m_insertionSet.insertNode(m_indexInBlock, SpecNone, CheckTypeInfoFlags, node->origin, OpInfo(ImplementsDefaultHasInstance), Edge(node->child1().node(), CellUse));
     1115                    m_graph.convertToConstant(node, jsBoolean(false));
     1116                    break;
     1117                }
     1118            }
     1119
     1120            fixEdge<CellUse>(node->child1());
     1121            break;
     1122        }
    11031123           
    11041124        case CheckStructure:
    11051125        case CheckCell:
    1106         case CheckHasInstance:
    11071126        case CreateThis:
    11081127        case GetButterfly:
     
    11651184            break;
    11661185        }
    1167            
     1186
     1187        case InstanceOfCustom:
     1188            fixEdge<CellUse>(node->child2());
     1189            break;
     1190
    11681191        case In: {
    11691192            // FIXME: We should at some point have array profiling on op_in, in which
     
    14111434        case VarInjectionWatchpoint:
    14121435        case Call:
     1436        case CheckTypeInfoFlags:
    14131437        case TailCallInlinedCaller:
    14141438        case Construct:
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r190896 r193974  
    9696        out.print("ButterflyReadOnlyLoc");
    9797        return;
    98        
    99     case CheckHasInstanceLoc:
    100         out.print("CheckHasInstanceLoc");
     98
     99    case CheckTypeInfoFlagsLoc:
     100        out.print("CheckTypeInfoFlagsLoc");
     101        return;
     102
     103    case OverridesHasInstanceLoc:
     104        out.print("OverridesHasInstanceLoc");
    101105        return;
    102106       
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h

    r190896 r193974  
    4141    ButterflyLoc,
    4242    ButterflyReadOnlyLoc,
    43     CheckHasInstanceLoc,
     43    CheckTypeInfoFlagsLoc,
     44    OverridesHasInstanceLoc,
    4445    ClosureVariableLoc,
    4546    DirectArgumentsLoc,
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r193470 r193974  
    13551355        switch (op()) {
    13561356        case CheckCell:
     1357        case OverridesHasInstance:
    13571358        case NewFunction:
    13581359        case NewArrowFunction:
     
    14141415        ASSERT(hasUidOperand());
    14151416        return reinterpret_cast<UniquedStringImpl*>(m_opInfo);
     1417    }
     1418
     1419    bool hasTypeInfoOperand()
     1420    {
     1421        return op() == CheckTypeInfoFlags;
     1422    }
     1423
     1424    unsigned typeInfoOperand()
     1425    {
     1426        ASSERT(hasTypeInfoOperand() && m_opInfo <= UCHAR_MAX);
     1427        return static_cast<unsigned>(m_opInfo);
    14161428    }
    14171429
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r193766 r193974  
    222222    macro(CheckInBounds, NodeMustGenerate) \
    223223    macro(CheckIdent, NodeMustGenerate) \
     224    macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\
    224225    \
    225226    /* Optimizations for array mutation. */\
     
    279280    macro(ProfileWillCall, NodeMustGenerate) \
    280281    macro(ProfileDidCall, NodeMustGenerate) \
    281     macro(CheckHasInstance, NodeMustGenerate) \
     282    macro(OverridesHasInstance, NodeMustGenerate | NodeResultBoolean) \
    282283    macro(InstanceOf, NodeResultBoolean) \
     284    macro(InstanceOfCustom, NodeMustGenerate | NodeResultBoolean) \
    283285    macro(IsUndefined, NodeResultBoolean) \
    284286    macro(IsBoolean, NodeResultBoolean) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r193781 r193974  
    403403        case CompareEq:
    404404        case CompareStrictEq:
     405        case OverridesHasInstance:
    405406        case InstanceOf:
     407        case InstanceOfCustom:
    406408        case IsUndefined:
    407409        case IsBoolean:
     
    570572        case GetLocalUnlinked:
    571573        case CheckArray:
     574        case CheckTypeInfoFlags:
    572575        case Arrayify:
    573576        case ArrayifyToStructure:
     
    681684        case ProfileType:
    682685        case ProfileControlFlow:
    683         case CheckHasInstance:
    684686        case ThrowReferenceError:
    685687        case ForceOSRExit:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r193766 r193974  
    242242    case ProfileType:
    243243    case ProfileControlFlow:
    244     case CheckHasInstance:
     244    case CheckTypeInfoFlags:
     245    case OverridesHasInstance:
    245246    case InstanceOf:
     247    case InstanceOfCustom:
    246248    case IsUndefined:
    247249    case IsBoolean:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r193795 r193974  
    27392739}
    27402740
     2741void SpeculativeJIT::compileCheckTypeInfoFlags(Node* node)
     2742{
     2743    SpeculateCellOperand base(this, node->child1());
     2744
     2745    GPRReg baseGPR = base.gpr();
     2746
     2747    speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
     2748
     2749    noResult(node);
     2750}
     2751
    27412752void SpeculativeJIT::compileInstanceOf(Node* node)
    27422753{
     
    29492960    jsValueResult(resultRegs, node);
    29502961    return;
     2962}
     2963
     2964void SpeculativeJIT::compileInstanceOfCustom(Node* node)
     2965{
     2966    // We could do something smarter here but this case is currently super rare and unless
     2967    // Symbol.hasInstance becomes popular will likely remain that way.
     2968
     2969    JSValueOperand value(this, node->child1());
     2970    SpeculateCellOperand constructor(this, node->child2());
     2971    JSValueOperand hasInstanceValue(this, node->child3());
     2972    GPRTemporary result(this);
     2973
     2974    JSValueRegs valueRegs = value.jsValueRegs();
     2975    GPRReg constructorGPR = constructor.gpr();
     2976    JSValueRegs hasInstanceRegs = hasInstanceValue.jsValueRegs();
     2977    GPRReg resultGPR = result.gpr();
     2978
     2979    MacroAssembler::Jump slowCase = m_jit.jump();
     2980
     2981    addSlowPathGenerator(slowPathCall(slowCase, this, operationInstanceOfCustom, resultGPR, valueRegs, constructorGPR, hasInstanceRegs));
     2982
     2983    unblessedBooleanResult(resultGPR, node);
    29512984}
    29522985
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r193795 r193974  
    728728    void compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchAndResultReg, GPRReg scratch2Reg);
    729729    void compileInstanceOf(Node*);
     730    void compileInstanceOfCustom(Node*);
    730731   
    731732    void emitCall(Node*);
     
    15121513        return appendCallSetResult(operation, result);
    15131514    }
     1515
     1516    JITCompiler::Call callOperation(Z_JITOperation_EJOJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     1517    {
     1518        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
     1519        return appendCallSetResult(operation, result);
     1520    }
     1521    JITCompiler::Call callOperation(Z_JITOperation_EJOJ operation, GPRReg result, JSValueRegs arg1, GPRReg arg2, JSValueRegs arg3)
     1522    {
     1523        return callOperation(operation, result, arg1.payloadGPR(), arg2, arg3.payloadGPR());
     1524    }
     1525
    15141526    JITCompiler::Call callOperation(Z_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, unsigned arg2)
    15151527    {
     
    18311843        m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG SH4_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
    18321844        return appendCall(operation);
     1845    }
     1846
     1847    JITCompiler::Call callOperation(Z_JITOperation_EJOJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
     1848    {
     1849        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
     1850        return appendCallSetResult(operation, result);
     1851    }
     1852    JITCompiler::Call callOperation(Z_JITOperation_EJOJ operation, GPRReg result, JSValueRegs arg1, GPRReg arg2, JSValueRegs arg3)
     1853    {
     1854        return callOperation(operation, result, arg1.tagGPR(), arg1.payloadGPR(), arg2, arg3.tagGPR(), arg3.payloadGPR());
    18331855    }
    18341856
     
    22052227    void compileGetArrayLength(Node*);
    22062228
     2229    void compileCheckTypeInfoFlags(Node*);
    22072230    void compileCheckIdent(Node*);
    22082231   
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r193795 r193974  
    41604160    }
    41614161
    4162     case CheckHasInstance: {
     4162    case CheckTypeInfoFlags: {
     4163        compileCheckTypeInfoFlags(node);
     4164        break;
     4165    }
     4166
     4167    case OverridesHasInstance: {
     4168
     4169        Node* hasInstanceValueNode = node->child2().node();
     4170        JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
     4171
     4172        MacroAssembler::Jump notDefaulthasInstanceValue;
     4173        MacroAssembler::Jump hasInstanceValueNotCell;
    41634174        SpeculateCellOperand base(this, node->child1());
    4164         GPRTemporary structure(this);
    4165 
    4166         // Speculate that base 'ImplementsDefaultHasInstance'.
    4167         speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branchTest8(
    4168             MacroAssembler::Zero,
    4169             MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()),
    4170             MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
    4171 
    4172         noResult(node);
     4175        JSValueOperand hasInstanceValue(this, node->child2());
     4176        GPRTemporary result(this);
     4177
     4178        GPRReg resultGPR = result.gpr();
     4179
     4180        // If we have proven that the constructor's Symbol.hasInstance will always be the one on
     4181        // Function.prototype[Symbol.hasInstance] then we don't need a runtime check here. We don't worry
     4182        // about the case where the constructor's Symbol.hasInstance is a constant but is not the default
     4183        // one as fixup should have converted this check to true.
     4184        ASSERT(!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction == hasInstanceValueNode->asCell());
     4185        if (!hasInstanceValueNode->isCellConstant()) {
     4186
     4187            JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs();
     4188            hasInstanceValueNotCell = m_jit.branchIfNotCell(hasInstanceValueRegs);
     4189            notDefaulthasInstanceValue = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(defaultHasInstanceFunction));
     4190        }
     4191
     4192        // Check that constructor 'ImplementsDefaultHasInstance'.
     4193        m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
     4194        MacroAssembler::Jump done = m_jit.jump();
     4195
     4196        if (!hasInstanceValueNode->isCellConstant()) {
     4197            hasInstanceValueNotCell.link(&m_jit);
     4198            notDefaulthasInstanceValue.link(&m_jit);
     4199            moveTrueTo(resultGPR);
     4200        }
     4201
     4202        done.link(&m_jit);
     4203        booleanResult(resultGPR, node);
    41734204        break;
    41744205    }
     
    41764207    case InstanceOf: {
    41774208        compileInstanceOf(node);
     4209        break;
     4210    }
     4211
     4212    case InstanceOfCustom: {
     4213        compileInstanceOfCustom(node);
    41784214        break;
    41794215    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r193795 r193974  
    41504150    }
    41514151
    4152     case CheckHasInstance: {
     4152    case CheckTypeInfoFlags: {
     4153        compileCheckTypeInfoFlags(node);
     4154        break;
     4155    }
     4156
     4157    case OverridesHasInstance: {
     4158
     4159        Node* hasInstanceValueNode = node->child2().node();
     4160        JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
     4161
     4162        MacroAssembler::Jump notDefault;
    41534163        SpeculateCellOperand base(this, node->child1());
    4154         GPRTemporary structure(this);
    4155 
    4156         // Speculate that base 'ImplementsDefaultHasInstance'.
    4157         speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branchTest8(
    4158             MacroAssembler::Zero,
    4159             MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()),
    4160             MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
    4161 
    4162         noResult(node);
     4164        JSValueOperand hasInstanceValue(this, node->child2());
     4165        GPRTemporary result(this);
     4166
     4167        GPRReg resultGPR = result.gpr();
     4168
     4169        // If we have proven that the constructor's Symbol.hasInstance will always be the one on Function.prototype[Symbol.hasInstance]
     4170        // then we don't need a runtime check here. We don't worry about the case where the constructor's Symbol.hasInstance is a constant
     4171        // but is not the default one as fixup should have converted this check to true.
     4172        ASSERT(!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction == hasInstanceValueNode->asCell());
     4173        if (!hasInstanceValueNode->isCellConstant())
     4174            notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValue.gpr(), TrustedImmPtr(defaultHasInstanceFunction));
     4175
     4176        // Check that base 'ImplementsDefaultHasInstance'.
     4177        m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
     4178        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
     4179        MacroAssembler::Jump done = m_jit.jump();
     4180
     4181        if (notDefault.isSet()) {
     4182            notDefault.link(&m_jit);
     4183            moveTrueTo(resultGPR);
     4184        }
     4185
     4186        done.link(&m_jit);
     4187        jsValueResult(resultGPR, node, DataFormatJSBoolean);
    41634188        break;
    41644189    }
     
    41664191    case InstanceOf: {
    41674192        compileInstanceOf(node);
     4193        break;
     4194    }
     4195
     4196    case InstanceOfCustom: {
     4197        compileInstanceOfCustom(node);
    41684198        break;
    41694199    }
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r193766 r193974  
    175175    case IsObjectOrNull:
    176176    case IsFunction:
    177     case CheckHasInstance:
     177    case CheckTypeInfoFlags:
     178    case OverridesHasInstance:
    178179    case InstanceOf:
     180    case InstanceOfCustom:
    179181    case DoubleRep:
    180182    case ValueRep:
  • trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h

    r192671 r193974  
    129129    macro(Z_JITOperation_EC, functionType(int32, intPtr, intPtr)) \
    130130    macro(Z_JITOperation_EGC, functionType(int32, intPtr, intPtr, intPtr)) \
     131    macro(Z_JITOperation_EJOJ, functionType(int32, intPtr, int64, intPtr, int64)) \
    131132    macro(Z_JITOperation_EJZ, functionType(int32, intPtr, int64, int32)) \
    132133    macro(Z_JITOperation_ESJss, functionType(int32, intPtr, intPtr, int64)) \
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r193955 r193974  
    942942            compileTypeOf();
    943943            break;
    944         case CheckHasInstance:
    945             compileCheckHasInstance();
     944        case CheckTypeInfoFlags:
     945            compileCheckTypeInfoFlags();
     946            break;
     947        case OverridesHasInstance:
     948            compileOverridesHasInstance();
    946949            break;
    947950        case InstanceOf:
    948951            compileInstanceOf();
     952            break;
     953        case InstanceOfCustom:
     954            compileInstanceOfCustom();
    949955            break;
    950956        case CountExecution:
     
    57165722    }
    57175723
    5718     void compileCheckHasInstance()
     5724    void compileOverridesHasInstance()
     5725    {
     5726        JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(m_node->cellOperand()->value());
     5727
     5728        LValue constructor = lowCell(m_node->child1());
     5729        LValue hasInstance = lowJSValue(m_node->child2());
     5730
     5731        LBasicBlock defaultHasInstance = FTL_NEW_BLOCK(m_out, ("OverridesHasInstance Symbol.hasInstance is default"));
     5732        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("OverridesHasInstance continuation"));
     5733
     5734        // Unlike in the DFG, we don't worry about cleaning this code up for the case where we have proven the hasInstanceValue is a constant as LLVM should fix it for us.
     5735
     5736        ASSERT(!m_node->child2().node()->isCellConstant() || defaultHasInstanceFunction == m_node->child2().node()->asCell());
     5737
     5738        ValueFromBlock notDefaultHasInstanceResult = m_out.anchor(m_out.booleanTrue);
     5739        m_out.branch(m_out.notEqual(hasInstance, m_out.constIntPtr(defaultHasInstanceFunction)), unsure(continuation), unsure(defaultHasInstance));
     5740
     5741        LBasicBlock lastNext = m_out.appendTo(defaultHasInstance, continuation);
     5742        ValueFromBlock implementsDefaultHasInstanceResult = m_out.anchor(m_out.testIsZero32(
     5743            m_out.load8ZeroExt32(constructor, m_heaps.JSCell_typeInfoFlags),
     5744            m_out.constInt32(ImplementsDefaultHasInstance)));
     5745        m_out.jump(continuation);
     5746
     5747        m_out.appendTo(continuation, lastNext);
     5748        setBoolean(m_out.phi(m_out.boolean, implementsDefaultHasInstanceResult, notDefaultHasInstanceResult));
     5749    }
     5750
     5751    void compileCheckTypeInfoFlags()
    57195752    {
    57205753        speculate(
    5721             Uncountable, noValue(), 0,
     5754            BadTypeInfoFlags, noValue(), 0,
    57225755            m_out.testIsZero32(
    57235756                m_out.load8ZeroExt32(lowCell(m_node->child1()), m_heaps.JSCell_typeInfoFlags),
    5724                 m_out.constInt32(ImplementsDefaultHasInstance)));
     5757                m_out.constInt32(m_node->typeInfoOperand())));
    57255758    }
    57265759   
     
    57745807        setBoolean(
    57755808            m_out.phi(m_out.boolean, notCellResult, isInstanceResult, notInstanceResult));
     5809    }
     5810
     5811    void compileInstanceOfCustom()
     5812    {
     5813        LValue value = lowJSValue(m_node->child1());
     5814        LValue constructor = lowCell(m_node->child2());
     5815        LValue hasInstance = lowJSValue(m_node->child3());
     5816
     5817        setBoolean(m_out.bitNot(m_out.equal(m_out.constInt32(0), vmCall(m_out.int32, m_out.operation(operationInstanceOfCustom), m_callFrame, value, constructor, hasInstance))));
    57765818    }
    57775819   
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r193766 r193974  
    229229        DEFINE_OP(op_get_by_id)
    230230        DEFINE_OP(op_get_by_val)
    231         DEFINE_OP(op_check_has_instance)
     231        DEFINE_OP(op_overrides_has_instance)
    232232        DEFINE_OP(op_instanceof)
     233        DEFINE_OP(op_instanceof_custom)
    233234        DEFINE_OP(op_is_undefined)
    234235        DEFINE_OP(op_is_boolean)
     
    400401        DEFINE_SLOWCASE_OP(op_get_by_id)
    401402        DEFINE_SLOWCASE_OP(op_get_by_val)
    402         DEFINE_SLOWCASE_OP(op_check_has_instance)
    403403        DEFINE_SLOWCASE_OP(op_instanceof)
     404        DEFINE_SLOWCASE_OP(op_instanceof_custom)
    404405        DEFINE_SLOWCASE_OP(op_jfalse)
    405406        DEFINE_SLOWCASE_OP(op_jless)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r193788 r193974  
    510510        void emit_op_get_argument_by_val(Instruction*);
    511511        void emit_op_init_lazy_reg(Instruction*);
    512         void emit_op_check_has_instance(Instruction*);
     512        void emit_op_overrides_has_instance(Instruction*);
    513513        void emit_op_instanceof(Instruction*);
     514        void emit_op_instanceof_custom(Instruction*);
    514515        void emit_op_is_undefined(Instruction*);
    515516        void emit_op_is_boolean(Instruction*);
     
    617618        void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
    618619        void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
    619         void emitSlow_op_check_has_instance(Instruction*, Vector<SlowCaseEntry>::iterator&);
    620620        void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
     621        void emitSlow_op_instanceof_custom(Instruction*, Vector<SlowCaseEntry>::iterator&);
    621622        void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
    622623        void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&);
     
    745746        MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*);
    746747        MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*);
     748        MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg);
    747749        MacroAssembler::Call callOperation(C_JITOperation_EJsc, GPRReg);
    748750        MacroAssembler::Call callOperation(J_JITOperation_EJscC, int, GPRReg, JSCell*);
     
    812814        MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, GPRReg, const Identifier*);
    813815        MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg, GPRReg, GPRReg);
     816        MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg, GPRReg, GPRReg);
    814817        MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, GPRReg, GPRReg, ArrayProfile*);
    815818        MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, GPRReg, GPRReg, ByValInfo*);
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r192836 r193974  
    504504}
    505505
     506ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJOJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     507{
     508    setupArgumentsWithExecState(arg1, arg2, arg3);
     509    return appendCallWithExceptionCheck(operation);
     510}
     511
    506512ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(V_JITOperation_EJ operation, GPRReg arg1)
    507513{
     
    595601    updateTopCallFrame();
    596602    return appendCall(operation);
     603}
     604
     605ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJOJ operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
     606{
     607    setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
     608    return appendCallWithExceptionCheck(operation);
    597609}
    598610
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r193766 r193974  
    106106}
    107107
    108 void JIT::emit_op_check_has_instance(Instruction* currentInstruction)
    109 {
    110     int baseVal = currentInstruction[3].u.operand;
    111 
    112     emitGetVirtualRegister(baseVal, regT0);
    113 
    114     // Check that baseVal is a cell.
    115     emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
    116 
    117     // Check that baseVal 'ImplementsHasInstance'.
    118     addSlowCase(branchTest8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance)));
     108void JIT::emit_op_overrides_has_instance(Instruction* currentInstruction)
     109{
     110    int dst = currentInstruction[1].u.operand;
     111    int constructor = currentInstruction[2].u.operand;
     112    int hasInstanceValue = currentInstruction[3].u.operand;
     113
     114    emitGetVirtualRegister(hasInstanceValue, regT0);
     115
     116    // We don't jump if we know what Symbol.hasInstance would do.
     117    Jump customhasInstanceValue = branchPtr(NotEqual, regT0, TrustedImmPtr(m_codeBlock->globalObject()->functionProtoHasInstanceSymbolFunction()));
     118
     119    emitGetVirtualRegister(constructor, regT0);
     120
     121    // Check that constructor 'ImplementsHasInstance' i.e. the object is a C-API user or a bound function.
     122    test8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance), regT0);
     123    emitTagBool(regT0);
     124    Jump done = jump();
     125
     126    customhasInstanceValue.link(this);
     127    move(TrustedImm32(ValueTrue), regT0);
     128
     129    done.link(this);
     130    emitPutVirtualRegister(dst);
    119131}
    120132
     
    130142    emitGetVirtualRegister(proto, regT1);
    131143
    132     // Check that proto are cells.  baseVal must be a cell - this is checked by op_check_has_instance.
     144    // Check that proto are cells. baseVal must be a cell - this is checked by the get_by_id for Symbol.hasInstance.
    133145    emitJumpSlowCaseIfNotJSCell(regT2, value);
    134146    emitJumpSlowCaseIfNotJSCell(regT1, proto);
     
    156168    isInstance.link(this);
    157169    emitPutVirtualRegister(dst);
     170}
     171
     172void JIT::emit_op_instanceof_custom(Instruction*)
     173{
     174    // This always goes to slow path since we expect it to be rare.
     175    addSlowCase(jump());
    158176}
    159177
     
    830848}
    831849
    832 void JIT::emitSlow_op_check_has_instance(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    833 {
    834     int dst = currentInstruction[1].u.operand;
    835     int value = currentInstruction[2].u.operand;
    836     int baseVal = currentInstruction[3].u.operand;
    837 
    838     linkSlowCaseIfNotJSCell(iter, baseVal);
    839     linkSlowCase(iter);
    840     emitGetVirtualRegister(value, regT0);
    841     emitGetVirtualRegister(baseVal, regT1);
    842     callOperation(operationCheckHasInstance, dst, regT0, regT1);
    843 
    844     emitJumpSlowToHot(jump(), currentInstruction[4].u.operand);
    845 }
    846 
    847850void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    848851{
     
    857860    emitGetVirtualRegister(proto, regT1);
    858861    callOperation(operationInstanceOf, dst, regT0, regT1);
     862}
     863
     864void JIT::emitSlow_op_instanceof_custom(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     865{
     866    int dst = currentInstruction[1].u.operand;
     867    int value = currentInstruction[2].u.operand;
     868    int constructor = currentInstruction[3].u.operand;
     869    int hasInstanceValue = currentInstruction[4].u.operand;
     870
     871    linkSlowCase(iter);
     872    emitGetVirtualRegister(value, regT0);
     873    emitGetVirtualRegister(constructor, regT1);
     874    emitGetVirtualRegister(hasInstanceValue, regT2);
     875    callOperation(operationInstanceOfCustom, regT0, regT1, regT2);
     876    emitTagBool(returnValueGPR);
     877    emitPutVirtualRegister(dst, returnValueGPR);
    859878}
    860879
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r193766 r193974  
    184184}
    185185
    186 void JIT::emit_op_check_has_instance(Instruction* currentInstruction)
    187 {
    188     int baseVal = currentInstruction[3].u.operand;
    189 
    190     emitLoadPayload(baseVal, regT0);
    191 
    192     // Check that baseVal is a cell.
    193     emitJumpSlowCaseIfNotJSCell(baseVal);
    194    
    195     // Check that baseVal 'ImplementsHasInstance'.
    196     addSlowCase(branchTest8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance)));
     186void JIT::emit_op_overrides_has_instance(Instruction* currentInstruction)
     187{
     188    int dst = currentInstruction[1].u.operand;
     189    int constructor = currentInstruction[2].u.operand;
     190    int hasInstanceValue = currentInstruction[3].u.operand;
     191
     192    emitLoadPayload(hasInstanceValue, regT0);
     193    // We don't jump if we know what Symbol.hasInstance would do.
     194    Jump hasInstanceValueNotCell = emitJumpIfNotJSCell(hasInstanceValue);
     195    Jump customhasInstanceValue = branchPtr(NotEqual, regT0, TrustedImmPtr(m_codeBlock->globalObject()->functionProtoHasInstanceSymbolFunction()));
     196
     197    // We know that constructor is an object from the way bytecode is emitted for instanceof expressions.
     198    emitLoadPayload(constructor, regT0);
     199
     200    // Check that constructor 'ImplementsHasInstance' i.e. the object is a C-API user or a bound function.
     201    test8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance), regT0);
     202    Jump done = jump();
     203
     204    hasInstanceValueNotCell.link(this);
     205    customhasInstanceValue.link(this);
     206    move(TrustedImm32(1), regT0);
     207
     208    done.link(this);
     209    emitStoreBool(dst, regT0);
     210
    197211}
    198212
     
    208222    emitLoadPayload(proto, regT1);
    209223
    210     // Check that proto are cells.  baseVal must be a cell - this is checked by op_check_has_instance.
     224    // Check that proto are cells. baseVal must be a cell - this is checked by the get_by_id for Symbol.hasInstance.
    211225    emitJumpSlowCaseIfNotJSCell(value);
    212226    emitJumpSlowCaseIfNotJSCell(proto);
     
    236250}
    237251
    238 void JIT::emitSlow_op_check_has_instance(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    239 {
    240     int dst = currentInstruction[1].u.operand;
    241     int value = currentInstruction[2].u.operand;
    242     int baseVal = currentInstruction[3].u.operand;
    243 
    244     linkSlowCaseIfNotJSCell(iter, baseVal);
    245     linkSlowCase(iter);
    246 
    247     emitLoad(value, regT1, regT0);
    248     emitLoad(baseVal, regT3, regT2);
    249     callOperation(operationCheckHasInstance, dst, regT1, regT0, regT3, regT2);
    250 
    251     emitJumpSlowToHot(jump(), currentInstruction[4].u.operand);
     252void JIT::emit_op_instanceof_custom(Instruction*)
     253{
     254    // This always goes to slow path since we expect it to be rare.
     255    addSlowCase(jump());
    252256}
    253257
     
    265269    emitLoad(proto, regT3, regT2);
    266270    callOperation(operationInstanceOf, dst, regT1, regT0, regT3, regT2);
     271}
     272
     273void JIT::emitSlow_op_instanceof_custom(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     274{
     275    int dst = currentInstruction[1].u.operand;
     276    int value = currentInstruction[2].u.operand;
     277    int constructor = currentInstruction[3].u.operand;
     278    int hasInstanceValue = currentInstruction[4].u.operand;
     279
     280    linkSlowCase(iter);
     281
     282    emitLoad(value, regT1, regT0);
     283    emitLoadPayload(constructor, regT2);
     284    emitLoad(hasInstanceValue, regT4, regT3);
     285    callOperation(operationInstanceOfCustom, regT1, regT0, regT2, regT4, regT3);
     286    emitStoreBool(dst, returnValueGPR);
    267287}
    268288
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r192937 r193974  
    14881488}
    14891489
    1490 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBaseVal)
     1490int32_t JIT_OPERATION operationInstanceOfCustom(ExecState* exec, EncodedJSValue encodedValue, JSObject* constructor, EncodedJSValue encodedHasInstance)
    14911491{
    14921492    VM& vm = exec->vm();
     
    14941494
    14951495    JSValue value = JSValue::decode(encodedValue);
    1496     JSValue baseVal = JSValue::decode(encodedBaseVal);
    1497 
    1498     if (baseVal.isObject()) {
    1499         JSObject* baseObject = asObject(baseVal);
    1500         ASSERT(!baseObject->structure(vm)->typeInfo().implementsDefaultHasInstance());
    1501         if (baseObject->structure(vm)->typeInfo().implementsHasInstance()) {
    1502             bool result = baseObject->methodTable(vm)->customHasInstance(baseObject, exec, value);
    1503             return JSValue::encode(jsBoolean(result));
    1504         }
    1505     }
    1506 
    1507     vm.throwException(exec, createInvalidInstanceofParameterError(exec, baseVal));
    1508     return JSValue::encode(JSValue());
     1496    JSValue hasInstanceValue = JSValue::decode(encodedHasInstance);
     1497
     1498    ASSERT(hasInstanceValue != exec->lexicalGlobalObject()->functionProtoHasInstanceSymbolFunction() || !constructor->structure()->typeInfo().implementsDefaultHasInstance());
     1499
     1500    if (constructor->hasInstance(exec, value, hasInstanceValue))
     1501        return 1;
     1502    return 0;
    15091503}
    15101504
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r192937 r193974  
    176176typedef int32_t JIT_OPERATION (*Z_JITOperation_ESJss)(ExecState*, size_t, JSString*);
    177177typedef int32_t JIT_OPERATION (*Z_JITOperation_EJ)(ExecState*, EncodedJSValue);
     178typedef int32_t JIT_OPERATION (*Z_JITOperation_EJOJ)(ExecState*, EncodedJSValue, JSObject*, EncodedJSValue);
    178179typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
    179180typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
     
    329330void JIT_OPERATION operationProfileDidCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
    330331void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
    331 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState*, EncodedJSValue, EncodedJSValue baseVal) WTF_INTERNAL;
    332332EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
    333333EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
     
    358358
    359359int32_t JIT_OPERATION operationCheckIfExceptionIsUncatchableAndNotifyProfiler(ExecState*);
     360int32_t JIT_OPERATION operationInstanceOfCustom(ExecState*, EncodedJSValue encodedValue, JSObject* constructor, EncodedJSValue encodedHasInstance) WTF_INTERNAL;
    360361
    361362EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r190916 r193974  
    3535#include "Opcode.h"
    3636#include "PropertyOffset.h"
     37#include "WriteBarrier.h"
    3738
    3839namespace JSC { namespace LLInt {
     
    155156    ASSERT(ModuleCode == 3);
    156157
     158    ASSERT(!(reinterpret_cast<ptrdiff_t>((reinterpret_cast<WriteBarrier<JSCell>*>(0x4000)->slot())) - 0x4000));
    157159    static_assert(PutByIdPrimaryTypeMask == 0x6, "LLInt assumes PutByIdPrimaryTypeMask is == 0x6");
    158160    static_assert(PutByIdPrimaryTypeSecondary == 0x0, "LLInt assumes PutByIdPrimaryTypeSecondary is == 0x0");
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r193766 r193974  
    523523}
    524524
    525 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
    526 {
    527     LLINT_BEGIN();
    528    
    529     JSValue value = LLINT_OP_C(2).jsValue();
    530     JSValue baseVal = LLINT_OP_C(3).jsValue();
    531     if (baseVal.isObject()) {
    532         JSObject* baseObject = asObject(baseVal);
    533         ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
    534         if (baseObject->structure()->typeInfo().implementsHasInstance()) {
    535             JSValue result = jsBoolean(baseObject->methodTable()->customHasInstance(baseObject, exec, value));
    536             LLINT_RETURN_WITH_PC_ADJUSTMENT(result, pc[4].u.operand);
    537         }
    538     }
    539     LLINT_THROW(createInvalidInstanceofParameterError(exec, baseVal));
    540 }
    541 
    542525LLINT_SLOW_PATH_DECL(slow_path_instanceof)
    543526{
     
    547530    ASSERT(!value.isObject() || !proto.isObject());
    548531    LLINT_RETURN(jsBoolean(JSObject::defaultHasInstance(exec, value, proto)));
     532}
     533
     534LLINT_SLOW_PATH_DECL(slow_path_instanceof_custom)
     535{
     536    LLINT_BEGIN();
     537
     538    JSValue value = LLINT_OP_C(2).jsValue();
     539    JSValue constructor = LLINT_OP_C(3).jsValue();
     540    JSValue hasInstanceValue = LLINT_OP_C(4).jsValue();
     541
     542    ASSERT(constructor.isObject());
     543    ASSERT(hasInstanceValue != exec->lexicalGlobalObject()->functionProtoHasInstanceSymbolFunction() || !constructor.getObject()->structure()->typeInfo().implementsDefaultHasInstance());
     544
     545    JSValue result = jsBoolean(constructor.getObject()->hasInstance(exec, value, hasInstanceValue));
     546    LLINT_RETURN(result);
    549547}
    550548
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r192937 r193974  
    6868LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_array_buffer);
    6969LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_regexp);
    70 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_check_has_instance);
    7170LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof);
     71LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_instanceof_custom);
    7272LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id);
    7373LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r193766 r193974  
    11761176
    11771177
    1178 _llint_op_check_has_instance:
    1179     traceExecution()
    1180     loadi 12[PC], t1
    1181     loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow)
    1182     btbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, .opCheckHasInstanceSlow
    1183     dispatch(5)
    1184 
    1185 .opCheckHasInstanceSlow:
    1186     callSlowPath(_llint_slow_path_check_has_instance)
    1187     dispatch(0)
    1188 
     1178_llint_op_overrides_has_instance:
     1179    traceExecution()
     1180
     1181    loadisFromInstruction(1, t3)
     1182    storei BooleanTag, TagOffset[cfr, t3, 8]
     1183
     1184    # First check if hasInstanceValue is the one on Function.prototype[Symbol.hasInstance]
     1185    loadisFromInstruction(3, t0)
     1186    loadConstantOrVariablePayload(t0, CellTag, t2, .opOverrideshasInstanceValueNotCell)
     1187    loadConstantOrVariable(t0, t1, t2)
     1188    bineq t1, CellTag, .opOverrideshasInstanceValueNotCell
     1189
     1190    # We don't need hasInstanceValue's tag register anymore.
     1191    loadp CodeBlock[cfr], t1
     1192    loadp CodeBlock::m_globalObject[t1], t1
     1193    loadp JSGlobalObject::m_functionProtoHasInstanceSymbolFunction[t1], t1
     1194    bineq t1, t2, .opOverrideshasInstanceValueNotDefault
     1195
     1196    # We know the constructor is a cell.
     1197    loadisFromInstruction(2, t0)
     1198    loadConstantOrVariablePayloadUnchecked(t0, t1)
     1199    tbz JSCell::m_flags[t1], ImplementsDefaultHasInstance, t0
     1200    storei t0, PayloadOffset[cfr, t3, 8]
     1201    dispatch(4)
     1202
     1203.opOverrideshasInstanceValueNotCell:
     1204.opOverrideshasInstanceValueNotDefault:
     1205    storei 1, PayloadOffset[cfr, t3, 8]
     1206    dispatch(4)
    11891207
    11901208_llint_op_instanceof:
     
    12151233    callSlowPath(_llint_slow_path_instanceof)
    12161234    dispatch(4)
     1235
     1236_llint_op_instanceof_custom:
     1237    traceExecution()
     1238    callSlowPath(_llint_slow_path_instanceof_custom)
     1239    dispatch(5)
    12171240
    12181241
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r193766 r193974  
    10701070
    10711071
    1072 _llint_op_check_has_instance:
    1073     traceExecution()
     1072_llint_op_overrides_has_instance:
     1073    traceExecution()
     1074    loadisFromInstruction(1, t3)
     1075
    10741076    loadisFromInstruction(3, t1)
    1075     loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
    1076     btbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, .opCheckHasInstanceSlow
    1077     dispatch(5)
    1078 
    1079 .opCheckHasInstanceSlow:
    1080     callSlowPath(_llint_slow_path_check_has_instance)
    1081     dispatch(0)
     1077    loadConstantOrVariable(t1, t0)
     1078    loadp CodeBlock[cfr], t2
     1079    loadp CodeBlock::m_globalObject[t2], t2
     1080    loadp JSGlobalObject::m_functionProtoHasInstanceSymbolFunction[t2], t2
     1081    bqneq t0, t2, .opOverridesHasInstanceNotDefaultSymbol
     1082
     1083    loadisFromInstruction(2, t1)
     1084    loadConstantOrVariable(t1, t0)
     1085    tbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, t1
     1086    orq ValueFalse, t1
     1087    storeq t1, [cfr, t3, 8]
     1088    dispatch(4)
     1089
     1090.opOverridesHasInstanceNotDefaultSymbol:
     1091    storeq ValueTrue, t1
     1092    storeq t1, [cfr, t3, 8]
     1093    dispatch(4)
    10821094
    10831095
     
    11101122    dispatch(4)
    11111123
     1124_llint_op_instanceof_custom:
     1125    traceExecution()
     1126    callSlowPath(_llint_slow_path_instanceof_custom)
     1127    dispatch(5)
    11121128
    11131129_llint_op_is_undefined:
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r193899 r193974  
    251251
    252252#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL_NOT_IMPLEMENTED_YET(macro)\
    253     macro(hasInstance) \
    254253    macro(isConcatSpreadable) \
    255254    macro(match) \
     
    261260
    262261#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
     262    macro(hasInstance) \
    263263    macro(iterator) \
    264264    macro(unscopables) \
     
    346346    macro(newTargetLocal) \
    347347    macro(derivedConstructor) \
     348    macro(isBoundFunction) \
     349    macro(hasInstanceBoundFunction) \
     350    macro(instanceOf) \
    348351
    349352
  • trunk/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp

    r189920 r193974  
    210210}
    211211
    212 static String invalidParameterInstanceofSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
     212inline String invalidParameterInstanceofSourceAppender(const String& content, const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
    213213{
    214214    if (occurrence == ErrorInstance::FoundApproximateSource)
     
    223223    static const unsigned instanceofLength = 10;
    224224    String rightHandSide = sourceText.substring(instanceofIndex + instanceofLength).simplifyWhiteSpace();
    225     return makeString(rightHandSide, " is not a function. (evaluating '", sourceText, "')");
     225    return makeString(rightHandSide, content, ". (evaluating '", sourceText, "')");
     226}
     227
     228static String invalidParameterInstanceofNotFunctionSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType runtimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
     229{
     230    return invalidParameterInstanceofSourceAppender(WTF::makeString(" is not a function"), originalMessage, sourceText, runtimeType, occurrence);
     231}
     232
     233static String invalidParameterInstanceofhasInstanceValueNotFunctionSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType runtimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
     234{
     235    return invalidParameterInstanceofSourceAppender(WTF::makeString("[Symbol.hasInstance] is not a function, undefined, or null"), originalMessage, sourceText, runtimeType, occurrence);
    226236}
    227237
     
    246256}
    247257
    248 JSObject* createInvalidInstanceofParameterError(ExecState* exec, JSValue value)
    249 {
    250     return createError(exec, value, makeString("is not a function."), invalidParameterInstanceofSourceAppender);
     258JSObject* createInvalidInstanceofParameterErrorNotFunction(ExecState* exec, JSValue value)
     259{
     260    return createError(exec, value, makeString(" is not a function"), invalidParameterInstanceofNotFunctionSourceAppender);
     261}
     262
     263JSObject* createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(ExecState* exec, JSValue value)
     264{
     265    return createError(exec, value, makeString("[Symbol.hasInstance] is not a function, undefined, or null"), invalidParameterInstanceofhasInstanceValueNotFunctionSourceAppender);
    251266}
    252267
  • trunk/Source/JavaScriptCore/runtime/ExceptionHelpers.h

    r186860 r193974  
    4646JSObject* createInvalidFunctionApplyParameterError(ExecState*, JSValue);
    4747JSObject* createInvalidInParameterError(ExecState*, JSValue);
    48 JSObject* createInvalidInstanceofParameterError(ExecState*, JSValue);
     48JSObject* createInvalidInstanceofParameterErrorNotFunction(ExecState*, JSValue);
     49JSObject* createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(ExecState*, JSValue);
    4950JSObject* createNotAConstructorError(ExecState*, JSValue);
    5051JSObject* createNotAFunctionError(ExecState*, JSValue);
  • trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp

    r190096 r193974  
    5454}
    5555
    56 void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction)
     56void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction, JSFunction** hasInstanceSymbolFunction)
    5757{
    5858    VM& vm = exec->vm();
     
    6363    *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), DontEnum);
    6464    *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), DontEnum);
     65    *hasInstanceSymbolFunction = putDirectBuiltinFunction(vm, globalObject, vm.propertyNames->hasInstanceSymbol, functionPrototypeSymbolHasInstanceCodeGenerator(vm), DontDelete | ReadOnly | DontEnum);
    6566
    6667    JSFunction* bindFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->bind.string(), functionProtoFuncBind);
  • trunk/Source/JavaScriptCore/runtime/FunctionPrototype.h

    r173269 r193974  
    3737    }
    3838
    39     void addFunctionProperties(ExecState*, JSGlobalObject*, JSFunction** callFunction, JSFunction** applyFunction);
     39    void addFunctionProperties(ExecState*, JSGlobalObject*, JSFunction** callFunction, JSFunction** applyFunction, JSFunction** hasInstanceSymbolFunction);
    4040
    4141    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
  • trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp

    r189561 r193974  
    7575}
    7676
     77EncodedJSValue JSC_HOST_CALL isBoundFunction(ExecState* exec)
     78{
     79    return JSValue::encode(JSValue(static_cast<bool>(jsDynamicCast<JSBoundFunction*>(exec->uncheckedArgument(0)))));
     80}
     81
     82EncodedJSValue JSC_HOST_CALL hasInstanceBoundFunction(ExecState* exec)
     83{
     84    JSBoundFunction* boundObject = jsCast<JSBoundFunction*>(exec->uncheckedArgument(0));
     85    JSValue value = exec->uncheckedArgument(1);
     86
     87    return JSValue::encode(jsBoolean(boundObject->targetFunction()->hasInstance(exec, value)));
     88}
     89
     90
    7791JSBoundFunction* JSBoundFunction::create(VM& vm, JSGlobalObject* globalObject, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int length, const String& name)
    7892{
  • trunk/Source/JavaScriptCore/runtime/JSBoundFunction.h

    r182899 r193974  
    3333EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState*);
    3434EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState*);
     35EncodedJSValue JSC_HOST_CALL isBoundFunction(ExecState*);
     36EncodedJSValue JSC_HOST_CALL hasInstanceBoundFunction(ExecState*);
    3537
    3638class JSBoundFunction : public JSFunction {
    3739public:
    3840    typedef JSFunction Base;
    39     const static unsigned StructureFlags = OverridesHasInstance | Base::StructureFlags;
     41    const static unsigned StructureFlags = OverridesHasInstanceFlag | Base::StructureFlags;
    4042
    4143    static JSBoundFunction* create(VM&, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String&);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r193766 r193974  
    287287    JSFunction* callFunction = 0;
    288288    JSFunction* applyFunction = 0;
    289     m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction);
     289    JSFunction* hasInstanceSymbolFunction = 0;
     290    m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction, &hasInstanceSymbolFunction);
    290291    m_callFunction.set(vm, this, callFunction);
    291292    m_applyFunction.set(vm, this, applyFunction);
     
    293294    m_initializePromiseFunction.set(vm, this, JSFunction::createBuiltinFunction(vm, promiseOperationsInitializePromiseCodeGenerator(vm), this));
    294295    m_newPromiseCapabilityFunction.set(vm, this, JSFunction::createBuiltinFunction(vm, promiseOperationsNewPromiseCapabilityCodeGenerator(vm), this));
     296    m_functionProtoHasInstanceSymbolFunction.set(vm, this, hasInstanceSymbolFunction);
    295297    m_nullGetterFunction.set(vm, this, NullGetterFunction::create(vm, NullGetterFunction::createStructure(vm, this, m_functionPrototype.get())));
    296298    m_nullSetterFunction.set(vm, this, NullSetterFunction::create(vm, NullSetterFunction::createStructure(vm, this, m_functionPrototype.get())));
     
    522524    JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength);
    523525    JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
     526    JSFunction* privateFuncIsBoundFunction = JSFunction::create(vm, this, 0, String(), isBoundFunction);
     527    JSFunction* privateFuncHasInstanceBoundFunction = JSFunction::create(vm, this, 0, String(), hasInstanceBoundFunction);
     528    JSFunction* privateFuncInstanceOf = JSFunction::create(vm, this, 0, String(), objectPrivateFuncInstanceOf);
    524529
    525530    GlobalPropertyInfo staticGlobals[] = {
     
    536541        GlobalPropertyInfo(vm.propertyNames->typedArrayLengthPrivateName, privateFuncTypedArrayLength, DontEnum | DontDelete | ReadOnly),
    537542        GlobalPropertyInfo(vm.propertyNames->typedArraySortPrivateName, privateFuncTypedArraySort, DontEnum | DontDelete | ReadOnly),
     543        GlobalPropertyInfo(vm.propertyNames->isBoundFunctionPrivateName, privateFuncIsBoundFunction, DontEnum | DontDelete | ReadOnly),
     544        GlobalPropertyInfo(vm.propertyNames->hasInstanceBoundFunctionPrivateName, privateFuncHasInstanceBoundFunction, DontEnum | DontDelete | ReadOnly),
     545        GlobalPropertyInfo(vm.propertyNames->instanceOfPrivateName, privateFuncInstanceOf, DontEnum | DontDelete | ReadOnly),
    538546        GlobalPropertyInfo(vm.propertyNames->BuiltinLogPrivateName, builtinLog, DontEnum | DontDelete | ReadOnly),
    539547        GlobalPropertyInfo(vm.propertyNames->ArrayPrivateName, arrayConstructor, DontEnum | DontDelete | ReadOnly),
     
    833841    visitor.append(&thisObject->m_initializePromiseFunction);
    834842    visitor.append(&thisObject->m_newPromiseCapabilityFunction);
     843    visitor.append(&thisObject->m_functionProtoHasInstanceSymbolFunction);
    835844    visitor.append(&thisObject->m_throwTypeErrorGetterSetter);
    836845    visitor.append(&thisObject->m_moduleLoader);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r193766 r193974  
    223223    WriteBarrier<JSFunction> m_initializePromiseFunction;
    224224    WriteBarrier<JSFunction> m_newPromiseCapabilityFunction;
     225    WriteBarrier<JSFunction> m_functionProtoHasInstanceSymbolFunction;
    225226    WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
    226227
     
    439440    JSFunction* initializePromiseFunction() const { return m_initializePromiseFunction.get(); }
    440441    JSFunction* newPromiseCapabilityFunction() const { return m_newPromiseCapabilityFunction.get(); }
     442    JSFunction* functionProtoHasInstanceSymbolFunction() const { return m_functionProtoHasInstanceSymbolFunction.get(); }
    441443    GetterSetter* throwTypeErrorGetterSetter(VM& vm)
    442444    {
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r192858 r193974  
    14581458}
    14591459
    1460 bool JSObject::hasInstance(ExecState* exec, JSValue value)
     1460bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue hasInstanceValue)
    14611461{
    14621462    VM& vm = exec->vm();
     1463
     1464    if (!hasInstanceValue.isUndefinedOrNull() && hasInstanceValue != exec->lexicalGlobalObject()->functionProtoHasInstanceSymbolFunction()) {
     1465        CallData callData;
     1466        CallType callType = JSC::getCallData(hasInstanceValue, callData);
     1467        if (callType == CallTypeNone) {
     1468            vm.throwException(exec, createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(exec, this));
     1469            return false;
     1470        }
     1471
     1472        MarkedArgumentBuffer args;
     1473        args.append(value);
     1474        JSValue result = call(exec, hasInstanceValue, callType, callData, this, args);
     1475        return result.toBoolean(exec);
     1476    }
     1477
    14631478    TypeInfo info = structure(vm)->typeInfo();
    14641479    if (info.implementsDefaultHasInstance())
     
    14661481    if (info.implementsHasInstance())
    14671482        return methodTable(vm)->customHasInstance(this, exec, value);
    1468     vm.throwException(exec, createInvalidInstanceofParameterError(exec, this));
     1483    vm.throwException(exec, createInvalidInstanceofParameterErrorNotFunction(exec, this));
    14691484    return false;
     1485}
     1486
     1487bool JSObject::hasInstance(ExecState* exec, JSValue value)
     1488{
     1489    JSValue hasInstanceValue = get(exec, exec->propertyNames().hasInstanceSymbol);
     1490
     1491    return hasInstance(exec, value, hasInstanceValue);
    14701492}
    14711493
     
    14861508    }
    14871509    return false;
     1510}
     1511
     1512EncodedJSValue JSC_HOST_CALL objectPrivateFuncInstanceOf(ExecState* exec)
     1513{
     1514    JSValue value = exec->uncheckedArgument(0);
     1515    JSValue proto = exec->uncheckedArgument(1);
     1516
     1517    return JSValue::encode(jsBoolean(JSObject::defaultHasInstance(exec, value, proto)));
    14881518}
    14891519
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r191215 r193974  
    486486    JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
    487487
     488    JS_EXPORT_PRIVATE bool hasInstance(ExecState*, JSValue value, JSValue hasInstanceValue);
    488489    bool hasInstance(ExecState*, JSValue);
    489490    static bool defaultHasInstance(ExecState*, JSValue, JSValue prototypeProperty);
     
    974975    }
    975976};
     977
     978JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectPrivateFuncInstanceOf(ExecState*);
    976979
    977980inline JSFinalObject* JSFinalObject::create(
  • trunk/Source/JavaScriptCore/runtime/JSTypeInfo.h

    r192693 r193974  
    3939static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable.
    4040static const unsigned ImplementsHasInstance = 1 << 1;
    41 static const unsigned OverridesHasInstance = 1 << 2;
     41static const unsigned OverridesHasInstanceFlag = 1 << 2; // FIXME: This is only trivially used by the runtime and should be removed: https://bugs.webkit.org/show_bug.cgi?id=152005
    4242static const unsigned ImplementsDefaultHasInstance = 1 << 3;
    4343static const unsigned TypeOfShouldCallGetCallData = 1 << 4; // Need this flag if you override getCallData() and you want typeof to use this to determine if it should say "function". Currently we always set this flag when we override getCallData().
     
    6969    {
    7070        // No object that doesn't ImplementsHasInstance should override it!
    71         ASSERT((m_flags & (ImplementsHasInstance | OverridesHasInstance)) != OverridesHasInstance);
     71        ASSERT((m_flags & (ImplementsHasInstance | OverridesHasInstanceFlag)) != OverridesHasInstanceFlag);
    7272        // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
    73         if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
     73        if ((m_flags & (ImplementsHasInstance | OverridesHasInstanceFlag)) == ImplementsHasInstance)
    7474            m_flags |= ImplementsDefaultHasInstance;
    7575    }
     
    8484    bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); }
    8585    bool implementsHasInstance() const { return isSetOnFlags1(ImplementsHasInstance); }
    86     bool overridesHasInstance() const { return isSetOnFlags1(OverridesHasInstance); }
     86    bool overridesHasInstance() const { return isSetOnFlags1(OverridesHasInstanceFlag); }
    8787    bool implementsDefaultHasInstance() const { return isSetOnFlags1(ImplementsDefaultHasInstance); }
    8888    bool typeOfShouldCallGetCallData() const { return isSetOnFlags1(TypeOfShouldCallGetCallData); }
  • trunk/Source/JavaScriptCore/runtime/WriteBarrier.h

    r186860 r193974  
    153153    bool isCustomGetterSetter() const { return get().isCustomGetterSetter(); }
    154154   
    155     JSValue* slot()
     155    JSValue* slot() const
    156156    {
    157         union {
    158             EncodedJSValue* v;
    159             JSValue* slot;
    160         } u;
    161         u.v = &m_value;
    162         return u.slot;
     157        return bitwise_cast<JSValue*>(&m_value);
    163158    }
    164159   
  • trunk/Source/JavaScriptCore/tests/es6.yaml

    r193766 r193974  
    11841184  cmd: runES6 :fail
    11851185- path: es6/well-known_symbols_Symbol.hasInstance.js
    1186   cmd: runES6 :fail
     1186  cmd: runES6 :normal
    11871187- path: es6/well-known_symbols_Symbol.isConcatSpreadable.js
    11881188  cmd: runES6 :fail
Note: See TracChangeset for help on using the changeset viewer.