Created
December 30, 2011 13:23
-
-
Save melix/1539838 to your computer and use it in GitHub Desktop.
Make use of LDC for class literals when possible
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: groovy-git/src/main/org/codehaus/groovy/classgen/Verifier.java | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>UTF-8 | |
=================================================================== | |
--- groovy-git/src/main/org/codehaus/groovy/classgen/Verifier.java (date 1325233165000) | |
+++ groovy-git/src/main/org/codehaus/groovy/classgen/Verifier.java (revision ) | |
@@ -210,7 +210,7 @@ | |
node.addConstructor(constructor); | |
} | |
- private void addStaticMetaClassField(ClassNode node, final String classInternalName) { | |
+ private void addStaticMetaClassField(final ClassNode node, final String classInternalName) { | |
String _staticClassInfoFieldName = "$staticClassInfo"; | |
while (node.getDeclaredField(_staticClassInfoFieldName) != null) | |
_staticClassInfoFieldName = _staticClassInfoFieldName + "$"; | |
@@ -229,8 +229,11 @@ | |
public void visit(MethodVisitor mv) { | |
mv.visitVarInsn(ALOAD, 0); | |
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;"); | |
+ if (BytecodeHelper.isClassLiteralPossible(node)) { | |
+ BytecodeHelper.visitClassLiteral(mv,node); | |
+ } else { | |
- mv.visitMethodInsn(INVOKESTATIC, classInternalName, "$get$$class$" + classInternalName.replaceAll("\\/", "\\$"), "()Ljava/lang/Class;"); | |
+ mv.visitMethodInsn(INVOKESTATIC, classInternalName, "$get$$class$" + classInternalName.replaceAll("\\/", "\\$"), "()Ljava/lang/Class;"); | |
- | |
+ } | |
Label l1 = new Label(); | |
mv.visitJumpInsn(IF_ACMPEQ, l1); | |
Index: groovy-git/src/main/org/codehaus/groovy/classgen/AsmClassGenerator.java | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>UTF-8 | |
=================================================================== | |
--- groovy-git/src/main/org/codehaus/groovy/classgen/AsmClassGenerator.java (date 1325233165000) | |
+++ groovy-git/src/main/org/codehaus/groovy/classgen/AsmClassGenerator.java (revision ) | |
@@ -1294,7 +1294,7 @@ | |
} | |
protected void createSyntheticStaticFields() { | |
- MethodVisitor mv = controller.getMethodVisitor(); | |
+ MethodVisitor mv; | |
for (String staticFieldName : referencedClasses.keySet()) { | |
// generate a field node | |
FieldNode fn = controller.getClassNode().getDeclaredField(staticFieldName); | |
@@ -1364,23 +1364,30 @@ | |
public void visitClassExpression(ClassExpression expression) { | |
ClassNode type = expression.getType(); | |
MethodVisitor mv = controller.getMethodVisitor(); | |
- | |
- if (ClassHelper.isPrimitiveType(type)) { | |
- ClassNode objectType = ClassHelper.getWrapper(type); | |
- mv.visitFieldInsn(GETSTATIC, BytecodeHelper.getClassInternalName(objectType), "TYPE", "Ljava/lang/Class;"); | |
+ if (BytecodeHelper.isClassLiteralPossible(type)) { | |
+ if (controller.getClassNode().isInterface()) { | |
+ InterfaceHelperClassNode interfaceClassLoadingClass = controller.getInterfaceClassLoadingClass(); | |
+ if (BytecodeHelper.isClassLiteralPossible(interfaceClassLoadingClass)) { | |
+ BytecodeHelper.visitClassLiteral(mv, interfaceClassLoadingClass); | |
+ controller.getOperandStack().push(ClassHelper.CLASS_Type); | |
+ return; | |
+ } | |
- } else { | |
+ } else { | |
+ BytecodeHelper.visitClassLiteral(mv, type); | |
+ controller.getOperandStack().push(ClassHelper.CLASS_Type); | |
+ return; | |
+ } | |
+ } | |
- String staticFieldName = getStaticFieldName(type); | |
+ String staticFieldName = getStaticFieldName(type); | |
- referencedClasses.put(staticFieldName,type); | |
+ referencedClasses.put(staticFieldName, type); | |
- String internalClassName = controller.getInternalClassName(); | |
- if (controller.getClassNode().isInterface()) { | |
- internalClassName = BytecodeHelper.getClassInternalName(controller.getInterfaceClassLoadingClass()); | |
- mv.visitFieldInsn(GETSTATIC, internalClassName, staticFieldName, "Ljava/lang/Class;"); | |
- } else { | |
- mv.visitMethodInsn(INVOKESTATIC, internalClassName, "$get$" + staticFieldName, "()Ljava/lang/Class;"); | |
- } | |
+ String internalClassName = controller.getInternalClassName(); | |
+ if (controller.getClassNode().isInterface()) { | |
+ internalClassName = BytecodeHelper.getClassInternalName(controller.getInterfaceClassLoadingClass()); | |
+ mv.visitFieldInsn(GETSTATIC, internalClassName, staticFieldName, "Ljava/lang/Class;"); | |
+ } else { | |
+ mv.visitMethodInsn(INVOKESTATIC, internalClassName, "$get$" + staticFieldName, "()Ljava/lang/Class;"); | |
+ } | |
- } | |
- | |
controller.getOperandStack().push(ClassHelper.CLASS_Type); | |
} | |
Index: groovy-git/src/main/org/codehaus/groovy/runtime/callsite/CallSiteArray.java | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>UTF-8 | |
=================================================================== | |
--- groovy-git/src/main/org/codehaus/groovy/runtime/callsite/CallSiteArray.java (date 1325233165000) | |
+++ groovy-git/src/main/org/codehaus/groovy/runtime/callsite/CallSiteArray.java (revision ) | |
@@ -56,6 +56,11 @@ | |
private static CallSite createCallStaticSite(CallSite callSite, Class receiver, Object[] args) { | |
CallSite site; | |
+ try { | |
+ Class.forName(receiver.getName(), true, receiver.getClassLoader()); | |
+ } catch (ClassNotFoundException e) { | |
+ // force call of <cinit> | |
+ } | |
MetaClass metaClass = InvokerHelper.getMetaClass(receiver); | |
if (metaClass instanceof MetaClassImpl) { | |
site = ((MetaClassImpl)metaClass).createStaticSite(callSite, args); | |
Index: groovy-git/src/main/org/codehaus/groovy/classgen/asm/BytecodeHelper.java | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>UTF-8 | |
=================================================================== | |
--- groovy-git/src/main/org/codehaus/groovy/classgen/asm/BytecodeHelper.java (date 1325233165000) | |
+++ groovy-git/src/main/org/codehaus/groovy/classgen/asm/BytecodeHelper.java (revision ) | |
@@ -22,6 +22,8 @@ | |
import org.objectweb.asm.MethodVisitor; | |
import org.objectweb.asm.Opcodes; | |
+import java.lang.reflect.Modifier; | |
+ | |
/** | |
* A helper class for bytecode generation with AsmClassGenerator. | |
* | |
@@ -605,5 +607,35 @@ | |
return true; | |
} | |
return false; | |
+ } | |
+ | |
+ /** | |
+ * Returns the asm type for a class node. | |
+ */ | |
+ public static void visitClassLiteral(MethodVisitor mv, ClassNode classNode) { | |
+ if (ClassHelper.isPrimitiveType(classNode)) { | |
+ mv.visitFieldInsn( | |
+ GETSTATIC, | |
+ getClassInternalName(ClassHelper.getWrapper(classNode)), | |
+ "TYPE", | |
+ "Ljava/lang/Class;"); | |
+ } else { | |
+ mv.visitLdcInsn(org.objectweb.asm.Type.getType(getTypeDescription(classNode))); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Tells if a class node is candidate for class literal bytecode optimization. If so, | |
+ * bytecode may use LDC instructions instead of static constant Class fields to retrieve | |
+ * class literals. | |
+ * @param classNode the classnode for which we want to know if bytecode optimization is possible | |
+ * @return true if the bytecode can be optimized | |
+ */ | |
+ public static boolean isClassLiteralPossible(ClassNode classNode) { | |
+ // the current implementation only checks for public modifier, because Groovy used to allow | |
+ // handles on classes even if they are package protected and not in the same package. | |
+ // There are situations where we could make more fine grained checks, but be careful of | |
+ // potential breakage of existing code. | |
+ return Modifier.isPublic(classNode.getModifiers()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment