Title: [206065] trunk
Revision
206065
Author
utatane....@gmail.com
Date
2016-09-16 23:32:50 -0700 (Fri, 16 Sep 2016)

Log 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/_javascript_Core:

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):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (206064 => 206065)


--- trunk/JSTests/ChangeLog	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/JSTests/ChangeLog	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1,5 +1,23 @@
 2016-09-16  Yusuke Suzuki  <utatane....@gmail.com>
 
+        [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.
+
+        * 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):
+
+2016-09-16  Yusuke Suzuki  <utatane....@gmail.com>
+
         Unreviewed, gardening test262 results
 
         Some tests are now passed with JSC, but marked as failed.

Added: trunk/JSTests/microbenchmarks/is-array-for-array.js (0 => 206065)


--- trunk/JSTests/microbenchmarks/is-array-for-array.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/is-array-for-array.js	2016-09-17 06:32:50 UTC (rev 206065)
@@ -0,0 +1,8 @@
+function isArray(array)
+{
+    return Array.isArray(array);
+}
+noInline(isArray);
+
+for (var i = 0; i < 1e5; ++i)
+    isArray([]);

Added: trunk/JSTests/microbenchmarks/is-array-for-mixed-case.js (0 => 206065)


--- trunk/JSTests/microbenchmarks/is-array-for-mixed-case.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/is-array-for-mixed-case.js	2016-09-17 06:32:50 UTC (rev 206065)
@@ -0,0 +1,22 @@
+function isArray(array)
+{
+    return Array.isArray(array);
+}
+noInline(isArray);
+
+let values = [
+    [ 0, false ],
+    [ [], true ],
+    [ {}, false ],
+    [ "Cappuccino", false ],
+    [ Symbol("Cocoa"), false ],
+    [ null, false ],
+    [ undefined, false ],
+]
+
+for (var i = 0; i < 1e4; ++i) {
+    for (let pair of values) {
+        if (isArray(pair[0]) != pair[1])
+            throw new Error(`bad value:${String(pair[1])}`);
+    }
+}

Added: trunk/JSTests/microbenchmarks/is-array-for-non-array-object.js (0 => 206065)


--- trunk/JSTests/microbenchmarks/is-array-for-non-array-object.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/is-array-for-non-array-object.js	2016-09-17 06:32:50 UTC (rev 206065)
@@ -0,0 +1,8 @@
+function isArray(array)
+{
+    return Array.isArray(array);
+}
+noInline(isArray);
+
+for (var i = 0; i < 1e5; ++i)
+    isArray({});

Added: trunk/JSTests/microbenchmarks/is-array-for-proxy.js (0 => 206065)


--- trunk/JSTests/microbenchmarks/is-array-for-proxy.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/is-array-for-proxy.js	2016-09-17 06:32:50 UTC (rev 206065)
@@ -0,0 +1,24 @@
+{
+    function isArray(array)
+    {
+        return Array.isArray(array);
+    }
+    noInline(isArray);
+    let proxy = new Proxy([], {});
+    for (let i = 0; i < 1e5; ++i) {
+        if (!isArray(proxy))
+            throw new Error(`bad error`);
+    }
+}
+{
+    function isArray(array)
+    {
+        return Array.isArray(array);
+    }
+    noInline(isArray);
+    let proxy = new Proxy({}, {});
+    for (let i = 0; i < 1e5; ++i) {
+        if (isArray(proxy))
+            throw new Error(`bad error`);
+    }
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (206064 => 206065)


--- trunk/Source/_javascript_Core/ChangeLog	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1,5 +1,179 @@
 2016-09-16  Yusuke Suzuki  <utatane....@gmail.com>
 
+        [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.
+
+        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:
+
+2016-09-16  Yusuke Suzuki  <utatane....@gmail.com>
+
         [DFG] Introduce ArrayUse
         https://bugs.webkit.org/show_bug.cgi?id=162063
 

Modified: trunk/Source/_javascript_Core/builtins/ArrayConstructor.js (206064 => 206065)


--- trunk/Source/_javascript_Core/builtins/ArrayConstructor.js	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/builtins/ArrayConstructor.js	2016-09-17 06:32:50 UTC (rev 206065)
@@ -102,3 +102,14 @@
     result.length = arrayLikeLength;
     return result;
 }
+
+function isArray(array)
+{
+    "use strict";
+
+    if (@isJSArray(array) || @isDerivedArray(array))
+        return true;
+    if (!@isProxyObject(array))
+        return false;
+    return @isArraySlow(array);
+}

Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (206064 => 206065)


--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -126,7 +126,7 @@
     macro(isBoundFunction) \
     macro(hasInstanceBoundFunction) \
     macro(instanceOf) \
-    macro(isArray) \
+    macro(isArraySlow) \
     macro(isArrayConstructor) \
     macro(isConstructor) \
     macro(isDerivedConstructor) \

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -43,6 +43,8 @@
     macro(assert) \
     macro(isObject) \
     macro(isJSArray) \
+    macro(isProxyObject) \
+    macro(isDerivedArray) \
     macro(tailCallForwardArguments) \
     macro(tryGetById) \
     macro(putByValDirect) \

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-09-17 06:32:50 UTC (rev 206065)
@@ -57,9 +57,11 @@
             { "name" : "op_is_number", "length" : 3 },
             { "name" : "op_is_string", "length" : 3 },
             { "name" : "op_is_jsarray", "length" : 3 },
+            { "name" : "op_is_proxy_object", "length" : 3 },
             { "name" : "op_is_object", "length" : 3 },
             { "name" : "op_is_object_or_null", "length" : 3 },
             { "name" : "op_is_function", "length" : 3 },
+            { "name" : "op_is_derived_array", "length" : 3 },
             { "name" : "op_in", "length" : 4 },
             { "name" : "op_get_array_length", "length" : 9 },
             { "name" : "op_get_by_id", "length" : 9  },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -165,9 +165,11 @@
     case op_is_number:
     case op_is_string:
     case op_is_jsarray:
+    case op_is_proxy_object:
     case op_is_object:
     case op_is_object_or_null:
     case op_is_function:
+    case op_is_derived_array:
     case op_to_number:
     case op_to_string:
     case op_negate:
@@ -398,9 +400,11 @@
     case op_is_number:
     case op_is_string:
     case op_is_jsarray:
+    case op_is_proxy_object:
     case op_is_object:
     case op_is_object_or_null:
     case op_is_function:
+    case op_is_derived_array:
     case op_in:
     case op_to_number:
     case op_to_string:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1110,6 +1110,10 @@
             printUnaryOp(out, exec, location, it, "is_jsarray");
             break;
         }
+        case op_is_proxy_object: {
+            printUnaryOp(out, exec, location, it, "is_proxy_object");
+            break;
+        }
         case op_is_object: {
             printUnaryOp(out, exec, location, it, "is_object");
             break;
@@ -1122,6 +1126,10 @@
             printUnaryOp(out, exec, location, it, "is_function");
             break;
         }
