📄 methodbuilder.java
字号:
append(InstructionConstants.DCMPG); m_stackState.pop(2); m_stackState.push("int"); } /** * Append a DUP to the instruction list. */ public void appendDUP() { verifyStackDepth(1); append(InstructionConstants.DUP); m_stackState.push(m_stackState.peek()); } /** * Append a DUP2 to the instruction list. */ public void appendDUP2() { verifyStackDepth(1); append(InstructionConstants.DUP2); m_stackState.push(m_stackState.peek()); } /** * Append a DUP_X1 to the instruction list. */ public void appendDUP_X1() { verifyStackDepth(2); append(InstructionConstants.DUP_X1); String hold0 = m_stackState.pop(); String hold1 = m_stackState.pop(); m_stackState.push(hold0); m_stackState.push(hold1); m_stackState.push(hold0); } /** * Append an FCMPG to the instruction list. */ public void appendFCMPG() { verifyStack("float", "float"); append(InstructionConstants.FCMPG); m_stackState.pop(2); m_stackState.push("int"); } /** * Append an IASTORE to the instruction list. Doesn't actually check the * types, just the count of items present. */ public void appendIASTORE() { verifyStackDepth(3); append(InstructionConstants.IASTORE); m_stackState.pop(3); } /** * Append an ICONST_0 to the instruction list. */ public void appendICONST_0() { append(InstructionConstants.ICONST_0); m_stackState.push("int"); } /** * Append an ICONST_1 to the instruction list. */ public void appendICONST_1() { append(InstructionConstants.ICONST_1); m_stackState.push("int"); } /** * Append an ISUB to the instruction list. */ public void appendISUB() { verifyStack("int", "int"); append(InstructionConstants.ISUB); m_stackState.pop(1); } /** * Append an IXOR to the instruction list. */ public void appendIXOR() { verifyStack("int", "int"); append(InstructionConstants.IXOR); m_stackState.pop(1); } /** * Append an LCMP to the instruction list. */ public void appendLCMP() { verifyStack("long", "long"); append(InstructionConstants.LCMP); m_stackState.pop(2); m_stackState.push("int"); } /** * Append a POP to the instruction list. */ public void appendPOP() { verifyStackDepth(1); String type = m_stackState.peek(); if ("long".equals(type) || "double".equals(type)) { throw new IllegalStateException ("Internal error: POP splits long value"); } append(InstructionConstants.POP); m_stackState.pop(); } /** * Append a POP2 to the instruction list. */ public void appendPOP2() { verifyStackDepth(1); String type = m_stackState.peek(); if (!"long".equals(type) && !"double".equals(type)) { throw new IllegalStateException ("Internal error: POP2 requires long value"); } append(InstructionConstants.POP2); m_stackState.pop(); } /** * Append a SWAP to the instruction list. */ public void appendSWAP() { verifyStackDepth(2); append(InstructionConstants.SWAP); String hold0 = m_stackState.pop(); String hold1 = m_stackState.pop(); m_stackState.push(hold0); m_stackState.push(hold1); } /** * Append instructions to exchange a single-word value on the top of the * stack with the double-word value below it on the stack. */ public void appendSWAP1For2() { verifyStackDepth(2); append(InstructionConstants.DUP_X2); append(InstructionConstants.POP); String hold0 = m_stackState.pop(); String hold1 = m_stackState.pop(); m_stackState.push(hold0); m_stackState.push(hold1); } /** * Append a compound instruction to the list as a branch target. * * @param inst compound instruction to be appended as branch target * @return branch target information */ private BranchTarget appendTargetInstruction(CompoundInstruction inst) { String[] types = m_stackState.toArray(); InstructionHandle hand = m_instructionList.append(inst); return new BranchTarget(hand, types); } /** * Append an instruction to the list as a branch target. * * @param inst instruction to be appended as branch target * @return branch target information */ private BranchTarget appendTargetInstruction(Instruction inst) { String[] types = m_stackState.toArray(); InstructionHandle hand = m_instructionList.append(inst); return new BranchTarget(hand, types); } /** * Append a NOP to the instruction list as a branch target. * * @return branch target information */ public BranchTarget appendTargetNOP() { return appendTargetInstruction(InstructionConstants.NOP); } /** * Append an ACONST_NULL to the instruction list as a branch target. * * @return branch target information */ public BranchTarget appendTargetACONST_NULL() { BranchTarget target = appendTargetInstruction (InstructionConstants.ACONST_NULL); m_stackState.push("<null>"); return target; } /** * Append a load constant instruction as a branch target. Builds the most * appropriate type of instruction for the value. * * @param value constant value to be loaded * @return branch target information */ public BranchTarget appendTargetLoadConstant(int value) { BranchTarget target = appendTargetInstruction(m_instructionBuilder. createLoadConstant(value)); m_stackState.push("int"); return target; } /** * Append a load constant instruction as a branch target. Loads a * <code>String</code> reference from the constant pool. * * @param value constant value to be loaded * @return branch target information */ public BranchTarget appendTargetLoadConstant(String value) { BranchTarget target = appendTargetInstruction(m_instructionBuilder. createLoadConstant(value)); m_stackState.push("java.lang.String"); return target; } /** * Append instruction to create instance of class as a branch target. * * @param name fully qualified class name * @return branch target information */ public BranchTarget appendTargetCreateNew(String name) { BranchTarget target = appendTargetInstruction(m_instructionBuilder.createNew(name)); m_stackState.push(name); return target; } /** * Internal append instruction to create instance of class. This is used by * subclasses when they need access to the actual instruction handle. * * @param name fully qualified class name */ protected InstructionHandle internalAppendCreateNew(String name) { InstructionHandle handle = m_instructionList.append (m_instructionBuilder.createNew(name)); m_stackState.push(name); return handle; } /** * Check if top item on stack is a long value. * * @return <code>true</code> if long value, <code>false</code> if not */ public boolean isStackTopLong() { verifyStackDepth(1); String type = m_stackState.peek(); return "long".equals(type) || "double".equals(type); } /** * Initialize stack state to match branch source. This can be used to set * the expected stack state following an unconditional transfer of control * instruction. The principle here is that the code to be generated must be * reached by a branch, so the stack state must match that of the branch * source. * * @param branch wrapper for branch to be for stack initialization */ public void initStackState(BranchWrapper branch) { m_stackState = new StringStack(branch.getStackState()); } /** * Initialize stack state to partially match branch source. This can be used * to set the expected stack state following an unconditional transfer of * control instruction. The specified number of items are removed from the * branch stack, with the assumption that code to add these items will be * appended before the branch join point is reached. * * @param branch wrapper for branch to be for stack initialization * @param pop number of items to be removed from branch source stack state */ public void initStackState(BranchWrapper branch, int pop) { m_stackState = new StringStack(branch.getStackState()); if (pop > 0) { m_stackState.pop(pop); } } /** * Initialize stack state to array of value types. This can be used to set * the expected stack state following an unconditional transfer of control * instruction. * * @param types array of type names on stack */ protected void initStackState(String[] types) { m_stackState = new StringStack(types); } /** * Set branch target as next instruction added to method. This effectively * sets up a state trigger for the next append operation. The appended * instruction is set as the target for the branch. This requires that * instructions are only appended using the methods supplied in this class. * * @param branch wrapper for branch to be aimed at next instruction (may be * <code>null</code>, in which case nothing is done) */ public void targetNext(BranchWrapper branch) { if (branch != null) { if (m_targetBranches == null) { m_targetBranches = new BranchWrapper[] { branch }; if (m_stackState == null) { m_stackState = new StringStack(branch.getStackState()); } } else { int length = m_targetBranches.length; BranchWrapper[] wrappers = new BranchWrapper[length+1]; System.arraycopy(m_targetBranches, 0, wrappers, 0, length); wrappers[length] = branch; m_targetBranches = wrappers; } } } /** * Set branch targets as next instruction added to method. This effectively * sets up a state trigger for the next append operation. The appended * instruction is set as the target for all the branches. This requires that * instructions are only appended using the methods supplied in this class. * * @param branches wrappers for branches to be aimed at next instruction * (may be <code>null</code>, in which case nothing is done) */ public void targetNext(BranchWrapper[] branches) { if (branches != null && branches.length > 0) { if (m_targetBranches == null) { m_targetBranches = branches; if (m_stackState == null) { m_stackState = new StringStack(branches[0].getStackState()); } } else { int offset = m_targetBranches.length; int length = offset + branches.length; BranchWrapper[] wrappers = new BranchWrapper[length]; System.arraycopy(m_targetBranches, 0, wrappers, 0, offset); System.arraycopy(branches, 0, wrappers, offset, branches.length); m_targetBranches = wrappers; } } } /** * Process accumulated exceptions. Each subclass must implement this * method to perform the appropriate handling of the checked exceptions * that may be thrown in the constructed method. * * @throws JiBXException on error in exception handling */ protected abstract void handleExceptions() throws JiBXException; /** * Complete method construction. Finalizes the instruction list and * generates the byte code for the constructed method, then computes the * hash code based on the byte code. If requested, an appropriate suffix is * tacked on the end of the supplied name in order to make sure that it will * not be duplicated (even in a superclass or subclass). * * @param suffix add suffix to make method name unique * @throws JiBXException on error in finishing method construction */ public void codeComplete(boolean suffix) throws JiBXException { if (m_targetBranches != null) { throw new IllegalStateException ("Method complete with pending branch target"); } if (m_exceptions != null) { handleExceptions(); } if (suffix) { m_generator.setName(getClassFile(). makeUniqueMethodName(m_generator.getName())); } m_generator.setMaxStack(); m_generator.setMaxLocals(); m_instructionList.setPositions(true); m_method = m_generator.getMethod(); m_instructionList.dispose(); m_hashCode = computeMethodHash(m_method); } /** * Get the method item. * * @return method item information */ public ClassItem getItem() { if (m_item == null) { throw new IllegalStateException("Method not added to class"); } else { return m_item; } } /** * Get hash code. This is based only on the byte code in the method, and * is only valid after the {@link #codeComplete} method is called. * * @return hash code based on code sequence */ public int hashCode() { if (m_method == null) { throw new IllegalStateException("Method still under construction"); } else { return m_hashCode; } } /** * Add constructed method to class. Makes the method callable, generating * the method information. * * @return added method information * @throws JiBXException on error in finishing method construction */ public ClassItem addMethod() throws JiBXException { if (m_method == null) { throw new IllegalStateException("Method not finalized."); } else { m_item = getClassFile().addMethod(m_method); return m_item; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -