Skip to content

Commit

Permalink
Startup Time Regression in EclipseLink fix - ASM Opcodes loading (#2065)
Browse files Browse the repository at this point in the history
This is performance fix to avoid unnecessary loading of Opcodes constants from selected ASM provider.
There was 4-6% Startup Time Regression in EclipseLink.
Fixes #2048

Signed-off-by: Radek Felcman <radek.felcman@oracle.com>
Co-authored-by: anija-anil <135797466+anija-anil@users.noreply.github.com>
  • Loading branch information
rfelcman and anija-anil committed Feb 20, 2024
1 parent 1f7906b commit ef626d4
Show file tree
Hide file tree
Showing 34 changed files with 946 additions and 872 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -58,12 +58,12 @@ protected byte[] generateClassBytes(String className) {
* }
*/
ClassWriter cw = new EclipseLinkASMClassWriter();
cw.visit(Opcodes.valueInt("ACC_PUBLIC") + Opcodes.valueInt("ACC_SUPER"), className, null, SOAP_RESPONSE_CLASSNAME_SLASHES, null);
cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className, null, SOAP_RESPONSE_CLASSNAME_SLASHES, null);

MethodVisitor mv = cw.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "<init>", "()V", null, null);
mv.visitVarInsn(Opcodes.valueInt("ALOAD"), 0);
mv.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), SOAP_RESPONSE_CLASSNAME_SLASHES, "<init>", "()V", false);
mv.visitInsn(Opcodes.valueInt("RETURN"));
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, SOAP_RESPONSE_CLASSNAME_SLASHES, "<init>", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -67,44 +67,44 @@ public byte[] writeClass(DynamicClassLoader loader, String className) throws Cla

// special-case: build sub-class of XRDynamicEntityCollection
if (className.endsWith(COLLECTION_WRAPPER_SUFFIX)) {
cw.visit(Opcodes.valueInt("ACC_PUBLIC") + Opcodes.valueInt("ACC_SUPER"), classNameAsSlashes, null, XR_DYNAMIC_ENTITY_COLLECTION_CLASSNAME_SLASHES, null);
mv = cw.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), INIT, "()V", null, null);
mv.visitVarInsn(Opcodes.valueInt("ALOAD"), 0);
mv.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), XR_DYNAMIC_ENTITY_COLLECTION_CLASSNAME_SLASHES, INIT, "()V", false);
mv.visitInsn(Opcodes.valueInt("RETURN"));
cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classNameAsSlashes, null, XR_DYNAMIC_ENTITY_COLLECTION_CLASSNAME_SLASHES, null);
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, INIT, "()V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, XR_DYNAMIC_ENTITY_COLLECTION_CLASSNAME_SLASHES, INIT, "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
} else {
// public class Foo extends XRDynamicEntity {
cw.visit(Opcodes.valueInt("ACC_PUBLIC") + Opcodes.valueInt("ACC_SUPER"), classNameAsSlashes, null, XR_DYNAMIC_ENTITY_CLASSNAME_SLASHES, null);
cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classNameAsSlashes, null, XR_DYNAMIC_ENTITY_CLASSNAME_SLASHES, null);

// public static XRDynamicPropertiesManager DPM = new
// XRDynamicPropertiesManager();
cw.visitField(Opcodes.valueInt("ACC_PUBLIC") + Opcodes.valueInt("ACC_STATIC"), PROPERTIES_MANAGER_FIELD, "L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";", null, null);

mv = cw.visitMethod(Opcodes.valueInt("ACC_STATIC"), CLINIT, "()V", null, null);
mv.visitTypeInsn(Opcodes.valueInt("NEW"), XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES);
mv.visitInsn(Opcodes.valueInt("DUP"));
mv.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES, INIT, "()V", false);
mv.visitFieldInsn(Opcodes.valueInt("PUTSTATIC"), classNameAsSlashes, PROPERTIES_MANAGER_FIELD, "L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";");
mv.visitInsn(Opcodes.valueInt("RETURN"));
cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, PROPERTIES_MANAGER_FIELD, "L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";", null, null);

mv = cw.visitMethod(Opcodes.ACC_STATIC, CLINIT, "()V", null, null);
mv.visitTypeInsn(Opcodes.NEW, XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES);
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES, INIT, "()V", false);
mv.visitFieldInsn(Opcodes.PUTSTATIC, classNameAsSlashes, PROPERTIES_MANAGER_FIELD, "L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();

// public Foo() {
// super();
// }
mv = cw.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), INIT, "()V", null, null);
mv.visitVarInsn(Opcodes.valueInt("ALOAD"), 0);
mv.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), XR_DYNAMIC_ENTITY_CLASSNAME_SLASHES, INIT, "()V", false);
mv.visitInsn(Opcodes.valueInt("RETURN"));
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, INIT, "()V", null, null);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, XR_DYNAMIC_ENTITY_CLASSNAME_SLASHES, INIT, "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();

