blob: 714a98aaf3eced82a5965dc3bd55e1401b4d5f20 [file] [log] [blame]
Alex Light21611932017-09-26 13:07:39 -07001/*
2 * Copyright (C) 2017 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
17import art.Locals;
18import art.StackTrace;
19import art.Suspension;
20import java.lang.reflect.Constructor;
21import java.lang.reflect.Executable;
22import java.lang.reflect.Method;
23import java.nio.ByteBuffer;
24import java.util.concurrent.Semaphore;
25import java.util.Arrays;
26import java.util.Collection;
27import java.util.List;
28import java.util.Set;
29import java.util.function.Function;
30import java.util.function.Predicate;
31import java.util.function.Supplier;
32import java.util.function.Consumer;
33
34public class Main {
35 public static final int SET_VALUE = 1337;
36 public static final String TARGET_VAR = "TARGET";
37
38 public static void main(String[] args) throws Exception {
39 System.loadLibrary(args[0]);
40 Locals.EnableLocalVariableAccess();
41 runGet();
42 runSet();
43 }
44
45 public static void reportValue(Object val) {
46 System.out.println("\tValue is '" + val + "'");
47 }
48
49 public static class IntRunner implements Runnable {
50 private volatile boolean continueBusyLoop;
51 private volatile boolean inBusyLoop;
Nicolas Geoffray4f3d1cf2018-03-29 08:13:20 +000052 public IntRunner() {
Alex Light21611932017-09-26 13:07:39 -070053 this.continueBusyLoop = true;
54 this.inBusyLoop = false;
55 }
56 public void run() {
57 int TARGET = 42;
58 // We will suspend the thread during this loop.
59 while (continueBusyLoop) {
60 inBusyLoop = true;
61 }
62 int i = 0;
63 while (Main.isInterpreted() && i < 10000) {
64 Main.ensureJitCompiled(IntRunner.class, "run");
65 i++;
66 }
Nicolas Geoffray4f3d1cf2018-03-29 08:13:20 +000067 // We shouldn't be doing OSR since we are using JVMTI and the get/set prevents OSR.
Vladimir Markof8655b32018-03-21 17:53:56 +000068 // Set local will also push us to interpreter but the get local may remain in compiled code.
Nicolas Geoffray4f3d1cf2018-03-29 08:13:20 +000069 System.out.println("isInOsrCode? " + (hasJit() && Main.isInOsrCode("run")));
Alex Light21611932017-09-26 13:07:39 -070070 reportValue(TARGET);
71 }
72 public void waitForBusyLoopStart() { while (!inBusyLoop) {} }
73 public void finish() {
74 continueBusyLoop = false;
75 }
76 }
77
78 public static void runGet() throws Exception {
79 Method target = IntRunner.class.getDeclaredMethod("run");
80 // Get Int
Nicolas Geoffray4f3d1cf2018-03-29 08:13:20 +000081 IntRunner int_runner = new IntRunner();
Alex Light21611932017-09-26 13:07:39 -070082 Thread target_get = new Thread(int_runner, "GetLocalInt - Target");
83 target_get.start();
84 int_runner.waitForBusyLoopStart();
85 try {
86 Suspension.suspend(target_get);
87 } catch (Exception e) {
88 System.out.println("FAIL: got " + e);
89 e.printStackTrace();
90 int_runner.finish();
91 target_get.join();
92 return;
93 }
94 try {
95 StackTrace.StackFrameData frame = FindStackFrame(target_get, target);
96 int depth = frame.depth;
97 if (depth != 0) { throw new Error("Expected depth 0 but got " + depth); }
98 int slot = FindSlot(frame);
99 int value = Locals.GetLocalVariableInt(target_get, depth, slot);
100 System.out.println("From GetLocalInt(), value is " + value);
101 } finally {
102 Suspension.resume(target_get);
103 int_runner.finish();
104 target_get.join();
105 }
106 }
107
108 public static void runSet() throws Exception {
109 Method target = IntRunner.class.getDeclaredMethod("run");
110 // Set Int
Nicolas Geoffray4f3d1cf2018-03-29 08:13:20 +0000111 IntRunner int_runner = new IntRunner();
Alex Light21611932017-09-26 13:07:39 -0700112 Thread target_set = new Thread(int_runner, "SetLocalInt - Target");
113 target_set.start();
114 int_runner.waitForBusyLoopStart();
115 try {
116 Suspension.suspend(target_set);
117 } catch (Exception e) {
118 System.out.println("FAIL: got " + e);
119 e.printStackTrace();
120 int_runner.finish();
121 target_set.join();
122 return;
123 }
124 try {
125 StackTrace.StackFrameData frame = FindStackFrame(target_set, target);
126 int depth = frame.depth;
127 if (depth != 0) { throw new Error("Expected depth 0 but got " + depth); }
128 int slot = FindSlot(frame);
129 System.out.println("Setting TARGET to " + SET_VALUE);
130 Locals.SetLocalVariableInt(target_set, depth, slot, SET_VALUE);
131 } finally {
132 Suspension.resume(target_set);
133 int_runner.finish();
134 target_set.join();
135 }
136 }
137
138 public static int FindSlot(StackTrace.StackFrameData frame) throws Exception {
139 long loc = frame.current_location;
140 for (Locals.VariableDescription var : Locals.GetLocalVariableTable(frame.method)) {
141 if (var.start_location <= loc &&
142 var.length + var.start_location > loc &&
143 var.name.equals(TARGET_VAR)) {
144 return var.slot;
145 }
146 }
147 throw new Error(
148 "Unable to find variable " + TARGET_VAR + " in " + frame.method + " at loc " + loc);
149 }
150
151 private static StackTrace.StackFrameData FindStackFrame(Thread thr, Method target) {
152 for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(thr)) {
153 if (frame.method.equals(target)) {
154 return frame;
155 }
156 }
157 throw new Error("Unable to find stack frame in method " + target + " on thread " + thr);
158 }
159
160 public static native void ensureJitCompiled(Class k, String f);
161 public static native boolean isInterpreted();
Vladimir Markof8655b32018-03-21 17:53:56 +0000162 public static native boolean isInOsrCode(String methodName);
163 public static native boolean hasJit();
Alex Light21611932017-09-26 13:07:39 -0700164}