diff --git a/src/Examples.java b/src/Examples.java index 4aabe1d..2608754 100644 --- a/src/Examples.java +++ b/src/Examples.java @@ -1,10 +1,11 @@ import async_example.Delay; -import async_example.Jokio; import async_example.Socket; import generator.future.Future; import generator.future.Waker; import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; public class Examples { // public static Gen parse(String str){ @@ -83,10 +84,29 @@ public class Examples { return Future.ret(value); } + public Future send(ByteBuffer buffer, Socket socket){ + String message = "hello world!\n"; + buffer.limit(message.length()).put(message.getBytes(StandardCharsets.UTF_8)).position(0); + var wrote = socket.write_all(buffer).await(); + buffer.clear().limit(wrote); + var read = socket.read_all(buffer).await(); + System.out.println(new String(buffer.array(), 0, read)); + + return Future.ret(null); + } + public Future awaitTest(int number){ - var result = number(10).await()+number(20).await(); - Jokio.runtime().await().spawn(awaitTest2(5000)); - return Future.ret(""+result); +// var result = number(10).await()+number(20).await(); +// Jokio.runtime().await().spawn(awaitTest2(5000)); + + var buffer = ByteBuffer.allocate(500); + try(var socket = Socket.connect(new InetSocketAddress("45.79.112.203", 4242)).await()){ + send(buffer, socket).await(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return Future.ret(""); } public Future closing(int number){ diff --git a/src/async_example/Socket.java b/src/async_example/Socket.java index 23f772e..3b0d553 100644 --- a/src/async_example/Socket.java +++ b/src/async_example/Socket.java @@ -5,48 +5,71 @@ import generator.future.Waker; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; +import java.util.ArrayDeque; public class Socket implements AutoCloseable{ - private final static Selector selector; - + private final static Selector SELECTOR; + private record ToRegister(SocketChannel sc, int ops, Waker waker){} + private final static ArrayDeque to_register = new ArrayDeque<>(); static{ try { - selector = Selector.open(); + SELECTOR = Selector.open(); } catch (IOException e) { throw new RuntimeException(e); } - new Thread(() -> { + var thread = new Thread(() -> { while(!Thread.currentThread().isInterrupted()){ try{ - selector.select(); - var keys = selector.selectedKeys().iterator(); + synchronized (to_register){ + while(!to_register.isEmpty()){ + var to = to_register.poll(); + to.sc.register(SELECTOR, to.ops, to.waker); + } + } + + SELECTOR.select(); + var keys = SELECTOR.selectedKeys().iterator(); while (keys.hasNext()) { SelectionKey key = keys.next(); keys.remove(); + var c = (SocketChannel)key.channel(); + var w = (Waker)key.attachment(); + System.out.println(key); if (!key.isValid()) { - - }else if(key.isAcceptable()){ + } + if(key.isAcceptable()){ }else if(key.isConnectable()){ - + c.finishConnect(); }else if(key.isReadable()){ - }else if(key.isWritable()){ } + w.wake(); } }catch (Exception e){ e.printStackTrace(); } } - }).start(); + }); + thread.setName("Socket Polling Thread"); + thread.setDaemon(true); + thread.start(); + } + + private static void register(SocketChannel sc, int ops, Waker waker){ + synchronized (to_register){ + to_register.add(new ToRegister(sc, ops, waker)); + } + SELECTOR.wakeup(); } private final SocketChannel socket; @@ -55,25 +78,84 @@ public class Socket implements AutoCloseable{ this.socket = sc; } - public static Future bind(InetSocketAddress inet) throws IOException{ - var socket = SocketChannel.open(); + public static Future connect(InetSocketAddress inet) { return new Future<>() { + public SocketChannel socket; @Override - public Socket poll(Waker waker) { - try{ - socket.configureBlocking(false); - socket.socket().bind(new InetSocketAddress("localhost", 8080)); - socket.register(selector, SelectionKey.OP_ACCEPT | SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE); - return new Socket(socket); - }catch (Exception e){ - throw new RuntimeException(e); + public Object poll(Waker waker) { + if(socket==null){ + try{ + socket = SocketChannel.open(); + socket.configureBlocking(false); + var connected = socket.connect(inet); + if(!connected) { + register(socket, SelectionKey.OP_CONNECT, waker); + return Pending.INSTANCE; + } + }catch (Exception e){ + throw new RuntimeException(e); + } } + if(socket.isConnected()) return new Socket(socket); + return Pending.INSTANCE; } @Override public void cancel() { try { - socket.close(); + if(socket!=null) socket.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + } + + public Future write_all(ByteBuffer buffer){ + return new Future<>() { + int wrote = 0; + @Override + public Object poll(Waker waker) { + try { + wrote += socket.write(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + if(!buffer.hasRemaining()) return wrote; + register(socket, SelectionKey.OP_WRITE, waker); + return Pending.INSTANCE; + } + + @Override + public void cancel() { + try { + if(socket!=null) socket.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + } + + public Future read_all(ByteBuffer buffer){ + return new Future<>() { + int read = 0; + @Override + public Object poll(Waker waker) { + try { + read += socket.read(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + if(!buffer.hasRemaining()) return read; + register(socket, SelectionKey.OP_READ, waker); + return Pending.INSTANCE; + } + + @Override + public void cancel() { + try { + if(socket!=null) socket.close(); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/generator/runtime/Frame.java b/src/generator/runtime/Frame.java index fd10614..104ebee 100644 --- a/src/generator/runtime/Frame.java +++ b/src/generator/runtime/Frame.java @@ -2,6 +2,7 @@ package generator.runtime; import java.lang.classfile.CodeBuilder; import java.lang.classfile.TypeKind; +import java.lang.constant.ConstantDescs; import java.util.Arrays; public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack) { @@ -16,6 +17,7 @@ public record Frame(FrameTracker.Type[] locals, FrameTracker.Type[] stack) { for (var entry : locals) { slot++; if (slot <= loc_off) continue; + if (entry.isCategory2_2nd()) continue; sst.save_local(smb, cob, entry.toCD(), slot - smb.paramSlotOff + loc_off - 1); diff --git a/src/generator/runtime/FrameTracker.java b/src/generator/runtime/FrameTracker.java index 750043c..aab666d 100644 --- a/src/generator/runtime/FrameTracker.java +++ b/src/generator/runtime/FrameTracker.java @@ -7,7 +7,11 @@ import java.lang.classfile.attribute.StackMapFrameInfo; import java.lang.classfile.attribute.StackMapTableAttribute; import java.lang.classfile.instruction.*; import java.lang.constant.ClassDesc; +import java.lang.constant.DynamicConstantDesc; +import java.lang.constant.MethodHandleDesc; +import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Objects; @@ -310,10 +314,29 @@ public class FrameTracker { case BranchInstruction b when b.opcode() == Opcode.GOTO || b.opcode() == Opcode.GOTO_W -> {} case BranchInstruction b -> popStack(); case ConstantInstruction c when ins.opcode() == Opcode.ACONST_NULL -> pushStack(Type.NULL_TYPE); - case ConstantInstruction c -> pushStack(c.typeKind().upperBound()); + case ConstantInstruction c -> { + switch(c.constantValue()){ + case Double _ -> pushStack(Type.DOUBLE_TYPE); + case Float _ -> pushStack(Type.FLOAT_TYPE); + case Integer _ -> pushStack(Type.INTEGER_TYPE); + case Long _ -> pushStack(Type.LONG_TYPE); + case String _ -> pushStack(Type.STRING_TYPE); + case ClassDesc desc -> pushStack(desc); + case DynamicConstantDesc dynamicConstantDesc -> pushStack(dynamicConstantDesc.constantType()); + case MethodHandleDesc methodHandleDesc -> + throw new RuntimeException(); + case MethodTypeDesc methodTypeDesc -> + throw new RuntimeException(); + } + } case ConvertInstruction c -> decStack(c.fromType().slotSize()).pushStack(c.toType().upperBound()); case FieldInstruction f -> { - + switch(f.opcode()){ + case GETFIELD -> decStack(1).pushStack(f.typeSymbol()); + case GETSTATIC -> pushStack(f.typeSymbol()); + case PUTFIELD -> decStack(1 + TypeKind.from(f.typeSymbol()).slotSize()); + case PUTSTATIC -> decStack(TypeKind.from(f.typeSymbol()).slotSize()); + } } case IncrementInstruction i -> {} case InvokeDynamicInstruction i -> { @@ -334,6 +357,9 @@ public class FrameTracker { case InvokeInstruction i -> { for(var param : i.typeSymbol().parameterArray()) decStack(TypeKind.from(param).slotSize()); + if(stack.isEmpty()){ + System.out.println(Arrays.toString(i.typeSymbol().parameterArray())); + } popStack(); pushStack(i.typeSymbol().returnType()); } @@ -449,8 +475,16 @@ public class FrameTracker { locals.clear(); for( var sl : tmp.stack()) pushStack(Type.verificationType(sl)); - for( var local : tmp.locals()) - locals.add(Type.verificationType(local)); + + for( var sl : tmp.locals()) + locals.add(Type.verificationType(sl)); + +// while(locals.size()>tmp.locals().size())locals.removeLast(); +// while(locals.size() TypeKind.from(p).slotSize()).sum(); + System.out.println("FRAME"); var lt = new FrameTracker(this, src_com); for(var coe : src_com){ - if(coe instanceof Instruction) + if(coe instanceof Instruction) { frames.add(new Frame(lt.locals(), lt.stack())); + System.out.println(frames.getLast() + " " + coe); + } lt.encounter(coe); + } frames.add(new Frame(lt.locals(), lt.stack())); - - for(var wf : with_frames()){ - if(wf.coe instanceof Instruction) - System.out.println(wf.coe() + " " + wf.frame()); - } } public record WithFrame(CodeElement coe, Frame frame){}