// public XRDynamicPropertiesManager fetchPropertiesManager() {
mv = cw.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "fetchPropertiesManager", "()L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";", null, null);
mv.visitFieldInsn(Opcodes.valueInt("GETSTATIC"), classNameAsSlashes, PROPERTIES_MANAGER_FIELD, "L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";");
mv.visitInsn(Opcodes.valueInt("ARETURN"));
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "fetchPropertiesManager", "()L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";", null, null);
mv.visitFieldInsn(Opcodes.GETSTATIC, classNameAsSlashes, PROPERTIES_MANAGER_FIELD, "L" + XR_DYNAMIC_PROPERTIES_MANAGER_CLASSNAME_SLASHES + ";");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -16,6 +16,7 @@

import org.eclipse.persistence.asm.ASMFactory;
import org.eclipse.persistence.asm.ClassVisitor;
import org.eclipse.persistence.asm.Opcodes;
import org.eclipse.persistence.config.SystemProperties;
import org.junit.Test;

Expand All @@ -40,7 +41,7 @@ public void getAsmServiceTest() {
@Test
public void createClassVisitorTest() {
String asmServiceSysProperty = System.getProperty(SystemProperties.ASM_SERVICE, "");
ClassVisitor classVisitor = ASMFactory.createClassVisitor(ASMFactory.ASM_API_SELECTED);
ClassVisitor classVisitor = ASMFactory.createClassVisitor(Opcodes.ASM_API_SELECTED);
switch (asmServiceSysProperty) {
case ASMFactory.ASM_SERVICE_OW2:
assertEquals(org.eclipse.persistence.asm.internal.platform.ow2.ClassVisitorImpl.class, classVisitor.getClass());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -14,6 +14,7 @@
// Oracle - initial API and implementation
package org.eclipse.persistence.asm;

import org.eclipse.persistence.asm.internal.Util;
import org.eclipse.persistence.config.SystemProperties;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
Expand All @@ -26,23 +27,23 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class ASMFactory {

private final static SessionLog LOG = AbstractSessionLog.getLog();

// This block must be first - begin
public final static String ASM_SERVICE_ECLIPSELINK = "eclipselink";
public final static String ASM_SERVICE_OW2 = "ow2";
private final static String ASM_OW2_CLASS_VISITOR = "org.objectweb.asm.ClassVisitor";
private final static String ASM_ECLIPSELINK_CLASS_VISITOR = "org.eclipse.persistence.internal.libraries.asm.ClassVisitor";
private final static SessionLog LOG = AbstractSessionLog.getLog();
// This block must be first - end

//Should be changed in case of ASM upgrade
public final static int ASM_API_SELECTED = Opcodes.valueInt("ASM9");
public final static int JAVA_CLASS_VERSION = Opcodes.valueInt("V1_8");
// Should be changed in case of ASM upgrade
public final static int JAVA_CLASS_LATEST_VERSION = ASMFactory.getLatestOPCodeVersion();

public static AnnotationVisitor createAnnotationVisitor(final int api) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -21,6 +21,7 @@

public abstract class ClassReader {

//This block must be first - begin
private final static String ASM_CLASSREADER_ECLIPSELINK = "org.eclipse.persistence.internal.libraries.asm.ClassReader";
private final static String ASM_CLASSREADER_OW2 = "org.objectweb.asm.ClassReader";

Expand All @@ -30,8 +31,13 @@ public abstract class ClassReader {
ASM_CLASSREADER_MAP.put(ASMFactory.ASM_SERVICE_OW2, ASM_CLASSREADER_OW2);
ASM_CLASSREADER_MAP.put(ASMFactory.ASM_SERVICE_ECLIPSELINK, ASM_CLASSREADER_ECLIPSELINK);
}
//This block must be first - end

public static int valueInt(String fieldName) {
public static final int SKIP_CODE = valueInt("SKIP_CODE");
public static final int SKIP_DEBUG = valueInt("SKIP_DEBUG");
public static final int SKIP_FRAMES = valueInt("SKIP_FRAMES");

private static int valueInt(String fieldName) {
return ((int) Util.getFieldValue(ASM_CLASSREADER_MAP, fieldName, Integer.TYPE));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -21,6 +21,7 @@

public abstract class ClassWriter extends ClassVisitor {

//This block must be first - begin
private final static String ASM_CLASSWRITER_ECLIPSELINK = "org.eclipse.persistence.internal.libraries.asm.ClassWriter";
private final static String ASM_CLASSWRITER_OW2 = "org.objectweb.asm.ClassWriter";

Expand All @@ -30,7 +31,9 @@ public abstract class ClassWriter extends ClassVisitor {
ASM_CLASSWRITER_MAP.put(ASMFactory.ASM_SERVICE_OW2, ASM_CLASSWRITER_OW2);
ASM_CLASSWRITER_MAP.put(ASMFactory.ASM_SERVICE_ECLIPSELINK, ASM_CLASSWRITER_ECLIPSELINK);
}
//This block must be first - end

public static final int COMPUTE_FRAMES = valueInt("COMPUTE_FRAMES");
private ClassWriter cw;
protected ClassWriter customClassWriter;

Expand All @@ -42,7 +45,7 @@ public ClassWriter(final int flags) {
}

public ClassWriter(final ClassReader classReader, final int flags) {
super(ASMFactory.ASM_API_SELECTED);
super(Opcodes.ASM_API_SELECTED);
cw = ASMFactory.createClassWriter(flags);
}

Expand All @@ -58,7 +61,7 @@ public ClassWriter getInternal() {
return cw;
}

public static int valueInt(String fieldName) {
private static int valueInt(String fieldName) {
return ((int) Util.getFieldValue(ASM_CLASSWRITER_MAP, fieldName, Integer.TYPE));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -23,7 +23,7 @@ public class EclipseLinkASMClassWriter extends ClassWriter {
private ClassWriter classWriter;

public EclipseLinkASMClassWriter() {
this(ClassWriter.valueInt("COMPUTE_FRAMES"));
this(ClassWriter.COMPUTE_FRAMES);
}

public EclipseLinkASMClassWriter(final int flags) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -19,11 +19,11 @@ public abstract class EclipseLinkAnnotationVisitor extends AnnotationVisitor {
private AnnotationVisitor annotationVisitor;

public EclipseLinkAnnotationVisitor() {
this.annotationVisitor = ASMFactory.createAnnotationVisitor(ASMFactory.ASM_API_SELECTED);
this.annotationVisitor = ASMFactory.createAnnotationVisitor(Opcodes.ASM_API_SELECTED);
}

public EclipseLinkAnnotationVisitor(AnnotationVisitor annotationVisitor) {
this.annotationVisitor = ASMFactory.createAnnotationVisitor(ASMFactory.ASM_API_SELECTED, annotationVisitor);
this.annotationVisitor = ASMFactory.createAnnotationVisitor(Opcodes.ASM_API_SELECTED, annotationVisitor);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -17,11 +17,11 @@
public abstract class EclipseLinkClassVisitor extends ClassVisitor {

public EclipseLinkClassVisitor() {
super(ASMFactory.ASM_API_SELECTED);
super(Opcodes.ASM_API_SELECTED);
}

public EclipseLinkClassVisitor(ClassVisitor classVisitor) {
super(ASMFactory.ASM_API_SELECTED, classVisitor);
super(Opcodes.ASM_API_SELECTED, classVisitor);
}

public void visit(
Expand All @@ -30,7 +30,7 @@ public void visit(
final String signature,
final String superName,
final String[] interfaces) {
visit(ASMFactory.ASM_API_SELECTED, access, name, signature, superName, interfaces);
visit(Opcodes.ASM_API_SELECTED, access, name, signature, superName, interfaces);
}

public abstract AnnotationVisitor visitAnnotation(String desc, boolean visible);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -19,11 +19,11 @@ public class EclipseLinkFieldVisitor extends FieldVisitor {
private FieldVisitor fieldVisitor;

public EclipseLinkFieldVisitor() {
this.fieldVisitor = ASMFactory.createFieldVisitor(ASMFactory.ASM_API_SELECTED);
this.fieldVisitor = ASMFactory.createFieldVisitor(Opcodes.ASM_API_SELECTED);
}

public EclipseLinkFieldVisitor(FieldVisitor fieldVisitor) {
this.fieldVisitor = ASMFactory.createFieldVisitor(ASMFactory.ASM_API_SELECTED, fieldVisitor);
this.fieldVisitor = ASMFactory.createFieldVisitor(Opcodes.ASM_API_SELECTED, fieldVisitor);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -19,11 +19,11 @@ public class EclipseLinkMethodVisitor extends MethodVisitor {
protected MethodVisitor methodVisitor;

public EclipseLinkMethodVisitor() {
this.methodVisitor = ASMFactory.createMethodVisitor(ASMFactory.ASM_API_SELECTED);
this.methodVisitor = ASMFactory.createMethodVisitor(Opcodes.ASM_API_SELECTED);
}

public EclipseLinkMethodVisitor(MethodVisitor methodVisitor) {
this.methodVisitor = ASMFactory.createMethodVisitor(ASMFactory.ASM_API_SELECTED, methodVisitor);
this.methodVisitor = ASMFactory.createMethodVisitor(Opcodes.ASM_API_SELECTED, methodVisitor);
}

@Override
Expand Down

0 comments on commit ef626d4

Please sign in to comment.