diff --git a/src/builtins/array-reverse.tq b/src/builtins/array-reverse.tq index 69a678a513..b5835f8be9 100644 --- a/src/builtins/array-reverse.tq +++ b/src/builtins/array-reverse.tq @@ -3,65 +3,50 @@ // found in the LICENSE file. namespace array { -macro LoadElement( +macro LoadElement( elements: FixedArrayBase, index: Smi): T; -LoadElement(implicit context: Context)( - elements: FixedArrayBase, index: Smi): Smi { +LoadElement(implicit context: Context)( + elements: FixedArrayBase, index: Smi): Object { const elements: FixedArray = UnsafeCast(elements); - return UnsafeCast(elements.objects[index]); + return elements.objects[index]; } -LoadElement(implicit context: Context)( - elements: FixedArrayBase, index: Smi): JSAny { - const elements: FixedArray = UnsafeCast(elements); - return UnsafeCast(elements.objects[index]); -} - -LoadElement( - implicit context: Context)(elements: FixedArrayBase, index: Smi): float64 { +LoadElement(implicit context: Context)( + elements: FixedArrayBase, index: Smi): float64_or_hole { const elements: FixedDoubleArray = UnsafeCast(elements); - // This macro is only used for PACKED_DOUBLE, loading the hole should - // be impossible. - return elements.floats[index].Value() otherwise unreachable; + return elements.floats[index]; } -macro StoreElement( +macro StoreElement( implicit context: Context)( elements: FixedArrayBase, index: Smi, value: T): void; -StoreElement(implicit context: Context)( - elements: FixedArrayBase, index: Smi, value: Smi): void { - const elems: FixedArray = UnsafeCast(elements); - StoreFixedArrayElement(elems, index, value); -} - -StoreElement(implicit context: Context)( - elements: FixedArrayBase, index: Smi, value: JSAny): void { +StoreElement(implicit context: Context)( + elements: FixedArrayBase, index: Smi, value: Object): void { const elements: FixedArray = UnsafeCast(elements); elements.objects[index] = value; } -StoreElement( - implicit context: Context)( - elements: FixedArrayBase, index: Smi, value: float64): void { +StoreElement(implicit context: Context)( + elements: FixedArrayBase, index: Smi, value: float64_or_hole): void { const elems: FixedDoubleArray = UnsafeCast(elements); - StoreFixedDoubleArrayElement(elems, index, value); + elems.floats[index] = value; } // Fast-path for all PACKED_* elements kinds. These do not need to check // whether a property is present, so we can simply swap them using fast // FixedArray loads/stores. -macro FastPackedArrayReverse( +macro FastArrayReverse( implicit context: Context)(elements: FixedArrayBase, length: Smi): void { let lower: Smi = 0; let upper: Smi = length - 1; while (lower < upper) { - const lowerValue: T = LoadElement(elements, lower); - const upperValue: T = LoadElement(elements, upper); - StoreElement(elements, lower, upperValue); - StoreElement(elements, upper, lowerValue); + const lowerValue: T = LoadElement(elements, lower); + const upperValue: T = LoadElement(elements, upper); + StoreElement(elements, lower, upperValue); + StoreElement(elements, upper, lowerValue); ++lower; --upper; } @@ -144,19 +129,27 @@ macro TryFastPackedArrayReverse(implicit context: Context)(receiver: JSAny): const array: FastJSArray = Cast(receiver) otherwise Slow; const kind: ElementsKind = array.map.elements_kind; - if (kind == ElementsKind::PACKED_SMI_ELEMENTS) { + if (kind == ElementsKind::PACKED_SMI_ELEMENTS || + kind == ElementsKind::PACKED_ELEMENTS) { array::EnsureWriteableFastElements(array); - FastPackedArrayReverse( - array.elements, array.length); - } else if (kind == ElementsKind::PACKED_ELEMENTS) { - array::EnsureWriteableFastElements(array); - FastPackedArrayReverse( - array.elements, array.length); + FastArrayReverse(array.elements, array.length); } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) { - FastPackedArrayReverse( + FastArrayReverse( array.elements, array.length); } else { - goto Slow; + if (!IsPrototypeInitialArrayPrototype(array.map)) goto Slow; + if (IsNoElementsProtectorCellInvalid()) goto Slow; + + if (kind == ElementsKind::HOLEY_SMI_ELEMENTS || + kind == ElementsKind::HOLEY_ELEMENTS) { + array::EnsureWriteableFastElements(array); + FastArrayReverse(array.elements, array.length); + } else if (kind == ElementsKind::HOLEY_DOUBLE_ELEMENTS) { + FastArrayReverse( + array.elements, array.length); + } else { + goto Slow; + } } } diff --git a/src/builtins/array-to-reversed.tq b/src/builtins/array-to-reversed.tq index 5d97d6546e..5194174c17 100644 --- a/src/builtins/array-to-reversed.tq +++ b/src/builtins/array-to-reversed.tq @@ -3,7 +3,7 @@ // found in the LICENSE file. namespace array { -macro FastPackedArrayToReversed( +macro FastArrayToReversed( implicit context: Context)( kind: constexpr ElementsKind, elements: FixedArrayBase, length: Smi): JSArray { @@ -21,10 +21,10 @@ macro FastPackedArrayToReversed( const from = length - k - 1; // c. Let fromValue be ? Get(O, from). - const fromValue: T = LoadElement(elements, from); + const fromValue: T = LoadElement(elements, from); // d. Perform ! CreateDataPropertyOrThrow(A, Pk, fromValue). - StoreElement(copy, k, fromValue); + StoreElement(copy, k, fromValue); // e. Set k to k + 1. ++k; @@ -35,7 +35,7 @@ macro FastPackedArrayToReversed( return NewJSArray(map, copy); } -macro TryFastPackedArrayToReversed(implicit context: Context)(receiver: JSAny): +macro TryFastArrayToReversed(implicit context: Context)(receiver: JSAny): JSArray labels Slow { const array: FastJSArray = Cast(receiver) otherwise Slow; @@ -43,19 +43,31 @@ macro TryFastPackedArrayToReversed(implicit context: Context)(receiver: JSAny): const kind: ElementsKind = array.map.elements_kind; if (kind == ElementsKind::PACKED_SMI_ELEMENTS) { - return FastPackedArrayToReversed( + return FastArrayToReversed( ElementsKind::PACKED_SMI_ELEMENTS, array.elements, array.length); - } - if (kind == ElementsKind::PACKED_ELEMENTS) { - return FastPackedArrayToReversed( + } else if (kind == ElementsKind::PACKED_ELEMENTS) { + return FastArrayToReversed( ElementsKind::PACKED_ELEMENTS, array.elements, array.length); - } - if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) { - return FastPackedArrayToReversed( + } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) { + return FastArrayToReversed( ElementsKind::PACKED_DOUBLE_ELEMENTS, array.elements, array.length); - } + } else { + if (!IsPrototypeInitialArrayPrototype(array.map)) goto Slow; + if (IsNoElementsProtectorCellInvalid()) goto Slow; - goto Slow; + if (kind == ElementsKind::HOLEY_SMI_ELEMENTS) { + return FastArrayToReversed( + ElementsKind::HOLEY_SMI_ELEMENTS, array.elements, array.length); + } else if (kind == ElementsKind::HOLEY_ELEMENTS) { + return FastArrayToReversed( + ElementsKind::HOLEY_ELEMENTS, array.elements, array.length); + } else if (kind == ElementsKind::HOLEY_DOUBLE_ELEMENTS) { + return FastArrayToReversed( + ElementsKind::HOLEY_DOUBLE_ELEMENTS, array.elements, array.length); + } + + goto Slow; + } } transitioning builtin GenericArrayToReversed(implicit context: Context)( @@ -96,7 +108,7 @@ transitioning builtin GenericArrayToReversed(implicit context: Context)( transitioning javascript builtin ArrayPrototypeToReversed( js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { try { - return TryFastPackedArrayToReversed(receiver) otherwise Slow; + return TryFastArrayToReversed(receiver) otherwise Slow; } label Slow { return GenericArrayToReversed(receiver); } diff --git a/test/mjsunit/array-reverse.js b/test/mjsunit/array-reverse.js index 11aeb60cac..a2918a9bd6 100644 --- a/test/mjsunit/array-reverse.js +++ b/test/mjsunit/array-reverse.js @@ -10,6 +10,8 @@ assertArrayEquals(["str4", "str3", "str2"], ["str2", "str3", "str4"].reverse()); assertArrayEquals([4,3,,1], [1,,3,4].reverse()); assertArrayEquals([4,,2,1], [1,2,,4].reverse()); assertArrayEquals([5,,3,,1], [1,,3,,5].reverse()); +assertArrayEquals([0.5,,0.3,,0.1], [0.1,,0.3,,0.5].reverse()); +assertArrayEquals(["5",,"3",,"1"], ["1",,"3",,"5"].reverse()); function TestReverseWithObject() { let obj = { length: 5 }; diff --git a/test/mjsunit/harmony/array-to-reversed.js b/test/mjsunit/harmony/array-to-reversed.js index caae4079ab..0835aacf74 100644 --- a/test/mjsunit/harmony/array-to-reversed.js +++ b/test/mjsunit/harmony/array-to-reversed.js @@ -31,6 +31,30 @@ assertEquals("toReversed", Array.prototype.toReversed.name); assertFalse(a === r); })(); +(function TestSmiHoley() { + let a = [1,,3,4]; + let r = a.toReversed(); + assertEquals([1,,3,4], a); + assertEquals([4,3,,1], r); + assertFalse(a === r); +})(); + +(function TestDoubleHoley() { + let a = [1.1,,3.3,4.4]; + let r = a.toReversed(); + assertEquals([1.1,,3.3,4.4], a); + assertEquals([4.4,3.3,,1.1], r); + assertFalse(a === r); +})(); + +(function TestHoley() { + let a = [true,false,,1,42.42]; + let r = a.toReversed(); + assertEquals([true,false,,1,42.42], a); + assertEquals([42.42,1,,false,true], r); + assertFalse(a === r); +})(); + (function TestGeneric() { let a = { length: 4, get "0"() { return "hello"; },