Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/mirkosertic/Bytecoder
Browse files Browse the repository at this point in the history
  • Loading branch information
mirkosertic committed Jun 15, 2023
2 parents 4e982db + 99e37aa commit 64b8f88
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@ public class TEnum implements Comparable<Enum> {

private final String name;
private final int ordinalNumber;
public final Class getDeclaringClass() throws ClassNotFoundException {
Class clazzObj = getClass();
String clazzname = clazzObj.getName();

if(clazzname.matches(".+\\$\\d+")){
//its a subclassed Enum
// enum E { VAL {private int i;} }
// E.VAL.getClass() == E$1
return Class.forName(clazzname.substring(0,clazzname.lastIndexOf('$')));
}
return clazzObj;
}
@NoExceptionCheck
protected TEnum(final String aName, final int aOrdinalNumber) {
name = aName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public String toString() {
return (String) (Object) this;
}

public native boolean matches(String regex);

static String valueOf(final Object obj) {
if (obj == null) {
return "null";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,20 @@ public static boolean equals(final byte[] a, final byte[] b) {
}
return true;
}
public static boolean equals(final short[] a, final short[] b) {
if (a == b) {
return true;
}
if (a.length != b.length) {
return false;
}
for (int i=0;i<a.length;i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

public static boolean equals(final long[] a, final long[] b) {
if (a == b) {
Expand Down Expand Up @@ -236,6 +250,20 @@ public static boolean equals(final float[] a, final float[] b) {
}
return true;
}
public static boolean equals(final double[] a, final double[] b) {
if (a == b) {
return true;
}
if (a.length != b.length) {
return false;
}
for (int i=0;i<a.length;i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

public static boolean equals(final int[] a, final int[] b) {
if (a == b) {
Expand All @@ -252,6 +280,36 @@ public static boolean equals(final int[] a, final int[] b) {
return true;
}

public static boolean equals(final boolean[] a, final boolean[] b) {
if (a == b) {
return true;
}
if (a.length != b.length) {
return false;
}
for (int i=0;i<a.length;i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

public static boolean equals(final char[] a, final char[] b) {
if (a == b) {
return true;
}
if (a.length != b.length) {
return false;
}
for (int i=0;i<a.length;i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

public static boolean equals(final Object[] a, final Object[] b) {
if (a == b) {
return true;
Expand Down
4 changes: 2 additions & 2 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>4.9.1</version>
<version>4.10.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.12.0</version>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private void generateHeader(final CompileUnit compileUnit, final PrintWriter pw)
}
}

pw.println(" throw 'Not supported class for reflective access';");
pw.println(" throw new Error('Not supported class for reflective access');");
pw.println("};");
pw.println();
}
Expand Down Expand Up @@ -246,9 +246,10 @@ private void generateClassInitFor(final PrintWriter pw, final CompileUnit compil
pw.println(" static #rt = undefined;");
pw.println(" static get $rt() {");
pw.println(" if (!this.#rt) {");
pw.print(" this.#rt = bytecoder.newRuntimeClassFor(");
pw.print(generateClassName(cl.type));
pw.print(",[");
pw.println(" this.#rt = bytecoder.newRuntimeClassFor(");
pw.println(" "+generateClassName(cl.type)+",");
pw.println(" '"+cl.type.getClassName()+"',");
pw.print(" [");
boolean f = true;
for (final ResolvedClass type : cl.allTypesOf()) {
if (f) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,11 +682,11 @@ private void generateInvokeDynamicLambdaMetaFactoryInvocation(final InvokeDynami
}
}
}
if (source.getSort() == Type.OBJECT && target.getSort() != Type.OBJECT) {
if (source.getSort() == Type.OBJECT && target.getSort() != Type.OBJECT && target.getSort() != Type.VOID) {
// Object to primitive
switch (source.getSort()) {
default: {
throw new IllegalStateException("No converter from " + source + " to " + target + " implemented!");
throw new IllegalStateException("No converter from " + source + " to " + target + " implemented! (" + argMethodName +")");
}
}
}
Expand Down Expand Up @@ -1988,7 +1988,7 @@ public void finishIfBlock() {
@Override
public void startBlock(final Sequencer.Block block) {
writeIndent();
pw.print(block.label);
pw.print(block.label.replace("-",""));
pw.print(": ");
if (block.type == Sequencer.Block.Type.LOOP) {
pw.print("while(true) ");
Expand Down Expand Up @@ -2066,15 +2066,15 @@ public void write(final ReturnValue node) {
public void writeBreakTo(final String label) {
writeIndent();
pw.print("break ");
pw.print(label);
pw.print(label.replace("-",""));
pw.println(";");
}

@Override
public void writeContinueTo(final String label) {
writeIndent();
pw.print("continue ");
pw.print(label);
pw.print(label.replace("-",""));
pw.println(";");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;

import java.io.*;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -109,11 +110,21 @@ public void registerDirectSubclass(final ResolvedClass cl) {
public ResolvedMethod resolveMethod(final String methodName, final Type methodType, final AnalysisStack analysisStack) {
final ResolvedMethod m = resolveMethodInternal(methodName, methodType, analysisStack, false);
if (m == null) {
throw new IllegalStateException("No such method : " + classNode.name + "." + methodName + methodType);
throw new AnalysisException(
new IllegalStateException("No such method : " + classNode.name + "." + methodName + methodType),
analysisStack
);
}
return m;
}

private String printStackTrace(AnalysisStack analysisStack) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream stringStream = new PrintStream(bos);
analysisStack.dumpAnalysisStack(stringStream);
return "\n" + bos;
}

private ResolvedMethod resolveMethodInternal(final String methodName, final Type methodType, final AnalysisStack analysisStack, final boolean onlyImplementations) {
for (final ResolvedMethod m : resolvedMethods) {
final MethodNode methodNode = m.methodNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ResolvedMethod(final ResolvedClass owner, final MethodNode methodNode, fi
public void parseBody(final AnalysisStack analysisStack) {
if (!Modifier.isAbstract(methodNode.access) && !Modifier.isNative(methodNode.access)) {
// Method is not abstract and not native
final AnalysisStack newStack = analysisStack.addAction(new AnalysisStack.Action("Parsing method body of " + owner.type + "." + methodNode.name));
final AnalysisStack newStack = analysisStack.addAction(new AnalysisStack.Action("Parsing method body of " + owner.type.getClassName() + "." + methodNode.name));
try {
final GraphParser graphParser = new GraphParser(owner.compileUnit, owner.type, methodNode, newStack);
methodBody = graphParser.graph();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ public ResolvedClass resolveClass(final Type type, final AnalysisStack analysisS
throw new RuntimeException(e);
}
resolvedClasses.put(resourceName, rs);

boolean isEnumType = rs.allTypesOf().stream().anyMatch(parent -> parent.type.getClassName().equals(Enum.class.getName())) || rs.type.getClassName().equals(Enum.class.getName());
if(isEnumType){
//Why aren't all classes considered for lookups? Performance? It would simplify implementation a lot if Class.forName just looped over classes.#rt and checked that
getReflectionConfiguration().resolve(rs.type.getClassName()).setSupportsClassForName(true);
getConstantPool().resolveFromPool(rs.type.getClassName());//add of not already there
}
// If there are any methods annotated with Export, we resolve them, too
for (final MethodNode mn : rs.classNode.methods) {
if (AnnotationUtils.hasAnnotation("Lde/mirkosertic/bytecoder/api/Export;", mn.visibleAnnotations)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@
*/
package de.mirkosertic.bytecoder.core.parser;

import de.mirkosertic.bytecoder.core.ir.AnalysisStack;
import de.mirkosertic.bytecoder.core.ir.ControlTokenConsumer;
import de.mirkosertic.bytecoder.core.ir.Graph;
import de.mirkosertic.bytecoder.core.ir.InvocationType;
import de.mirkosertic.bytecoder.core.ir.ResolvedClass;
import de.mirkosertic.bytecoder.core.ir.ResolvedMethod;
import de.mirkosertic.bytecoder.core.ir.Value;
import de.mirkosertic.bytecoder.core.ir.*;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.MethodInsnNode;
Expand All @@ -35,54 +29,63 @@ public ControlTokenConsumer intrinsifyMethodInvocation(final CompileUnit compile
if (System.class.getName().equals(targetClass.getClassName())) {
if ("arraycopy".equals(node.name)) {
final Value source = incomingData[1];
final Type methodType;
final ResolvedClass systemClass = compileUnit.resolveClass(Type.getType(System.class), analysisStack);

if (source.type.getSort() != Type.ARRAY) {
throw new IllegalArgumentException("Expected array type for arrayCopy, got " + source.type);
}

final ResolvedClass systemClass = compileUnit.resolveClass(Type.getType(System.class), analysisStack);

final Type methodType;
switch (source.type.getElementType().getSort()) {
case Type.CHAR: {
methodType = Type.getMethodType("([CI[CII)V");
break;
}
case Type.BYTE: {
methodType = Type.getMethodType("([BI[BII)V");
break;
}
case Type.DOUBLE: {
methodType = Type.getMethodType("([DI[DII)V");
break;
}
case Type.FLOAT: {
methodType = Type.getMethodType("([FI[FII)V");
break;
}
case Type.INT: {
methodType = Type.getMethodType("([II[III)V");
break;
}
case Type.LONG: {
methodType = Type.getMethodType("([JI[JII)V");
break;
}
case Type.SHORT: {
methodType = Type.getMethodType("([SI[SII)V");
break;
}
case Type.BOOLEAN: {
methodType = Type.getMethodType("([ZI[ZII)V");
break;
}
default: {
// (Ljava/lang/Object;ILjava/lang/Object;II)V
methodType = Type.getMethodType(node.desc);
break;
if (source.type.getClassName().contentEquals(Object.class.getName())) {
// (Ljava/lang/Object;ILjava/lang/Object;II)V
methodType = Type.getMethodType(node.desc);
} else if (source.type.getSort() == Type.ARRAY) {
switch (source.type.getElementType().getSort()) {
case Type.CHAR: {
methodType = Type.getMethodType("([CI[CII)V");
break;
}
case Type.BYTE: {
methodType = Type.getMethodType("([BI[BII)V");
break;
}
case Type.DOUBLE: {
methodType = Type.getMethodType("([DI[DII)V");
break;
}
case Type.FLOAT: {
methodType = Type.getMethodType("([FI[FII)V");
break;
}
case Type.INT: {
methodType = Type.getMethodType("([II[III)V");
break;
}
case Type.LONG: {
methodType = Type.getMethodType("([JI[JII)V");
break;
}
case Type.SHORT: {
methodType = Type.getMethodType("([SI[SII)V");
break;
}
case Type.BOOLEAN: {
methodType = Type.getMethodType("([ZI[ZII)V");
break;
}
case Type.OBJECT: {
// (Ljava/lang/Object;ILjava/lang/Object;II)V
methodType = Type.getMethodType(node.desc);
break;
}
default: {
throw new IllegalArgumentException(source.type.getElementType().getSort()+" is not a valid type for an array in System.arraycopy() !");
}
}
} else {
throw new IllegalArgumentException("Expected array type or "+Object.class.getName()+" for arrayCopy, got " + source.type);
}



final ResolvedMethod rm = systemClass.resolveMethod(node.name,
methodType, analysisStack);
final ControlTokenConsumer n = graph.newMethodInvocation(InvocationType.STATIC, node, rm);
Expand Down
Loading

0 comments on commit 64b8f88

Please sign in to comment.