blob: d7b32ba1021ddcb912d98281a236aa95646e04ab [file] [log] [blame]
Alex Lightdba61482016-12-21 08:20:29 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Alex Light4eec3c52017-04-14 13:17:26 -070017
18import art.Redefinition;
19
Alex Lightdba61482016-12-21 08:20:29 -080020import java.util.function.Consumer;
21import java.lang.reflect.Method;
22import java.util.Base64;
23
24public class Main {
25
26 // import java.util.function.Consumer;
27 //
28 // class Transform {
29 // private void Start(Consumer<String> reporter) {
30 // reporter.accept("Hello - private - Transformed");
31 // }
32 //
33 // private void Finish(Consumer<String> reporter) {
34 // reporter.accept("Goodbye - private - Transformed");
35 // }
36 //
37 // public void sayHi(Runnable r, Consumer<String> reporter) {
38 // reporter.accept("pre Start private method call - Transformed");
39 // Start(reporter);
40 // reporter.accept("post Start private method call - Transformed");
41 // r.run();
42 // reporter.accept("pre Finish private method call - Transformed");
43 // Finish(reporter);
44 // reporter.accept("post Finish private method call - Transformed");
45 // }
46 // }
47 private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
48 "yv66vgAAADQAMAoADQAcCAAdCwAeAB8IACAIACEKAAwAIggAIwsAJAAlCAAmCgAMACcIACgHACkH" +
49 "ACoBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFU3RhcnQBACAoTGph" +
50 "dmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjspVgEACVNpZ25hdHVyZQEANChMamF2YS91dGlsL2Z1" +
51 "bmN0aW9uL0NvbnN1bWVyPExqYXZhL2xhbmcvU3RyaW5nOz47KVYBAAZGaW5pc2gBAAVzYXlIaQEA" +
52 "NChMamF2YS9sYW5nL1J1bm5hYmxlO0xqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7KVYBAEgo" +
53 "TGphdmEvbGFuZy9SdW5uYWJsZTtMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyPExqYXZhL2xh" +
54 "bmcvU3RyaW5nOz47KVYBAApTb3VyY2VGaWxlAQAOVHJhbnNmb3JtLmphdmEMAA4ADwEAHUhlbGxv" +
55 "IC0gcHJpdmF0ZSAtIFRyYW5zZm9ybWVkBwArDAAsAC0BAB9Hb29kYnllIC0gcHJpdmF0ZSAtIFRy" +
56 "YW5zZm9ybWVkAQArcHJlIFN0YXJ0IHByaXZhdGUgbWV0aG9kIGNhbGwgLSBUcmFuc2Zvcm1lZAwA" +
57 "EgATAQAscG9zdCBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQHAC4MAC8A" +
58 "DwEALHByZSBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkDAAWABMBAC1w" +
59 "b3N0IEZpbmlzaCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQBAAlUcmFuc2Zvcm0B" +
60 "ABBqYXZhL2xhbmcvT2JqZWN0AQAbamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAQAGYWNjZXB0" +
61 "AQAVKExqYXZhL2xhbmcvT2JqZWN0OylWAQASamF2YS9sYW5nL1J1bm5hYmxlAQADcnVuACAADAAN" +
62 "AAAAAAAEAAAADgAPAAEAEAAAAB0AAQABAAAABSq3AAGxAAAAAQARAAAABgABAAAAEwACABIAEwAC" +
63 "ABAAAAAlAAIAAgAAAAkrEgK5AAMCALEAAAABABEAAAAKAAIAAAAVAAgAFgAUAAAAAgAVAAIAFgAT" +
64 "AAIAEAAAACUAAgACAAAACSsSBLkAAwIAsQAAAAEAEQAAAAoAAgAAABkACAAaABQAAAACABUAAQAX" +
65 "ABgAAgAQAAAAZQACAAMAAAAxLBIFuQADAgAqLLcABiwSB7kAAwIAK7kACAEALBIJuQADAgAqLLcA" +
66 "CiwSC7kAAwIAsQAAAAEAEQAAACIACAAAAB0ACAAeAA0AHwAVACAAGwAhACMAIgAoACMAMAAkABQA" +
67 "AAACABkAAQAaAAAAAgAb");
68 private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
69 "ZGV4CjAzNQBc8wr9PcHqnOR61m+0kimXTSddVMToJPuYBQAAcAAAAHhWNBIAAAAAAAAAAOAEAAAc" +
70 "AAAAcAAAAAYAAADgAAAABAAAAPgAAAAAAAAAAAAAAAcAAAAoAQAAAQAAAGABAAAYBAAAgAEAAHoC" +
71 "AAB9AgAAgAIAAIgCAACOAgAAlgIAALcCAADWAgAA4wIAAAIDAAAWAwAALAMAAEADAABeAwAAfQMA" +
72 "AIQDAACUAwAAlwMAAJsDAACgAwAAqAMAALwDAADrAwAAGQQAAEcEAAB0BAAAeQQAAIAEAAAHAAAA" +
73 "CAAAAAkAAAAKAAAADQAAABAAAAAQAAAABQAAAAAAAAARAAAABQAAAGQCAAASAAAABQAAAGwCAAAR" +
74 "AAAABQAAAHQCAAAAAAAAAgAAAAAAAwAEAAAAAAADAA4AAAAAAAIAGgAAAAIAAAACAAAAAwAAABkA" +
75 "AAAEAAEAEwAAAAAAAAAAAAAAAgAAAAAAAAAPAAAAPAIAAMoEAAAAAAAAAQAAAKgEAAABAAAAuAQA" +
76 "AAEAAQABAAAAhwQAAAQAAABwEAQAAAAOAAMAAgACAAAAjAQAAAcAAAAbAAUAAAByIAYAAgAOAAAA" +
77 "AwACAAIAAACTBAAABwAAABsABgAAAHIgBgACAA4AAAAEAAMAAgAAAJoEAAAiAAAAGwAYAAAAciAG" +
78 "AAMAcCACADEAGwAWAAAAciAGAAMAchAFAAIAGwAXAAAAciAGAAMAcCABADEAGwAVAAAAciAGAAMA" +
79 "DgAAAAAAAAAAAAMAAAAAAAAAAQAAAIABAAACAAAAgAEAAAMAAACIAQAAAQAAAAIAAAACAAAAAwAE" +
80 "AAEAAAAEAAEoAAE8AAY8aW5pdD4ABD47KVYABkZpbmlzaAAfR29vZGJ5ZSAtIHByaXZhdGUgLSBU" +
81 "cmFuc2Zvcm1lZAAdSGVsbG8gLSBwcml2YXRlIC0gVHJhbnNmb3JtZWQAC0xUcmFuc2Zvcm07AB1M" +
82 "ZGFsdmlrL2Fubm90YXRpb24vU2lnbmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9s" +
83 "YW5nL1J1bm5hYmxlOwASTGphdmEvbGFuZy9TdHJpbmc7ABxMamF2YS91dGlsL2Z1bmN0aW9uL0Nv" +
84 "bnN1bWVyAB1MamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyOwAFU3RhcnQADlRyYW5zZm9ybS5q" +
85 "YXZhAAFWAAJWTAADVkxMAAZhY2NlcHQAEmVtaXR0ZXI6IGphY2stNC4xOQAtcG9zdCBGaW5pc2gg" +
86 "cHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkACxwb3N0IFN0YXJ0IHByaXZhdGUgbWV0" +
87 "aG9kIGNhbGwgLSBUcmFuc2Zvcm1lZAAscHJlIEZpbmlzaCBwcml2YXRlIG1ldGhvZCBjYWxsIC0g" +
88 "VHJhbnNmb3JtZWQAK3ByZSBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQA" +
89 "A3J1bgAFc2F5SGkABXZhbHVlABMABw4AGQEABw5pABUBAAcOaQAdAgAABw5pPGk8aTxpAAIBARsc" +
90 "BRcAFwwXARcLFwMCAQEbHAYXABcKFwwXARcLFwMAAAMBAICABJADAQKoAwECyAMDAegDDwAAAAAA" +
91 "AAABAAAAAAAAAAEAAAAcAAAAcAAAAAIAAAAGAAAA4AAAAAMAAAAEAAAA+AAAAAUAAAAHAAAAKAEA" +
92 "AAYAAAABAAAAYAEAAAMQAAACAAAAgAEAAAEgAAAEAAAAkAEAAAYgAAABAAAAPAIAAAEQAAADAAAA" +
93 "ZAIAAAIgAAAcAAAAegIAAAMgAAAEAAAAhwQAAAQgAAACAAAAqAQAAAAgAAABAAAAygQAAAAQAAAB" +
94 "AAAA4AQAAA==");
95
96 // A class that we can use to keep track of the output of this test.
97 private static class TestWatcher implements Consumer<String> {
98 private StringBuilder sb;
99 public TestWatcher() {
100 sb = new StringBuilder();
101 }
102
103 @Override
104 public void accept(String s) {
105 sb.append(s);
106 sb.append('\n');
107 }
108
109 public String getOutput() {
110 return sb.toString();
111 }
112
113 public void clear() {
114 sb = new StringBuilder();
115 }
116 }
117
118 public static void main(String[] args) {
Alex Lightdba61482016-12-21 08:20:29 -0800119 doTest(new Transform(), new TestWatcher());
120 }
121
Alex Lightdba61482016-12-21 08:20:29 -0800122 private static boolean interpreting = true;
123 private static boolean retry = false;
124
125 public static void doTest(Transform t, TestWatcher w) {
126 // Get the methods that need to be optimized.
127 Method say_hi_method;
Alex Lightdba61482016-12-21 08:20:29 -0800128 // Figure out if we can even JIT at all.
129 final boolean has_jit = hasJit();
130 try {
131 say_hi_method = Transform.class.getDeclaredMethod(
132 "sayHi", Runnable.class, Consumer.class);
Alex Lightdba61482016-12-21 08:20:29 -0800133 } catch (Exception e) {
134 System.out.println("Unable to find methods!");
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000135 e.printStackTrace(System.out);
Alex Lightdba61482016-12-21 08:20:29 -0800136 return;
137 }
138 // Makes sure the stack is the way we want it for the test and does the redefinition. It will
Alex Light5ecd5b72017-01-30 14:15:54 -0800139 // set the retry boolean to true if the stack does not have a JIT-compiled sayHi entry. This can
140 // only happen if the method gets GC'd.
Alex Lightdba61482016-12-21 08:20:29 -0800141 Runnable do_redefinition = () -> {
Alex Light4ba388a2017-01-27 10:26:49 -0800142 if (has_jit && Main.isInterpretedFunction(say_hi_method, true)) {
Alex Lightdba61482016-12-21 08:20:29 -0800143 // Try again. We are not running the right jitted methods/cannot redefine them now.
144 retry = true;
145 } else {
146 // Actually do the redefinition. The stack looks good.
147 retry = false;
148 w.accept("transforming calling function");
Alex Light4eec3c52017-04-14 13:17:26 -0700149 Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
Alex Lightdba61482016-12-21 08:20:29 -0800150 }
151 };
Alex Lightdba61482016-12-21 08:20:29 -0800152 // This just prints something out to show we are running the Runnable.
153 Runnable say_nothing = () -> { w.accept("Not doing anything here"); };
Alex Lightdba61482016-12-21 08:20:29 -0800154 do {
Alex Light4e03c522017-01-14 01:48:01 +0000155 // Run ensureJitCompiled here since it might get GCd
156 ensureJitCompiled(Transform.class, "sayHi");
Alex Light4e03c522017-01-14 01:48:01 +0000157 // Clear output.
Alex Lightdba61482016-12-21 08:20:29 -0800158 w.clear();
159 // Try and redefine.
160 t.sayHi(say_nothing, w);
161 t.sayHi(do_redefinition, w);
162 t.sayHi(say_nothing, w);
163 } while (retry);
164 // Print output of last run.
165 System.out.print(w.getOutput());
166 }
167
168 private static native boolean hasJit();
169
170 private static native boolean isInterpretedFunction(Method m, boolean require_deoptimizable);
171
Alex Light4e03c522017-01-14 01:48:01 +0000172 private static native void ensureJitCompiled(Class c, String name);
Alex Lightdba61482016-12-21 08:20:29 -0800173}