📄 methodbuilder.java
字号:
* @param signature method signature in standard form */ public void appendCallVirtual(String method, String signature) { // verify all call parameters and object reference on stack String[] types = ClassItem.getParametersFromSignature(signature); int split = method.lastIndexOf('.'); if (split < 0) { throw new IllegalArgumentException ("Internal error: Missing class name on method " + method); } verifyCallStack(method.substring(0, split), types); // generate the actual method call append(m_instructionBuilder.createCallVirtual(method, signature)); // change stack state to reflect result of call m_stackState.pop(types.length+1); String result = ClassItem.getTypeFromSignature(signature); if (!"void".equals(result)) { m_stackState.push(result); } } /** * Create invoke interface method instruction from signature and append to * method. * * @param method fully qualified interface and method name * @param signature method signature in standard form */ public void appendCallInterface(String method, String signature) { // verify all call parameters and object reference on stack String[] types = ClassItem.getParametersFromSignature(signature); int split = method.lastIndexOf('.'); if (split < 0) { throw new IllegalArgumentException ("Internal error: Missing class name on method " + method); } verifyCallStack(method.substring(0, split), types); // generate the actual method call append(m_instructionBuilder.createCallInterface(method, signature)); // change stack state to reflect result of call m_stackState.pop(types.length+1); String result = ClassItem.getTypeFromSignature(signature); if (!"void".equals(result)) { m_stackState.push(result); } } /** * Append instruction to create instance of class. * * @param name fully qualified class name */ public void appendCreateNew(String name) { append(m_instructionBuilder.createNew(name)); m_stackState.push(name); } /** * Create invoke initializer instruction from signature and append to * method. * * @param name fully qualified class name * @param signature method signature in standard form */ public void appendCallInit(String name, String signature) { // verify all call parameters and object reference on stack String[] types = ClassItem.getParametersFromSignature(signature); verifyCallStack(name, types); // generate the actual method call append(m_instructionBuilder.createCallInit(name, signature)); // change stack state to reflect result of call m_stackState.pop(types.length+1); } /** * Append instruction to create instance of array. * * @param type fully qualified type name of array elements */ public void appendCreateArray(String type) { if (ClassItem.isPrimitive(type)) { String sig = Utility.getSignature(type); append(new NEWARRAY(Utility.typeOfSignature(sig))); } else if (type.endsWith("[]")) { String cname = Utility.getSignature(type + "[]"); append(new MULTIANEWARRAY(m_instructionBuilder. getConstantPoolGen().addClass(cname), (short)1)); } else { append(new ANEWARRAY(m_instructionBuilder. getConstantPoolGen().addClass(type))); } m_stackState.pop(); m_stackState.push(type + "[]"); } /** * Append check cast instruction (if needed). * * @param from fully qualified name of current type * @param to fully qualified name of desired type */ public void appendCreateCast(String from, String to) { // verify current top of stack verifyStack(from); // check if any change of type if (!from.equals(to)) { // generate instruction and change stack state to match append(m_instructionBuilder. createCast(ClassItem.typeFromName(from), ClassItem.typeFromName(to))); m_stackState.pop(); m_stackState.push(to); } } /** * Append check cast instruction from object (if needed). * * @param to fully qualified name of desired type */ public void appendCreateCast(String to) { // verify current top of stack verifyStackObject(); // check if any change of type if (!m_stackState.peek().equals(to)) { // generate instruction and change stack state to match append(m_instructionBuilder. createCast(Type.OBJECT, ClassItem.typeFromName(to))); m_stackState.pop(); m_stackState.push(to); } } /** * Append instanceof check instruction. * * @param to fully qualified name of type to check */ public void appendInstanceOf(String to) { // make sure the stack has an object reference verifyStackObject(); // see if anything actually needs to be checked if ("java.lang.Object".equals(to)) { append(InstructionConstants.POP); appendLoadConstant(1); } else { append(m_instructionBuilder. createInstanceOf((ReferenceType)ClassItem.typeFromName(to))); } // change stack state to reflect results of added code m_stackState.pop(); m_stackState.push("int"); } /** * Add local variable to method. The current code in the method must have * the initial value for the variable on the stack. The scope of the * variable is defined from the last instruction to the end of the * method unless otherwise modified. * * @param name local variable name (may be <code>null</code> to use default) * @param type variable type */ protected LocalVariableGen createLocal(String name, Type type) { // verify top of stack verifyStack(type.toString()); // create name if needed if (name == null) { name = "var" + m_generator.getLocalVariables().length; } // allocation local and store value LocalVariableGen var = m_generator.addLocalVariable (name, type, getLastInstruction(), null); append(InstructionFactory.createStore(type, var.getIndex())); // save type information for local variable slot int slot = var.getIndex(); while (slot >= m_localTypes.size()) { m_localTypes.add(null); } m_localTypes.set(slot, type.toString()); // change stack state to reflect result m_stackState.pop(); return var; } /** * Add local variable to method. The current code in the method must have * the initial value for the variable on the stack. The scope of the * variable is defined from the preceding instruction to the end of the * method. * * @param name local variable name * @param type variable type * @return local variable slot number */ public int addLocal(String name, Type type) { LocalVariableGen var = createLocal(name, type); return var.getIndex(); } /** * Append instruction to load local variable. * * @param slot local variable slot to load */ public void appendLoadLocal(int slot) { String type = (String)m_localTypes.get(slot); if (type == null) { throw new IllegalArgumentException ("Internal error: No variable defined at position " + slot); } append(InstructionFactory. createLoad(ClassItem.typeFromName(type), slot)); m_stackState.push(type); } /** * Append instruction to store local variable. * * @param slot local variable slot to store */ public void appendStoreLocal(int slot) { String type = (String)m_localTypes.get(slot); if (type == null) { throw new IllegalArgumentException ("Internal error: No variable defined at position " + slot); } verifyStack(type); append(InstructionFactory. createStore(ClassItem.typeFromName(type), slot)); m_stackState.pop(); } /** * Append instruction to increment local integer variable. * * @param inc amount of incrment * @param slot local variable slot to load */ public void appendIncrementLocal(int inc, int slot) { String type = (String)m_localTypes.get(slot); if (type == null) { throw new IllegalArgumentException ("Internal error: No variable defined at position " + slot); } else if (!"int".equals(type)) { throw new IllegalArgumentException("Internal error: Variable at " + slot + " is " + type + ", not int"); } append(new IINC(slot, inc)); } /** * Append simple return. */ public void appendReturn() { append(InstructionConstants.RETURN); m_stackState = null; } /** * Append typed return. * * @param type returned type (may be <code>Type.VOID</code>) */ public void appendReturn(Type type) { // verify and return the object reference if (type != Type.VOID) { verifyStack(type.toString()); } append(InstructionFactory.createReturn(type)); // set open stack state for potential continuation code m_stackState = null; } /** * Append typed return. * * @param type returned type (may be <code>void</code>) */ public void appendReturn(String type) { // verify stack and generate return if ("void".equals(type)) { append(InstructionConstants.RETURN); } else { verifyStack(type); if (ClassItem.isPrimitive(type)) { if ("int".equals(type) || "char".equals(type) || "short".equals(type) || "boolean".equals(type)) { append(InstructionConstants.IRETURN); } else if ("long".equals(type)) { append(InstructionConstants.LRETURN); } else if ("float".equals(type)) { append(InstructionConstants.FRETURN); } else if ("double".equals(type)) { append(InstructionConstants.DRETURN); } else { throw new IllegalArgumentException("Unknown argument type"); } } else { append(InstructionConstants.ARETURN); } } // set open stack state for potential continuation code m_stackState = null; } /** * Append exception throw. */ public void appendThrow() { append(InstructionConstants.ATHROW); m_stackState = null; } /** * Append appropriate array load to the instruction list. * * @param type array item type expected */ public void appendALOAD(String type) { verifyStack("int"); m_stackState.pop(); verifyArray(type); if ("byte".equals(type) || "boolean".equals(type)) { append(InstructionConstants.BALOAD); } else if ("char".equals(type)) { append(InstructionConstants.CALOAD); } else if ("double".equals(type)) { append(InstructionConstants.DALOAD); } else if ("float".equals(type)) { append(InstructionConstants.FALOAD); } else if ("int".equals(type)) { append(InstructionConstants.IALOAD); } else if ("long".equals(type)) { append(InstructionConstants.LALOAD); } else if ("short".equals(type)) { append(InstructionConstants.SALOAD); } else { append(InstructionConstants.AALOAD); } m_stackState.pop(); m_stackState.push(type); } /** * Append an AASTORE to the instruction list. Doesn't actually check the * types, just the count of items present. */ public void appendAASTORE() { verifyStackDepth(3); String vtype = m_stackState.pop(); verifyStack("int"); m_stackState.pop(); String atype = verifyArray(); verifyCompatible(vtype, atype); m_stackState.pop(); append(InstructionConstants.AASTORE); } /** * Append the appropriate array store to the instruction list. * * @param type array item type expected */ public void appendASTORE(String type) { verifyStackDepth(3); String vtype = m_stackState.pop(); verifyStack("int"); m_stackState.pop(); String atype = verifyArray(); verifyCompatible(vtype, atype); m_stackState.pop(); if ("byte".equals(type) || "boolean".equals(type)) { append(InstructionConstants.BASTORE); } else if ("char".equals(type)) { append(InstructionConstants.CASTORE); } else if ("double".equals(type)) { append(InstructionConstants.DASTORE); } else if ("float".equals(type)) { append(InstructionConstants.FASTORE); } else if ("int".equals(type)) { append(InstructionConstants.IASTORE); } else if ("long".equals(type)) { append(InstructionConstants.LASTORE); } else if ("short".equals(type)) { append(InstructionConstants.SASTORE); } else { append(InstructionConstants.AASTORE); } } /** * Append an ACONST_NULL to the instruction list. */ public void appendACONST_NULL() { append(InstructionConstants.ACONST_NULL); m_stackState.push("<null>"); } /** * Append an ARRAYLENGTH to the instruction list. */ public void appendARRAYLENGTH() { verifyArray(); append(InstructionConstants.ARRAYLENGTH); m_stackState.pop(); m_stackState.push("int"); } /** * Append an DCMPG to the instruction list. */ public void appendDCMPG() { verifyStack("double", "double");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -