Skip to content

Commit

Permalink
applying recommandation from sirthias#104
Browse files Browse the repository at this point in the history
  • Loading branch information
sleroy committed Feb 2, 2021
1 parent 6df9100 commit 09872de
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 108 deletions.
2 changes: 1 addition & 1 deletion examples-java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<parent>
<groupId>com.byoskill.parboiled</groupId>
<version>1.3.3</version>
<version>1.3.4-SNAPSHOT</version>
<artifactId>parboiled-parent</artifactId>
</parent>
<licenses>
Expand Down
2 changes: 1 addition & 1 deletion examples-scala/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<parent>
<groupId>com.byoskill.parboiled</groupId>
<version>1.3.3</version>
<version>1.3.4-SNAPSHOT</version>
<artifactId>parboiled-parent</artifactId>
</parent>
<licenses>
Expand Down
2 changes: 1 addition & 1 deletion parboiled-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<packaging>jar</packaging>
<parent>
<groupId>com.byoskill.parboiled</groupId>
<version>1.3.3</version>
<version>1.3.4-SNAPSHOT</version>
<artifactId>parboiled-parent</artifactId>
</parent>
<licenses>
Expand Down
7 changes: 6 additions & 1 deletion parboiled-java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<packaging>jar</packaging>
<parent>
<groupId>com.byoskill.parboiled</groupId>
<version>1.3.3</version>
<version>1.3.4-SNAPSHOT</version>
<artifactId>parboiled-parent</artifactId>
</parent>
<licenses>
Expand All @@ -23,6 +23,11 @@
<artifactId>parboiled-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.19</version>
</dependency>

