Changeset 194248 in webkit


Ignore:
Timestamp:
Dec 17, 2015 4:37:35 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:

Fixed version of r193986, r193983, and r193974.

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.

  • inspector/model/remote-object-get-properties-expected.txt:
  • 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
65 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r194246 r194248  
     12015-12-17  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        * inspector/model/remote-object-get-properties-expected.txt:
     15        * js/Object-getOwnPropertyNames-expected.txt:
     16        * js/exception-for-nonobject-expected.txt:
     17        * js/exception-instanceof-expected.txt:
     18        * js/instance-of-immediates-expected.txt:
     19        * js/regress/instanceof-bound-expected.txt: Added.
     20        * js/regress/instanceof-bound.html: Added.
     21        * js/regress/script-tests/instanceof-bound.js: Added.
     22        (Constructor):
     23        (test):
     24        * js/script-tests/Object-getOwnPropertyNames.js:
     25
    1262015-12-17  Simon Fraser  <simon.fraser@apple.com>
    227
  • trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt

    r194036 r194248  
    203203    bind
    204204    constructor
     205    Symbol(Symbol.hasInstance)
    205206    toLocaleString
    206207    valueOf
     
    252253    bind
    253254    constructor
     255    Symbol(Symbol.hasInstance)
    254256    toLocaleString
    255257    valueOf
  • trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    7474    case op_inc:
    7575    case op_resume: {
     76        ASSERT(opcodeLengths[opcodeID] >= 1);
    7677        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    7778        return;
     
    8687    case op_jless:
    8788    case op_copy_rest: {
     89        ASSERT(opcodeLengths[opcodeID] >= 2);
    8890        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    8991        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     
    9294    case op_put_by_val_direct:
    9395    case op_put_by_val: {
     96        ASSERT(opcodeLengths[opcodeID] >= 3);
    9497        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    9598        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     
    101104    case op_put_to_scope:
    102105    case op_put_to_arguments: {
     106        ASSERT(opcodeLengths[opcodeID] >= 3);
    103107        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    104108        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     
    107111    case op_put_getter_by_id:
    108112    case op_put_setter_by_id: {
     113        ASSERT(opcodeLengths[opcodeID] >= 4);
    109114        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    110115        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
     
    112117    }
    113118    case op_put_getter_setter_by_id: {
     119        ASSERT(opcodeLengths[opcodeID] >= 5);
    114120        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    115121        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
     
    119125    case op_put_getter_by_val:
    120126    case op_put_setter_by_val: {
     127        ASSERT(opcodeLengths[opcodeID] >= 4);
    121128        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    122129        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     
    160167    case op_create_scoped_arguments:
    161168    case op_get_from_arguments: {
     169        ASSERT(opcodeLengths[opcodeID] >= 2);
    162170        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    163171        return;
     
    169177    case op_get_by_val:
    170178    case op_in:
     179    case op_overrides_has_instance:
    171180    case op_instanceof:
    172     case op_check_has_instance:
    173181    case op_add:
    174182    case op_mul:
     
    192200    case op_push_with_scope:
    193201    case op_del_by_val: {
    194         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    195         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
    196         return;
    197     }
     202        ASSERT(opcodeLengths[opcodeID] > 3);
     203        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     204        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     205        return;
     206    }
     207    case op_instanceof_custom:
    198208    case op_has_structure_property:
    199209    case op_construct_varargs:
    200210    case op_call_varargs:
    201211    case op_tail_call_varargs: {
     212        ASSERT(opcodeLengths[opcodeID] > 4);
    202213        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    203214        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     
    206217    }
    207218    case op_get_direct_pname: {
     219        ASSERT(opcodeLengths[opcodeID] > 5);
    208220        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    209221        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     
    215227    case op_switch_char:
    216228    case op_switch_imm: {
     229        ASSERT(opcodeLengths[opcodeID] > 3);
    217230        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
    218231        return;
     
    351364    case op_get_by_id:
    352365    case op_get_array_length:
    353     case op_check_has_instance:
     366    case op_overrides_has_instance:
    354367    case op_instanceof:
     368    case op_instanceof_custom:
    355369    case op_get_by_val:
    356370    case op_typeof:
     
    403417    case op_get_from_arguments:
    404418    case op_get_rest_length: {
     419        ASSERT(opcodeLengths[opcodeID] > 1);
    405420        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    406421        return;
    407422    }
    408423    case op_catch: {
     424        ASSERT(opcodeLengths[opcodeID] > 2);
    409425        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    410426        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r194036 r194248  
    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

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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    16651665RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    16661666{
    1667     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    1668     RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
     1667    RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
     1668    RefPtr<RegisterID> isObject = generator.newTemporary();
     1669    RefPtr<RegisterID> isCustom = generator.newTemporary();
    16691670    RefPtr<RegisterID> prototype = generator.newTemporary();
    1670     RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
    1671     RefPtr<Label> target = generator.newLabel();
     1671    RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
     1672    RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
     1673    RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
     1674    RefPtr<Label> custom = generator.newLabel();
     1675    RefPtr<Label> done = generator.newLabel();
     1676    RefPtr<Label> typeError = generator.newLabel();
    16721677
    16731678    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1674     generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
     1679    generator.emitIsObject(isObject.get(), constructor.get());
     1680    generator.emitJumpIfFalse(isObject.get(), typeError.get());
    16751681
    16761682    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1677     generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
     1683    generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
    16781684
    16791685    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1680     RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
    1681     generator.emitLabel(target.get());
    1682     return result;
     1686    generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
     1687
     1688    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1689    generator.emitJumpIfTrue(isCustom.get(), custom.get());
     1690
     1691    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1692    generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
     1693
     1694    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1695    generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
     1696
     1697    generator.emitJump(done.get());
     1698
     1699    generator.emitLabel(typeError.get());
     1700    generator.emitThrowTypeError("Right hand side of instanceof is not an object");
     1701
     1702    generator.emitLabel(custom.get());
     1703
     1704    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1705    generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
     1706
     1707    generator.emitLabel(done.get());
     1708
     1709    return dstReg.get();
    16831710}
    16841711
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r194216 r194248  
    24662466        break;
    24672467           
    2468     case CheckHasInstance:
    2469         // Sadly, we don't propagate the fact that we've done CheckHasInstance
     2468    case OverridesHasInstance:
     2469        forNode(node).setType(SpecBoolean);
    24702470        break;
    24712471           
    24722472    case InstanceOf:
    2473         // Again, sadly, we don't propagate the fact that we've done InstanceOf
     2473        // Sadly, we don't propagate the fact that we've done InstanceOf
     2474        forNode(node).setType(SpecBoolean);
     2475        break;
     2476
     2477    case InstanceOfCustom:
     2478        clobberWorld(node->origin.semantic, clobberLimit);
    24742479        forNode(node).setType(SpecBoolean);
    24752480        break;
     
    25282533    case CheckTierUpInLoop:
    25292534    case CheckTierUpAtReturn:
     2535    case CheckTypeInfoFlags:
    25302536        break;
    25312537
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r194216 r194248  
    35063506        }
    35073507
    3508         case op_check_has_instance:
    3509             addToGraph(CheckHasInstance, get(VirtualRegister(currentInstruction[3].u.operand)));
    3510             NEXT_OPCODE(op_check_has_instance);
     3508        case op_overrides_has_instance: {
     3509            JSFunction* defaultHasInstanceSymbolFunction = m_inlineStackTop->m_codeBlock->globalObjectFor(currentCodeOrigin())->functionProtoHasInstanceSymbolFunction();
     3510
     3511            Node* constructor = get(VirtualRegister(currentInstruction[2].u.operand));
     3512            Node* hasInstanceValue = get(VirtualRegister(currentInstruction[3].u.operand));
     3513
     3514            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(OverridesHasInstance, OpInfo(m_graph.freeze(defaultHasInstanceSymbolFunction)), constructor, hasInstanceValue));
     3515            NEXT_OPCODE(op_overrides_has_instance);
     3516        }
    35113517
    35123518        case op_instanceof: {
     
    35163522            NEXT_OPCODE(op_instanceof);
    35173523        }
    3518            
     3524
     3525        case op_instanceof_custom: {
     3526            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
     3527            Node* constructor = get(VirtualRegister(currentInstruction[3].u.operand));
     3528            Node* hasInstanceValue = get(VirtualRegister(currentInstruction[4].u.operand));
     3529            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(InstanceOfCustom, value, constructor, hasInstanceValue));
     3530            NEXT_OPCODE(op_instanceof_custom);
     3531        }
     3532
    35193533        case op_is_undefined: {
    35203534            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r194216 r194248  
    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

    r194216 r194248  
    741741        return;
    742742
    743     case CheckHasInstance:
     743    case CheckTypeInfoFlags:
    744744        read(JSCell_typeInfoFlags);
    745         def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
     745        def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
     746        return;
     747
     748    case OverridesHasInstance:
     749        read(JSCell_typeInfoFlags);
     750        def(HeapLocation(OverridesHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
    746751        return;
    747752
     
    749754        read(JSCell_structureID);
    750755        def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), LazyNode(node));
     756        return;
     757
     758    case InstanceOfCustom:
     759        read(World);
     760        write(Heap);
    751761        return;
    752762
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r194216 r194248  
    143143    case ProfileType:
    144144    case ProfileControlFlow:
    145     case CheckHasInstance:
     145    case OverridesHasInstance:
    146146    case InstanceOf:
     147    case InstanceOfCustom:
    147148    case IsUndefined:
    148149    case IsBoolean:
     
    182183    case ConstantStoragePointer:
    183184    case Check:
     185    case CheckTypeInfoFlags:
    184186    case MultiGetByOffset:
    185187    case ValueRep:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r194216 r194248  
    11121112            break;
    11131113        }
     1114
     1115        case OverridesHasInstance: {
     1116            if (node->child2().node()->isCellConstant()) {
     1117                if (node->child2().node()->asCell() != m_graph.globalObjectFor(node->origin.semantic)->functionProtoHasInstanceSymbolFunction()) {
     1118
     1119                    m_graph.convertToConstant(node, jsBoolean(true));
     1120                    break;
     1121                }
     1122
     1123                if (!m_graph.hasExitSite(node->origin.semantic, BadTypeInfoFlags)) {
     1124                    // Here we optimistically assume that we will not see an bound/C-API function here.
     1125                    m_insertionSet.insertNode(m_indexInBlock, SpecNone, CheckTypeInfoFlags, node->origin, OpInfo(ImplementsDefaultHasInstance), Edge(node->child1().node(), CellUse));
     1126                    m_graph.convertToConstant(node, jsBoolean(false));
     1127                    break;
     1128                }
     1129            }
     1130
     1131            fixEdge<CellUse>(node->child1());
     1132            break;
     1133        }
    11141134           
    11151135        case CheckStructure:
    11161136        case CheckCell:
    1117         case CheckHasInstance:
    11181137        case CreateThis:
    11191138        case GetButterfly:
     
    11761195            break;
    11771196        }
    1178            
     1197
     1198        case InstanceOfCustom:
     1199            fixEdge<CellUse>(node->child2());
     1200            break;
     1201
    11791202        case In: {
    11801203            // FIXME: We should at some point have array profiling on op_in, in which
     
    14241447        case VarInjectionWatchpoint:
    14251448        case Call:
     1449        case CheckTypeInfoFlags:
    14261450        case TailCallInlinedCaller:
    14271451        case Construct:
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r194036 r194248  
    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

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

    r194216 r194248  
    13651365        switch (op()) {
    13661366        case CheckCell:
     1367        case OverridesHasInstance:
    13671368        case NewFunction:
    13681369        case NewArrowFunction:
     
    14251426        ASSERT(hasUidOperand());
    14261427        return reinterpret_cast<UniquedStringImpl*>(m_opInfo);
     1428    }
     1429
     1430    bool hasTypeInfoOperand()
     1431    {
     1432        return op() == CheckTypeInfoFlags;
     1433    }
     1434
     1435    unsigned typeInfoOperand()
     1436    {
     1437        ASSERT(hasTypeInfoOperand() && m_opInfo <= UCHAR_MAX);
     1438        return static_cast<unsigned>(m_opInfo);
    14271439    }
    14281440
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r194216 r194248  
    223223    macro(CheckInBounds, NodeMustGenerate) \
    224224    macro(CheckIdent, NodeMustGenerate) \
     225    macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\
    225226    \
    226227    /* Optimizations for array mutation. */\
     
    281282    macro(ProfileWillCall, NodeMustGenerate) \
    282283    macro(ProfileDidCall, NodeMustGenerate) \
    283     macro(CheckHasInstance, NodeMustGenerate) \
     284    macro(OverridesHasInstance, NodeMustGenerate | NodeResultBoolean) \
    284285    macro(InstanceOf, NodeResultBoolean) \
     286    macro(InstanceOfCustom, NodeMustGenerate | NodeResultBoolean) \
    285287    macro(IsUndefined, NodeResultBoolean) \
    286288    macro(IsBoolean, NodeResultBoolean) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r194216 r194248  
    409409        case CompareEq:
    410410        case CompareStrictEq:
     411        case OverridesHasInstance:
    411412        case InstanceOf:
     413        case InstanceOfCustom:
    412414        case IsUndefined:
    413415        case IsBoolean:
     
    576578        case GetLocalUnlinked:
    577579        case CheckArray:
     580        case CheckTypeInfoFlags:
    578581        case Arrayify:
    579582        case ArrayifyToStructure:
     
    688691        case ProfileType:
    689692        case ProfileControlFlow:
    690         case CheckHasInstance:
    691693        case ThrowReferenceError:
    692694        case ForceOSRExit:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r194216 r194248  
    243243    case ProfileType:
    244244    case ProfileControlFlow:
    245     case CheckHasInstance:
     245    case CheckTypeInfoFlags:
     246    case OverridesHasInstance:
    246247    case InstanceOf:
     248    case InstanceOfCustom:
    247249    case IsUndefined:
    248250    case IsBoolean:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r194216 r194248  
    27452745}
    27462746
     2747void SpeculativeJIT::compileCheckTypeInfoFlags(Node* node)
     2748{
     2749    SpeculateCellOperand base(this, node->child1());
     2750
     2751    GPRReg baseGPR = base.gpr();
     2752
     2753    speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
     2754
     2755    noResult(node);
     2756}
     2757
    27472758void SpeculativeJIT::compileInstanceOf(Node* node)
    27482759{
     
    31813192    jsValueResult(resultRegs, node);
    31823193    return;
     3194}
     3195
     3196void SpeculativeJIT::compileInstanceOfCustom(Node* node)
     3197{
     3198    // We could do something smarter here but this case is currently super rare and unless
     3199    // Symbol.hasInstance becomes popular will likely remain that way.
     3200
     3201    JSValueOperand value(this, node->child1());
     3202    SpeculateCellOperand constructor(this, node->child2());
     3203    JSValueOperand hasInstanceValue(this, node->child3());
     3204    GPRTemporary result(this);
     3205
     3206    JSValueRegs valueRegs = value.jsValueRegs();
     3207    GPRReg constructorGPR = constructor.gpr();
     3208    JSValueRegs hasInstanceRegs = hasInstanceValue.jsValueRegs();
     3209    GPRReg resultGPR = result.gpr();
     3210
     3211    MacroAssembler::Jump slowCase = m_jit.jump();
     3212
     3213    addSlowPathGenerator(slowPathCall(slowCase, this, operationInstanceOfCustom, resultGPR, valueRegs, constructorGPR, hasInstanceRegs));
     3214
     3215    unblessedBooleanResult(resultGPR, node);
    31833216}
    31843217
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r194113 r194248  
    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    {
     
    18361848        m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG SH4_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
    18371849        return appendCall(operation);
     1850    }
     1851
     1852    JITCompiler::Call callOperation(Z_JITOperation_EJOJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
     1853    {
     1854        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
     1855        return appendCallSetResult(operation, result);
     1856    }
     1857    JITCompiler::Call callOperation(Z_JITOperation_EJOJ operation, GPRReg result, JSValueRegs arg1, GPRReg arg2, JSValueRegs arg3)
     1858    {
     1859        return callOperation(operation, result, arg1.tagGPR(), arg1.payloadGPR(), arg2, arg3.tagGPR(), arg3.payloadGPR());
    18381860    }
    18391861
     
    22102232    void compileGetArrayLength(Node*);
    22112233
     2234    void compileCheckTypeInfoFlags(Node*);
    22122235    void compileCheckIdent(Node*);
    22132236   
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

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

    r194216 r194248  
    41544154    }
    41554155
    4156     case CheckHasInstance: {
     4156    case CheckTypeInfoFlags: {
     4157        compileCheckTypeInfoFlags(node);
     4158        break;
     4159    }
     4160
     4161    case OverridesHasInstance: {
     4162
     4163        Node* hasInstanceValueNode = node->child2().node();
     4164        JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
     4165
     4166        MacroAssembler::Jump notDefault;
    41574167        SpeculateCellOperand base(this, node->child1());
    4158         GPRTemporary structure(this);
    4159 
    4160         // Speculate that base 'ImplementsDefaultHasInstance'.
    4161         speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branchTest8(
    4162             MacroAssembler::Zero,
    4163             MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()),
    4164             MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
    4165 
    4166         noResult(node);
     4168        JSValueOperand hasInstanceValue(this, node->child2());
     4169        GPRTemporary result(this);
     4170
     4171        GPRReg resultGPR = result.gpr();
     4172
     4173        // If we have proven that the constructor's Symbol.hasInstance will always be the one on Function.prototype[Symbol.hasInstance]
     4174        // 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
     4175        // but is not the default one as fixup should have converted this check to true.
     4176        ASSERT(!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction == hasInstanceValueNode->asCell());
     4177        if (!hasInstanceValueNode->isCellConstant())
     4178            notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValue.gpr(), TrustedImmPtr(defaultHasInstanceFunction));
     4179
     4180        // Check that base 'ImplementsDefaultHasInstance'.
     4181        m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
     4182        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
     4183        MacroAssembler::Jump done = m_jit.jump();
     4184
     4185        if (notDefault.isSet()) {
     4186            notDefault.link(&m_jit);
     4187            moveTrueTo(resultGPR);
     4188        }
     4189
     4190        done.link(&m_jit);
     4191        jsValueResult(resultGPR, node, DataFormatJSBoolean);
    41674192        break;
    41684193    }
     
    41704195    case InstanceOf: {
    41714196        compileInstanceOf(node);
     4197        break;
     4198    }
     4199
     4200    case InstanceOfCustom: {
     4201        compileInstanceOfCustom(node);
    41724202        break;
    41734203    }
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r194216 r194248  
    177177    case IsObjectOrNull:
    178178    case IsFunction:
    179     case CheckHasInstance:
     179    case CheckTypeInfoFlags:
     180    case OverridesHasInstance:
    180181    case InstanceOf:
     182    case InstanceOfCustom:
    181183    case DoubleRep:
    182184    case ValueRep:
  • trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h

    r194036 r194248  
    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

    r194216 r194248  
    949949            compileTypeOf();
    950950            break;
    951         case CheckHasInstance:
    952             compileCheckHasInstance();
     951        case CheckTypeInfoFlags:
     952            compileCheckTypeInfoFlags();
     953            break;
     954        case OverridesHasInstance:
     955            compileOverridesHasInstance();
    953956            break;
    954957        case InstanceOf:
    955958            compileInstanceOf();
     959            break;
     960        case InstanceOfCustom:
     961            compileInstanceOfCustom();
    956962            break;
    957963        case CountExecution:
     
    57465752    }
    57475753
    5748     void compileCheckHasInstance()
     5754    void compileOverridesHasInstance()
     5755    {
     5756        JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(m_node->cellOperand()->value());
     5757
     5758        LValue constructor = lowCell(m_node->child1());
     5759        LValue hasInstance = lowJSValue(m_node->child2());
     5760
     5761        LBasicBlock defaultHasInstance = FTL_NEW_BLOCK(m_out, ("OverridesHasInstance Symbol.hasInstance is default"));
     5762        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("OverridesHasInstance continuation"));
     5763
     5764        // 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.
     5765
     5766        ASSERT(!m_node->child2().node()->isCellConstant() || defaultHasInstanceFunction == m_node->child2().node()->asCell());
     5767
     5768        ValueFromBlock notDefaultHasInstanceResult = m_out.anchor(m_out.booleanTrue);
     5769        m_out.branch(m_out.notEqual(hasInstance, m_out.constIntPtr(defaultHasInstanceFunction)), unsure(continuation), unsure(defaultHasInstance));
     5770
     5771        LBasicBlock lastNext = m_out.appendTo(defaultHasInstance, continuation);
     5772        ValueFromBlock implementsDefaultHasInstanceResult = m_out.anchor(m_out.testIsZero32(
     5773            m_out.load8ZeroExt32(constructor, m_heaps.JSCell_typeInfoFlags),
     5774            m_out.constInt32(ImplementsDefaultHasInstance)));
     5775        m_out.jump(continuation);
     5776
     5777        m_out.appendTo(continuation, lastNext);
     5778        setBoolean(m_out.phi(m_out.boolean, implementsDefaultHasInstanceResult, notDefaultHasInstanceResult));
     5779    }
     5780
     5781    void compileCheckTypeInfoFlags()
    57495782    {
    57505783        speculate(
    5751             Uncountable, noValue(), 0,
     5784            BadTypeInfoFlags, noValue(), 0,
    57525785            m_out.testIsZero32(
    57535786                m_out.load8ZeroExt32(lowCell(m_node->child1()), m_heaps.JSCell_typeInfoFlags),
    5754                 m_out.constInt32(ImplementsDefaultHasInstance)));
     5787                m_out.constInt32(m_node->typeInfoOperand())));
    57555788    }
    57565789   
     
    58045837        setBoolean(
    58055838            m_out.phi(m_out.boolean, notCellResult, isInstanceResult, notInstanceResult));
     5839    }
     5840
     5841    void compileInstanceOfCustom()
     5842    {
     5843        LValue value = lowJSValue(m_node->child1());
     5844        LValue constructor = lowCell(m_node->child2());
     5845        LValue hasInstance = lowJSValue(m_node->child3());
     5846
     5847        setBoolean(m_out.bitNot(m_out.equal(m_out.constInt32(0), vmCall(m_out.int32, m_out.operation(operationInstanceOfCustom), m_callFrame, value, constructor, hasInstance))));
    58065848    }
    58075849   
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194175 r194248  
    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

    r194087 r194248  
    177177typedef int32_t JIT_OPERATION (*Z_JITOperation_ESJss)(ExecState*, size_t, JSString*);
    178178typedef int32_t JIT_OPERATION (*Z_JITOperation_EJ)(ExecState*, EncodedJSValue);
     179typedef int32_t JIT_OPERATION (*Z_JITOperation_EJOJ)(ExecState*, EncodedJSValue, JSObject*, EncodedJSValue);
    179180typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
    180181typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
     
    330331void JIT_OPERATION operationProfileDidCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
    331332void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
    332 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState*, EncodedJSValue, EncodedJSValue baseVal) WTF_INTERNAL;
    333333EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
    334334EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
     
    359359
    360360int32_t JIT_OPERATION operationCheckIfExceptionIsUncatchableAndNotifyProfiler(ExecState*);
     361int32_t JIT_OPERATION operationInstanceOfCustom(ExecState*, EncodedJSValue encodedValue, JSObject* constructor, EncodedJSValue encodedHasInstance) WTF_INTERNAL;
    361362
    362363EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r194036 r194248  
    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

    r194175 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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, [cfr, t3, 8]
     1092    dispatch(4)
    10821093
    10831094
     
    11101121    dispatch(4)
    11111122
     1123_llint_op_instanceof_custom:
     1124    traceExecution()
     1125    callSlowPath(_llint_slow_path_instanceof_custom)
     1126    dispatch(5)
    11121127
    11131128_llint_op_is_undefined:
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194242 r194248  
    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),
     
    841849    visitor.append(&thisObject->m_initializePromiseFunction);
    842850    visitor.append(&thisObject->m_newPromiseCapabilityFunction);
     851    visitor.append(&thisObject->m_functionProtoHasInstanceSymbolFunction);
    843852    visitor.append(&thisObject->m_throwTypeErrorGetterSetter);
    844853    visitor.append(&thisObject->m_moduleLoader);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r194242 r194248  
    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

    r194175 r194248  
    14381438}
    14391439
    1440 bool JSObject::hasInstance(ExecState* exec, JSValue value)
     1440bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue hasInstanceValue)
    14411441{
    14421442    VM& vm = exec->vm();
     1443
     1444    if (!hasInstanceValue.isUndefinedOrNull() && hasInstanceValue != exec->lexicalGlobalObject()->functionProtoHasInstanceSymbolFunction()) {
     1445        CallData callData;
     1446        CallType callType = JSC::getCallData(hasInstanceValue, callData);
     1447        if (callType == CallTypeNone) {
     1448            vm.throwException(exec, createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(exec, this));
     1449            return false;
     1450        }
     1451
     1452        MarkedArgumentBuffer args;
     1453        args.append(value);
     1454        JSValue result = call(exec, hasInstanceValue, callType, callData, this, args);
     1455        return result.toBoolean(exec);
     1456    }
     1457
    14431458    TypeInfo info = structure(vm)->typeInfo();
    14441459    if (info.implementsDefaultHasInstance())
     
    14461461    if (info.implementsHasInstance())
    14471462        return methodTable(vm)->customHasInstance(this, exec, value);
    1448     vm.throwException(exec, createInvalidInstanceofParameterError(exec, this));
     1463    vm.throwException(exec, createInvalidInstanceofParameterErrorNotFunction(exec, this));
    14491464    return false;
     1465}
     1466
     1467bool JSObject::hasInstance(ExecState* exec, JSValue value)
     1468{
     1469    JSValue hasInstanceValue = get(exec, exec->propertyNames().hasInstanceSymbol);
     1470
     1471    return hasInstance(exec, value, hasInstanceValue);
    14501472}
    14511473
     
    14661488    }
    14671489    return false;
     1490}
     1491
     1492EncodedJSValue JSC_HOST_CALL objectPrivateFuncInstanceOf(ExecState* exec)
     1493{
     1494    JSValue value = exec->uncheckedArgument(0);
     1495    JSValue proto = exec->uncheckedArgument(1);
     1496
     1497    return JSValue::encode(jsBoolean(JSObject::defaultHasInstance(exec, value, proto)));
    14681498}
    14691499
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r194175 r194248  
    488488    JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
    489489
     490    JS_EXPORT_PRIVATE bool hasInstance(ExecState*, JSValue value, JSValue hasInstanceValue);
    490491    bool hasInstance(ExecState*, JSValue);
    491492    static bool defaultHasInstance(ExecState*, JSValue, JSValue prototypeProperty);
     
    978979    }
    979980};
     981
     982JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectPrivateFuncInstanceOf(ExecState*);
    980983
    981984inline JSFinalObject* JSFinalObject::create(
  • trunk/Source/JavaScriptCore/runtime/JSTypeInfo.h

    r194036 r194248  
    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

    r194036 r194248  
    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

    r194036 r194248  
    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.