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 deopt itself by "print("Test2 obj2:", obj2.y)\ 22 * and then trigger lazy deoptimization by modifying the prototype, 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 deopt itself by printing a property from obj2 and then calls ChangeProto to trigger lazy deoptimization. 45// Additionally, repeated accesses are performed at the end to avoid inlining. 46function Test2(obj, obj2, shouldChange) { 47 print("Test2 start."); 48 49 // Trigger Test2 deopt. 50 print("Test2 obj2:", obj2.y); 51 52 // Trigger prototype change and lazy deoptimization. 53 ChangePrototypeValue(obj, shouldChange); 54 55 Test3(); 56 print("Test2 end."); 57 58 // Additional code to prevent aggressive inlining. 59 let test = {}; 60 test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; test.x; 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} 65 66// Function Test calls Test2 to trigger deoptimization and then prints the value of 'x'. 67// This function helps verify if the JIT compiled code detected the changes. 68function Test(obj, obj2, shouldChange) { 69 print("Test start."); 70 Test2(obj, obj2, shouldChange); 71 print("Test obj.x:", obj.x); 72 print("Test end."); 73} 74 75class A {} 76class B extends A {} 77class C extends B {} 78 79// Set initial property values on A's prototype. 80A.prototype.x = 1; 81A.prototype.y = 1; 82 83let c = new C(); 84c.y = 2; 85 86// First test: do not modify the prototype, so property 'x' remains unchanged. 87Test(c, c, false); 88 89ArkTools.jitCompileAsync(Test2); 90print(ArkTools.waitJitCompileFinish(Test2)); 91 92ArkTools.jitCompileAsync(Test); 93print(ArkTools.waitJitCompileFinish(Test)); 94 95print("------------------------------------------------------"); 96// Second test: change the prototype to trigger lazy deoptimization. 97let a = new A(); 98Test(c, a, true); 99