<dependency>
<groupId>org.ow2.asm</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
public class ASMSettings {
public static final int ASM_API = Opcodes.ASM8;
@Deprecated
public static final int JDK_VERSION = Opcodes.V1_8;
public static final int FRAMES = ClassWriter.COMPUTE_FRAMES;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,26 @@
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

import java.util.function.BiConsumer;
import java.util.function.IntSupplier;
import java.util.function.Supplier;

import static org.objectweb.asm.Opcodes.*;

class ActionClassGenerator extends GroupClassGenerator {

@Deprecated
public ActionClassGenerator(boolean forceCodeBuilding) {
super(forceCodeBuilding);
}


public ActionClassGenerator(boolean forceCodeBuilding, BiConsumer<String, Supplier<byte[]>> classInjector, IntSupplier classFileVersion) {
super(forceCodeBuilding, classInjector, classFileVersion);
}


public boolean appliesTo(ParserClassNode classNode, RuleMethod method) {
checkArgNotNull(method, "method");
return method.containsExplicitActions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public static Constructor getClassConstructor(String classInternalName, String c
* @param classLoader the class loader to use
* @return the class instance or null
*/
@Deprecated
public static Class<?> findLoadedClass(String className, ClassLoader classLoader) {
checkArgNotNull(className, "className");
checkArgNotNull(classLoader, "classLoader");
Expand Down Expand Up @@ -232,6 +233,7 @@ public static Class<?> findLoadedClass(String className, ClassLoader classLoader
* @param classLoader the class loader to use
* @return the class instance
*/
@Deprecated
public static Class<?> loadClass(String className, byte[] code, ClassLoader classLoader) {
checkArgNotNull(className, "className");
checkArgNotNull(code, "code");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,39 @@

package org.parboiled.transform;

import static org.parboiled.common.Preconditions.*;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.MethodNode;
import org.parboiled.support.Checks;

import java.io.IOException;
import java.util.function.IntSupplier;

import static org.objectweb.asm.Opcodes.*;
import static org.parboiled.common.Preconditions.checkArgNotNull;
import static org.parboiled.transform.AsmUtils.createClassReader;
import static org.parboiled.transform.AsmUtils.getExtendedParserClassName;
import static org.objectweb.asm.Opcodes.*;

/**
* Initializes the basic ParserClassNode fields and collects all methods.
*/
class ClassNodeInitializer extends ClassVisitor {

private ParserClassNode classNode;
private Class<?> ownerClass;
private boolean hasBuildParseTree;
private boolean hasExplicitActionOnlyAnnotation;
private boolean hasDontLabelAnnotation;
private boolean hasSkipActionsInPredicates;
private Class<?> ownerClass;
private boolean hasBuildParseTree;
private boolean hasExplicitActionOnlyAnnotation;
private boolean hasDontLabelAnnotation;
private boolean hasSkipActionsInPredicates;
private IntSupplier classFileVersion = () -> ASMSettings.JDK_VERSION;

public ClassNodeInitializer(IntSupplier classFileVersion) {
this();
if (classFileVersion != null) {
this.classFileVersion = classFileVersion;
}
}

@Deprecated
public ClassNodeInitializer() {
super(ASMSettings.ASM_API);
}
Expand Down Expand Up @@ -87,7 +97,7 @@ public void visit(int version, int access, String name, String signature, String
Checks.ensure((access & ACC_PRIVATE) == 0, "Parser class '%s' must not be private", name);
Checks.ensure((access & ACC_FINAL) == 0, "Parser class '%s' must not be final.", name);
classNode.visit(
ASMSettings.JDK_VERSION,
classFileVersion.getAsInt(),
ACC_PUBLIC,
getExtendedParserClassName(name),
null,
Expand All @@ -97,6 +107,11 @@ public void visit(int version, int access, String name, String signature, String
}
}

@Override
public void visitSource(String source, String debug) {
classNode.visitSource(null, null);
}

@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (Types.EXPLICIT_ACTIONS_ONLY_DESC.equals(desc)) {
Expand All @@ -120,11 +135,6 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return visible && ownerClass == classNode.getParentClass() ? classNode.visitAnnotation(desc, true) : null;
}

@Override
public void visitSource(String source, String debug) {
classNode.visitSource(null, null);
}

@Override
@SuppressWarnings("unchecked")
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
Expand Down Expand Up @@ -157,7 +167,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
}

RuleMethod method = new RuleMethod(ownerClass, access, name, desc, signature, exceptions,
hasExplicitActionOnlyAnnotation, hasDontLabelAnnotation, hasSkipActionsInPredicates);
hasExplicitActionOnlyAnnotation, hasDontLabelAnnotation, hasSkipActionsInPredicates);
classNode.getRuleMethods().put(methodKey, method);
return method; // return the newly created method in order to have it "filled" with the actual method code
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,61 @@

package org.parboiled.transform;

import static org.parboiled.common.Preconditions.*;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.parboiled.common.ParboiledException;

import java.util.function.BiConsumer;
import java.util.function.IntSupplier;
import java.util.function.Supplier;

import static org.objectweb.asm.Opcodes.*;
import static org.parboiled.common.Preconditions.checkArgNotNull;
import static org.parboiled.transform.AsmUtils.findLoadedClass;
import static org.parboiled.transform.AsmUtils.loadClass;

abstract class GroupClassGenerator implements RuleMethodProcessor {

private static final Object lock = new Object();

private final boolean forceCodeBuilding;
protected ParserClassNode classNode;
protected RuleMethod method;

protected ParserClassNode classNode;
protected RuleMethod method;
private BiConsumer<String, Supplier<byte[]>> classInjector;
private IntSupplier classFileVersion;

protected GroupClassGenerator(boolean forceCodeBuilding, BiConsumer<String, Supplier<byte[]>> classInjector,
IntSupplier classFileVersion) {
this(forceCodeBuilding);
if (classInjector != null) {
this.classInjector = classInjector;
}
if (classFileVersion != null) {
this.classFileVersion = classFileVersion;
}
}

@Deprecated
protected GroupClassGenerator(boolean forceCodeBuilding) {

this.forceCodeBuilding = forceCodeBuilding;
Object lock = new Object();
this.classInjector = (className, groupClassCodeGenerator) -> {
ClassLoader classLoader = classNode.getParentClass().getClassLoader();
Class<?> groupClass;
synchronized (lock) {
groupClass = findLoadedClass(className, classLoader);
if (groupClass == null) {
byte[] groupClassCode = groupClassCodeGenerator.get();

if (groupClass == null) {
loadClass(className, groupClassCode, classLoader);
}
}
}
};
this.classFileVersion = () -> ASMSettings.JDK_VERSION;
}

public void process(ParserClassNode classNode, RuleMethod method) {
Expand All @@ -55,25 +89,27 @@ public void process(ParserClassNode classNode, RuleMethod method) {
private void loadGroupClass(InstructionGroup group) {
createGroupClassType(group);
String className = group.getGroupClassType().getClassName();
ClassLoader classLoader = classNode.getParentClass().getClassLoader();
Supplier<byte[]> groupClassCodeGenerator = () -> {
byte[] groupClassCode = group.getGroupClassCode();
if (groupClassCode == null) {
groupClassCode = generateGroupClassCode(group);

Class<?> groupClass;
synchronized (lock) {
groupClass = findLoadedClass(className, classLoader);
if (groupClass == null || forceCodeBuilding) {
byte[] groupClassCode = generateGroupClassCode(group);
if (groupClassCode == null) throw new ParboiledException("No code has been generated for " + group);
group.setGroupClassCode(groupClassCode);
if (groupClass == null) {
loadClass(className, groupClassCode, classLoader);
}
}
return groupClassCode;
};
classInjector.accept(className, groupClassCodeGenerator);
if (forceCodeBuilding) {
groupClassCodeGenerator.get();
}
}


private void createGroupClassType(InstructionGroup group) {
String s = classNode.name;
int lastSlash = classNode.name.lastIndexOf('/');
String groupClassInternalName = (lastSlash >= 0 ? s.substring(0, lastSlash) : s)+ '/' + group.getName();
String s = classNode.name;
int lastSlash = classNode.name.lastIndexOf('/');
String groupClassInternalName = (lastSlash >= 0 ? s.substring(0, lastSlash) : s) + '/' + group.getName();
group.setGroupClassType(Type.getObjectType(groupClassInternalName));
}

Expand All @@ -92,13 +128,11 @@ protected byte[] generateGroupClassCode(InstructionGroup group) {
}

private void generateClassBasics(InstructionGroup group, ClassWriter cw) {
cw.visit(ASMSettings.JDK_VERSION, ACC_PUBLIC + ACC_FINAL + ACC_SYNTHETIC, group.getGroupClassType().getInternalName(), null,
getBaseType().getInternalName(), null);
cw.visit(classFileVersion.getAsInt(), ACC_PUBLIC + ACC_FINAL + ACC_SYNTHETIC, group.getGroupClassType().getInternalName(), null,
getBaseType().getInternalName(), null);
cw.visitSource(classNode.sourceFile, null);
}

protected abstract Type getBaseType();

private void generateFields(InstructionGroup group, ClassWriter cw) {
for (FieldNode field : group.getFields()) {
// CAUTION: the FieldNode has illegal access flags and an illegal value field since these two members
Expand All @@ -120,6 +154,8 @@ private void generateConstructor(ClassWriter cw) {

protected abstract void generateMethod(InstructionGroup group, ClassWriter cw);

protected abstract Type getBaseType();

protected void insertSetContextCalls(InstructionGroup group, int localVarIx) {
InsnList instructions = group.getInstructions();
for (InstructionGraphNode node : group.getNodes()) {
Expand All @@ -141,7 +177,8 @@ protected void insertSetContextCalls(InstructionGroup group, int localVarIx) {
}
instructions.insertBefore(insn, new VarInsnNode(ALOAD, 1));
instructions.insertBefore(insn, new MethodInsnNode(INVOKEINTERFACE,
Types.CONTEXT_AWARE.getInternalName(), "setContext", "(" + Types.CONTEXT_DESC + ")V", true));
Types.CONTEXT_AWARE.getInternalName(), "setContext",
"(" + Types.CONTEXT_DESC + ")V", true));
}
}
}
Expand All @@ -151,8 +188,8 @@ protected void convertXLoads(InstructionGroup group) {
for (InstructionGraphNode node : group.getNodes()) {
if (!node.isXLoad()) continue;

VarInsnNode insn = (VarInsnNode) node.getInstruction();
FieldNode field = group.getFields().get(insn.var);
VarInsnNode insn = (VarInsnNode) node.getInstruction();
FieldNode field = group.getFields().get(insn.var);

// insert the correct GETFIELD after the xLoad
group.getInstructions().insert(insn, new FieldInsnNode(GETFIELD, owner, field.name, field.desc));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

package org.parboiled.transform;

import static org.parboiled.common.Preconditions.*;

import org.objectweb.asm.*;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.VarInsnNode;
Expand All @@ -33,6 +33,8 @@
import java.util.List;

import static org.objectweb.asm.Opcodes.ALOAD;
import static org.parboiled.common.Preconditions.checkArgNotNull;
import static org.parboiled.common.Preconditions.checkState;

class InstructionGroupPreparer implements RuleMethodProcessor {

Expand Down Expand Up @@ -286,15 +288,15 @@ private void update(Label label) {
}

private void ensureRemaining(int bytes) {
if (buffer.remaining() < bytes) {
if (((Buffer)buffer).remaining() < bytes) {
digest();
}
}

private void digest() {
buffer.flip();
((Buffer)buffer).flip();
digest.update(buffer);
buffer.clear();
((Buffer)buffer).clear();
}

public byte[] getMD5Hash() {
Expand Down
Loading

0 comments on commit 09872de

Please sign in to comment.