You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by ka...@apache.org on 2014/03/25 18:57:57 UTC
git commit: FIXED - TAP5-2214: Make tapestry5 java8 compatible -
update ASM source to 5.0.1
Repository: tapestry-5
Updated Branches:
refs/heads/master cb2ef6a24 -> b6ea90f11
FIXED - TAP5-2214: Make tapestry5 java8 compatible
- update ASM source to 5.0.1
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/b6ea90f1
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/b6ea90f1
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/b6ea90f1
Branch: refs/heads/master
Commit: b6ea90f114176f54814483e03c55f943c0fa5595
Parents: cb2ef6a
Author: kaosko <ka...@apache.org>
Authored: Tue Mar 25 10:57:53 2014 -0700
Committer: kaosko <ka...@apache.org>
Committed: Tue Mar 25 10:57:53 2014 -0700
----------------------------------------------------------------------
plastic/NOTICE.txt | 2 +-
.../internal/plastic/asm/ClassWriter.java | 28 +++++-
.../internal/plastic/asm/MethodWriter.java | 99 ++++++++++----------
.../plastic/asm/commons/InstructionAdapter.java | 2 +-
.../asm/commons/SerialVersionUIDAdder.java | 4 +-
.../plastic/asm/optimizer/ClassOptimizer.java | 89 +++++++++++++++++-
.../plastic/asm/optimizer/MethodOptimizer.java | 63 ++-----------
7 files changed, 171 insertions(+), 116 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/NOTICE.txt
----------------------------------------------------------------------
diff --git a/plastic/NOTICE.txt b/plastic/NOTICE.txt
index ec83bda..beec8e0 100644
--- a/plastic/NOTICE.txt
+++ b/plastic/NOTICE.txt
@@ -1,6 +1,6 @@
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
-This product imports and repackages ASM 5.0 code which is
+This product imports and repackages ASM 5.0.1 code which is
released under a BSD style License
http://asm.ow2.org/license.html
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
index 5074b0f..6cd89a5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
@@ -756,11 +756,29 @@ public class ClassWriter extends ClassVisitor {
if (innerClasses == null) {
innerClasses = new ByteVector();
}
- ++innerClassesCount;
- innerClasses.putShort(name == null ? 0 : newClass(name));
- innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
- innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
- innerClasses.putShort(access);
+ // �4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
+ // constant_pool table which represents a class or interface C that is
+ // not a package member must have exactly one corresponding entry in the
+ // classes array". To avoid duplicates we keep track in the intVal field
+ // of the Item of each CONSTANT_Class_info entry C whether an inner
+ // class entry has already been added for C (this field is unused for
+ // class entries, and changing its value does not change the hashcode
+ // and equality tests). If so we store the index of this inner class
+ // entry (plus one) in intVal. This hack allows duplicate detection in
+ // O(1) time.
+ Item nameItem = newClassItem(name);
+ if (nameItem.intVal == 0) {
+ ++innerClassesCount;
+ innerClasses.putShort(nameItem.index);
+ innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+ innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+ innerClasses.putShort(access);
+ nameItem.intVal = innerClassesCount;
+ } else {
+ // Compare the inner classes entry nameItem.intVal - 1 with the
+ // arguments of this method and throw an exception if there is a
+ // difference?
+ }
}
@Override
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
index 9900fbf..3128ff6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
@@ -43,7 +43,7 @@ class MethodWriter extends MethodVisitor {
* Pseudo access flag used to denote constructors.
*/
static final int ACC_CONSTRUCTOR = 0x80000;
-
+
/**
* Frame has exactly the same locals as the previous stack map frame and
* number of stack items is zero.
@@ -1401,6 +1401,14 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (resize) {
+ // replaces the temporary jump opcodes introduced by Label.resolve.
+ if (ClassReader.RESIZE) {
+ resizeInstructions();
+ } else {
+ throw new RuntimeException("Method code too large!");
+ }
+ }
if (ClassReader.FRAMES && compute == FRAMES) {
// completes the control flow graph with exception handler blocks
Handler handler = firstHandler;
@@ -2022,14 +2030,6 @@ class MethodWriter extends MethodVisitor {
if (classReaderOffset != 0) {
return 6 + classReaderLength;
}
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- if (ClassReader.RESIZE) {
- resizeInstructions();
- } else {
- throw new RuntimeException("Method code too large!");
- }
- }
int size = 8;
if (code.length > 0) {
if (code.length > 65536) {
@@ -2686,49 +2686,50 @@ class MethodWriter extends MethodVisitor {
}
}
- // recomputes the stack map frames
- if (frameCount > 0) {
- if (compute == FRAMES) {
- frameCount = 0;
- stackMap = null;
- previousFrame = null;
- frame = null;
- Frame f = new Frame();
- f.owner = labels;
- Type[] args = Type.getArgumentTypes(descriptor);
- f.initInputFrame(cw, access, args, maxLocals);
- visitFrame(f);
- Label l = labels;
- while (l != null) {
- /*
- * here we need the original label position. getNewOffset
- * must therefore never have been called for this label.
- */
- u = l.position - 3;
- if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) {
- getNewOffset(allIndexes, allSizes, l);
- // TODO update offsets in UNINITIALIZED values
- visitFrame(l.frame);
- }
- l = l.successor;
- }
- } else {
+ // updates the stack map frame labels
+ if (compute == FRAMES) {
+ Label l = labels;
+ while (l != null) {
/*
- * Resizing an existing stack map frame table is really hard.
- * Not only the table must be parsed to update the offets, but
- * new frames may be needed for jump instructions that were
- * inserted by this method. And updating the offsets or
- * inserting frames can change the format of the following
- * frames, in case of packed frames. In practice the whole table
- * must be recomputed. For this the frames are marked as
- * potentially invalid. This will cause the whole class to be
- * reread and rewritten with the COMPUTE_FRAMES option (see the
- * ClassWriter.toByteArray method). This is not very efficient
- * but is much easier and requires much less code than any other
- * method I can think of.
+ * Detects the labels that are just after an IF instruction that
+ * has been resized with the IFNOT GOTO_W pattern. These labels
+ * are now the target of a jump instruction (the IFNOT
+ * instruction). Note that we need the original label position
+ * here. getNewOffset must therefore never have been called for
+ * this label.
*/
- cw.invalidFrames = true;
+ u = l.position - 3;
+ if (u >= 0 && resize[u]) {
+ l.status |= Label.TARGET;
+ }
+ getNewOffset(allIndexes, allSizes, l);
+ l = l.successor;
}
+ // Update the offsets in the uninitialized types
+ for (i = 0; i < cw.typeTable.length; ++i) {
+ Item item = cw.typeTable[i];
+ if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
+ item.intVal = getNewOffset(allIndexes, allSizes, 0,
+ item.intVal);
+ }
+ }
+ // The stack map frames are not serialized yet, so we don't need
+ // to update them. They will be serialized in visitMaxs.
+ } else if (frameCount > 0) {
+ /*
+ * Resizing an existing stack map frame table is really hard. Not
+ * only the table must be parsed to update the offets, but new
+ * frames may be needed for jump instructions that were inserted by
+ * this method. And updating the offsets or inserting frames can
+ * change the format of the following frames, in case of packed
+ * frames. In practice the whole table must be recomputed. For this
+ * the frames are marked as potentially invalid. This will cause the
+ * whole class to be reread and rewritten with the COMPUTE_FRAMES
+ * option (see the ClassWriter.toByteArray method). This is not very
+ * efficient but is much easier and requires much less code than any
+ * other method I can think of.
+ */
+ cw.invalidFrames = true;
}
// updates the exception handler block labels
Handler h = firstHandler;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
index dd10e0b..fe8400a 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -1060,7 +1060,7 @@ public class InstructionAdapter extends MethodVisitor {
@Deprecated
public void invokestatic(final String owner, final String name,
final String desc) {
- if (api < Opcodes.ASM5) {
+ if (api >= Opcodes.ASM5) {
invokestatic(owner, name, desc, false);
return;
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
index 7ce521c..04dcc9b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
@@ -210,7 +210,9 @@ public class SerialVersionUIDAdder extends ClassVisitor {
if (computeSVUID) {
this.name = name;
this.access = access;
- this.interfaces = Arrays.copyOf(interfaces, interfaces.length);
+ this.interfaces = new String[interfaces.length];
+ System.arraycopy(interfaces, 0, this.interfaces, 0,
+ interfaces.length);
}
super.visit(version, access, name, signature, superName, interfaces);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
index ac34ba7..f4a7a22 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
@@ -29,10 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.optimizer;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.TypePath;
@@ -50,7 +54,10 @@ public class ClassOptimizer extends RemappingClassAdapter {
private String pkgName;
String clsName;
- boolean class$;
+
+ boolean isInterface = false;
+ boolean hasClinitMethod = false;
+ List<String> syntheticClassFields = new ArrayList<String>();
public ClassOptimizer(final ClassVisitor cv, final Remapper remapper) {
super(Opcodes.ASM5, cv, remapper);
@@ -70,13 +77,14 @@ public class ClassOptimizer extends RemappingClassAdapter {
final String signature, final String superName,
final String[] interfaces) {
super.visit(Opcodes.V1_2, access, name, null, superName, interfaces);
- clsName = name;
int index = name.lastIndexOf('/');
if (index > 0) {
pkgName = name.substring(0, index);
} else {
pkgName = "";
}
+ clsName = name;
+ isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
}
@Override
@@ -149,6 +157,19 @@ public class ClassOptimizer extends RemappingClassAdapter {
if ("-".equals(s)) {
return null;
}
+ if (name.equals("<clinit>") && !isInterface) {
+ hasClinitMethod = true;
+ MethodVisitor mv = super.visitMethod(access, name, desc, null,
+ exceptions);
+ return new MethodVisitor(Opcodes.ASM5, mv) {
+ @Override
+ public void visitCode() {
+ super.visitCode();
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName,
+ "_clinit_", "()V", false);
+ }
+ };
+ }
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
if ("org/objectweb/asm".equals(pkgName) && !name.startsWith("<")
@@ -172,4 +193,68 @@ public class ClassOptimizer extends RemappingClassAdapter {
String newDesc, MethodVisitor mv) {
return new MethodOptimizer(this, access, newDesc, mv, remapper);
}
+
+ @Override
+ public void visitEnd() {
+ if (syntheticClassFields.isEmpty()) {
+ if (hasClinitMethod) {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+ | Opcodes.ACC_SYNTHETIC, "_clinit_", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+ } else {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+ | Opcodes.ACC_SYNTHETIC, "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
+ mv.visitCode();
+ Label l0 = new Label();
+ Label l1 = new Label();
+ Label l2 = new Label();
+ mv.visitTryCatchBlock(l0, l1, l2,
+ "java/lang/ClassNotFoundException");
+ mv.visitLabel(l0);
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class",
+ "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ mv.visitLabel(l1);
+ mv.visitInsn(Opcodes.ARETURN);
+ mv.visitLabel(l2);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/ClassNotFoundException", "getMessage",
+ "()Ljava/lang/String;", false);
+ mv.visitVarInsn(Opcodes.ASTORE, 1);
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/NoClassDefFoundError");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ALOAD, 1);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ "java/lang/NoClassDefFoundError", "<init>",
+ "(Ljava/lang/String;)V", false);
+ mv.visitInsn(Opcodes.ATHROW);
+ mv.visitMaxs(3, 2);
+ mv.visitEnd();
+
+ if (hasClinitMethod) {
+ mv = cv.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+ "_clinit_", "()V", null, null);
+ } else {
+ mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V",
+ null, null);
+ }
+ for (String ldcName : syntheticClassFields) {
+ String fieldName = "class$" + ldcName.replace('/', '$');
+ mv.visitLdcInsn(ldcName.replace('/', '.'));
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName, "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, clsName, fieldName,
+ "Ljava/lang/Class;");
+ }
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(1, 0);
+ mv.visitEnd();
+ }
+ super.visitEnd();
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b6ea90f1/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
index afb4b27..adad6b4 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
@@ -50,8 +50,6 @@ public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
private final ClassOptimizer classOptimizer;
- private boolean ldcClass = false;
-
public MethodOptimizer(ClassOptimizer classOptimizer, int access,
String desc, MethodVisitor mv, Remapper remapper) {
super(Opcodes.ASM5, access, desc, mv, remapper);
@@ -122,66 +120,17 @@ public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
return;
}
- // transform Foo.class to foo$(class) for 1.2 compatibility
+ // transform Foo.class for 1.2 compatibility
String ldcName = ((Type) cst).getInternalName();
String fieldName = "class$" + ldcName.replace('/', '$');
-
- FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
- | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
- fv.visitEnd();
-
- if (!classOptimizer.class$) {
- MethodVisitor mv = classOptimizer.visitMethod(ACC_STATIC
- | ACC_SYNTHETIC, "class$",
- "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
- mv.visitCode();
- Label l0 = new Label();
- Label l1 = new Label();
- Label l2 = new Label();
- mv.visitTryCatchBlock(l0, l1, l2,
- "java/lang/ClassNotFoundException");
- mv.visitLabel(l0);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName",
- "(Ljava/lang/String;)Ljava/lang/Class;", false);
- mv.visitLabel(l1);
- mv.visitInsn(ARETURN);
- mv.visitLabel(l2);
- mv.visitMethodInsn(INVOKEVIRTUAL,
- "java/lang/ClassNotFoundException", "getMessage",
- "()Ljava/lang/String;", false);
- mv.visitVarInsn(ASTORE, 1);
- mv.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
- mv.visitInsn(DUP);
- mv.visitVarInsn(ALOAD, 1);
- mv.visitMethodInsn(INVOKESPECIAL, "java/lang/NoClassDefFoundError",
- "<init>", "(Ljava/lang/String;)V", false);
- mv.visitInsn(ATHROW);
- mv.visitMaxs(3, 2);
- mv.visitEnd();
-
- classOptimizer.class$ = true;
+ if (!classOptimizer.syntheticClassFields.contains(ldcName)) {
+ classOptimizer.syntheticClassFields.add(ldcName);
+ FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
+ | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
+ fv.visitEnd();
}
String clsName = classOptimizer.clsName;
mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
- Label elseLabel = new Label();
- mv.visitJumpInsn(IFNONNULL, elseLabel);
- mv.visitLdcInsn(ldcName.replace('/', '.'));
- mv.visitMethodInsn(INVOKESTATIC, clsName, "class$",
- "(Ljava/lang/String;)Ljava/lang/Class;", false);
- mv.visitInsn(DUP);
- mv.visitFieldInsn(PUTSTATIC, clsName, fieldName, "Ljava/lang/Class;");
- Label endLabel = new Label();
- mv.visitJumpInsn(GOTO, endLabel);
- mv.visitLabel(elseLabel);
- mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
- mv.visitLabel(endLabel);
- ldcClass = true;
- }
-
- @Override
- public void visitMaxs(int maxStack, int maxLocals) {
- super.visitMaxs(ldcClass ? maxStack + 1 : maxStack, maxLocals);
}
}