public void visitLocalVariableTable(LocalVariableTable table) { table.accept(visitor); LocalVariable[] vars = table.getLocalVariableTable(); for (int i = 0; i < vars.length; i++) vars[i].accept(this); }
/** * Write the local variable table. The necessary constants have already been added to the constant * table by the collect() method. The flowFields method is used to determine which variables are * alive at each pc. */ public void writeLocalVariableTable( Environment env, MemberDefinition field, DataOutputStream out, ConstantPool tab) throws IOException { MemberDefinition locals[] = new MemberDefinition[maxvar]; int i = 0; // Initialize arguments if ((field != null) && (field.getArguments() != null)) { int reg = 0; Vector v = field.getArguments(); for (Enumeration e = v.elements(); e.hasMoreElements(); ) { MemberDefinition f = ((MemberDefinition) e.nextElement()); locals[reg] = f; reg += f.getType().stackSize(); } } flowFields(env, first, locals); LocalVariableTable lvtab = new LocalVariableTable(); // Initialize arguments again for (i = 0; i < maxvar; i++) locals[i] = null; if ((field != null) && (field.getArguments() != null)) { int reg = 0; Vector v = field.getArguments(); for (Enumeration e = v.elements(); e.hasMoreElements(); ) { MemberDefinition f = ((MemberDefinition) e.nextElement()); locals[reg] = f; lvtab.define(f, reg, 0, maxpc); reg += f.getType().stackSize(); } } int pcs[] = new int[maxvar]; for (Instruction inst = first; inst != null; inst = inst.next) { switch (inst.opc) { case opc_istore: case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3: case opc_fstore: case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3: case opc_astore: case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3: case opc_lstore: case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3: case opc_dstore: case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3: if (inst.value instanceof LocalVariable) { LocalVariable v = (LocalVariable) inst.value; int pc = (inst.next != null) ? inst.next.pc : inst.pc; if (locals[v.slot] != null) { lvtab.define(locals[v.slot], v.slot, pcs[v.slot], pc); } pcs[v.slot] = pc; locals[v.slot] = v.field; } break; case opc_label: { // flush previous labels for (i = 0; i < maxvar; i++) { if (locals[i] != null) { lvtab.define(locals[i], i, pcs[i], inst.pc); } } // init new labels int pc = inst.pc; MemberDefinition[] labelLocals = ((Label) inst).locals; if (labelLocals == null) { // unreachable code?? for (i = 0; i < maxvar; i++) locals[i] = null; } else { System.arraycopy(labelLocals, 0, locals, 0, maxvar); } for (i = 0; i < maxvar; i++) { pcs[i] = pc; } break; } } } // flush remaining labels for (i = 0; i < maxvar; i++) { if (locals[i] != null) { lvtab.define(locals[i], i, pcs[i], maxpc); } } // write the local variable table lvtab.write(env, out, tab); }
/** * Called from {@link ClassFileReader#readClass(TypeReference,DataInputStream)} to create an * instance of a RVMMethod by reading the relevant data from the argument bytecode stream. * * @param declaringClass the TypeReference of the class being loaded * @param constantPool the constantPool of the RVMClass object that's being constructed * @param memRef the canonical memberReference for this member. * @param modifiers modifiers associated with this member. * @param input the DataInputStream to read the method's attributes from */ static RVMMethod readMethod( TypeReference declaringClass, int[] constantPool, MemberReference memRef, short modifiers, DataInputStream input) throws IOException { short tmp_localWords = 0; short tmp_operandWords = 0; byte[] tmp_bytecodes = null; ExceptionHandlerMap tmp_exceptionHandlerMap = null; TypeReference[] tmp_exceptionTypes = null; int[] tmp_lineNumberMap = null; LocalVariableTable tmp_localVariableTable = null; Atom tmp_signature = null; RVMAnnotation[] annotations = null; RVMAnnotation[][] parameterAnnotations = null; Object tmp_annotationDefault = null; // Read the attributes for (int i = 0, n = input.readUnsignedShort(); i < n; i++) { Atom attName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); int attLength = input.readInt(); // Only bother to interpret non-boring Method attributes if (attName == RVMClassLoader.codeAttributeName) { tmp_operandWords = input.readShort(); tmp_localWords = input.readShort(); tmp_bytecodes = new byte[input.readInt()]; input.readFully(tmp_bytecodes); tmp_exceptionHandlerMap = ExceptionHandlerMap.readExceptionHandlerMap(input, constantPool); // Read the attributes portion of the code attribute for (int j = 0, n2 = input.readUnsignedShort(); j < n2; j++) { attName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); attLength = input.readInt(); if (attName == RVMClassLoader.lineNumberTableAttributeName) { int cnt = input.readUnsignedShort(); if (cnt != 0) { tmp_lineNumberMap = new int[cnt]; for (int k = 0; k < cnt; k++) { int startPC = input.readUnsignedShort(); int lineNumber = input.readUnsignedShort(); tmp_lineNumberMap[k] = (lineNumber << BITS_IN_SHORT) | startPC; } } } else if (attName == RVMClassLoader.localVariableTableAttributeName) { tmp_localVariableTable = LocalVariableTable.readLocalVariableTable(input, constantPool); } else { // All other entries in the attribute portion of the code attribute are boring. int skippedAmount = input.skipBytes(attLength); if (skippedAmount != attLength) { throw new IOException("Unexpected short skip"); } } } } else if (attName == RVMClassLoader.exceptionsAttributeName) { int cnt = input.readUnsignedShort(); if (cnt != 0) { tmp_exceptionTypes = new TypeReference[cnt]; for (int j = 0, m = tmp_exceptionTypes.length; j < m; ++j) { tmp_exceptionTypes[j] = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); } } } else if (attName == RVMClassLoader.syntheticAttributeName) { modifiers |= ACC_SYNTHETIC; } else if (attName == RVMClassLoader.signatureAttributeName) { tmp_signature = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); } else if (attName == RVMClassLoader.runtimeVisibleAnnotationsAttributeName) { annotations = AnnotatedElement.readAnnotations(constantPool, input, declaringClass.getClassLoader()); } else if (attName == RVMClassLoader.runtimeVisibleParameterAnnotationsAttributeName) { int numParameters = input.readByte() & 0xFF; parameterAnnotations = new RVMAnnotation[numParameters][]; for (int a = 0; a < numParameters; ++a) { parameterAnnotations[a] = AnnotatedElement.readAnnotations( constantPool, input, declaringClass.getClassLoader()); } } else if (attName == RVMClassLoader.annotationDefaultAttributeName) { try { tmp_annotationDefault = RVMAnnotation.readValue( memRef.asMethodReference().getReturnType(), constantPool, input, declaringClass.getClassLoader()); } catch (ClassNotFoundException e) { throw new Error(e); } } else { // all other method attributes are boring int skippedAmount = input.skipBytes(attLength); if (skippedAmount != attLength) { throw new IOException("Unexpected short skip"); } } } RVMMethod method; if ((modifiers & ACC_NATIVE) != 0) { method = new NativeMethod( declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations, tmp_annotationDefault); } else if ((modifiers & ACC_ABSTRACT) != 0) { method = new AbstractMethod( declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations, tmp_annotationDefault); } else { method = new NormalMethod( declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_localWords, tmp_operandWords, tmp_bytecodes, tmp_exceptionHandlerMap, tmp_lineNumberMap, tmp_localVariableTable, constantPool, tmp_signature, annotations, parameterAnnotations, tmp_annotationDefault); } return method; }
/** * Return the local variable object this instruction operates on, or null if none. * * @see LocalVariableTable#getLocalVariable(int) */ public LocalVariable getLocalVariable() { LocalVariableTable table = getCode().getLocalVariableTable(false); if (table == null) return null; return table.getLocalVariable(getLocal()); }