From 7acc29cf052e9bd7107c416cd405582d657e9e9c Mon Sep 17 00:00:00 2001 From: Col-E Date: Sat, 9 Sep 2023 01:14:38 -0400 Subject: [PATCH 1/3] Create intermediate builder model for VM and VM-interface to allow creating simple copies This is intended for the use case where you initiate one 'base' VM and want to re-use it with different operations that may not have compatible VMInterface processors. Now you can create shallow VirtualMachine copies with a modified VMInterface value and operate on each VM copy. --- .../java/dev/xdark/ssvm/VirtualMachine.java | 55 ++++++ .../dev/xdark/ssvm/VirtualMachineBuilder.java | 165 ++++++++++++++++++ .../xdark/ssvm/api/DelegatingVMInterface.java | 5 + .../dev/xdark/ssvm/api/SimpleVMInterface.java | 49 +++++- .../java/dev/xdark/ssvm/api/VMInterface.java | 10 ++ .../ssvm/execution/ExecutionContext.java | 10 -- .../dev/xdark/ssvm/thread/ThreadManager.java | 8 +- .../thread/backtrace/SimpleBacktrace.java | 7 +- .../backtrace/SimpleExecutionContext.java | 11 ++ .../thread/virtual/VirtualThreadManager.java | 43 ++++- 10 files changed, 334 insertions(+), 29 deletions(-) create mode 100644 ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachineBuilder.java diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachine.java b/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachine.java index 6eabf20..ac3d79f 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachine.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachine.java @@ -93,6 +93,47 @@ public class VirtualMachine implements VMEventCollection { private volatile InstanceValue systemThreadGroup; private volatile InstanceValue mainThreadGroup; + /* + * Constructor for copying, see VirtualMachineBuilder + */ + VirtualMachine(VMInterface vmInterface, MemoryAllocator memoryAllocator, ObjectSynchronizer objectSynchronizer, + MemoryManager memoryManager, ClassDefiner classDefiner, ThreadManager threadManager, + FileManager fileManager, NativeLibraryManager nativeLibraryManager, TimeManager timeManager, + ManagementInterface managementInterface, StringPool stringPool, ClassLoaders classLoaders, + ExecutionEngine executionEngine, MirrorFactory mirrorFactory, BootClassFinder bootClassFinder, + ClassStorage classStorage, LinkResolver linkResolver, RuntimeResolver runtimeResolver, + Map properties, Map env, Reflection reflection, JVMTI jvmti, + VMOperations operations, Symbols symbols, Primitives primitives, InstanceValue systemThreadGroup, + InstanceValue mainThreadGroup) { + this.vmInterface = vmInterface; + this.memoryAllocator = memoryAllocator; + this.objectSynchronizer = objectSynchronizer; + this.memoryManager = memoryManager; + this.classDefiner = classDefiner; + this.threadManager = threadManager.copyForVm(this); + this.fileManager = fileManager; + this.nativeLibraryManager = nativeLibraryManager; + this.timeManager = timeManager; + this.managementInterface = managementInterface; + this.stringPool = stringPool; + this.classLoaders = classLoaders; + this.executionEngine = executionEngine; + this.mirrorFactory = mirrorFactory; + this.bootClassFinder = bootClassFinder; + this.classStorage = classStorage; + this.linkResolver = linkResolver; + this.runtimeResolver = runtimeResolver; + this.properties = properties; + this.env = env; + this.reflection = reflection; + this.jvmti = jvmti; + this.operations = operations; + this.symbols = symbols; + this.primitives = primitives; + this.systemThreadGroup = systemThreadGroup; + this.mainThreadGroup = mainThreadGroup; + } + public VirtualMachine() { vmInterface = createVMInterface(); DelegatingSymbols delegatingSymbols = new DelegatingSymbols(); @@ -126,6 +167,13 @@ public VirtualMachine() { operations = new VMOperations(this); } + /** + * @return New builder with values copied from this VM. + */ + public VirtualMachineBuilder toBuilder() { + return new VirtualMachineBuilder(this); + } + protected VMInterface createVMInterface() { return new SimpleVMInterface(); } @@ -279,6 +327,13 @@ public VMInterface getInterface() { return vmInterface; } + /** + * @return JVMTI manager. + */ + public JVMTI getJvmti() { + return jvmti; + } + /** * @return New JVMTI environment. */ diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachineBuilder.java b/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachineBuilder.java new file mode 100644 index 0000000..03ed66d --- /dev/null +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/VirtualMachineBuilder.java @@ -0,0 +1,165 @@ +package dev.xdark.ssvm; + +import dev.xdark.ssvm.api.VMInterface; +import dev.xdark.ssvm.classloading.BootClassFinder; +import dev.xdark.ssvm.classloading.ClassDefiner; +import dev.xdark.ssvm.classloading.ClassLoaders; +import dev.xdark.ssvm.classloading.ClassStorage; +import dev.xdark.ssvm.execution.ExecutionEngine; +import dev.xdark.ssvm.filesystem.FileManager; +import dev.xdark.ssvm.jni.NativeLibraryManager; +import dev.xdark.ssvm.jvm.ManagementInterface; +import dev.xdark.ssvm.memory.allocation.MemoryAllocator; +import dev.xdark.ssvm.memory.management.MemoryManager; +import dev.xdark.ssvm.memory.management.StringPool; +import dev.xdark.ssvm.mirror.MirrorFactory; +import dev.xdark.ssvm.operation.VMOperations; +import dev.xdark.ssvm.symbol.Primitives; +import dev.xdark.ssvm.symbol.Symbols; +import dev.xdark.ssvm.synchronizer.ObjectSynchronizer; +import dev.xdark.ssvm.thread.ThreadManager; +import dev.xdark.ssvm.timezone.TimeManager; +import dev.xdark.ssvm.util.Reflection; +import dev.xdark.ssvm.value.InstanceValue; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * An intermediate 'builder' for {@link VirtualMachine} which allows swapping out of a few components of an existing VM. + * + * @author Matt Coley + */ +public class VirtualMachineBuilder { + private AtomicReference state; + private VMInterface vmInterface; + private MemoryAllocator memoryAllocator; + private ObjectSynchronizer objectSynchronizer; + private MemoryManager memoryManager; + private ClassDefiner classDefiner; + private ThreadManager threadManager; + private FileManager fileManager; + private NativeLibraryManager nativeLibraryManager; + private TimeManager timeManager; + private ManagementInterface managementInterface; + private StringPool stringPool; + private ClassLoaders classLoaders; + private ExecutionEngine executionEngine; + private MirrorFactory mirrorFactory; + private BootClassFinder bootClassFinder; + private ClassStorage classStorage; + private LinkResolver linkResolver; + private RuntimeResolver runtimeResolver; + private Map properties; + private Map env; + private Reflection reflection; + private JVMTI jvmti; + private VMOperations operations; + private Symbols symbols; + private Primitives primitives; + private InstanceValue systemThreadGroup; + private InstanceValue mainThreadGroup; + + /** + * @param vm Base VM to copy values from. + */ + VirtualMachineBuilder(VirtualMachine vm) { + this.vmInterface = vm.getInterface(); + this.memoryAllocator = vm.getMemoryAllocator(); + this.objectSynchronizer = vm.getObjectSynchronizer(); + this.memoryManager = vm.getMemoryManager(); + this.classDefiner = vm.getClassDefiner(); + this.threadManager = vm.getThreadManager(); + this.fileManager = vm.getFileManager(); + this.nativeLibraryManager = vm.getNativeLibraryManager(); + this.timeManager = vm.getTimeManager(); + this.managementInterface = vm.getManagementInterface(); + this.stringPool = vm.getStringPool(); + this.classLoaders = vm.getClassLoaders(); + this.executionEngine = vm.getExecutionEngine(); + this.mirrorFactory = vm.getMirrorFactory(); + this.bootClassFinder = vm.getBootClassFinder(); + this.classStorage = vm.getClassStorage(); + this.linkResolver = vm.getLinkResolver(); + this.runtimeResolver = vm.getRuntimeResolver(); + this.properties = vm.getProperties(); + this.env = vm.getenv(); + this.reflection = vm.getReflection(); + this.jvmti = vm.getJvmti(); + this.operations = vm.getOperations(); + this.symbols = vm.getSymbols(); + this.primitives = vm.getPrimitives(); + this.systemThreadGroup = vm.getSystemThreadGroup(); + this.mainThreadGroup = vm.getMainThreadGroup(); + } + + /** + * @see VMInterface#copy() Used to deep copy an existing VM interface. + * @param vmInterface New VM interface to use. + * @return Self. + */ + public VirtualMachineBuilder withVmInterface(VMInterface vmInterface) { + this.vmInterface = vmInterface; + return this; + } + + /** + * @param fileManager New file manager to use. + * @return Self. + */ + public VirtualMachineBuilder withFileManager(FileManager fileManager) { + this.fileManager = fileManager; + return this; + } + + /** + * @param timeManager New time manager to use. + * @return Self. + */ + public VirtualMachineBuilder withTimeManager(TimeManager timeManager) { + this.timeManager = timeManager; + return this; + } + + /** + * @param executionEngine New execution engine to use. + * @return Self. + */ + public VirtualMachineBuilder withExecutionEngine(ExecutionEngine executionEngine) { + this.executionEngine = executionEngine; + return this; + } + + /** + * @return New VM with values from this builder. + */ + public VirtualMachine build() { + return new VirtualMachine(vmInterface, + memoryAllocator, + objectSynchronizer, + memoryManager, + classDefiner, + threadManager, + fileManager, + nativeLibraryManager, + timeManager, + managementInterface, + stringPool, + classLoaders, + executionEngine, + mirrorFactory, + bootClassFinder, + classStorage, + linkResolver, + runtimeResolver, + properties, + env, + reflection, + jvmti, + operations, + symbols, + primitives, + systemThreadGroup, + mainThreadGroup); + } +} diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/api/DelegatingVMInterface.java b/ssvm-core/src/main/java/dev/xdark/ssvm/api/DelegatingVMInterface.java index 8ca845b..ce69482 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/api/DelegatingVMInterface.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/api/DelegatingVMInterface.java @@ -138,4 +138,9 @@ public void handleAbstractMethodError(ExecutionContext ctx) { public void handleMaxInterations(ExecutionContext ctx) { delegate.handleMaxInterations(ctx); } + + @Override + public VMInterface copy() { + return delegate.copy(); + } } \ No newline at end of file diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/api/SimpleVMInterface.java b/ssvm-core/src/main/java/dev/xdark/ssvm/api/SimpleVMInterface.java index cabd773..a7176e5 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/api/SimpleVMInterface.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/api/SimpleVMInterface.java @@ -16,28 +16,51 @@ */ public class SimpleVMInterface implements VMInterface { private static final int MAX_INSNS = 1024; - private final InstructionProcessor[] processors = new InstructionProcessor[MAX_INSNS]; - private final Map invokerMap = new HashMap<>(); - private final List methodEnters = new ArrayList<>(); - private final List methodExits = new ArrayList<>(); - private final List methodEntersView = Collections.unmodifiableList(methodEnters); - private final List methodExitsView = Collections.unmodifiableList(methodExits); - private final List instructionInterceptors = new ArrayList<>(); - private final List instructionInterceptorsView = Collections.unmodifiableList(instructionInterceptors); + private final InstructionProcessor[] processors; + private final Map invokerMap; + private final List methodEnters; + private final List methodExits; + private final List methodEntersView; + private final List methodExitsView; + private final List instructionInterceptors; + private final List instructionInterceptorsView; private Consumer> linkageErrorHandler = SimpleVMInterface::handleLinkageError0; private Consumer> abstractMethodHandler = SimpleVMInterface::handleAbstractMethodError0; private Consumer> maxIterationsHandler = SimpleVMInterface::handleMaxIterations0; + private SimpleVMInterface(InstructionProcessor[] processors, Map invokerMap, + List methodEnters, List methodExits, + List instructionInterceptors) { + this.processors = processors; + this.invokerMap = invokerMap; + this.methodEnters = methodEnters; + this.methodExits = methodExits; + this.instructionInterceptors = instructionInterceptors; + + methodEntersView = Collections.unmodifiableList(methodEnters); + methodExitsView = Collections.unmodifiableList(methodExits); + instructionInterceptorsView = Collections.unmodifiableList(instructionInterceptors); + } + public SimpleVMInterface() { + this(new InstructionProcessor[MAX_INSNS], + new HashMap<>(), + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>() + ); + Arrays.fill(processors, new UnknownInstructionProcessor()); } @Override + @SuppressWarnings("unchecked") public InstructionProcessor getProcessor(I insn) { return processors[insn.getOpcode()]; } @Override + @SuppressWarnings("unchecked") public InstructionProcessor getProcessor(int opcode) { return processors[opcode]; } @@ -156,6 +179,16 @@ public void handleMaxInterations(ExecutionContext ctx) { maxIterationsHandler.accept(ctx); } + @Override + public VMInterface copy() { + SimpleVMInterface copy = new SimpleVMInterface(processors, new HashMap<>(invokerMap), + new ArrayList<>(methodEnters), new ArrayList<>(methodExits), + new ArrayList<>(instructionInterceptors) + ); + System.arraycopy(processors, 0, copy.processors, 0, Math.min(processors.length, copy.processors.length)); + return copy; + } + // Default impl for handling linkage errors is to throw UnsatisfiedLinkError private static void handleLinkageError0(ExecutionContext ctx) { ctx.getOperations().throwException(ctx.getSymbols().java_lang_UnsatisfiedLinkError(), ctx.getMethod().toString()); diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/api/VMInterface.java b/ssvm-core/src/main/java/dev/xdark/ssvm/api/VMInterface.java index 1b963fc..4d564db 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/api/VMInterface.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/api/VMInterface.java @@ -1,5 +1,6 @@ package dev.xdark.ssvm.api; +import dev.xdark.ssvm.VirtualMachine; import dev.xdark.ssvm.asm.Modifier; import dev.xdark.ssvm.execution.ExecutionContext; import dev.xdark.ssvm.execution.InstructionProcessor; @@ -175,4 +176,13 @@ public interface VMInterface { * @param ctx Context of the native method that interpreted {@link Interpreter#getMaxIterations() the maximum number of allowed iterations}. */ void handleMaxInterations(ExecutionContext ctx); + + /** + * Copying this interface may be viable when combined with {@link VirtualMachine#toBuilder()} to create basic + * "scopes". Each scope can have its own set of listeners and interceptors, while not polluting other + * {@link VMInterface} instances. + * + * @return Copy of this interface. + */ + VMInterface copy(); } \ No newline at end of file diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/execution/ExecutionContext.java b/ssvm-core/src/main/java/dev/xdark/ssvm/execution/ExecutionContext.java index 2c405da..e1ad827 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/execution/ExecutionContext.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/execution/ExecutionContext.java @@ -1,9 +1,7 @@ package dev.xdark.ssvm.execution; -import dev.xdark.ssvm.VirtualMachine; import dev.xdark.ssvm.mirror.member.JavaMethod; import dev.xdark.ssvm.mirror.type.InstanceClass; -import dev.xdark.ssvm.operation.VMOperations; import dev.xdark.ssvm.util.VMFunctions; import dev.xdark.ssvm.value.ObjectValue; import dev.xdark.ssvm.value.sink.ValueSink; @@ -114,12 +112,4 @@ default InstanceClass getOwner() { default ObjectValue getClassLoader() { return getOwner().getClassLoader(); } - - /** - * @return VM instance in which method is being executed. - */ - @Override - default VirtualMachine getVM() { - return getOwner().getVM(); - } } diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/ThreadManager.java b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/ThreadManager.java index a4cfa9b..f5634f7 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/ThreadManager.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/ThreadManager.java @@ -1,5 +1,6 @@ package dev.xdark.ssvm.thread; +import dev.xdark.ssvm.VirtualMachine; import dev.xdark.ssvm.thread.backtrace.Backtrace; import dev.xdark.ssvm.value.InstanceValue; @@ -12,7 +13,6 @@ * @see OSThread */ public interface ThreadManager { - /** * Starts the thread, assigns new OS thread to * the {@code oop} instance. @@ -148,4 +148,10 @@ default Backtrace currentBacktrace() { * @return Java thread or {@code null}, if thread is not alive. */ JavaThread getThread(InstanceValue oop); + + /** + * @param newVm New VM for the copied thread manager to reside in. + * @return Copy of thread manager. + */ + ThreadManager copyForVm(VirtualMachine newVm); } diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleBacktrace.java b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleBacktrace.java index bd2ca9d..825ee74 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleBacktrace.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleBacktrace.java @@ -1,5 +1,6 @@ package dev.xdark.ssvm.thread.backtrace; +import dev.xdark.ssvm.VirtualMachine; import dev.xdark.ssvm.execution.ExecutionContext; import dev.xdark.ssvm.execution.ExecutionRequest; import dev.xdark.ssvm.util.CloseableUtil; @@ -18,9 +19,11 @@ public final class SimpleBacktrace implements Backtrace { private static final int RESERVED_FRAMES = 12; private final List> frames; + private final VirtualMachine vm; private int frame; - public SimpleBacktrace(int frameCount) { + public SimpleBacktrace(VirtualMachine vm, int frameCount) { + this.vm = vm; frames = Arrays.asList(new ExecutionContext[Math.max(frameCount, RESERVED_FRAMES + 4)]); } @@ -33,7 +36,7 @@ public ExecutionContext push(ExecutionRequest reques } SimpleExecutionContext ctx = (SimpleExecutionContext) frames.get(frameIndex); if (ctx == null) { - ctx = new SimpleExecutionContext<>(); + ctx = new SimpleExecutionContext<>(vm); frames.set(frameIndex, ctx); } ctx.init(request.getMethod(), request.getStack(), request.getLocals(), request.getResultSink()); diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleExecutionContext.java b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleExecutionContext.java index d3019c2..ab527e9 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleExecutionContext.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/backtrace/SimpleExecutionContext.java @@ -1,5 +1,6 @@ package dev.xdark.ssvm.thread.backtrace; +import dev.xdark.ssvm.VirtualMachine; import dev.xdark.ssvm.execution.ExecutionContext; import dev.xdark.ssvm.execution.Locals; import dev.xdark.ssvm.execution.Stack; @@ -12,6 +13,7 @@ final class SimpleExecutionContext implements ExecutionContext, SafeCloseable { + private final VirtualMachine vm; private JavaMethod method; private Stack stack; private Locals locals; @@ -19,6 +21,15 @@ final class SimpleExecutionContext implements ExecutionCont private int insnPosition; private int lineNumber = -1; + SimpleExecutionContext(VirtualMachine vm) { + this.vm = vm; + } + + @Override + public VirtualMachine getVM() { + return vm; + } + @Override public JavaMethod getMethod() { return method; diff --git a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/virtual/VirtualThreadManager.java b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/virtual/VirtualThreadManager.java index 13bf23d..721b9bb 100644 --- a/ssvm-core/src/main/java/dev/xdark/ssvm/thread/virtual/VirtualThreadManager.java +++ b/ssvm-core/src/main/java/dev/xdark/ssvm/thread/virtual/VirtualThreadManager.java @@ -34,21 +34,48 @@ public final class VirtualThreadManager implements ThreadManager { private static final VirtualJavaThread SENTINEL = new VirtualJavaThread(null, null); // Mapping between eetop and Java thread - private final Map javaThreads = new HashMap<>(); + private final Map javaThreads; // Attached threads - private final Map foreignThreads = new IdentityHashMap<>(); + private final Map foreignThreads; // All threads so far - private final List allThreads = new LinkedList<>(); + private final List allThreads; // Threads for scheduling - private final Queue scheduled = new PriorityQueue<>(Comparator.comparingInt(t -> t.getOsThread().getPriority())); - // TODO this is stupid - private final List asleep = new ArrayList<>(); - private final Object threadLock = new Object[0]; + private final Queue scheduled; + // All asleep threads - TODO this is stupid + private final List asleep; + private final Object threadLock; private final VirtualMachine vm; private VirtualJavaThread currentThread; + /** + * Constructor for copying, where we want to replace the 'vm' field with a new value. + * + * @param vm New VM we want to operate within. + * @param vtm Old instance to shallow-copy from. + */ + private VirtualThreadManager(VirtualMachine vm, VirtualThreadManager vtm) { + this.vm = vm; + this.javaThreads = vtm.javaThreads; + this.foreignThreads = vtm.foreignThreads; + this.allThreads = vtm.allThreads; + this.scheduled = vtm.scheduled; + this.asleep = vtm.asleep; + this.threadLock = vtm.threadLock; + } + public VirtualThreadManager(VirtualMachine vm) { this.vm = vm; + threadLock = new Object[0]; + javaThreads = new HashMap<>(); + foreignThreads = new IdentityHashMap<>(); + allThreads = new LinkedList<>(); + scheduled = new PriorityQueue<>(Comparator.comparingInt(t -> t.getOsThread().getPriority())); + asleep = new ArrayList<>(); + } + + @Override + public VirtualThreadManager copyForVm(VirtualMachine newVm) { + return new VirtualThreadManager(newVm, this); } @Override @@ -290,7 +317,7 @@ private VirtualOSThread newOsThread(long stackSize) { // TODO configurable, like Java's -Xss flag. stackSize = 1024L * 1024L; } - Backtrace backtrace = new SimpleBacktrace(1024); + Backtrace backtrace = new SimpleBacktrace(vm, 1024); MemoryAllocator memoryAllocator = vm.getMemoryAllocator(); ThreadStorage storage = new HeapThreadStorage(vm.getMemoryManager(), memoryAllocator, memoryAllocator.allocateHeap(stackSize)); return new VirtualOSThread(backtrace, storage); From 86d3d43ddf6e62ff8fd8a3086fd8c0f65910ae85 Mon Sep 17 00:00:00 2001 From: Col-E Date: Mon, 18 Sep 2023 05:52:49 -0400 Subject: [PATCH 2/3] Make argument subtypes public, add type exposure --- .../main/java/dev/xdark/ssvm/invoke/Argument.java | 6 ++++++ .../java/dev/xdark/ssvm/invoke/DoubleArgument.java | 12 +++++++++++- .../java/dev/xdark/ssvm/invoke/FloatArgument.java | 12 +++++++++++- .../main/java/dev/xdark/ssvm/invoke/IntArgument.java | 12 +++++++++++- .../java/dev/xdark/ssvm/invoke/LongArgument.java | 12 +++++++++++- .../dev/xdark/ssvm/invoke/ReferenceArgument.java | 12 +++++++++++- 6 files changed, 61 insertions(+), 5 deletions(-) diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/Argument.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/Argument.java index 9f31a52..7f22cca 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/Argument.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/Argument.java @@ -2,6 +2,7 @@ import dev.xdark.ssvm.execution.Locals; import dev.xdark.ssvm.value.ObjectValue; +import org.objectweb.asm.Type; /** * Method argument. @@ -19,6 +20,11 @@ public interface Argument { */ int store(Locals locals, int index); + /** + * @return Argument value type. + */ + Type getType(); + /** * {@literal long} argument. * diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/DoubleArgument.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/DoubleArgument.java index 9a02e25..1b46ab8 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/DoubleArgument.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/DoubleArgument.java @@ -1,22 +1,32 @@ package dev.xdark.ssvm.invoke; import dev.xdark.ssvm.execution.Locals; +import org.objectweb.asm.Type; /** * Int argument. * * @author xDark */ -final class DoubleArgument implements Argument { +public final class DoubleArgument implements Argument { private final double value; DoubleArgument(double value) { this.value = value; } + public double getValue() { + return value; + } + @Override public int store(Locals locals, int index) { locals.setDouble(index, value); return 2; } + + @Override + public Type getType() { + return Type.DOUBLE_TYPE; + } } diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/FloatArgument.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/FloatArgument.java index 5e76382..2a0cf92 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/FloatArgument.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/FloatArgument.java @@ -1,22 +1,32 @@ package dev.xdark.ssvm.invoke; import dev.xdark.ssvm.execution.Locals; +import org.objectweb.asm.Type; /** * Float argument. * * @author xDark */ -final class FloatArgument implements Argument { +public final class FloatArgument implements Argument { private final float value; FloatArgument(float value) { this.value = value; } + public float getValue() { + return value; + } + @Override public int store(Locals locals, int index) { locals.setFloat(index, value); return 1; } + + @Override + public Type getType() { + return Type.FLOAT_TYPE; + } } diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/IntArgument.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/IntArgument.java index 7a38afe..4ecd994 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/IntArgument.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/IntArgument.java @@ -1,22 +1,32 @@ package dev.xdark.ssvm.invoke; import dev.xdark.ssvm.execution.Locals; +import org.objectweb.asm.Type; /** * Int argument. * * @author xDark */ -final class IntArgument implements Argument { +public final class IntArgument implements Argument { private final int value; IntArgument(int value) { this.value = value; } + public int getValue() { + return value; + } + @Override public int store(Locals locals, int index) { locals.setInt(index, value); return 1; } + + @Override + public Type getType() { + return Type.INT_TYPE; + } } diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/LongArgument.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/LongArgument.java index 19f9d1a..421a1d6 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/LongArgument.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/LongArgument.java @@ -1,22 +1,32 @@ package dev.xdark.ssvm.invoke; import dev.xdark.ssvm.execution.Locals; +import org.objectweb.asm.Type; /** * Long argument. * * @author xDark */ -final class LongArgument implements Argument { +public final class LongArgument implements Argument { private final long value; LongArgument(long value) { this.value = value; } + public long getValue() { + return value; + } + @Override public int store(Locals locals, int index) { locals.setLong(index, value); return 2; } + + @Override + public Type getType() { + return Type.LONG_TYPE; + } } diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/ReferenceArgument.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/ReferenceArgument.java index 334d43d..7f94335 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/ReferenceArgument.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/invoke/ReferenceArgument.java @@ -2,22 +2,32 @@ import dev.xdark.ssvm.execution.Locals; import dev.xdark.ssvm.value.ObjectValue; +import org.objectweb.asm.Type; /** * Reference argument. * * @author xDark */ -final class ReferenceArgument implements Argument { +public final class ReferenceArgument implements Argument { private final ObjectValue value; ReferenceArgument(ObjectValue value) { this.value = value; } + public ObjectValue getValue() { + return value; + } + @Override public int store(Locals locals, int index) { locals.setReference(index, value); return 1; } + + @Override + public Type getType() { + return value.getJavaClass().getType(); + } } From fea362e737e389dedd43c7cf34255207fa64ee78 Mon Sep 17 00:00:00 2001 From: Col-E Date: Mon, 18 Sep 2023 06:27:08 -0400 Subject: [PATCH 3/3] Expose loader instance in helper --- .../ssvm/classloading/SupplyingClassLoaderInstaller.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ssvm-invoke/src/main/java/dev/xdark/ssvm/classloading/SupplyingClassLoaderInstaller.java b/ssvm-invoke/src/main/java/dev/xdark/ssvm/classloading/SupplyingClassLoaderInstaller.java index 15f7373..8bc64b5 100644 --- a/ssvm-invoke/src/main/java/dev/xdark/ssvm/classloading/SupplyingClassLoaderInstaller.java +++ b/ssvm-invoke/src/main/java/dev/xdark/ssvm/classloading/SupplyingClassLoaderInstaller.java @@ -402,6 +402,14 @@ public Helper(VirtualMachine vm, InstanceClass loaderClass) { classStorage = vm.getClassStorage(); } + /** + * @return The class-loader instance used to load classes into the VM. + */ + public InstanceValue getClassLoaderInstance() { + init(); // Ensure loaded + return loaderInstance; + } + /** * Initialize the {@link SupplyingClassLoader} inside the {@link VirtualMachine}. */