Java Code Examples for org.objectweb.asm.commons.GeneratorAdapter#pop()

The following examples show how to use org.objectweb.asm.commons.GeneratorAdapter#pop() . 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: ByteCodeUtils.java    From Stark with Apache License 2.0 6 votes vote down vote up
/**
 * Given an array with values at the top of the stack, the values are unboxed and stored
 * on the given variables. The array is popped from the stack.
 */
static void restoreVariables(
        @NonNull GeneratorAdapter mv,
        @NonNull List<LocalVariable> variables) {
    for (int i = 0; i < variables.size(); i++) {
        LocalVariable variable = variables.get(i);
        // Duplicates the array on the stack;
        mv.dup();
        // Sets up the index
        mv.push(i);
        // Gets the Object value
        mv.arrayLoad(Type.getType(Object.class));
        // Unboxes to the type of the local variable
        mv.unbox(variable.type);
        // Restores the local variable
        mv.visitVarInsn(variable.type.getOpcode(Opcodes.ISTORE), variable.var);
    }
    // Pops the array from the stack.
    mv.pop();
}
 
Example 2
Source File: Redirection.java    From Stark with Apache License 2.0 6 votes vote down vote up
/**
 * Adds the instructions to do a generic redirection.
 * <p>
 * Note that the generated bytecode does not have a direct translation to code, but as an
 * example, the following code block gets inserted.
 * <code>
 * if ($starkChange != null) {
 *   $starkChange.access$dispatch($name, new object[] { arg0, ... argsN })
 *   $anyCodeInsertedbyRestore
 * }
 * $originalMethodBody
 *</code>
 * @param mv the method visitor to add the instructions to.
 * @param change the local variable containing the alternate implementation.
 */
void redirect(GeneratorAdapter mv, int change) {
    // code to check if a new implementation of the current class is available.
    Label l0 = new Label();
    mv.loadLocal(change);
    mv.visitJumpInsn(Opcodes.IFNULL, l0);

    doRedirect(mv, change);

    // Return
    if (type == Type.VOID_TYPE) {
        mv.pop();
    } else {
        ByteCodeUtils.unbox(mv, type);
    }
    mv.returnValue();

    // jump label for classes without any new implementation, just invoke the original
    // method implementation.
    mv.visitLabel(l0);
}
 
Example 3
Source File: Redirection.java    From Aceso with Apache License 2.0 6 votes vote down vote up
/**
 * Adds the instructions to do a generic redirection.
 */
protected void redirect(GeneratorAdapter mv, int change) {
    // code to check if a new implementation of the current class is available.
    Label l0 = new Label();
    mv.loadLocal(change);
    mv.visitJumpInsn(Opcodes.IFNULL, l0);
    doRedirect(mv, change);

    // Return
    if (type == Type.VOID_TYPE) {
        mv.pop();
    } else {
        ByteCodeUtils.unbox(mv, type);
    }
    mv.returnValue();

    // jump label for classes without any new implementation, just invoke the original
    // method implementation.
    mv.visitLabel(l0);
}
 
Example 4
Source File: ExpressionSequence.java    From datakernel with Apache License 2.0 6 votes vote down vote up
@Override
public Type load(Context ctx) {
	GeneratorAdapter g = ctx.getGeneratorAdapter();

	Type type = VOID_TYPE;
	for (int i = 0; i < expressions.size(); i++) {
		Expression expression = expressions.get(i);
		type = expression.load(ctx);
		if (i != expressions.size() - 1) {
			if (type.getSize() == 1)
				g.pop();
			if (type.getSize() == 2)
				g.pop2();
		}
	}

	return type;
}
 
Example 5
Source File: AbstractExpressionMapForEach.java    From datakernel with Apache License 2.0 5 votes vote down vote up
@Override
public final Type load(Context ctx) {
	GeneratorAdapter g = ctx.getGeneratorAdapter();
	Label labelLoop = new Label();
	Label labelExit = new Label();

	ctx.invoke(getEntries(), "iterator");
	VarLocal iterator = ctx.newLocal(getType(Iterator.class));
	iterator.store(ctx);

	g.mark(labelLoop);

	ctx.invoke(iterator, "hasNext");
	g.push(false);
	g.ifCmp(BOOLEAN_TYPE, GeneratorAdapter.EQ, labelExit);

	Type entryType = getType(entryClazz);
	ctx.cast(ctx.invoke(iterator, "next"), entryType);

	VarLocal entry = ctx.newLocal(entryType);
	entry.store(ctx);

	Type forKeyType = forKey.apply(getKey(entry)).load(ctx);
	if (forKeyType.getSize() == 1)
		g.pop();
	if (forKeyType.getSize() == 2)
		g.pop2();

	Type forValueType = forValue.apply(getValue(entry)).load(ctx);
	if (forValueType.getSize() == 1)
		g.pop();
	if (forValueType.getSize() == 2)
		g.pop2();

	g.goTo(labelLoop);
	g.mark(labelExit);
	return Type.VOID_TYPE;
}
 
Example 6
Source File: ExpressionFor.java    From datakernel with Apache License 2.0 5 votes vote down vote up
@Override
public Type load(Context ctx) {
	GeneratorAdapter g = ctx.getGeneratorAdapter();
	Label labelLoop = new Label();
	Label labelExit = new Label();

	VarLocal to = ctx.newLocal(INT_TYPE);
	this.to.load(ctx);
	to.store(ctx);

	from.load(ctx);
	VarLocal it = ctx.newLocal(INT_TYPE);
	it.store(ctx);

	g.mark(labelLoop);

	it.load(ctx);
	to.load(ctx);

	g.ifCmp(INT_TYPE, GeneratorAdapter.GE, labelExit);

	Type forType = forVar.apply(it).load(ctx);
	if (forType.getSize() == 1)
		g.pop();
	if (forType.getSize() == 2)
		g.pop2();

	it.load(ctx);
	g.push(1);
	g.math(GeneratorAdapter.ADD, INT_TYPE);
	it.store(ctx);

	g.goTo(labelLoop);
	g.mark(labelExit);

	return VOID_TYPE;
}
 
Example 7
Source File: ConstructorRedirection.java    From Stark with Apache License 2.0 4 votes vote down vote up
@Override
protected void doRedirect(GeneratorAdapter mv, int change) {
    mv.loadLocal(change);
    mv.push("init$args." + constructor.args.desc);

    Type arrayType = Type.getType("[Ljava/lang/Object;");
    // init$args args (including this) + locals
    mv.push(types.size() + 1);
    mv.newArray(Type.getType(Object.class));

    int array = mv.newLocal(arrayType);
    mv.dup();
    mv.storeLocal(array);

    // "this" is not ready yet, use null instead.
    mv.dup();
    mv.push(0);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.arrayStore(Type.getType(Object.class));

    // Set the arguments in positions 1..(n-1);
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value

    // Add the locals array at the last position.
    mv.dup();
    // The index of the last position of the array.
    mv.push(types.size());
    // Create the array with all the local variables declared up to this point.
    ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis));
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(MonitorVisitor.CHANGE_TYPE, Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    //// At this point, init$args has been called and the result Object is on the stack.
    //// The value of that Object is Object[] with exactly n + 2 elements.
    //// The first element is the resulting local variables
    //// The second element is a string with the qualified name of the constructor to call.
    //// The remaining elements are the constructor arguments.

    // Keep a reference to the new locals array
    mv.dup();
    mv.push(0);
    mv.arrayLoad(Type.getType("[Ljava/lang/Object;"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    mv.storeLocal(array);

    // Call super constructor
    // Put this behind the returned array
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.swap();
    // Push a null for the marker parameter.
    mv.visitInsn(Opcodes.ACONST_NULL);
    // Invoke the constructor
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, "<init>", DISPATCHING_THIS_SIGNATURE, false);

    // Dispatch to init$body
    mv.loadLocal(change);
    mv.push("init$body." + constructor.body.desc);
    mv.loadLocal(array);

    // Now "this" can be set
    mv.dup();
    mv.push(0);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(MonitorVisitor.CHANGE_TYPE, Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.pop();
}
 
Example 8
Source File: TBConstructorRedirection.java    From atlas with Apache License 2.0 4 votes vote down vote up
@Override
protected void doRedirect(GeneratorAdapter mv, int change) {
    mv.loadLocal(change);
    mv.push("init$args." + constructor.args.desc);

    Type arrayType = Type.getType("[Ljava/lang/Object;");
    // init$args args (including this) + locals
    mv.push(types.size() + 1);
    mv.newArray(Type.getType(Object.class));

    int array = mv.newLocal(arrayType);
    mv.dup();
    mv.storeLocal(array);

    // "this" is not ready yet, use null instead.
    mv.dup();
    mv.push(0);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.arrayStore(Type.getType(Object.class));

    // Set the arguments in positions 1..(n-1);
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value

    // Add the locals array at the last position.
    mv.dup();
    // The index of the last position of the array.
    mv.push(types.size());
    // Create the array with all the local variables declared up to this point.
    ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis));
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(TBIncrementalVisitor.ALI_CHANGE_TYPE, Method.getMethod("Object ipc$dispatch(String, Object[])"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    //// At this point, init$args has been called and the result Object is on the stack.
    //// The value of that Object is Object[] with exactly n + 2 elements.
    //// The first element is the resulting local variables
    //// The second element is a string with the qualified name of the constructor to call.
    //// The remaining elements are the constructor arguments.

    // Keep a reference to the new locals array
    mv.dup();
    mv.push(0);
    mv.arrayLoad(Type.getType("[Ljava/lang/Object;"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    mv.storeLocal(array);

    // Call super constructor
    // Put this behind the returned array
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.swap();
    // Push a null for the marker parameter.
    mv.visitInsn(Opcodes.ACONST_NULL);
    // Invoke the constructor
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, "<init>", DISPATCHING_THIS_SIGNATURE, false);

    // Dispatch to init$body
    mv.loadLocal(change);
    mv.push("init$body." + constructor.body.desc);
    mv.loadLocal(array);

    // Now "this" can be set
    mv.dup();
    mv.push(0);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(TBIncrementalVisitor.ALI_CHANGE_TYPE, Method.getMethod("Object ipc$dispatch(String, Object[])"));
    mv.pop();
}
 
Example 9
Source File: ConstructorArgsRedirection.java    From AnoleFix with MIT License 4 votes vote down vote up
@Override
protected void restore(GeneratorAdapter mv, List<Type> args) {
    // At this point, init$args has been called and the result Object is on the stack.
    // The value of that Object is Object[] with exactly n + 1 elements.
    // The first element is a string with the qualified name of the constructor to call.
    // The remaining elements are the constructtor arguments.

    // Create a new local that holds the result of init$args call.
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    int constructorArgs = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(constructorArgs);

    // Reinstate local values
    mv.loadLocal(locals);
    int stackIndex = 0;
    for (int arrayIndex = 0; arrayIndex < args.size(); arrayIndex++) {
        Type arg = args.get(arrayIndex);
        // Do not restore "this"
        if (arrayIndex > 0) {
            // duplicates the array
            mv.dup();
            // index in the array of objects to restore the boxed parameter.
            mv.push(arrayIndex);
            // get it from the array
            mv.arrayLoad(Type.getType(Object.class));
            // unbox the argument
            ByteCodeUtils.unbox(mv, arg);
            // restore the argument
            mv.visitVarInsn(arg.getOpcode(Opcodes.ISTORE), stackIndex);
        }
        // stack index must progress according to the parameter type we just processed.
        stackIndex += arg.getSize();
    }
    // pops the array
    mv.pop();

    // Push a null for the marker parameter.
    mv.loadLocal(constructorArgs);
    mv.visitInsn(Opcodes.ACONST_NULL);

    // Invoke the constructor
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, thisClassName, "<init>", DISPATCHING_THIS_SIGNATURE, false);

    mv.goTo(end.getLabel());
}
 
Example 10
Source File: TestThreadExecutionGenerator.java    From lin-check with GNU Lesser General Public License v3.0 4 votes vote down vote up
private static void generateRun(ClassVisitor cv, Type testType, int iThread, List<Actor> actors, List<Object> objArgs, boolean waitsEnabled) {
    int access = ACC_PUBLIC;
    Method m = new Method("call", RESULT_ARRAY_TYPE, NO_ARGS);
    GeneratorAdapter mv = new GeneratorAdapter(access, m,
        // Try-catch blocks sorting is required
        new TryCatchBlockSorter(cv.visitMethod(access, m.getName(), m.getDescriptor(), null, null),
            access, m.getName(), m.getDescriptor(), null, null)
    );
    mv.visitCode();
    // Create Result[] array and store it to a local variable
    int resLocal = createResultArray(mv, actors.size());
    // Call runner's onStart(iThread) method
    mv.loadThis();
    mv.getField(TEST_THREAD_EXECUTION_TYPE, "runner", RUNNER_TYPE);
    mv.push(iThread);
    mv.invokeVirtual(RUNNER_TYPE, RUNNER_ON_START_METHOD);
    // Number of current operation (starts with 0)
    int iLocal = mv.newLocal(Type.INT_TYPE);
    mv.push(0);
    mv.storeLocal(iLocal);
    // Invoke actors
    for (int i = 0; i < actors.size(); i++) {
        Actor actor = actors.get(i);
        // Add busy-wait before operation execution (for non-first operations only)
        if (waitsEnabled && i > 0) {
            mv.loadThis();
            mv.getField(TEST_THREAD_EXECUTION_TYPE, "waits", INT_ARRAY_TYPE);
            mv.push(i - 1);
            mv.arrayLoad(Type.INT_TYPE);
            mv.invokeStatic(UTILS_TYPE, UTILS_CONSUME_CPU);
        }
        // Start of try-catch block for exceptions which this actor should handle
        Label start, end = null, handler = null, handlerEnd = null;
        if (actor.handlesExceptions()) {
            start = mv.newLabel();
            end = mv.newLabel();
            handler = mv.newLabel();
            handlerEnd = mv.newLabel();
            for (Class<? extends Throwable> ec : actor.handledExceptions)
                mv.visitTryCatchBlock(start, end, handler, Type.getType(ec).getInternalName());
            mv.visitLabel(start);
        }
        // Load result array and index to store the current result
        mv.loadLocal(resLocal);
        mv.push(i);
        // Load test instance
        mv.loadThis();
        mv.getField(TEST_THREAD_EXECUTION_TYPE, "testInstance", OBJECT_TYPE);
        mv.checkCast(testType);
        // Load arguments for operation
        for (int j = 0; j < actor.arguments.length; j++) {
            pushArgumentOnStack(mv, objArgs, actor.arguments[j], actor.method.getParameterTypes()[j]);
        }
        // Invoke operation
        Method actorMethod = Method.getMethod(actor.method);
        mv.invokeVirtual(testType, actorMethod);
        // Create result
        mv.box(actorMethod.getReturnType()); // box if needed
        if (actor.method.getReturnType() == void.class) {
            mv.pop();
            mv.invokeStatic(RESULT_TYPE, RESULT_CREATE_VOID_RESULT);
        } else {
            mv.invokeStatic(RESULT_TYPE, RESULT_CREATE_VALUE_RESULT);
        }
        // Store result to array
        mv.arrayStore(RESULT_TYPE);
        // End of try-catch block
        if (actor.handlesExceptions()) {
            mv.visitLabel(end);
            mv.goTo(handlerEnd);
            mv.visitLabel(handler);
            storeExceptionResultFromThrowable(mv, resLocal, iLocal);
            mv.visitLabel(handlerEnd);
        }
        // Increment number of current operation
        mv.iinc(iLocal, 1);
    }
    // Call runner's onFinish(iThread) method
    mv.loadThis();
    mv.getField(TEST_THREAD_EXECUTION_TYPE, "runner", RUNNER_TYPE);
    mv.push(iThread);
    mv.invokeVirtual(RUNNER_TYPE, RUNNER_ON_FINISH_METHOD);
    // Return results
    mv.loadThis();
    mv.loadLocal(resLocal);
    mv.returnValue();
    mv.visitMaxs(1, 1);
    mv.visitEnd();
}
 
Example 11
Source File: AbstractExpressionIteratorForEach.java    From datakernel with Apache License 2.0 4 votes vote down vote up
@Override
public final Type load(Context ctx) {
	GeneratorAdapter g = ctx.getGeneratorAdapter();
	Label labelLoop = new Label();
	Label labelExit = new Label();

	Type collectionType = collection.load(ctx);
	if (collectionType.getSort() == ARRAY) {
		return arrayForEach(ctx, g, labelLoop, labelExit);
	}

	VarLocal varIter = ctx.newLocal(getType(Iterator.class));

	Class<?> t = ctx.toJavaType(collectionType);
	if (t.isInstance(Iterator.class) || t == Iterator.class) {
		// do nothing
	} else {
		ctx.invoke(collectionType, "iterator");
	}
	varIter.store(ctx);

	g.mark(labelLoop);

	ctx.invoke(varIter, "hasNext");
	g.push(false);
	g.ifCmp(BOOLEAN_TYPE, GeneratorAdapter.EQ, labelExit);

	ctx.cast(ctx.invoke(varIter, "next"), getType(type));
	VarLocal it = ctx.newLocal(getType(type));
	it.store(ctx);

	Type forEachType = forEach.apply(getValue(it)).load(ctx);
	if (forEachType.getSize() == 1)
		g.pop();
	if (forEachType.getSize() == 2)
		g.pop2();

	g.goTo(labelLoop);
	g.mark(labelExit);
	return VOID_TYPE;

}
 
Example 12
Source File: ExpressionComparator.java    From datakernel with Apache License 2.0 4 votes vote down vote up
@Override
public Type load(Context ctx) {
	GeneratorAdapter g = ctx.getGeneratorAdapter();

	Label labelReturn = new Label();

	for (ComparablePair pair : pairs) {
		Type leftPropertyType = pair.left.load(ctx);
		Type rightPropertyType = pair.right.load(ctx);

		checkArgument(leftPropertyType.equals(rightPropertyType), "Types of compared values should match");
		if (isPrimitiveType(leftPropertyType)) {
			g.invokeStatic(wrap(leftPropertyType), new Method("compare", INT_TYPE, new Type[]{leftPropertyType, leftPropertyType}));
			g.dup();
			g.ifZCmp(NE, labelReturn);
			g.pop();
		} else if (!pair.nullable) {
			g.invokeVirtual(leftPropertyType, new Method("compareTo", INT_TYPE, new Type[]{Type.getType(Object.class)}));
			g.dup();
			g.ifZCmp(NE, labelReturn);
			g.pop();
		} else {
			VarLocal varRight = ctx.newLocal(rightPropertyType);
			varRight.store(ctx);

			VarLocal varLeft = ctx.newLocal(leftPropertyType);
			varLeft.store(ctx);

			Label continueLabel = new Label();
			Label nonNulls = new Label();
			Label leftNonNull = new Label();

			varLeft.load(ctx);
			g.ifNonNull(leftNonNull);

			varRight.load(ctx);
			g.ifNull(continueLabel);
			g.push(-1);
			g.returnValue();

			g.mark(leftNonNull);

			varRight.load(ctx);
			g.ifNonNull(nonNulls);
			g.push(1);
			g.returnValue();

			g.mark(nonNulls);

			varLeft.load(ctx);
			varRight.load(ctx);

			g.invokeVirtual(leftPropertyType, new Method("compareTo", INT_TYPE, new Type[]{Type.getType(Object.class)}));
			g.dup();
			g.ifZCmp(NE, labelReturn);
			g.pop();

			g.mark(continueLabel);
		}
	}

	g.push(0);

	g.mark(labelReturn);

	return INT_TYPE;
}
 
Example 13
Source File: ExpressionToString.java    From datakernel with Apache License 2.0 4 votes vote down vote up
@Override
public Type load(Context ctx) {
	GeneratorAdapter g = ctx.getGeneratorAdapter();

	g.newInstance(getType(StringBuilder.class));
	g.dup();
	g.invokeConstructor(getType(StringBuilder.class), getMethod("void <init> ()"));

	boolean first = true;

	for (Object key : arguments.keySet()) {
		String str = first ? begin : separator;
		first = false;
		if (key instanceof String) {
			str += key;
		}
		if (!str.isEmpty()) {
			g.dup();
			g.push(str);
			g.invokeVirtual(getType(StringBuilder.class), getMethod("StringBuilder append(String)"));
			g.pop();
		}

		g.dup();
		Expression expression = arguments.get(key);
		Type type = expression.load(ctx);
		if (isPrimitiveType(type)) {
			g.invokeStatic(wrap(type), new Method("toString", getType(String.class), new Type[]{type}));
		} else {
			Label nullLabel = new Label();
			Label afterToString = new Label();
			g.dup();
			g.ifNull(nullLabel);
			g.invokeVirtual(type, getMethod("String toString()"));
			g.goTo(afterToString);
			g.mark(nullLabel);
			g.pop();
			g.push("null");
			g.mark(afterToString);
		}
		g.invokeVirtual(getType(StringBuilder.class), getMethod("StringBuilder append(String)"));
		g.pop();
	}

	if (!end.isEmpty()) {
		g.dup();
		g.push(end);
		g.invokeVirtual(getType(StringBuilder.class), getMethod("StringBuilder append(String)"));
		g.pop();
	}

	g.invokeVirtual(getType(StringBuilder.class), getMethod("String toString()"));
	return getType(String.class);
}
 
Example 14
Source File: MethodRedirection.java    From AnoleFix with MIT License 3 votes vote down vote up
/**
 * For methods, restore creates a return from the dispatch call, to exit the method
 * once the new implementation has been executed. for void methods, this is an empty return
 * and for all other methods, it returns the value from the dispatch call.
 * <p/>
 * Note that the generated bytecode does not have a direct translation to code, but as an
 * example, this restore implementation in combination with the base class generates the
 * following for methods with avoid return type:
 * <code>
 * if ($change != null) {
 * $change.access$dispatch($name, new object[] { arg0, ... argsN })
 * return;
 * }
 * $originalMethodBody
 * </code>
 * and the following for methods with a non-void return type:
 * <code>
 * if ($change != null) {
 * return $change.access$dispatch($name, new object[] { arg0, ... argsN })
 * }
 * $originalMethodBody
 * </code>
 */
@Override
protected void restore(GeneratorAdapter mv, List<Type> args) {
    if (type == Type.VOID_TYPE) {
        mv.pop();
    } else {
        ByteCodeUtils.unbox(mv, type);
    }
    mv.returnValue();
}