From b47d1a7576ae26396a4e2747f134267223698e20 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:53:36 +0200 Subject: [PATCH] refactor: remove StackData and Data usage --- src/me/topchetoeu/jscript/engine/Context.java | 62 +++++++++++++++-- src/me/topchetoeu/jscript/engine/Engine.java | 15 +++-- .../jscript/engine/Environment.java | 3 - .../topchetoeu/jscript/engine/StackData.java | 66 ------------------- .../jscript/engine/debug/SimpleDebugger.java | 7 +- .../jscript/engine/debug/WebSocket.java | 6 -- .../jscript/engine/values/CodeFunction.java | 5 +- .../jscript/lib/AsyncFunctionLib.java | 5 +- .../jscript/lib/AsyncGeneratorLib.java | 5 +- src/me/topchetoeu/jscript/lib/ErrorLib.java | 3 +- .../topchetoeu/jscript/lib/GeneratorLib.java | 5 +- 11 files changed, 75 insertions(+), 107 deletions(-) delete mode 100644 src/me/topchetoeu/jscript/engine/StackData.java diff --git a/src/me/topchetoeu/jscript/engine/Context.java b/src/me/topchetoeu/jscript/engine/Context.java index 0261737..fa46bbe 100644 --- a/src/me/topchetoeu/jscript/engine/Context.java +++ b/src/me/topchetoeu/jscript/engine/Context.java @@ -1,17 +1,23 @@ package me.topchetoeu.jscript.engine; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Stack; import java.util.TreeSet; import me.topchetoeu.jscript.Filename; import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.values.FunctionValue; import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.Values; +import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.parsing.Parsing; public class Context { private final Stack env = new Stack<>(); + private final ArrayList frames = new ArrayList<>(); public final Data data; public final Engine engine; @@ -48,16 +54,58 @@ public class Context { return res; } - public Context(Engine engine, Data data) { - this.data = new Data(engine.data); - if (data != null) this.data.addAll(data); + + public void pushFrame(CodeFrame frame) { + frames.add(frame); + if (frames.size() > engine.maxStackFrames) throw EngineException.ofRange("Stack overflow!"); + pushEnv(frame.function.environment); + } + public boolean popFrame(CodeFrame frame) { + if (frames.size() == 0) return false; + if (frames.get(frames.size() - 1) != frame) return false; + frames.remove(frames.size() - 1); + popEnv(); + engine.onFramePop(this, frame); + return true; + } + public CodeFrame peekFrame() { + if (frames.size() == 0) return null; + return frames.get(frames.size() - 1); + } + + public List frames() { + return Collections.unmodifiableList(frames); + } + public List stackTrace() { + var res = new ArrayList(); + + for (var i = frames.size() - 1; i >= 0; i--) { + var el = frames.get(i); + var name = el.function.name; + Location loc = null; + + for (var j = el.codePtr; j >= 0 && loc == null; j--) loc = el.function.body[j].location; + if (loc == null) loc = el.function.loc(); + + var trace = ""; + + if (loc != null) trace += "at " + loc.toString() + " "; + if (name != null && !name.equals("")) trace += "in " + name + " "; + + trace = trace.trim(); + + if (!trace.equals("")) res.add(trace); + } + + return res; + } + + public Context(Engine engine) { + this.data = new Data(); this.engine = engine; } - public Context(Engine engine) { - this(engine, (Data)null); - } public Context(Engine engine, Environment env) { - this(engine, (Data)null); + this(engine); this.pushEnv(env); } diff --git a/src/me/topchetoeu/jscript/engine/Engine.java b/src/me/topchetoeu/jscript/engine/Engine.java index 88a56ed..a48366f 100644 --- a/src/me/topchetoeu/jscript/engine/Engine.java +++ b/src/me/topchetoeu/jscript/engine/Engine.java @@ -53,17 +53,18 @@ public class Engine implements DebugController { private static int nextId = 0; public static final HashMap functions = new HashMap<>(); + public final int id = ++nextId; + public final boolean debugging; + public int maxStackFrames = 10000; + + private final HashMap sources = new HashMap<>(); + private final HashMap> bpts = new HashMap<>(); + + private DebugController debugger; private Thread thread; private LinkedBlockingDeque macroTasks = new LinkedBlockingDeque<>(); private LinkedBlockingDeque microTasks = new LinkedBlockingDeque<>(); - public final int id = ++nextId; - public final Data data = new Data().set(StackData.MAX_FRAMES, 10000); - public final boolean debugging; - private final HashMap sources = new HashMap<>(); - private final HashMap> bpts = new HashMap<>(); - private DebugController debugger; - public boolean attachDebugger(DebugController debugger) { if (!debugging || this.debugger != null) return false; diff --git a/src/me/topchetoeu/jscript/engine/Environment.java b/src/me/topchetoeu/jscript/engine/Environment.java index 5c2c4e2..397ec78 100644 --- a/src/me/topchetoeu/jscript/engine/Environment.java +++ b/src/me/topchetoeu/jscript/engine/Environment.java @@ -68,9 +68,6 @@ public class Environment { return res; } - public Context context(Engine engine, Data data) { - return new Context(engine, data).pushEnv(this); - } public Context context(Engine engine) { return new Context(engine).pushEnv(this); } diff --git a/src/me/topchetoeu/jscript/engine/StackData.java b/src/me/topchetoeu/jscript/engine/StackData.java deleted file mode 100644 index 9e42eca..0000000 --- a/src/me/topchetoeu/jscript/engine/StackData.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.topchetoeu.jscript.engine; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import me.topchetoeu.jscript.Location; -import me.topchetoeu.jscript.engine.debug.Debugger; -import me.topchetoeu.jscript.engine.frame.CodeFrame; -import me.topchetoeu.jscript.exceptions.EngineException; - -public class StackData { - public static final DataKey> FRAMES = new DataKey<>(); - public static final DataKey MAX_FRAMES = new DataKey<>(); - public static final DataKey DEBUGGER = new DataKey<>(); - - public static void pushFrame(Context ctx, CodeFrame frame) { - var frames = ctx.data.get(FRAMES, new ArrayList<>()); - frames.add(frame); - if (frames.size() > ctx.data.get(MAX_FRAMES, 10000)) - throw EngineException.ofRange("Stack overflow!"); - ctx.pushEnv(frame.function.environment); - } - public static boolean popFrame(Context ctx, CodeFrame frame) { - var frames = ctx.data.get(FRAMES, new ArrayList<>()); - if (frames.size() == 0) return false; - if (frames.get(frames.size() - 1) != frame) return false; - frames.remove(frames.size() - 1); - ctx.popEnv(); - ctx.engine.onFramePop(ctx, frame); - return true; - } - public static CodeFrame peekFrame(Context ctx) { - var frames = ctx.data.get(FRAMES, new ArrayList<>()); - if (frames.size() == 0) return null; - return frames.get(frames.size() - 1); - } - - public static List frames(Context ctx) { - return Collections.unmodifiableList(ctx.data.get(FRAMES, new ArrayList<>())); - } - public static List stackTrace(Context ctx) { - var res = new ArrayList(); - var frames = frames(ctx); - - for (var i = frames.size() - 1; i >= 0; i--) { - var el = frames.get(i); - var name = el.function.name; - Location loc = null; - - for (var j = el.codePtr; j >= 0 && loc == null; j--) loc = el.function.body[j].location; - if (loc == null) loc = el.function.loc(); - - var trace = ""; - - if (loc != null) trace += "at " + loc.toString() + " "; - if (name != null && !name.equals("")) trace += "in " + name + " "; - - trace = trace.trim(); - - if (!trace.equals("")) res.add(trace); - } - - return res; - } -} diff --git a/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java b/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java index c2d7c4a..bee5428 100644 --- a/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java +++ b/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java @@ -15,7 +15,6 @@ import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Instruction.Type; import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Engine; -import me.topchetoeu.jscript.engine.StackData; import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.scope.GlobalScope; @@ -187,7 +186,7 @@ public class SimpleDebugger implements Debugger { } private void updateFrames(Context ctx) { - var frame = StackData.peekFrame(ctx); + var frame = ctx.peekFrame(); if (frame == null) return; if (!codeFrameToFrame.containsKey(frame)) { @@ -202,7 +201,7 @@ public class SimpleDebugger implements Debugger { } private JSONList serializeFrames(Context ctx) { var res = new JSONList(); - var frames = StackData.frames(ctx); + var frames = ctx.frames(); for (var i = frames.size() - 1; i >= 0; i--) { res.add(codeFrameToFrame.get(frames.get(i)).serialized); @@ -782,7 +781,7 @@ public class SimpleDebugger implements Debugger { try { idToFrame.remove(codeFrameToFrame.remove(frame).id); } catch (NullPointerException e) { } - if (StackData.frames(ctx).size() == 0) resume(State.RESUMED); + if (ctx.frames().size() == 0) resume(State.RESUMED); else if (stepOutFrame != null && stepOutFrame.frame == frame && (state == State.STEPPING_OUT || state == State.STEPPING_IN || state == State.STEPPING_OVER) ) { diff --git a/src/me/topchetoeu/jscript/engine/debug/WebSocket.java b/src/me/topchetoeu/jscript/engine/debug/WebSocket.java index 253bf38..ea1eaef 100644 --- a/src/me/topchetoeu/jscript/engine/debug/WebSocket.java +++ b/src/me/topchetoeu/jscript/engine/debug/WebSocket.java @@ -118,8 +118,6 @@ public class WebSocket implements AutoCloseable { else send(msg.textData()); } public void send(Object data) { - // TODO: Remove - // System.out.println("SEND: " + data); if (closed) throw new IllegalStateException("Object is closed."); write(1, data.toString().getBytes()); } @@ -201,10 +199,6 @@ public class WebSocket implements AutoCloseable { if (!fin) continue; var raw = data.toByteArray(); - // TODO: Remove - // System.out.println("RECEIVED: " + new String(raw)); - - if (type == 1) return new WebSocketMessage(new String(raw)); else return new WebSocketMessage(raw); } diff --git a/src/me/topchetoeu/jscript/engine/values/CodeFunction.java b/src/me/topchetoeu/jscript/engine/values/CodeFunction.java index e2dc2bf..adc14d4 100644 --- a/src/me/topchetoeu/jscript/engine/values/CodeFunction.java +++ b/src/me/topchetoeu/jscript/engine/values/CodeFunction.java @@ -5,7 +5,6 @@ import me.topchetoeu.jscript.compilation.FunctionBody; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Environment; -import me.topchetoeu.jscript.engine.StackData; import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.scope.ValueVariable; @@ -35,7 +34,7 @@ public class CodeFunction extends FunctionValue { public Object call(Context ctx, Object thisArg, Object ...args) { var frame = new CodeFrame(ctx, thisArg, args, this); try { - StackData.pushFrame(ctx, frame); + ctx.pushFrame(frame); while (true) { var res = frame.next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, null); @@ -43,7 +42,7 @@ public class CodeFunction extends FunctionValue { } } finally { - StackData.popFrame(ctx, frame); + ctx.popFrame(frame); } } diff --git a/src/me/topchetoeu/jscript/lib/AsyncFunctionLib.java b/src/me/topchetoeu/jscript/lib/AsyncFunctionLib.java index ff248e4..c352a20 100644 --- a/src/me/topchetoeu/jscript/lib/AsyncFunctionLib.java +++ b/src/me/topchetoeu/jscript/lib/AsyncFunctionLib.java @@ -1,7 +1,6 @@ package me.topchetoeu.jscript.lib; import me.topchetoeu.jscript.engine.Context; -import me.topchetoeu.jscript.engine.StackData; import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.values.CodeFunction; @@ -21,7 +20,7 @@ import me.topchetoeu.jscript.interop.Native; private void next(Context ctx, Object inducedValue, Object inducedError) { Object res = null; - StackData.pushFrame(ctx, frame); + ctx.pushFrame(frame); ctx.pushEnv(frame.function.environment); awaiting = false; @@ -40,7 +39,7 @@ import me.topchetoeu.jscript.interop.Native; } } - StackData.popFrame(ctx, frame); + ctx.popFrame(frame); if (awaiting) { PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject)); diff --git a/src/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java b/src/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java index 7f2e78c..0a2dd47 100644 --- a/src/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java +++ b/src/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java @@ -3,7 +3,6 @@ package me.topchetoeu.jscript.lib; import java.util.Map; import me.topchetoeu.jscript.engine.Context; -import me.topchetoeu.jscript.engine.StackData; import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.values.NativeFunction; @@ -29,7 +28,7 @@ import me.topchetoeu.jscript.interop.Native; } Object res = null; - StackData.pushFrame(ctx, frame); + ctx.pushFrame(frame); state = 0; while (state == 0) { @@ -50,7 +49,7 @@ import me.topchetoeu.jscript.interop.Native; } } - StackData.popFrame(ctx, frame); + ctx.popFrame(frame); if (state == 1) { PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject)); diff --git a/src/me/topchetoeu/jscript/lib/ErrorLib.java b/src/me/topchetoeu/jscript/lib/ErrorLib.java index e33cf1a..6952e97 100644 --- a/src/me/topchetoeu/jscript/lib/ErrorLib.java +++ b/src/me/topchetoeu/jscript/lib/ErrorLib.java @@ -2,7 +2,6 @@ package me.topchetoeu.jscript.lib; import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Environment; -import me.topchetoeu.jscript.engine.StackData; import me.topchetoeu.jscript.engine.values.ArrayValue; import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.Values; @@ -51,7 +50,7 @@ import me.topchetoeu.jscript.interop.NativeInit; var target = new ObjectValue(); if (thisArg instanceof ObjectValue) target = (ObjectValue)thisArg; - target.defineProperty(ctx, "stack", ArrayValue.of(ctx, StackData.stackTrace(ctx))); + target.defineProperty(ctx, "stack", ArrayValue.of(ctx, ctx.stackTrace())); target.defineProperty(ctx, "name", "Error"); if (message == null) target.defineProperty(ctx, "message", ""); else target.defineProperty(ctx, "message", Values.toString(ctx, message)); diff --git a/src/me/topchetoeu/jscript/lib/GeneratorLib.java b/src/me/topchetoeu/jscript/lib/GeneratorLib.java index 6f055a7..9df2175 100644 --- a/src/me/topchetoeu/jscript/lib/GeneratorLib.java +++ b/src/me/topchetoeu/jscript/lib/GeneratorLib.java @@ -1,7 +1,6 @@ package me.topchetoeu.jscript.lib; import me.topchetoeu.jscript.engine.Context; -import me.topchetoeu.jscript.engine.StackData; import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.values.ObjectValue; @@ -25,7 +24,7 @@ import me.topchetoeu.jscript.interop.Native; } Object res = null; - StackData.pushFrame(ctx, frame); + ctx.pushFrame(frame); yielding = false; while (!yielding) { @@ -43,7 +42,7 @@ import me.topchetoeu.jscript.interop.Native; } } - StackData.popFrame(ctx, frame); + ctx.popFrame(frame); if (done) frame = null; else res = frame.pop();