• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package art;
18 
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Executable;
21 import java.lang.reflect.Method;
22 import java.nio.ByteBuffer;
23 import java.util.concurrent.Semaphore;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.function.Function;
29 import java.util.function.Predicate;
30 import java.util.function.Supplier;
31 import java.util.function.Consumer;
32 
33 public class Test1915 {
34   public static final int SET_VALUE = 1337;
35   public static final String TARGET_VAR = "TARGET";
36 
reportValue(Object val)37   public static void reportValue(Object val) {
38     System.out.println("\tValue is '" + val + "'");
39   }
40   public static interface ThrowRunnable {
run()41     public void run() throws Exception;
42   }
43 
IntMethod(ThrowRunnable safepoint)44   public static void IntMethod(ThrowRunnable safepoint) throws Exception {
45     int TARGET = 42;
46     safepoint.run();
47     reportValue(TARGET);
48   }
49 
run()50   public static void run() throws Exception {
51     Locals.EnableLocalVariableAccess();
52     final Method target = Test1915.class.getDeclaredMethod("IntMethod", ThrowRunnable.class);
53     // Get Variable.
54     System.out.println("GetLocalInt on current thread!");
55     IntMethod(() -> {
56       StackTrace.StackFrameData frame = FindStackFrame(target);
57       int depth = FindExpectedFrameDepth(frame);
58       int slot = FindSlot(frame);
59       int value = Locals.GetLocalVariableInt(Thread.currentThread(), depth, slot);
60       System.out.println("From GetLocalInt(), value is " + value);
61     });
62     // Set Variable.
63     System.out.println("SetLocalInt on current thread!");
64     IntMethod(() -> {
65       StackTrace.StackFrameData frame = FindStackFrame(target);
66       int depth = FindExpectedFrameDepth(frame);
67       int slot = FindSlot(frame);
68       Locals.SetLocalVariableInt(Thread.currentThread(), depth, slot, SET_VALUE);
69     });
70   }
71 
FindSlot(StackTrace.StackFrameData frame)72   public static int FindSlot(StackTrace.StackFrameData frame) throws Exception {
73     long loc = frame.current_location;
74     for (Locals.VariableDescription var : Locals.GetLocalVariableTable(frame.method)) {
75       if (var.start_location <= loc &&
76           var.length + var.start_location > loc &&
77           var.name.equals(TARGET_VAR)) {
78         return var.slot;
79       }
80     }
81     throw new Error(
82         "Unable to find variable " + TARGET_VAR + " in " + frame.method + " at loc " + loc);
83   }
84 
FindExpectedFrameDepth(StackTrace.StackFrameData frame)85   public static int FindExpectedFrameDepth(StackTrace.StackFrameData frame) throws Exception {
86     // Adjust the 'frame' depth since it is modified by:
87     // +1 for Get/SetLocalVariableInt in future.
88     // -1 for FindStackFrame
89     // -1 for GetStackTrace
90     // -1 for GetStackTraceNative
91     // ------------------------------
92     // -2
93     return frame.depth - 2;
94   }
95 
FindStackFrame(Method target)96   private static StackTrace.StackFrameData FindStackFrame(Method target) {
97     for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(Thread.currentThread())) {
98       if (frame.method.equals(target)) {
99         return frame;
100       }
101     }
102     throw new Error("Unable to find stack frame in method " + target);
103   }
104 }
105 
106