java.net.bytebuddy.implementation.bytecode.Duplication Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of securemock Show documentation
Show all versions of securemock Show documentation
Libraries for Elasticsearch
The newest version!
/*
* Copyright 2014 - 2018 Rafael Winterhalter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bytebuddy.implementation.bytecode;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.implementation.Implementation;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* Duplicates a value that is lying on top of the stack.
*/
public enum Duplication implements StackManipulation {
/**
* A duplication of no values. This corresponds a no-op instruction.
*/
ZERO(StackSize.ZERO, Opcodes.NOP) {
@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
return size;
}
@Override
public StackManipulation flipOver(TypeDefinition typeDefinition) {
throw new IllegalStateException("Cannot flip zero value");
}
},
/**
* A duplication of a single-sized stack values.
*/
SINGLE(StackSize.SINGLE, Opcodes.DUP) {
@Override
public StackManipulation flipOver(TypeDefinition typeDefinition) {
switch (typeDefinition.getStackSize()) {
case SINGLE:
return WithFlip.SINGLE_SINGLE;
case DOUBLE:
return WithFlip.SINGLE_DOUBLE;
default:
throw new IllegalArgumentException("Cannot flip: " + typeDefinition);
}
}
},
/**
* A duplication of a double-sized stack value.
*/
DOUBLE(StackSize.DOUBLE, Opcodes.DUP2) {
@Override
public StackManipulation flipOver(TypeDefinition typeDefinition) {
switch (typeDefinition.getStackSize()) {
case SINGLE:
return WithFlip.DOUBLE_SINGLE;
case DOUBLE:
return WithFlip.DOUBLE_DOUBLE;
default:
throw new IllegalArgumentException("Cannot flip: " + typeDefinition);
}
}
};
/**
* The size representing the impact of applying the duplication onto the operand stack.
*/
protected final Size size;
/**
* The opcode that represents the manipulation.
*/
private final int opcode;
/**
* Creates a new duplication.
*
* @param stackSize The size representing the impact of applying the duplication onto the operand stack.
* @param opcode The opcode that represents the manipulation.
*/
Duplication(StackSize stackSize, int opcode) {
size = stackSize.toIncreasingSize();
this.opcode = opcode;
}
/**
* Duplicates a value given its type.
*
* @param typeDefinition The type to be duplicated.
* @return A stack manipulation that duplicates the given type.
*/
public static Duplication of(TypeDefinition typeDefinition) {
switch (typeDefinition.getStackSize()) {
case SINGLE:
return SINGLE;
case DOUBLE:
return DOUBLE;
case ZERO:
return ZERO;
default:
throw new AssertionError("Unexpected type: " + typeDefinition);
}
}
/**
* Creates a duplication that flips the stack's top value over the second stack element.
*
* @param typeDefinition The type of the second element on the operand stack.
* @return A stack manipulation that represents such a duplication flip.
*/
public abstract StackManipulation flipOver(TypeDefinition typeDefinition);
/**
* {@inheritDoc}
*/
public boolean isValid() {
return true;
}
/**
* {@inheritDoc}
*/
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
methodVisitor.visitInsn(opcode);
return size;
}
/**
* A duplication that flips a value over the second value on the operand stack.
*/
protected enum WithFlip implements StackManipulation {
/**
* A flip instruction that flips a single-sized element over another single-size element.
*/
SINGLE_SINGLE(Opcodes.DUP_X1, StackSize.SINGLE),
/**
* A flip instruction that flips a double-sized element over a single-size element.
*/
SINGLE_DOUBLE(Opcodes.DUP_X2, StackSize.SINGLE),
/**
* A flip instruction that flips a single-sized element over a double-size element.
*/
DOUBLE_SINGLE(Opcodes.DUP2_X1, StackSize.DOUBLE),
/**
* A flip instruction that flips a double-sized element over another double-size element.
*/
DOUBLE_DOUBLE(Opcodes.DUP2_X2, StackSize.DOUBLE);
/**
* The opcode to apply.
*/
private final int opcode;
/**
* The size that is added to the operand stack.
*/
private final StackSize stackSize;
/**
* Creates a flip duplication.
*
* @param opcode The opcode to apply.
* @param stackSize The size that is added to the operand stack.
*/
WithFlip(int opcode, StackSize stackSize) {
this.opcode = opcode;
this.stackSize = stackSize;
}
/**
* {@inheritDoc}
*/
public boolean isValid() {
return true;
}
/**
* {@inheritDoc}
*/
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
methodVisitor.visitInsn(opcode);
return stackSize.toIncreasingSize();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy