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 16/* 17 * Description: 18 * 1. This code tests the lazy deoptimization that occurs in ldobjbyname. 19 * After the JIT code for a function is compiled, modifying its associated HClass 20 * invalidates the function, and subsequent accesses will detect this invalidation. 21 * 2. Function Test2 is used to trigger lazy deoptimization by modifying the prototype, 22 * and then deopt itself by "print("Test2 obj2:", obj2.y)". 23 * 3. Test2 call ChangePrototypeValue not inlined. 24 * 4. Test call Test2 not inlined. 25 */ 26 27// Function to test lazy deoptimization; triggers a change in the return address of Test2. 28// After deoptimization, it checks whether the ASM Interpreter bridge's return address has been replaced. 29function ChangePrototypeValue(obj, shouldChange) { 30 print("ChangeProto start."); 31 if (shouldChange == true) { 32 // Modify the 'x' property at the second level of the prototype chain, 33 // triggering lazy deoptimization of the JIT-compiled 'test' function. 34 obj.__proto__.__proto__.x = 2; 35 } 36 print("ChangeProto end."); 37} 38 39function Test3() { 40 print("Test3"); 41} 42 43// Function Test2 - performs lazy deoptimization and deoptimization. 44// It calls ChangeProto to trigger lazy deoptimization and then deopt itself by printing a property from obj2. 45// Additionally, repeated accesses are performed at the end to avoid inlining. 46function Test2(obj, obj2, shouldChange) { 47 print("Test2 start."); 48 ArkTools.iterateFrame(); 49 50 // Trigger prototype change and lazy deoptimization. 51 ChangePrototypeValue(obj, shouldChange); 52 // Trigger Test2 deopt. 53 print("Test2 obj2:", obj2.y); 54 ArkTools.iterateFrame(); 55 56 Test3(); 57 print("Test2 end."); 58 59 // Additional code to prevent aggressive inlining. 60 let test = {}; 61 test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; 62 test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; 63 test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; 64 test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; 65} 66 67// Function Test calls Test2 to trigger deoptimization and then prints the value of 'x'. 68// This function helps verify if the JIT compiled code detected the changes. 69function Test(obj, obj2, shouldChange) { 70 print("Test start."); 71 Test2(obj, obj2, shouldChange); 72 ArkTools.iterateFrame(); 73 print("Test obj.x:", obj.x); 74 print("Test end."); 75} 76 77class A {} 78class B extends A {} 79class C extends B {} 80 81// Set initial property values on A's prototype. 82A.prototype.x = 1; 83A.prototype.y = 1; 84 85let c = new C(); 86c.y = 2; 87 88// First test: do not modify the prototype, so property 'x' remains unchanged. 89Test(c, c, false); 90 91ArkTools.jitCompileAsync(Test2); 92print(ArkTools.waitJitCompileFinish(Test2)); 93 94ArkTools.jitCompileAsync(Test); 95print(ArkTools.waitJitCompileFinish(Test)); 96 97print("------------------------------------------------------"); 98// Second test: change the prototype to trigger lazy deoptimization. 99let a = new A(); 100Test(c, a, true);