+        case op_is_derived_array: {
+            printUnaryOp(out, exec, location, it, "is_derived_array");
+            break;
+        }
         case op_in: {
             printBinaryOp(out, exec, location, it, "in");
             break;

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -35,6 +35,7 @@
 #include "JSFunction.h"
 #include "JSMap.h"
 #include "JSSet.h"
+#include "ProxyObject.h"
 #include "ScopedArguments.h"
 #include "StringObject.h"
 #include "ValueProfile.h"
@@ -148,6 +149,26 @@
                 myOut.print("Regexpobject");
             else
                 isTop = false;
+
+            if (value & SpecMapObject)
+                myOut.print("Mapobject");
+            else
+                isTop = false;
+
+            if (value & SpecSetObject)
+                myOut.print("Setobject");
+            else
+                isTop = false;
+
+            if (value & SpecProxyObject)
+                myOut.print("Proxyobject");
+            else
+                isTop = false;
+
+            if (value & SpecDerivedArray)
+                myOut.print("Derivedarray");
+            else
+                isTop = false;
         }
 
         if ((value & SpecString) == SpecString)
@@ -354,6 +375,9 @@
 
     if (classInfo == JSSet::info())
         return SpecSetObject;
+
+    if (classInfo == ProxyObject::info())
+        return SpecProxyObject;
     
     if (classInfo->isSubClassOf(JSFunction::info()))
         return SpecFunction;
@@ -373,6 +397,8 @@
         return SpecString;
     if (structure->typeInfo().type() == SymbolType)
         return SpecSymbol;
+    if (structure->typeInfo().type() == DerivedArrayType)
+        return SpecDerivedArray;
     return speculationFromClassInfo(structure->classInfo());
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -56,26 +56,28 @@
 static const SpeculatedType SpecScopedArguments    = 1ull << 13; // It's definitely a ScopedArguments object.
 static const SpeculatedType SpecStringObject       = 1ull << 14; // It's definitely a StringObject.
 static const SpeculatedType SpecRegExpObject       = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
-static const SpeculatedType SpecMapObject          = 1ull << 16; // It's definitely Map object (can it be a subclass? FIXME).
-static const SpeculatedType SpecSetObject          = 1ull << 17; // It's definitely s Set object (can it be a subclass? FIXME).
-static const SpeculatedType SpecObjectOther        = 1ull << 18; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
-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.
-static const SpeculatedType SpecStringIdent        = 1ull << 19; // It's definitely a JSString, and it's an identifier.
-static const SpeculatedType SpecStringVar          = 1ull << 20; // It's definitely a JSString, and it's not an identifier.
+static const SpeculatedType SpecMapObject          = 1ull << 16; // It's definitely a Map object or one of its subclasses.
+static const SpeculatedType SpecSetObject          = 1ull << 17; // It's definitely a Set object or one of its subclasses.
+static const SpeculatedType SpecProxyObject        = 1ull << 18; // It's definitely a Proxy object or one of its subclasses.
+static const SpeculatedType SpecDerivedArray       = 1ull << 19; // It's definitely a DerivedArray object.
+static const SpeculatedType SpecObjectOther        = 1ull << 20; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static 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.
+static const SpeculatedType SpecStringIdent        = 1ull << 21; // It's definitely a JSString, and it's an identifier.
+static const SpeculatedType SpecStringVar          = 1ull << 22; // It's definitely a JSString, and it's not an identifier.
 static const SpeculatedType SpecString             = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
-static const SpeculatedType SpecSymbol             = 1ull << 21; // It's definitely a Symbol.
-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
+static const SpeculatedType SpecSymbol             = 1ull << 23; // It's definitely a Symbol.
+static 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
 static const SpeculatedType SpecCell               = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell.
-static const SpeculatedType SpecBoolInt32          = 1ull << 23; // It's definitely an Int32 with value 0 or 1.
-static const SpeculatedType SpecNonBoolInt32       = 1ull << 24; // It's definitely an Int32 with value other than 0 or 1.
+static const SpeculatedType SpecBoolInt32          = 1ull << 25; // It's definitely an Int32 with value 0 or 1.
+static const SpeculatedType SpecNonBoolInt32       = 1ull << 26; // It's definitely an Int32 with value other than 0 or 1.
 static const SpeculatedType SpecInt32Only          = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
-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.
+static const SpeculatedType SpecInt52Only          = 1ull << 27; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
 static const SpeculatedType SpecAnyInt             = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
-static const SpeculatedType SpecAnyIntAsDouble     = 1ull << 26; // It's definitely an Int52 and it's inside a double.
-static const SpeculatedType SpecNonIntAsDouble     = 1ull << 27; // It's definitely not an Int52 but it's a real number and it's a double.
+static const SpeculatedType SpecAnyIntAsDouble     = 1ull << 28; // It's definitely an Int52 and it's inside a double.
+static const SpeculatedType SpecNonIntAsDouble     = 1ull << 29; // It's definitely not an Int52 but it's a real number and it's a double.
 static const SpeculatedType SpecDoubleReal         = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
-static const SpeculatedType SpecDoublePureNaN      = 1ull << 28; // It's definitely a NaN that is sae to tag (i.e. pure).
-static const SpeculatedType SpecDoubleImpureNaN    = 1ull << 29; // It's definitely a NaN that is unsafe to tag (i.e. impure).
+static const SpeculatedType SpecDoublePureNaN      = 1ull << 30; // It's definitely a NaN that is sae to tag (i.e. pure).
+static const SpeculatedType SpecDoubleImpureNaN    = 1ull << 31; // It's definitely a NaN that is unsafe to tag (i.e. impure).
 static const SpeculatedType SpecDoubleNaN          = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
 static const SpeculatedType SpecBytecodeDouble     = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
 static const SpeculatedType SpecFullDouble         = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double.
@@ -83,12 +85,12 @@
 static const SpeculatedType SpecFullRealNumber     = SpecAnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52.
 static const SpeculatedType SpecBytecodeNumber     = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
 static const SpeculatedType SpecFullNumber         = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
-static const SpeculatedType SpecBoolean            = 1ull << 30; // It's definitely a Boolean.
-static const SpeculatedType SpecOther              = 1ull << 31; // It's definitely either Null or Undefined.
+static const SpeculatedType SpecBoolean            = 1ull << 32; // It's definitely a Boolean.
+static const SpeculatedType SpecOther              = 1ull << 33; // It's definitely either Null or Undefined.
 static const SpeculatedType SpecMisc               = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
 static const SpeculatedType SpecHeapTop            = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
 static const SpeculatedType SpecPrimitive          = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc; // It's any non-Object JSValue.
-static const SpeculatedType SpecEmpty              = 1ull << 32; // It's definitely an empty value marker.
+static const SpeculatedType SpecEmpty              = 1ull << 34; // It's definitely an empty value marker.
 static 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.
 static const SpeculatedType SpecFullTop            = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
 
@@ -170,6 +172,16 @@
     return value == SpecFunction;
 }
 
+inline bool isProxyObjectSpeculation(SpeculatedType value)
+{
+    return value == SpecProxyObject;
+}
+
+inline bool isDerivedArraySpeculation(SpeculatedType value)
+{
+    return value == SpecDerivedArray;
+}
+
 inline bool isInt8ArraySpeculation(SpeculatedType value)
 {
     return value == SpecInt8Array;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -631,9 +631,11 @@
         RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
 
         RegisterID* emitIsJSArray(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_is_jsarray, dst, src); }
+        RegisterID* emitIsProxyObject(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_is_proxy_object, dst, src); }
         RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src);
+        RegisterID* emitIsDerivedArray(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_is_derived_array, dst, src); }
         void emitRequireObjectCoercible(RegisterID* value, const String& error);
 
         RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -946,6 +946,15 @@
     return generator.moveToDestinationIfNeeded(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> src = ""
+    ASSERT(!node->m_next);
+
+    return generator.moveToDestinationIfNeeded(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;
@@ -955,6 +964,15 @@
     return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> src = ""
+    ASSERT(!node->m_next);
+
+    return generator.moveToDestinationIfNeeded(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1010,7 +1010,6 @@
         break;
 
     case IsEmpty:
-    case IsJSArray:
     case IsUndefined:
     case IsBoolean:
     case IsNumber:
@@ -1018,14 +1017,14 @@
     case IsObject:
     case IsObjectOrNull:
     case IsFunction:
-    case IsRegExpObject:
+    case IsCellWithType:
     case IsTypedArrayView: {
         AbstractValue child = forNode(node->child1());
         if (child.value()) {
             bool constantWasSet = true;
             switch (node->op()) {
-            case IsJSArray:
-                setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == ArrayType));
+            case IsCellWithType:
+                setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
                 break;
             case IsUndefined:
                 setConstant(node, jsBoolean(
@@ -1075,9 +1074,6 @@
                 } else
                     setConstant(node, jsBoolean(false));
                 break;
-            case IsRegExpObject:
-                setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType));
-                break;
             case IsEmpty:
                 setConstant(node, jsBoolean(child.value().isEmpty()));
                 break;
@@ -1098,21 +1094,6 @@
         
         bool constantWasSet = false;
         switch (node->op()) {
-        case IsJSArray:
-            // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
-            if (!(child.m_type & ~SpecArray)) {
-                setConstant(node, jsBoolean(true));
-                constantWasSet = true;
-                break;
-            }
-
-            if (!(child.m_type & SpecObject)) {
-                setConstant(node, jsBoolean(false));
-                constantWasSet = true;
-                break;
-            }
-
-            break;
         case IsEmpty: {
             if (child.m_type && !(child.m_type & SpecEmpty)) {
                 setConstant(node, jsBoolean(false));
@@ -1241,14 +1222,13 @@
             }
             break;
 
-        case IsRegExpObject:
-            // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
-            if (!(child.m_type & ~SpecRegExpObject)) {
+        case IsCellWithType:
+            if (!(child.m_type & ~node->speculatedTypeForQuery())) {
                 setConstant(node, jsBoolean(true));
                 constantWasSet = true;
                 break;
             }
-            if (!(child.m_type & SpecObject)) {
+            if (!(child.m_type & node->speculatedTypeForQuery())) {
                 setConstant(node, jsBoolean(false));
                 constantWasSet = true;
                 break;

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -2366,7 +2366,7 @@
         ASSERT(argumentCountIncludingThis == 2);
 
         insertChecks();
-        Node* isRegExpObject = addToGraph(IsRegExpObject, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
+        Node* isRegExpObject = addToGraph(IsCellWithType, OpInfo(RegExpObjectType), OpInfo(SpecRegExpObject), get(virtualRegisterForArgument(1, registerOffset)));
         set(VirtualRegister(resultOperand), isRegExpObject);
         return true;
     }
@@ -3978,10 +3978,16 @@
 
         case op_is_jsarray: {
             Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsJSArray, value));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsCellWithType, OpInfo(ArrayType), OpInfo(SpecArray), value));
             NEXT_OPCODE(op_is_jsarray);
         }
 
+        case op_is_proxy_object: {
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsCellWithType, OpInfo(ProxyObjectType), OpInfo(SpecProxyObject), value));
+            NEXT_OPCODE(op_is_proxy_object);
+        }
+
         case op_is_object: {
             Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsObject, value));
@@ -4000,6 +4006,12 @@
             NEXT_OPCODE(op_is_function);
         }
 
+        case op_is_derived_array: {
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsCellWithType, OpInfo(DerivedArrayType), OpInfo(SpecDerivedArray), value));
+            NEXT_OPCODE(op_is_derived_array);
+        }
+
         case op_not: {
             Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, value));

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -142,9 +142,11 @@
     case op_is_number:
     case op_is_string:
     case op_is_jsarray:
+    case op_is_proxy_object:
     case op_is_object:
     case op_is_object_or_null:
     case op_is_function:
+    case op_is_derived_array:
     case op_not:
     case op_less:
     case op_lesseq:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -158,7 +158,6 @@
     case StringCharCodeAt:
     case CompareStrictEq:
     case CompareEqPtr:
-    case IsJSArray:
     case IsEmpty:
     case IsUndefined:
     case IsBoolean:
@@ -165,7 +164,6 @@
     case IsNumber:
     case IsString:
     case IsObject:
-    case IsRegExpObject:
     case IsTypedArrayView:
     case LogicalNot:
     case CheckInBounds:
@@ -215,6 +213,10 @@
         }
         return;
 
+    case IsCellWithType:
+        def(PureValue(node, node->queriedType()));
+        return;
+
     case BitAnd:
     case BitOr:
     case BitXor:

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -157,7 +157,6 @@
     case OverridesHasInstance:
     case InstanceOf:
     case InstanceOfCustom:
-    case IsJSArray:
     case IsEmpty:
     case IsUndefined:
     case IsBoolean:
@@ -166,7 +165,7 @@
     case IsObject:
     case IsObjectOrNull:
     case IsFunction:
-    case IsRegExpObject:
+    case IsCellWithType:
     case IsTypedArrayView:
     case TypeOf:
     case LogicalNot:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1417,15 +1417,10 @@
             }
             break;
 
-        case IsJSArray:
-            if (node->child1()->shouldSpeculateArray()) {
-                m_insertionSet.insertNode(
-                    m_indexInBlock, SpecNone, Check, node->origin,
-                    Edge(node->child1().node(), ArrayUse));
-                m_graph.convertToConstant(node, jsBoolean(true));
-                observeUseKindOnNode<ArrayUse>(node);
-            }
+        case IsCellWithType: {
+            fixupIsCellWithType(node);
             break;
+        }
 
         case GetEnumerableLength: {
             fixEdge<CellUse>(node->child1());
@@ -1639,7 +1634,6 @@
         case IsNumber:
         case IsObjectOrNull:
         case IsFunction:
-        case IsRegExpObject:
         case CreateDirectArguments:
         case CreateClonedArguments:
         case Jump:
@@ -1770,6 +1764,69 @@
         }
     }
 
