improved package names, split demos

This commit is contained in:
Parker TenBroeck 2025-05-05 12:30:33 -04:00
parent ecb18b417e
commit a577a825f8
27 changed files with 350 additions and 272 deletions

View file

@ -92,7 +92,7 @@ public class Socket implements AutoCloseable, Readable<IOException>, Writable<IO
public Future<Integer, IOException> write_all(ByteBuffer buffer){
var wrote = buffer.remaining();
return waker -> {
socket.write(buffer);
var nya = socket.write(buffer);
if(!buffer.hasRemaining()) return wrote;
SELECTOR.register(socket, SelectionKey.OP_WRITE, waker);
return Future.Pending.INSTANCE;
@ -103,6 +103,7 @@ public class Socket implements AutoCloseable, Readable<IOException>, Writable<IO
public Future<Integer, IOException> read(ByteBuffer buffer){
return waker -> {
var read = socket.read(buffer);
if(read == -1)throw new IOException("Reached end of stream");
if(read!=0) return read;
SELECTOR.register(socket, SelectionKey.OP_READ, waker);
return Future.Pending.INSTANCE;

View file

@ -0,0 +1,31 @@
package com.parkertenbroeck.bcms;
import com.parkertenbroeck.bcms.loadtime.StateMachineClassLoader;
import java.lang.reflect.Modifier;
import java.util.Set;
import static java.lang.StackWalker.Option.*;
public class RT {
public static void runWithStateMachines(StateMachineClassLoader.Config config, Object... params){
if(RT.class.getClassLoader() instanceof StateMachineClassLoader)return;
var loader = new StateMachineClassLoader(RT.class.getClassLoader(), config);
try{
StackWalker walker = StackWalker.getInstance(Set.of(RETAIN_CLASS_REFERENCE, SHOW_REFLECT_FRAMES, SHOW_HIDDEN_FRAMES));
var frame = walker.walk(s -> s.skip(1).findFirst()).get();
var clazzL = loader.loadClass(frame.getClassName());
var method = clazzL.getDeclaredMethod(frame.getMethodName(), frame.getMethodType().parameterArray());
if((method.getModifiers() & Modifier.STATIC) == 0){
method.invoke(clazzL.getConstructor().newInstance(), params);
}else{
method.invoke(null, params);
}
System.exit(0);
}catch (Exception e){
throw new RuntimeException(e);
}
}
}

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.instruction.LineNumber;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.*;
@ -30,7 +30,7 @@ public class FrameTracker {
ITEM_LONG_2ND = 13,
ITEM_DOUBLE_2ND = 14;
public static ArrayList<Frame> frames(StateMachineBuilder smb, CodeModel src_com) {
public static ArrayList<Frame> frames(StateMachineBuilder<?> smb, CodeModel src_com) {
var ft = new FrameTracker(smb, src_com);
var frames = new ArrayList<Frame>();
for(var coe : src_com){
@ -496,6 +496,16 @@ public class FrameTracker {
}
}
private void pushFromStackMapFrame(List<Type> list, Type type){
list.add(type);
if(type.tag() == Type.LONG_TYPE.tag()){
list.add(Type.LONG2_TYPE);
}
if(type.tag() == Type.DOUBLE2_TYPE.tag()){
list.add(Type.DOUBLE2_TYPE);
}
}
public void encounterLabel(Label l) {
if(annotationStartMap.get(l) instanceof ArrayList<LocalVariableAnnotation> list)
activeAnnotations.addAll(list);
@ -507,11 +517,11 @@ public class FrameTracker {
if (tmp != null) {
stack.clear();
locals.clear();
for( var sl : tmp.stack())
pushStack(Type.verificationType(sl, this));
for(var sl : tmp.stack())
pushFromStackMapFrame(stack, Type.verificationType(sl, this));
for( var sl : tmp.locals())
locals.add(Type.verificationType(sl, this));
for(var lv : tmp.locals())
pushFromStackMapFrame(locals, Type.verificationType(lv, this));
}
}
}

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.constant.ClassDesc;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
public enum ReplacementKind {
ImmediateReplacingPop,

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.TypeKind;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.CodeBuilder;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.CodeBuilder;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.Label;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import java.lang.classfile.*;
import java.lang.classfile.attribute.InnerClassInfo;
@ -65,8 +65,8 @@ public abstract class StateMachineBuilder<T extends StateMachineBuilder<T>> {
.replace("[", "_____")
)
.collect(Collectors.joining("$"));
innerClassName = method_name;
var name = cdn + "$" +innerClassName;
innerClassName = method_name + "______" + param_cnd;
var name = cdn + "$" + innerClassName;
this.CD_this = ClassDesc.of(src_clm.thisClass().asSymbol().packageName(), name);
this.params = mts.parameterArray();
@ -116,7 +116,7 @@ public abstract class StateMachineBuilder<T extends StateMachineBuilder<T>> {
if(shouldBeInnerClass()){
src_clm.findAttributes(Attributes.sourceFile()).forEach(clb::with);
clb.with(InnerClassesAttribute.of(InnerClassInfo.of(CD_this, Optional.of(src_clm.thisClass().asSymbol()), Optional.of(innerClassName), AccessFlag.PUBLIC)));
clb.with(InnerClassesAttribute.of(InnerClassInfo.of(CD_this, Optional.empty(), Optional.empty(), AccessFlag.PUBLIC)));
clb.with(NestHostAttribute.of(src_clm.thisClass()));
}
@ -128,7 +128,7 @@ public abstract class StateMachineBuilder<T extends StateMachineBuilder<T>> {
clb.withField(STATE_NAME, ConstantDescs.CD_int, ClassFile.ACC_PRIVATE);
// constructor
clb.withMethod(ConstantDescs.INIT_NAME, MTD_init, ClassFile.ACC_PUBLIC, mb -> mb.withCode(cob -> {
clb.withMethod(ConstantDescs.INIT_NAME, MTD_init, ClassFile.ACC_PRIVATE, mb -> mb.withCode(cob -> {
cob.aload(0).invokespecial(ConstantDescs.CD_Object, ConstantDescs.INIT_NAME, ConstantDescs.MTD_void);
params(1, (param, slot, type) -> {
cob.aload(0).loadLocal(TypeKind.from(type), slot).putfield(CD_this, param, type);

View file

@ -1,25 +1,65 @@
package com.parkertenbroeck.generators.loadtime;
package com.parkertenbroeck.bcms.loadtime;
import com.parkertenbroeck.future.Future;
import com.parkertenbroeck.gen.Gen;
import com.parkertenbroeck.generators.loadtime.future.FutureSMBuilder;
import com.parkertenbroeck.generators.loadtime.gen.GenSMBuilder;
import com.parkertenbroeck.generator.Gen;
import com.parkertenbroeck.bcms.loadtime.future.FutureSMBuilder;
import com.parkertenbroeck.bcms.loadtime.gen.GenSMBuilder;
import java.io.IOException;
import java.lang.classfile.*;
import java.lang.classfile.attribute.*;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
public class GeneratorClassLoader extends ClassLoader {
public class StateMachineClassLoader extends ClassLoader {
private final HashMap<String, Class<?>> customClazzMap = new HashMap<>();
private final List<String> skip;
private final HashMap<ClassDesc, SMBB> builders;
public GeneratorClassLoader(ClassLoader parent) {
public interface SMBB{
StateMachineBuilder<?> build(ClassModel src_clm, MethodModel src_mem, CodeModel src_com);
}
public static class Config{
HashSet<String> skip = new HashSet<>();
HashMap<ClassDesc, SMBB> builders = new HashMap<>();
public static Config empty(){
return new Config();
}
public static Config builtin(){
return empty()
.skip("java", "jdk", "jre", "com.parkertenbroeck.generators.loadtime")
.with(Future.class, FutureSMBuilder::new)
.with(Gen.class, GenSMBuilder::new);
}
public Config skip(String... paths){
skip.addAll(List.of(paths));
return this;
}
public Config with(Class<?> ret, SMBB builder){
builders.put(ClassDesc.ofDescriptor(ret.descriptorString()), builder);
return this;
}
public Config with(ClassDesc ret, SMBB builder){
builders.put(ret, builder);
return this;
}
}
public StateMachineClassLoader(ClassLoader parent) {
this(parent, Config.builtin());
}
public StateMachineClassLoader(ClassLoader parent, Config config) {
super(parent);
skip = config.skip.stream().toList();
builders = new HashMap<>(config.builders);
}
void add(String name, byte[] def){
@ -36,23 +76,23 @@ public class GeneratorClassLoader extends ClassLoader {
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (customClazzMap.get(name) instanceof Class<?> clazz)
return clazz;
if (name.startsWith("java"))
return super.loadClass(name);
for(var item : skip)
if(name.startsWith(item))
return super.loadClass(name);
var p = "/" + name.replace('.', '/') + ".class";
try (var stream = GeneratorClassLoader.class.getResourceAsStream(p)) {
try (var stream = StateMachineClassLoader.class.getResourceAsStream(p)) {
var bytes = Objects.requireNonNull(stream).readAllBytes();
add(name, searchReplaceMethods(bytes));
add(name, searchReplaceableMethods(bytes));
return customClazzMap.get(name);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
}
public byte[] searchReplaceMethods(byte[] in) {
public byte[] searchReplaceableMethods(byte[] in) {
var clm = ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES).parse(in);
var isGen = clm.thisClass().asSymbol().descriptorString().equals(Gen.class.descriptorString());
var isFuture = clm.thisClass().asSymbol().descriptorString().equals(Future.class.descriptorString());
var nestMem = new ArrayList<ClassDesc>();
@ -62,23 +102,21 @@ public class GeneratorClassLoader extends ClassLoader {
return ClassFile.of(ClassFile.AttributesProcessingOption.PASS_ALL_ATTRIBUTES, ClassFile.StackMapsOption.STACK_MAPS_WHEN_REQUIRED).build(clm.thisClass().asSymbol(), cb -> {
for (var ce : clm) {
if (ce instanceof MethodModel mem && !isGen && !isFuture && mem.code().isPresent()) {
StateMachineBuilder<?> builder;
if(mem.methodTypeSymbol().returnType().descriptorString().equals(Gen.class.descriptorString())){
builder = new GenSMBuilder(clm, mem, mem.code().get());
}else if(mem.methodTypeSymbol().returnType().descriptorString().equals(Future.class.descriptorString())){
builder = new FutureSMBuilder(clm, mem, mem.code().get());
}else{
builder= null;
}
if (ce instanceof MethodModel mem && mem.code().isPresent()) {
StateMachineBuilder<?> builder = builders
.getOrDefault(
mem.methodTypeSymbol().returnType(),
(_, _, _) -> null
).build(clm, mem, mem.code().get());
if(builder!=null&&builder.hasAnyHandlers()){
add(builder.CD_this.packageName() + "." + builder.CD_this.displayName(), builder.buildStateMachine());
cb.withMethod(mem.methodName(), mem.methodType(), mem.flags().flagsMask()&~ClassFile.ACC_SYNCHRONIZED, mb -> {
mb.withCode(builder::buildSourceMethodShim);
});
if(builder.shouldBeInnerClass()){
innerCl.add(InnerClassInfo.of(builder.CD_this, Optional.of(clm.thisClass().asSymbol()), Optional.of(builder.innerClassName)));
nestMem.add(ClassDesc.of(builder.CD_this.displayName()));
innerCl.add(InnerClassInfo.of(builder.CD_this, Optional.empty(), Optional.empty()));
nestMem.add(builder.CD_this);
}
}else{
cb.with(mem);

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.generators.loadtime.future;
package com.parkertenbroeck.bcms.loadtime.future;
import java.lang.annotation.*;

View file

@ -1,8 +1,8 @@
package com.parkertenbroeck.generators.loadtime.future;
package com.parkertenbroeck.bcms.loadtime.future;
import com.parkertenbroeck.future.Future;
import com.parkertenbroeck.future.Waker;
import com.parkertenbroeck.generators.loadtime.*;
import com.parkertenbroeck.bcms.loadtime.*;
import java.lang.classfile.*;
import java.lang.classfile.instruction.SwitchCase;

View file

@ -1,7 +1,7 @@
package com.parkertenbroeck.generators.loadtime.gen;
package com.parkertenbroeck.bcms.loadtime.gen;
import com.parkertenbroeck.gen.Gen;
import com.parkertenbroeck.generators.loadtime.*;
import com.parkertenbroeck.generator.Gen;
import com.parkertenbroeck.bcms.loadtime.*;
import java.lang.classfile.*;
import java.lang.constant.ClassDesc;

View file

@ -1,4 +1,4 @@
package com.parkertenbroeck.gen;
package com.parkertenbroeck.generator;
public interface Gen<Y, R> {
Res<Y, R> next();

View file

@ -1,15 +0,0 @@
package com.parkertenbroeck.generators;
import com.parkertenbroeck.generators.loadtime.GeneratorClassLoader;
public class RT {
public static void runWithGeneratorSupport(Class<? extends Runnable> clazz){
var loader = new GeneratorClassLoader(RT.class.getClassLoader());
try{
((Runnable)loader.loadClass(clazz.getName()).getConstructor().newInstance()).run();
}catch (Exception e){
throw new RuntimeException(e);
}
}
}