Skip to content

Commit

Permalink
Merge pull request #40197 from Sanne/CacheableTransformations
Browse files Browse the repository at this point in the history
VertxCoreProcessor and HibernateValidatorProcessor bytecode transformers are safe to be cached
  • Loading branch information
Sanne authored Apr 25, 2024
2 parents 438c23e + ccd92be commit 7470de8
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -566,32 +566,37 @@ void exceptionMapper(BuildProducer<ExceptionMapperBuildItem> exceptionMapperProd
// from Arc
@BuildStep
void overrideStandardValidationFactoryResolution(BuildProducer<BytecodeTransformerBuildItem> transformer) {
BytecodeTransformerBuildItem transformation = new BytecodeTransformerBuildItem(Validation.class.getName(),
(className, classVisitor) -> new ClassVisitor(Gizmo.ASM_API_VERSION, classVisitor) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions);

if (name.equals("buildDefaultValidatorFactory")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitMethodInsn(Opcodes.INVOKESTATIC,
ValidationSupport.class.getName().replace(".", "/"),
"buildDefaultValidatorFactory",
String.format("()L%s;", ValidatorFactory.class.getName().replace(".", "/")), false);
visitInsn(Opcodes.ARETURN);
BytecodeTransformerBuildItem transformation = new BytecodeTransformerBuildItem.Builder()
.setClassToTransform(Validation.class.getName())
.setCacheable(true)
.setVisitorFunction(
(className, classVisitor) -> new ClassVisitor(Gizmo.ASM_API_VERSION, classVisitor) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions);

if (name.equals("buildDefaultValidatorFactory")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitMethodInsn(Opcodes.INVOKESTATIC,
ValidationSupport.class.getName().replace('.', '/'),
"buildDefaultValidatorFactory",
String.format("()L%s;", ValidatorFactory.class.getName().replace('.', '/')),
false);
visitInsn(Opcodes.ARETURN);
}
};
}
};
}

// TODO: should intercept the other methods and throw an exception to indicate they are unsupported?
// TODO: should intercept the other methods and throw an exception to indicate they are unsupported?

return visitor;
}
});
return visitor;
}
})
.build();
transformer.produce(transformation);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,77 +118,85 @@ void overrideContextInternalInterfaceToAddSafeGuards(BuildProducer<BytecodeTrans

for (String name : classes) {
if (QuarkusClassLoader.isClassPresentAtRuntime(name)) {
BytecodeTransformerBuildItem transformation = new BytecodeTransformerBuildItem(name,
(className, classVisitor) -> new ClassVisitor(Gizmo.ASM_API_VERSION, classVisitor) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions);

if (name.equals("get") || name.equals("put") || name.equals("remove")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace(".", "/"),
"throwOnRootContextAccess",
"()V", false);
final BytecodeTransformerBuildItem transformation = new BytecodeTransformerBuildItem.Builder()
.setClassToTransform(name)
.setCacheable(true)
.setVisitorFunction(
(className, classVisitor) -> new ClassVisitor(Gizmo.ASM_API_VERSION, classVisitor) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature,
String[] exceptions) {
MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature,
exceptions);

if (name.equals("get") || name.equals("put") || name.equals("remove")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace('.', '/'),
"throwOnRootContextAccess",
"()V", false);
}
};
}
};
}

if (name.equals("getLocal") && descriptor.equals("(Ljava/lang/Object;)Ljava/lang/Object;")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitVarInsn(Opcodes.ALOAD, 0); // this
visitVarInsn(Opcodes.ALOAD, 1); // first param (object)
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace(".", "/"), "getLocal",
"(Lio/vertx/core/impl/ContextInternal;Ljava/lang/Object;)Ljava/lang/Object;",
false);
visitInsn(Opcodes.ARETURN);

if (name.equals("getLocal")
&& descriptor.equals("(Ljava/lang/Object;)Ljava/lang/Object;")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitVarInsn(Opcodes.ALOAD, 0); // this
visitVarInsn(Opcodes.ALOAD, 1); // first param (object)
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace('.', '/'), "getLocal",
"(Lio/vertx/core/impl/ContextInternal;Ljava/lang/Object;)Ljava/lang/Object;",
false);
visitInsn(Opcodes.ARETURN);
}
};
}
};
}

if (name.equals("putLocal") && descriptor.equals("(Ljava/lang/Object;Ljava/lang/Object;)V")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitVarInsn(Opcodes.ALOAD, 0); // this
visitVarInsn(Opcodes.ALOAD, 1); // first param (object)
visitVarInsn(Opcodes.ALOAD, 2); // second param (object)
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace(".", "/"), "putLocal",
"(Lio/vertx/core/impl/ContextInternal;Ljava/lang/Object;Ljava/lang/Object;)V",
false);
visitInsn(Opcodes.RETURN);

if (name.equals("putLocal")
&& descriptor.equals("(Ljava/lang/Object;Ljava/lang/Object;)V")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitVarInsn(Opcodes.ALOAD, 0); // this
visitVarInsn(Opcodes.ALOAD, 1); // first param (object)
visitVarInsn(Opcodes.ALOAD, 2); // second param (object)
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace('.', '/'), "putLocal",
"(Lio/vertx/core/impl/ContextInternal;Ljava/lang/Object;Ljava/lang/Object;)V",
false);
visitInsn(Opcodes.RETURN);
}
};
}
};
}

if (name.equals("removeLocal") && descriptor.equals("(Ljava/lang/Object;)Z")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitVarInsn(Opcodes.ALOAD, 0); // this
visitVarInsn(Opcodes.ALOAD, 1); // first param (object)
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace(".", "/"), "removeLocal",
"(Lio/vertx/core/impl/ContextInternal;Ljava/lang/Object;)Z", false);
visitInsn(Type.getType(Boolean.TYPE).getOpcode(Opcodes.IRETURN));

if (name.equals("removeLocal") && descriptor.equals("(Ljava/lang/Object;)Z")) {
return new MethodVisitor(Gizmo.ASM_API_VERSION, visitor) {
@Override
public void visitCode() {
super.visitCode();
visitVarInsn(Opcodes.ALOAD, 0); // this
visitVarInsn(Opcodes.ALOAD, 1); // first param (object)
visitMethodInsn(Opcodes.INVOKESTATIC,
VertxLocalsHelper.class.getName().replace('.', '/'), "removeLocal",
"(Lio/vertx/core/impl/ContextInternal;Ljava/lang/Object;)Z", false);
visitInsn(Type.getType(Boolean.TYPE).getOpcode(Opcodes.IRETURN));
}
};
}
};
}

return visitor;
}
});
return visitor;
}
})
.build();
transformer.produce(transformation);
}
}
Expand Down

0 comments on commit 7470de8

Please sign in to comment.