1// Copyright 2018 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5namespace array { 6macro LoadElement<ElementsAccessor : type extends ElementsKind, T: type>( 7 elements: FixedArrayBase, index: Smi): T; 8 9LoadElement<array::FastPackedSmiElements, Smi>(implicit context: Context)( 10 elements: FixedArrayBase, index: Smi): Smi { 11 const elements: FixedArray = UnsafeCast<FixedArray>(elements); 12 return UnsafeCast<Smi>(elements.objects[index]); 13} 14 15LoadElement<array::FastPackedObjectElements, JSAny>(implicit context: Context)( 16 elements: FixedArrayBase, index: Smi): JSAny { 17 const elements: FixedArray = UnsafeCast<FixedArray>(elements); 18 return UnsafeCast<JSAny>(elements.objects[index]); 19} 20 21LoadElement<array::FastPackedDoubleElements, float64>( 22 implicit context: Context)(elements: FixedArrayBase, index: Smi): float64 { 23 const elements: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements); 24 // This macro is only used for PACKED_DOUBLE, loading the hole should 25 // be impossible. 26 return elements.floats[index].Value() otherwise unreachable; 27} 28 29macro StoreElement<ElementsAccessor : type extends ElementsKind, T: type>( 30 implicit context: Context)( 31 elements: FixedArrayBase, index: Smi, value: T): void; 32 33StoreElement<array::FastPackedSmiElements, Smi>(implicit context: Context)( 34 elements: FixedArrayBase, index: Smi, value: Smi): void { 35 const elems: FixedArray = UnsafeCast<FixedArray>(elements); 36 StoreFixedArrayElement(elems, index, value); 37} 38 39StoreElement<array::FastPackedObjectElements, JSAny>(implicit context: Context)( 40 elements: FixedArrayBase, index: Smi, value: JSAny): void { 41 const elements: FixedArray = UnsafeCast<FixedArray>(elements); 42 elements.objects[index] = value; 43} 44 45StoreElement<array::FastPackedDoubleElements, float64>( 46 implicit context: Context)( 47 elements: FixedArrayBase, index: Smi, value: float64): void { 48 const elems: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements); 49 StoreFixedDoubleArrayElement(elems, index, value); 50} 51 52// Fast-path for all PACKED_* elements kinds. These do not need to check 53// whether a property is present, so we can simply swap them using fast 54// FixedArray loads/stores. 55macro FastPackedArrayReverse<Accessor: type, T: type>( 56 implicit context: Context)(elements: FixedArrayBase, length: Smi): void { 57 let lower: Smi = 0; 58 let upper: Smi = length - 1; 59 60 while (lower < upper) { 61 const lowerValue: T = LoadElement<Accessor, T>(elements, lower); 62 const upperValue: T = LoadElement<Accessor, T>(elements, upper); 63 StoreElement<Accessor>(elements, lower, upperValue); 64 StoreElement<Accessor>(elements, upper, lowerValue); 65 ++lower; 66 --upper; 67 } 68} 69 70transitioning macro GenericArrayReverse( 71 context: Context, receiver: JSAny): JSAny { 72 // 1. Let O be ? ToObject(this value). 73 const object: JSReceiver = ToObject_Inline(context, receiver); 74 75 // 2. Let len be ? ToLength(? Get(O, "length")). 76 const length: Number = GetLengthProperty(object); 77 78 // 3. Let middle be floor(len / 2). 79 // 4. Let lower be 0. 80 // 5. Repeat, while lower != middle. 81 // a. Let upper be len - lower - 1. 82 83 // Instead of calculating the middle value, we simply initialize upper 84 // with len - 1 and decrement it after each iteration. 85 let lower: Number = 0; 86 let upper: Number = length - 1; 87 88 while (lower < upper) { 89 let lowerValue: JSAny = Undefined; 90 let upperValue: JSAny = Undefined; 91 92 // b. Let upperP be ! ToString(upper). 93 // c. Let lowerP be ! ToString(lower). 94 // d. Let lowerExists be ? HasProperty(O, lowerP). 95 const lowerExists: Boolean = HasProperty(object, lower); 96 97 // e. If lowerExists is true, then. 98 if (lowerExists == True) { 99 // i. Let lowerValue be ? Get(O, lowerP). 100 lowerValue = GetProperty(object, lower); 101 } 102 103 // f. Let upperExists be ? HasProperty(O, upperP). 104 const upperExists: Boolean = HasProperty(object, upper); 105 106 // g. If upperExists is true, then. 107 if (upperExists == True) { 108 // i. Let upperValue be ? Get(O, upperP). 109 upperValue = GetProperty(object, upper); 110 } 111 112 // h. If lowerExists is true and upperExists is true, then 113 if (lowerExists == True && upperExists == True) { 114 // i. Perform ? Set(O, lowerP, upperValue, true). 115 SetProperty(object, lower, upperValue); 116 117 // ii. Perform ? Set(O, upperP, lowerValue, true). 118 SetProperty(object, upper, lowerValue); 119 } else if (lowerExists == False && upperExists == True) { 120 // i. Perform ? Set(O, lowerP, upperValue, true). 121 SetProperty(object, lower, upperValue); 122 123 // ii. Perform ? DeletePropertyOrThrow(O, upperP). 124 DeleteProperty(object, upper, LanguageMode::kStrict); 125 } else if (lowerExists == True && upperExists == False) { 126 // i. Perform ? DeletePropertyOrThrow(O, lowerP). 127 DeleteProperty(object, lower, LanguageMode::kStrict); 128 129 // ii. Perform ? Set(O, upperP, lowerValue, true). 130 SetProperty(object, upper, lowerValue); 131 } 132 133 // l. Increase lower by 1. 134 ++lower; 135 --upper; 136 } 137 138 // 6. Return O. 139 return object; 140} 141 142macro TryFastPackedArrayReverse(implicit context: Context)(receiver: JSAny): 143 void labels Slow { 144 const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; 145 146 const kind: ElementsKind = array.map.elements_kind; 147 if (kind == ElementsKind::PACKED_SMI_ELEMENTS) { 148 array::EnsureWriteableFastElements(array); 149 FastPackedArrayReverse<array::FastPackedSmiElements, Smi>( 150 array.elements, array.length); 151 } else if (kind == ElementsKind::PACKED_ELEMENTS) { 152 array::EnsureWriteableFastElements(array); 153 FastPackedArrayReverse<array::FastPackedObjectElements, JSAny>( 154 array.elements, array.length); 155 } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) { 156 FastPackedArrayReverse<array::FastPackedDoubleElements, float64>( 157 array.elements, array.length); 158 } else { 159 goto Slow; 160 } 161} 162 163// https://tc39.github.io/ecma262/#sec-array.prototype.reverse 164transitioning javascript builtin ArrayPrototypeReverse( 165 js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 166 try { 167 TryFastPackedArrayReverse(receiver) otherwise Baseline; 168 return receiver; 169 } label Baseline { 170 return GenericArrayReverse(context, receiver); 171 } 172} 173} 174