+    void fixupIsCellWithType(Node* node)
+    {
+        switch (node->speculatedTypeForQuery()) {
+        case SpecProxyObject:
+            if (node->child1()->shouldSpeculateProxyObject()) {
+                m_insertionSet.insertNode(
+                    m_indexInBlock, SpecNone, Check, node->origin,
+                    Edge(node->child1().node(), ProxyObjectUse));
+                m_graph.convertToConstant(node, jsBoolean(true));
+                observeUseKindOnNode<ProxyObjectUse>(node);
+                return;
+            }
+            break;
+
+        case SpecRegExpObject:
+            if (node->child1()->shouldSpeculateRegExpObject()) {
+                m_insertionSet.insertNode(
+                    m_indexInBlock, SpecNone, Check, node->origin,
+                    Edge(node->child1().node(), RegExpObjectUse));
+                m_graph.convertToConstant(node, jsBoolean(true));
+                observeUseKindOnNode<RegExpObjectUse>(node);
+                return;
+            }
+            break;
+
+        case SpecArray:
+            if (node->child1()->shouldSpeculateArray()) {
+                m_insertionSet.insertNode(
+                    m_indexInBlock, SpecNone, Check, node->origin,
+                    Edge(node->child1().node(), ArrayUse));
+                m_graph.convertToConstant(node, jsBoolean(true));
+                observeUseKindOnNode<ArrayUse>(node);
+                return;
+            }
+            break;
+
+        case SpecDerivedArray:
+            if (node->child1()->shouldSpeculateDerivedArray()) {
+                m_insertionSet.insertNode(
+                    m_indexInBlock, SpecNone, Check, node->origin,
+                    Edge(node->child1().node(), DerivedArrayUse));
+                m_graph.convertToConstant(node, jsBoolean(true));
+                observeUseKindOnNode<DerivedArrayUse>(node);
+                return;
+            }
+            break;
+        }
+
+        if (node->child1()->shouldSpeculateCell()) {
+            fixEdge<CellUse>(node->child1());
+            return;
+        }
+
+        if (node->child1()->shouldSpeculateNotCell()) {
+            m_insertionSet.insertNode(
+                m_indexInBlock, SpecNone, Check, node->origin,
+                Edge(node->child1().node(), NotCellUse));
+            m_graph.convertToConstant(node, jsBoolean(false));
+            observeUseKindOnNode<NotCellUse>(node);
+            return;
+        }
+    }
+
     void fixupToThis(Node* node)
     {
         ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -267,6 +267,8 @@
             }
         }
     }
+    if (node->hasSpeculatedTypeForQuery())
+        out.print(comma, SpeculationDump(node->speculatedTypeForQuery()));
     if (node->hasStorageAccessData()) {
         StorageAccessData& storageAccessData = node->storageAccessData();
         out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1160,6 +1160,27 @@
         ASSERT(hasLoadVarargsData());
         return m_opInfo.as<LoadVarargsData*>();
     }
+
+    bool hasQueriedType()
+    {
+        return op() == IsCellWithType;
+    }
+
+    JSType queriedType()
+    {
+        static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
+        return static_cast<JSType>(m_opInfo.as<uint32_t>());
+    }
+
+    bool hasSpeculatedTypeForQuery()
+    {
+        return op() == IsCellWithType;
+    }
+
+    SpeculatedType speculatedTypeForQuery()
+    {
+        return m_opInfo2.as<SpeculatedType>();
+    }
     
     bool hasResult()
     {
@@ -2059,6 +2080,16 @@
     {
         return isArraySpeculation(prediction());
     }
+
+    bool shouldSpeculateProxyObject()
+    {
+        return isProxyObjectSpeculation(prediction());
+    }
+
+    bool shouldSpeculateDerivedArray()
+    {
+        return isDerivedArraySpeculation(prediction());
+    }
     
     bool shouldSpeculateDirectArguments()
     {

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -309,7 +309,7 @@
     macro(InstanceOf, NodeResultBoolean) \
     macro(InstanceOfCustom, NodeMustGenerate | NodeResultBoolean) \
     \
-    macro(IsJSArray, NodeResultBoolean) \
+    macro(IsCellWithType, NodeResultBoolean) \
     macro(IsEmpty, NodeResultBoolean) \
     macro(IsUndefined, NodeResultBoolean) \
     macro(IsBoolean, NodeResultBoolean) \
@@ -318,7 +318,6 @@
     macro(IsObject, NodeResultBoolean) \
     macro(IsObjectOrNull, NodeResultBoolean) \
     macro(IsFunction, NodeResultBoolean) \
-    macro(IsRegExpObject, NodeResultBoolean) \
     macro(IsTypedArrayView, NodeResultBoolean) \
     macro(TypeOf, NodeResultJS) \
     macro(LogicalNot, NodeResultBoolean) \

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -793,7 +793,6 @@
         case OverridesHasInstance:
         case InstanceOf:
         case InstanceOfCustom:
-        case IsJSArray:
         case IsEmpty:
         case IsUndefined:
         case IsBoolean:
@@ -802,7 +801,7 @@
         case IsObject:
         case IsObjectOrNull:
         case IsFunction:
-        case IsRegExpObject:
+        case IsCellWithType:
         case IsTypedArrayView: {
             setPrediction(SpecBoolean);
             break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -59,6 +59,8 @@
         case FunctionUse:
         case FinalObjectUse:
         case RegExpObjectUse:
+        case ProxyObjectUse:
+        case DerivedArrayUse:
         case MapObjectUse:
         case SetObjectUse:
         case ObjectOrOtherUse:
@@ -261,7 +263,6 @@
     case OverridesHasInstance:
     case InstanceOf:
     case InstanceOfCustom:
-    case IsJSArray:
     case IsEmpty:
     case IsUndefined:
     case IsBoolean:
@@ -270,7 +271,7 @@
     case IsObject:
     case IsObjectOrNull:
     case IsFunction:
-    case IsRegExpObject:
+    case IsCellWithType:
     case IsTypedArrayView:
     case TypeOf:
     case LogicalNot:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -3603,52 +3603,57 @@
     unblessedBooleanResult(resultGPR, node);
 }
 
-void SpeculativeJIT::compileIsJSArray(Node* node)
+void SpeculativeJIT::compileIsCellWithType(Node* node)
 {
-    JSValueOperand value(this, node->child1());
-    GPRFlushedCallResult result(this);
+    switch (node->child1().useKind()) {
+    case UntypedUse: {
+        JSValueOperand value(this, node->child1());
+#if USE(JSVALUE64)
+        GPRTemporary result(this, Reuse, value);
+#else
+        GPRTemporary result(this, Reuse, value, PayloadWord);
+#endif
 
-    JSValueRegs valueRegs = value.jsValueRegs();
-    GPRReg resultGPR = result.gpr();
+        JSValueRegs valueRegs = value.jsValueRegs();
+        GPRReg resultGPR = result.gpr();
 
-    JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
+        JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
 
-    m_jit.compare8(JITCompiler::Equal,
-        JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
-        TrustedImm32(ArrayType),
-        resultGPR);
-    blessBoolean(resultGPR);
-    JITCompiler::Jump done = m_jit.jump();
+        m_jit.compare8(JITCompiler::Equal,
+            JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
+            TrustedImm32(node->queriedType()),
+            resultGPR);
+        blessBoolean(resultGPR);
+        JITCompiler::Jump done = m_jit.jump();
 
-    isNotCell.link(&m_jit);
-    moveFalseTo(resultGPR);
+        isNotCell.link(&m_jit);
+        moveFalseTo(resultGPR);
 
-    done.link(&m_jit);
-    blessedBooleanResult(resultGPR, node);
-}
+        done.link(&m_jit);
+        blessedBooleanResult(resultGPR, node);
+        return;
+    }
 
-void SpeculativeJIT::compileIsRegExpObject(Node* node)
-{
-    JSValueOperand value(this, node->child1());
-    GPRFlushedCallResult result(this);
+    case CellUse: {
+        SpeculateCellOperand cell(this, node->child1());
+        GPRTemporary result(this, Reuse, cell);
 
-    JSValueRegs valueRegs = value.jsValueRegs();
-    GPRReg resultGPR = result.gpr();
+        GPRReg cellGPR = cell.gpr();
+        GPRReg resultGPR = result.gpr();
 
-    JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
+        m_jit.compare8(JITCompiler::Equal,
+            JITCompiler::Address(cellGPR, JSCell::typeInfoTypeOffset()),
+            TrustedImm32(node->queriedType()),
+            resultGPR);
+        blessBoolean(resultGPR);
+        blessedBooleanResult(resultGPR, node);
+        return;
+    }
 
-    m_jit.compare8(JITCompiler::Equal,
-        JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
-        TrustedImm32(RegExpObjectType),
-        resultGPR);
-    blessBoolean(resultGPR);
-    JITCompiler::Jump done = m_jit.jump();
-
-    isNotCell.link(&m_jit);
-    moveFalseTo(resultGPR);
-
-    done.link(&m_jit);
-    blessedBooleanResult(resultGPR, node);
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
 }
 
 void SpeculativeJIT::compileIsTypedArrayView(Node* node)
@@ -7408,6 +7413,34 @@
     speculateArray(edge, operand.gpr());
 }
 
+void SpeculativeJIT::speculateProxyObject(Edge edge, GPRReg cell)
+{
+    speculateCellType(edge, cell, SpecProxyObject, ProxyObjectType);
+}
+
+void SpeculativeJIT::speculateProxyObject(Edge edge)
+{
+    if (!needsTypeCheck(edge, SpecProxyObject))
+        return;
+
+    SpeculateCellOperand operand(this, edge);
+    speculateProxyObject(edge, operand.gpr());
+}
+
+void SpeculativeJIT::speculateDerivedArray(Edge edge, GPRReg cell)
+{
+    speculateCellType(edge, cell, SpecDerivedArray, DerivedArrayType);
+}
+
+void SpeculativeJIT::speculateDerivedArray(Edge edge)
+{
+    if (!needsTypeCheck(edge, SpecDerivedArray))
+        return;
+
+    SpeculateCellOperand operand(this, edge);
+    speculateDerivedArray(edge, operand.gpr());
+}
+
 void SpeculativeJIT::speculateMapObject(Edge edge, GPRReg cell)
 {
     speculateCellType(edge, cell, SpecMapObject, JSMapType);
@@ -7726,6 +7759,12 @@
     case RegExpObjectUse:
         speculateRegExpObject(edge);
         break;
+    case ProxyObjectUse:
+        speculateProxyObject(edge);
+        break;
+    case DerivedArrayUse:
+        speculateDerivedArray(edge);
+        break;
     case MapObjectUse:
         speculateMapObject(edge);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -755,8 +755,7 @@
     void compileInstanceOf(Node*);
     void compileInstanceOfCustom(Node*);
 
-    void compileIsJSArray(Node*);
-    void compileIsRegExpObject(Node*);
+    void compileIsCellWithType(Node*);
     void compileIsTypedArrayView(Node*);
 
     void emitCall(Node*);
@@ -2680,6 +2679,10 @@
     void speculateFinalObject(Edge);
     void speculateRegExpObject(Edge, GPRReg cell);
     void speculateRegExpObject(Edge);
+    void speculateProxyObject(Edge, GPRReg cell);
+    void speculateProxyObject(Edge);
+    void speculateDerivedArray(Edge, GPRReg cell);
+    void speculateDerivedArray(Edge);
     void speculateMapObject(Edge);
     void speculateMapObject(Edge, GPRReg cell);
     void speculateSetObject(Edge);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -4660,11 +4660,6 @@
         break;
     }
 
-    case IsJSArray: {
-        compileIsJSArray(node);
-        break;
-    }
-
     case IsObject: {
         JSValueOperand value(this, node->child1());
         GPRTemporary result(this, Reuse, value, TagWord);
@@ -4695,8 +4690,8 @@
         break;
     }
 
-    case IsRegExpObject: {
-        compileIsRegExpObject(node);
+    case IsCellWithType: {
+        compileIsCellWithType(node);
         break;
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -4632,11 +4632,6 @@
         break;
     }
 
-    case IsJSArray: {
-        compileIsJSArray(node);
-        break;
-    }
-
     case MapHash: {
         JSValueOperand input(this, node->child1());
         GPRTemporary temp(this);
@@ -4830,8 +4825,8 @@
         break;
     }
 
-    case IsRegExpObject: {
-        compileIsRegExpObject(node);
+    case IsCellWithType: {
+        compileIsCellWithType(node);
         break;
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -97,6 +97,12 @@
     case RegExpObjectUse:
         out.print("RegExpObject");
         return;
+    case ProxyObjectUse:
+        out.print("ProxyObject");
+        return;
+    case DerivedArrayUse:
+        out.print("DerivedArray");
+        return;
     case MapObjectUse:
         out.print("MapObjectUse");
         return;

Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.h (206064 => 206065)


--- trunk/Source/_javascript_Core/dfg/DFGUseKind.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -57,6 +57,8 @@
     FunctionUse,
     FinalObjectUse,
     RegExpObjectUse,
+    ProxyObjectUse,
+    DerivedArrayUse,
     ObjectOrOtherUse,
     StringIdentUse,
     StringUse,
@@ -126,6 +128,10 @@
         return SpecFinalObject;
     case RegExpObjectUse:
         return SpecRegExpObject;
+    case ProxyObjectUse:
+        return SpecProxyObject;
+    case DerivedArrayUse:
+        return SpecDerivedArray;
     case ObjectOrOtherUse:
         return SpecObject | SpecOther;
     case StringIdentUse:
@@ -225,6 +231,8 @@
     case FunctionUse:
     case FinalObjectUse:
     case RegExpObjectUse:
+    case ProxyObjectUse:
+    case DerivedArrayUse:
     case StringIdentUse:
     case StringUse:
     case KnownStringUse:

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -181,7 +181,7 @@
     case ThrowReferenceError:
     case Unreachable:
     case In:
-    case IsJSArray:
+    case IsCellWithType:
     case MapHash:
     case GetMapBucket:
     case LoadFromJSMapBucket:
@@ -194,7 +194,6 @@
     case IsObject:
     case IsObjectOrNull:
     case IsFunction:
-    case IsRegExpObject:
     case IsTypedArrayView:
     case CheckTypeInfoFlags:
     case OverridesHasInstance:
@@ -436,6 +435,8 @@
                 case SetObjectUse:
                 case FinalObjectUse:
                 case RegExpObjectUse:
+                case ProxyObjectUse:
+                case DerivedArrayUse:
                 case NotCellUse:
                 case OtherUse:
                 case MiscUse:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -899,8 +899,8 @@
         case IsString:
             compileIsString();
             break;
-        case IsJSArray:
-            compileIsJSArray();
+        case IsCellWithType:
+            compileIsCellWithType();
             break;
         case MapHash:
             compileMapHash();
@@ -923,9 +923,6 @@
         case IsFunction:
             compileIsFunction();
             break;
-        case IsRegExpObject:
-            compileIsRegExpObject();
-            break;
         case IsTypedArrayView:
             compileIsTypedArrayView();
             break;
@@ -6286,23 +6283,28 @@
         setBoolean(m_out.phi(Int32, notCellResult, cellResult));
     }
 
-    void compileIsJSArray()
+    void compileIsCellWithType()
     {
-        LValue value = lowJSValue(m_node->child1());
+        if (m_node->child1().useKind() == UntypedUse) {
+            LValue value = lowJSValue(m_node->child1());
 
-        LBasicBlock isCellCase = m_out.newBlock();
-        LBasicBlock continuation = m_out.newBlock();
+            LBasicBlock isCellCase = m_out.newBlock();
+            LBasicBlock continuation = m_out.newBlock();
 
-        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
-        m_out.branch(
-            isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
+            ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
+            m_out.branch(
+                isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
 
-        LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
-        ValueFromBlock cellResult = m_out.anchor(isArray(value, provenType(m_node->child1())));
-        m_out.jump(continuation);
+            LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
+            ValueFromBlock cellResult = m_out.anchor(isCellWithType(value, m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
+            m_out.jump(continuation);
 
-        m_out.appendTo(continuation, lastNext);
-        setBoolean(m_out.phi(Int32, notCellResult, cellResult));
+            m_out.appendTo(continuation, lastNext);
+            setBoolean(m_out.phi(Int32, notCellResult, cellResult));
+        } else {
+            ASSERT(m_node->child1().useKind() == CellUse);
+            setBoolean(isCellWithType(lowCell(m_node->child1()), m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
+        }
     }
 
     void compileIsObject()
@@ -6647,25 +6649,6 @@
         setBoolean(result);
     }
 
-    void compileIsRegExpObject()
-    {
-        LValue value = lowJSValue(m_node->child1());
-
-        LBasicBlock isCellCase = m_out.newBlock();
-        LBasicBlock continuation = m_out.newBlock();
-
-        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
-        m_out.branch(
-            isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
-
-        LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
-        ValueFromBlock cellResult = m_out.anchor(isRegExpObject(value, provenType(m_node->child1())));
-        m_out.jump(continuation);
-
-        m_out.appendTo(continuation, lastNext);
-        setBoolean(m_out.phi(Int32, notCellResult, cellResult));
-    }
-
     void compileIsTypedArrayView()
     {
         LValue value = lowJSValue(m_node->child1());
@@ -10691,6 +10674,12 @@
         case RegExpObjectUse:
             speculateRegExpObject(edge);
             break;
+        case ProxyObjectUse:
+            speculateProxyObject(edge);
+            break;
+        case DerivedArrayUse:
+            speculateDerivedArray(edge);
+            break;
         case MapObjectUse:
             speculateMapObject(edge);
             break;
@@ -10786,13 +10775,13 @@
         jsValueToStrictInt52(edge, lowJSValue(edge, ManualOperandSpeculation));
     }
 
-    LValue isArray(LValue cell, SpeculatedType type = SpecFullTop)
+    LValue isCellWithType(LValue cell, JSType queriedType, SpeculatedType speculatedTypeForQuery, SpeculatedType type = SpecFullTop)
     {
-        if (LValue proven = isProvenValue(type & SpecCell, SpecArray))
+        if (LValue proven = isProvenValue(type & SpecCell, speculatedTypeForQuery))
             return proven;
         return m_out.equal(
             m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
-            m_out.constInt32(ArrayType));
+            m_out.constInt32(queriedType));
     }
 
     LValue isTypedArrayView(LValue cell, SpeculatedType type = SpecFullTop)
@@ -10933,15 +10922,6 @@
             m_out.constInt32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData));
     }
 
-    LValue isRegExpObject(LValue cell, SpeculatedType type = SpecFullTop)
-    {
-        if (LValue proven = isProvenValue(type & SpecCell, SpecRegExpObject))
-            return proven;
-        return m_out.equal(
-            m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
-            m_out.constInt32(RegExpObjectType));
-    }
-
     LValue isType(LValue cell, JSType type)
     {
         return m_out.equal(
@@ -11037,6 +11017,28 @@
         speculateRegExpObject(edge, lowCell(edge));
     }
 
+    void speculateProxyObject(Edge edge, LValue cell)
+    {
+        FTL_TYPE_CHECK(
+            jsValueValue(cell), edge, SpecProxyObject, isNotType(cell, ProxyObjectType));
+    }
+
+    void speculateProxyObject(Edge edge)
+    {
+        speculateProxyObject(edge, lowCell(edge));
+    }
+
+    void speculateDerivedArray(Edge edge, LValue cell)
+    {
+        FTL_TYPE_CHECK(
+            jsValueValue(cell), edge, SpecDerivedArray, isNotType(cell, DerivedArrayType));
+    }
+
+    void speculateDerivedArray(Edge edge)
+    {
+        speculateDerivedArray(edge, lowCell(edge));
+    }
+
     void speculateMapObject(Edge edge, LValue cell)
     {
         FTL_TYPE_CHECK(

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -270,7 +270,9 @@
         DEFINE_OP(op_is_number)
         DEFINE_OP(op_is_string)
         DEFINE_OP(op_is_jsarray)
+        DEFINE_OP(op_is_proxy_object)
         DEFINE_OP(op_is_object)
+        DEFINE_OP(op_is_derived_array)
         DEFINE_OP(op_jeq_null)
         DEFINE_OP(op_jfalse)
         DEFINE_OP(op_jmp)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (206064 => 206065)


--- trunk/Source/_javascript_Core/jit/JIT.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -401,6 +401,8 @@
         int32_t getOperandConstantInt(int src);
         double getOperandConstantDouble(int src);
 
+        void emitIsCellWithType(Instruction*, JSType);
+
 #if USE(JSVALUE32_64)
         bool getOperandConstantInt(int op1, int op2, int& op, int32_t& constant);
 
@@ -516,7 +518,9 @@
         void emit_op_is_number(Instruction*);
         void emit_op_is_string(Instruction*);
         void emit_op_is_jsarray(Instruction*);
+        void emit_op_is_proxy_object(Instruction*);
         void emit_op_is_object(Instruction*);
+        void emit_op_is_derived_array(Instruction*);
         void emit_op_jeq_null(Instruction*);
         void emit_op_jfalse(Instruction*);
         void emit_op_jmp(Instruction*);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -243,42 +243,43 @@
     emitPutVirtualRegister(dst);
 }
 
-void JIT::emit_op_is_string(Instruction* currentInstruction)
+void JIT::emitIsCellWithType(Instruction* currentInstruction, JSType type)
 {
     int dst = currentInstruction[1].u.operand;
     int value = currentInstruction[2].u.operand;
-    
+
     emitGetVirtualRegister(value, regT0);
     Jump isNotCell = emitJumpIfNotJSCell(regT0);
-    
-    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType), regT0);
+
+    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(type), regT0);
     emitTagBool(regT0);
     Jump done = jump();
-    
+
     isNotCell.link(this);
     move(TrustedImm32(ValueFalse), regT0);
-    
+
     done.link(this);
     emitPutVirtualRegister(dst);
 }
 
+void JIT::emit_op_is_string(Instruction* currentInstruction)
+{
+    emitIsCellWithType(currentInstruction, StringType);
+}
+
 void JIT::emit_op_is_jsarray(Instruction* currentInstruction)
 {
-    int dst = currentInstruction[1].u.operand;
-    int value = currentInstruction[2].u.operand;
+    emitIsCellWithType(currentInstruction, ArrayType);
+}
 
-    emitGetVirtualRegister(value, regT0);
-    Jump isNotCell = emitJumpIfNotJSCell(regT0);
+void JIT::emit_op_is_proxy_object(Instruction* currentInstruction)
+{
+    emitIsCellWithType(currentInstruction, ProxyObjectType);
+}
 
-    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ArrayType), regT0);
-    emitTagBool(regT0);
-    Jump done = jump();
-
-    isNotCell.link(this);
-    move(TrustedImm32(ValueFalse), regT0);
-
-    done.link(this);
-    emitPutVirtualRegister(dst);
+void JIT::emit_op_is_derived_array(Instruction* currentInstruction)
+{
+    emitIsCellWithType(currentInstruction, DerivedArrayType);
 }
 
 void JIT::emit_op_is_object(Instruction* currentInstruction)

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -354,40 +354,42 @@
     emitStoreBool(dst, regT0);
 }
 
-void JIT::emit_op_is_string(Instruction* currentInstruction)
+void JIT::emitIsCellWithType(Instruction* currentInstruction, JSType type)
 {
     int dst = currentInstruction[1].u.operand;
     int value = currentInstruction[2].u.operand;
-    
+
     emitLoad(value, regT1, regT0);
     Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
-    
-    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType), regT0);
+
+    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(type), regT0);
     Jump done = jump();
-    
+
     isNotCell.link(this);
     move(TrustedImm32(0), regT0);
-    
+
     done.link(this);
     emitStoreBool(dst, regT0);
 }
 
+void JIT::emit_op_is_string(Instruction* currentInstruction)
+{
+    emitIsCellWithType(currentInstruction, StringType);
+}
+
 void JIT::emit_op_is_jsarray(Instruction* currentInstruction)
 {
-    int dst = currentInstruction[1].u.operand;
-    int value = currentInstruction[2].u.operand;
+    emitIsCellWithType(currentInstruction, ArrayType);
+}
 
-    emitLoad(value, regT1, regT0);
-    Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+void JIT::emit_op_is_proxy_object(Instruction* currentInstruction)
+{
+    emitIsCellWithType(currentInstruction, ProxyObjectType);
+}
 
-    compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ArrayType), regT0);
-    Jump done = jump();
-
-    isNotCell.link(this);
-    move(TrustedImm32(0), regT0);
-
-    done.link(this);
-    emitStoreBool(dst, regT0);
+void JIT::emit_op_is_derived_array(Instruction* currentInstruction)
+{
+    emitIsCellWithType(currentInstruction, DerivedArrayType);
 }
 
 void JIT::emit_op_is_object(Instruction* currentInstruction)

Modified: trunk/Source/_javascript_Core/jsc.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/jsc.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/jsc.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -455,7 +455,7 @@
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
+        return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
     }
 
 protected:

Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/llint/LLIntData.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -159,7 +159,9 @@
     STATIC_ASSERT(ObjectType == 20);
     STATIC_ASSERT(FinalObjectType == 21);
     STATIC_ASSERT(JSFunctionType == 23);
-    STATIC_ASSERT(ArrayType == 29);
+    STATIC_ASSERT(ArrayType == 31);
+    STATIC_ASSERT(DerivedArrayType == 32);
+    STATIC_ASSERT(ProxyObjectType == 116);
     STATIC_ASSERT(Int8ArrayType == 100);
     STATIC_ASSERT(Int16ArrayType == 101);
     STATIC_ASSERT(Int32ArrayType == 102);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (206064 => 206065)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-09-17 06:32:50 UTC (rev 206065)
@@ -346,7 +346,9 @@
 const ObjectType = 20
 const FinalObjectType = 21
 const JSFunctionType = 23
-const ArrayType = 29
+const ArrayType = 31
+const DerivedArrayType = 32
+const ProxyObjectType = 116
 
 # The typed array types need to be numbered in a particular order because of the manually written
 # switch statement in get_by_val and put_by_val.

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (206064 => 206065)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1257,36 +1257,41 @@
     dispatch(3)
 
 
-_llint_op_is_string:
-    traceExecution()
+macro isCellWithType(type)
     loadi 8[PC], t1
     loadi 4[PC], t2
     loadConstantOrVariable(t1, t0, t3)
     storei BooleanTag, TagOffset[cfr, t2, 8]
-    bineq t0, CellTag, .opIsStringNotCell
-    cbeq JSCell::m_type[t3], StringType, t1
+    bineq t0, CellTag, .notCellCase
+    cbeq JSCell::m_type[t3], type, t1
     storei t1, PayloadOffset[cfr, t2, 8]
     dispatch(3)
-.opIsStringNotCell:
+.notCellCase:
     storep 0, PayloadOffset[cfr, t2, 8]
     dispatch(3)
+end
 
 
+_llint_op_is_string:
+    traceExecution()
+    isCellWithType(StringType)
+
+
 _llint_op_is_jsarray:
     traceExecution()
-    loadi 8[PC], t1
-    loadi 4[PC], t2
-    loadConstantOrVariable(t1, t0, t3)
-    storei BooleanTag, TagOffset[cfr, t2, 8]
-    bineq t0, CellTag, .opIsJSArrayNotCell
-    cbeq JSCell::m_type[t3], ArrayType, t1
-    storei t1, PayloadOffset[cfr, t2, 8]
-    dispatch(3)
-.opIsJSArrayNotCell:
-    storep 0, PayloadOffset[cfr, t2, 8]
-    dispatch(3)
+    isCellWithType(ArrayType)
 
 
+_llint_op_is_proxy_object:
+    traceExecution()
+    isCellWithType(ProxyObjectType)
+
+
+_llint_op_is_derived_array:
+    traceExecution()
+    isCellWithType(DerivedArrayType)
+
+
 _llint_op_is_object:
     traceExecution()
     loadi 8[PC], t1

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (206064 => 206065)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1146,36 +1146,41 @@
     dispatch(3)
 
 
-_llint_op_is_string:
-    traceExecution()
+macro isCellWithType(type)
     loadisFromInstruction(2, t1)
     loadisFromInstruction(1, t2)
     loadConstantOrVariable(t1, t0)
-    btqnz t0, tagMask, .opIsStringNotCell
-    cbeq JSCell::m_type[t0], StringType, t1
+    btqnz t0, tagMask, .notCellCase
+    cbeq JSCell::m_type[t0], type, t1
     orq ValueFalse, t1
     storeq t1, [cfr, t2, 8]
     dispatch(3)
-.opIsStringNotCell:
+.notCellCase:
     storeq ValueFalse, [cfr, t2, 8]
     dispatch(3)
+end
 
 
+_llint_op_is_string:
+    traceExecution()
+    isCellWithType(StringType)
+
+
 _llint_op_is_jsarray:
     traceExecution()
-    loadisFromInstruction(2, t1)
-    loadisFromInstruction(1, t2)
-    loadConstantOrVariable(t1, t0)
-    btqnz t0, tagMask, .opIsJSArrayNotCell
-    cbeq JSCell::m_type[t0], ArrayType, t1
-    orq ValueFalse, t1
-    storeq t1, [cfr, t2, 8]
-    dispatch(3)
-.opIsJSArrayNotCell:
-    storeq ValueFalse, [cfr, t2, 8]
-    dispatch(3)
+    isCellWithType(ArrayType)
 
 
+_llint_op_is_proxy_object:
+    traceExecution()
+    isCellWithType(ProxyObjectType)
+
+
+_llint_op_is_derived_array:
+    traceExecution()
+    isCellWithType(DerivedArrayType)
+
+
 _llint_op_is_object:
     traceExecution()
     loadisFromInstruction(2, t1)

Modified: trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -35,12 +35,6 @@
 #include "ProxyObject.h"
 #include "JSCInlines.h"
 
