Skip to content

Latest commit

 

History

History
205 lines (142 loc) · 6.39 KB

File metadata and controls

205 lines (142 loc) · 6.39 KB

ASM Contract

JavaToGpu includes an ASM input path for advanced integrations that already generate bytecode.

Most application users should write normal Java source with @GPU. Use the ASM path only when you own the bytecode generation step and can keep the generated methods inside JavaToGpu's supported GPU subset.

When To Use ASM Input

Use this path when you have:

  • A custom language or DSL that emits JVM bytecode.
  • A compiler pipeline that already owns an AST or IR.
  • A build step that can normalize code before JavaToGpu sees it.
  • CI tooling that wants to preflight compiled classes or jars.

Do not use it as a general way to convert arbitrary Java libraries to GPU code.

Recommended Flow

Recommended:

your DSL/AST/IR -> supported JVM bytecode -> ASM preflight -> JavaToGpu compile -> OpenCL

Avoid:

arbitrary JVM bytecode -> automatic GPU recovery

The preflight step is important because it tells you what needs to be rewritten before compilation.

Bytecode Shape That Works Best

Generated bytecode should be simple and predictable:

  • Static methods.
  • Clear local variables for intermediate values.
  • Simple loops and branches.
  • Stable stack shape at branch merge points.
  • INVOKESTATIC calls to supported GPU helpers.
  • Primitive, vector, pointer, image, sampler, or struct-compatible signatures.
  • Math and backend operations expressed through GPU.* or known helper methods.

If your generator can choose between clever stack bytecode and boring local-variable bytecode, choose the boring version.

Bytecode Shapes To Avoid

These are not part of the current alpha ASM input contract:

  • invokevirtual, invokeinterface, and invokedynamic as general dispatch.
  • Exception tables and exception-driven control flow.
  • monitorenter, monitorexit, and Java synchronization semantics.
  • Runtime object allocation and object graph access.
  • Recursion and dynamic call graphs.
  • Unsupported field access, casts, type checks, and descriptors.
  • JVM array metadata patterns that should be passed explicitly instead.

Preflight A Class, Directory, Or Jar

Use preflight before real lowering:

GpuProgramCompiler compiler = GpuProgramCompiler.createDefault();
AsmFrontendFailureReport report = compiler.reportStructuredAsmArtifact(pathToClassesOrJar);

if (!report.successful()) {
    System.err.println(report.summaryLine());
    report.failures().forEach(failure -> System.err.println(failure.summary()));
}

The generic artifact preflight accepts:

  • A .class file.
  • A directory containing .class files.
  • A .jar file.

It scans in stable order and aggregates failures into one report.

Readiness Report

For migration planning, use the readiness report:

AsmFrontendReadinessReport readiness = compiler
        .reportStructuredAsmArtifactReadiness(pathToClassesOrJar);

System.err.println(readiness.summaryLine());

Readiness verdicts:

  • supported means the artifact matches the current supported subset.
  • rewriteRequired means an upstream generator can usually normalize the code.
  • rejected means the code likely needs manual redesign or new compiler support.

Migration buckets help group work into areas such as array metadata, object model, field state, static dispatch, synchronization, exceptions, or type signatures.

Shape Inventory

Use bytecode shape inventory when you want to understand arbitrary compiled artifacts before deciding what to support:

AsmBytecodeShapeInventoryReport inventory = compiler
        .inventoryStructuredAsmArtifact(pathToClassesOrJar);

System.err.println(inventory.summaryLine());

Inventory is read-only. It is useful for planning a broader ASM parser because it counts risky JVM shapes without changing what JavaToGpu accepts today.

CI Report Files

Write a preflight report when CI should archive unsupported bytecode details:

compiler.writeStructuredAsmArtifactReport(
        pathToClassesOrJar,
        Path.of("build/reports/javatogpu-asm-preflight.properties")
);

Fail the build after writing the report:

compiler.writeAndRequireStructuredAsmArtifactReport(
        pathToClassesOrJar,
        Path.of("build/reports/javatogpu-asm-preflight.properties")
);

Use the combined snapshot when you want preflight failures, readiness, and shape inventory in one artifact:

compiler.writeAndRequireStructuredAsmArtifactSnapshot(
        pathToClassesOrJar,
        Path.of("build/reports/javatogpu-asm-artifact-snapshot.properties")
);

Gradle Preflight Example

Create a small Java entry point in your build tooling:

package buildsupport;

import net.sixik.ga_utils.javatogpu.frontend.GpuProgramCompiler;

import java.nio.file.Path;

public final class AsmPreflightMain {
    private AsmPreflightMain() {
    }

    public static void main(String[] args) throws Exception {
        if (args.length != 2) {
            throw new IllegalArgumentException("Usage: AsmPreflightMain <classes-or-jar> <report.properties>");
        }

        GpuProgramCompiler.createDefault().writeAndRequireStructuredAsmArtifactReport(
                Path.of(args[0]),
                Path.of(args[1])
        );
    }
}

Then wire it into Gradle:

tasks.register('javatogpuAsmPreflight', JavaExec) {
    dependsOn classes
    classpath = sourceSets.test.runtimeClasspath
    mainClass = 'buildsupport.AsmPreflightMain'
    args layout.buildDirectory.dir('classes/java/main').get().asFile.absolutePath,
            layout.buildDirectory.file('reports/javatogpu-asm-preflight.properties').get().asFile.absolutePath
}

check.dependsOn tasks.named('javatogpuAsmPreflight')

For packaged artifacts, make the task depend on jar and pass the jar path instead of the classes directory.

Best Practices

  • Keep bytecode boring and explicit.
  • Prefer static helper calls.
  • Pass lengths, dimensions, and flags explicitly instead of reading JVM metadata.
  • Flatten object state into parameters, structs, or packed buffers.
  • Run preflight in CI before attempting real compilation.
  • Treat ASM diagnostics as feedback for your generator, not as runtime failures.

Future Direction

A broader arbitrary-ASM parser is planned, but the current alpha contract stays conservative so integrations can generate predictable GPU-safe input.

Read Next