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: