1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16declare interface ArkTools { 17 isAOTCompiled(args: any): boolean 18} 19 20//int array 21let literalIntArrayWithHole = [0, , 2, , 4, ,] 22let nIntArray = new Array(6) 23nIntArray[0] = 0 24nIntArray[2] = 2 25nIntArray[4] = 4 26function returnDoubleTypeIntNotConstant (x) { 27 if (x > 0) { 28 return 3.5 + 0.5 29 } else { 30 return 1.5 + 0.5 31 } 32} 33//double array 34let literalDoubleArrayWithHole = [0.5, , 2.5, , 4.5, ,] 35function returnNotConstantDouble (x) { 36 if (x > 0) { 37 return 4 + 0.5 38 } else { 39 return 2 + 0.5 40 } 41} 42let nDoubleArray = new Array(5) 43nDoubleArray[1] = 1.5 44nDoubleArray[4] = 4.5 45//string array 46let literalStringArrayWithHole = ['string1', , 'string2', , 'string4', ,] 47let nStringArray = new Array(5) 48nStringArray[1] = '1' 49nStringArray[4] = '4' 50function returnNotLitaralString (x) { 51 if (x > 0) { 52 return 'string' + '4' 53 } else { 54 return 'string4' 55 } 56} 57//object array 58let find1 = { 1: 1 } 59class findClass { 60 x 61 constructor (x) { 62 this.x = x 63 } 64} 65let find3 = new findClass(3) 66let find5 = new Date() 67let objArrayWithHoleNeverFind = [{ 0: 0 }, , { 2: 2 }, , { 4: 4 }, ,] 68let objnewArraywithHoleNeverFind = new Array(7) 69objnewArraywithHoleNeverFind[0] = { 0: 0 } 70objnewArraywithHoleNeverFind[2] = { 2: 2 } 71objnewArraywithHoleNeverFind[4] = { 4: 4 } 72 73let objArrayWithHoleCanFind = [, find1, , find3, , find5] 74let objnewArraywithHoleCanFind = new Array(7) 75objnewArraywithHoleCanFind[1] = find1 76objnewArraywithHoleCanFind[3] = find3 77objnewArraywithHoleCanFind[5] = find5 78 79//====================start nomarl kind test=================// 80//lastIndexOf int 81print('---- Case group #1: int[] ----') //: ---- Case group #1: int[] ---- 82//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 83print('case 1.1: ', literalIntArrayWithHole.lastIndexOf(4)) //: case 1.1: 4 84//aot: [trace] aot inline function name: #*#returnDoubleTypeIntNotConstant@builtinArrayLastIndexOf caller function name: func_main_0@builtinArrayLastIndexOf 85//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 86print( 87 'case 1.2: ', 88 literalIntArrayWithHole.lastIndexOf(returnDoubleTypeIntNotConstant(1)) 89) //: case 1.2: 4 90//aot: [trace] aot inline function name: #*#returnDoubleTypeIntNotConstant@builtinArrayLastIndexOf caller function name: func_main_0@builtinArrayLastIndexOf 91//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 92print( 93 'case 1.3: ', 94 literalIntArrayWithHole.lastIndexOf(returnDoubleTypeIntNotConstant(0)) 95) //: case 1.3: 2 96//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 97print('case 1.4: ', nIntArray.lastIndexOf(4)) //: case 1.4: 4 98//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 99print('case 1.5: ', literalIntArrayWithHole.lastIndexOf(undefined)) //: case 1.5: -1 100//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 101print('case 1.6: ', nIntArray.lastIndexOf(nIntArray.length)) //: case 1.6: -1 102 103//lastIndexOf double 104print('---- Case group #2: double[] ----') //: ---- Case group #2: double[] ---- 105//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 106print('case 2.1: ', literalDoubleArrayWithHole.lastIndexOf(4.5)) //: case 2.1: 4 107//aot: [trace] aot inline function name: #*#returnNotConstantDouble@builtinArrayLastIndexOf caller function name: func_main_0@builtinArrayLastIndexOf 108//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 109print( 110 'case 2.2: ', 111 literalDoubleArrayWithHole.lastIndexOf(returnNotConstantDouble(1)) 112) //: case 2.2: 4 113//aot: [trace] aot inline function name: #*#returnNotConstantDouble@builtinArrayLastIndexOf caller function name: func_main_0@builtinArrayLastIndexOf 114//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 115print( 116 'case 2.3: ', 117 literalDoubleArrayWithHole.lastIndexOf(returnNotConstantDouble(0)) 118) //: case 2.3: 2 119//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 120print('case 2.4: ', nDoubleArray.lastIndexOf(4.5)) //: case 2.4: 4 121//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 122print('case 2.5: ', literalDoubleArrayWithHole.lastIndexOf(undefined)) //: case 2.5: -1 123 124//lastIndexOf string 125print('---- Case group #3: string[] ----') //: ---- Case group #3: string[] ---- 126//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 127print('case 3.1: ', literalStringArrayWithHole.lastIndexOf('string4')) //: case 3.1: 4 128//aot: [trace] aot inline function name: #*#returnNotLitaralString@builtinArrayLastIndexOf caller function name: func_main_0@builtinArrayLastIndexOf 129//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 130print( 131 'case 3.2: ', 132 literalStringArrayWithHole.lastIndexOf(returnNotLitaralString(1)) 133) //: case 3.2: 4 134//aot: [trace] aot inline function name: #*#returnNotLitaralString@builtinArrayLastIndexOf caller function name: func_main_0@builtinArrayLastIndexOf 135//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 136print( 137 'case 3.3: ', 138 literalStringArrayWithHole.lastIndexOf(returnNotLitaralString(0)) 139) //: case 3.3: 4 140//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 141print('case 3.4: ', nStringArray.lastIndexOf('4')) //: case 3.4: 4 142//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 143print('case 3.5: ', nStringArray.lastIndexOf(undefined)) //: case 3.5: -1 144 145//lastIndexOf obj 146print('---- Case group #4: object[] ----') //: ---- Case group #4: object[] ---- 147//neverequal 148//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 149print('case 4.1: ', objArrayWithHoleNeverFind.lastIndexOf({ 4: 4 })) //: case 4.1: -1 150//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 151print('case 4.2: ', objnewArraywithHoleNeverFind.lastIndexOf({ 4: 4 })) //: case 4.2: -1 152//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 153print('case 4.3: ', objnewArraywithHoleNeverFind.lastIndexOf(undefined)) //: case 4.3: -1 154//can find 155//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 156print('case 4.4: ', objArrayWithHoleCanFind.lastIndexOf(find1)) //: case 4.4: 1 157//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 158print('case 4.5: ', objArrayWithHoleCanFind.lastIndexOf(find3)) //: case 4.5: 3 159//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 160print('case 4.6: ', objArrayWithHoleCanFind.lastIndexOf(find5)) //: case 4.6: 5 161//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 162print('case 4.7: ', objnewArraywithHoleCanFind.lastIndexOf(find1)) //: case 4.7: 1 163//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 164print('case 4.8: ', objnewArraywithHoleCanFind.lastIndexOf(find3)) //: case 4.8: 3 165//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 166print('case 4.9: ', objnewArraywithHoleCanFind.lastIndexOf(find5)) //: case 4.9: 5 167 168//============special test 169print('---- Case group #5: special array ----') //: ---- Case group #5: special array ---- 170//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinArrayLastIndexOf 171let specialArray = [ 172 null, 173 , 174 false, 175 true, 176 undefined, 177 +0, 178 -0, 179 BigInt(123456), 180 NaN, 181 5, 182 5.5 183] 184//lastIndexOf use strict equal 185//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 186print('case 5.1: ', specialArray.lastIndexOf(NaN)) //: case 5.1: -1 187//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 188print('case 5.2: ', specialArray.lastIndexOf(undefined, 3)) //: case 5.2: -1 189//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 190print('case 5.3: ', specialArray.lastIndexOf(undefined)) //: case 5.3: 4 191//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 192print('case 5.4: ', specialArray.lastIndexOf(NaN)) //: case 5.4: -1 193//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 194print('case 5.5: ', specialArray.lastIndexOf(+0)) //: case 5.5: 6 195//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 196print('case 5.6: ', specialArray.lastIndexOf(-0)) //: case 5.6: 6 197//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 198print('case 5.7: ', specialArray.lastIndexOf(false)) //: case 5.7: 2 199//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 200print('case 5.8: ', specialArray.lastIndexOf(true)) //: case 5.8: 3 201//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 202print('case 5.9: ', specialArray.lastIndexOf(null)) //: case 5.9: 0 203//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinArrayLastIndexOf 204//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 205print('case 5.10: ', specialArray.lastIndexOf(BigInt(123456))) //: case 5.10: 7 206//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 207print('case 5.11: ', specialArray.lastIndexOf(5)) //: case 5.11: 9 208//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 209print('case 5.12: ', specialArray.lastIndexOf(5.5)) //: case 5.12: 10 210 211print('---- Case group #6: unusual cases ----') //: ---- Case group #6: unusual cases ---- 212//aot: [trace] aot call builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 213print('case 6.1: ', specialArray.lastIndexOf()) //: case 6.1: 4 214//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 215print( 216 'case 6.2: ', 217 specialArray.lastIndexOf(() => {}) 218) //: case 6.2: -1 219//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 220print('case 6.3: ', specialArray.lastIndexOf(true, 2000000)) //: case 6.3: 3 221//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 222print('case 6.4: ', specialArray.lastIndexOf(true, -2000000)) //: case 6.4: -1 223//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 224print('case 6.5: ', specialArray.lastIndexOf(true, -1)) //: case 6.5: 3 225//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 226print('case 6.6: ', specialArray.lastIndexOf(5, 5, 78)) //: case 6.6: -1 227 228print('---- Case group #7: not int index ----') //: ---- Case group #7: not int index ---- 229function notIntIndex () { 230 let specialArray = [1, 2, NaN] 231 //aot: [trace] Check Type: IndexNotInt 232 print('case 7.1: ', specialArray.lastIndexOf(false, 'str')) 233} 234notIntIndex() //: case 7.1: -1 235 236// Check inside try-block 237print('---- Case group #8: inside try-block ----') //: ---- Case group #8: inside try-block ---- 238try { 239 //aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 240 print('case 8.1: ', specialArray.lastIndexOf(null)) //: case 8.1: 0 241} catch (e) {} 242 243print('---- Case group #9: target with valueOf ----') //: ---- Case group #9: target with valueOf ---- 244let obj = {} 245obj.valueOf = () => { 246 return 5 247} 248//aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 249print('case 9.1: ', specialArray.lastIndexOf(obj)) //: case 9.1: -1 250 251print('---- Case group #10: throwing ----') //: ---- Case group #10: throwing ---- 252function Throwing () { 253 this.value = 2 254 Throwing.prototype.valueOf = function () { 255 if (this.value > 0) { 256 throw new Error('positive') 257 } 258 return this.value 259 } 260} 261let throwingObj = new Throwing() 262try { 263 //aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 264 print('case 10.1: ', specialArray.lastIndexOf(throwingObj)) //: case 10.1: -1 265} catch (e) { 266 print(e) 267} finally { 268 //aot: [trace] aot inline builtin: Array.LastIndexOf, caller function name:func_main_0@builtinArrayLastIndexOf 269 print('case 10.2: ', specialArray.lastIndexOf(obj)) //: case 10.2: -1 270} 271 272//===========deopt type 273print('---- Case group #11: de-opt ----') //: ---- Case group #11: de-opt ---- 274//aot: [trace] Check Type: NotStableArray1 275function prototypeChange () { 276 let tArray = [1, , 3] 277 Array.prototype[1] = 2 278 print('case ProtoChange: ', tArray.lastIndexOf(2)) 279} 280prototypeChange() //: case ProtoChange: 1 281 282//aot: [trace] Check Type: NotStableArray1 283function lengthChange () { 284 let tArray = [1, , 3] 285 tArray.length = 2 286 print('case LengthChange: ', tArray.lastIndexOf(3)) 287} 288lengthChange() //: case LengthChange: -1 289 290// Replace standard builtin 291function replace (a: any) { 292 return a 293} 294 295let newArr = [1, 2, NaN] 296let true_lastIndexOf = newArr.lastIndexOf 297newArr.lastIndexOf = replace 298 299print('case BuiltinFunctionChange: ', newArr.lastIndexOf(undefined)) //: case BuiltinFunctionChange: undefined 300newArr.lastIndexOf = true_lastIndexOf 301//aot: [trace] Check Type: BuiltinInstanceHClassMismatch 302print('case BuiltinHClassMismatch: ', newArr.lastIndexOf(undefined)) //: case BuiltinHClassMismatch: -1 303 304function dolastIndexOf (x: any): any { 305 return newArr.lastIndexOf(x) 306} 307 308function printlastIndexOf (promptStr: string, x: any) { 309 try { 310 print(promptStr, dolastIndexOf(x)) 311 } finally { 312 } 313} 314 315let promptStr = 'pgo: ' 316if (ArkTools.isAOTCompiled(printlastIndexOf)) { 317 // Replace standard builtin after call to standard builtin was profiled 318 newArr.lastIndexOf = replace 319 promptStr = 'aot: ' 320} 321printlastIndexOf(promptStr, 2) //pgo: pgo: 1 322//aot: [trace] Check Type: NotCallTarget1 323//aot: aot: 2 324 325printlastIndexOf(promptStr, 'abc') //pgo: pgo: -1 326//aot: [trace] Check Type: NotCallTarget1 327//aot: aot: abc 328 329newArr.lastIndexOf = true_lastIndexOf 330 331function lastIndexOfCase1 () { 332 print('case 1 lastIndexOf') //: case 1 lastIndexOf 333 let arr1 = [1, 2] 334 let arr2 = [1, 2] 335 arr2.garbage = function (x: any): any { 336 return undefined 337 } 338 //aot: [trace] Check Type: NotStableArray1 339 print('de-opt case 1.1: ', arr1.lastIndexOf(1)) //: de-opt case 1.1: 0 340 print('de-opt case 1.2: ', arr2.lastIndexOf(2)) //: de-opt case 1.2: 1 341} 342lastIndexOfCase1() 343 344function lastIndexOfCase2 () { 345 print('case 2 lastIndexOf') //: case 2 lastIndexOf 346 let arr1 = [1, 2] 347 let arr2 = [1, 2] 348 arr2.lastIndexOf = function (x: any) { 349 return x 350 } 351 352 //aot: [trace] aot inline builtin: Object.getPrototypeOf, caller function name:#*#lastIndexOfCase2@builtinArrayLastIndexOf 353 print(Object.getPrototypeOf(arr2) === Array.prototype) //: true 354 355 //aot: [trace] Check Type: NotStableArray1 356 print('de-opt case 2.1: ', arr1.lastIndexOf(1)) //: de-opt case 2.1: 0 357 print('de-opt case 2.2: ', arr2.lastIndexOf(1)) //: de-opt case 2.2: 1 358} 359lastIndexOfCase2() 360 361function lastIndexOfCase3 () { 362 print('case 3 lastIndexOf') //: case 3 lastIndexOf 363 let marr = [1, 2] 364 let true_lastIndexOf = marr.lastIndexOf 365 let mimicArray = { 366 lastIndexOf: true_lastIndexOf 367 } 368 369 //aot: [trace] Check Type: NotStableArray1 370 print('de-opt case 3.1: ', marr.lastIndexOf(500)) //: de-opt case 3.1: -1 371 Object.setPrototypeOf(marr, mimicArray) 372 373 print('de-opt case 3.2: ', marr.lastIndexOf(500)) //: de-opt case 3.2: -1 374} 375lastIndexOfCase3() 376 377function lastIndexOfCase4 () { 378 print('case 4 lastIndexOf') //: case 4 lastIndexOf 379 let arr1 = [1, 2] 380 let arr2 = [1, 2] 381 let notArray = { 382 lastIndexOf (x: any) { 383 return -100 384 } 385 } 386 //aot: [trace] aot call builtin: Object.SetPrototypeOf, caller function name:#*#lastIndexOfCase4@builtinArrayLastIndexOf 387 Object.setPrototypeOf(arr2, notArray) 388 389 //aot: [trace] Check Type: NotStableArray1 390 print('de-opt case 4.1: ', arr1.lastIndexOf(1)) //: de-opt case 4.1: 0 391 print('de-opt case 4.2: ', arr2.lastIndexOf(1)) //: de-opt case 4.2: -100 392} 393lastIndexOfCase4() 394 395function lastIndexOfCase5 () { 396 print('case 5 lastIndexOf') //: case 5 lastIndexOf 397 let arr1 = [1, 2] 398 Array.prototype.lastIndexOf = function (x: any) { 399 return x 400 } 401 402 //aot: [trace] Check Type: NotStableArray1 403 print('de-opt case 5.1: ', arr1.lastIndexOf(300)) //: de-opt case 5.1: 300 404} 405lastIndexOfCase5() 406