use of org.objectweb.asm.Opcodes.RETURN in project LanternServer by LanternPowered.
the class FieldAccessFactory method createSetter.
/**
* Creates a setter {@link BiConsumer} for the given {@link Field}.
*
* @param field The field
* @param <T> The target object type
* @param <V> The field value type
* @return The bi consumer
*/
public static <T, V> BiConsumer<T, V> createSetter(Field field) {
checkNotNull(field, "field");
field.setAccessible(true);
boolean isFinal = Modifier.isFinal(field.getModifiers());
// Better check is somebody changed the final modifier already
if (!isFinal) {
final Field[] fields = field.getDeclaringClass().getDeclaredFields();
boolean isFound = false;
for (Field field1 : fields) {
// The same signature, now check if somebody tinkered with the field
if (field.getName().equals(field1.getName()) && field.getType().equals(field1.getType())) {
isFinal = Modifier.isFinal(field1.getModifiers());
isFound = true;
break;
}
}
if (!isFound) {
throw new IllegalStateException("Something funky happened with: " + field.getName());
}
} else {
try {
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
// Final fields don't allow direct access, so MethodHandles will do the trick.
if (isFinal) {
try {
final MethodHandle methodHandle = MethodHandleMagic.trustedLookup().in(field.getDeclaringClass()).unreflectSetter(field).asType(setterMethodType);
return (a, b) -> {
try {
methodHandle.invokeExact(a, b);
} catch (Throwable throwable) {
throw new IllegalStateException(throwable);
}
};
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
final ClassWriter cw = new ClassWriter(0);
final String className = field.getName().replace('.', '/') + "$$LanternSetter$" + setterCounter.incrementAndGet();
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, "Ljava/lang/Object;Ljava/util/function/BiConsumer<Ljava/lang/Object;Ljava/lang/Object;>;", "java/lang/Object", new String[] { "java/util/function/BiConsumer" });
// Add a empty constructor
BytecodeUtils.visitEmptyConstructor(cw);
// Generate the apply method
final MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null);
mv.visitCode();
final String descriptor = Type.getDescriptor(field.getType());
final String targetName = Type.getInternalName(field.getDeclaringClass());
final boolean isStatic = Modifier.isStatic(field.getModifiers());
if (!isStatic) {
// Load the target parameter
mv.visitVarInsn(ALOAD, 1);
// Cast it
mv.visitTypeInsn(CHECKCAST, targetName);
}
// Load the value parameter
mv.visitVarInsn(ALOAD, 2);
// Unbox the values in case they are primitives, otherwise cast
GeneratorUtils.visitUnboxingMethod(mv, Type.getType(field.getType()));
// Put the value into the field
if (isStatic) {
mv.visitFieldInsn(PUTSTATIC, targetName, field.getName(), descriptor);
} else {
mv.visitFieldInsn(PUTFIELD, targetName, field.getName(), descriptor);
}
// Return
mv.visitInsn(RETURN);
mv.visitMaxs(2, 3);
mv.visitEnd();
// Finish class generation
cw.visitEnd();
// Define the class and create a function instance
final MethodHandles.Lookup lookup = MethodHandleMagic.trustedLookup().in(field.getDeclaringClass());
final Class<?> functionClass = MethodHandleMagic.defineNestmateClass(lookup, cw.toByteArray());
try {
return (BiConsumer<T, V>) functionClass.newInstance();
} catch (Exception e) {
throw new IllegalStateException("Something went wrong!", e);
}
}
use of org.objectweb.asm.Opcodes.RETURN in project sonar-java by SonarSource.
the class BytecodeEGWalker method branchingState.
@VisibleForTesting
ProgramState branchingState(Instruction terminator, ProgramState programState) {
ProgramState.Pop pop;
ProgramState ps;
List<ProgramState.SymbolicValueSymbol> symbolicValueSymbols;
switch(terminator.opcode) {
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
pop = programState.unstackValue(1);
SymbolicValue svZero = new SymbolicValue();
symbolicValueSymbols = ImmutableList.of(new ProgramState.SymbolicValueSymbol(svZero, null), pop.valuesAndSymbols.get(0));
List<ProgramState> programStates = svZero.setConstraint(pop.state, DivisionByZeroCheck.ZeroConstraint.ZERO).stream().flatMap(s -> svZero.setConstraint(s, BooleanConstraint.FALSE).stream()).collect(Collectors.toList());
Preconditions.checkState(programStates.size() == 1);
ps = programStates.get(0);
break;
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
pop = programState.unstackValue(2);
symbolicValueSymbols = pop.valuesAndSymbols;
ps = pop.state;
break;
case IFNULL:
case IFNONNULL:
pop = programState.unstackValue(1);
symbolicValueSymbols = ImmutableList.of(new ProgramState.SymbolicValueSymbol(SymbolicValue.NULL_LITERAL, null), pop.valuesAndSymbols.get(0));
ps = pop.state;
break;
default:
throw new IllegalStateException("Unexpected terminator " + terminator);
}
return ps.stackValue(constraintManager.createBinarySymbolicValue(terminator, symbolicValueSymbols));
}
use of org.objectweb.asm.Opcodes.RETURN in project sonar-java by SonarSource.
the class BytecodeEGWalker method handleMethodInvocation.
private boolean handleMethodInvocation(Instruction instruction) {
boolean isStatic = instruction.opcode == Opcodes.INVOKESTATIC;
int arity = isStatic ? instruction.arity() : (instruction.arity() + 1);
ProgramState.Pop pop = programState.unstackValue(arity);
Preconditions.checkState(pop.values.size() == arity, "Arguments mismatch for INVOKE");
// TODO use constraintManager.createMethodSymbolicValue to create relational SV for equals
programState = pop.state;
SymbolicValue returnSV = instruction.hasReturnValue() ? constraintManager.createSymbolicValue(instruction) : null;
String signature = instruction.fieldOrMethod.completeSignature();
MethodBehavior methodInvokedBehavior = behaviorCache.get(signature);
enqueueUncheckedExceptions();
// FIXME : empty yields here should not happen, for now act as if behavior was not resolved.
if (methodInvokedBehavior != null && methodInvokedBehavior.isComplete() && !methodInvokedBehavior.yields().isEmpty()) {
List<SymbolicValue> stack = Lists.reverse(pop.values);
if (!isStatic) {
// remove "thisSV" from stack before trying to apply any yield, as it should not match with arguments
stack = stack.subList(1, stack.size());
}
List<SymbolicValue> arguments = stack;
methodInvokedBehavior.happyPathYields().forEach(yield -> yield.statesAfterInvocation(arguments, Collections.emptyList(), programState, () -> returnSV).forEach(ps -> {
checkerDispatcher.methodYield = yield;
if (ps.peekValue() != null) {
ps = setDoubleOrLong(ps, ps.peekValue(), instruction.isLongOrDoubleValue());
}
checkerDispatcher.addTransition(ps);
checkerDispatcher.methodYield = null;
}));
methodInvokedBehavior.exceptionalPathYields().forEach(yield -> {
Type exceptionType = yield.exceptionType(semanticModel);
yield.statesAfterInvocation(arguments, Collections.emptyList(), programState, () -> constraintManager.createExceptionalSymbolicValue(exceptionType)).forEach(ps -> {
ps.storeExitValue();
enqueueExceptionHandlers(exceptionType, ps);
});
});
return true;
}
if (methodInvokedBehavior != null) {
methodInvokedBehavior.getDeclaredExceptions().forEach(exception -> {
Type exceptionType = semanticModel.getClassType(exception);
ProgramState ps = programState.stackValue(constraintManager.createExceptionalSymbolicValue(exceptionType));
enqueueExceptionHandlers(exceptionType, ps);
});
}
if (instruction.hasReturnValue()) {
programState = programState.stackValue(returnSV);
programState = setDoubleOrLong(returnSV, instruction.isLongOrDoubleValue());
}
return false;
}
use of org.objectweb.asm.Opcodes.RETURN in project sonar-java by SonarSource.
the class BytecodeEGWalker method enqueueExceptionHandlers.
private void enqueueExceptionHandlers(Type exceptionType, ProgramState ps) {
List<BytecodeCFG.Block> blocksCatchingException = programPosition.block.successors().stream().map(b -> (BytecodeCFG.Block) b).filter(BytecodeCFG.Block::isCatchBlock).filter(b -> isExceptionHandledByBlock(exceptionType, b)).collect(Collectors.toList());
if (!blocksCatchingException.isEmpty()) {
blocksCatchingException.forEach(b -> enqueue(new ProgramPoint(b), ps));
if (isCatchExhaustive(exceptionType, blocksCatchingException)) {
return;
}
}
// exception was not handled or was handled only partially, enqueue exit block with exceptional SV
Preconditions.checkState(ps.peekValue() instanceof SymbolicValue.ExceptionalSymbolicValue, "Exception shall be on top of the stack");
ps.storeExitValue();
enqueue(new ProgramPoint(exitBlock), ps);
}
use of org.objectweb.asm.Opcodes.RETURN in project groovy by apache.
the class AsmClassGenerator method visitStdMethod.
private void visitStdMethod(final MethodNode node, final boolean isConstructor, final Parameter[] parameters, final Statement code) {
controller.getCompileStack().init(node.getVariableScope(), parameters);
controller.getCallSiteWriter().makeSiteEntry();
MethodVisitor mv = controller.getMethodVisitor();
if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall())) {
boolean hasCallToSuper = false;
if (code != null && controller.getClassNode().getOuterClass() != null) {
// the call to super is already added so we must ensure not to add it twice
if (code instanceof BlockStatement) {
hasCallToSuper = ((BlockStatement) code).getStatements().stream().map(statement -> statement instanceof ExpressionStatement ? ((ExpressionStatement) statement).getExpression() : null).anyMatch(expression -> expression instanceof ConstructorCallExpression && ((ConstructorCallExpression) expression).isSuperCall());
}
}
if (!hasCallToSuper) {
if (code != null) {
// GROOVY-9373
controller.visitLineNumber(code.getLineNumber());
}
// add call to "super()"
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, controller.getInternalBaseClassName(), "<init>", "()V", false);
}
}
if (code != null) {
code.visit(this);
}
if (code == null || maybeFallsThrough(code)) {
if (code != null) {
// GROOVY-7647, GROOVY-9373
controller.visitLineNumber(code.getLastLineNumber());
}
if (node.isVoidMethod()) {
mv.visitInsn(RETURN);
} else {
ClassNode type = node.getReturnType();
if (isPrimitiveType(type)) {
mv.visitLdcInsn(Integer.valueOf(0));
OperandStack operandStack = controller.getOperandStack();
operandStack.push(ClassHelper.int_TYPE);
operandStack.doGroovyCast(type);
BytecodeHelper.doReturn(mv, type);
operandStack.remove(1);
} else {
mv.visitInsn(ACONST_NULL);
BytecodeHelper.doReturn(mv, type);
}
}
}
controller.getCompileStack().clear();
}
Aggregations