Diff
Modified: trunk/LayoutTests/ChangeLog (198807 => 198808)
--- trunk/LayoutTests/ChangeLog 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/LayoutTests/ChangeLog 2016-03-29 22:57:01 UTC (rev 198808)
@@ -1,3 +1,16 @@
+2016-03-29 Keith Miller <keith_mil...@apple.com>
+
+ [ES6] Add support for Symbol.isConcatSpreadable.
+ https://bugs.webkit.org/show_bug.cgi?id=155351
+
+ Reviewed by Saam Barati.
+
+ Fix tests for Symbol.isConcatSpreadable on the Symbol object.
+
+ * js/Object-getOwnPropertyNames-expected.txt:
+ * js/dom/array-prototype-properties-expected.txt:
+ * js/script-tests/Object-getOwnPropertyNames.js:
+
2016-03-29 Nan Wang <n_w...@apple.com>
AX: VoiceOver: Navigating Numbered Lists Causes Number to be announced On Each Line of List
Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (198807 => 198808)
--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt 2016-03-29 22:57:01 UTC (rev 198808)
@@ -61,7 +61,7 @@
PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
-PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'match', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']
+PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'isConcatSpreadable', 'iterator', 'keyFor', 'length', 'match', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']
PASS getSortedOwnPropertyNames(Symbol.prototype) is ['constructor', 'toString', 'valueOf']
PASS getSortedOwnPropertyNames(Map) is ['length', 'name', 'prototype']
PASS getSortedOwnPropertyNames(Map.prototype) is ['clear', 'constructor', 'delete', 'entries', 'forEach', 'get', 'has', 'keys', 'set', 'size', 'values']
Modified: trunk/LayoutTests/js/dom/array-prototype-properties-expected.txt (198807 => 198808)
--- trunk/LayoutTests/js/dom/array-prototype-properties-expected.txt 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/LayoutTests/js/dom/array-prototype-properties-expected.txt 2016-03-29 22:57:01 UTC (rev 198808)
@@ -5,7 +5,7 @@
PASS Array.prototype.toString.call(undefined) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.toString.call(undefined)').
PASS Array.prototype.toLocaleString.call(undefined) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.toLocaleString.call(undefined)').
-PASS Array.prototype.concat.call(undefined, []) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.concat.call(undefined, [])').
+PASS Array.prototype.concat.call(undefined, []) threw exception TypeError: Array.prototype.concat requires that |this| not be undefined.
PASS Array.prototype.join.call(undefined, []) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.join.call(undefined, [])').
PASS Array.prototype.pop.call(undefined) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.pop.call(undefined)').
PASS Array.prototype.push.call(undefined, {}) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.push.call(undefined, {})').
Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (198807 => 198808)
--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -70,7 +70,7 @@
"Error.prototype": "['constructor', 'message', 'name', 'toString']",
"Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']",
"JSON": "['parse', 'stringify']",
- "Symbol": "['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'match', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']",
+ "Symbol": "['for', 'hasInstance', 'isConcatSpreadable', 'iterator', 'keyFor', 'length', 'match', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']",
"Symbol.prototype": "['constructor', 'toString', 'valueOf']",
"Map": "['length', 'name', 'prototype']",
"Map.prototype": "['clear', 'constructor', 'delete', 'entries', 'forEach', 'get', 'has', 'keys', 'set', 'size', 'values']",
Modified: trunk/Source/_javascript_Core/ChangeLog (198807 => 198808)
--- trunk/Source/_javascript_Core/ChangeLog 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-03-29 22:57:01 UTC (rev 198808)
@@ -1,3 +1,133 @@
+2016-03-29 Keith Miller <keith_mil...@apple.com>
+
+ [ES6] Add support for Symbol.isConcatSpreadable.
+ https://bugs.webkit.org/show_bug.cgi?id=155351
+
+ Reviewed by Saam Barati.
+
+ This patch adds support for Symbol.isConcatSpreadable. In order to do so it was necessary to move the
+ Array.prototype.concat function to JS. A number of different optimizations were needed to make such the move to
+ a builtin performant. First, four new DFG intrinsics were added.
+
+ 1) IsArrayObject (I would have called it IsArray but we use the same name for an IndexingType): an intrinsic of
+ the Array.isArray function.
+ 2) IsJSArray: checks the first child is a JSArray object.
+ 3) IsArrayConstructor: checks the first child is an instance of ArrayConstructor.
+ 4) CallObjectConstructor: an intrinsic of the Object constructor.
+
+ IsActualObject, IsJSArray, and CallObjectConstructor can all be converted into constants in the abstract interpreter if
+ we are able to prove that the first child is an Array or for ToObject an Object.
+
+ In order to further improve the perfomance we also now cover more indexing types in our fast path memcpy
+ code. Before we would only memcpy Arrays if they had the same indexing type and did not have Array storage and
+ were not undecided. Now the memcpy code covers the following additional two cases: One array is undecided and
+ the other is a non-array storage and the case where one array is Int32 and the other is contiguous (we map this
+ into a contiguous array).
+
+ This patch also adds a new fast path for concat with more than one array argument by using memcpy to append
+ values onto the result array. This works roughly the same as the two array fast path using the same methodology
+ to decide if we can memcpy the other butterfly into the result butterfly.
+
+ Two new debugging tools are also added to the jsc cli. One is a version of the print function with a private
+ name so it can be used for debugging builtins. The other is dumpDataLog, which takes a JSValue and runs our
+ dataLog function on it.
+
+ Finally, this patch add a new constructor to JSValueRegsTemporary that allows it to reuse the the registers of a
+ JSValueOperand if the operand's use count is one.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * builtins/ArrayPrototype.js:
+ (concatSlowPath):
+ (concat):
+ * bytecode/BytecodeIntrinsicRegistry.cpp:
+ (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+ * bytecode/BytecodeIntrinsicRegistry.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+ (JSC::DFG::SpeculativeJIT::compileIsJSArray):
+ (JSC::DFG::SpeculativeJIT::compileIsArrayObject):
+ (JSC::DFG::SpeculativeJIT::compileIsArrayConstructor):
+ (JSC::DFG::SpeculativeJIT::compileCallObjectConstructor):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileCallObjectConstructor):
+ (JSC::FTL::DFG::LowerDFGToB3::compileIsArrayObject):
+ (JSC::FTL::DFG::LowerDFGToB3::compileIsJSArray):
+ (JSC::FTL::DFG::LowerDFGToB3::compileIsArrayConstructor):
+ (JSC::FTL::DFG::LowerDFGToB3::isArray):
+ * jit/JITOperations.h:
+ * jsc.cpp:
+ (WTF::RuntimeArray::createStructure):
+ (GlobalObject::finishCreation):
+ (functionDebug):
+ (functionDataLogValue):
+ * runtime/ArrayConstructor.cpp:
+ (JSC::ArrayConstructor::finishCreation):
+ (JSC::arrayConstructorPrivateFuncIsArrayConstructor):
+ * runtime/ArrayConstructor.h:
+ (JSC::isArrayConstructor):
+ * runtime/ArrayPrototype.cpp:
+ (JSC::ArrayPrototype::finishCreation):
+ (JSC::arrayProtoPrivateFuncIsJSArray):
+ (JSC::moveElements):
+ (JSC::arrayProtoPrivateFuncConcatMemcpy):
+ (JSC::arrayProtoPrivateFuncAppendMemcpy):
+ (JSC::arrayProtoFuncConcat): Deleted.
+ * runtime/ArrayPrototype.h:
+ (JSC::ArrayPrototype::createStructure):
+ * runtime/CommonIdentifiers.h:
+ * runtime/Intrinsic.h:
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::appendMemcpy):
+ (JSC::JSArray::fastConcatWith): Deleted.
+ * runtime/JSArray.h:
+ (JSC::JSArray::createStructure):
+ (JSC::JSArray::fastConcatType): Deleted.
+ * runtime/JSArrayInlines.h: Added.
+ (JSC::JSArray::memCopyWithIndexingType):
+ (JSC::JSArray::canFastCopy):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ * runtime/JSType.h:
+ * runtime/ObjectConstructor.h:
+ (JSC::constructObject):
+ * tests/es6.yaml:
+ * tests/stress/array-concat-spread-object.js: Added.
+ (arrayEq):
+ * tests/stress/array-concat-spread-proxy-exception-check.js: Added.
+ (arrayEq):
+ * tests/stress/array-concat-spread-proxy.js: Added.
+ (arrayEq):
+ * tests/stress/array-concat-with-slow-indexingtypes.js: Added.
+ (arrayEq):
+ * tests/stress/array-species-config-array-constructor.js:
+
2016-03-29 Saam barati <sbar...@apple.com>
We don't properly optimize TDZ checks when we declare a let variable without an initializer
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (198807 => 198808)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-03-29 22:57:01 UTC (rev 198808)
@@ -1184,6 +1184,7 @@
5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; };
5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
+ 539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; };
5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
@@ -3312,6 +3313,7 @@
53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; };
53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = "<group>"; };
53917E831B791CB8000EBD33 /* TypedArrayPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = TypedArrayPrototype.js; path = builtins/TypedArrayPrototype.js; sourceTree = SOURCE_ROOT; };
+ 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArrayInlines.h; sourceTree = "<group>"; };
53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewPrototype.cpp; sourceTree = "<group>"; };
53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = "<group>"; };
593D43CCA0BBE06D89C59707 /* MapDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapDataInlines.h; sourceTree = "<group>"; };
@@ -5657,6 +5659,7 @@
70DC3E081B2DF2C700054299 /* IteratorPrototype.h */,
93ADFCE60CCBD7AC00D30B08 /* JSArray.cpp */,
938772E5038BFE19008635CE /* JSArray.h */,
+ 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */,
0F2B66B417B6B5AB00A7AE3F /* JSArrayBuffer.cpp */,
0F2B66B517B6B5AB00A7AE3F /* JSArrayBuffer.h */,
0F2B66B617B6B5AB00A7AE3F /* JSArrayBufferConstructor.cpp */,
@@ -7500,6 +7503,7 @@
0FB7F39B15ED8E4600F167B2 /* IndexingType.h in Headers */,
0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
+ 539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */,
0FF8BDEB1AD4CF7100DFE884 /* InferredValue.h in Headers */,
BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */,
A513E5B8185B8BD3007E95AD /* InjectedScript.h in Headers */,
Modified: trunk/Source/_javascript_Core/builtins/ArrayPrototype.js (198807 => 198808)
--- trunk/Source/_javascript_Core/builtins/ArrayPrototype.js 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/builtins/ArrayPrototype.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -646,6 +646,94 @@
return array;
}
+function concatSlowPath()
+{
+ "use strict";
+
+ var argCount = arguments.length;
+ var result = new this.species(0);
+ var resultIsArray = @isJSArray(result);
+
+ var currentElement = this.array;
+ var resultIndex = 0;
+ var argIndex = 0;
+
+ do {
+ var spreadable = @isObject(currentElement) && currentElement[@symbolIsConcatSpreadable];
+ if ((spreadable == @undefined && @isArray(currentElement)) || spreadable) {
+ var length = @toLength(currentElement.length);
+ if (resultIsArray && @isJSArray(currentElement)
+ && @appendMemcpy(result, currentElement)) {
+
+ resultIndex += length;
+ } else {
+ if (length + resultIndex > @MAX_SAFE_INTEGER)
+ throw @TypeError("length exceeded the maximum safe integer");
+ for (var i = 0; i < length; i++) {
+ if (i in currentElement)
+ @putByValDirect(result, resultIndex, currentElement[i]);
+ resultIndex++;
+ }
+ }
+ } else {
+ if (resultIndex >= @MAX_SAFE_INTEGER)
+ throw @TypeError("length exceeded the maximum safe integer");
+ @putByValDirect(result, resultIndex++, currentElement);
+ }
+ currentElement = arguments[argIndex];
+ } while (argIndex++ < argCount);
+
+ result.length = resultIndex;
+ return result;
+}
+
+function concat(first)
+{
+ "use strict";
+
+ if (this == null) {
+ if (this === null)
+ throw new @TypeError("Array.prototype.concat requires that |this| not be null");
+ throw new @TypeError("Array.prototype.concat requires that |this| not be undefined");
+ }
+
+ var array = @Object(this);
+
+ var constructor;
+ if (@isArray(array)) {
+ constructor = array.constructor;
+ // We have this check so that if some array from a different global object
+ // calls this map they don't get an array with the Array.prototype of the
+ // other global object.
+ if (@isArrayConstructor(constructor) && @Array !== constructor)
+ constructor = @undefined;
+ if (@isObject(constructor)) {
+ constructor = constructor[@symbolSpecies];
+ if (constructor === null)
+ constructor = @Array;
+ }
+ }
+ if (constructor === @undefined)
+ constructor = @Array;
+
+ var result;
+ if (arguments.length === 1
+ && constructor === @Array
+ && @isJSArray(array)
+ && @isJSArray(first)
+ // FIXME: these get_by_ids should be "in"s but using "in" here is a 10% regression.
+ // https://bugs.webkit.org/show_bug.cgi?id=155590
+ && array[@symbolIsConcatSpreadable] == @undefined
+ && first[@symbolIsConcatSpreadable] == @undefined) {
+
+ result = @concatMemcpy(array, first);
+ if (result !== null)
+ return result;
+ }
+
+ return @concatSlowPath.@apply({ array: array, species: constructor }, arguments);
+}
+
function copyWithin(target, start /*, end */)
{
"use strict";
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -47,9 +47,11 @@
m_arrayIterationKindKey.set(m_vm, jsNumber(ArrayIterateKey));
m_arrayIterationKindValue.set(m_vm, jsNumber(ArrayIterateValue));
m_arrayIterationKindKeyValue.set(m_vm, jsNumber(ArrayIterateKeyValue));
+ m_MAX_SAFE_INTEGER.set(m_vm, jsDoubleNumber(9007199254740991.0)); // 2 ^ 53 - 1
m_promiseStatePending.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Pending)));
m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled)));
m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected)));
+ m_symbolIsConcatSpreadable.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->isConcatSpreadableSymbol.impl())));
m_symbolIterator.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->iteratorSymbol.impl())));
m_symbolMatch.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->matchSymbol.impl())));
m_symbolSearch.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->searchSymbol.impl())));
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (198807 => 198808)
--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -49,9 +49,11 @@
macro(arrayIterationKindKey) \
macro(arrayIterationKindValue) \
macro(arrayIterationKindKeyValue) \
+ macro(MAX_SAFE_INTEGER) \
macro(promiseStatePending) \
macro(promiseStateFulfilled) \
macro(promiseStateRejected) \
+ macro(symbolIsConcatSpreadable) \
macro(symbolIterator) \
macro(symbolMatch) \
macro(symbolSearch) \
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -28,6 +28,7 @@
#if ENABLE(DFG_JIT)
+#include "ArrayConstructor.h"
#include "DFGAbstractInterpreter.h"
#include "GetByIdStatus.h"
#include "GetterSetter.h"
@@ -952,7 +953,10 @@
}
break;
}
-
+
+ case IsArrayObject:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
@@ -964,6 +968,28 @@
if (child.value()) {
bool constantWasSet = true;
switch (node->op()) {
+ case IsArrayObject:
+ if (child.value().isObject()) {
+ if (child.value().getObject()->type() == ArrayType) {
+ setConstant(node, jsBoolean(true));
+ break;
+ }
+
+ if (child.value().getObject()->type() == ProxyObjectType) {
+ // We have no way of knowing what type we are proxing yet.
+ constantWasSet = false;
+ break;
+ }
+ }
+
+ setConstant(node, jsBoolean(false));
+ break;
+ case IsJSArray:
+ setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == ArrayType));
+ break;
+ case IsArrayConstructor:
+ setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->classInfo() == ArrayConstructor::info()));
+ break;
case IsUndefined:
setConstant(node, jsBoolean(
child.value().isCell()
@@ -1026,6 +1052,22 @@
bool constantWasSet = false;
switch (node->op()) {
+ case IsJSArray:
+ case IsArrayObject:
+ // 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 IsUndefined:
// FIXME: Use the masquerades-as-undefined watchpoint thingy.
// https://bugs.webkit.org/show_bug.cgi?id=144456
@@ -1779,7 +1821,21 @@
ASSERT(node->structure());
forNode(node).set(m_graph, node->structure());
break;
-
+
+ case CallObjectConstructor: {
+ AbstractValue& source = forNode(node->child1());
+ AbstractValue& destination = forNode(node);
+
+ if (!(source.m_type & ~SpecObject)) {
+ m_state.setFoundConstants(true);
+ destination = source;
+ break;
+ }
+
+ forNode(node).setType(m_graph, SpecObject);
+ break;
+ }
+
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -43,6 +43,7 @@
#include "JSLexicalEnvironment.h"
#include "JSCInlines.h"
#include "JSModuleEnvironment.h"
+#include "ObjectConstructor.h"
#include "PreciseJumpTargets.h"
#include "PutByIdFlags.h"
#include "PutByIdStatus.h"
@@ -2121,6 +2122,34 @@
}
}
+ case IsArrayIntrinsic: {
+ if (argumentCountIncludingThis != 2)
+ return false;
+
+ insertChecks();
+ Node* isArray = addToGraph(IsArrayObject, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
+ set(VirtualRegister(resultOperand), isArray);
+ return true;
+ }
+
+ case IsJSArrayIntrinsic: {
+ ASSERT(argumentCountIncludingThis == 2);
+
+ insertChecks();
+ Node* isArray = addToGraph(IsJSArray, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
+ set(VirtualRegister(resultOperand), isArray);
+ return true;
+ }
+
+ case IsArrayConstructorIntrinsic: {
+ ASSERT(argumentCountIncludingThis == 2);
+
+ insertChecks();
+ Node* isArray = addToGraph(IsArrayConstructor, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
+ set(VirtualRegister(resultOperand), isArray);
+ return true;
+ }
+
case CharCodeAtIntrinsic: {
if (argumentCountIncludingThis != 2)
return false;
@@ -2493,7 +2522,16 @@
set(VirtualRegister(resultOperand), result);
return true;
}
-
+
+ // FIXME: This should handle construction as well. https://bugs.webkit.org/show_bug.cgi?id=155591
+ if (function->classInfo() == ObjectConstructor::info() && kind == CodeForCall) {
+ insertChecks();
+
+ Node* result = addToGraph(CallObjectConstructor, get(virtualRegisterForArgument(1, registerOffset)));
+ set(VirtualRegister(resultOperand), result);
+ return true;
+ }
+
for (unsigned typeIndex = 0; typeIndex < NUMBER_OF_TYPED_ARRAY_TYPES; ++typeIndex) {
bool result = handleTypedArrayConstructor(
resultOperand, function, registerOffset, argumentCountIncludingThis,
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -142,6 +142,8 @@
case GetGlobalObject:
case StringCharCodeAt:
case CompareStrictEq:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
@@ -181,7 +183,8 @@
read(MathDotRandomState);
write(MathDotRandomState);
return;
-
+
+ case IsArrayObject:
case HasGenericProperty:
case HasStructureProperty:
case GetEnumerableLength:
@@ -397,6 +400,7 @@
write(HeapObjectCount);
return;
+ case CallObjectConstructor:
case ToThis:
case CreateThis:
read(MiscFields);
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -149,6 +149,9 @@
case OverridesHasInstance:
case InstanceOf:
case InstanceOfCustom:
+ case IsArrayObject:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
@@ -238,6 +241,7 @@
case CreateDirectArguments:
case CreateScopedArguments:
case CreateClonedArguments:
+ case CallObjectConstructor:
case ToThis:
case CreateThis:
case AllocatePropertyStorage:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -1028,7 +1028,18 @@
fixEdge<Int32Use>(node->child1());
break;
}
-
+
+ case CallObjectConstructor: {
+ if (node->child1()->shouldSpeculateObject()) {
+ fixEdge<ObjectUse>(node->child1());
+ node->convertToIdentity();
+ break;
+ }
+
+ fixEdge<UntypedUse>(node->child1());
+ break;
+ }
+
case ToThis: {
fixupToThis(node);
break;
@@ -1488,6 +1499,9 @@
case NewRegexp:
case ProfileWillCall:
case ProfileDidCall:
+ case IsArrayObject:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -290,6 +290,11 @@
macro(OverridesHasInstance, NodeMustGenerate | NodeResultBoolean) \
macro(InstanceOf, NodeResultBoolean) \
macro(InstanceOfCustom, NodeMustGenerate | NodeResultBoolean) \
+ \
+ /* I'd like to call this IsArray but then we get namespace problems with the indexing type name. Also, it is marked must generate because it can throw. */ \
+ macro(IsArrayObject, NodeMustGenerate | NodeResultBoolean) \
+ macro(IsJSArray, NodeResultBoolean) \
+ macro(IsArrayConstructor, NodeResultBoolean) \
macro(IsUndefined, NodeResultBoolean) \
macro(IsBoolean, NodeResultBoolean) \
macro(IsNumber, NodeResultBoolean) \
@@ -301,6 +306,7 @@
macro(LogicalNot, NodeResultBoolean) \
macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \
macro(ToString, NodeResultJS | NodeMustGenerate) \
+ macro(CallObjectConstructor, NodeResultJS) \
macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \
macro(NewStringObject, NodeResultJS) \
macro(MakeRope, NodeResultJS) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -26,6 +26,7 @@
#include "config.h"
#include "DFGOperations.h"
+#include "ArrayConstructor.h"
#include "ButterflyInlines.h"
#include "ClonedArguments.h"
#include "CodeBlock.h"
@@ -176,6 +177,19 @@
return constructEmptyObject(exec);
}
+JSCell* JIT_OPERATION operationObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue value = JSValue::decode(encodedTarget);
+ ASSERT(!value.isObject());
+
+ if (value.isUndefinedOrNull())
+ return constructEmptyObject(exec, globalObject->objectPrototype());
+ return value.toObject(exec, globalObject);
+}
+
EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
VM* vm = &exec->vm();
@@ -710,6 +724,22 @@
return asRegExpObject(base)->test(exec, globalObject, input);
}
+size_t JIT_OPERATION operationIsArrayConstructor(ExecState* exec, EncodedJSValue encodedTarget)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ return isArrayConstructor(JSValue::decode(encodedTarget));
+}
+
+size_t JIT_OPERATION operationIsArrayObject(ExecState* exec, EncodedJSValue encodedTarget)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ return isArray(exec, JSValue::decode(encodedTarget));
+}
+
size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
VM* vm = &exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -41,6 +41,7 @@
EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState*, EncodedJSValue) WTF_INTERNAL;
// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
+JSCell* JIT_OPERATION operationObjectConstructor(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget) WTF_INTERNAL;
JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, int32_t inlineCapacity) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
@@ -110,6 +111,8 @@
size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
size_t JIT_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+size_t JIT_OPERATION operationIsArrayConstructor(ExecState*, EncodedJSValue);
+size_t JIT_OPERATION operationIsArrayObject(ExecState*, EncodedJSValue);
JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState*, Structure*, JSScope*, SymbolTable*, EncodedJSValue);
JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState*, Structure*, int32_t length, int32_t minCapacity);
JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -417,6 +417,9 @@
case OverridesHasInstance:
case InstanceOf:
case InstanceOfCustom:
+ case IsArrayObject:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
@@ -490,6 +493,11 @@
break;
}
+ case CallObjectConstructor: {
+ changed |= setPrediction(SpecObject);
+ break;
+ }
+
case ToThis: {
// ToThis in methods for primitive types should speculate primitive types in strict mode.
ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -250,6 +250,9 @@
case OverridesHasInstance:
case InstanceOf:
case InstanceOfCustom:
+ case IsArrayObject:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
@@ -259,6 +262,7 @@
case IsFunction:
case TypeOf:
case LogicalNot:
+ case CallObjectConstructor:
case ToPrimitive:
case ToString:
case SetFunctionName:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -1503,7 +1503,7 @@
dataLog("\n");
}
- if (Options::validateDFGExceptionHandling() && mayExit(m_jit.graph(), m_currentNode) != DoesNotExit)
+ if (Options::validateDFGExceptionHandling() && (mayExit(m_jit.graph(), m_currentNode) != DoesNotExit || m_currentNode->isTerminal()))
m_jit.jitReleaseAssertNoException();
m_jit.pcToCodeOriginMapBuilder().appendItem(m_jit.label(), m_origin.semantic);
@@ -3248,6 +3248,98 @@
unblessedBooleanResult(resultGPR, node);
}
+void SpeculativeJIT::compileIsJSArray(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+ GPRFlushedCallResult result(this);
+
+ JSValueRegs valueRegs = value.jsValueRegs();
+ GPRReg resultGPR = result.gpr();
+
+ 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();
+
+ isNotCell.link(&m_jit);
+ moveFalseTo(resultGPR);
+
+ done.link(&m_jit);
+ blessedBooleanResult(resultGPR, node);
+}
+
+void SpeculativeJIT::compileIsArrayObject(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+ GPRFlushedCallResult result(this);
+
+ JSValueRegs valueRegs = value.jsValueRegs();
+ GPRReg resultGPR = result.gpr();
+
+ JITCompiler::JumpList done;
+
+ JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
+
+ JITCompiler::Jump notJSArray = m_jit.branch8(JITCompiler::NotEqual,
+ JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
+ TrustedImm32(ArrayType));
+ m_jit.move(TrustedImm32(true), resultGPR);
+ done.append(m_jit.jump());
+
+ notJSArray.link(&m_jit);
+ silentSpillAllRegisters(resultGPR);
+ callOperation(operationIsArrayObject, resultGPR, valueRegs);
+ silentFillAllRegisters(resultGPR);
+ m_jit.exceptionCheck();
+ done.append(m_jit.jump());
+
+ isNotCell.link(&m_jit);
+ m_jit.move(TrustedImm32(false), resultGPR);
+
+ done.link(&m_jit);
+ unblessedBooleanResult(resultGPR, node);
+}
+
+// FIXME: This function should just get the ClassInfo and check if it's == ArrayConstructor::info(). https://bugs.webkit.org/show_bug.cgi?id=155667
+void SpeculativeJIT::compileIsArrayConstructor(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+ GPRFlushedCallResult result(this);
+
+ JSValueRegs valueRegs = value.jsValueRegs();
+ GPRReg resultGPR = result.gpr();
+
+ flushRegisters();
+ callOperation(operationIsArrayConstructor, resultGPR, valueRegs);
+ unblessedBooleanResult(resultGPR, node);
+}
+
+void SpeculativeJIT::compileCallObjectConstructor(Node* node)
+{
+ RELEASE_ASSERT(node->child1().useKind() == 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();
+
+ MacroAssembler::JumpList slowCases;
+ slowCases.append(m_jit.branchIfNotCell(valueRegs));
+ slowCases.append(m_jit.branchIfNotObject(valueRegs.payloadGPR()));
+ m_jit.move(valueRegs.payloadGPR(), resultGPR);
+
+ addSlowPathGenerator(slowPathCall(slowCases, this, operationObjectConstructor, resultGPR, m_jit.globalObjectFor(node->origin.semantic), valueRegs));
+ cellResult(resultGPR, node);
+}
+
void SpeculativeJIT::compileArithAdd(Node* node)
{
switch (node->binaryUseKind()) {
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -729,6 +729,10 @@
void compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchAndResultReg, GPRReg scratch2Reg);
void compileInstanceOf(Node*);
void compileInstanceOfCustom(Node*);
+
+ void compileIsJSArray(Node*);
+ void compileIsArrayConstructor(Node*);
+ void compileIsArrayObject(Node*);
void emitCall(Node*);
@@ -1392,6 +1396,17 @@
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg1);
+ return appendCallSetResult(operation, result);
+ }
+
+ JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1)
+ {
+ return callOperation(operation, result, globalObject, arg1.gpr());
+ }
+
JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, GPRReg arg1)
{
m_jit.setupArgumentsWithExecState(arg1);
@@ -1432,10 +1447,18 @@
m_jit.setupArgumentsWithExecState(arg1);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(S_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)
+ {
+ return callOperation(operation, result, arg1.gpr());
+ }
JITCompiler::Call callOperation(J_JITOperation_EJ operation, JSValueRegs result, JSValueRegs arg1)
{
return callOperation(operation, result.payloadGPR(), arg1.payloadGPR());
}
+ JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)
+ {
+ return callOperation(operation, result, arg1.payloadGPR());
+ }
JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, GPRReg arg1)
{
m_jit.setupArgumentsWithExecState(arg1);
@@ -1815,6 +1838,17 @@
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1Tag, GPRReg arg1Payload)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(globalObject), arg1Payload, arg1Tag);
+ return appendCallSetResult(operation, result);
+ }
+
+ JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1)
+ {
+ return callOperation(operation, result, globalObject, arg1.payloadGPR(), arg1.tagGPR());
+ }
+
JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
@@ -1839,6 +1873,11 @@
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(S_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)
+ {
+ return callOperation(operation, result, arg1.tagGPR(), arg1.payloadGPR());
+ }
+
JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
@@ -2412,7 +2451,9 @@
void compileGetRegExpObjectLastIndex(Node*);
void compileSetRegExpObjectLastIndex(Node*);
void compileLazyJSConstant(Node*);
-
+
+ void compileCallObjectConstructor(Node*);
+
void moveTrueTo(GPRReg);
void moveFalseTo(GPRReg);
void blessBoolean(GPRReg);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -3807,6 +3807,11 @@
cellResult(resultPayload.gpr(), node);
break;
}
+
+ case CallObjectConstructor: {
+ compileCallObjectConstructor(node);
+ break;
+ }
case ToThis: {
ASSERT(node->child1().useKind() == UntypedUse);
@@ -4458,6 +4463,21 @@
break;
}
+ case IsJSArray: {
+ compileIsJSArray(node);
+ break;
+ }
+
+ case IsArrayObject: {
+ compileIsArrayObject(node);
+ break;
+ }
+
+ case IsArrayConstructor: {
+ compileIsArrayConstructor(node);
+ break;
+ }
+
case IsObject: {
JSValueOperand value(this, node->child1());
GPRTemporary result(this, Reuse, value, TagWord);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -3871,7 +3871,12 @@
cellResult(result.gpr(), node);
break;
}
-
+
+ case CallObjectConstructor: {
+ compileCallObjectConstructor(node);
+ break;
+ }
+
case ToThis: {
ASSERT(node->child1().useKind() == UntypedUse);
JSValueOperand thisValue(this, node->child1());
@@ -4474,6 +4479,21 @@
break;
}
+ case IsJSArray: {
+ compileIsJSArray(node);
+ break;
+ }
+
+ case IsArrayObject: {
+ compileIsArrayObject(node);
+ break;
+ }
+
+ case IsArrayConstructor: {
+ compileIsArrayConstructor(node);
+ break;
+ }
+
case IsObject: {
JSValueOperand value(this, node->child1());
GPRTemporary result(this, Reuse, value);
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -161,6 +161,7 @@
case GetScope:
case GetCallee:
case GetArgumentCount:
+ case CallObjectConstructor:
case ToString:
case CallStringConstructor:
case MakeRope:
@@ -174,6 +175,9 @@
case Throw:
case ThrowReferenceError:
case Unreachable:
+ case IsArrayObject:
+ case IsJSArray:
+ case IsArrayConstructor:
case IsUndefined:
case IsBoolean:
case IsNumber:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -479,6 +479,9 @@
case DFG::Check:
compileNoOp();
break;
+ case CallObjectConstructor:
+ compileCallObjectConstructor();
+ break;
case ToThis:
compileToThis();
break;
@@ -842,6 +845,15 @@
case IsString:
compileIsString();
break;
+ case IsArrayObject:
+ compileIsArrayObject();
+ break;
+ case IsJSArray:
+ compileIsJSArray();
+ break;
+ case IsArrayConstructor:
+ compileIsArrayConstructor();
+ break;
case IsObject:
compileIsObject();
break;
@@ -1397,6 +1409,28 @@
{
DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
}
+
+ void compileCallObjectConstructor()
+ {
+ LValue value = lowJSValue(m_node->child1());
+
+ LBasicBlock isCellCase = m_out.newBlock();
+ LBasicBlock slowCase = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
+
+ m_out.branch(isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase));
+
+ LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);
+ ValueFromBlock fastResult = m_out.anchor(value);
+ m_out.branch(isObject(value), usually(continuation), rarely(slowCase));
+
+ m_out.appendTo(slowCase, continuation);
+ ValueFromBlock slowResult = m_out.anchor(vmCall(m_out.int64, m_out.operation(operationToObject), m_callFrame, value));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
+ }
void compileToThis()
{
@@ -5692,6 +5726,55 @@
setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult));
}
+ void compileIsArrayObject()
+ {
+ LValue value = lowJSValue(m_node->child1());
+
+ LBasicBlock cellCase = m_out.newBlock();
+ LBasicBlock notArrayCase = 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(cellCase), unsure(continuation));
+
+ LBasicBlock lastNext = m_out.appendTo(cellCase, notArrayCase);
+ ValueFromBlock arrayResult = m_out.anchor(m_out.booleanTrue);
+ m_out.branch(isArray(value, provenType(m_node->child1())), unsure(continuation), unsure(notArrayCase));
+
+ m_out.appendTo(notArrayCase, continuation);
+ ValueFromBlock notArrayResult = m_out.anchor(vmCall(m_out.boolean, m_out.operation(operationIsArrayObject), m_callFrame, value));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setBoolean(m_out.phi(m_out.boolean, notCellResult, arrayResult, notArrayResult));
+ }
+
+ void compileIsJSArray()
+ {
+ 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(isArray(value, provenType(m_node->child1())));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult));
+ }
+
+ void compileIsArrayConstructor()
+ {
+ LValue value = lowJSValue(m_node->child1());
+
+ setBoolean(vmCall(m_out.boolean, m_out.operation(operationIsArrayConstructor), m_callFrame, value));
+ }
+
void compileIsObject()
{
LValue value = lowJSValue(m_node->child1());
@@ -9459,6 +9542,15 @@
jsValueToStrictInt52(edge, lowJSValue(edge, ManualOperandSpeculation));
}
+
+ LValue isArray(LValue cell, SpeculatedType type = SpecFullTop)
+ {
+ if (LValue proven = isProvenValue(type & SpecCell, SpecArray))
+ return proven;
+ return m_out.equal(
+ m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
+ m_out.constInt32(ArrayType));
+ }
LValue isObject(LValue cell, SpeculatedType type = SpecFullTop)
{
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (198807 => 198808)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -163,6 +163,7 @@
typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZC)(ExecState*, JSCell*, int32_t, JSCell*);
typedef JSCell* JIT_OPERATION (*C_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
typedef JSCell* JIT_OPERATION (*C_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
+typedef JSCell* JIT_OPERATION (*C_JITOperation_EGJ)(ExecState*, JSGlobalObject*, EncodedJSValue);
typedef JSCell* JIT_OPERATION (*C_JITOperation_EIcf)(ExecState*, InlineCallFrame*);
typedef JSCell* JIT_OPERATION (*C_JITOperation_EJ)(ExecState*, EncodedJSValue);
typedef JSCell* JIT_OPERATION (*C_JITOperation_EJsc)(ExecState*, JSScope*);
Modified: trunk/Source/_javascript_Core/jsc.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/jsc.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/jsc.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -437,7 +437,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(ArrayType, StructureFlags), info(), ArrayClass);
}
protected:
@@ -558,6 +558,7 @@
static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDataLogValue(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
@@ -723,7 +724,8 @@
void finishCreation(VM& vm, const Vector<String>& arguments)
{
Base::finishCreation(vm);
-
+
+ addFunction(vm, "dataLogValue", functionDataLogValue, 1);
addFunction(vm, "debug", functionDebug, 1);
addFunction(vm, "describe", functionDescribe, 1);
addFunction(vm, "describeArray", functionDescribeArray, 1);
@@ -821,6 +823,7 @@
}
putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
+ putDirect(vm, vm.propertyNames->printPrivateName, JSFunction::create(vm, this, 1, vm.propertyNames->printPrivateName.string(), functionPrint));
}
void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
@@ -1120,6 +1123,12 @@
return JSValue::encode(jsUndefined());
}
+EncodedJSValue JSC_HOST_CALL functionDataLogValue(ExecState* exec)
+{
+ dataLog("value is: ", exec->argument(0), "\n");
+ return JSValue::encode(jsUndefined());
+}
+
EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
{
if (exec->argumentCount() < 1)
Modified: trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -68,7 +68,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_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArray, DontEnum, 1, IsArrayIntrinsic);
}
bool ArrayConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
@@ -135,7 +135,7 @@
EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArrayConstructor(ExecState* exec)
{
- return JSValue::encode(jsBoolean(jsDynamicCast<ArrayConstructor*>(exec->uncheckedArgument(0))));
+ return JSValue::encode(jsBoolean(isArrayConstructor(exec->uncheckedArgument(0))));
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/ArrayConstructor.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/ArrayConstructor.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/ArrayConstructor.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -91,6 +91,14 @@
ASSERT_NOT_REACHED();
}
+inline bool isArrayConstructor(JSValue argumentValue)
+{
+ if (!argumentValue.isObject())
+ return false;
+
+ return jsCast<JSObject*>(argumentValue)->classInfo() == ArrayConstructor::info();
+}
+
} // namespace JSC
#endif // ArrayConstructor_h
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -34,6 +34,7 @@
#include "Error.h"
#include "Interpreter.h"
#include "JIT.h"
+#include "JSArrayInlines.h"
#include "JSArrayIterator.h"
#include "JSCBuiltins.h"
#include "JSCInlines.h"
@@ -50,7 +51,6 @@
namespace JSC {
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*);
-EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*);
EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*);
EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*);
EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*);
@@ -93,7 +93,7 @@
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, arrayProtoFuncToString, DontEnum, 0);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, arrayProtoFuncToLocaleString, DontEnum, 0);
- JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("concat", arrayProtoFuncConcat, DontEnum, 1);
+ JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("concat", arrayPrototypeConcatCodeGenerator, DontEnum);
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("fill", arrayPrototypeFillCodeGenerator, DontEnum);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->join, arrayProtoFuncJoin, DontEnum, 1);
JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("pop", arrayProtoFuncPop, DontEnum, 0, ArrayPopIntrinsic);
@@ -590,87 +590,6 @@
return JSValue::encode(join(*exec, thisObject, separator->view(exec).get()));
}
-EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
-{
- JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
- unsigned argCount = exec->argumentCount();
- JSValue curArg = thisValue.toObject(exec);
- if (!curArg)
- return JSValue::encode(JSValue());
- Checked<unsigned, RecordOverflow> finalArraySize = 0;
-
- // We need to do species construction before geting the rest of the elements.
- std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, curArg.getObject(), 0);
- if (speciesResult.first == SpeciesConstructResult::Exception)
- return JSValue::encode(jsUndefined());
-
- JSArray* currentArray = nullptr;
- JSArray* previousArray = nullptr;
- for (unsigned i = 0; ; ++i) {
- previousArray = currentArray;
- currentArray = jsDynamicCast<JSArray*>(curArg);
- if (currentArray) {
- // Can't use JSArray::length here because this might be a RuntimeArray!
- finalArraySize += getLength(exec, currentArray);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- } else
- ++finalArraySize;
- if (i == argCount)
- break;
- curArg = exec->uncheckedArgument(i);
- }
-
- if (finalArraySize.hasOverflowed())
- return JSValue::encode(throwOutOfMemoryError(exec));
-
- if (speciesResult.first == SpeciesConstructResult::FastPath && argCount == 1 && previousArray && currentArray && finalArraySize.unsafeGet() < MIN_SPARSE_ARRAY_INDEX) {
- IndexingType type = JSArray::fastConcatType(exec->vm(), *previousArray, *currentArray);
- if (type != NonArray)
- return previousArray->fastConcatWith(*exec, *currentArray);
- }
-
- ASSERT(speciesResult.first != SpeciesConstructResult::Exception);
-
- JSObject* result;
- if (speciesResult.first == SpeciesConstructResult::CreatedObject)
- result = speciesResult.second;
- else {
- // We add the newTarget because the compiler gets confused between 0 being a number and a pointer.
- result = constructEmptyArray(exec, nullptr, 0, JSValue());
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- }
-
- curArg = thisValue.toObject(exec);
- ASSERT(!exec->hadException());
- unsigned n = 0;
- for (unsigned i = 0; ; ++i) {
- if (JSArray* currentArray = jsDynamicCast<JSArray*>(curArg)) {
- // Can't use JSArray::length here because this might be a RuntimeArray!
- unsigned length = getLength(exec, currentArray);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- for (unsigned k = 0; k < length; ++k) {
- JSValue v = getProperty(exec, currentArray, k);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- if (v)
- result->putDirectIndex(exec, n, v);
- n++;
- }
- } else {
- result->putDirectIndex(exec, n, curArg);
- n++;
- }
- if (i == argCount)
- break;
- curArg = exec->uncheckedArgument(i);
- }
- setLength(exec, result, n);
- return JSValue::encode(result);
-}
-
EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
{
JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
@@ -1095,6 +1014,92 @@
return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateKey, thisObj));
}
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncIsJSArray(ExecState* exec)
+{
+ JSValue value = exec->uncheckedArgument(0);
+ if (value.isObject())
+ return JSValue::encode(jsBoolean(value.getObject()->type() == ArrayType));
+ return JSValue::encode(jsBoolean(false));
+}
+
+inline bool moveElements(ExecState* exec, VM& vm, JSArray* target, unsigned targetOffset, JSArray* source, unsigned sourceLength)
+{
+ ASSERT(!hasAnyArrayStorage(source->indexingType()));
+ for (unsigned i = 0; i < sourceLength; ++i) {
+ JSValue value = getProperty(exec, source, i);
+ if (vm.exception())
+ return false;
+ if (value) {
+ target->putDirectIndex(exec, targetOffset + i, value);
+ if (vm.exception())
+ return false;
+ }
+ }
+ return true;
+}
+
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec)
+{
+ ASSERT(exec->argumentCount() == 2);
+ VM& vm = exec->vm();
+
+ JSArray* firstArray = jsCast<JSArray*>(exec->uncheckedArgument(0));
+ JSArray* secondArray = jsCast<JSArray*>(exec->uncheckedArgument(1));
+
+ if (!firstArray->canFastCopy(vm, secondArray))
+ return JSValue::encode(jsNull());
+
+ Butterfly* firstButterfly = firstArray->butterfly();
+ Butterfly* secondButterfly = secondArray->butterfly();
+
+ unsigned firstArraySize = firstButterfly->publicLength();
+ unsigned secondArraySize = secondButterfly->publicLength();
+
+ IndexingType type = firstArray->memCopyWithIndexingType(secondArray->indexingType());
+ if (type == NonArray || firstArraySize + secondArraySize >= MIN_SPARSE_ARRAY_INDEX) {
+ JSArray* result = constructEmptyArray(exec, nullptr, firstArraySize + secondArraySize);
+ if (vm.exception())
+ return JSValue::encode(JSValue());
+
+ if (!moveElements(exec, vm, result, 0, firstArray, firstArraySize)
+ || !moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize)) {
+ ASSERT(vm.exception());
+ return JSValue::encode(JSValue());
+ }
+
+ return JSValue::encode(result);
+ }
+
+ Structure* resultStructure = exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(type);
+ JSArray* result = JSArray::tryCreateUninitialized(vm, resultStructure, firstArraySize + secondArraySize);
+ if (!result)
+ return JSValue::encode(throwOutOfMemoryError(exec));
+
+ if (type == ArrayWithDouble) {
+ double* buffer = result->butterfly()->contiguousDouble().data();
+ memcpy(buffer, firstButterfly->contiguousDouble().data(), sizeof(JSValue) * firstArraySize);
+ memcpy(buffer + firstArraySize, secondButterfly->contiguousDouble().data(), sizeof(JSValue) * secondArraySize);
+ } else if (type != ArrayWithUndecided) {
+ WriteBarrier<Unknown>* buffer = result->butterfly()->contiguous().data();
+ memcpy(buffer, firstButterfly->contiguous().data(), sizeof(JSValue) * firstArraySize);
+ memcpy(buffer + firstArraySize, secondButterfly->contiguous().data(), sizeof(JSValue) * secondArraySize);
+ }
+
+ result->butterfly()->setPublicLength(firstArraySize + secondArraySize);
+ return JSValue::encode(result);
+}
+
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncAppendMemcpy(ExecState* exec)
+{
+ ASSERT(exec->argumentCount() == 2);
+
+ JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0));
+ JSArray* otherArray = jsCast<JSArray*>(exec->uncheckedArgument(1));
+
+ return JSValue::encode(jsBoolean(resultArray->appendMemcpy(exec, exec->vm(), otherArray)));
+}
+
+
// -------------------- ArrayPrototype.constructor Watchpoint ------------------
class ArrayPrototypeAdaptiveInferredPropertyWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase {
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -41,7 +41,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(ArrayType, StructureFlags), info(), ArrayClass);
}
void setConstructor(VM&, JSObject* constructorProperty, unsigned attributes);
@@ -65,6 +65,9 @@
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*);
EncodedJSValue JSC_HOST_CALL arrayProtoFuncValues(ExecState*);
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncIsJSArray(ExecState*);
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState*);
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncAppendMemcpy(ExecState*);
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -273,12 +273,12 @@
macro(yield)
#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL_NOT_IMPLEMENTED_YET(macro)\
- macro(isConcatSpreadable) \
macro(replace) \
macro(split)
#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
macro(hasInstance) \
+ macro(isConcatSpreadable) \
macro(iterator) \
macro(match) \
macro(search) \
@@ -373,7 +373,12 @@
macro(hasInstanceBoundFunction) \
macro(instanceOf) \
macro(isArray) \
+ macro(isJSArray) \
macro(isArrayConstructor) \
+ macro(concatMemcpy) \
+ macro(appendMemcpy) \
+ macro(predictFinalLengthFromArgumunts) \
+ macro(print) \
macro(isSet) \
macro(isMap) \
macro(SetIterator) \
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -56,6 +56,9 @@
IMulIntrinsic,
RandomIntrinsic,
FRoundIntrinsic,
+ IsArrayIntrinsic,
+ IsArrayConstructorIntrinsic,
+ IsJSArrayIntrinsic,
// Getter intrinsics.
TypedArrayLengthIntrinsic,
Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/JSArray.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -392,6 +392,37 @@
return true;
}
+bool JSArray::appendMemcpy(ExecState* exec, VM& vm, JSC::JSArray* otherArray)
+{
+ if (!canFastCopy(vm, otherArray))
+ return false;
+
+ IndexingType type = indexingType();
+ if (type != memCopyWithIndexingType(otherArray->indexingType()))
+ return false;
+
+ unsigned oldLength = length();
+ unsigned otherLength = otherArray->length();
+ unsigned newLength = oldLength + otherLength;
+ if (newLength >= MIN_SPARSE_ARRAY_INDEX)
+ return false;
+
+ if (!ensureLength(vm, newLength))
+ return false;
+ ASSERT(type == indexingType());
+ if (length() != newLength) {
+ throwOutOfMemoryError(exec);
+ return false;
+ }
+
+ if (type == ArrayWithDouble)
+ memcpy(butterfly()->contiguousDouble().data() + oldLength, otherArray->butterfly()->contiguousDouble().data(), sizeof(JSValue) * otherLength);
+ else
+ memcpy(butterfly()->contiguous().data() + oldLength, otherArray->butterfly()->contiguous().data(), sizeof(JSValue) * otherLength);
+
+ return true;
+}
+
bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException)
{
Butterfly* butterfly = m_butterfly.get();
@@ -719,38 +750,6 @@
}
}
-EncodedJSValue JSArray::fastConcatWith(ExecState& exec, JSArray& otherArray)
-{
- auto newArrayType = indexingType();
-
- VM& vm = exec.vm();
- ASSERT(newArrayType == fastConcatType(vm, *this, otherArray));
-
- unsigned thisArraySize = m_butterfly.get()->publicLength();
- unsigned otherArraySize = otherArray.m_butterfly.get()->publicLength();
- ASSERT(thisArraySize + otherArraySize < MIN_SPARSE_ARRAY_INDEX);
-
- Structure* resultStructure = exec.lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(newArrayType);
- JSArray* resultArray = JSArray::tryCreateUninitialized(vm, resultStructure, thisArraySize + otherArraySize);
- if (!resultArray)
- return JSValue::encode(throwOutOfMemoryError(&exec));
-
- auto& resultButterfly = *resultArray->butterfly();
- auto& otherButterfly = *otherArray.butterfly();
- if (newArrayType == ArrayWithDouble) {
- auto buffer = resultButterfly.contiguousDouble().data();
- memcpy(buffer, m_butterfly.get()->contiguousDouble().data(), sizeof(JSValue) * thisArraySize);
- memcpy(buffer + thisArraySize, otherButterfly.contiguousDouble().data(), sizeof(JSValue) * otherArraySize);
- } else {
- auto buffer = resultButterfly.contiguous().data();
- memcpy(buffer, m_butterfly.get()->contiguous().data(), sizeof(JSValue) * thisArraySize);
- memcpy(buffer + thisArraySize, otherButterfly.contiguous().data(), sizeof(JSValue) * otherArraySize);
- }
-
- resultButterfly.setPublicLength(thisArraySize + otherArraySize);
- return JSValue::encode(resultArray);
-}
-
bool JSArray::shiftCountWithArrayStorage(VM& vm, unsigned startIndex, unsigned count, ArrayStorage* storage)
{
unsigned oldLength = storage->length();
Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/JSArray.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -23,6 +23,7 @@
#include "ArrayConventions.h"
#include "ButterflyInlines.h"
+#include "JSCellInlines.h"
#include "JSObject.h"
namespace JSC {
@@ -78,19 +79,10 @@
JSArray* fastSlice(ExecState&, unsigned startIndex, unsigned count);
- static IndexingType fastConcatType(VM& vm, JSArray& firstArray, JSArray& secondArray)
- {
- IndexingType type = firstArray.indexingType();
- if (type != secondArray.indexingType())
- return NonArray;
- if (type != ArrayWithDouble && type != ArrayWithInt32 && type != ArrayWithContiguous)
- return NonArray;
- if (firstArray.structure(vm)->holesMustForwardToPrototype(vm)
- || secondArray.structure(vm)->holesMustForwardToPrototype(vm))
- return NonArray;
- return type;
- }
- EncodedJSValue fastConcatWith(ExecState&, JSArray&);
+ bool canFastCopy(VM&, JSArray* otherArray);
+ // This function returns NonArray if the indexing types are not compatable for memcpying.
+ IndexingType memCopyWithIndexingType(IndexingType other);
+ bool appendMemcpy(ExecState*, VM&, JSArray* otherArray);
enum ShiftCountMode {
// This form of shift hints that we're doing queueing. With this assumption in hand,
@@ -152,7 +144,7 @@
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
{
- return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), indexingType);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ArrayType, StructureFlags), info(), indexingType);
}
protected:
Added: trunk/Source/_javascript_Core/runtime/JSArrayInlines.h (0 => 198808)
--- trunk/Source/_javascript_Core/runtime/JSArrayInlines.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/JSArrayInlines.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef JSArrayInlines_h
+#define JSArrayInlines_h
+
+#include "JSArray.h"
+#include "JSCellInlines.h"
+#include "Structure.h"
+
+namespace JSC {
+
+IndexingType JSArray::memCopyWithIndexingType(IndexingType other)
+{
+ IndexingType type = indexingType();
+ if (!(type & IsArray && other & IsArray))
+ return NonArray;
+
+ if (hasAnyArrayStorage(type) || hasAnyArrayStorage(other))
+ return NonArray;
+
+ if (type == ArrayWithUndecided)
+ return other;
+
+ if (other == ArrayWithUndecided)
+ return type;
+
+ // We can memcpy an Int32 and a Contiguous into a Contiguous array since
+ // both share the same memory layout for Int32 numbers.
+ if ((type == ArrayWithInt32 || type == ArrayWithContiguous)
+ && (other == ArrayWithInt32 || other == ArrayWithContiguous)) {
+ if (other == ArrayWithContiguous)
+ return other;
+ return type;
+ }
+
+ if (type != other)
+ return NonArray;
+
+ return type;
+}
+
+bool JSArray::canFastCopy(VM& vm, JSArray* otherArray)
+{
+ if (hasAnyArrayStorage(this->indexingType()) || hasAnyArrayStorage(otherArray->indexingType()))
+ return false;
+ // FIXME: We should have a watchpoint for indexed properties on Array.prototype and Object.prototype
+ // instead of walking the prototype chain. https://bugs.webkit.org/show_bug.cgi?id=155592
+ if (otherArray->structure(vm)->holesMustForwardToPrototype(vm)
+ || otherArray->structure(vm)->holesMustForwardToPrototype(vm))
+ return false;
+ return true;
+}
+
+} // namespace JSC
+
+#endif /* JSArrayInlines_h */
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-03-29 22:57:01 UTC (rev 198808)
@@ -515,6 +515,8 @@
putDirectWithoutTransition(vm, vm.propertyNames->Uint32ArrayPrivateName, m_typedArrays[toIndex(TypeUint32)].constructor.get(), DontEnum);
putDirectWithoutTransition(vm, vm.propertyNames->Float32ArrayPrivateName, m_typedArrays[toIndex(TypeFloat32)].constructor.get(), DontEnum);
putDirectWithoutTransition(vm, vm.propertyNames->Float64ArrayPrivateName, m_typedArrays[toIndex(TypeFloat64)].constructor.get(), DontEnum);
+ putDirectWithoutTransition(vm, vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(vm, vm.propertyNames->ArrayPrivateName, arrayConstructor, DontEnum | DontDelete | ReadOnly);
m_moduleLoader.set(vm, this, ModuleLoaderObject::create(vm, this, ModuleLoaderObject::createStructure(vm, this, m_objectPrototype.get())));
if (Options::exposeInternalModuleLoader())
@@ -537,13 +539,16 @@
JSFunction* privateFuncHasInstanceBoundFunction = JSFunction::create(vm, this, 0, String(), hasInstanceBoundFunction);
JSFunction* privateFuncInstanceOf = JSFunction::create(vm, this, 0, String(), objectPrivateFuncInstanceOf);
JSFunction* privateFuncThisTimeValue = JSFunction::create(vm, this, 0, String(), dateProtoFuncGetTime);
- JSFunction* privateFuncIsArrayConstructor = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArrayConstructor);
+ JSFunction* privateFuncIsArrayConstructor = JSFunction::create(vm, this, 0, String(), arrayConstructorPrivateFuncIsArrayConstructor, IsArrayConstructorIntrinsic);
+ JSFunction* privateFuncIsJSArray = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncIsJSArray, IsJSArrayIntrinsic);
+ 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);
GlobalPropertyInfo staticGlobals[] = {
GlobalPropertyInfo(vm.propertyNames->NaN, jsNaN(), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->Infinity, jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly),
- GlobalPropertyInfo(vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->ownEnumerablePropertyKeysPrivateName, JSFunction::create(vm, this, 0, String(), ownEnumerablePropertyKeys), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->getTemplateObjectPrivateName, privateFuncGetTemplateObject, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->enqueueJobPrivateName, JSFunction::create(vm, this, 0, String(), enqueueJob), DontEnum | DontDelete | ReadOnly),
@@ -556,7 +561,6 @@
GlobalPropertyInfo(vm.propertyNames->hasInstanceBoundFunctionPrivateName, privateFuncHasInstanceBoundFunction, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->instanceOfPrivateName, privateFuncInstanceOf, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->BuiltinLogPrivateName, builtinLog, DontEnum | DontDelete | ReadOnly),
- GlobalPropertyInfo(vm.propertyNames->ArrayPrivateName, arrayConstructor, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->NumberPrivateName, numberConstructor, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->RegExpPrivateName, m_regExpConstructor.get(), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->StringPrivateName, stringConstructor, DontEnum | DontDelete | ReadOnly),
@@ -574,6 +578,10 @@
GlobalPropertyInfo(vm.propertyNames->isMapPrivateName, JSFunction::create(vm, this, 1, String(), privateFuncIsMap), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->isArrayPrivateName, arrayConstructor->getDirect(vm, vm.propertyNames->isArray), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->isArrayConstructorPrivateName, privateFuncIsArrayConstructor, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->isJSArrayPrivateName, privateFuncIsJSArray, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->concatMemcpyPrivateName, privateFuncConcatMemcpy, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->appendMemcpyPrivateName, privateFuncAppendMemcpy, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->builtinNames().concatSlowPathPrivateName(), privateFuncConcatSlowPath, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->MapIteratorPrivateName, JSFunction::create(vm, this, 1, String(), privateFuncMapIterator), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->mapIteratorNextPrivateName, JSFunction::create(vm, this, 0, String(), privateFuncMapIteratorNext), DontEnum | DontDelete | ReadOnly),
Modified: trunk/Source/_javascript_Core/runtime/JSType.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/JSType.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/JSType.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -61,6 +61,7 @@
PureForwardingProxyType,
ImpureProxyType,
WithScopeType,
+ ArrayType,
DirectArgumentsType,
ScopedArgumentsType,
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.h (198807 => 198808)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -91,6 +91,13 @@
return constructEmptyObject(exec, exec->lexicalGlobalObject()->objectPrototype());
}
+inline JSObject* constructObject(ExecState* exec, JSGlobalObject* globalObject, JSValue arg)
+{
+ if (arg.isUndefinedOrNull())
+ return constructEmptyObject(exec, globalObject->objectPrototype());
+ return arg.toObject(exec, globalObject);
+}
+
// Section 6.2.4.4 of the ES6 specification.
// https://tc39.github.io/ecma262/#sec-frompropertydescriptor
inline JSObject* constructObjectFromPropertyDescriptor(ExecState* exec, const PropertyDescriptor& descriptor)
Modified: trunk/Source/_javascript_Core/tests/es6.yaml (198807 => 198808)
--- trunk/Source/_javascript_Core/tests/es6.yaml 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/tests/es6.yaml 2016-03-29 22:57:01 UTC (rev 198808)
@@ -955,7 +955,7 @@
- path: es6/Proxy_internal_get_calls_Array.from.js
cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_Array.prototype.concat.js
- cmd: runES6 :fail
+ cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_Array.prototype.pop.js
cmd: runES6 :normal
- path: es6/Proxy_internal_get_calls_Array.prototype.reverse.js
@@ -1195,7 +1195,7 @@
- path: es6/well-known_symbols_Symbol.hasInstance.js
cmd: runES6 :normal
- path: es6/well-known_symbols_Symbol.isConcatSpreadable.js
- cmd: runES6 :fail
+ cmd: runES6 :normal
- path: es6/well-known_symbols_Symbol.match.js
cmd: runES6 :normal
- path: es6/well-known_symbols_Symbol.replace.js
Added: trunk/Source/_javascript_Core/tests/stress/array-concat-spread-object.js (0 => 198808)
--- trunk/Source/_javascript_Core/tests/stress/array-concat-spread-object.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/array-concat-spread-object.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -0,0 +1,48 @@
+// This file tests is concat spreadable.
+
+function arrayEq(a, b) {
+ if (a.length !== b.length)
+ return false;
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] !== b[i])
+ return false;
+ }
+ return true;
+}
+
+
+{
+ let o = {0:1, 1:2, 2:3, length:3};
+
+ // Test it works with proxies by default
+ for (let i = 0; i < 100000; i++) {
+ if (!arrayEq(Array.prototype.concat.call(o,o), [o,o]))
+ throw "failed normally with an object"
+ }
+
+ // Test it works with spreadable true
+ o[Symbol.isConcatSpreadable] = true;
+ for (let i = 0; i < 100000; i++) {
+ let result = Array.prototype.concat.call(o,o)
+ if (!arrayEq(result, [1,2,3,1,2,3]))
+ throw "failed with spread got: " + result;
+ }
+
+ // Test it works with many things
+ o[Symbol.isConcatSpreadable] = true;
+ let other = {}
+ for (let i = 0; i < 100000; i++) {
+ let result = Array.prototype.concat.call(o,o,true,[1,2],other)
+ if (!arrayEq(result, [1,2,3,1,2,3,true,1,2,other]))
+ throw "failed with spread got: " + result;
+ }
+
+ // Test it works with strings
+ String.prototype[Symbol.isConcatSpreadable] = true;
+ for (let i = 0; i < 100000; i++) {
+ let result = Array.prototype.concat.call("hi","hi")
+ // This is what the spec says is the correct answer... D:
+ if (!arrayEq(result, ["h", "i", "hi"]))
+ throw "failed with string got: " + result;
+ }
+}
Added: trunk/Source/_javascript_Core/tests/stress/array-concat-spread-proxy-exception-check.js (0 => 198808)
--- trunk/Source/_javascript_Core/tests/stress/array-concat-spread-proxy-exception-check.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/array-concat-spread-proxy-exception-check.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -0,0 +1,34 @@
+function arrayEq(a, b) {
+ if (a.length !== b.length)
+ return false;
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] !== b[i])
+ return false;
+ }
+ return true;
+}
+
+{
+ let concat = Array.prototype.concat;
+ noInline(concat);
+ let array = [1, 2, 3];
+ let {proxy:p, revoke} = Proxy.revocable(array, { get : function(o, k) { return o[k]; } });
+
+ concat.call(p,p);
+
+ for (let i = 0; i < 100000; i++) {
+ if (!arrayEq(concat.call(p,p), [1,2,3,1,2,3]))
+ throw "bad";
+ }
+ revoke();
+ failed = true;
+ try {
+ concat.call(p,p);
+ } catch (e) {
+ failed = false;
+ }
+
+ if (failed)
+ throw "bad"
+
+}
Added: trunk/Source/_javascript_Core/tests/stress/array-concat-spread-proxy.js (0 => 198808)
--- trunk/Source/_javascript_Core/tests/stress/array-concat-spread-proxy.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/array-concat-spread-proxy.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -0,0 +1,39 @@
+// This file tests is concat spreadable.
+
+function arrayEq(a, b) {
+ if (a.length !== b.length)
+ return false;
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] !== b[i])
+ return false;
+ }
+ return true;
+}
+
+
+{
+ let array = [1,2,3];
+ let {proxy:p, revoke} = Proxy.revocable(array, { get : function(o, k) { return o[k]; } });
+
+ // Test it works with proxies by default
+ for (let i = 0; i < 100000; i++) {
+ if (!arrayEq(Array.prototype.concat.call(p,p), [1,2,3,1,2,3]))
+ throw "failed normally with a proxy"
+ }
+
+ // Test it works with spreadable false.
+ p[Symbol.isConcatSpreadable] = false;
+ for (let i = 0; i < 100000; i++) {
+ if (!arrayEq(Array.prototype.concat.call(p,p), [p,p]))
+ throw "failed with no spread"
+ }
+
+ p[Symbol.isConcatSpreadable] = undefined;
+ revoke();
+ passed = true;
+ try {
+ Array.prototype.concat.call(p,[]);
+ passed = false;
+ } catch (e) { }
+
+}
Added: trunk/Source/_javascript_Core/tests/stress/array-concat-with-slow-indexingtypes.js (0 => 198808)
--- trunk/Source/_javascript_Core/tests/stress/array-concat-with-slow-indexingtypes.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/array-concat-with-slow-indexingtypes.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -0,0 +1,35 @@
+function arrayEq(a, b) {
+ if (a.length !== b.length)
+ return false;
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] !== b[i])
+ return false;
+ }
+ return true;
+}
+
+
+{
+
+ array = [1,2];
+ Object.defineProperty(array, 2, { get: () => { return 1; } });
+
+ for (let i = 0; i < 100000; i++) {
+ if (!arrayEq(Array.prototype.concat.call(array,array), [1,2,1,1,2,1]))
+ throw "failed normally with a getter"
+ if (!arrayEq(Array.prototype.concat.call([],array), [1,2,1]))
+ throw "failed with undecided and a getter"
+ }
+
+ // Test with indexed types on prototype.
+ array = [1,2];
+ array.length = 3;
+ Array.prototype[2] = 1;
+
+ for (let i = 0; i < 100000; i++) {
+ if (!arrayEq(Array.prototype.concat.call(array,array), [1,2,1,1,2,1]))
+ throw "failed normally with an indexed prototype"
+ if (!arrayEq(Array.prototype.concat.call([],array), [1,2,1]))
+ throw "failed with undecided and an indexed prototype"
+ }
+}
Modified: trunk/Source/_javascript_Core/tests/stress/array-species-config-array-constructor.js (198807 => 198808)
--- trunk/Source/_javascript_Core/tests/stress/array-species-config-array-constructor.js 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/_javascript_Core/tests/stress/array-species-config-array-constructor.js 2016-03-29 22:57:01 UTC (rev 198808)
@@ -16,6 +16,9 @@
Object.defineProperty(Array, Symbol.species, { value: Int32Array, configurable: true });
+// We can't write to the length property on a typed array by default.
+Object.defineProperty(Int32Array.prototype, "length", { value: 0, writable: true });
+
result = foo.concat([1]);
if (!(result instanceof Int32Array))
throw "concat failed";
Modified: trunk/Source/WebCore/ChangeLog (198807 => 198808)
--- trunk/Source/WebCore/ChangeLog 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/WebCore/ChangeLog 2016-03-29 22:57:01 UTC (rev 198808)
@@ -1,3 +1,15 @@
+2016-03-29 Keith Miller <keith_mil...@apple.com>
+
+ [ES6] Add support for Symbol.isConcatSpreadable.
+ https://bugs.webkit.org/show_bug.cgi?id=155351
+
+ Reviewed by Saam Barati.
+
+ Makes runtime arrays have the new ArrayType
+
+ * bridge/runtime_array.h:
+ (JSC::RuntimeArray::createStructure):
+
2016-03-29 Nan Wang <n_w...@apple.com>
AX: VoiceOver: Navigating Numbered Lists Causes Number to be announced On Each Line of List
Modified: trunk/Source/WebCore/bridge/runtime_array.h (198807 => 198808)
--- trunk/Source/WebCore/bridge/runtime_array.h 2016-03-29 22:23:42 UTC (rev 198807)
+++ trunk/Source/WebCore/bridge/runtime_array.h 2016-03-29 22:57:01 UTC (rev 198808)
@@ -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(ArrayType, StructureFlags), info(), ArrayClass);
}
protected: