xref: /aosp_15_r20/art/test/943-private-recursive-jit/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import static art.Redefinition.doCommonClassRedefinition;
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker import java.util.Base64;
20*795d594fSAndroid Build Coastguard Worker import java.util.function.Consumer;
21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker public class Main {
24*795d594fSAndroid Build Coastguard Worker   static final boolean ALWAYS_PRINT = false;
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker   // import java.util.function.Consumer;
27*795d594fSAndroid Build Coastguard Worker   // class Transform {
28*795d594fSAndroid Build Coastguard Worker   //   public void sayHi(int recur, Consumer<String> reporter, Runnable r) {
29*795d594fSAndroid Build Coastguard Worker   //     privateSayHi(recur, reporter, r);
30*795d594fSAndroid Build Coastguard Worker   //   }
31*795d594fSAndroid Build Coastguard Worker   //   private void privateSayHi(int recur, Consumer<String> reporter, Runnable r) {
32*795d594fSAndroid Build Coastguard Worker   //     reporter.accpet("hello" + recur + " - transformed");
33*795d594fSAndroid Build Coastguard Worker   //     if (recur == 1) {
34*795d594fSAndroid Build Coastguard Worker   //       r.run();
35*795d594fSAndroid Build Coastguard Worker   //       privateSayHi(recur - 1, reporter, r);
36*795d594fSAndroid Build Coastguard Worker   //     } else if (recur != 0) {
37*795d594fSAndroid Build Coastguard Worker   //       privateSayHi(recur - 1, reporter, r);
38*795d594fSAndroid Build Coastguard Worker   //     }
39*795d594fSAndroid Build Coastguard Worker   //     reporter.accept("goodbye" + recur + " - transformed");
40*795d594fSAndroid Build Coastguard Worker   //   }
41*795d594fSAndroid Build Coastguard Worker   // }
42*795d594fSAndroid Build Coastguard Worker   private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
43*795d594fSAndroid Build Coastguard Worker     "yv66vgAAADQANAoADgAbCgANABwHAB0KAAMAGwgAHgoAAwAfCgADACAIACEKAAMAIgsAIwAkCwAl" +
44*795d594fSAndroid Build Coastguard Worker     "ACYIACcHACgHACkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2F5" +
45*795d594fSAndroid Build Coastguard Worker     "SGkBADUoSUxqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7TGphdmEvbGFuZy9SdW5uYWJsZTsp" +
46*795d594fSAndroid Build Coastguard Worker     "VgEACVNpZ25hdHVyZQEASShJTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjxMamF2YS9sYW5n" +
47*795d594fSAndroid Build Coastguard Worker     "L1N0cmluZzs+O0xqYXZhL2xhbmcvUnVubmFibGU7KVYBAAxwcml2YXRlU2F5SGkBAA1TdGFja01h" +
48*795d594fSAndroid Build Coastguard Worker     "cFRhYmxlAQAKU291cmNlRmlsZQEADlRyYW5zZm9ybS5qYXZhDAAPABAMABcAFAEAF2phdmEvbGFu" +
49*795d594fSAndroid Build Coastguard Worker     "Zy9TdHJpbmdCdWlsZGVyAQAFaGVsbG8MACoAKwwAKgAsAQAOIC0gdHJhbnNmb3JtZWQMAC0ALgcA" +
50*795d594fSAndroid Build Coastguard Worker     "LwwAMAAxBwAyDAAzABABAAdnb29kYnllAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAEA" +
51*795d594fSAndroid Build Coastguard Worker     "BmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEA" +
52*795d594fSAndroid Build Coastguard Worker     "HChJKUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9T" +
53*795d594fSAndroid Build Coastguard Worker     "dHJpbmc7AQAbamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAQAGYWNjZXB0AQAVKExqYXZhL2xh" +
54*795d594fSAndroid Build Coastguard Worker     "bmcvT2JqZWN0OylWAQASamF2YS9sYW5nL1J1bm5hYmxlAQADcnVuACAADQAOAAAAAAADAAAADwAQ" +
55*795d594fSAndroid Build Coastguard Worker     "AAEAEQAAAB0AAQABAAAABSq3AAGxAAAAAQASAAAABgABAAAAAgABABMAFAACABEAAAAkAAQABAAA" +
56*795d594fSAndroid Build Coastguard Worker     "AAgqGywttwACsQAAAAEAEgAAAAoAAgAAAAQABwAFABUAAAACABYAAgAXABQAAgARAAAAnwAEAAQA" +
57*795d594fSAndroid Build Coastguard Worker     "AABhLLsAA1m3AAQSBbYABhu2AAcSCLYABrYACbkACgIAGwSgABUtuQALAQAqGwRkLC23AAKnABAb" +
58*795d594fSAndroid Build Coastguard Worker     "mQAMKhsEZCwttwACLLsAA1m3AAQSDLYABhu2AAcSCLYABrYACbkACgIAsQAAAAIAEgAAACIACAAA" +
59*795d594fSAndroid Build Coastguard Worker     "AAcAHgAIACMACQApAAoANQALADkADABCAA4AYAAPABgAAAAEAAI1DAAVAAAAAgAWAAEAGQAAAAIA" +
60*795d594fSAndroid Build Coastguard Worker     "Gg==");
61*795d594fSAndroid Build Coastguard Worker   private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
62*795d594fSAndroid Build Coastguard Worker     "ZGV4CjAzNQCevtlr8B0kh/duuDYqXkGz/w9lMmtCCuRoBQAAcAAAAHhWNBIAAAAAAAAAALAEAAAg" +
63*795d594fSAndroid Build Coastguard Worker     "AAAAcAAAAAkAAADwAAAABgAAABQBAAAAAAAAAAAAAAoAAABcAQAAAQAAAKwBAACcAwAAzAEAAPYC" +
64*795d594fSAndroid Build Coastguard Worker     "AAAGAwAACgMAAA4DAAARAwAAGQMAAB0DAAAgAwAAIwMAACcDAAArAwAAOAMAAFcDAABrAwAAgQMA" +
65*795d594fSAndroid Build Coastguard Worker     "AJUDAACwAwAAzgMAAO0DAAD9AwAAAAQAAAYEAAAKBAAAEgQAABoEAAAuBAAANwQAAD4EAABMBAAA" +
66*795d594fSAndroid Build Coastguard Worker     "UQQAAFgEAABiBAAABgAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABEAAAATAAAABwAAAAUAAAAA" +
67*795d594fSAndroid Build Coastguard Worker     "AAAACAAAAAYAAADUAgAACQAAAAYAAADcAgAAEwAAAAgAAAAAAAAAFAAAAAgAAADkAgAAFQAAAAgA" +
68*795d594fSAndroid Build Coastguard Worker     "AADwAgAAAQADAAQAAAABAAQAGwAAAAEABAAdAAAAAwADAAQAAAAEAAMAHAAAAAYAAwAEAAAABgAB" +
69*795d594fSAndroid Build Coastguard Worker     "ABcAAAAGAAIAFwAAAAYAAAAeAAAABwAFABYAAAABAAAAAAAAAAMAAAAAAAAAEgAAALQCAACeBAAA" +
70*795d594fSAndroid Build Coastguard Worker     "AAAAAAEAAACKBAAAAQABAAEAAABpBAAABAAAAHAQAwAAAA4ABgAEAAQAAABuBAAAUAAAACIABgBw" +
71*795d594fSAndroid Build Coastguard Worker     "EAUAAAAbARoAAABuIAcAEAAMAG4gBgAwAAwAGwEAAAAAbiAHABAADABuEAgAAAAMAHIgCQAEABIQ" +
72*795d594fSAndroid Build Coastguard Worker     "MwMpAHIQBAAFANgAA/9wQAEAAlQiAAYAcBAFAAAAGwEZAAAAbiAHABAADABuIAYAMAAMABsBAAAA" +
73*795d594fSAndroid Build Coastguard Worker     "AG4gBwAQAAwAbhAIAAAADAByIAkABAAOADgD4f/YAAP/cEABAAJUKNoEAAQABAAAAIEEAAAEAAAA" +
74*795d594fSAndroid Build Coastguard Worker     "cEABABAyDgAAAAAAAAAAAAIAAAAAAAAAAQAAAMwBAAACAAAAzAEAAAEAAAAAAAAAAQAAAAUAAAAD" +
75*795d594fSAndroid Build Coastguard Worker     "AAAAAAAHAAQAAAABAAAAAwAOIC0gdHJhbnNmb3JtZWQAAihJAAIpVgABPAAGPGluaXQ+AAI+OwAB" +
76*795d594fSAndroid Build Coastguard Worker     "SQABTAACTEkAAkxMAAtMVHJhbnNmb3JtOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVyZTsA" +
77*795d594fSAndroid Build Coastguard Worker     "EkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcvU3Ry" +
78*795d594fSAndroid Build Coastguard Worker     "aW5nOwAZTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwAcTGphdmEvdXRpbC9mdW5jdGlvbi9Db25z" +
79*795d594fSAndroid Build Coastguard Worker     "dW1lcgAdTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjsADlRyYW5zZm9ybS5qYXZhAAFWAARW" +
80*795d594fSAndroid Build Coastguard Worker     "SUxMAAJWTAAGYWNjZXB0AAZhcHBlbmQAEmVtaXR0ZXI6IGphY2stNC4yNAAHZ29vZGJ5ZQAFaGVs" +
81*795d594fSAndroid Build Coastguard Worker     "bG8ADHByaXZhdGVTYXlIaQADcnVuAAVzYXlIaQAIdG9TdHJpbmcABXZhbHVlAAIABw4ABwMAAAAH" +
82*795d594fSAndroid Build Coastguard Worker     "DgEeDzw8XQEeDxktAAQDAAAABw48AAICAR8cBxcBFxAXAxcOFwUXDRcCAAACAQCAgATUAwEC7AMC" +
83*795d594fSAndroid Build Coastguard Worker     "AZwFDwAAAAAAAAABAAAAAAAAAAEAAAAgAAAAcAAAAAIAAAAJAAAA8AAAAAMAAAAGAAAAFAEAAAUA" +
84*795d594fSAndroid Build Coastguard Worker     "AAAKAAAAXAEAAAYAAAABAAAArAEAAAMQAAABAAAAzAEAAAEgAAADAAAA1AEAAAYgAAABAAAAtAIA" +
85*795d594fSAndroid Build Coastguard Worker     "AAEQAAAEAAAA1AIAAAIgAAAgAAAA9gIAAAMgAAADAAAAaQQAAAQgAAABAAAAigQAAAAgAAABAAAA" +
86*795d594fSAndroid Build Coastguard Worker     "ngQAAAAQAAABAAAAsAQAAA==");
87*795d594fSAndroid Build Coastguard Worker 
88*795d594fSAndroid Build Coastguard Worker   // A class that we can use to keep track of the output of this test.
89*795d594fSAndroid Build Coastguard Worker   private static class TestWatcher implements Consumer<String> {
90*795d594fSAndroid Build Coastguard Worker     private StringBuilder sb;
TestWatcher()91*795d594fSAndroid Build Coastguard Worker     public TestWatcher() {
92*795d594fSAndroid Build Coastguard Worker       sb = new StringBuilder();
93*795d594fSAndroid Build Coastguard Worker     }
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker     @Override
accept(String s)96*795d594fSAndroid Build Coastguard Worker     public void accept(String s) {
97*795d594fSAndroid Build Coastguard Worker       if (Main.ALWAYS_PRINT) {
98*795d594fSAndroid Build Coastguard Worker         System.out.println(s);
99*795d594fSAndroid Build Coastguard Worker       }
100*795d594fSAndroid Build Coastguard Worker       sb.append(s);
101*795d594fSAndroid Build Coastguard Worker       sb.append('\n');
102*795d594fSAndroid Build Coastguard Worker     }
103*795d594fSAndroid Build Coastguard Worker 
getOutput()104*795d594fSAndroid Build Coastguard Worker     public String getOutput() {
105*795d594fSAndroid Build Coastguard Worker       return sb.toString();
106*795d594fSAndroid Build Coastguard Worker     }
107*795d594fSAndroid Build Coastguard Worker 
clear()108*795d594fSAndroid Build Coastguard Worker     public void clear() {
109*795d594fSAndroid Build Coastguard Worker       sb = new StringBuilder();
110*795d594fSAndroid Build Coastguard Worker     }
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
main(String[] args)113*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) {
114*795d594fSAndroid Build Coastguard Worker     doTest(new Transform());
115*795d594fSAndroid Build Coastguard Worker   }
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker   private static boolean retry = false;
118*795d594fSAndroid Build Coastguard Worker 
doTest(Transform t)119*795d594fSAndroid Build Coastguard Worker   public static void doTest(Transform t) {
120*795d594fSAndroid Build Coastguard Worker     final TestWatcher reporter = new TestWatcher();
121*795d594fSAndroid Build Coastguard Worker     Method say_hi_method;
122*795d594fSAndroid Build Coastguard Worker     Method private_say_hi_method;
123*795d594fSAndroid Build Coastguard Worker     // Figure out if we can even JIT at all.
124*795d594fSAndroid Build Coastguard Worker     final boolean has_jit = hasJit();
125*795d594fSAndroid Build Coastguard Worker     try {
126*795d594fSAndroid Build Coastguard Worker       say_hi_method = Transform.class.getDeclaredMethod(
127*795d594fSAndroid Build Coastguard Worker           "sayHi", int.class, Consumer.class, Runnable.class);
128*795d594fSAndroid Build Coastguard Worker       private_say_hi_method = Transform.class.getDeclaredMethod(
129*795d594fSAndroid Build Coastguard Worker           "privateSayHi", int.class, Consumer.class, Runnable.class);
130*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
131*795d594fSAndroid Build Coastguard Worker       System.out.println("Unable to find methods!");
132*795d594fSAndroid Build Coastguard Worker       e.printStackTrace(System.out);
133*795d594fSAndroid Build Coastguard Worker       return;
134*795d594fSAndroid Build Coastguard Worker     }
135*795d594fSAndroid Build Coastguard Worker     // Makes sure the stack is the way we want it for the test and does the redefinition. It will
136*795d594fSAndroid Build Coastguard Worker     // set the retry boolean to true if we need to go around again due to jit code being GCd.
137*795d594fSAndroid Build Coastguard Worker     Runnable do_redefinition = () -> {
138*795d594fSAndroid Build Coastguard Worker       if (has_jit &&
139*795d594fSAndroid Build Coastguard Worker           (Main.isInterpretedFunction(say_hi_method, true) ||
140*795d594fSAndroid Build Coastguard Worker            Main.isInterpretedFunction(private_say_hi_method, true))) {
141*795d594fSAndroid Build Coastguard Worker         // Try again. We are not running the right jitted methods/cannot redefine them now.
142*795d594fSAndroid Build Coastguard Worker         retry = true;
143*795d594fSAndroid Build Coastguard Worker       } else {
144*795d594fSAndroid Build Coastguard Worker         // Actually do the redefinition. The stack looks good.
145*795d594fSAndroid Build Coastguard Worker         retry = false;
146*795d594fSAndroid Build Coastguard Worker         reporter.accept("transforming calling function");
147*795d594fSAndroid Build Coastguard Worker         doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
148*795d594fSAndroid Build Coastguard Worker       }
149*795d594fSAndroid Build Coastguard Worker     };
150*795d594fSAndroid Build Coastguard Worker     do {
151*795d594fSAndroid Build Coastguard Worker       // Run ensureJitCompiled here since it might get GCd
152*795d594fSAndroid Build Coastguard Worker       ensureJitCompiled(Transform.class, "sayHi");
153*795d594fSAndroid Build Coastguard Worker       ensureJitCompiled(Transform.class, "privateSayHi");
154*795d594fSAndroid Build Coastguard Worker       // We want to make sure sayHi method gets deoptimized. So we cannot allow any runtime frames
155*795d594fSAndroid Build Coastguard Worker       // between sayHi and the run method where the transformation is happening. If the run method
156*795d594fSAndroid Build Coastguard Worker       // is interpreted there will be a runtime frame to transition from JIT to interpreted code.
157*795d594fSAndroid Build Coastguard Worker       // So ensure the run method is JITed too, so we don't loop for a long time in the hope of
158*795d594fSAndroid Build Coastguard Worker       // getting the run method JITed.
159*795d594fSAndroid Build Coastguard Worker       ensureJitCompiled(do_redefinition.getClass(), "run");
160*795d594fSAndroid Build Coastguard Worker       // Clear output.
161*795d594fSAndroid Build Coastguard Worker       reporter.clear();
162*795d594fSAndroid Build Coastguard Worker       t.sayHi(2, reporter, () -> { reporter.accept("Not doing anything here"); });
163*795d594fSAndroid Build Coastguard Worker       t.sayHi(2, reporter, do_redefinition);
164*795d594fSAndroid Build Coastguard Worker       t.sayHi(2, reporter, () -> { reporter.accept("Not doing anything here"); });
165*795d594fSAndroid Build Coastguard Worker     } while(retry);
166*795d594fSAndroid Build Coastguard Worker     System.out.println(reporter.getOutput());
167*795d594fSAndroid Build Coastguard Worker   }
168*795d594fSAndroid Build Coastguard Worker 
hasJit()169*795d594fSAndroid Build Coastguard Worker   private static native boolean hasJit();
170*795d594fSAndroid Build Coastguard Worker 
isInterpretedFunction(Method m, boolean require_deoptimizable)171*795d594fSAndroid Build Coastguard Worker   private static native boolean isInterpretedFunction(Method m, boolean require_deoptimizable);
172*795d594fSAndroid Build Coastguard Worker 
ensureJitCompiled(Class c, String name)173*795d594fSAndroid Build Coastguard Worker   private static native void ensureJitCompiled(Class c, String name);
174*795d594fSAndroid Build Coastguard Worker }
175