-namespace JSC {
-
-static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*);
-
-}
-
 #include "ArrayConstructor.lut.h"
 
 namespace JSC {
@@ -67,7 +61,7 @@
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
     putDirectNonIndexAccessor(vm, vm.propertyNames->speciesSymbol, speciesSymbol, Accessor | ReadOnly | DontEnum);
-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArray, DontEnum, 1);
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArrayCodeGenerator, DontEnum);
 }
 
 // ------------------------------ Functions ---------------------------
@@ -122,11 +116,41 @@
     return CallType::Host;
 }
 
+static ALWAYS_INLINE bool isArraySlowInline(ExecState* exec, ProxyObject* proxy)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    while (true) {
+        if (proxy->isRevoked()) {
+            throwTypeError(exec, scope, ASCIILiteral("Array.isArray cannot be called on a Proxy that has been revoked"));
+            return false;
+        }
+        JSObject* argument = proxy->target();
+
+        if (argument->type() == ArrayType ||  argument->type() == DerivedArrayType)
+            return true;
+
+        if (argument->type() != ProxyObjectType)
+            return false;
+
+        proxy = jsCast<ProxyObject*>(argument);
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
+bool isArraySlow(ExecState* exec, ProxyObject* argument)
+{
+    return isArraySlowInline(exec, argument);
+}
+
 // ES6 7.2.2
 // https://tc39.github.io/ecma262/#sec-isarray
-EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState* exec)
+EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArraySlow(ExecState* exec)
 {
-    return JSValue::encode(jsBoolean(isArray(exec, exec->argument(0))));
+    ASSERT(jsDynamicCast<ProxyObject*>(exec->argument(0)));
+    return JSValue::encode(jsBoolean(isArraySlowInline(exec, jsCast<ProxyObject*>(exec->uncheckedArgument(0)))));
 }
 
 EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArrayConstructor(ExecState* exec)

Modified: trunk/Source/_javascript_Core/runtime/ArrayConstructor.h (206064 => 206065)


--- trunk/Source/_javascript_Core/runtime/ArrayConstructor.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/runtime/ArrayConstructor.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -64,34 +64,23 @@
 JSValue constructArrayWithSizeQuirk(ExecState*, ArrayAllocationProfile*, JSGlobalObject*, JSValue length, JSValue prototype = JSValue());
 
 EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArrayConstructor(ExecState*);
+EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArraySlow(ExecState*);
+bool isArraySlow(ExecState*, ProxyObject* argument);
 
 // ES6 7.2.2
 // https://tc39.github.io/ecma262/#sec-isarray
 inline bool isArray(ExecState* exec, JSValue argumentValue)
 {
-    VM& vm = exec->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
     if (!argumentValue.isObject())
         return false;
 
     JSObject* argument = jsCast<JSObject*>(argumentValue);
-    while (true) {
-        if (argument->inherits(JSArray::info()))
-            return true;
+    if (argument->type() == ArrayType || argument->type() == DerivedArrayType)
+        return true;
 
-        if (argument->type() != ProxyObjectType)
-            return false;
-
-        ProxyObject* proxy = jsCast<ProxyObject*>(argument);
-        if (proxy->isRevoked()) {
-            throwTypeError(exec, scope, ASCIILiteral("Array.isArray cannot be called on a Proxy that has been revoked"));
-            return false;
-        }
-        argument = proxy->target();
-    }
-
-    ASSERT_NOT_REACHED();
+    if (argument->type() != ProxyObjectType)
+        return false;
+    return isArraySlow(exec, jsCast<ProxyObject*>(argument));
 }
 
 inline bool isArrayConstructor(JSValue argumentValue)

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.h (206064 => 206065)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -47,7 +47,7 @@
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
+        return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
     }
 
     SpeciesWatchpointStatus speciesWatchpointStatus() const { return m_speciesWatchpointStatus; }

Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (206064 => 206065)


--- trunk/Source/_javascript_Core/runtime/JSArray.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -148,6 +148,12 @@
     }
         
 protected:
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+        ASSERT_WITH_MESSAGE(type() == ArrayType || type() == DerivedArrayType, "Instance inheriting JSArray should have either ArrayType or DerivedArrayType");
+    }
+
     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
 
     static bool deleteProperty(JSCell*, ExecState*, PropertyName);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (206064 => 206065)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-09-17 06:32:50 UTC (rev 206065)
@@ -686,6 +686,7 @@
     JSFunction* privateFuncThisTimeValue = JSFunction::create(vm, this, 0, String(), dateProtoFuncGetTime);
     JSFunction* privateFuncThisNumberValue = JSFunction::create(vm, this, 0, String(), numberProtoFuncValueOf);
     JSFunction* privateFuncIsArrayConstructor = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArrayConstructor);
+    JSFunction* privateFuncIsArraySlow = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArraySlow);
     JSFunction* privateFuncConcatMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncConcatMemcpy);
     JSFunction* privateFuncAppendMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncAppendMemcpy);
     JSFunction* privateFuncConcatSlowPath = JSFunction::createBuiltinFunction(vm, arrayPrototypeConcatSlowPathCodeGenerator(vm), this);
@@ -750,6 +751,7 @@
         GlobalPropertyInfo(vm.propertyNames->builtinNames().setIteratorNextPrivateName(), JSFunction::create(vm, this, 0, String(), privateFuncSetIteratorNext), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().isMapPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncIsMap), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayPrivateName(), arrayConstructor->getDirect(vm, vm.propertyNames->isArray), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArraySlowPrivateName(), privateFuncIsArraySlow, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayConstructorPrivateName(), privateFuncIsArrayConstructor, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().concatMemcpyPrivateName(), privateFuncConcatMemcpy, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().appendMemcpyPrivateName(), privateFuncAppendMemcpy, DontEnum | DontDelete | ReadOnly),

Modified: trunk/Source/_javascript_Core/runtime/JSType.h (206064 => 206065)


--- trunk/Source/_javascript_Core/runtime/JSType.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/_javascript_Core/runtime/JSType.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -60,10 +60,12 @@
     PureForwardingProxyType,
     ImpureProxyType,
     WithScopeType,
-    ArrayType,
     DirectArgumentsType,
     ScopedArgumentsType,
 
+    ArrayType,
+    DerivedArrayType,
+
     Int8ArrayType = 100,
     Int16ArrayType,
     Int32ArrayType,

Modified: trunk/Source/WebCore/ChangeLog (206064 => 206065)


--- trunk/Source/WebCore/ChangeLog	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/WebCore/ChangeLog	2016-09-17 06:32:50 UTC (rev 206065)
@@ -1,3 +1,13 @@
+2016-09-16  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [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.
+
+        * bridge/runtime_array.h:
+        (JSC::RuntimeArray::createStructure):
+
 2016-09-16  Chris Dumez  <cdu...@apple.com>
 
         Cancelling one frame's load cancels load in other frames that have the same URL as well

Modified: trunk/Source/WebCore/bridge/runtime_array.h (206064 => 206065)


--- trunk/Source/WebCore/bridge/runtime_array.h	2016-09-17 05:18:20 UTC (rev 206064)
+++ trunk/Source/WebCore/bridge/runtime_array.h	2016-09-17 06:32:50 UTC (rev 206065)
@@ -75,7 +75,7 @@
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
+        return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
     }
 
 protected:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to