From e84645ab273b3ee27ab29c5afa787e1eb93ae3af Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 27 Jul 2022 18:10:20 +0200 Subject: [PATCH 01/20] added update class message and first faulty implementation of it --- src/tools/debugger/FrontendConnector.java | 17 ++++++++++++++++ .../RuntimeReflectionRegistration.java | 18 ++--------------- src/tools/debugger/message/UpdateClass.java | 20 +++++++++++++++++++ 3 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 src/tools/debugger/message/UpdateClass.java diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index 98522f88fb..449f6fbfca 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -1,5 +1,6 @@ package tools.debugger; +import java.io.File; import java.io.IOException; import java.net.BindException; import java.net.InetSocketAddress; @@ -24,6 +25,10 @@ import bd.source.SourceCoordinate; import bd.source.TaggedSourceCoordinate; +import som.VM; +import som.compiler.MixinDefinition; +import som.interpreter.SomLanguage; +import som.vm.ObjectSystem; import som.vm.VmSettings; import som.vmobjects.SSymbol; import tools.Tagging; @@ -189,6 +194,7 @@ private void ensureConnectionIsAvailable() { private static TaggedSourceCoordinate[] createSourceSections(final Source source, final Map>>> sourcesTags, final Instrumenter instrumenter, final Set rootNodes) { + Set sections = new HashSet<>(); Map>> tagsForSections = sourcesTags.get(source); @@ -349,4 +355,15 @@ private void closeAllSockets() { traceHandler.stop(delay); } catch (InterruptedException e) {} } + + // Code Uptading stuff + public void updateClass(String filePath) { + try { + this.get + MixinDefinition newMethod = webDebugger.vm.getProcessPool() + System.out.println(newMethod.getName().toString()); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/src/tools/debugger/RuntimeReflectionRegistration.java b/src/tools/debugger/RuntimeReflectionRegistration.java index d32b04da11..8d2a3a62e8 100644 --- a/src/tools/debugger/RuntimeReflectionRegistration.java +++ b/src/tools/debugger/RuntimeReflectionRegistration.java @@ -13,24 +13,9 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import tools.debugger.message.InitializationResponse; -import tools.debugger.message.InitializeConnection; +import tools.debugger.message.*; import tools.debugger.message.Message.IncommingMessage; import tools.debugger.message.Message.OutgoingMessage; -import tools.debugger.message.ProgramInfoRequest; -import tools.debugger.message.ProgramInfoResponse; -import tools.debugger.message.ScopesRequest; -import tools.debugger.message.ScopesResponse; -import tools.debugger.message.SourceMessage; -import tools.debugger.message.StackTraceRequest; -import tools.debugger.message.StackTraceResponse; -import tools.debugger.message.StepMessage; -import tools.debugger.message.StoppedMessage; -import tools.debugger.message.SymbolMessage; -import tools.debugger.message.TraceDataRequest; -import tools.debugger.message.UpdateBreakpoint; -import tools.debugger.message.VariablesRequest; -import tools.debugger.message.VariablesResponse; import tools.debugger.session.BreakpointInfo; import tools.debugger.session.LineBreakpoint; import tools.debugger.session.SectionBreakpoint; @@ -89,6 +74,7 @@ public void register(final String name, final Class klass) { inMsgs.register(VariablesRequest.class); inMsgs.register(ProgramInfoRequest.class); inMsgs.register(TraceDataRequest.class); + inMsgs.register(UpdateClass.class); ClassGroup bps = new ClassGroup(BreakpointInfo.class, "type", true); bps.register(LineBreakpoint.class); diff --git a/src/tools/debugger/message/UpdateClass.java b/src/tools/debugger/message/UpdateClass.java new file mode 100644 index 0000000000..13b76787c5 --- /dev/null +++ b/src/tools/debugger/message/UpdateClass.java @@ -0,0 +1,20 @@ +package tools.debugger.message; + +import org.java_websocket.WebSocket; +import tools.debugger.FrontendConnector; +import tools.debugger.message.Message.IncommingMessage; + + +public class UpdateClass extends IncommingMessage { + private final String classToRecompile ; + + public UpdateClass(String classToRecompile) { + this.classToRecompile = classToRecompile; + } + + @Override public void process(FrontendConnector connector, WebSocket conn) { + connector.updateClass(classToRecompile); + System.out.println("Done Recompilation"); + System.out.println(classToRecompile); + } +} From b9a37cae709d9bc46b33b59f0429bf36a7393bfa Mon Sep 17 00:00:00 2001 From: matteo Date: Fri, 29 Jul 2022 11:15:05 +0200 Subject: [PATCH 02/20] moved calls to application thread but still trying to fetch correct class object --- src/som/VM.java | 6 +++ src/tools/debugger/FrontendConnector.java | 27 ++++++++--- .../frontend/ApplicationThreadTask.java | 4 +- src/tools/debugger/frontend/Suspension.java | 2 +- src/tools/debugger/message/UpdateClass.java | 48 ++++++++++++++++++- 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/som/VM.java b/src/som/VM.java index 90f5e59fc2..f71075c633 100644 --- a/src/som/VM.java +++ b/src/som/VM.java @@ -409,6 +409,8 @@ public void setupInstruments(final Env env) { : "Currently, CandidateIdentifer and Snapshots are not compatible"; structuralProbe = SnapshotBackend.getProbe(); } + + System.out.println(structuralProbe); } public SClass loadExtensionModule(final String filename) { @@ -443,4 +445,8 @@ public static void resetClassReferences(final boolean callFromUnitTest) { ChannelPrimitives.resetClassReferences(); } + + public StructuralProbe getStructuralProbe(){ + return objectSystem.getStructuralProbe(); + } } diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index 449f6fbfca..d122aef1cc 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -5,10 +5,7 @@ import java.net.BindException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Function; @@ -25,11 +22,15 @@ import bd.source.SourceCoordinate; import bd.source.TaggedSourceCoordinate; +import bd.tools.structure.StructuralProbe; import som.VM; import som.compiler.MixinDefinition; +import som.compiler.Variable; import som.interpreter.SomLanguage; import som.vm.ObjectSystem; import som.vm.VmSettings; +import som.vmobjects.SClass; +import som.vmobjects.SInvokable; import som.vmobjects.SSymbol; import tools.Tagging; import tools.TraceData; @@ -61,6 +62,8 @@ import tools.debugger.session.Breakpoints; import tools.debugger.session.LineBreakpoint; +import java.util.function.Consumer; + /** * Connect the debugger to the UI front-end. @@ -359,9 +362,19 @@ private void closeAllSockets() { // Code Uptading stuff public void updateClass(String filePath) { try { - this.get - MixinDefinition newMethod = webDebugger.vm.getProcessPool() - System.out.println(newMethod.getName().toString()); + VM vm = webDebugger.vm; + MixinDefinition newModule = vm.loadModule(filePath); + System.out.println(newModule.getName().toString()); + StructuralProbe structuralProbe = vm.getStructuralProbe(); + Iterator it = structuralProbe.getClasses().iterator(); + while (it.hasNext()) { + MixinDefinition klass = it.next(); + if(klass == newModule){ + System.out.println("FOUND"); + System.out.println(klass.getIdentifier()); + System.out.println(newModule.getIdentifier()); + } + } } catch (IOException e) { e.printStackTrace(); } diff --git a/src/tools/debugger/frontend/ApplicationThreadTask.java b/src/tools/debugger/frontend/ApplicationThreadTask.java index 2b16e20454..3396b7e1df 100644 --- a/src/tools/debugger/frontend/ApplicationThreadTask.java +++ b/src/tools/debugger/frontend/ApplicationThreadTask.java @@ -7,11 +7,11 @@ * A task that needs to be executed by the application thread while it is in a * {@link Suspension}. */ -abstract class ApplicationThreadTask { +abstract public class ApplicationThreadTask { /** * @return continue waiting on true, resume execution on false. */ - abstract boolean execute(); + protected abstract boolean execute(); static class Resume extends ApplicationThreadTask { @Override diff --git a/src/tools/debugger/frontend/Suspension.java b/src/tools/debugger/frontend/Suspension.java index d701cf4362..491ca2684b 100644 --- a/src/tools/debugger/frontend/Suspension.java +++ b/src/tools/debugger/frontend/Suspension.java @@ -132,7 +132,7 @@ public void sendVariables(final long varRef, final FrontendConnector frontend, frontend.sendVariables(varRef, requestId, this, filter, start, count); } - private void submitTask(final ApplicationThreadTask task) { + public void submitTask(final ApplicationThreadTask task) { try { tasks.put(task); } catch (InterruptedException e) { diff --git a/src/tools/debugger/message/UpdateClass.java b/src/tools/debugger/message/UpdateClass.java index 13b76787c5..63a81af086 100644 --- a/src/tools/debugger/message/UpdateClass.java +++ b/src/tools/debugger/message/UpdateClass.java @@ -1,8 +1,16 @@ package tools.debugger.message; +import com.oracle.truffle.api.debug.DebugStackFrame; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameInstance; +import com.oracle.truffle.api.nodes.RootNode; import org.java_websocket.WebSocket; +import som.interpreter.SomLanguage; import tools.debugger.FrontendConnector; +import tools.debugger.frontend.ApplicationThreadTask; +import tools.debugger.frontend.Suspension; import tools.debugger.message.Message.IncommingMessage; +import tools.debugger.frontend.ApplicationThreadTask; public class UpdateClass extends IncommingMessage { @@ -13,8 +21,46 @@ public UpdateClass(String classToRecompile) { } @Override public void process(FrontendConnector connector, WebSocket conn) { - connector.updateClass(classToRecompile); + Suspension suspension = connector.getSuspension(0); + UpdateClassTask updateTask = new UpdateClassTask(connector,suspension,classToRecompile); + suspension.submitTask(updateTask); + + //suspension.resume(); + //connector.updateClass(classToRecompile); System.out.println("Done Recompilation"); System.out.println(classToRecompile); } + + private class UpdateClassTask extends ApplicationThreadTask { + + private final FrontendConnector frontend; + private final Suspension suspension; + private final String filePath; + + UpdateClassTask(final FrontendConnector frontend, final Suspension suspension, String filePath) { + this.frontend = frontend; + this.suspension = suspension; + this.filePath = filePath; + + } + + @Override + public boolean execute() { + frontend.updateClass(filePath); + suspension.getEvent().prepareUnwindFrame(suspension.getFrame(2)); + suspension.resume(); + System.out.println(suspension.getEvent().getTopStackFrame().getName()); + +// RootNode node = suspension.getStackFrames().get(2).getRawNode(SomLanguage.class).getRootNode(); +// +// System.out.println(node.getName()); +// System.out.println(node.getCallTarget().); +// DebugStackFrame frame = suspension.getStackFrames().get(2); +// System.out.println(frame.getName()); +// Frame realFrame = frame.getRawFrame(SomLanguage.class, FrameInstance.FrameAccess.READ_ONLY); +// System.out.println("GOT REAL FRAME"); +// + return true; + } + } } From d8f52dac6a282990cf7474f33e1504f950596fb9 Mon Sep 17 00:00:00 2001 From: matteo Date: Fri, 29 Jul 2022 15:34:47 +0200 Subject: [PATCH 03/20] added intellij profile in build.xml --- build.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.xml b/build.xml index 3fec34f04a..d72c556f47 100644 --- a/build.xml +++ b/build.xml @@ -529,4 +529,14 @@ kernel: ${kernel} + + + + + + + + + + From bd2a05c3ed3c1f8a2ebf90730a95b2d1091148aa Mon Sep 17 00:00:00 2001 From: matteo Date: Fri, 29 Jul 2022 15:36:23 +0200 Subject: [PATCH 04/20] recompiling same module now substitutes invokables of old module with invokable of new module --- src/som/VM.java | 2 +- src/som/compiler/MixinDefinition.java | 1 + src/som/compiler/SourcecodeCompiler.java | 8 +++++ src/som/vm/ObjectSystem.java | 7 ++++- src/tools/debugger/FrontendConnector.java | 34 +++++++++++++++------ src/tools/debugger/message/UpdateClass.java | 11 +++++-- 6 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/som/VM.java b/src/som/VM.java index f71075c633..44e74f8e6d 100644 --- a/src/som/VM.java +++ b/src/som/VM.java @@ -447,6 +447,6 @@ public static void resetClassReferences(final boolean callFromUnitTest) { } public StructuralProbe getStructuralProbe(){ - return objectSystem.getStructuralProbe(); + return structuralProbe; } } diff --git a/src/som/compiler/MixinDefinition.java b/src/som/compiler/MixinDefinition.java index c12ad50eac..3740e6ac91 100644 --- a/src/som/compiler/MixinDefinition.java +++ b/src/som/compiler/MixinDefinition.java @@ -907,4 +907,5 @@ public SSymbol getIdentifier() { return identifier; } + } diff --git a/src/som/compiler/SourcecodeCompiler.java b/src/som/compiler/SourcecodeCompiler.java index 0d26ffad21..6a4ce6b8eb 100644 --- a/src/som/compiler/SourcecodeCompiler.java +++ b/src/som/compiler/SourcecodeCompiler.java @@ -62,4 +62,12 @@ protected final MixinDefinition compile(final Parser parser, language.getVM().reportLoadedSource(source); return result; } + + public MixinDefinition recompileModule(Source source, StructuralProbe structuralProbe) throws ProgramDefinitionError { + Parser parser = new Parser(source.getCharacters().toString(), source, null, language); + int coord = parser.getStartIndex(); + MixinBuilder mxnBuilder = parser.moduleDeclaration(); + MixinDefinition result = mxnBuilder.assemble(parser.getSource(coord)); + return result; + } } diff --git a/src/som/vm/ObjectSystem.java b/src/som/vm/ObjectSystem.java index abf9a8ce35..0714f87885 100644 --- a/src/som/vm/ObjectSystem.java +++ b/src/som/vm/ObjectSystem.java @@ -153,7 +153,12 @@ public MixinDefinition loadModule(final String filename) throws IOException { public MixinDefinition loadModule(final Source source) throws IOException { URI uri = source.getURI(); if (loadedModules.containsKey(uri)) { - return loadedModules.get(uri); + System.out.println("UPDATING MODULE"); + try { + return compiler.recompileModule(source,null); + } catch (ProgramDefinitionError programDefinitionError) { + programDefinitionError.printStackTrace(); + } } MixinDefinition module; diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index d122aef1cc..723fb2eac3 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -5,11 +5,15 @@ import java.net.BindException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Function; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; import org.java_websocket.WebSocket; import com.google.gson.Gson; @@ -27,6 +31,7 @@ import som.compiler.MixinDefinition; import som.compiler.Variable; import som.interpreter.SomLanguage; +import som.interpreter.nodes.dispatch.Dispatchable; import som.vm.ObjectSystem; import som.vm.VmSettings; import som.vmobjects.SClass; @@ -363,18 +368,29 @@ private void closeAllSockets() { public void updateClass(String filePath) { try { VM vm = webDebugger.vm; - MixinDefinition newModule = vm.loadModule(filePath); - System.out.println(newModule.getName().toString()); StructuralProbe structuralProbe = vm.getStructuralProbe(); - Iterator it = structuralProbe.getClasses().iterator(); - while (it.hasNext()) { - MixinDefinition klass = it.next(); - if(klass == newModule){ - System.out.println("FOUND"); - System.out.println(klass.getIdentifier()); - System.out.println(newModule.getIdentifier()); + EconomicSet modules = structuralProbe.getClasses(); + MixinDefinition oldModule = null; + Path newSource = Paths.get(VmSettings.BASE_DIRECTORY).toAbsolutePath().relativize(Path.of(filePath)); + for(MixinDefinition module : modules ) { + if(module.getIdentifier().getString().split(":")[0].equals(newSource.toString())) { + oldModule = module; } } + MixinDefinition newModule = vm.loadModule(filePath); + System.out.println(newModule.getName().toString()); + EconomicMap oldMethods = oldModule.getInstanceDispatchables(); + oldMethods.putAll(newModule.getInstanceDispatchables()); + System.out.println("SUBSTITUTED METHODS IN MODULE"); +// Iterator it = structuralProbe.getClasses().iterator(); +// while (it.hasNext()) { +// MixinDefinition klass = it.next(); +// if (klass.getName().equals(newModule.getName())) { +// System.out.println("FOUND"); +// System.out.println(klass.getIdentifier()); +// System.out.println(newModule.getIdentifier()); +// } +// } } catch (IOException e) { e.printStackTrace(); } diff --git a/src/tools/debugger/message/UpdateClass.java b/src/tools/debugger/message/UpdateClass.java index 63a81af086..ac1c94c957 100644 --- a/src/tools/debugger/message/UpdateClass.java +++ b/src/tools/debugger/message/UpdateClass.java @@ -12,6 +12,8 @@ import tools.debugger.message.Message.IncommingMessage; import tools.debugger.frontend.ApplicationThreadTask; +import java.util.ArrayList; + public class UpdateClass extends IncommingMessage { private final String classToRecompile ; @@ -47,9 +49,12 @@ private class UpdateClassTask extends ApplicationThreadTask { @Override public boolean execute() { frontend.updateClass(filePath); - suspension.getEvent().prepareUnwindFrame(suspension.getFrame(2)); - suspension.resume(); - System.out.println(suspension.getEvent().getTopStackFrame().getName()); + ArrayList frames = suspension.getStackFrames(); + int a = 1 + 1; + System.out.println(a); + //suspension.getEvent().prepareUnwindFrame(suspension.getFrame(2)); + //suspension.resume(); + // System.out.println(suspension.getEvent().getTopStackFrame().getName()); // RootNode node = suspension.getStackFrames().get(2).getRawNode(SomLanguage.class).getRootNode(); // From 10858126db2256682c0736bbc49cfbd9263fa805 Mon Sep 17 00:00:00 2001 From: matteo Date: Fri, 29 Jul 2022 16:09:23 +0200 Subject: [PATCH 05/20] trying to figure out how to update --- src/tools/debugger/FrontendConnector.java | 13 +++---------- src/tools/debugger/message/UpdateClass.java | 9 +++++---- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index 723fb2eac3..5526204dba 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -365,7 +365,7 @@ private void closeAllSockets() { } // Code Uptading stuff - public void updateClass(String filePath) { + public MixinDefinition updateClass(String filePath) { try { VM vm = webDebugger.vm; StructuralProbe structuralProbe = vm.getStructuralProbe(); @@ -382,17 +382,10 @@ public void updateClass(String filePath) { EconomicMap oldMethods = oldModule.getInstanceDispatchables(); oldMethods.putAll(newModule.getInstanceDispatchables()); System.out.println("SUBSTITUTED METHODS IN MODULE"); -// Iterator it = structuralProbe.getClasses().iterator(); -// while (it.hasNext()) { -// MixinDefinition klass = it.next(); -// if (klass.getName().equals(newModule.getName())) { -// System.out.println("FOUND"); -// System.out.println(klass.getIdentifier()); -// System.out.println(newModule.getIdentifier()); -// } -// } + return oldModule; } catch (IOException e) { e.printStackTrace(); + return null; } } } diff --git a/src/tools/debugger/message/UpdateClass.java b/src/tools/debugger/message/UpdateClass.java index ac1c94c957..e14d0a751f 100644 --- a/src/tools/debugger/message/UpdateClass.java +++ b/src/tools/debugger/message/UpdateClass.java @@ -5,6 +5,7 @@ import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.nodes.RootNode; import org.java_websocket.WebSocket; +import som.compiler.MixinDefinition; import som.interpreter.SomLanguage; import tools.debugger.FrontendConnector; import tools.debugger.frontend.ApplicationThreadTask; @@ -48,13 +49,13 @@ private class UpdateClassTask extends ApplicationThreadTask { @Override public boolean execute() { - frontend.updateClass(filePath); + MixinDefinition updatedModule = frontend.updateClass(filePath); ArrayList frames = suspension.getStackFrames(); - int a = 1 + 1; - System.out.println(a); +// int a = 1 + 1; +// System.out.println(a); //suspension.getEvent().prepareUnwindFrame(suspension.getFrame(2)); //suspension.resume(); - // System.out.println(suspension.getEvent().getTopStackFrame().getName()); + System.out.println(suspension.getEvent().getTopStackFrame().getName()); // RootNode node = suspension.getStackFrames().get(2).getRawNode(SomLanguage.class).getRootNode(); // From 251210bde6695e454d9a7dbbadbd78a718a9904d Mon Sep 17 00:00:00 2001 From: matteo Date: Tue, 2 Aug 2022 17:43:59 +0200 Subject: [PATCH 06/20] adding restart message + updateClass --- src/tools/debugger/FrontendConnector.java | 29 +++++++++++++++++++- src/tools/debugger/message/RestartFrame.java | 19 +++++++++++++ src/tools/debugger/message/UpdateClass.java | 13 +++++++-- 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/tools/debugger/message/RestartFrame.java diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index 5526204dba..e88a708710 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -12,6 +12,7 @@ import java.util.concurrent.ExecutionException; import java.util.function.Function; +import com.oracle.truffle.api.debug.DebugStackFrame; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.java_websocket.WebSocket; @@ -31,7 +32,10 @@ import som.compiler.MixinDefinition; import som.compiler.Variable; import som.interpreter.SomLanguage; +import som.interpreter.nodes.dispatch.AbstractDispatchNode; +import som.interpreter.nodes.dispatch.DispatchGuard; import som.interpreter.nodes.dispatch.Dispatchable; +import som.interpreter.objectstorage.ClassFactory; import som.vm.ObjectSystem; import som.vm.VmSettings; import som.vmobjects.SClass; @@ -66,6 +70,7 @@ import tools.debugger.message.VariablesResponse; import tools.debugger.session.Breakpoints; import tools.debugger.session.LineBreakpoint; +import tools.debugger.visitors.UpdateMixinIdVisitor; import java.util.function.Consumer; @@ -364,9 +369,16 @@ private void closeAllSockets() { } catch (InterruptedException e) {} } + public void restartFrame(Suspension suspension, DebugStackFrame frame) { + suspension.getEvent().prepareUnwindFrame(frame); + suspension.resume(); + suspension.resume(); + } + // Code Uptading stuff public MixinDefinition updateClass(String filePath) { try { + //TODO: support inner classes VM vm = webDebugger.vm; StructuralProbe structuralProbe = vm.getStructuralProbe(); EconomicSet modules = structuralProbe.getClasses(); @@ -377,11 +389,26 @@ public MixinDefinition updateClass(String filePath) { oldModule = module; } } - MixinDefinition newModule = vm.loadModule(filePath); + MixinDefinition newModule = vm.loadModule(filePath,oldModule); System.out.println(newModule.getName().toString()); EconomicMap oldMethods = oldModule.getInstanceDispatchables(); oldMethods.putAll(newModule.getInstanceDispatchables()); + for(ClassFactory module : oldModule.cache) { + module.dispatchables.putAll(newModule.getInstanceDispatchables()); + } + UpdateMixinIdVisitor visitor; + for (Dispatchable disp : oldModule.getInstanceDispatchables().getValues()) { + if (disp instanceof SInvokable){ + SInvokable inv = (SInvokable) disp; + inv.setHolder(oldModule); +// visitor = new UpdateMixinIdVisitor(oldModule.getMixinId()); +// inv.getInvokable().accept(visitor); + } + } System.out.println("SUBSTITUTED METHODS IN MODULE"); + + DispatchGuard.invalidateAssumption(); + return oldModule; } catch (IOException e) { e.printStackTrace(); diff --git a/src/tools/debugger/message/RestartFrame.java b/src/tools/debugger/message/RestartFrame.java new file mode 100644 index 0000000000..604c6c79b1 --- /dev/null +++ b/src/tools/debugger/message/RestartFrame.java @@ -0,0 +1,19 @@ +package tools.debugger.message; +import org.java_websocket.WebSocket; +import tools.debugger.FrontendConnector; +import tools.debugger.frontend.Suspension; +import tools.debugger.message.Message.IncommingMessage; +public class RestartFrame extends IncommingMessage { + private final int currentFrameId; + + public RestartFrame(int currentFrameId) { + this.currentFrameId = currentFrameId; + } + + @Override + public void process(FrontendConnector connector, WebSocket conn) { + Suspension suspension= connector.getSuspension(0); + int realId = currentFrameId + suspension.getFrameSkipCount(); + connector.restartFrame(suspension,suspension.getStackFrames().get(realId)); + } +} diff --git a/src/tools/debugger/message/UpdateClass.java b/src/tools/debugger/message/UpdateClass.java index e14d0a751f..bc4447991b 100644 --- a/src/tools/debugger/message/UpdateClass.java +++ b/src/tools/debugger/message/UpdateClass.java @@ -53,8 +53,17 @@ public boolean execute() { ArrayList frames = suspension.getStackFrames(); // int a = 1 + 1; // System.out.println(a); - //suspension.getEvent().prepareUnwindFrame(suspension.getFrame(2)); - //suspension.resume(); + DebugStackFrame restartFrame = null; + for(DebugStackFrame frame : frames){ + if(frame.getSourceSection().getSource().getURI() == updatedModule.getSourceSection().getSource().getURI()) { + restartFrame = frame; + break; + } + } + + //frontend.restartFrame(suspension, restartFrame); + //suspension.resum + System.out.println(suspension.getEvent().getTopStackFrame().getName()); // RootNode node = suspension.getStackFrames().get(2).getRawNode(SomLanguage.class).getRootNode(); From 4522509dd0294e9d66af4103cf35ca9f2f49419c Mon Sep 17 00:00:00 2001 From: matteo Date: Tue, 2 Aug 2022 17:44:30 +0200 Subject: [PATCH 07/20] Implementing updating of module on compiler side [still not working] --- src/som/compiler/MixinBuilder.java | 25 ++++++++++++- src/som/compiler/MixinDefinition.java | 2 +- src/som/compiler/Parser.java | 46 ++++++++++++++++++++++++ src/som/compiler/SourcecodeCompiler.java | 8 +++++ src/som/vm/ObjectSystem.java | 24 +++++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/src/som/compiler/MixinBuilder.java b/src/som/compiler/MixinBuilder.java index 458ae6b438..91b0414b09 100644 --- a/src/som/compiler/MixinBuilder.java +++ b/src/som/compiler/MixinBuilder.java @@ -157,6 +157,29 @@ public MixinBuilder(final ScopeBuilder outer, final AccessModifier accessModi this.structuralProbe = structuralProbe; } + public MixinBuilder(final ScopeBuilder outer, final AccessModifier accessModifier, + final SSymbol name, final SourceSection nameSection, + final StructuralProbe structuralProbe, + final SomLanguage language, final MixinDefinitionId mixinId){ + super(outer, outer == null ? null : outer.getScope()); + this.name = name; + this.nameSection = nameSection; + this.mixinId = mixinId; + + this.classSide = false; + this.language = language; + + this.classScope = createScope(scope); + + this.initializer = new MethodBuilder(this, structuralProbe); + this.primaryFactoryMethod = + new MethodBuilder(this, classScope, false, language, structuralProbe); + this.superclassAndMixinResolutionBuilder = createSuperclassResolutionBuilder(); + + this.accessModifier = accessModifier; + this.structuralProbe = structuralProbe; + } + public static class MixinDefinitionError extends SemanticDefinitionError { private static final long serialVersionUID = 5030639383869198851L; @@ -493,7 +516,7 @@ protected boolean isImmutable() { return true; } - private void setHolders(final MixinDefinition clsDef) { + public void setHolders(final MixinDefinition clsDef) { assert clsDef != null; for (Dispatchable disp : dispatchables.getValues()) { if (disp instanceof SInvokable) { diff --git a/src/som/compiler/MixinDefinition.java b/src/som/compiler/MixinDefinition.java index 3740e6ac91..86e0892a83 100644 --- a/src/som/compiler/MixinDefinition.java +++ b/src/som/compiler/MixinDefinition.java @@ -291,7 +291,7 @@ protected static boolean sameClassConstruction(final Object a, final Object b) { return sameClassConstruction(aC.getSuperClass(), bC.getSuperClass()); } - private final ArrayList cache = new ArrayList<>(2); + public final ArrayList cache = new ArrayList<>(2); private ClassFactory getCached(final Object superclassAndMixins) { if (superclassAndMixins == null) { diff --git a/src/som/compiler/Parser.java b/src/som/compiler/Parser.java index b5324953b6..a134e67edb 100644 --- a/src/som/compiler/Parser.java +++ b/src/som/compiler/Parser.java @@ -335,6 +335,13 @@ public MixinBuilder moduleDeclaration() throws ProgramDefinitionError { return classDeclaration(null, AccessModifier.PUBLIC); } + public MixinBuilder moduleDeclaration(MixinBuilder.MixinDefinitionId mixinDefinitionId) throws ProgramDefinitionError { + compatibilityNewspeakVersionAndFileCategory(); + + comments(); + return classDeclaration(null, AccessModifier.PUBLIC, mixinDefinitionId); + } + protected String className() throws ParseError { String mixinName = text; expect(Identifier, IdentifierTag.class); @@ -380,6 +387,45 @@ private MixinBuilder classDeclaration(final MixinBuilder outerBuilder, return mxnBuilder; } + private MixinBuilder classDeclaration(final MixinBuilder outerBuilder, + final AccessModifier accessModifier, MixinBuilder.MixinDefinitionId mixinDefinitionId) throws ProgramDefinitionError { + expectIdentifier("class", "Found unexpected token %(found)s. " + + "Tried parsing a class declaration and expected 'class' instead.", + KeywordTag.class); + + int coord = getStartIndex(); + String mixinName = className(); + SourceSection nameSS = getSource(coord); + + MixinBuilder mxnBuilder = new MixinBuilder(outerBuilder, accessModifier, + symbolFor(mixinName), nameSS, structuralProbe, language,mixinDefinitionId); + + MethodBuilder primaryFactory = mxnBuilder.getPrimaryFactoryMethodBuilder(); + coord = getStartIndex(); + + // Newspeak-spec: this is not strictly sufficient for Newspeak + // it could also parse a binary selector here, I think + // but, doesn't seem so useful, so, let's keep it simple + if (sym == Identifier || sym == Keyword) { + messagePattern(primaryFactory); + } else { + // in the standard case, the primary factory method is #new + primaryFactory.addArgument(Symbols.SELF, getEmptySource()); + primaryFactory.setSignature(Symbols.NEW); + } + mxnBuilder.setupInitializerBasedOnPrimaryFactory(getSource(coord)); + + comments(); + + expect(Equal, "Unexpected symbol %(found)s." + + " Tried to parse the class declaration of " + mixinName + + " and expect '=' before the (optional) inheritance declaration.", + KeywordTag.class); + + inheritanceListAndOrBody(mxnBuilder); + return mxnBuilder; + } + private void inheritanceListAndOrBody(final MixinBuilder mxnBuilder) throws ProgramDefinitionError { if (sym == NewTerm) { diff --git a/src/som/compiler/SourcecodeCompiler.java b/src/som/compiler/SourcecodeCompiler.java index 6a4ce6b8eb..c33fcd189a 100644 --- a/src/som/compiler/SourcecodeCompiler.java +++ b/src/som/compiler/SourcecodeCompiler.java @@ -70,4 +70,12 @@ public MixinDefinition recompileModule(Source source, StructuralProbe structuralProbe, MixinDefinition oldModule) throws ProgramDefinitionError { + Parser parser = new Parser(source.getCharacters().toString(), source, null, language); + int coord = parser.getStartIndex(); + MixinBuilder mxnBuilder = parser.moduleDeclaration(oldModule.getMixinId()); + MixinDefinition result = mxnBuilder.assemble(parser.getSource(coord)); + return result; + } } diff --git a/src/som/vm/ObjectSystem.java b/src/som/vm/ObjectSystem.java index 0714f87885..0cf4654814 100644 --- a/src/som/vm/ObjectSystem.java +++ b/src/som/vm/ObjectSystem.java @@ -150,6 +150,30 @@ public MixinDefinition loadModule(final String filename) throws IOException { return loadModule(source); } + public MixinDefinition reLoadModule(final String filename, MixinDefinition oldModule) throws IOException{ + File file = new File(filename); + + if (!file.exists()) { + throw new FileNotFoundException(filename); + } + + if (!file.isFile()) { + throw new NotAFileException(filename); + } + + Source source = SomLanguage.getSource(file); + return reLoadModule(source,oldModule); + } + + public MixinDefinition reLoadModule(final Source source, MixinDefinition oldModule) throws IOException { + try { + return compiler.recompileModule(source,null,oldModule); + } catch (ProgramDefinitionError programDefinitionError) { + programDefinitionError.printStackTrace(); + } + return null; + } + public MixinDefinition loadModule(final Source source) throws IOException { URI uri = source.getURI(); if (loadedModules.containsKey(uri)) { From 15b02b7e77334a1c80d2c1f60276c0ed81945e01 Mon Sep 17 00:00:00 2001 From: matteo Date: Tue, 2 Aug 2022 17:45:06 +0200 Subject: [PATCH 08/20] adding ast visitor for updating module with old mixin id (not working) --- src/som/VM.java | 9 ++- .../interpreter/nodes/ArgumentReadNode.java | 59 ++++++++++++++++++- src/som/interpreter/nodes/ContextualNode.java | 13 +++- .../interpreter/nodes/OuterObjectRead.java | 9 ++- .../nodes/ResolvingImplicitReceiverSend.java | 18 ++++++ .../nodes/dispatch/DispatchGuard.java | 30 ++++++++++ .../nodes/dispatch/GenericDispatchNode.java | 13 ++++ .../dispatch/GenericSuperDispatchNode.java | 13 ++++ .../dispatch/UninitializedDispatchNode.java | 23 ++++++++ .../objectstorage/ClassFactory.java | 2 +- 10 files changed, 184 insertions(+), 5 deletions(-) diff --git a/src/som/VM.java b/src/som/VM.java index 44e74f8e6d..22390d4c8b 100644 --- a/src/som/VM.java +++ b/src/som/VM.java @@ -410,7 +410,7 @@ public void setupInstruments(final Env env) { structuralProbe = SnapshotBackend.getProbe(); } - System.out.println(structuralProbe); + structuralProbe = new StructuralProbe<>(); } public SClass loadExtensionModule(final String filename) { @@ -421,6 +421,13 @@ public MixinDefinition loadModule(final String filename) throws IOException { return objectSystem.loadModule(filename); } + public MixinDefinition loadModule(final String filename,MixinDefinition oldModule) throws IOException { + if (oldModule == null) { + return objectSystem.loadModule(filename); + } + return objectSystem.reLoadModule(filename,oldModule); + } + public MixinDefinition loadModule(final Source source) throws IOException { return objectSystem.loadModule(source); } diff --git a/src/som/interpreter/nodes/ArgumentReadNode.java b/src/som/interpreter/nodes/ArgumentReadNode.java index 7fe5e07bb5..6ba870132c 100644 --- a/src/som/interpreter/nodes/ArgumentReadNode.java +++ b/src/som/interpreter/nodes/ArgumentReadNode.java @@ -9,6 +9,7 @@ import bd.inlining.ScopeAdaptationVisitor; import bd.tools.nodes.Invocation; import som.compiler.MixinBuilder.MixinDefinitionId; +import som.compiler.MixinDefinition; import som.compiler.Variable.AccessNodeState; import som.compiler.Variable.Argument; import som.interpreter.SArguments; @@ -16,6 +17,7 @@ import som.vmobjects.SSymbol; import tools.debugger.Tags.ArgumentTag; import tools.debugger.Tags.KeywordTag; +import tools.debugger.visitors.UpdateMixinIdVisitor; import tools.dym.Tags.LocalArgRead; @@ -48,6 +50,7 @@ public LocalArgumentReadNode(final boolean insidePrim, final int argIdx) { assert insidePrim : "Only to be used for primitive nodes"; } + @Override public WrapperNode createWrapper(final ProbeNode probe) { return new LocalArgumentReadNodeWrapper(this, probe); @@ -92,13 +95,23 @@ public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) { public static class LocalSelfReadNode extends LocalArgumentReadNode implements ISpecialSend { private final MixinDefinitionId mixin; - private final ValueProfile rcvrClass = ValueProfile.createClassProfile(); + private ValueProfile rcvrClass = ValueProfile.createClassProfile(); public LocalSelfReadNode(final Argument arg, final MixinDefinitionId mixin) { super(arg); this.mixin = mixin; } + public LocalSelfReadNode(LocalSelfReadNode oldInstance, MixinDefinitionId newMixinId) { + this.mixin = newMixinId; + this.rcvrClass = oldInstance.rcvrClass; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new LocalSelfReadNode(this,visitor.getMixinDefinitionId())); + } + @Override public Object executeGeneric(final VirtualFrame frame) { return rcvrClass.profile(SArguments.rcvr(frame)); @@ -149,6 +162,18 @@ public NonLocalArgumentReadNode(final Argument arg, final int contextLevel) { this.arg = arg; } + public NonLocalArgumentReadNode(NonLocalArgumentReadNode oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance,newMixinId); + this.argumentIndex = oldInstance.argumentIndex; + this.arg = oldInstance.arg; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new NonLocalArgumentReadNode(this,visitor.getMixinDefinitionId())); + } + + public final Argument getArg() { return arg; } @@ -191,6 +216,16 @@ public NonLocalSelfReadNode(final Argument arg, final MixinDefinitionId mixin, super(arg, contextLevel); this.mixin = mixin; } + public NonLocalSelfReadNode(NonLocalSelfReadNode oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance,newMixinId); + this.mixin = newMixinId; + //this.rcvrClass = oldInstance.rcvrClass; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new NonLocalSelfReadNode(this,visitor.getMixinDefinitionId())); + } @Override public Object executeGeneric(final VirtualFrame frame) { @@ -239,6 +274,16 @@ public LocalSuperReadNode(final Argument arg, final MixinDefinitionId holderMixi this.holderMixin = holderMixin; this.classSide = classSide; } + public LocalSuperReadNode(LocalSuperReadNode oldInstance, MixinDefinitionId newMixinId) { + this.holderMixin = newMixinId; + this.classSide = oldInstance.classSide; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new LocalSuperReadNode(this,visitor.getMixinDefinitionId())); + } + @Override public MixinDefinitionId getEnclosingMixinId() { @@ -278,6 +323,18 @@ public NonLocalSuperReadNode(final Argument arg, final int contextLevel, this.classSide = classSide; } + + public NonLocalSuperReadNode(NonLocalSuperReadNode oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance,newMixinId); + this.holderMixin = newMixinId; + this.classSide = oldInstance.classSide; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new NonLocalSuperReadNode(this,visitor.getMixinDefinitionId())); + } + @Override public MixinDefinitionId getEnclosingMixinId() { return holderMixin; diff --git a/src/som/interpreter/nodes/ContextualNode.java b/src/som/interpreter/nodes/ContextualNode.java index 1fc46d2bd7..aa2875757a 100644 --- a/src/som/interpreter/nodes/ContextualNode.java +++ b/src/som/interpreter/nodes/ContextualNode.java @@ -28,6 +28,7 @@ import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.profiles.ValueProfile; +import som.compiler.MixinBuilder; import som.interpreter.SArguments; import som.interpreter.nodes.nary.ExprWithTagsNode; import som.vmobjects.SBlock; @@ -53,7 +54,17 @@ public ContextualNode(final int contextLevel) { this.rcvrType = ValueProfile.createClassProfile(); } - public final int getContextLevel() { + public ContextualNode(ContextualNode oldInstance, MixinBuilder.MixinDefinitionId newMixinId) { + super(); + this.outerType = oldInstance.outerType; + this.rcvrType = oldInstance.rcvrType; + this.contextLevel = oldInstance.contextLevel; + this.determineContext = oldInstance.determineContext; + this.sourceSection = oldInstance.sourceSection; + this.tagMark = oldInstance.tagMark; + } + + public final int getContextLevel() { return contextLevel; } diff --git a/src/som/interpreter/nodes/OuterObjectRead.java b/src/som/interpreter/nodes/OuterObjectRead.java index 91dacaeb05..8686404397 100644 --- a/src/som/interpreter/nodes/OuterObjectRead.java +++ b/src/som/interpreter/nodes/OuterObjectRead.java @@ -29,6 +29,7 @@ import som.vmobjects.SClass; import som.vmobjects.SObjectWithClass; import som.vmobjects.SSymbol; +import tools.debugger.visitors.UpdateMixinIdVisitor; /** @@ -63,7 +64,7 @@ public abstract class OuterObjectRead * encloses either {@code self} or one of its superclasses. {@code mixinId} is used * to distinguish the two where necessary. */ - private final MixinDefinitionId enclosingMixinId; + private MixinDefinitionId enclosingMixinId; private final ValueProfile enclosingObj; @@ -74,6 +75,12 @@ public OuterObjectRead(final MixinDefinitionId mixinId, this.enclosingObj = ValueProfile.createIdentityProfile(); } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.enclosingMixinId = visitor.getMixinDefinitionId(); + } + public MixinDefinitionId getMixinId() { return mixinId; } diff --git a/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java b/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java index 1debaed13d..0cb17937f5 100644 --- a/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java +++ b/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java @@ -12,6 +12,7 @@ import som.interpreter.LexicalScope.MethodScope; import som.interpreter.nodes.MessageSendNode.AbstractMessageSendNode; import som.vmobjects.SSymbol; +import tools.debugger.visitors.UpdateMixinIdVisitor; public class ResolvingImplicitReceiverSend extends AbstractMessageSendNode { @@ -47,6 +48,23 @@ public ResolvingImplicitReceiverSend(final SSymbol selector, this.vm = vm; } + public ResolvingImplicitReceiverSend(ResolvingImplicitReceiverSend oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance.argumentNodes); + this.currentScope = oldInstance.currentScope; + this.mixinId = newMixinId; + this.selector = oldInstance.selector; + this.vm = oldInstance.vm; + this.newReceiverNodeForOuterSend = oldInstance.newReceiverNodeForOuterSend; + this.replacedBy = oldInstance.replacedBy; + this.sourceSection = oldInstance.sourceSection; + this.tagMark = oldInstance.tagMark; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new ResolvingImplicitReceiverSend(this,visitor.getMixinDefinitionId())); + } + /** * For wrapped nodes only. */ diff --git a/src/som/interpreter/nodes/dispatch/DispatchGuard.java b/src/som/interpreter/nodes/dispatch/DispatchGuard.java index 6b5129b3b0..bee181ea32 100644 --- a/src/som/interpreter/nodes/dispatch/DispatchGuard.java +++ b/src/som/interpreter/nodes/dispatch/DispatchGuard.java @@ -1,5 +1,9 @@ package som.interpreter.nodes.dispatch; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.nodes.InvalidAssumptionException; import som.compiler.MixinDefinition.SlotDefinition; @@ -14,6 +18,15 @@ public abstract class DispatchGuard { + + @CompilerDirectives.CompilationFinal + private static Assumption noModuleReloaded = Truffle.getRuntime().createAssumption("no module reloaded"); + + public static void invalidateAssumption() { + noModuleReloaded.invalidate(); + noModuleReloaded = Truffle.getRuntime().createAssumption("noMoRel"); + } + public abstract boolean entryMatches(Object obj) throws InvalidAssumptionException; @@ -58,6 +71,7 @@ public static CheckSObject createSObjectCheck(final SObject obj) { private static final class CheckClass extends DispatchGuard { private final Class expected; + private final Assumption noLoad = noModuleReloaded; CheckClass(final Class expectedClass) { this.expected = expectedClass; @@ -65,20 +79,29 @@ private static final class CheckClass extends DispatchGuard { @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); return obj.getClass() == expected; } } private static final class CheckTrue extends DispatchGuard { + + private final Assumption noLoad = noModuleReloaded; + @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); return obj == Boolean.TRUE; } } private static final class CheckFalse extends DispatchGuard { + + private final Assumption noLoad = noModuleReloaded; + @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); return obj == Boolean.FALSE; } } @@ -86,6 +109,7 @@ public boolean entryMatches(final Object obj) throws InvalidAssumptionException private static final class CheckObjectWithoutFields extends DispatchGuard { private final ClassFactory expected; + private final Assumption noLoad = noModuleReloaded; CheckObjectWithoutFields(final ClassFactory expected) { this.expected = expected; @@ -93,6 +117,7 @@ private static final class CheckObjectWithoutFields extends DispatchGuard { @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); return obj instanceof SObjectWithoutFields && ((SObjectWithoutFields) obj).getFactory() == expected; } @@ -101,6 +126,7 @@ public boolean entryMatches(final Object obj) throws InvalidAssumptionException private static final class CheckSClass extends DispatchGuard { private final ClassFactory expected; + private final Assumption noLoad = noModuleReloaded; CheckSClass(final ClassFactory expected) { this.expected = expected; @@ -108,6 +134,7 @@ private static final class CheckSClass extends DispatchGuard { @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); return obj instanceof SClass && ((SClass) obj).getFactory() == expected; } @@ -115,6 +142,7 @@ public boolean entryMatches(final Object obj) throws InvalidAssumptionException public abstract static class CheckSObject extends DispatchGuard { protected final ObjectLayout expected; + protected final Assumption noLoad = noModuleReloaded; CheckSObject(final ObjectLayout expected) { this.expected = expected; @@ -136,6 +164,7 @@ private static final class CheckSMutableObject extends CheckSObject { @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); expected.checkIsLatest(); return obj instanceof SMutableObject && ((SMutableObject) obj).getObjectLayout() == expected; @@ -155,6 +184,7 @@ private static final class CheckSImmutableObject extends CheckSObject { @Override public boolean entryMatches(final Object obj) throws InvalidAssumptionException { + noLoad.check(); expected.checkIsLatest(); return obj instanceof SImmutableObject && ((SImmutableObject) obj).getObjectLayout() == expected; diff --git a/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java b/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java index b1023df1dc..06f7824155 100644 --- a/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java +++ b/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java @@ -5,8 +5,10 @@ import som.compiler.AccessModifier; import som.compiler.MixinBuilder.MixinDefinitionId; +import som.interpreter.nodes.ArgumentReadNode; import som.vmobjects.SClass; import som.vmobjects.SSymbol; +import tools.debugger.visitors.UpdateMixinIdVisitor; public final class GenericDispatchNode extends AbstractGenericDispatchNode { @@ -21,6 +23,17 @@ public GenericDispatchNode(final SourceSection source, final SSymbol selector, this.mixinId = mixinId; } + public GenericDispatchNode(GenericDispatchNode oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance.sourceSection,oldInstance.selector); + this.mixinId = newMixinId; + this.minimalVisibility = oldInstance.minimalVisibility; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new GenericDispatchNode(this,visitor.getMixinDefinitionId())); + } + @Override @TruffleBoundary protected Dispatchable doLookup(final SClass rcvrClass) { diff --git a/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java b/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java index bbf1058385..30989333c5 100644 --- a/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java +++ b/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java @@ -5,8 +5,10 @@ import som.compiler.AccessModifier; import som.compiler.MixinBuilder.MixinDefinitionId; +import som.interpreter.nodes.ArgumentReadNode; import som.vmobjects.SClass; import som.vmobjects.SSymbol; +import tools.debugger.visitors.UpdateMixinIdVisitor; public class GenericSuperDispatchNode extends AbstractGenericDispatchNode { @@ -21,6 +23,17 @@ public GenericSuperDispatchNode(final SourceSection source, this.classSide = classSide; } + public GenericSuperDispatchNode(GenericSuperDispatchNode oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance.sourceSection,oldInstance.selector); + this.holderMixin = newMixinId; + this.classSide = oldInstance.classSide; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new GenericSuperDispatchNode(this,visitor.getMixinDefinitionId())); + } + private static SClass getSuperClass(final SClass rcvrClass, final MixinDefinitionId holderMixin, final boolean classSide) { SClass cls = rcvrClass.lookupClass(holderMixin); diff --git a/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java b/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java index 7a0f5c7c32..686f7e03bf 100644 --- a/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java +++ b/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java @@ -17,6 +17,7 @@ import som.interpreter.SomLanguage; import som.interpreter.TruffleCompiler; import som.interpreter.Types; +import som.interpreter.nodes.ArgumentReadNode; import som.interpreter.nodes.ISuperReadNode; import som.interpreter.nodes.MessageSendNode.GenericMessageSendNode; import som.interpreter.objectstorage.ObjectTransitionSafepoint; @@ -24,6 +25,7 @@ import som.vmobjects.SInvokable; import som.vmobjects.SObject; import som.vmobjects.SSymbol; +import tools.debugger.visitors.UpdateMixinIdVisitor; public final class UninitializedDispatchNode { @@ -237,6 +239,16 @@ private static final class UninitializedLexicallyBound extends AbstractUninitial this.mixinForPrivateLookup = mixinForPrivateLookup; } + public UninitializedLexicallyBound(UninitializedLexicallyBound oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance.sourceSection,oldInstance.selector); + this.mixinForPrivateLookup = newMixinId; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new UninitializedLexicallyBound(this,visitor.getMixinDefinitionId())); + } + @Override protected AbstractUninitialized createNewChainEnd(final Object rcvr, final SClass rcvrClass, final Dispatchable result) { @@ -293,6 +305,17 @@ protected Dispatchable doLookup(final SClass rcvrClass) { rcvrClass, selector, holderMixin, classSide); } + public UninitializedSuper(UninitializedSuper oldInstance, MixinDefinitionId newMixinId) { + super(oldInstance.sourceSection,oldInstance.selector); + this.holderMixin = newMixinId; + this.classSide = oldInstance.classSide; + } + + + public void accept(UpdateMixinIdVisitor visitor){ + this.replace(new UninitializedSuper(this,visitor.getMixinDefinitionId())); + } + @Override protected AbstractUninitialized createNewChainEnd(final Object rcvr, final SClass rcvrClass, final Dispatchable result) { diff --git a/src/som/interpreter/objectstorage/ClassFactory.java b/src/som/interpreter/objectstorage/ClassFactory.java index 6397640428..4bcda3bbe4 100644 --- a/src/som/interpreter/objectstorage/ClassFactory.java +++ b/src/som/interpreter/objectstorage/ClassFactory.java @@ -53,7 +53,7 @@ public final class ClassFactory { private final MixinDefinition mixinDef; private final EconomicSet instanceSlots; - private final EconomicMap dispatchables; + public final EconomicMap dispatchables; private final boolean hasOnlyImmutableFields; From 6facd8f825b9a2c9e8d4f0645fc6dd762dc4be32 Mon Sep 17 00:00:00 2001 From: matteo Date: Tue, 2 Aug 2022 17:45:19 +0200 Subject: [PATCH 09/20] registering restart command --- src/tools/debugger/RuntimeReflectionRegistration.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/debugger/RuntimeReflectionRegistration.java b/src/tools/debugger/RuntimeReflectionRegistration.java index 8d2a3a62e8..6b7eee5689 100644 --- a/src/tools/debugger/RuntimeReflectionRegistration.java +++ b/src/tools/debugger/RuntimeReflectionRegistration.java @@ -75,6 +75,7 @@ public void register(final String name, final Class klass) { inMsgs.register(ProgramInfoRequest.class); inMsgs.register(TraceDataRequest.class); inMsgs.register(UpdateClass.class); + inMsgs.register(RestartFrame.class); ClassGroup bps = new ClassGroup(BreakpointInfo.class, "type", true); bps.register(LineBreakpoint.class); From b9000dc1aa6d10041dbac185ef9f37e9e7148d2a Mon Sep 17 00:00:00 2001 From: matteo Date: Tue, 2 Aug 2022 17:45:33 +0200 Subject: [PATCH 10/20] added visitor for stubstituting mixin (not working) --- .../visitors/UpdateMixinIdVisitor.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/tools/debugger/visitors/UpdateMixinIdVisitor.java diff --git a/src/tools/debugger/visitors/UpdateMixinIdVisitor.java b/src/tools/debugger/visitors/UpdateMixinIdVisitor.java new file mode 100644 index 0000000000..04ae06e19a --- /dev/null +++ b/src/tools/debugger/visitors/UpdateMixinIdVisitor.java @@ -0,0 +1,24 @@ +package tools.debugger.visitors; + +import com.oracle.truffle.api.instrumentation.InstrumentableNode; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeVisitor; +import com.oracle.truffle.api.nodes.RootNode; +import som.compiler.MixinBuilder; + +public class UpdateMixinIdVisitor implements NodeVisitor { + private MixinBuilder.MixinDefinitionId mixinDefinitionId; + + public UpdateMixinIdVisitor(MixinBuilder.MixinDefinitionId mixinDefinitionId) { + this.mixinDefinitionId = mixinDefinitionId; + } + + @Override + public boolean visit(Node node) { + return true; + } + + public MixinBuilder.MixinDefinitionId getMixinDefinitionId() { + return mixinDefinitionId; + } +} From 638f936991767ce35f2c1ed0555dd0c4c494fe7f Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 3 Aug 2022 16:17:13 +0200 Subject: [PATCH 11/20] updating the class keeps old slots and skips slot definitions. Updating now works unless object is reinitialized --- src/som/compiler/MixinBuilder.java | 4 ++++ src/som/compiler/SourcecodeCompiler.java | 1 + .../interpreter/nodes/dispatch/DispatchGuard.java | 2 +- src/tools/debugger/FrontendConnector.java | 13 ++++++++++++- src/tools/debugger/message/UpdateClass.java | 6 ++++-- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/som/compiler/MixinBuilder.java b/src/som/compiler/MixinBuilder.java index 91b0414b09..7f7b573655 100644 --- a/src/som/compiler/MixinBuilder.java +++ b/src/som/compiler/MixinBuilder.java @@ -698,6 +698,10 @@ public void addNestedMixin(final MixinDefinition nestedMixin) slots.put(name, cacheSlot); } + public void addSlotsUnsafe(EconomicMap newSlots){ + slots.putAll(newSlots); + } + public MixinDefinitionId getMixinId() { return mixinId; } diff --git a/src/som/compiler/SourcecodeCompiler.java b/src/som/compiler/SourcecodeCompiler.java index c33fcd189a..afc982c39c 100644 --- a/src/som/compiler/SourcecodeCompiler.java +++ b/src/som/compiler/SourcecodeCompiler.java @@ -75,6 +75,7 @@ public MixinDefinition recompileModule(Source source, StructuralProbe oldMethods = oldModule.getInstanceDispatchables(); oldMethods.putAll(newModule.getInstanceDispatchables()); + EconomicMap newDisp = newModule.getInstanceDispatchables(); + //remove slot definition from dispatchables for(ClassFactory module : oldModule.cache) { + for (SSymbol key : newDisp.getKeys()){ + if(newDisp.get(key) instanceof MixinDefinition.SlotDefinition){ + newDisp.removeKey(key); + } + } module.dispatchables.putAll(newModule.getInstanceDispatchables()); } UpdateMixinIdVisitor visitor; for (Dispatchable disp : oldModule.getInstanceDispatchables().getValues()) { + if(disp instanceof MixinDefinition.SlotDefinition){ + System.out.println("Skipping slot definition"); + } else{ if (disp instanceof SInvokable){ SInvokable inv = (SInvokable) disp; inv.setHolder(oldModule); // visitor = new UpdateMixinIdVisitor(oldModule.getMixinId()); // inv.getInvokable().accept(visitor); } - } + }} + //oldModule.getSlots().putAll(newModule.getSlots()); System.out.println("SUBSTITUTED METHODS IN MODULE"); DispatchGuard.invalidateAssumption(); diff --git a/src/tools/debugger/message/UpdateClass.java b/src/tools/debugger/message/UpdateClass.java index bc4447991b..f38a00ea78 100644 --- a/src/tools/debugger/message/UpdateClass.java +++ b/src/tools/debugger/message/UpdateClass.java @@ -60,12 +60,14 @@ public boolean execute() { break; } } - - //frontend.restartFrame(suspension, restartFrame); + if (restartFrame != null) { + // frontend.restartFrame(suspension, restartFrame); + } //suspension.resum System.out.println(suspension.getEvent().getTopStackFrame().getName()); + // RootNode node = suspension.getStackFrames().get(2).getRawNode(SomLanguage.class).getRootNode(); // // System.out.println(node.getName()); From 9d0db71284d650225af3e156ff09ebaa75ef4fca Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 3 Aug 2022 17:06:20 +0200 Subject: [PATCH 12/20] code update now migrates also slots from the recompiled class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New slots with the same name of old slots are pushed in the old class and they are mapped to the same location of old slots. For this reason, we don’t need to place the old slots in the mixinBuilder anymore. --- src/som/compiler/SourcecodeCompiler.java | 2 +- src/tools/debugger/FrontendConnector.java | 34 +++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/som/compiler/SourcecodeCompiler.java b/src/som/compiler/SourcecodeCompiler.java index afc982c39c..57eed172ff 100644 --- a/src/som/compiler/SourcecodeCompiler.java +++ b/src/som/compiler/SourcecodeCompiler.java @@ -75,7 +75,7 @@ public MixinDefinition recompileModule(Source source, StructuralProbe newDisp = newModule.getInstanceDispatchables(); //remove slot definition from dispatchables for(ClassFactory module : oldModule.cache) { - for (SSymbol key : newDisp.getKeys()){ - if(newDisp.get(key) instanceof MixinDefinition.SlotDefinition){ - newDisp.removeKey(key); - } - } +// for (SSymbol key : newDisp.getKeys()){ +// if(newDisp.get(key) instanceof MixinDefinition.SlotDefinition){ +// newDisp.removeKey(key); +// } +// } module.dispatchables.putAll(newModule.getInstanceDispatchables()); } UpdateMixinIdVisitor visitor; @@ -415,7 +417,27 @@ public MixinDefinition updateClass(String filePath) { // inv.getInvokable().accept(visitor); } }} - //oldModule.getSlots().putAll(newModule.getSlots()); + oldModule.getSlots().putAll(newModule.getSlots()); + // Pushing new slots + for (MixinDefinition.SlotDefinition sl : oldModule.getSlots().getValues()){ + for(ClassFactory module : oldModule.cache) { + EconomicMap storageLocations = + module.getInstanceLayout().getStorageLocations(); + Iterable oldKeys = storageLocations.getKeys(); + Map toSubstitute = new HashMap<>(); + for (MixinDefinition.SlotDefinition oldKey : oldKeys){ + if(oldKey.getName() == sl.getName()){ + toSubstitute.put(oldKey,sl); + break; + } + } + for (Map.Entry newOld : toSubstitute.entrySet()){ + StorageLocation location = storageLocations.get(newOld.getKey()); + storageLocations.removeKey(newOld.getKey()); + storageLocations.put(newOld.getValue(),location); + } + } + } System.out.println("SUBSTITUTED METHODS IN MODULE"); DispatchGuard.invalidateAssumption(); From 180bac48f2b01f5180f4fe08b0add11a200fcfb2 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 3 Aug 2022 17:06:30 +0200 Subject: [PATCH 13/20] restart acts like a ST restart --- src/tools/debugger/message/RestartFrame.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/debugger/message/RestartFrame.java b/src/tools/debugger/message/RestartFrame.java index 604c6c79b1..e7e8f853a8 100644 --- a/src/tools/debugger/message/RestartFrame.java +++ b/src/tools/debugger/message/RestartFrame.java @@ -13,7 +13,9 @@ public RestartFrame(int currentFrameId) { @Override public void process(FrontendConnector connector, WebSocket conn) { Suspension suspension= connector.getSuspension(0); - int realId = currentFrameId + suspension.getFrameSkipCount(); + int skipCount = suspension.getFrameSkipCount(); + skipCount = skipCount > 0 ? skipCount - 1 : skipCount; + int realId = currentFrameId + skipCount; connector.restartFrame(suspension,suspension.getStackFrames().get(realId)); } } From f8f0d6feba2ad7ebe55165e83644e47f649296b1 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 3 Aug 2022 17:09:32 +0200 Subject: [PATCH 14/20] ignoring dsStores --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 0483f54096..201e4ab1a7 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ traces /tests/streams/*.txt npm-debug.log* /.metadata +.DS_Store +/SOMns.iml +/libs/black-diamonds From a13abbb54ac1b233c4c1a1bc5982447a5c7baf5c Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 3 Aug 2022 17:19:38 +0200 Subject: [PATCH 15/20] reverting changes to AST for visitor --- .../interpreter/nodes/ArgumentReadNode.java | 59 +------------------ src/som/interpreter/nodes/ContextualNode.java | 13 +--- .../interpreter/nodes/OuterObjectRead.java | 9 +-- .../nodes/ResolvingImplicitReceiverSend.java | 18 ------ .../nodes/dispatch/GenericDispatchNode.java | 13 ---- .../dispatch/GenericSuperDispatchNode.java | 13 ---- .../dispatch/UninitializedDispatchNode.java | 23 -------- 7 files changed, 3 insertions(+), 145 deletions(-) diff --git a/src/som/interpreter/nodes/ArgumentReadNode.java b/src/som/interpreter/nodes/ArgumentReadNode.java index 6ba870132c..7fe5e07bb5 100644 --- a/src/som/interpreter/nodes/ArgumentReadNode.java +++ b/src/som/interpreter/nodes/ArgumentReadNode.java @@ -9,7 +9,6 @@ import bd.inlining.ScopeAdaptationVisitor; import bd.tools.nodes.Invocation; import som.compiler.MixinBuilder.MixinDefinitionId; -import som.compiler.MixinDefinition; import som.compiler.Variable.AccessNodeState; import som.compiler.Variable.Argument; import som.interpreter.SArguments; @@ -17,7 +16,6 @@ import som.vmobjects.SSymbol; import tools.debugger.Tags.ArgumentTag; import tools.debugger.Tags.KeywordTag; -import tools.debugger.visitors.UpdateMixinIdVisitor; import tools.dym.Tags.LocalArgRead; @@ -50,7 +48,6 @@ public LocalArgumentReadNode(final boolean insidePrim, final int argIdx) { assert insidePrim : "Only to be used for primitive nodes"; } - @Override public WrapperNode createWrapper(final ProbeNode probe) { return new LocalArgumentReadNodeWrapper(this, probe); @@ -95,23 +92,13 @@ public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) { public static class LocalSelfReadNode extends LocalArgumentReadNode implements ISpecialSend { private final MixinDefinitionId mixin; - private ValueProfile rcvrClass = ValueProfile.createClassProfile(); + private final ValueProfile rcvrClass = ValueProfile.createClassProfile(); public LocalSelfReadNode(final Argument arg, final MixinDefinitionId mixin) { super(arg); this.mixin = mixin; } - public LocalSelfReadNode(LocalSelfReadNode oldInstance, MixinDefinitionId newMixinId) { - this.mixin = newMixinId; - this.rcvrClass = oldInstance.rcvrClass; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new LocalSelfReadNode(this,visitor.getMixinDefinitionId())); - } - @Override public Object executeGeneric(final VirtualFrame frame) { return rcvrClass.profile(SArguments.rcvr(frame)); @@ -162,18 +149,6 @@ public NonLocalArgumentReadNode(final Argument arg, final int contextLevel) { this.arg = arg; } - public NonLocalArgumentReadNode(NonLocalArgumentReadNode oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance,newMixinId); - this.argumentIndex = oldInstance.argumentIndex; - this.arg = oldInstance.arg; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new NonLocalArgumentReadNode(this,visitor.getMixinDefinitionId())); - } - - public final Argument getArg() { return arg; } @@ -216,16 +191,6 @@ public NonLocalSelfReadNode(final Argument arg, final MixinDefinitionId mixin, super(arg, contextLevel); this.mixin = mixin; } - public NonLocalSelfReadNode(NonLocalSelfReadNode oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance,newMixinId); - this.mixin = newMixinId; - //this.rcvrClass = oldInstance.rcvrClass; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new NonLocalSelfReadNode(this,visitor.getMixinDefinitionId())); - } @Override public Object executeGeneric(final VirtualFrame frame) { @@ -274,16 +239,6 @@ public LocalSuperReadNode(final Argument arg, final MixinDefinitionId holderMixi this.holderMixin = holderMixin; this.classSide = classSide; } - public LocalSuperReadNode(LocalSuperReadNode oldInstance, MixinDefinitionId newMixinId) { - this.holderMixin = newMixinId; - this.classSide = oldInstance.classSide; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new LocalSuperReadNode(this,visitor.getMixinDefinitionId())); - } - @Override public MixinDefinitionId getEnclosingMixinId() { @@ -323,18 +278,6 @@ public NonLocalSuperReadNode(final Argument arg, final int contextLevel, this.classSide = classSide; } - - public NonLocalSuperReadNode(NonLocalSuperReadNode oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance,newMixinId); - this.holderMixin = newMixinId; - this.classSide = oldInstance.classSide; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new NonLocalSuperReadNode(this,visitor.getMixinDefinitionId())); - } - @Override public MixinDefinitionId getEnclosingMixinId() { return holderMixin; diff --git a/src/som/interpreter/nodes/ContextualNode.java b/src/som/interpreter/nodes/ContextualNode.java index aa2875757a..1fc46d2bd7 100644 --- a/src/som/interpreter/nodes/ContextualNode.java +++ b/src/som/interpreter/nodes/ContextualNode.java @@ -28,7 +28,6 @@ import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.profiles.ValueProfile; -import som.compiler.MixinBuilder; import som.interpreter.SArguments; import som.interpreter.nodes.nary.ExprWithTagsNode; import som.vmobjects.SBlock; @@ -54,17 +53,7 @@ public ContextualNode(final int contextLevel) { this.rcvrType = ValueProfile.createClassProfile(); } - public ContextualNode(ContextualNode oldInstance, MixinBuilder.MixinDefinitionId newMixinId) { - super(); - this.outerType = oldInstance.outerType; - this.rcvrType = oldInstance.rcvrType; - this.contextLevel = oldInstance.contextLevel; - this.determineContext = oldInstance.determineContext; - this.sourceSection = oldInstance.sourceSection; - this.tagMark = oldInstance.tagMark; - } - - public final int getContextLevel() { + public final int getContextLevel() { return contextLevel; } diff --git a/src/som/interpreter/nodes/OuterObjectRead.java b/src/som/interpreter/nodes/OuterObjectRead.java index 8686404397..91dacaeb05 100644 --- a/src/som/interpreter/nodes/OuterObjectRead.java +++ b/src/som/interpreter/nodes/OuterObjectRead.java @@ -29,7 +29,6 @@ import som.vmobjects.SClass; import som.vmobjects.SObjectWithClass; import som.vmobjects.SSymbol; -import tools.debugger.visitors.UpdateMixinIdVisitor; /** @@ -64,7 +63,7 @@ public abstract class OuterObjectRead * encloses either {@code self} or one of its superclasses. {@code mixinId} is used * to distinguish the two where necessary. */ - private MixinDefinitionId enclosingMixinId; + private final MixinDefinitionId enclosingMixinId; private final ValueProfile enclosingObj; @@ -75,12 +74,6 @@ public OuterObjectRead(final MixinDefinitionId mixinId, this.enclosingObj = ValueProfile.createIdentityProfile(); } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.enclosingMixinId = visitor.getMixinDefinitionId(); - } - public MixinDefinitionId getMixinId() { return mixinId; } diff --git a/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java b/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java index 0cb17937f5..1debaed13d 100644 --- a/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java +++ b/src/som/interpreter/nodes/ResolvingImplicitReceiverSend.java @@ -12,7 +12,6 @@ import som.interpreter.LexicalScope.MethodScope; import som.interpreter.nodes.MessageSendNode.AbstractMessageSendNode; import som.vmobjects.SSymbol; -import tools.debugger.visitors.UpdateMixinIdVisitor; public class ResolvingImplicitReceiverSend extends AbstractMessageSendNode { @@ -48,23 +47,6 @@ public ResolvingImplicitReceiverSend(final SSymbol selector, this.vm = vm; } - public ResolvingImplicitReceiverSend(ResolvingImplicitReceiverSend oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance.argumentNodes); - this.currentScope = oldInstance.currentScope; - this.mixinId = newMixinId; - this.selector = oldInstance.selector; - this.vm = oldInstance.vm; - this.newReceiverNodeForOuterSend = oldInstance.newReceiverNodeForOuterSend; - this.replacedBy = oldInstance.replacedBy; - this.sourceSection = oldInstance.sourceSection; - this.tagMark = oldInstance.tagMark; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new ResolvingImplicitReceiverSend(this,visitor.getMixinDefinitionId())); - } - /** * For wrapped nodes only. */ diff --git a/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java b/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java index 06f7824155..b1023df1dc 100644 --- a/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java +++ b/src/som/interpreter/nodes/dispatch/GenericDispatchNode.java @@ -5,10 +5,8 @@ import som.compiler.AccessModifier; import som.compiler.MixinBuilder.MixinDefinitionId; -import som.interpreter.nodes.ArgumentReadNode; import som.vmobjects.SClass; import som.vmobjects.SSymbol; -import tools.debugger.visitors.UpdateMixinIdVisitor; public final class GenericDispatchNode extends AbstractGenericDispatchNode { @@ -23,17 +21,6 @@ public GenericDispatchNode(final SourceSection source, final SSymbol selector, this.mixinId = mixinId; } - public GenericDispatchNode(GenericDispatchNode oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance.sourceSection,oldInstance.selector); - this.mixinId = newMixinId; - this.minimalVisibility = oldInstance.minimalVisibility; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new GenericDispatchNode(this,visitor.getMixinDefinitionId())); - } - @Override @TruffleBoundary protected Dispatchable doLookup(final SClass rcvrClass) { diff --git a/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java b/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java index 30989333c5..bbf1058385 100644 --- a/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java +++ b/src/som/interpreter/nodes/dispatch/GenericSuperDispatchNode.java @@ -5,10 +5,8 @@ import som.compiler.AccessModifier; import som.compiler.MixinBuilder.MixinDefinitionId; -import som.interpreter.nodes.ArgumentReadNode; import som.vmobjects.SClass; import som.vmobjects.SSymbol; -import tools.debugger.visitors.UpdateMixinIdVisitor; public class GenericSuperDispatchNode extends AbstractGenericDispatchNode { @@ -23,17 +21,6 @@ public GenericSuperDispatchNode(final SourceSection source, this.classSide = classSide; } - public GenericSuperDispatchNode(GenericSuperDispatchNode oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance.sourceSection,oldInstance.selector); - this.holderMixin = newMixinId; - this.classSide = oldInstance.classSide; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new GenericSuperDispatchNode(this,visitor.getMixinDefinitionId())); - } - private static SClass getSuperClass(final SClass rcvrClass, final MixinDefinitionId holderMixin, final boolean classSide) { SClass cls = rcvrClass.lookupClass(holderMixin); diff --git a/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java b/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java index 686f7e03bf..7a0f5c7c32 100644 --- a/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java +++ b/src/som/interpreter/nodes/dispatch/UninitializedDispatchNode.java @@ -17,7 +17,6 @@ import som.interpreter.SomLanguage; import som.interpreter.TruffleCompiler; import som.interpreter.Types; -import som.interpreter.nodes.ArgumentReadNode; import som.interpreter.nodes.ISuperReadNode; import som.interpreter.nodes.MessageSendNode.GenericMessageSendNode; import som.interpreter.objectstorage.ObjectTransitionSafepoint; @@ -25,7 +24,6 @@ import som.vmobjects.SInvokable; import som.vmobjects.SObject; import som.vmobjects.SSymbol; -import tools.debugger.visitors.UpdateMixinIdVisitor; public final class UninitializedDispatchNode { @@ -239,16 +237,6 @@ private static final class UninitializedLexicallyBound extends AbstractUninitial this.mixinForPrivateLookup = mixinForPrivateLookup; } - public UninitializedLexicallyBound(UninitializedLexicallyBound oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance.sourceSection,oldInstance.selector); - this.mixinForPrivateLookup = newMixinId; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new UninitializedLexicallyBound(this,visitor.getMixinDefinitionId())); - } - @Override protected AbstractUninitialized createNewChainEnd(final Object rcvr, final SClass rcvrClass, final Dispatchable result) { @@ -305,17 +293,6 @@ protected Dispatchable doLookup(final SClass rcvrClass) { rcvrClass, selector, holderMixin, classSide); } - public UninitializedSuper(UninitializedSuper oldInstance, MixinDefinitionId newMixinId) { - super(oldInstance.sourceSection,oldInstance.selector); - this.holderMixin = newMixinId; - this.classSide = oldInstance.classSide; - } - - - public void accept(UpdateMixinIdVisitor visitor){ - this.replace(new UninitializedSuper(this,visitor.getMixinDefinitionId())); - } - @Override protected AbstractUninitialized createNewChainEnd(final Object rcvr, final SClass rcvrClass, final Dispatchable result) { From 3d687ee52e18c18c1135dac30f8c76625f9234f3 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 3 Aug 2022 17:21:40 +0200 Subject: [PATCH 16/20] removed unnecessary visitor --- src/tools/debugger/FrontendConnector.java | 13 +--------- .../visitors/UpdateMixinIdVisitor.java | 24 ------------------- 2 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 src/tools/debugger/visitors/UpdateMixinIdVisitor.java diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index b999ffeee8..ff0fa69710 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -1,6 +1,5 @@ package tools.debugger; -import java.io.File; import java.io.IOException; import java.net.BindException; import java.net.InetSocketAddress; @@ -15,7 +14,6 @@ import com.oracle.truffle.api.debug.DebugStackFrame; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; -import org.graalvm.collections.Pair; import org.java_websocket.WebSocket; import com.google.gson.Gson; @@ -32,15 +30,11 @@ import som.VM; import som.compiler.MixinDefinition; import som.compiler.Variable; -import som.interpreter.SomLanguage; -import som.interpreter.nodes.dispatch.AbstractDispatchNode; import som.interpreter.nodes.dispatch.DispatchGuard; import som.interpreter.nodes.dispatch.Dispatchable; import som.interpreter.objectstorage.ClassFactory; import som.interpreter.objectstorage.StorageLocation; -import som.vm.ObjectSystem; import som.vm.VmSettings; -import som.vmobjects.SClass; import som.vmobjects.SInvokable; import som.vmobjects.SSymbol; import tools.Tagging; @@ -72,9 +66,6 @@ import tools.debugger.message.VariablesResponse; import tools.debugger.session.Breakpoints; import tools.debugger.session.LineBreakpoint; -import tools.debugger.visitors.UpdateMixinIdVisitor; - -import java.util.function.Consumer; /** @@ -405,7 +396,7 @@ public MixinDefinition updateClass(String filePath) { // } module.dispatchables.putAll(newModule.getInstanceDispatchables()); } - UpdateMixinIdVisitor visitor; + for (Dispatchable disp : oldModule.getInstanceDispatchables().getValues()) { if(disp instanceof MixinDefinition.SlotDefinition){ System.out.println("Skipping slot definition"); @@ -413,8 +404,6 @@ public MixinDefinition updateClass(String filePath) { if (disp instanceof SInvokable){ SInvokable inv = (SInvokable) disp; inv.setHolder(oldModule); -// visitor = new UpdateMixinIdVisitor(oldModule.getMixinId()); -// inv.getInvokable().accept(visitor); } }} oldModule.getSlots().putAll(newModule.getSlots()); diff --git a/src/tools/debugger/visitors/UpdateMixinIdVisitor.java b/src/tools/debugger/visitors/UpdateMixinIdVisitor.java deleted file mode 100644 index 04ae06e19a..0000000000 --- a/src/tools/debugger/visitors/UpdateMixinIdVisitor.java +++ /dev/null @@ -1,24 +0,0 @@ -package tools.debugger.visitors; - -import com.oracle.truffle.api.instrumentation.InstrumentableNode; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.NodeVisitor; -import com.oracle.truffle.api.nodes.RootNode; -import som.compiler.MixinBuilder; - -public class UpdateMixinIdVisitor implements NodeVisitor { - private MixinBuilder.MixinDefinitionId mixinDefinitionId; - - public UpdateMixinIdVisitor(MixinBuilder.MixinDefinitionId mixinDefinitionId) { - this.mixinDefinitionId = mixinDefinitionId; - } - - @Override - public boolean visit(Node node) { - return true; - } - - public MixinBuilder.MixinDefinitionId getMixinDefinitionId() { - return mixinDefinitionId; - } -} From 689df1071df9a44b0bc4f10b12a02a5ab1c7e749 Mon Sep 17 00:00:00 2001 From: matteo Date: Mon, 19 Sep 2022 15:26:46 +0200 Subject: [PATCH 17/20] fixing restartframe and frame ids. restartframe now restarts correct frame. restart is still not same behaviour as ST (reenter instead of redispatch) --- src/tools/debugger/FrontendConnector.java | 9 ++++----- src/tools/debugger/message/RestartFrame.java | 7 ++++--- src/tools/debugger/message/StackTraceResponse.java | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/tools/debugger/FrontendConnector.java b/src/tools/debugger/FrontendConnector.java index ff0fa69710..8de15643f4 100644 --- a/src/tools/debugger/FrontendConnector.java +++ b/src/tools/debugger/FrontendConnector.java @@ -12,6 +12,7 @@ import java.util.function.Function; import com.oracle.truffle.api.debug.DebugStackFrame; +import com.oracle.truffle.api.debug.DebugValue; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.java_websocket.WebSocket; @@ -363,7 +364,7 @@ private void closeAllSockets() { } public void restartFrame(Suspension suspension, DebugStackFrame frame) { - suspension.getEvent().prepareUnwindFrame(frame); + suspension.getEvent().prepareUnwindFrame(frame,null) ; suspension.resume(); suspension.resume(); } @@ -398,14 +399,11 @@ public MixinDefinition updateClass(String filePath) { } for (Dispatchable disp : oldModule.getInstanceDispatchables().getValues()) { - if(disp instanceof MixinDefinition.SlotDefinition){ - System.out.println("Skipping slot definition"); - } else{ if (disp instanceof SInvokable){ SInvokable inv = (SInvokable) disp; inv.setHolder(oldModule); } - }} + } oldModule.getSlots().putAll(newModule.getSlots()); // Pushing new slots for (MixinDefinition.SlotDefinition sl : oldModule.getSlots().getValues()){ @@ -424,6 +422,7 @@ public MixinDefinition updateClass(String filePath) { StorageLocation location = storageLocations.get(newOld.getKey()); storageLocations.removeKey(newOld.getKey()); storageLocations.put(newOld.getValue(),location); + location.setSlot(newOld.getValue()); } } } diff --git a/src/tools/debugger/message/RestartFrame.java b/src/tools/debugger/message/RestartFrame.java index e7e8f853a8..df845bb914 100644 --- a/src/tools/debugger/message/RestartFrame.java +++ b/src/tools/debugger/message/RestartFrame.java @@ -4,10 +4,10 @@ import tools.debugger.frontend.Suspension; import tools.debugger.message.Message.IncommingMessage; public class RestartFrame extends IncommingMessage { - private final int currentFrameId; + private final int frameId; public RestartFrame(int currentFrameId) { - this.currentFrameId = currentFrameId; + this.frameId = currentFrameId; } @Override @@ -15,7 +15,8 @@ public void process(FrontendConnector connector, WebSocket conn) { Suspension suspension= connector.getSuspension(0); int skipCount = suspension.getFrameSkipCount(); skipCount = skipCount > 0 ? skipCount - 1 : skipCount; - int realId = currentFrameId + skipCount; + int realId = frameId + skipCount; + System.out.print("Restarted Frame Request " + frameId + "After skipping " + realId); connector.restartFrame(suspension,suspension.getStackFrames().get(realId)); } } diff --git a/src/tools/debugger/message/StackTraceResponse.java b/src/tools/debugger/message/StackTraceResponse.java index 0adc25e83f..5e5f20fea9 100644 --- a/src/tools/debugger/message/StackTraceResponse.java +++ b/src/tools/debugger/message/StackTraceResponse.java @@ -74,11 +74,14 @@ private static class StackFrame { /** An optional number of characters in the range. */ private final int length; - StackFrame(final long globalId, final String name, final String sourceUri, + private final long frameId; + + StackFrame(final long globalId, final long frameId, final String name, final String sourceUri, final int line, final int column, final int endLine, final int endColumn, final int length) { assert TraceData.isWithinJSIntValueRange(globalId); this.id = globalId; + this.frameId = frameId; this.name = name; this.sourceUri = sourceUri; this.line = line; @@ -170,6 +173,6 @@ private static StackFrame createFrame(final Suspension suspension, endColumn = 0; length = 0; } - return new StackFrame(id, name, sourceUri, line, column, endLine, endColumn, length); + return new StackFrame(id, frameId, name, sourceUri, line, column, endLine, endColumn, length); } } From d07a9f97e0d405b0294611499e3a91c78b7fa138 Mon Sep 17 00:00:00 2001 From: matteo Date: Mon, 19 Sep 2022 15:27:55 +0200 Subject: [PATCH 18/20] working on adding support for nested slots --- .../objectstorage/StorageLocation.java | 6 ++- src/som/vmobjects/SObject.java | 52 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/som/interpreter/objectstorage/StorageLocation.java b/src/som/interpreter/objectstorage/StorageLocation.java index a933cddf07..0291c0ed63 100644 --- a/src/som/interpreter/objectstorage/StorageLocation.java +++ b/src/som/interpreter/objectstorage/StorageLocation.java @@ -54,16 +54,20 @@ public static StorageLocation createForObject(final ObjectLayout layout, } protected final ObjectLayout layout; - protected final SlotDefinition slot; + protected SlotDefinition slot; protected StorageLocation(final ObjectLayout layout, final SlotDefinition slot) { this.layout = layout; this.slot = slot; } + public SlotDefinition getSlot() { return slot; } + public void setSlot(SlotDefinition slot) { + this.slot = slot; + } /** * @return true, if it is an object location, false otherwise. diff --git a/src/som/vmobjects/SObject.java b/src/som/vmobjects/SObject.java index a12f4ee878..c5a437ea6a 100644 --- a/src/som/vmobjects/SObject.java +++ b/src/som/vmobjects/SObject.java @@ -25,6 +25,8 @@ package som.vmobjects; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; @@ -35,8 +37,10 @@ import com.oracle.truffle.api.nodes.ExplodeLoop; import som.compiler.MixinDefinition.SlotDefinition; +import som.interpreter.nodes.dispatch.DispatchGuard; import som.interpreter.objectstorage.ClassFactory; import som.interpreter.objectstorage.ObjectLayout; +import som.interpreter.objectstorage.ObjectTransitionSafepoint; import som.interpreter.objectstorage.StorageLocation; import som.interpreter.objectstorage.StorageLocation.DoubleStorageLocation; import som.interpreter.objectstorage.StorageLocation.LongStorageLocation; @@ -394,7 +398,6 @@ private EconomicMap getAllFields() { private void setAllFields(final EconomicMap fieldValues) { resetFields(); primitiveUsedMap = 0; - MapCursor entry = fieldValues.getEntries(); while (entry.advance()) { if (entry.getValue() != null) { @@ -413,7 +416,7 @@ public final synchronized boolean updateLayoutToMatchClass() { ObjectLayout layoutAtClass = clazz.getLayoutForInstancesToUpdateObject(); if (objectLayout != layoutAtClass) { - setLayoutAndTransferFields(layoutAtClass); + setLayoutAndTransferFieldsOnClassUpdate(layoutAtClass); return true; } else { return false; @@ -424,12 +427,50 @@ private void setLayoutAndTransferFields(final ObjectLayout layoutAtClass) { CompilerDirectives.transferToInterpreterAndInvalidate(); EconomicMap fieldValues = getAllFields(); + //fieldValues = fixFieldsToNewSlots(layoutAtClass, fieldValues); + ObjectLayout oldObjectLayout = objectLayout; + objectLayout = layoutAtClass; + assert oldObjectLayout != objectLayout; + extensionPrimFields = getExtendedPrimStorage(layoutAtClass); + extensionObjFields = getExtendedObjectStorage(layoutAtClass); + try { + setAllFields(fieldValues); + } catch ( ArithmeticException error){ + objectLayout = oldObjectLayout; + this.updateLayoutToMatchClass(); + } + } + + private void setLayoutAndTransferFieldsOnClassUpdate(final ObjectLayout layoutAtClass) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + EconomicMap fieldValues = getAllFields(); + fieldValues = fixFieldsToNewSlots(layoutAtClass, fieldValues); objectLayout = layoutAtClass; extensionPrimFields = getExtendedPrimStorage(layoutAtClass); extensionObjFields = getExtendedObjectStorage(layoutAtClass); setAllFields(fieldValues); + DispatchGuard.invalidateAssumption(); + } + + private EconomicMap fixFieldsToNewSlots(ObjectLayout layoutAtClass, EconomicMap fieldValues ) { + EconomicMap oldSlots = objectLayout.getStorageLocations(); + EconomicMap newSlots = layoutAtClass.getStorageLocations(); + Map layoutLocations = new HashMap(); + EconomicMap newFieldValues = EconomicMap.create(); + for (SlotDefinition d : newSlots.getKeys()){ + layoutLocations.put(newSlots.get(d),d); + } + + for (SlotDefinition slot : fieldValues.getKeys()) { + StorageLocation location = oldSlots.get(slot); + SlotDefinition newSlotDef = layoutLocations.get(location); + if (newSlotDef != null) { + newFieldValues.put(newSlotDef, fieldValues.get(slot)); + } + } + return newFieldValues; } /** @@ -483,7 +524,12 @@ public static int getPrimitiveFieldMask(final int fieldIndex) { private StorageLocation getLocation(final SlotDefinition slot) { StorageLocation location = objectLayout.getStorageLocation(slot); - assert location != null; + // TODO: added here a division by 0 to be able to debug this when it happens. + // I do not recall what it is due to, but probably it is about reloading nested classes + // assert location != null; + if (location == null) { + int a = 1 / 0; + } return location; } From 98847964db8ecf029cbd327fd995568a39a0f60c Mon Sep 17 00:00:00 2001 From: matteo Date: Mon, 19 Sep 2022 16:46:46 +0200 Subject: [PATCH 19/20] fixed update of nested classes. only variable access in debugger is now broken --- .../nodes/dispatch/ClassSlotAccessNode.java | 3 +++ src/som/vmobjects/SObject.java | 12 +++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/som/interpreter/nodes/dispatch/ClassSlotAccessNode.java b/src/som/interpreter/nodes/dispatch/ClassSlotAccessNode.java index 51109b072c..96f6c769cd 100644 --- a/src/som/interpreter/nodes/dispatch/ClassSlotAccessNode.java +++ b/src/som/interpreter/nodes/dispatch/ClassSlotAccessNode.java @@ -87,6 +87,9 @@ public SClass read(final SObject rcvr) { if (cachedValue == Nil.nilObject) { return instantiateAndWriteUnsynced(rcvr); } else { + if (cachedValue == null) { + return instantiateAndWriteUnsynced(rcvr); + } assert cachedValue instanceof SClass; return (SClass) cachedValue; } diff --git a/src/som/vmobjects/SObject.java b/src/som/vmobjects/SObject.java index c5a437ea6a..8535007c59 100644 --- a/src/som/vmobjects/SObject.java +++ b/src/som/vmobjects/SObject.java @@ -416,7 +416,7 @@ public final synchronized boolean updateLayoutToMatchClass() { ObjectLayout layoutAtClass = clazz.getLayoutForInstancesToUpdateObject(); if (objectLayout != layoutAtClass) { - setLayoutAndTransferFieldsOnClassUpdate(layoutAtClass); + setLayoutAndTransferFields(layoutAtClass); return true; } else { return false; @@ -437,20 +437,18 @@ private void setLayoutAndTransferFields(final ObjectLayout layoutAtClass) { setAllFields(fieldValues); } catch ( ArithmeticException error){ objectLayout = oldObjectLayout; - this.updateLayoutToMatchClass(); + this.setLayoutAndTransferFieldsOnClassUpdate(layoutAtClass, fieldValues); } } - private void setLayoutAndTransferFieldsOnClassUpdate(final ObjectLayout layoutAtClass) { + private void setLayoutAndTransferFieldsOnClassUpdate(final ObjectLayout layoutAtClass,EconomicMap fieldValues) { CompilerDirectives.transferToInterpreterAndInvalidate(); - - EconomicMap fieldValues = getAllFields(); - fieldValues = fixFieldsToNewSlots(layoutAtClass, fieldValues); + EconomicMap newSlots = fixFieldsToNewSlots(layoutAtClass, fieldValues); objectLayout = layoutAtClass; extensionPrimFields = getExtendedPrimStorage(layoutAtClass); extensionObjFields = getExtendedObjectStorage(layoutAtClass); - setAllFields(fieldValues); + setAllFields(newSlots); DispatchGuard.invalidateAssumption(); } From 778496f182403b49f593cda808f280372b1e091d Mon Sep 17 00:00:00 2001 From: matteo Date: Tue, 20 Sep 2022 13:34:59 +0200 Subject: [PATCH 20/20] transitioning object to updated classs now correctly remaps slots that already have a value. Some slots still stay duplicated but it seems to work --- src/som/vmobjects/SObject.java | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/som/vmobjects/SObject.java b/src/som/vmobjects/SObject.java index 8535007c59..d793b6881f 100644 --- a/src/som/vmobjects/SObject.java +++ b/src/som/vmobjects/SObject.java @@ -36,6 +36,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.nodes.ExplodeLoop; +import org.graalvm.collections.Pair; import som.compiler.MixinDefinition.SlotDefinition; import som.interpreter.nodes.dispatch.DispatchGuard; import som.interpreter.objectstorage.ClassFactory; @@ -230,7 +231,7 @@ private boolean txMutObjLocEquals(final SMutableObject o) { // need to ignore mutators and class slots // ignore primitives, have been checked separately before if (e.getKey().getClass() == SlotDefinition.class && e.getValue().isObjectLocation() && - e.getValue().read(this) != oLocs.get(e.getKey()).read(o)) { + e.getValue().read(this) != oLocs.get(e.getKey()).read(this)) { return false; } } @@ -455,17 +456,25 @@ private void setLayoutAndTransferFieldsOnClassUpdate(final ObjectLayout layoutAt private EconomicMap fixFieldsToNewSlots(ObjectLayout layoutAtClass, EconomicMap fieldValues ) { EconomicMap oldSlots = objectLayout.getStorageLocations(); EconomicMap newSlots = layoutAtClass.getStorageLocations(); - Map layoutLocations = new HashMap(); + Map> layoutLocations = new HashMap<>(); EconomicMap newFieldValues = EconomicMap.create(); - for (SlotDefinition d : newSlots.getKeys()){ - layoutLocations.put(newSlots.get(d),d); - } + for (SlotDefinition newSlot : newSlots.getKeys()){ + for (SlotDefinition oldSlot : oldSlots.getKeys()){ + if(oldSlot.getName() == newSlot.getName()){ + StorageLocation newLoc = newSlots.get(newSlot); + if (newLoc.isObjectLocation()){ + layoutLocations.put(oldSlot, Pair.create(newSlot,fieldValues.get(oldSlot))); + break; + } + } + } + } for (SlotDefinition slot : fieldValues.getKeys()) { - StorageLocation location = oldSlots.get(slot); - SlotDefinition newSlotDef = layoutLocations.get(location); + //StorageLocation location = oldSlots.get(slot); + Pair newSlotDef = layoutLocations.get(slot); if (newSlotDef != null) { - newFieldValues.put(newSlotDef, fieldValues.get(slot)); + newFieldValues.put(newSlotDef.getLeft(),newSlotDef.getRight()); } } return newFieldValues;