📄 methodinliner.java
字号:
// Copy the instructions. codeAttribute.instructionsAccept(clazz, method, this); // Copy the exceptions. codeAttribute.exceptionsAccept(clazz, method, this); // Append a label just after the code. codeAttributeComposer.appendLabel(codeAttribute.u4codeLength); codeAttributeComposer.endCodeFragment(); } // Implementations for InstructionVisitor. public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) { codeAttributeComposer.appendInstruction(offset, instruction.shrink()); } public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) { // Are we inlining this instruction? if (inlining) { // Replace any return instructions by branches to the end of the code. switch (simpleInstruction.opcode) { case InstructionConstants.OP_IRETURN: case InstructionConstants.OP_LRETURN: case InstructionConstants.OP_FRETURN: case InstructionConstants.OP_DRETURN: case InstructionConstants.OP_ARETURN: case InstructionConstants.OP_RETURN: // Are we not at the last instruction? if (offset < codeAttribute.u4codeLength-1) { // Replace the return instruction by a branch instruction. Instruction branchInstruction = new BranchInstruction(InstructionConstants.OP_GOTO_W, codeAttribute.u4codeLength - offset); codeAttributeComposer.appendInstruction(offset, branchInstruction.shrink()); } else { // Just leave out the instruction, but put in a label, // for the sake of any other branch instructions. codeAttributeComposer.appendLabel(offset); } return; } } codeAttributeComposer.appendInstruction(offset, simpleInstruction.shrink()); } public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) { // Are we inlining this instruction? if (inlining) { // Update the variable index. variableInstruction.variableIndex += variableOffset; } codeAttributeComposer.appendInstruction(offset, variableInstruction.shrink()); } public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) { // Is it a method invocation? switch (constantInstruction.opcode) { case InstructionConstants.OP_NEW: uninitializedObjectCount++; break; case InstructionConstants.OP_INVOKEVIRTUAL: case InstructionConstants.OP_INVOKESPECIAL: case InstructionConstants.OP_INVOKESTATIC: case InstructionConstants.OP_INVOKEINTERFACE: // See if we can inline it. inlined = false; // Append a label, in case the invocation will be inlined. codeAttributeComposer.appendLabel(offset); emptyInvokingStack = !inlining && stackSizeComputer.isReachable(offset) && stackSizeComputer.getStackSize(offset) == 0; variableOffset += codeAttribute.u2maxLocals; clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); variableOffset -= codeAttribute.u2maxLocals; // Was the method inlined? if (inlined) { if (extraInlinedInvocationVisitor != null) { extraInlinedInvocationVisitor.visitConstantInstruction(clazz, method, codeAttribute, offset, constantInstruction); } // The invocation itself is no longer necessary. return; } break; } // Are we inlining this instruction? if (inlining) { // Make sure the constant is present in the constant pool of the // target class. clazz.constantPoolEntryAccept(constantInstruction.constantIndex, constantAdder); // Let the instruction point to this constant. constantInstruction.constantIndex = constantAdder.getConstantIndex(); } codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink()); } // Implementations for ExceptionInfoVisitor. public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) { int catchType = exceptionInfo.u2catchType; if (inlining && catchType != 0) { // Make sure the constant is present in the constant pool of the // target class. clazz.constantPoolEntryAccept(catchType, constantAdder); // Let the exception point to this constant. catchType = constantAdder.getConstantIndex(); } codeAttributeComposer.appendException(new ExceptionInfo(exceptionInfo.u2startPC, exceptionInfo.u2endPC, exceptionInfo.u2handlerPC, catchType)); } // Implementations for ConstantVisitor. public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) {} public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) { methodrefConstant.referencedMemberAccept(this); } // Implementations for MemberVisitor. public void visitAnyMember(Clazz Clazz, Member member) {} public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { int accessFlags = programMethod.getAccessFlags(); if (// Only inline the method if it is private, static, or final. (accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_FINAL)) != 0 && // Only inline the method if it is not synchronized, etc. (accessFlags & (ClassConstants.INTERNAL_ACC_SYNCHRONIZED | ClassConstants.INTERNAL_ACC_NATIVE | ClassConstants.INTERNAL_ACC_INTERFACE | ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 && // Don't inline an <init> method, except in an <init> method in the // same class. (!programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) || (programClass.equals(targetClass) && targetMethod.getName(targetClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))) && // Don't inline a recursive method. (!programMethod.equals(targetMethod) || !programClass.equals(targetClass)) && // Don't inline a method that invokes a super method, unless it is // in the same class. (!SuperInvocationMarker.invokesSuperMethods(programMethod) || programClass.equals(targetClass)) && // Don't inline a method that branches backward while there are // uninitialized objects. (!BackwardBranchMarker.branchesBackward(programMethod) || uninitializedObjectCount == 0) && // Only inline if the code access of the inlined method allows it. (allowAccessModification || ((!AccessMethodMarker.accessesPrivateCode(programMethod) || programClass.equals(targetClass)) && (!AccessMethodMarker.accessesPackageCode(programMethod) || ClassUtil.internalPackageName(programClass.getName()).equals( ClassUtil.internalPackageName(targetClass.getName()))))) &&// (!AccessMethodMarker.accessesProtectedCode(programMethod) ||// targetClass.extends_(programClass) ||// targetClass.implements_(programClass)) || (!AccessMethodMarker.accessesProtectedCode(programMethod) || programClass.equals(targetClass)) && // Don't inline the method if it catches exceptions, unless it is // invoked with an empty stack. (!CatchExceptionMarker.catchesExceptions(programMethod) || emptyInvokingStack)) {// System.out.print("MethodInliner: inlining ");// programMethod.accept(programClass, new SimpleClassPrinter(true));// System.out.print(" in ");// targetMethod.accept(targetClass, new SimpleClassPrinter(true));//// System.out.println(" Private: "+// (!AccessMethodMarker.accessesPrivateCode(programMethod) ||// programClass.equals(targetClass)));//// System.out.println(" Package: "+// (!AccessMethodMarker.accessesPackageCode(programMethod) ||// ClassUtil.internalPackageName(programClass.getName()).equals(// ClassUtil.internalPackageName(targetClass.getName()))));//// System.out.println(" Protected: "+// ((!AccessMethodMarker.accessesProtectedCode(programMethod) ||// targetClass.extends_(programClass) ||// targetClass.implements_(programClass)) ||// ClassUtil.internalPackageName(programClass.getName()).equals(// ClassUtil.internalPackageName(targetClass.getName())))); boolean oldInlining = inlining; inlining = true; // Inline the method body. programMethod.attributesAccept(programClass, this); inlining = oldInlining; } else if (programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) { uninitializedObjectCount--; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -