Java Code Examples for org.objectweb.asm.Opcodes#DUP

The following examples show how to use org.objectweb.asm.Opcodes#DUP . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SpecialArmorApplyVisitor.java    From GregTech with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    if (checkTargetInsn(opcode, owner, name, desc)) {
    	markPatchedSuccessfully();
        super.visitFieldInsn(Opcodes.PUTSTATIC, TARGET_CLASS_NAME, SpecialArmorClassVisitor.CACHED_TOUGHNESS_FIELD_NAME, "F"); //store armorToughness
        super.visitFieldInsn(Opcodes.PUTSTATIC, TARGET_CLASS_NAME, SpecialArmorClassVisitor.CACHED_TOTAL_ARMOR_FIELD_NAME, "F"); //store totalArmor
        super.visitInsn(Opcodes.DUP); //duplicate damage
        super.visitVarInsn(Opcodes.ALOAD, 0); //load entity
        super.visitVarInsn(Opcodes.ALOAD, 1); //load inventory
        super.visitVarInsn(Opcodes.ALOAD, 2); //load damageSource
        super.visitMethodInsn(Opcodes.INVOKESTATIC, ARMOR_HOOKS_OWNER, ARMOR_HOOKS_METHOD_NAME, ARMOR_HOOKS_SIGNATURE, false); //call ArmorHooks
        super.visitFieldInsn(Opcodes.GETSTATIC, TARGET_CLASS_NAME, SpecialArmorClassVisitor.CACHED_TOTAL_ARMOR_FIELD_NAME, "F"); //load totalArmor back
        super.visitFieldInsn(Opcodes.GETSTATIC, TARGET_CLASS_NAME, SpecialArmorClassVisitor.CACHED_TOUGHNESS_FIELD_NAME, "F"); //load armorToughness back
    }
    super.visitMethodInsn(opcode, owner, name, desc, itf);
}
 
Example 2
Source File: ReturnValuesMutator.java    From pitest with Apache License 2.0 6 votes vote down vote up
/**
 * Mutates a primitive float return (<code>Opcode.FRETURN</code>). The
 * strategy used was translated from jumble BCEL code. The following is
 * complicated by the problem of <tt>NaN</tt>s. By default the new value is
 * <code>-(x + 1)</code>, but this doesn't work for <tt>NaN</tt>s. But for a
 * <tt>NaN</tt> <code>x != x</code> is true, and we use this to detect them.
 *
 * @see #mutatePrimitiveDoubleReturn()
 */
private void mutatePrimitiveFloatReturn() {
  if (shouldMutate("primitive float", "(x != NaN)? -(x + 1) : -1 ")) {
    final Label label = new Label();

    super.visitInsn(Opcodes.DUP);
    super.visitInsn(Opcodes.DUP);
    super.visitInsn(Opcodes.FCMPG);
    super.visitJumpInsn(Opcodes.IFEQ, label);

    super.visitInsn(Opcodes.POP);
    super.visitInsn(Opcodes.FCONST_0);

    // the following code is executed in NaN case, too
    super.visitLabel(label);
    super.visitInsn(Opcodes.FCONST_1);
    super.visitInsn(Opcodes.FADD);
    super.visitInsn(Opcodes.FNEG);
    super.visitInsn(Opcodes.FRETURN);
  }
}
 
Example 3
Source File: AllocationMethodAdapter.java    From allocation-instrumenter with Apache License 2.0 6 votes vote down vote up
private void buildRecorderFromObject(
    int opcode, String owner, String name, String signature, boolean itf) {
  super.visitMethodInsn(opcode, owner, name, signature, itf);
  // -> stack: ... newobj
  super.visitInsn(Opcodes.DUP);
  // -> stack: ... newobj newobj
  super.visitInsn(Opcodes.DUP);
  // -> stack: ... newobj newobj newobj
  // We could be instantiating this class or a subclass, so we
  // have to get the class the hard way.
  super.visitMethodInsn(
      Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
  // -> stack: ... newobj newobj Class
  super.visitInsn(Opcodes.SWAP);
  // -> stack: ... newobj Class newobj
  super.visitMethodInsn(
      Opcodes.INVOKESTATIC, recorderClass, recorderMethod, CLASS_RECORDER_SIG, false);
  // -> stack: ... newobj
}
 
Example 4
Source File: DupExpression.java    From CodenameOne with GNU General Public License v2.0 6 votes vote down vote up
public static int tryReduce(List<Instruction> instructions, int index) {
    Instruction instr = instructions.get(index);
    if (index < 1 || instr.getOpcode() != Opcodes.DUP) {
        return -1;
    }
    
    Instruction prev = instructions.get(index-1);
    StringBuilder devNull = new StringBuilder();
    if (prev.getOpcode() == Opcodes.ALOAD && prev instanceof AssignableExpression && ((AssignableExpression)prev).assignTo(null, devNull)) {
        DupExpression dup = new DupExpression();
        dup.sourceInstr = prev;
        dup.dupInstr = instr;
        instructions.remove(index);
        instructions.add(index, dup);
        return index;
    }
    return -1;
}
 
Example 5
Source File: ReturnValuesMutator.java    From pitest with Apache License 2.0 6 votes vote down vote up
private void mutatePrimitiveIntegerReturn() {

      if (shouldMutate("primitive boolean/byte/short/integer",
          "(x == 1) ? 0 : x + 1")) {
        final Label label = new Label();

        super.visitInsn(Opcodes.DUP);
        super.visitInsn(Opcodes.ICONST_1);
        super.visitJumpInsn(Opcodes.IF_ICMPEQ, label);

        super.visitInsn(Opcodes.ICONST_1);
        super.visitInsn(Opcodes.IADD);
        super.visitInsn(Opcodes.IRETURN);

        super.visitLabel(label);
        super.visitInsn(Opcodes.ICONST_0);
        super.visitInsn(Opcodes.IRETURN);
      }
    }
 
Example 6
Source File: AllocateInstrument.java    From dacapobench with Apache License 2.0 6 votes vote down vote up
private void addWhereAmI() {
	// 0: new #2; //class java/lang/Exception
	// 3: dup
	// 4: invokespecial #3; //Method java/lang/Exception."<init>":()V
	// 7: invokevirtual #4; //Method
	// java/lang/Exception.printStackTrace:()V
	// 10: return
	// super.visitTypeInsn(Opcodes.NEW, type);
	String exClass = Type.getInternalName(Exception.class);
	super.visitTypeInsn(Opcodes.NEW, exClass);
	super.visitInsn(Opcodes.DUP);
	super.visitMethodInsn(Opcodes.INVOKESPECIAL, exClass, "<init>",
			"()V");
	super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, exClass,
			"printStackTrace", "()V");
}
 
Example 7
Source File: RuntimeInstrument.java    From dacapobench with Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("unused")
protected void onMethodEnter() {
	if (done) return;

	overridden = true;
	Label start  = new Label();
	Label normal = new Label();
	super.visitLabel(start);
	super.visitFieldInsn(Opcodes.GETSTATIC, CONFIGURATION, CONFIGURATION_FIELD_NAME, Type.INT_TYPE.getDescriptor());
	super.visitInsn(Opcodes.DUP);
	super.visitJumpInsn(Opcodes.IFEQ, normal);
	super.visitInsn(Opcodes.IRETURN);
	super.visitLabel(normal);
	super.visitInsn(Opcodes.POP);
	Label end = new Label();
	super.visitJumpInsn(Opcodes.GOTO, end);
	super.visitLabel(end);
	super.visitTryCatchBlock(start, normal, end, Type.getType(Throwable.class).getDescriptor());
}
 
Example 8
Source File: FlowObfuscationTransformer.java    From deobfuscator with Apache License 2.0 6 votes vote down vote up
private List<AbstractInsnNode> getPossibleSwap(AbstractInsnNode ain, int mode)
{
	AbstractInsnNode next = ain;
	List<AbstractInsnNode> instrs = new ArrayList<>();
	while(next != null)
	{
		if(Utils.isInstruction(next) && next.getOpcode() != Opcodes.IINC)
			instrs.add(next);
		if(instrs.size() >= (mode == 0 ? 3 : 4))
			break;
		next = next.getNext();
	}
	if(mode == 0 && instrs.size() >= 3 && willPush(instrs.get(0)) && willPush(instrs.get(1))
		&& instrs.get(2).getOpcode() == Opcodes.SWAP)
		return instrs;
	else if(mode == 1 && instrs.size() >= 4 && willPush(instrs.get(0)) 
		&& (willPush(instrs.get(1)) || instrs.get(1).getOpcode() == Opcodes.DUP)
		&& instrs.get(2).getOpcode() == Opcodes.GETFIELD
		&& Type.getType(((FieldInsnNode)instrs.get(2)).desc).getSort() != Type.LONG
		&& Type.getType(((FieldInsnNode)instrs.get(2)).desc).getSort() != Type.DOUBLE
		&& instrs.get(3).getOpcode() == Opcodes.SWAP)
		return instrs;
	else
		return null;
}
 
Example 9
Source File: FlowObfuscationTransformer.java    From deobfuscator with Apache License 2.0 6 votes vote down vote up
private List<AbstractInsnNode> getPossibleDupPop(AbstractInsnNode ain)
{
	AbstractInsnNode next = ain;
	List<AbstractInsnNode> instrs = new ArrayList<>();
	while(next != null)
	{
		if(Utils.isInstruction(next) && next.getOpcode() != Opcodes.IINC)
			instrs.add(next);
		if(instrs.size() >= 3)
			break;
		next = next.getNext();
	}
	if(instrs.size() >= 3 && (willPush(instrs.get(0)) || ain.getOpcode() == Opcodes.DUP) 
		&& (willPush(instrs.get(1)) || instrs.get(1).getOpcode() == Opcodes.DUP)
		&& instrs.get(2).getOpcode() == Opcodes.POP2)
		return instrs;
	else
		return null;
}
 
Example 10
Source File: MethodHookInjector.java    From Hook-Manager with Mozilla Public License 2.0 5 votes vote down vote up
@Override
public void visitInsn(int opcode)
{
	if(methodData.hasHookAt(HookPosition.METHOD_END) && opcode >= 172
		&& opcode <= 177)
	{
		HookData hookData = methodData.getHook(HookPosition.METHOD_END);
		super.visitLdcInsn(className + "." + methodName + "|end");
		
		if(hookData.collectsParams())
		{
			
			super.visitIntInsn(Opcodes.BIPUSH, paramCount);
			super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
			for(byte i = 0; i < paramCount; i++)
			{
				super.visitInsn(Opcodes.DUP);
				super.visitIntInsn(Opcodes.BIPUSH, i);
				super.visitVarInsn(Opcodes.ALOAD, i);
				super.visitInsn(Opcodes.AASTORE);
			}
		}
		
		// TODO: Custom class path
		super.visitMethodInsn(Opcodes.INVOKESTATIC,
			"tk/wurst_client/hooks/HookManager", "hook",
			"(Ljava/lang/String;"
				+ (hookData.collectsParams() ? "[Ljava/lang/Object;" : "")
				+ ")V", false);
	}
	super.visitInsn(opcode);
}
 
Example 11
Source File: AllocationMethodAdapter.java    From allocation-instrumenter with Apache License 2.0 5 votes vote down vote up
private void pushClassNameOnStack() {
  super.visitInsn(Opcodes.DUP);
  // -> stack: ... class class
  super.visitMethodInsn(
      Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
  // -> stack: ... class classNameDotted
}
 
Example 12
Source File: MethodHookInjector.java    From Hook-Manager with Mozilla Public License 2.0 5 votes vote down vote up
@Override
public void visitCode()
{
	super.visitCode();
	if(methodData.hasHookAt(HookPosition.METHOD_START))
	{
		HookData hookData = methodData.getHook(HookPosition.METHOD_START);
		super.visitLdcInsn(className + "." + methodName + "|start");
		
		if(hookData.collectsParams())
		{
			super.visitIntInsn(Opcodes.BIPUSH, paramCount);
			super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
			for(byte i = 0; i < paramCount; i++)
			{
				super.visitInsn(Opcodes.DUP);
				super.visitIntInsn(Opcodes.BIPUSH, i);
				super.visitVarInsn(Opcodes.ALOAD, i);
				super.visitInsn(Opcodes.AASTORE);
			}
		}
		
		// TODO: Custom class path
		super.visitMethodInsn(Opcodes.INVOKESTATIC,
			"tk/wurst_client/hooks/HookManager", "hook",
			"(Ljava/lang/String;"
				+ (hookData.collectsParams() ? "[Ljava/lang/Object;" : "")
				+ ")V", false);
	}
}
 
Example 13
Source File: HeaderClassLoader.java    From bazel with Apache License 2.0 5 votes vote down vote up
@Override
public void visitEnd() {
  if (!hasCode) {
    super.visitTypeInsn(Opcodes.NEW, EXCEPTION_INTERNAL_NAME);
    super.visitInsn(Opcodes.DUP);
    super.visitMethodInsn(
        Opcodes.INVOKESPECIAL, EXCEPTION_INTERNAL_NAME, "<init>", "()V", /*itf*/ false);
    super.visitInsn(Opcodes.ATHROW);
    super.visitMaxs(0, 0); // triggers computation of the actual max's
  }
  super.visitEnd();
}
 
Example 14
Source File: IncrementalChangeVisitor.java    From AnoleFix with MIT License 5 votes vote down vote up
@Override
public void visitInsn(int opcode) {
    // check the last object allocation we encountered, if this is in the same package
    // we need to go through reflection and should therefore remove the DUP, otherwise
    // we leave it.
    if (opcode == Opcodes.DUP && state == MachineState.AFTER_NEW) {

        state = MachineState.NORMAL;
        return;
    }
    super.visitInsn(opcode);
}
 
Example 15
Source File: AllocateInstrument.java    From dacapobench with Apache License 2.0 5 votes vote down vote up
private void addLog(boolean dup, int site) {
	if (dup)
		super.visitInsn(Opcodes.DUP);
	super.visitLdcInsn(new Integer(site));
	super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
			LOG_INTERNAL_ALLOC_REPORT, OBJECT_SITE_SIGNATURE);
	if (!constructor)
		super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
				LOG_INTERNAL_ALLOC_DONE, VOID_SIGNATURE);
}
 
Example 16
Source File: StateTrackingMethodVisitor.java    From scott with MIT License 5 votes vote down vote up
private void instrumentToTrackReturn(int opcode) {
	if (!VariableType.isReturnOperation(opcode)) {
		return;
	}
	
	if (Opcodes.RETURN == opcode) {
		super.visitLdcInsn(lineNumber);
		super.visitLdcInsn(methodName);
		super.visitLdcInsn(Type.getType("L" + className + ";"));
		super.visitMethodInsn(Opcodes.INVOKESTATIC, instrumentationActions.trackerClass, "trackReturn", "(ILjava/lang/String;Ljava/lang/Class;)V", false);
	} else {
		if (opcode == Opcodes.DRETURN || opcode == Opcodes.LRETURN) {
			super.visitInsn(Opcodes.DUP2);
		} else {
			super.visitInsn(Opcodes.DUP);
		}
		
		final VariableType variableType;
		if (opcode == Opcodes.IRETURN) {
			variableType = VariableType.getReturnTypeFromMethodDesc(desc);
		} else {
			variableType = VariableType.getByReturnOpCode(opcode);
		}
		
		super.visitLdcInsn(lineNumber);
		super.visitLdcInsn(methodName);
		super.visitLdcInsn(Type.getType("L" + className + ";"));
		super.visitMethodInsn(Opcodes.INVOKESTATIC, instrumentationActions.trackerClass, "trackReturn", "(" + variableType.desc + "ILjava/lang/String;Ljava/lang/Class;)V", false);
	}
}
 
Example 17
Source File: InsnNode.java    From JByteMod-Beta with GNU General Public License v2.0 4 votes vote down vote up
public InsnNode() {
  super(Opcodes.DUP);
}
 
Example 18
Source File: AllocateInstrument.java    From dacapobench with Apache License 2.0 4 votes vote down vote up
public void visitFieldInsn(int opcode, String owner, String fieldName,
		String desc) {
	if (firstInstruction)
		addInc();
	if (logPointerChange && opcode == Opcodes.PUTFIELD
			&& desc.charAt(0) == 'L') {
		if (constructor && !doneSuperConstructor && name.equals(owner)
				&& finalFields.contains(fieldName))
			delayedFieldPointer.put(fieldName, desc);
		else {
			// instrument reference changes from
			// putfield ...,obj,v' => ...
			// to
			// dup2 ...,obj,v' => ...,obj,v',obj,v'
			// swap ...,obj,v',obj,v' => ...,obj,v',v',obj
			// dup ...,obj,v',v',obj => ...,obj,v',v',obj,obj
			// getfield ...,obj,v',v',obj,obj => ...,obj,v',v',obj,v
			// invokespecial
			// pointerchangelog(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
			// ...,obj,v',v',obj,v => ...,obj,v'
			// putfield ...,obj,v' =>
			super.visitInsn(Opcodes.DUP2);
			super.visitInsn(Opcodes.SWAP);
			super.visitInsn(Opcodes.DUP);
			super.visitFieldInsn(Opcodes.GETFIELD, owner, fieldName,
					desc);
			super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
					LOG_INTERNAL_POINTER_CHANGE,
					POINTER_CHANGE_SIGNATURE);
		}
	} else if (logPointerChange && opcode == Opcodes.PUTSTATIC
			&& desc.charAt(0) == 'L') {
		// if (finalFields.contains(fieldName)) {
		// // assume field is initially null
		// super.visitInsn(Opcodes.DUP);
		// } else {
		// instrument reference changes from
		// putstatic ...,v' => ...
		// to
		// dup ...,v' => ...,v',v'
		// ldc owner.class ...,v',v' => ...,v',v',k
		// getstatic ...,v',v',k => ...,v',v',k,v
		// invokespecial
		// staticpointerchangelog(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Object;)V
		// ...,v',v',k,v => ...,v'
		super.visitInsn(Opcodes.DUP);
		super.visitLdcInsn(Type.getObjectType(owner));
		super.visitFieldInsn(Opcodes.GETSTATIC, owner, fieldName, desc);
		super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
				LOG_INTERNAL_STATIC_POINTER_CHANGE,
				STATIC_POINTER_CHANGE_SIGNATURE);
		// }
	}
	super.visitFieldInsn(opcode, owner, fieldName, desc);
}
 
Example 19
Source File: AllocationMethodAdapter.java    From allocation-instrumenter with Apache License 2.0 4 votes vote down vote up
void calculateArrayLengthAndDispatch(String typeName, int dimCount) {
  // Since the dimensions of the array are not known at instrumentation
  // time, we take the created multi-dimensional array and peel off nesting
  // levels from the left.  For each nesting layer we probe the array length
  // and accumulate a partial product which we can then feed the recording
  // function.

  // below we note the partial product of dimensions 1 to X-1 as productToX
  // (so productTo1 == 1 == no dimensions yet).  We denote by aref0 the
  // array reference at the current nesting level (the containing aref's [0]
  // element).  If we hit a level whose arraylength is 0 or whose
  // reference is null, there's no point continuing, so we shortcut
  // out.

  // This approach works pretty well when you create a new array with the
  // newarray bytecodes.  You can also create a new array by cloning an
  // existing array; an existing multidimensional array might have had some
  // of its [0] elements nulled out.  We currently deal with this by bailing
  // out, but arguably we should do something more principled (like calculate
  // the size of the multidimensional array from scratch if you are using
  // clone()).
  // TODO(java-platform-team): Do something about modified multidimensional
  // arrays and clone().
  Label zeroDimension = new Label();
  super.visitInsn(Opcodes.DUP); // -> stack: ... origaref aref0
  super.visitLdcInsn(1); // -> stack: ... origaref aref0 productTo1
  for (int i = 0; i < dimCount; ++i) {
    // pre: stack: ... origaref aref0 productToI
    super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref productToI aref
    super.visitInsn(Opcodes.DUP);

    Label nonNullDimension = new Label();
    // -> stack: ... origaref productToI aref aref
    super.visitJumpInsn(Opcodes.IFNONNULL, nonNullDimension);
    // -> stack: ... origaref productToI aref
    super.visitInsn(Opcodes.SWAP);
    // -> stack: ... origaref aref productToI
    super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
    super.visitLabel(nonNullDimension);

    // -> stack: ... origaref productToI aref
    super.visitInsn(Opcodes.DUP_X1);
    // -> stack: ... origaref aref0 productToI aref
    super.visitInsn(Opcodes.ARRAYLENGTH);
    // -> stack: ... origaref aref0 productToI dimI

    Label nonZeroDimension = new Label();
    super.visitInsn(Opcodes.DUP);
    // -> stack: ... origaref aref0 productToI dimI dimI
    super.visitJumpInsn(Opcodes.IFNE, nonZeroDimension);
    // -> stack: ... origaref aref0 productToI dimI
    super.visitInsn(Opcodes.POP);
    // -> stack: ... origaref aref0 productToI
    super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
    super.visitLabel(nonZeroDimension);
    // -> stack: ... origaref aref0 productToI max(dimI,1)

    super.visitInsn(Opcodes.IMUL);
    // -> stack: ... origaref aref0 productTo{I+1}
    if (i < dimCount - 1) {
      super.visitInsn(Opcodes.SWAP);
      // -> stack: ... origaref productTo{I+1} aref0
      super.visitInsn(Opcodes.ICONST_0);
      // -> stack: ... origaref productTo{I+1} aref0 0
      super.visitInsn(Opcodes.AALOAD);
      // -> stack: ... origaref productTo{I+1} aref0'
      super.visitInsn(Opcodes.SWAP);
    }
    // post: stack: ... origaref aref0 productTo{I+1}
  }
  super.visitLabel(zeroDimension);

  super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref product aref0
  super.visitInsn(Opcodes.POP); // -> stack: ... origaref product
  super.visitInsn(Opcodes.SWAP); // -> stack: ... product origaref
  invokeRecordAllocation(typeName);
}
 
Example 20
Source File: LazyLoadingMethodVisitor.java    From AVM with MIT License 4 votes vote down vote up
/**
 * NOTE:  All calls to instruction visitation routines are made against super, directly, since we do frame offset accounting within our overrides
 * and that offset only applies to incoming bytecodes, not outgoing ones.
 * 
 * @param opcode The opcode.
 * @param descriptor The type descriptor of the field to which the opcode is applied.
 */
private void checkInjectLazyLoad(int opcode, String descriptor) {
    // If this is a PUTFIELD or GETFIELD, we want to call "lazyLoad()":
    // -PUTIFELD:  DUP2, POP, INVOKEVIRTUAL
    // -GETIFELD:  DUP, INVOKEVIRTUAL
    if ((Opcodes.PUTFIELD == opcode) && ((null == this.tracker) || !this.tracker.isThisTargetOfPut(this.frameOffset))) {
        // We need to see how big this type is since double and long need a far more complex dance.
        if ((1 == descriptor.length()) && ((DescriptorParser.LONG == descriptor.charAt(0)) || (DescriptorParser.DOUBLE == descriptor.charAt(0)))) {
            // Here, the stack looks like: ... OBJECT, VAR1, VAR2 (top)
            // Where we need:  ... OBJECT, VAR1, VAR2, OBJECT (top)
            // This is multiple stages:
            // DUP2_X1: ... VAR1, VAR2, OBJECT, VAR1, VAR2 (top)
            super.visitInsn(Opcodes.DUP2_X1);
            // POP2: ... VAR1, VAR2, OBJECT (top)
            super.visitInsn(Opcodes.POP2);
            // DUP: ... VAR1, VAR2, OBJECT, OBJECT (top)
            super.visitInsn(Opcodes.DUP);
            // INOKE: ... VAR1, VAR2, OBJECT (top)
            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, SHADOW_OBJECT_NAME, LAZY_LOAD_NAME, LAZY_LOAD_DESCRIPTOR, false);
            // DUP_X2: ... OBJECT, VAR1, VAR2, OBJECT (top)
            super.visitInsn(Opcodes.DUP_X2);
            // POP: ... OBJECT, VAR1, VAR2 (top)
            super.visitInsn(Opcodes.POP);
        } else {
            // Here, the stack looks like: ... OBJECT, VAR, (top)
            // Where we need:  ... OBJECT, VAR, OBJECT (top)
            // Stages:
            // DUP2: ... OBJECT, VAR, OBJECT, VAR (top)
            super.visitInsn(Opcodes.DUP2);
            // POP: ... OBJECT, VAR, OBJECT (top)
            super.visitInsn(Opcodes.POP);
            // INOKE: ... OBJECT, VAR (top)
            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, SHADOW_OBJECT_NAME, LAZY_LOAD_NAME, LAZY_LOAD_DESCRIPTOR, false);
        }
    } else if ((Opcodes.GETFIELD == opcode) && ((null == this.tracker) || !this.tracker.isThisTargetOfGet(this.frameOffset))) {
        // Here, the stack looks like: ... OBJECT, (top)
        // Where we need:  ... OBJECT, OBJECT (top)
        super.visitInsn(Opcodes.DUP);
        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, SHADOW_OBJECT_NAME, LAZY_LOAD_NAME, LAZY_LOAD_DESCRIPTOR, false);
    }
}