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 Test1916 { 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 41 public static class IntRunner implements Runnable { 42 private volatile boolean continueBusyLoop; 43 private volatile boolean inBusyLoop; IntRunner()44 public IntRunner() { 45 this.continueBusyLoop = true; 46 this.inBusyLoop = false; 47 } run()48 public void run() { 49 int TARGET = 42; 50 // We will suspend the thread during this loop. 51 while (continueBusyLoop) { 52 inBusyLoop = true; 53 } 54 reportValue(TARGET); 55 } waitForBusyLoopStart()56 public void waitForBusyLoopStart() { while (!inBusyLoop) {} } finish()57 public void finish() { continueBusyLoop = false; } 58 } 59 run()60 public static void run() throws Exception { 61 Locals.EnableLocalVariableAccess(); 62 runGet(); 63 runSet(); 64 } 65 runGet()66 public static void runGet() throws Exception { 67 Method target = IntRunner.class.getDeclaredMethod("run"); 68 // Get Int 69 IntRunner int_runner = new IntRunner(); 70 Thread target_get = new Thread(int_runner, "GetLocalInt - Target"); 71 target_get.start(); 72 int_runner.waitForBusyLoopStart(); 73 try { 74 Suspension.suspend(target_get); 75 } catch (Exception e) { 76 System.out.println("FAIL: got " + e); 77 e.printStackTrace(); 78 int_runner.finish(); 79 target_get.join(); 80 return; 81 } 82 try { 83 StackTrace.StackFrameData frame = FindStackFrame(target_get, target); 84 int depth = frame.depth; 85 if (depth != 0) { throw new Error("Expected depth 0 but got " + depth); } 86 int slot = FindSlot(frame); 87 int value = Locals.GetLocalVariableInt(target_get, depth, slot); 88 System.out.println("From GetLocalInt(), value is " + value); 89 } finally { 90 Suspension.resume(target_get); 91 int_runner.finish(); 92 target_get.join(); 93 } 94 } 95 runSet()96 public static void runSet() throws Exception { 97 Method target = IntRunner.class.getDeclaredMethod("run"); 98 // Set Int 99 IntRunner int_runner = new IntRunner(); 100 Thread target_set = new Thread(int_runner, "SetLocalInt - Target"); 101 target_set.start(); 102 int_runner.waitForBusyLoopStart(); 103 try { 104 Suspension.suspend(target_set); 105 } catch (Exception e) { 106 System.out.println("FAIL: got " + e); 107 e.printStackTrace(); 108 int_runner.finish(); 109 target_set.join(); 110 return; 111 } 112 try { 113 StackTrace.StackFrameData frame = FindStackFrame(target_set, target); 114 int depth = frame.depth; 115 if (depth != 0) { throw new Error("Expected depth 0 but got " + depth); } 116 int slot = FindSlot(frame); 117 System.out.println("Setting TARGET to " + SET_VALUE); 118 Locals.SetLocalVariableInt(target_set, depth, slot, SET_VALUE); 119 } finally { 120 Suspension.resume(target_set); 121 int_runner.finish(); 122 target_set.join(); 123 } 124 } 125 FindSlot(StackTrace.StackFrameData frame)126 public static int FindSlot(StackTrace.StackFrameData frame) throws Exception { 127 long loc = frame.current_location; 128 for (Locals.VariableDescription var : Locals.GetLocalVariableTable(frame.method)) { 129 if (var.start_location <= loc && 130 var.length + var.start_location > loc && 131 var.name.equals(TARGET_VAR)) { 132 return var.slot; 133 } 134 } 135 throw new Error( 136 "Unable to find variable " + TARGET_VAR + " in " + frame.method + " at loc " + loc); 137 } 138 FindStackFrame(Thread thr, Method target)139 private static StackTrace.StackFrameData FindStackFrame(Thread thr, Method target) { 140 for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(thr)) { 141 if (frame.method.equals(target)) { 142 return frame; 143 } 144 } 145 throw new Error("Unable to find stack frame in method " + target + " on thread " + thr); 146 } 147 } 148 149