Changeset 206065 in webkit


Ignore:
Timestamp:
Sep 16, 2016 11:32:50 PM (8 years ago)
Author:
Yusuke Suzuki
Message:

[DFG] Introduce IsCellWithType node and unify IsJSArray, IsRegExpObject and newly added IsProxyObject
https://bugs.webkit.org/show_bug.cgi?id=162000

Reviewed by Filip Pizlo.

JSTests:

  • microbenchmarks/is-array-for-array.js: Added.

(isArray):

  • microbenchmarks/is-array-for-mixed-case.js: Added.

(isArray):

  • microbenchmarks/is-array-for-non-array-object.js: Added.

(isArray):

  • microbenchmarks/is-array-for-proxy.js: Added.

(isArray):
(isArray.proxy.throw.new.Error.isArray):
(isArray.proxy.throw.new.Error):

Source/JavaScriptCore:

Sampling profiler tells that ES6SampleBench/Basic frequently calls Array.isArray(). This function is introduced in
ES5 and it is well-used to distinguish Array from the other objects. Moreover, this function is used in Array.prototype.xxx
methods as @isArray. So it's worth optimizing.

The difference between Array.isArray and @isJSArray is that Array.isArray need to consider about ProxyObject while
@isJSArray builtin intrinsic does not. So in this patch, we leverage the existing @isJSArray to implement Array.isArray.
Array.isArray is written in builtin JS code using @isJSArray and newly added @isProxyObject(). That allow us to inline
Array.isArray() code and the inlined code uses existing DFG nodes well.

Another problem is RuntimeArray and ArrayPrototype. They inherit JSArray and their JSType is ObjectType. But Array.isArray need
to return true for those types. While optimizing type checking in generic way by type display is nice, RuntimeArray and
ArrayPrototype are a bit tricky and it is super rare that these functions are passed to Array.isArray(). So instead of introducing
type display in this patch, we just introduce a new JSType, DerivedArrayType and use it in the above 2 use classes. Since
Array.isArray is specially handled in the spec (while we don't have any Date.isDate() like functions, only Array.isArray
is specified in the spec because we frequently want to distinguish Arrays from other Objects), optimizing Array.isArray specially
by introducing special DerivedArrayType is reasonable.

In LLInt level, we add a new opcode, op_is_proxy_object and op_is_derived_array. This works similar to op_is_jsarray.
And we also perform LLInt code cleanup by introducing a macro isCellWithType.

In baseline, we perform some clean up for op_is_proxy_object etc. Now duplicate code is reduced.

In DFG, we unify IsJSArray, IsRegExpObject, IsProxyObject, and IsDerivedArray into one IsCellWithType node. And we clean up
some AI code related to IsJSArray and IsRegExpObject since SpeculatedType now recognizes ProxyObject. IsJSArray and IsRegExpObject
does not do anything special for proxy objects.

The above change simplify things to create a new IsXXX DFG handling and paves the way for optimizing @isMap & @isSet in DFG.
Furthermore, introducing @isProxyObject() is nice for the first step to optimize ProxyObject handling.

Here is microbenchmark result. We can see stable performance improvement (Even if we use Proxies!).

baseline patched

is-array-for-array 2.5156+-0.0288 2.0668+-0.0285 definitely 1.2171x faster
is-array-for-mixed-case 4.7787+-0.0755 4.4722+-0.0789 definitely 1.0686x faster
is-array-for-non-array-object 2.3596+-0.0368 1.8178+-0.0262 definitely 1.2980x faster
is-array-for-proxy 4.0469+-0.0437 3.3845+-0.0404 definitely 1.1957x faster

And ES6SampleBench/Basic reports 5.2% perf improvement. And now sampling result in ES6SampleBench/Basic does not pose Array.isArray.

Benchmark First Iteration Worst 2% Steady State
baseline:Basic 28.59 ms +- 1.03 ms 15.08 ms +- 0.28 ms 1656.96 ms +- 18.02 ms
patched:Basic 27.82 ms +- 0.44 ms 14.59 ms +- 0.16 ms 1574.65 ms +- 8.44 ms

  • builtins/ArrayConstructor.js:

(isArray):
(from): Deleted.

  • builtins/BuiltinNames.h:
  • bytecode/BytecodeIntrinsicRegistry.h:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

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

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/SpeculatedType.cpp:

(JSC::dumpSpeculation):
(JSC::speculationFromClassInfo):
(JSC::speculationFromStructure):

  • bytecode/SpeculatedType.h:

(JSC::isProxyObjectSpeculation):
(JSC::isDerivedArraySpeculation):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::emitIsProxyObject):
(JSC::BytecodeGenerator::emitIsDerivedArray):
(JSC::BytecodeGenerator::emitIsJSArray): Deleted.

  • bytecompiler/NodesCodegen.cpp:

(JSC::BytecodeIntrinsicNode::emit_intrinsic_isProxyObject):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray):

  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
(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):
(JSC::DFG::FixupPhase::fixupIsCellWithType):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasQueriedType):
(JSC::DFG::Node::queriedType):
(JSC::DFG::Node::hasSpeculatedTypeForQuery):
(JSC::DFG::Node::speculatedTypeForQuery):
(JSC::DFG::Node::shouldSpeculateProxyObject):
(JSC::DFG::Node::shouldSpeculateDerivedArray):
(JSC::DFG::Node::loadVarargsData): Deleted.
(JSC::DFG::Node::shouldSpeculateArray): Deleted.

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

(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileIsCellWithType):
(JSC::DFG::SpeculativeJIT::speculateProxyObject):
(JSC::DFG::SpeculativeJIT::speculateDerivedArray):
(JSC::DFG::SpeculativeJIT::speculate):
(JSC::DFG::SpeculativeJIT::compileIsJSArray): Deleted.
(JSC::DFG::SpeculativeJIT::compileIsRegExpObject): Deleted.

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):
(JSC::DFG::isCell):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileIsCellWithType):
(JSC::FTL::DFG::LowerDFGToB3::speculate):
(JSC::FTL::DFG::LowerDFGToB3::isCellWithType):
(JSC::FTL::DFG::LowerDFGToB3::speculateProxyObject):
(JSC::FTL::DFG::LowerDFGToB3::speculateDerivedArray):
(JSC::FTL::DFG::LowerDFGToB3::compileIsJSArray): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::compileIsRegExpObject): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::isArray): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::isRegExpObject): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emitIsCellWithType):
(JSC::JIT::emit_op_is_string):
(JSC::JIT::emit_op_is_jsarray):
(JSC::JIT::emit_op_is_proxy_object):
(JSC::JIT::emit_op_is_derived_array):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emitIsCellWithType):
(JSC::JIT::emit_op_is_string):
(JSC::JIT::emit_op_is_jsarray):
(JSC::JIT::emit_op_is_proxy_object):
(JSC::JIT::emit_op_is_derived_array):

  • jsc.cpp:

(WTF::RuntimeArray::createStructure):

  • llint/LLIntData.cpp:

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

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/ArrayConstructor.cpp:

(JSC::ArrayConstructor::finishCreation):
(JSC::isArraySlowInline):
(JSC::isArraySlow):
(JSC::arrayConstructorPrivateFuncIsArraySlow):
(JSC::arrayConstructorIsArray): Deleted.

  • runtime/ArrayConstructor.h:

(JSC::isArray):

  • runtime/ArrayPrototype.h:

(JSC::ArrayPrototype::createStructure):

  • runtime/JSArray.h:

(JSC::JSArray::finishCreation):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSType.h:

Source/WebCore:

  • bridge/runtime_array.h:

(JSC::RuntimeArray::createStructure):

