1 /* 2 * Copyright (C) 2007 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 com.android.dx.cf.code; 18 19 import com.android.dx.rop.code.LocalItem; 20 import com.android.dx.rop.cst.Constant; 21 import com.android.dx.rop.type.Prototype; 22 import com.android.dx.rop.type.Type; 23 import java.util.ArrayList; 24 25 /** 26 * Interface for machines capable of executing bytecode by acting 27 * upon a {@link Frame}. A machine conceptually contains four arbitrary-value 28 * argument slots, slots for several literal-value arguments, and slots for 29 * branch target information. 30 */ 31 public interface Machine { 32 /** 33 * Gets the effective prototype of the method that this instance is 34 * being used for. The <i>effective</i> prototype includes an initial 35 * {@code this} argument for instance methods. 36 * 37 * @return {@code non-null;} the method prototype 38 */ getPrototype()39 public Prototype getPrototype(); 40 41 /** 42 * Clears the regular and auxiliary arguments area. 43 */ clearArgs()44 public void clearArgs(); 45 46 /** 47 * Pops the given number of values from the stack (of either category), 48 * and store them in the arguments area, indicating that there are now 49 * that many arguments. Also, clear the auxiliary arguments. 50 * 51 * @param frame {@code non-null;} frame to operate on 52 * @param count {@code >= 0;} number of values to pop 53 */ popArgs(Frame frame, int count)54 public void popArgs(Frame frame, int count); 55 56 /** 57 * Pops values from the stack of the types indicated by the given 58 * {@code Prototype} (popped in reverse of the argument 59 * order, so the first prototype argument type is for the deepest 60 * element of the stack), and store them in the arguments area, 61 * indicating that there are now that many arguments. Also, clear 62 * the auxiliary arguments. 63 * 64 * @param frame {@code non-null;} frame to operate on 65 * @param prototype {@code non-null;} prototype indicating arguments to pop 66 */ popArgs(Frame frame, Prototype prototype)67 public void popArgs(Frame frame, Prototype prototype); 68 69 /** 70 * Pops a value from the stack of the indicated type, and store it 71 * in the arguments area, indicating that there are now that many 72 * arguments. Also, clear the auxiliary arguments. 73 * 74 * @param frame {@code non-null;} frame to operate on 75 * @param type {@code non-null;} type of the argument 76 */ popArgs(Frame frame, Type type)77 public void popArgs(Frame frame, Type type); 78 79 /** 80 * Pops values from the stack of the indicated types (popped in 81 * reverse argument order, so the first indicated type is for the 82 * deepest element of the stack), and store them in the arguments 83 * area, indicating that there are now that many arguments. Also, 84 * clear the auxiliary arguments. 85 * 86 * @param frame {@code non-null;} frame to operate on 87 * @param type1 {@code non-null;} type of the first argument 88 * @param type2 {@code non-null;} type of the second argument 89 */ popArgs(Frame frame, Type type1, Type type2)90 public void popArgs(Frame frame, Type type1, Type type2); 91 92 /** 93 * Pops values from the stack of the indicated types (popped in 94 * reverse argument order, so the first indicated type is for the 95 * deepest element of the stack), and store them in the arguments 96 * area, indicating that there are now that many arguments. Also, 97 * clear the auxiliary arguments. 98 * 99 * @param frame {@code non-null;} frame to operate on 100 * @param type1 {@code non-null;} type of the first argument 101 * @param type2 {@code non-null;} type of the second argument 102 * @param type3 {@code non-null;} type of the third argument 103 */ popArgs(Frame frame, Type type1, Type type2, Type type3)104 public void popArgs(Frame frame, Type type1, Type type2, Type type3); 105 106 /** 107 * Loads the local variable with the given index as the sole argument in 108 * the arguments area. Also, clear the auxiliary arguments. 109 * 110 * @param frame {@code non-null;} frame to operate on 111 * @param idx {@code >= 0;} the local variable index 112 */ localArg(Frame frame, int idx)113 public void localArg(Frame frame, int idx); 114 115 /** 116 * Used to specify if a loaded local variable has info in the local 117 * variable table. 118 * 119 * @param local {@code true} if local arg has info in local variable table 120 */ localInfo(boolean local)121 public void localInfo(boolean local); 122 123 /** 124 * Indicates that the salient type of this operation is as 125 * given. This differentiates between, for example, the various 126 * arithmetic opcodes, which, by the time they hit a 127 * {@code Machine} are collapsed to the {@code int} 128 * variant. (See {@link BytecodeArray#parseInstruction} for 129 * details.) 130 * 131 * @param type {@code non-null;} the salient type of the upcoming operation 132 */ auxType(Type type)133 public void auxType(Type type); 134 135 /** 136 * Indicates that there is an auxiliary (inline, not stack) 137 * argument of type {@code int}, with the given value. 138 * 139 * <p><b>Note:</b> Perhaps unintuitively, the stack manipulation 140 * ops (e.g., {@code dup} and {@code swap}) use this to 141 * indicate the result stack pattern with a straightforward hex 142 * encoding of the push order starting with least-significant 143 * nibbles getting pushed first). For example, an all-category-1 144 * {@code dup2_x1} sets this to {@code 0x12312}, and the 145 * other form of that op sets this to 146 * {@code 0x121}.</p> 147 * 148 * <p><b>Also Note:</b> For {@code switch*} instructions, this is 149 * used to indicate the padding value (which is only useful for 150 * verification).</p> 151 * 152 * @param value the argument value 153 */ auxIntArg(int value)154 public void auxIntArg(int value); 155 156 /** 157 * Indicates that there is an auxiliary (inline, not stack) object 158 * argument, with the value based on the given constant. 159 * 160 * <p><b>Note:</b> Some opcodes use both {@code int} and 161 * constant auxiliary arguments.</p> 162 * 163 * @param cst {@code non-null;} the constant containing / referencing 164 * the value 165 */ auxCstArg(Constant cst)166 public void auxCstArg(Constant cst); 167 168 /** 169 * Indicates that there is an auxiliary (inline, not stack) argument 170 * indicating a branch target. 171 * 172 * @param target the argument value 173 */ auxTargetArg(int target)174 public void auxTargetArg(int target); 175 176 /** 177 * Indicates that there is an auxiliary (inline, not stack) argument 178 * consisting of a {@code switch*} table. 179 * 180 * <p><b>Note:</b> This is generally used in conjunction with 181 * {@link #auxIntArg} (which holds the padding).</p> 182 * 183 * @param cases {@code non-null;} the list of key-target pairs, plus the default 184 * target 185 */ auxSwitchArg(SwitchList cases)186 public void auxSwitchArg(SwitchList cases); 187 188 /** 189 * Indicates that there is an auxiliary (inline, not stack) argument 190 * consisting of a list of initial values for a newly created array. 191 * 192 * @param initValues {@code non-null;} the list of constant values to initialize 193 * the array 194 */ auxInitValues(ArrayList<Constant> initValues)195 public void auxInitValues(ArrayList<Constant> initValues); 196 197 /** 198 * Indicates that the target of this operation is the given local. 199 * 200 * @param idx {@code >= 0;} the local variable index 201 * @param type {@code non-null;} the type of the local 202 * @param local {@code null-ok;} the name and signature of the local, if known 203 */ localTarget(int idx, Type type, LocalItem local)204 public void localTarget(int idx, Type type, LocalItem local); 205 206 /** 207 * "Runs" the indicated opcode in an appropriate way, using the arguments 208 * area as appropriate, and modifying the given frame in response. 209 * 210 * @param frame {@code non-null;} frame to operate on 211 * @param offset {@code >= 0;} byte offset in the method to the opcode being 212 * run 213 * @param opcode {@code >= 0;} the opcode to run 214 */ run(Frame frame, int offset, int opcode)215 public void run(Frame frame, int offset, int opcode); 216 } 217