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.cst.Constant; 20 import com.android.dx.rop.type.Prototype; 21 import com.android.dx.rop.type.Type; 22 import com.android.dx.rop.code.LocalItem; 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 * Indicates that the salient type of this operation is as 117 * given. This differentiates between, for example, the various 118 * arithmetic opcodes, which, by the time they hit a 119 * {@code Machine} are collapsed to the {@code int} 120 * variant. (See {@link BytecodeArray#parseInstruction} for 121 * details.) 122 * 123 * @param type {@code non-null;} the salient type of the upcoming operation 124 */ auxType(Type type)125 public void auxType(Type type); 126 127 /** 128 * Indicates that there is an auxiliary (inline, not stack) 129 * argument of type {@code int}, with the given value. 130 * 131 * <p><b>Note:</b> Perhaps unintuitively, the stack manipulation 132 * ops (e.g., {@code dup} and {@code swap}) use this to 133 * indicate the result stack pattern with a straightforward hex 134 * encoding of the push order starting with least-significant 135 * nibbles getting pushed first). For example, an all-category-1 136 * {@code dup2_x1} sets this to {@code 0x12312}, and the 137 * other form of that op sets this to 138 * {@code 0x121}.</p> 139 * 140 * <p><b>Also Note:</b> For {@code switch*} instructions, this is 141 * used to indicate the padding value (which is only useful for 142 * verification).</p> 143 * 144 * @param value the argument value 145 */ auxIntArg(int value)146 public void auxIntArg(int value); 147 148 /** 149 * Indicates that there is an auxiliary (inline, not stack) object 150 * argument, with the value based on the given constant. 151 * 152 * <p><b>Note:</b> Some opcodes use both {@code int} and 153 * constant auxiliary arguments.</p> 154 * 155 * @param cst {@code non-null;} the constant containing / referencing 156 * the value 157 */ auxCstArg(Constant cst)158 public void auxCstArg(Constant cst); 159 160 /** 161 * Indicates that there is an auxiliary (inline, not stack) argument 162 * indicating a branch target. 163 * 164 * @param target the argument value 165 */ auxTargetArg(int target)166 public void auxTargetArg(int target); 167 168 /** 169 * Indicates that there is an auxiliary (inline, not stack) argument 170 * consisting of a {@code switch*} table. 171 * 172 * <p><b>Note:</b> This is generally used in conjunction with 173 * {@link #auxIntArg} (which holds the padding).</p> 174 * 175 * @param cases {@code non-null;} the list of key-target pairs, plus the default 176 * target 177 */ auxSwitchArg(SwitchList cases)178 public void auxSwitchArg(SwitchList cases); 179 180 /** 181 * Indicates that there is an auxiliary (inline, not stack) argument 182 * consisting of a list of initial values for a newly created array. 183 * 184 * @param initValues {@code non-null;} the list of constant values to initialize 185 * the array 186 */ auxInitValues(ArrayList<Constant> initValues)187 public void auxInitValues(ArrayList<Constant> initValues); 188 189 /** 190 * Indicates that the target of this operation is the given local. 191 * 192 * @param idx {@code >= 0;} the local variable index 193 * @param type {@code non-null;} the type of the local 194 * @param local {@code null-ok;} the name and signature of the local, if known 195 */ localTarget(int idx, Type type, LocalItem local)196 public void localTarget(int idx, Type type, LocalItem local); 197 198 /** 199 * "Runs" the indicated opcode in an appropriate way, using the arguments 200 * area as appropriate, and modifying the given frame in response. 201 * 202 * @param frame {@code non-null;} frame to operate on 203 * @param offset {@code >= 0;} byte offset in the method to the opcode being 204 * run 205 * @param opcode {@code >= 0;} the opcode to run 206 */ run(Frame frame, int offset, int opcode)207 public void run(Frame frame, int offset, int opcode); 208 } 209