Location:
trunk
Files:
4 added
48 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r206064 r206065  
     12016-09-16  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DFG] Introduce IsCellWithType node and unify IsJSArray, IsRegExpObject and newly added IsProxyObject
     4        https://bugs.webkit.org/show_bug.cgi?id=162000
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * microbenchmarks/is-array-for-array.js: Added.
     9        (isArray):
     10        * microbenchmarks/is-array-for-mixed-case.js: Added.
     11        (isArray):
     12        * microbenchmarks/is-array-for-non-array-object.js: Added.
     13        (isArray):
     14        * microbenchmarks/is-array-for-proxy.js: Added.
     15        (isArray):
     16        (isArray.proxy.throw.new.Error.isArray):
     17        (isArray.proxy.throw.new.Error):
     18
    1192016-09-16  Yusuke Suzuki  <utatane.tea@gmail.com>
    220
  • trunk/Source/JavaScriptCore/ChangeLog

    r206047 r206065  
     12016-09-16  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DFG] Introduce IsCellWithType node and unify IsJSArray, IsRegExpObject and newly added IsProxyObject
     4        https://bugs.webkit.org/show_bug.cgi?id=162000
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Sampling profiler tells that ES6SampleBench/Basic frequently calls Array.isArray(). This function is introduced in
     9        ES5 and it is well-used to distinguish Array from the other objects. Moreover, this function is used in Array.prototype.xxx
     10        methods as @isArray. So it's worth optimizing.
     11
     12        The difference between Array.isArray and @isJSArray is that Array.isArray need to consider about ProxyObject while
     13        @isJSArray builtin intrinsic does not. So in this patch, we leverage the existing @isJSArray to implement Array.isArray.
     14        Array.isArray is written in builtin JS code using @isJSArray and newly added @isProxyObject(). That allow us to inline
     15        Array.isArray() code and the inlined code uses existing DFG nodes well.
     16
     17        Another problem is RuntimeArray and ArrayPrototype. They inherit JSArray and their JSType is ObjectType. But Array.isArray need
     18        to return true for those types. While optimizing type checking in generic way by type display is nice, RuntimeArray and
     19        ArrayPrototype are a bit tricky and it is super rare that these functions are passed to Array.isArray(). So instead of introducing
     20        type display in this patch, we just introduce a new JSType, DerivedArrayType and use it in the above 2 use classes. Since
     21        Array.isArray is specially handled in the spec (while we don't have any Date.isDate() like functions, only Array.isArray
     22        is specified in the spec because we frequently want to distinguish Arrays from other Objects), optimizing Array.isArray specially
     23        by introducing special DerivedArrayType is reasonable.
     24
     25        In LLInt level, we add a new opcode, op_is_proxy_object and op_is_derived_array. This works similar to op_is_jsarray.
     26        And we also perform LLInt code cleanup by introducing a macro isCellWithType.
     27
     28        In baseline, we perform some clean up for op_is_proxy_object etc. Now duplicate code is reduced.
     29
     30        In DFG, we unify IsJSArray, IsRegExpObject, IsProxyObject, and IsDerivedArray into one IsCellWithType node. And we clean up
     31        some AI code related to IsJSArray and IsRegExpObject since SpeculatedType now recognizes ProxyObject. IsJSArray and IsRegExpObject
     32        does not do anything special for proxy objects.
     33
     34        The above change simplify things to create a new IsXXX DFG handling and paves the way for optimizing @isMap & @isSet in DFG.
     35        Furthermore, introducing @isProxyObject() is nice for the first step to optimize ProxyObject handling.
     36
     37        Here is microbenchmark result. We can see stable performance improvement (Even if we use Proxies!).
     38
     39                                                    baseline                  patched
     40
     41            is-array-for-array                   2.5156+-0.0288     ^      2.0668+-0.0285        ^ definitely 1.2171x faster
     42            is-array-for-mixed-case              4.7787+-0.0755     ^      4.4722+-0.0789        ^ definitely 1.0686x faster
     43            is-array-for-non-array-object        2.3596+-0.0368     ^      1.8178+-0.0262        ^ definitely 1.2980x faster
     44            is-array-for-proxy                   4.0469+-0.0437     ^      3.3845+-0.0404        ^ definitely 1.1957x faster
     45
     46        And ES6SampleBench/Basic reports 5.2% perf improvement. And now sampling result in ES6SampleBench/Basic does not pose Array.isArray.
     47
     48            Benchmark             First Iteration        Worst 2%               Steady State
     49            baseline:Basic        28.59 ms +- 1.03 ms    15.08 ms +- 0.28 ms    1656.96 ms +- 18.02 ms
     50            patched:Basic         27.82 ms +- 0.44 ms    14.59 ms +- 0.16 ms    1574.65 ms +- 8.44 ms
     51
     52        * builtins/ArrayConstructor.js:
     53        (isArray):
     54        (from): Deleted.
     55        * builtins/BuiltinNames.h:
     56        * bytecode/BytecodeIntrinsicRegistry.h:
     57        * bytecode/BytecodeList.json:
     58        * bytecode/BytecodeUseDef.h:
     59        (JSC::computeUsesForBytecodeOffset):
     60        (JSC::computeDefsForBytecodeOffset):
     61        * bytecode/CodeBlock.cpp:
     62        (JSC::CodeBlock::dumpBytecode):
     63        * bytecode/SpeculatedType.cpp:
     64        (JSC::dumpSpeculation):
     65        (JSC::speculationFromClassInfo):
     66        (JSC::speculationFromStructure):
     67        * bytecode/SpeculatedType.h:
     68        (JSC::isProxyObjectSpeculation):
     69        (JSC::isDerivedArraySpeculation):
     70        * bytecompiler/BytecodeGenerator.h:
     71        (JSC::BytecodeGenerator::emitIsProxyObject):
     72        (JSC::BytecodeGenerator::emitIsDerivedArray):
     73        (JSC::BytecodeGenerator::emitIsJSArray): Deleted.
     74        * bytecompiler/NodesCodegen.cpp:
     75        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isProxyObject):
     76        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray):
     77        * dfg/DFGAbstractInterpreterInlines.h:
     78        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     79        * dfg/DFGByteCodeParser.cpp:
     80        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     81        (JSC::DFG::ByteCodeParser::parseBlock):
     82        * dfg/DFGCapabilities.cpp:
     83        (JSC::DFG::capabilityLevel):
     84        * dfg/DFGClobberize.h:
     85        (JSC::DFG::clobberize):
     86        * dfg/DFGDoesGC.cpp:
     87        (JSC::DFG::doesGC):
     88        * dfg/DFGFixupPhase.cpp:
     89        (JSC::DFG::FixupPhase::fixupNode):
     90        (JSC::DFG::FixupPhase::fixupIsCellWithType):
     91        * dfg/DFGGraph.cpp:
     92        (JSC::DFG::Graph::dump):
     93        * dfg/DFGNode.h:
     94        (JSC::DFG::Node::hasQueriedType):
     95        (JSC::DFG::Node::queriedType):
     96        (JSC::DFG::Node::hasSpeculatedTypeForQuery):
     97        (JSC::DFG::Node::speculatedTypeForQuery):
     98        (JSC::DFG::Node::shouldSpeculateProxyObject):
     99        (JSC::DFG::Node::shouldSpeculateDerivedArray):
     100        (JSC::DFG::Node::loadVarargsData): Deleted.
     101        (JSC::DFG::Node::shouldSpeculateArray): Deleted.
     102        * dfg/DFGNodeType.h:
     103        * dfg/DFGPredictionPropagationPhase.cpp:
     104        * dfg/DFGSafeToExecute.h:
     105        (JSC::DFG::SafeToExecuteEdge::operator()):
     106        (JSC::DFG::safeToExecute):
     107        * dfg/DFGSpeculativeJIT.cpp:
     108        (JSC::DFG::SpeculativeJIT::compileIsCellWithType):
     109        (JSC::DFG::SpeculativeJIT::speculateProxyObject):
     110        (JSC::DFG::SpeculativeJIT::speculateDerivedArray):
     111        (JSC::DFG::SpeculativeJIT::speculate):
     112        (JSC::DFG::SpeculativeJIT::compileIsJSArray): Deleted.
     113        (JSC::DFG::SpeculativeJIT::compileIsRegExpObject): Deleted.
     114        * dfg/DFGSpeculativeJIT.h:
     115        * dfg/DFGSpeculativeJIT32_64.cpp:
     116        (JSC::DFG::SpeculativeJIT::compile):
     117        * dfg/DFGSpeculativeJIT64.cpp:
     118        (JSC::DFG::SpeculativeJIT::compile):
     119        * dfg/DFGUseKind.cpp:
     120        (WTF::printInternal):
     121        * dfg/DFGUseKind.h:
     122        (JSC::DFG::typeFilterFor):
     123        (JSC::DFG::isCell):
     124        * ftl/FTLCapabilities.cpp:
     125        (JSC::FTL::canCompile):
     126        * ftl/FTLLowerDFGToB3.cpp:
     127        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     128        (JSC::FTL::DFG::LowerDFGToB3::compileIsCellWithType):
     129        (JSC::FTL::DFG::LowerDFGToB3::speculate):
     130        (JSC::FTL::DFG::LowerDFGToB3::isCellWithType):
     131        (JSC::FTL::DFG::LowerDFGToB3::speculateProxyObject):
     132        (JSC::FTL::DFG::LowerDFGToB3::speculateDerivedArray):
     133        (JSC::FTL::DFG::LowerDFGToB3::compileIsJSArray): Deleted.
     134        (JSC::FTL::DFG::LowerDFGToB3::compileIsRegExpObject): Deleted.
     135        (JSC::FTL::DFG::LowerDFGToB3::isArray): Deleted.
     136        (JSC::FTL::DFG::LowerDFGToB3::isRegExpObject): Deleted.
     137        * jit/JIT.cpp:
     138        (JSC::JIT::privateCompileMainPass):
     139        * jit/JIT.h:
     140        * jit/JITOpcodes.cpp:
     141        (JSC::JIT::emitIsCellWithType):
     142        (JSC::JIT::emit_op_is_string):
     143        (JSC::JIT::emit_op_is_jsarray):
     144        (JSC::JIT::emit_op_is_proxy_object):
     145        (JSC::JIT::emit_op_is_derived_array):
     146        * jit/JITOpcodes32_64.cpp:
     147        (JSC::JIT::emitIsCellWithType):
     148        (JSC::JIT::emit_op_is_string):
     149        (JSC::JIT::emit_op_is_jsarray):
     150        (JSC::JIT::emit_op_is_proxy_object):
     151        (JSC::JIT::emit_op_is_derived_array):
     152        * jsc.cpp:
     153        (WTF::RuntimeArray::createStructure):
     154        * llint/LLIntData.cpp:
     155        (JSC::LLInt::Data::performAssertions):
     156        * llint/LowLevelInterpreter.asm:
     157        * llint/LowLevelInterpreter32_64.asm:
     158        * llint/LowLevelInterpreter64.asm:
     159        * runtime/ArrayConstructor.cpp:
     160        (JSC::ArrayConstructor::finishCreation):
     161        (JSC::isArraySlowInline):
     162        (JSC::isArraySlow):
     163        (JSC::arrayConstructorPrivateFuncIsArraySlow):
     164        (JSC::arrayConstructorIsArray): Deleted.
     165        * runtime/ArrayConstructor.h:
     166        (JSC::isArray):
     167        * runtime/ArrayPrototype.h:
     168        (JSC::ArrayPrototype::createStructure):
     169        * runtime/JSArray.h:
     170        (JSC::JSArray::finishCreation):
     171        * runtime/JSGlobalObject.cpp:
     172        (JSC::JSGlobalObject::init):
     173        * runtime/JSType.h:
     174
    11752016-09-16  Yusuke Suzuki  <utatane.tea@gmail.com>
    2176
  • trunk/Source/JavaScriptCore/builtins/ArrayConstructor.js

    r204597 r206065  
    103103    return result;
    104104}
     105
     106function isArray(array)
     107{
     108    "use strict";
     109
     110    if (@isJSArray(array) || @isDerivedArray(array))
     111        return true;
     112    if (!@isProxyObject(array))
     113        return false;
     114    return @isArraySlow(array);
     115}
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r205848 r206065  
    127127    macro(hasInstanceBoundFunction) \
    128128    macro(instanceOf) \
    129     macro(isArray) \
     129    macro(isArraySlow) \
    130130    macro(isArrayConstructor) \
    131131    macro(isConstructor) \
  • trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h

    r205278 r206065  
    4444    macro(isObject) \
    4545    macro(isJSArray) \
     46    macro(isProxyObject) \
     47    macro(isDerivedArray) \
    4648    macro(tailCallForwardArguments) \
    4749    macro(tryGetById) \
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r205321 r206065  
    5858            { "name" : "op_is_string", "length" : 3 },
    5959            { "name" : "op_is_jsarray", "length" : 3 },
     60            { "name" : "op_is_proxy_object", "length" : 3 },
    6061            { "name" : "op_is_object", "length" : 3 },
    6162            { "name" : "op_is_object_or_null", "length" : 3 },
    6263            { "name" : "op_is_function", "length" : 3 },
     64            { "name" : "op_is_derived_array", "length" : 3 },
    6365            { "name" : "op_in", "length" : 4 },
    6466            { "name" : "op_get_array_length", "length" : 9 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r205462 r206065  
    166166    case op_is_string:
    167167    case op_is_jsarray:
     168    case op_is_proxy_object:
    168169    case op_is_object:
    169170    case op_is_object_or_null:
    170171    case op_is_function:
     172    case op_is_derived_array:
    171173    case op_to_number:
    172174    case op_to_string:
     
    399401    case op_is_string:
    400402    case op_is_jsarray:
     403    case op_is_proxy_object:
    401404    case op_is_object:
    402405    case op_is_object_or_null:
    403406    case op_is_function:
     407    case op_is_derived_array:
    404408    case op_in:
    405409    case op_to_number:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r205794 r206065  
    11111111            break;
    11121112        }
     1113        case op_is_proxy_object: {
     1114            printUnaryOp(out, exec, location, it, "is_proxy_object");
     1115            break;
     1116        }
    11131117        case op_is_object: {
    11141118            printUnaryOp(out, exec, location, it, "is_object");
     
    11211125        case op_is_function: {
    11221126            printUnaryOp(out, exec, location, it, "is_function");
     1127            break;
     1128        }
     1129        case op_is_derived_array: {
     1130            printUnaryOp(out, exec, location, it, "is_derived_array");
    11231131            break;
    11241132        }
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp

    r205520 r206065  
    3636#include "JSMap.h"
    3737#include "JSSet.h"
     38#include "ProxyObject.h"
    3839#include "ScopedArguments.h"
    3940#include "StringObject.h"
     
    147148            if (value & SpecRegExpObject)
    148149                myOut.print("Regexpobject");
     150            else
     151                isTop = false;
     152
     153            if (value & SpecMapObject)
     154                myOut.print("Mapobject");
     155            else
     156                isTop = false;
     157
     158            if (value & SpecSetObject)
     159                myOut.print("Setobject");
     160            else
     161                isTop = false;
     162
     163            if (value & SpecProxyObject)
     164                myOut.print("Proxyobject");
     165            else
     166                isTop = false;
     167
     168            if (value & SpecDerivedArray)
     169                myOut.print("Derivedarray");
    149170            else
    150171                isTop = false;
     
    355376    if (classInfo == JSSet::info())
    356377        return SpecSetObject;
     378
     379    if (classInfo == ProxyObject::info())
     380        return SpecProxyObject;
    357381   
    358382    if (classInfo->isSubClassOf(JSFunction::info()))
     
    374398    if (structure->typeInfo().type() == SymbolType)
    375399        return SpecSymbol;
     400    if (structure->typeInfo().type() == DerivedArrayType)
     401        return SpecDerivedArray;
    376402    return speculationFromClassInfo(structure->classInfo());
    377403}
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r205520 r206065  
    5757static const SpeculatedType SpecStringObject       = 1ull << 14; // It's definitely a StringObject.
    5858static const SpeculatedType SpecRegExpObject       = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
    59 static const SpeculatedType SpecMapObject          = 1ull << 16; // It's definitely Map object (can it be a subclass? FIXME).
    60 static const SpeculatedType SpecSetObject          = 1ull << 17; // It's definitely s Set object (can it be a subclass? FIXME).
    61 static const SpeculatedType SpecObjectOther        = 1ull << 18; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
    62 static const SpeculatedType SpecObject             = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
    63 static const SpeculatedType SpecStringIdent        = 1ull << 19; // It's definitely a JSString, and it's an identifier.
    64 static const SpeculatedType SpecStringVar          = 1ull << 20; // It's definitely a JSString, and it's not an identifier.
     59static const SpeculatedType SpecMapObject          = 1ull << 16; // It's definitely a Map object or one of its subclasses.
     60static const SpeculatedType SpecSetObject          = 1ull << 17; // It's definitely a Set object or one of its subclasses.
     61static const SpeculatedType SpecProxyObject        = 1ull << 18; // It's definitely a Proxy object or one of its subclasses.
     62static const SpeculatedType SpecDerivedArray       = 1ull << 19; // It's definitely a DerivedArray object.
     63static const SpeculatedType SpecObjectOther        = 1ull << 20; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
     64static const SpeculatedType SpecObject             = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
     65static const SpeculatedType SpecStringIdent        = 1ull << 21; // It's definitely a JSString, and it's an identifier.
     66static const SpeculatedType SpecStringVar          = 1ull << 22; // It's definitely a JSString, and it's not an identifier.
    6567static const SpeculatedType SpecString             = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
    66 static const SpeculatedType SpecSymbol             = 1ull << 21; // It's definitely a Symbol.
    67 static const SpeculatedType SpecCellOther          = 1ull << 22; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
     68static const SpeculatedType SpecSymbol             = 1ull << 23; // It's definitely a Symbol.
     69static const SpeculatedType SpecCellOther          = 1ull << 24; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
    6870static const SpeculatedType SpecCell               = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell.
    69 static const SpeculatedType SpecBoolInt32          = 1ull << 23; // It's definitely an Int32 with value 0 or 1.
    70 static const SpeculatedType SpecNonBoolInt32       = 1ull << 24; // It's definitely an Int32 with value other than 0 or 1.
     71static const SpeculatedType SpecBoolInt32          = 1ull << 25; // It's definitely an Int32 with value 0 or 1.
     72static const SpeculatedType SpecNonBoolInt32       = 1ull << 26; // It's definitely an Int32 with value other than 0 or 1.
    7173static const SpeculatedType SpecInt32Only          = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
    72 static const SpeculatedType SpecInt52Only          = 1ull << 25; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
     74static const SpeculatedType SpecInt52Only          = 1ull << 27; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
    7375static const SpeculatedType SpecAnyInt             = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
    74 static const SpeculatedType SpecAnyIntAsDouble     = 1ull << 26; // It's definitely an Int52 and it's inside a double.
    75 static const SpeculatedType SpecNonIntAsDouble     = 1ull << 27; // It's definitely not an Int52 but it's a real number and it's a double.
     76static const SpeculatedType SpecAnyIntAsDouble     = 1ull << 28; // It's definitely an Int52 and it's inside a double.
     77static const SpeculatedType SpecNonIntAsDouble     = 1ull << 29; // It's definitely not an Int52 but it's a real number and it's a double.
    7678static const SpeculatedType SpecDoubleReal         = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
    77 static const SpeculatedType SpecDoublePureNaN      = 1ull << 28; // It's definitely a NaN that is sae to tag (i.e. pure).
    78 static const SpeculatedType SpecDoubleImpureNaN    = 1ull << 29; // It's definitely a NaN that is unsafe to tag (i.e. impure).
     79static const SpeculatedType SpecDoublePureNaN      = 1ull << 30; // It's definitely a NaN that is sae to tag (i.e. pure).
     80static const SpeculatedType SpecDoubleImpureNaN    = 1ull << 31; // It's definitely a NaN that is unsafe to tag (i.e. impure).
    7981static const SpeculatedType SpecDoubleNaN          = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
    8082static const SpeculatedType SpecBytecodeDouble     = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
     
    8486static const SpeculatedType SpecBytecodeNumber     = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
    8587static const SpeculatedType SpecFullNumber         = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
    86 static const SpeculatedType SpecBoolean            = 1ull << 30; // It's definitely a Boolean.
    87 static const SpeculatedType SpecOther              = 1ull << 31; // It's definitely either Null or Undefined.
     88static const SpeculatedType SpecBoolean            = 1ull << 32; // It's definitely a Boolean.
     89static const SpeculatedType SpecOther              = 1ull << 33; // It's definitely either Null or Undefined.
    8890static const SpeculatedType SpecMisc               = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
    8991static const SpeculatedType SpecHeapTop            = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
    9092static const SpeculatedType SpecPrimitive          = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc; // It's any non-Object JSValue.
    91 static const SpeculatedType SpecEmpty              = 1ull << 32; // It's definitely an empty value marker.
     93static const SpeculatedType SpecEmpty              = 1ull << 34; // It's definitely an empty value marker.
    9294static const SpeculatedType SpecBytecodeTop        = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
    9395static const SpeculatedType SpecFullTop            = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
     
    169171{
    170172    return value == SpecFunction;
     173}
     174
     175inline bool isProxyObjectSpeculation(SpeculatedType value)
     176{
     177    return value == SpecProxyObject;
     178}
     179
     180inline bool isDerivedArraySpeculation(SpeculatedType value)
     181{
     182    return value == SpecDerivedArray;
    171183}
    172184
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r204994 r206065  
    632632
    633633        RegisterID* emitIsJSArray(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_is_jsarray, dst, src); }
     634        RegisterID* emitIsProxyObject(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_is_proxy_object, dst, src); }
    634635        RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
    635636        RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
    636637        RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src);
     638        RegisterID* emitIsDerivedArray(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_is_derived_array, dst, src); }
    637639        void emitRequireObjectCoercible(RegisterID* value, const String& error);
    638640
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r205944 r206065  
    947947}
    948948
    949 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
     949RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
    950950{
    951951    ArgumentListNode* node = m_args->m_listNode;
     
    953953    ASSERT(!node->m_next);
    954954
     955    return generator.moveToDestinationIfNeeded(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
     956}
     957
     958RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
     959{
     960    ArgumentListNode* node = m_args->m_listNode;
     961    RefPtr<RegisterID> src = generator.emitNode(node);
     962    ASSERT(!node->m_next);
     963
    955964    return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
     965}
     966
     967RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
     968{
     969    ArgumentListNode* node = m_args->m_listNode;
     970    RefPtr<RegisterID> src = generator.emitNode(node);
     971    ASSERT(!node->m_next);
     972
     973    return generator.moveToDestinationIfNeeded(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
    956974}
    957975
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r205974 r206065  
    10111011
    10121012    case IsEmpty:
    1013     case IsJSArray:
    10141013    case IsUndefined:
    10151014    case IsBoolean:
     
    10191018    case IsObjectOrNull:
    10201019    case IsFunction:
    1021     case IsRegExpObject:
     1020    case IsCellWithType:
    10221021    case IsTypedArrayView: {
    10231022        AbstractValue child = forNode(node->child1());
     
    10251024            bool constantWasSet = true;
    10261025            switch (node->op()) {
    1027             case IsJSArray:
    1028                 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == ArrayType));
     1026            case IsCellWithType:
     1027                setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
    10291028                break;
    10301029            case IsUndefined:
     
    10761075                    setConstant(node, jsBoolean(false));
    10771076                break;
    1078             case IsRegExpObject:
    1079                 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType));
    1080                 break;
    10811077            case IsEmpty:
    10821078                setConstant(node, jsBoolean(child.value().isEmpty()));
     
    10991095        bool constantWasSet = false;
    11001096        switch (node->op()) {
    1101         case IsJSArray:
    1102             // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
    1103             if (!(child.m_type & ~SpecArray)) {
    1104                 setConstant(node, jsBoolean(true));
    1105                 constantWasSet = true;
    1106                 break;
    1107             }
    1108 
    1109             if (!(child.m_type & SpecObject)) {
    1110                 setConstant(node, jsBoolean(false));
    1111                 constantWasSet = true;
    1112                 break;
    1113             }
    1114 
    1115             break;
    11161097        case IsEmpty: {
    11171098            if (child.m_type && !(child.m_type & SpecEmpty)) {
     
    12421223            break;
    12431224
    1244         case IsRegExpObject:
    1245             // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
    1246             if (!(child.m_type & ~SpecRegExpObject)) {
     1225        case IsCellWithType:
     1226            if (!(child.m_type & ~node->speculatedTypeForQuery())) {
    12471227                setConstant(node, jsBoolean(true));
    12481228                constantWasSet = true;
    12491229                break;
    12501230            }
    1251             if (!(child.m_type & SpecObject)) {
     1231            if (!(child.m_type & node->speculatedTypeForQuery())) {
    12521232                setConstant(node, jsBoolean(false));
    12531233                constantWasSet = true;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r205974 r206065  
    23672367
    23682368        insertChecks();
    2369         Node* isRegExpObject = addToGraph(IsRegExpObject, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
     2369        Node* isRegExpObject = addToGraph(IsCellWithType, OpInfo(RegExpObjectType), OpInfo(SpecRegExpObject), get(virtualRegisterForArgument(1, registerOffset)));
    23702370        set(VirtualRegister(resultOperand), isRegExpObject);
    23712371        return true;
     
    39793979        case op_is_jsarray: {
    39803980            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
    3981             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsJSArray, value));
     3981            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsCellWithType, OpInfo(ArrayType), OpInfo(SpecArray), value));
    39823982            NEXT_OPCODE(op_is_jsarray);
     3983        }
     3984
     3985        case op_is_proxy_object: {
     3986            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
     3987            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsCellWithType, OpInfo(ProxyObjectType), OpInfo(SpecProxyObject), value));
     3988            NEXT_OPCODE(op_is_proxy_object);
    39833989        }
    39843990
     
    39994005            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsFunction, value));
    40004006            NEXT_OPCODE(op_is_function);
     4007        }
     4008
     4009        case op_is_derived_array: {
     4010            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
     4011            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsCellWithType, OpInfo(DerivedArrayType), OpInfo(SpecDerivedArray), value));
     4012            NEXT_OPCODE(op_is_derived_array);
    40014013        }
    40024014
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r204958 r206065  
    143143    case op_is_string:
    144144    case op_is_jsarray:
     145    case op_is_proxy_object:
    145146    case op_is_object:
    146147    case op_is_object_or_null:
    147148    case op_is_function:
     149    case op_is_derived_array:
    148150    case op_not:
    149151    case op_less:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r205974 r206065  
    159159    case CompareStrictEq:
    160160    case CompareEqPtr:
    161     case IsJSArray:
    162161    case IsEmpty:
    163162    case IsUndefined:
     
    166165    case IsString:
    167166    case IsObject:
    168     case IsRegExpObject:
    169167    case IsTypedArrayView:
    170168    case LogicalNot:
     
    214212            write(Heap);
    215213        }
     214        return;
     215
     216    case IsCellWithType:
     217        def(PureValue(node, node->queriedType()));
    216218        return;
    217219
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r205828 r206065  
    158158    case InstanceOf:
    159159    case InstanceOfCustom:
    160     case IsJSArray:
    161160    case IsEmpty:
    162161    case IsUndefined:
     
    167166    case IsObjectOrNull:
    168167    case IsFunction:
    169     case IsRegExpObject:
     168    case IsCellWithType:
    170169    case IsTypedArrayView:
    171170    case TypeOf:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r206047 r206065  
    14181418            break;
    14191419
    1420         case IsJSArray:
    1421             if (node->child1()->shouldSpeculateArray()) {
    1422                 m_insertionSet.insertNode(
    1423                     m_indexInBlock, SpecNone, Check, node->origin,
    1424                     Edge(node->child1().node(), ArrayUse));
    1425                 m_graph.convertToConstant(node, jsBoolean(true));
    1426                 observeUseKindOnNode<ArrayUse>(node);
    1427             }
    1428             break;
     1420        case IsCellWithType: {
     1421            fixupIsCellWithType(node);
     1422            break;
     1423        }
    14291424
    14301425        case GetEnumerableLength: {
     
    16401635        case IsObjectOrNull:
    16411636        case IsFunction:
    1642         case IsRegExpObject:
    16431637        case CreateDirectArguments:
    16441638        case CreateClonedArguments:
     
    17681762            ASSERT(!node->child3());
    17691763            node->convertToIdentity();
     1764        }
     1765    }
     1766
     1767    void fixupIsCellWithType(Node* node)
     1768    {
     1769        switch (node->speculatedTypeForQuery()) {
     1770        case SpecProxyObject:
     1771            if (node->child1()->shouldSpeculateProxyObject()) {
     1772                m_insertionSet.insertNode(
     1773                    m_indexInBlock, SpecNone, Check, node->origin,
     1774                    Edge(node->child1().node(), ProxyObjectUse));
     1775                m_graph.convertToConstant(node, jsBoolean(true));
     1776                observeUseKindOnNode<ProxyObjectUse>(node);
     1777                return;
     1778            }
     1779            break;
     1780
     1781        case SpecRegExpObject:
     1782            if (node->child1()->shouldSpeculateRegExpObject()) {
     1783                m_insertionSet.insertNode(
     1784                    m_indexInBlock, SpecNone, Check, node->origin,
     1785                    Edge(node->child1().node(), RegExpObjectUse));
     1786                m_graph.convertToConstant(node, jsBoolean(true));
     1787                observeUseKindOnNode<RegExpObjectUse>(node);
     1788                return;
     1789            }
     1790            break;
     1791
     1792        case SpecArray:
     1793            if (node->child1()->shouldSpeculateArray()) {
     1794                m_insertionSet.insertNode(
     1795                    m_indexInBlock, SpecNone, Check, node->origin,
     1796                    Edge(node->child1().node(), ArrayUse));
     1797                m_graph.convertToConstant(node, jsBoolean(true));
     1798                observeUseKindOnNode<ArrayUse>(node);
     1799                return;
     1800            }
     1801            break;
     1802
     1803        case SpecDerivedArray:
     1804            if (node->child1()->shouldSpeculateDerivedArray()) {
     1805                m_insertionSet.insertNode(
     1806                    m_indexInBlock, SpecNone, Check, node->origin,
     1807                    Edge(node->child1().node(), DerivedArrayUse));
     1808                m_graph.convertToConstant(node, jsBoolean(true));
     1809                observeUseKindOnNode<DerivedArrayUse>(node);
     1810                return;
     1811            }
     1812            break;
     1813        }
     1814
     1815        if (node->child1()->shouldSpeculateCell()) {
     1816            fixEdge<CellUse>(node->child1());
     1817            return;
     1818        }
     1819
     1820        if (node->child1()->shouldSpeculateNotCell()) {
     1821            m_insertionSet.insertNode(
     1822                m_indexInBlock, SpecNone, Check, node->origin,
     1823                Edge(node->child1().node(), NotCellUse));
     1824            m_graph.convertToConstant(node, jsBoolean(false));
     1825            observeUseKindOnNode<NotCellUse>(node);
     1826            return;
    17701827        }
    17711828    }
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r204393 r206065  
    268268        }
    269269    }
     270    if (node->hasSpeculatedTypeForQuery())
     271        out.print(comma, SpeculationDump(node->speculatedTypeForQuery()));
    270272    if (node->hasStorageAccessData()) {
    271273        StorageAccessData& storageAccessData = node->storageAccessData();
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r205520 r206065  
    11601160        ASSERT(hasLoadVarargsData());
    11611161        return m_opInfo.as<LoadVarargsData*>();
     1162    }
     1163
     1164    bool hasQueriedType()
     1165    {
     1166        return op() == IsCellWithType;
     1167    }
     1168
     1169    JSType queriedType()
     1170    {
     1171        static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
     1172        return static_cast<JSType>(m_opInfo.as<uint32_t>());
     1173    }
     1174
     1175    bool hasSpeculatedTypeForQuery()
     1176    {
     1177        return op() == IsCellWithType;
     1178    }
     1179
     1180    SpeculatedType speculatedTypeForQuery()
     1181    {
     1182        return m_opInfo2.as<SpeculatedType>();
    11621183    }
    11631184   
     
    20602081        return isArraySpeculation(prediction());
    20612082    }
     2083
     2084    bool shouldSpeculateProxyObject()
     2085    {
     2086        return isProxyObjectSpeculation(prediction());
     2087    }
     2088
     2089    bool shouldSpeculateDerivedArray()
     2090    {
     2091        return isDerivedArraySpeculation(prediction());
     2092    }
    20622093   
    20632094    bool shouldSpeculateDirectArguments()
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r205974 r206065  
    310310    macro(InstanceOfCustom, NodeMustGenerate | NodeResultBoolean) \
    311311    \
    312     macro(IsJSArray, NodeResultBoolean) \
     312    macro(IsCellWithType, NodeResultBoolean) \
    313313    macro(IsEmpty, NodeResultBoolean) \
    314314    macro(IsUndefined, NodeResultBoolean) \
     
    319319    macro(IsObjectOrNull, NodeResultBoolean) \
    320320    macro(IsFunction, NodeResultBoolean) \
    321     macro(IsRegExpObject, NodeResultBoolean) \
    322321    macro(IsTypedArrayView, NodeResultBoolean) \
    323322    macro(TypeOf, NodeResultJS) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r205974 r206065  
    794794        case InstanceOf:
    795795        case InstanceOfCustom:
    796         case IsJSArray:
    797796        case IsEmpty:
    798797        case IsUndefined:
     
    803802        case IsObjectOrNull:
    804803        case IsFunction:
    805         case IsRegExpObject:
     804        case IsCellWithType:
    806805        case IsTypedArrayView: {
    807806            setPrediction(SpecBoolean);
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r206047 r206065  
    6060        case FinalObjectUse:
    6161        case RegExpObjectUse:
     62        case ProxyObjectUse:
     63        case DerivedArrayUse:
    6264        case MapObjectUse:
    6365        case SetObjectUse:
     
    262264    case InstanceOf:
    263265    case InstanceOfCustom:
    264     case IsJSArray:
    265266    case IsEmpty:
    266267    case IsUndefined:
     
    271272    case IsObjectOrNull:
    272273    case IsFunction:
    273     case IsRegExpObject:
     274    case IsCellWithType:
    274275    case IsTypedArrayView:
    275276    case TypeOf:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r206047 r206065  
    36043604}
    36053605
    3606 void SpeculativeJIT::compileIsJSArray(Node* node)
    3607 {
    3608     JSValueOperand value(this, node->child1());
    3609     GPRFlushedCallResult result(this);
    3610 
    3611     JSValueRegs valueRegs = value.jsValueRegs();
    3612     GPRReg resultGPR = result.gpr();
    3613 
    3614     JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
    3615 
    3616     m_jit.compare8(JITCompiler::Equal,
    3617         JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
    3618         TrustedImm32(ArrayType),
    3619         resultGPR);
    3620     blessBoolean(resultGPR);
    3621     JITCompiler::Jump done = m_jit.jump();
    3622 
    3623     isNotCell.link(&m_jit);
    3624     moveFalseTo(resultGPR);
    3625 
    3626     done.link(&m_jit);
    3627     blessedBooleanResult(resultGPR, node);
    3628 }
    3629 
    3630 void SpeculativeJIT::compileIsRegExpObject(Node* node)
    3631 {
    3632     JSValueOperand value(this, node->child1());
    3633     GPRFlushedCallResult result(this);
    3634 
    3635     JSValueRegs valueRegs = value.jsValueRegs();
    3636     GPRReg resultGPR = result.gpr();
    3637 
    3638     JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
    3639 
    3640     m_jit.compare8(JITCompiler::Equal,
    3641         JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
    3642         TrustedImm32(RegExpObjectType),
    3643         resultGPR);
    3644     blessBoolean(resultGPR);
    3645     JITCompiler::Jump done = m_jit.jump();
    3646 
    3647     isNotCell.link(&m_jit);
    3648     moveFalseTo(resultGPR);
    3649 
    3650     done.link(&m_jit);
    3651     blessedBooleanResult(resultGPR, node);
     3606void SpeculativeJIT::compileIsCellWithType(Node* node)
     3607{
     3608    switch (node->child1().useKind()) {
     3609    case UntypedUse: {
     3610        JSValueOperand value(this, node->child1());
     3611#if USE(JSVALUE64)
     3612        GPRTemporary result(this, Reuse, value);
     3613#else
     3614        GPRTemporary result(this, Reuse, value, PayloadWord);
     3615#endif
     3616
     3617        JSValueRegs valueRegs = value.jsValueRegs();
     3618        GPRReg resultGPR = result.gpr();
     3619
     3620        JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
     3621
     3622        m_jit.compare8(JITCompiler::Equal,
     3623            JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
     3624            TrustedImm32(node->queriedType()),
     3625            resultGPR);
     3626        blessBoolean(resultGPR);
     3627        JITCompiler::Jump done = m_jit.jump();
     3628
     3629        isNotCell.link(&m_jit);
     3630        moveFalseTo(resultGPR);
     3631
     3632        done.link(&m_jit);
     3633        blessedBooleanResult(resultGPR, node);
     3634        return;
     3635    }
     3636
     3637    case CellUse: {
     3638        SpeculateCellOperand cell(this, node->child1());
     3639        GPRTemporary result(this, Reuse, cell);
     3640
     3641        GPRReg cellGPR = cell.gpr();
     3642        GPRReg resultGPR = result.gpr();
     3643
     3644        m_jit.compare8(JITCompiler::Equal,
     3645            JITCompiler::Address(cellGPR, JSCell::typeInfoTypeOffset()),
     3646            TrustedImm32(node->queriedType()),
     3647            resultGPR);
     3648        blessBoolean(resultGPR);
     3649        blessedBooleanResult(resultGPR, node);
     3650        return;
     3651    }
     3652
     3653    default:
     3654        RELEASE_ASSERT_NOT_REACHED();
     3655        break;
     3656    }
    36523657}
    36533658
     
    74097414}
    74107415
     7416void SpeculativeJIT::speculateProxyObject(Edge edge, GPRReg cell)
     7417{
     7418    speculateCellType(edge, cell, SpecProxyObject, ProxyObjectType);
     7419}
     7420
     7421void SpeculativeJIT::speculateProxyObject(Edge edge)
     7422{
     7423    if (!needsTypeCheck(edge, SpecProxyObject))
     7424        return;
     7425
     7426    SpeculateCellOperand operand(this, edge);
     7427    speculateProxyObject(edge, operand.gpr());
     7428}
     7429
     7430void SpeculativeJIT::speculateDerivedArray(Edge edge, GPRReg cell)
     7431{
     7432    speculateCellType(edge, cell, SpecDerivedArray, DerivedArrayType);
     7433}
     7434
     7435void SpeculativeJIT::speculateDerivedArray(Edge edge)
     7436{
     7437    if (!needsTypeCheck(edge, SpecDerivedArray))
     7438        return;
     7439
     7440    SpeculateCellOperand operand(this, edge);
     7441    speculateDerivedArray(edge, operand.gpr());
     7442}
     7443
    74117444void SpeculativeJIT::speculateMapObject(Edge edge, GPRReg cell)
    74127445{
     
    77267759    case RegExpObjectUse:
    77277760        speculateRegExpObject(edge);
     7761        break;
     7762    case ProxyObjectUse:
     7763        speculateProxyObject(edge);
     7764        break;
     7765    case DerivedArrayUse:
     7766        speculateDerivedArray(edge);
    77287767        break;
    77297768    case MapObjectUse:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r206047 r206065  
    756756    void compileInstanceOfCustom(Node*);
    757757
    758     void compileIsJSArray(Node*);
    759     void compileIsRegExpObject(Node*);
     758    void compileIsCellWithType(Node*);
    760759    void compileIsTypedArrayView(Node*);
    761760
     
    26812680    void speculateRegExpObject(Edge, GPRReg cell);
    26822681    void speculateRegExpObject(Edge);
     2682    void speculateProxyObject(Edge, GPRReg cell);
     2683    void speculateProxyObject(Edge);
     2684    void speculateDerivedArray(Edge, GPRReg cell);
     2685    void speculateDerivedArray(Edge);
    26832686    void speculateMapObject(Edge);
    26842687    void speculateMapObject(Edge, GPRReg cell);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r205828 r206065  
    46614661    }
    46624662
    4663     case IsJSArray: {
    4664         compileIsJSArray(node);
    4665         break;
    4666     }
    4667 
    46684663    case IsObject: {
    46694664        JSValueOperand value(this, node->child1());
     
    46964691    }
    46974692
    4698     case IsRegExpObject: {
    4699         compileIsRegExpObject(node);
     4693    case IsCellWithType: {
     4694        compileIsCellWithType(node);
    47004695        break;
    47014696    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r205828 r206065  
    46334633    }
    46344634
    4635     case IsJSArray: {
    4636         compileIsJSArray(node);
    4637         break;
    4638     }
    4639 
    46404635    case MapHash: {
    46414636        JSValueOperand input(this, node->child1());
     
    48314826    }
    48324827
    4833     case IsRegExpObject: {
    4834         compileIsRegExpObject(node);
     4828    case IsCellWithType: {
     4829        compileIsCellWithType(node);
    48354830        break;
    48364831    }
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp

    r206047 r206065  
    9898        out.print("RegExpObject");
    9999        return;
     100    case ProxyObjectUse:
     101        out.print("ProxyObject");
     102        return;
     103    case DerivedArrayUse:
     104        out.print("DerivedArray");
     105        return;
    100106    case MapObjectUse:
    101107        out.print("MapObjectUse");
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.h

    r206047 r206065  
    5858    FinalObjectUse,
    5959    RegExpObjectUse,
     60    ProxyObjectUse,
     61    DerivedArrayUse,
    6062    ObjectOrOtherUse,
    6163    StringIdentUse,
     
    127129    case RegExpObjectUse:
    128130        return SpecRegExpObject;
     131    case ProxyObjectUse:
     132        return SpecProxyObject;
     133    case DerivedArrayUse:
     134        return SpecDerivedArray;
    129135    case ObjectOrOtherUse:
    130136        return SpecObject | SpecOther;
     
    226232    case FinalObjectUse:
    227233    case RegExpObjectUse:
     234    case ProxyObjectUse:
     235    case DerivedArrayUse:
    228236    case StringIdentUse:
    229237    case StringUse:
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r206047 r206065  
    182182    case Unreachable:
    183183    case In:
    184     case IsJSArray:
     184    case IsCellWithType:
    185185    case MapHash:
    186186    case GetMapBucket:
     
    195195    case IsObjectOrNull:
    196196    case IsFunction:
    197     case IsRegExpObject:
    198197    case IsTypedArrayView:
    199198    case CheckTypeInfoFlags:
     
    437436                case FinalObjectUse:
    438437                case RegExpObjectUse:
     438                case ProxyObjectUse:
     439                case DerivedArrayUse:
    439440                case NotCellUse:
    440441                case OtherUse:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r206047 r206065  
    900900            compileIsString();
    901901            break;
    902         case IsJSArray:
    903             compileIsJSArray();
     902        case IsCellWithType:
     903            compileIsCellWithType();
    904904            break;
    905905        case MapHash:
     
    923923        case IsFunction:
    924924            compileIsFunction();
    925             break;
    926         case IsRegExpObject:
    927             compileIsRegExpObject();
    928925            break;
    929926        case IsTypedArrayView:
     
    62876284    }
    62886285
    6289     void compileIsJSArray()
    6290     {
    6291         LValue value = lowJSValue(m_node->child1());
    6292 
    6293         LBasicBlock isCellCase = m_out.newBlock();
    6294         LBasicBlock continuation = m_out.newBlock();
    6295 
    6296         ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
    6297         m_out.branch(
    6298             isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
    6299 
    6300         LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
    6301         ValueFromBlock cellResult = m_out.anchor(isArray(value, provenType(m_node->child1())));
    6302         m_out.jump(continuation);
    6303 
    6304         m_out.appendTo(continuation, lastNext);
    6305         setBoolean(m_out.phi(Int32, notCellResult, cellResult));
     6286    void compileIsCellWithType()
     6287    {
     6288        if (m_node->child1().useKind() == UntypedUse) {
     6289            LValue value = lowJSValue(m_node->child1());
     6290
     6291            LBasicBlock isCellCase = m_out.newBlock();
     6292            LBasicBlock continuation = m_out.newBlock();
     6293
     6294            ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
     6295            m_out.branch(
     6296                isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
     6297
     6298            LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
     6299            ValueFromBlock cellResult = m_out.anchor(isCellWithType(value, m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
     6300            m_out.jump(continuation);
     6301
     6302            m_out.appendTo(continuation, lastNext);
     6303            setBoolean(m_out.phi(Int32, notCellResult, cellResult));
     6304        } else {
     6305            ASSERT(m_node->child1().useKind() == CellUse);
     6306            setBoolean(isCellWithType(lowCell(m_node->child1()), m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
     6307        }
    63066308    }
    63076309
     
    66466648            Int32, notCellResult, functionResult, objectResult, slowResult);
    66476649        setBoolean(result);
    6648     }
    6649 
    6650     void compileIsRegExpObject()
    6651     {
    6652         LValue value = lowJSValue(m_node->child1());
    6653 
    6654         LBasicBlock isCellCase = m_out.newBlock();
    6655         LBasicBlock continuation = m_out.newBlock();
    6656 
    6657         ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
    6658         m_out.branch(
    6659             isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
    6660 
    6661         LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
    6662         ValueFromBlock cellResult = m_out.anchor(isRegExpObject(value, provenType(m_node->child1())));
    6663         m_out.jump(continuation);
    6664 
    6665         m_out.appendTo(continuation, lastNext);
    6666         setBoolean(m_out.phi(Int32, notCellResult, cellResult));
    66676650    }
    66686651
     
    1069210675            speculateRegExpObject(edge);
    1069310676            break;
     10677        case ProxyObjectUse:
     10678            speculateProxyObject(edge);
     10679            break;
     10680        case DerivedArrayUse:
     10681            speculateDerivedArray(edge);
     10682            break;
    1069410683        case MapObjectUse:
    1069510684            speculateMapObject(edge);
     
    1078710776    }
    1078810777
    10789     LValue isArray(LValue cell, SpeculatedType type = SpecFullTop)
    10790     {
    10791         if (LValue proven = isProvenValue(type & SpecCell, SpecArray))
     10778    LValue isCellWithType(LValue cell, JSType queriedType, SpeculatedType speculatedTypeForQuery, SpeculatedType type = SpecFullTop)
     10779    {
     10780        if (LValue proven = isProvenValue(type & SpecCell, speculatedTypeForQuery))
    1079210781            return proven;
    1079310782        return m_out.equal(
    1079410783            m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
    10795             m_out.constInt32(ArrayType));
     10784            m_out.constInt32(queriedType));
    1079610785    }
    1079710786
     
    1093410923    }
    1093510924
    10936     LValue isRegExpObject(LValue cell, SpeculatedType type = SpecFullTop)
    10937     {
    10938         if (LValue proven = isProvenValue(type & SpecCell, SpecRegExpObject))
    10939             return proven;
    10940         return m_out.equal(
    10941             m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
    10942             m_out.constInt32(RegExpObjectType));
    10943     }
    10944 
    1094510925    LValue isType(LValue cell, JSType type)
    1094610926    {
     
    1103611016    {
    1103711017        speculateRegExpObject(edge, lowCell(edge));
     11018    }
     11019
     11020    void speculateProxyObject(Edge edge, LValue cell)
     11021    {
     11022        FTL_TYPE_CHECK(
     11023            jsValueValue(cell), edge, SpecProxyObject, isNotType(cell, ProxyObjectType));
     11024    }
     11025
     11026    void speculateProxyObject(Edge edge)
     11027    {
     11028        speculateProxyObject(edge, lowCell(edge));
     11029    }
     11030
     11031    void speculateDerivedArray(Edge edge, LValue cell)
     11032    {
     11033        FTL_TYPE_CHECK(
     11034            jsValueValue(cell), edge, SpecDerivedArray, isNotType(cell, DerivedArrayType));
     11035    }
     11036
     11037    void speculateDerivedArray(Edge edge)
     11038    {
     11039        speculateDerivedArray(edge, lowCell(edge));
    1103811040    }
    1103911041
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r205675 r206065  
    271271        DEFINE_OP(op_is_string)
    272272        DEFINE_OP(op_is_jsarray)
     273        DEFINE_OP(op_is_proxy_object)
    273274        DEFINE_OP(op_is_object)
     275        DEFINE_OP(op_is_derived_array)
    274276        DEFINE_OP(op_jeq_null)
    275277        DEFINE_OP(op_jfalse)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r205675 r206065  
    401401        int32_t getOperandConstantInt(int src);
    402402        double getOperandConstantDouble(int src);
     403
     404        void emitIsCellWithType(Instruction*, JSType);
    403405
    404406#if USE(JSVALUE32_64)
     
    517519        void emit_op_is_string(Instruction*);
    518520        void emit_op_is_jsarray(Instruction*);
     521        void emit_op_is_proxy_object(Instruction*);
    519522        void emit_op_is_object(Instruction*);
     523        void emit_op_is_derived_array(Instruction*);
    520524        void emit_op_jeq_null(Instruction*);
    521525        void emit_op_jfalse(Instruction*);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r205675 r206065  
    244244}
    245245
    246 void JIT::emit_op_is_string(Instruction* currentInstruction)
     246void JIT::emitIsCellWithType(Instruction* currentInstruction, JSType type)
    247247{
    248248    int dst = currentInstruction[1].u.operand;
    249249    int value = currentInstruction[2].u.operand;
    250    
     250
    251251    emitGetVirtualRegister(value, regT0);
    252252    Jump isNotCell = emitJumpIfNotJSCell(regT0);
    253    
    254     compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType), regT0);
     253
     254    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(type), regT0);
    255255    emitTagBool(regT0);
    256256    Jump done = jump();
    257    
     257
    258258    isNotCell.link(this);
    259259    move(TrustedImm32(ValueFalse), regT0);
    260    
     260
    261261    done.link(this);
    262262    emitPutVirtualRegister(dst);
    263263}
    264264
     265void JIT::emit_op_is_string(Instruction* currentInstruction)
     266{
     267    emitIsCellWithType(currentInstruction, StringType);
     268}
     269
    265270void JIT::emit_op_is_jsarray(Instruction* currentInstruction)
    266271{
    267     int dst = currentInstruction[1].u.operand;
    268     int value = currentInstruction[2].u.operand;
    269 
    270     emitGetVirtualRegister(value, regT0);
    271     Jump isNotCell = emitJumpIfNotJSCell(regT0);
    272 
    273     compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ArrayType), regT0);
    274     emitTagBool(regT0);
    275     Jump done = jump();
    276 
    277     isNotCell.link(this);
    278     move(TrustedImm32(ValueFalse), regT0);
    279 
    280     done.link(this);
    281     emitPutVirtualRegister(dst);
     272    emitIsCellWithType(currentInstruction, ArrayType);
     273}
     274
     275void JIT::emit_op_is_proxy_object(Instruction* currentInstruction)
     276{
     277    emitIsCellWithType(currentInstruction, ProxyObjectType);
     278}
     279
     280void JIT::emit_op_is_derived_array(Instruction* currentInstruction)
     281{
     282    emitIsCellWithType(currentInstruction, DerivedArrayType);
    282283}
    283284
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r205675 r206065  
    355355}
    356356
    357 void JIT::emit_op_is_string(Instruction* currentInstruction)
     357void JIT::emitIsCellWithType(Instruction* currentInstruction, JSType type)
    358358{
    359359    int dst = currentInstruction[1].u.operand;
    360360    int value = currentInstruction[2].u.operand;
    361    
     361
    362362    emitLoad(value, regT1, regT0);
    363363    Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
    364    
    365     compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType), regT0);
     364
     365    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(type), regT0);
    366366    Jump done = jump();
    367    
     367
    368368    isNotCell.link(this);
    369369    move(TrustedImm32(0), regT0);
    370    
     370
    371371    done.link(this);
    372372    emitStoreBool(dst, regT0);
    373373}
    374374
     375void JIT::emit_op_is_string(Instruction* currentInstruction)
     376{
     377    emitIsCellWithType(currentInstruction, StringType);
     378}
     379
    375380void JIT::emit_op_is_jsarray(Instruction* currentInstruction)
    376381{
    377     int dst = currentInstruction[1].u.operand;
    378     int value = currentInstruction[2].u.operand;
    379 
    380     emitLoad(value, regT1, regT0);
    381     Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
    382 
    383     compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ArrayType), regT0);
    384     Jump done = jump();
    385 
    386     isNotCell.link(this);
    387     move(TrustedImm32(0), regT0);
    388 
    389     done.link(this);
    390     emitStoreBool(dst, regT0);
     382    emitIsCellWithType(currentInstruction, ArrayType);
     383}
     384
     385void JIT::emit_op_is_proxy_object(Instruction* currentInstruction)
     386{
     387    emitIsCellWithType(currentInstruction, ProxyObjectType);
     388}
     389
     390void JIT::emit_op_is_derived_array(Instruction* currentInstruction)
     391{
     392    emitIsCellWithType(currentInstruction, DerivedArrayType);
    391393}
    392394
  • trunk/Source/JavaScriptCore/jsc.cpp

    r205880 r206065  
    456456    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    457457    {
    458         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
     458        return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
    459459    }
    460460
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r205462 r206065  
    160160    STATIC_ASSERT(FinalObjectType == 21);
    161161    STATIC_ASSERT(JSFunctionType == 23);
    162     STATIC_ASSERT(ArrayType == 29);
     162    STATIC_ASSERT(ArrayType == 31);
     163    STATIC_ASSERT(DerivedArrayType == 32);
     164    STATIC_ASSERT(ProxyObjectType == 116);
    163165    STATIC_ASSERT(Int8ArrayType == 100);
    164166    STATIC_ASSERT(Int16ArrayType == 101);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r205462 r206065  
    347347const FinalObjectType = 21
    348348const JSFunctionType = 23
    349 const ArrayType = 29
     349const ArrayType = 31
     350const DerivedArrayType = 32
     351const ProxyObjectType = 116
    350352
    351353# The typed array types need to be numbered in a particular order because of the manually written
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r205462 r206065  
    12581258
    12591259
    1260 _llint_op_is_string:
    1261     traceExecution()
     1260macro isCellWithType(type)
    12621261    loadi 8[PC], t1
    12631262    loadi 4[PC], t2
    12641263    loadConstantOrVariable(t1, t0, t3)
    12651264    storei BooleanTag, TagOffset[cfr, t2, 8]
    1266     bineq t0, CellTag, .opIsStringNotCell
    1267     cbeq JSCell::m_type[t3], StringType, t1
     1265    bineq t0, CellTag, .notCellCase
     1266    cbeq JSCell::m_type[t3], type, t1
    12681267    storei t1, PayloadOffset[cfr, t2, 8]
    12691268    dispatch(3)
    1270 .opIsStringNotCell:
     1269.notCellCase:
    12711270    storep 0, PayloadOffset[cfr, t2, 8]
    12721271    dispatch(3)
     1272end
     1273
     1274
     1275_llint_op_is_string:
     1276    traceExecution()
     1277    isCellWithType(StringType)
    12731278
    12741279
    12751280_llint_op_is_jsarray:
    12761281    traceExecution()
    1277     loadi 8[PC], t1
    1278     loadi 4[PC], t2
    1279     loadConstantOrVariable(t1, t0, t3)
    1280     storei BooleanTag, TagOffset[cfr, t2, 8]
    1281     bineq t0, CellTag, .opIsJSArrayNotCell
    1282     cbeq JSCell::m_type[t3], ArrayType, t1
    1283     storei t1, PayloadOffset[cfr, t2, 8]
    1284     dispatch(3)
    1285 .opIsJSArrayNotCell:
    1286     storep 0, PayloadOffset[cfr, t2, 8]
    1287     dispatch(3)
     1282    isCellWithType(ArrayType)
     1283
     1284
     1285_llint_op_is_proxy_object:
     1286    traceExecution()
     1287    isCellWithType(ProxyObjectType)
     1288
     1289
     1290_llint_op_is_derived_array:
     1291    traceExecution()
     1292    isCellWithType(DerivedArrayType)
    12881293
    12891294
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r205462 r206065  
    11471147
    11481148
    1149 _llint_op_is_string:
    1150     traceExecution()
     1149macro isCellWithType(type)
    11511150    loadisFromInstruction(2, t1)
    11521151    loadisFromInstruction(1, t2)
    11531152    loadConstantOrVariable(t1, t0)
    1154     btqnz t0, tagMask, .opIsStringNotCell
    1155     cbeq JSCell::m_type[t0], StringType, t1
     1153    btqnz t0, tagMask, .notCellCase
     1154    cbeq JSCell::m_type[t0], type, t1
    11561155    orq ValueFalse, t1
    11571156    storeq t1, [cfr, t2, 8]
    11581157    dispatch(3)
    1159 .opIsStringNotCell:
     1158.notCellCase:
    11601159    storeq ValueFalse, [cfr, t2, 8]
    11611160    dispatch(3)
     1161end
     1162
     1163
     1164_llint_op_is_string:
     1165    traceExecution()
     1166    isCellWithType(StringType)
    11621167
    11631168
    11641169_llint_op_is_jsarray:
    11651170    traceExecution()
    1166     loadisFromInstruction(2, t1)
    1167     loadisFromInstruction(1, t2)
    1168     loadConstantOrVariable(t1, t0)
    1169     btqnz t0, tagMask, .opIsJSArrayNotCell
    1170     cbeq JSCell::m_type[t0], ArrayType, t1
    1171     orq ValueFalse, t1
    1172     storeq t1, [cfr, t2, 8]
    1173     dispatch(3)
    1174 .opIsJSArrayNotCell:
    1175     storeq ValueFalse, [cfr, t2, 8]
    1176     dispatch(3)
     1171    isCellWithType(ArrayType)
     1172
     1173
     1174_llint_op_is_proxy_object:
     1175    traceExecution()
     1176    isCellWithType(ProxyObjectType)
     1177
     1178
     1179_llint_op_is_derived_array:
     1180    traceExecution()
     1181    isCellWithType(DerivedArrayType)
    11771182
    11781183
  • trunk/Source/JavaScriptCore/runtime/ArrayConstructor.cpp

    r205666 r206065  
    3636#include "JSCInlines.h"
    3737
    38 namespace JSC {
    39 
    40 static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*);
    41 
    42 }
    43 
    4438#include "ArrayConstructor.lut.h"
    4539
     
    6862    putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
    6963    putDirectNonIndexAccessor(vm, vm.propertyNames->speciesSymbol, speciesSymbol, Accessor | ReadOnly | DontEnum);
    70     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArray, DontEnum, 1);
     64    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArrayCodeGenerator, DontEnum);
    7165}
    7266
     
    123117}
    124118
     119static ALWAYS_INLINE bool isArraySlowInline(ExecState* exec, ProxyObject* proxy)
     120{
     121    VM& vm = exec->vm();
     122    auto scope = DECLARE_THROW_SCOPE(vm);
     123
     124    while (true) {
     125        if (proxy->isRevoked()) {
     126            throwTypeError(exec, scope, ASCIILiteral("Array.isArray cannot be called on a Proxy that has been revoked"));
     127            return false;
     128        }
     129        JSObject* argument = proxy->target();
     130
     131        if (argument->type() == ArrayType ||  argument->type() == DerivedArrayType)
     132            return true;
     133
     134        if (argument->type() != ProxyObjectType)
     135            return false;
     136
     137        proxy = jsCast<ProxyObject*>(argument);
     138    }
     139
     140    ASSERT_NOT_REACHED();
     141}
     142
     143bool isArraySlow(ExecState* exec, ProxyObject* argument)
     144{
     145    return isArraySlowInline(exec, argument);
     146}
     147
    125148// ES6 7.2.2
    126149// https://tc39.github.io/ecma262/#sec-isarray
    127 EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState* exec)
     150EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArraySlow(ExecState* exec)
    128151{
    129     return JSValue::encode(jsBoolean(isArray(exec, exec->argument(0))));
     152    ASSERT(jsDynamicCast<ProxyObject*>(exec->argument(0)));
     153    return JSValue::encode(jsBoolean(isArraySlowInline(exec, jsCast<ProxyObject*>(exec->uncheckedArgument(0)))));
    130154}
    131155
  • trunk/Source/JavaScriptCore/runtime/ArrayConstructor.h

    r205198 r206065  
    6565
    6666EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArrayConstructor(ExecState*);
     67EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArraySlow(ExecState*);
     68bool isArraySlow(ExecState*, ProxyObject* argument);
    6769
    6870// ES6 7.2.2
     
    7072inline bool isArray(ExecState* exec, JSValue argumentValue)
    7173{
    72     VM& vm = exec->vm();
    73     auto scope = DECLARE_THROW_SCOPE(vm);
    74 
    7574    if (!argumentValue.isObject())
    7675        return false;
    7776
    7877    JSObject* argument = jsCast<JSObject*>(argumentValue);
    79     while (true) {
    80         if (argument->inherits(JSArray::info()))
    81             return true;
     78    if (argument->type() == ArrayType || argument->type() == DerivedArrayType)
     79        return true;
    8280
    83         if (argument->type() != ProxyObjectType)
    84             return false;
    85 
    86         ProxyObject* proxy = jsCast<ProxyObject*>(argument);
    87         if (proxy->isRevoked()) {
    88             throwTypeError(exec, scope, ASCIILiteral("Array.isArray cannot be called on a Proxy that has been revoked"));
    89             return false;
    90         }
    91         argument = proxy->target();
    92     }
    93 
    94     ASSERT_NOT_REACHED();
     81    if (argument->type() != ProxyObjectType)
     82        return false;
     83    return isArraySlow(exec, jsCast<ProxyObject*>(argument));
    9584}
    9685
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.h

    r202125 r206065  
    4848    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    4949    {
    50         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
     50        return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
    5151    }
    5252
  • trunk/Source/JavaScriptCore/runtime/JSArray.h

    r205462 r206065  
    149149       
    150150protected:
     151    void finishCreation(VM& vm)
     152    {
     153        Base::finishCreation(vm);
     154        ASSERT_WITH_MESSAGE(type() == ArrayType || type() == DerivedArrayType, "Instance inheriting JSArray should have either ArrayType or DerivedArrayType");
     155    }
     156
    151157    static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
    152158
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r205856 r206065  
    687687    JSFunction* privateFuncThisNumberValue = JSFunction::create(vm, this, 0, String(), numberProtoFuncValueOf);
    688688    JSFunction* privateFuncIsArrayConstructor = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArrayConstructor);
     689    JSFunction* privateFuncIsArraySlow = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArraySlow);
    689690    JSFunction* privateFuncConcatMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncConcatMemcpy);
    690691    JSFunction* privateFuncAppendMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncAppendMemcpy);
     
    751752        GlobalPropertyInfo(vm.propertyNames->builtinNames().isMapPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncIsMap), DontEnum | DontDelete | ReadOnly),
    752753        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayPrivateName(), arrayConstructor->getDirect(vm, vm.propertyNames->isArray), DontEnum | DontDelete | ReadOnly),
     754        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArraySlowPrivateName(), privateFuncIsArraySlow, DontEnum | DontDelete | ReadOnly),
    753755        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayConstructorPrivateName(), privateFuncIsArrayConstructor, DontEnum | DontDelete | ReadOnly),
    754756        GlobalPropertyInfo(vm.propertyNames->builtinNames().concatMemcpyPrivateName(), privateFuncConcatMemcpy, DontEnum | DontDelete | ReadOnly),
  • trunk/Source/JavaScriptCore/runtime/JSType.h

    r205520 r206065  
    6161    ImpureProxyType,
    6262    WithScopeType,
    63     ArrayType,
    6463    DirectArgumentsType,
    6564    ScopedArgumentsType,
     65
     66    ArrayType,
     67    DerivedArrayType,
    6668
    6769    Int8ArrayType = 100,
  • trunk/Source/WebCore/ChangeLog

    r206062 r206065  
     12016-09-16  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DFG] Introduce IsCellWithType node and unify IsJSArray, IsRegExpObject and newly added IsProxyObject
     4        https://bugs.webkit.org/show_bug.cgi?id=162000
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * bridge/runtime_array.h:
     9        (JSC::RuntimeArray::createStructure):
     10
    1112016-09-16  Chris Dumez  <cdumez@apple.com>
    212
  • trunk/Source/WebCore/bridge/runtime_array.h

    r201703 r206065  
    7676    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    7777    {
    78         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
     78        return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
    7979    }
    8080
Note: See TracChangeset for help on using the changeset viewer.