mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-06-15 22:37:04 +00:00
Initial commit
This commit is contained in:
48
src/main/java/haidnor/jvm/Main.java
Normal file
48
src/main/java/haidnor/jvm/Main.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package haidnor.jvm;
|
||||
|
||||
import haidnor.jvm.classloader.ClassLoader;
|
||||
import haidnor.jvm.core.JavaExecutionEngine;
|
||||
import haidnor.jvm.rtda.heap.Klass;
|
||||
import haidnor.jvm.rtda.heap.KlassMethod;
|
||||
import haidnor.jvm.rtda.metaspace.Metaspace;
|
||||
import haidnor.jvm.runtime.JvmThread;
|
||||
import haidnor.jvm.util.JavaClassUtil;
|
||||
import haidnor.jvm.util.JvmThreadHolder;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
@Slf4j
|
||||
public class Main {
|
||||
|
||||
@SneakyThrows
|
||||
public static void main(String[] args) {
|
||||
Option jarOption = new Option("jar", true, "运行 jar 程序");
|
||||
Option classOption = new Option("class", true, "运行 .class 字节码文件");
|
||||
|
||||
OptionGroup optionGroup = new OptionGroup();
|
||||
optionGroup.addOption(jarOption).addOption(classOption);
|
||||
|
||||
Options options = new Options();
|
||||
options.addOptionGroup(optionGroup);
|
||||
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
CommandLine cmd = parser.parse(options, args);
|
||||
|
||||
if (cmd.hasOption("jar")) {
|
||||
String path = cmd.getOptionValue("jar");
|
||||
// TODO
|
||||
}
|
||||
if (cmd.hasOption("class")) {
|
||||
String path = cmd.getOptionValue("class");
|
||||
ClassLoader bootClassLoader = new ClassLoader("ApplicationClassLoader");
|
||||
Klass mainMeteKlass = bootClassLoader.loadClassWithAbsolutePath(path);
|
||||
KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass);
|
||||
Metaspace.registerJavaClass(mainMeteKlass);
|
||||
JvmThreadHolder.set(new JvmThread());
|
||||
|
||||
JavaExecutionEngine.callMainStaticMethod(mainKlassMethod);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package haidnor.jvm.classloader;
|
||||
|
||||
public class BootstrapClassLoader {
|
||||
|
||||
}
|
||||
82
src/main/java/haidnor/jvm/classloader/ClassLoader.java
Normal file
82
src/main/java/haidnor/jvm/classloader/ClassLoader.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package haidnor.jvm.classloader;
|
||||
|
||||
import haidnor.jvm.rtda.heap.Klass;
|
||||
import haidnor.jvm.rtda.metaspace.Metaspace;
|
||||
import org.apache.bcel.classfile.ClassParser;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
public class ClassLoader {
|
||||
|
||||
public final String name;
|
||||
|
||||
public final static String rtJarPath;
|
||||
|
||||
static {
|
||||
URL resource = ClassLoader.class.getResource("/");
|
||||
String path = resource.getPath();
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream(path + "/haidnorJVM.properties");
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties.load(fis);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
rtJarPath = properties.getProperty("rt.jar");
|
||||
}
|
||||
|
||||
public ClassLoader(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classPath 类路径,例如 haidnor/jvm/classloader/ClassLoader
|
||||
*/
|
||||
public Klass loadClass(String classPath) throws IOException {
|
||||
ClassParser classParser;
|
||||
if (classPath.startsWith("java/")) {
|
||||
String rtJarPath = getRtJarPath();
|
||||
|
||||
if (!new File(rtJarPath).exists()) {
|
||||
throw new IllegalStateException("rt.jar not found");
|
||||
}
|
||||
classParser = new ClassParser(rtJarPath, classPath + ".class");
|
||||
} else {
|
||||
URL resource = this.getClass().getResource("/");
|
||||
String fileName = resource.getPath() + classPath + ".class";
|
||||
classParser = new ClassParser(fileName);
|
||||
}
|
||||
|
||||
JavaClass javaClass = classParser.parse();
|
||||
Klass klass = new Klass(this, javaClass);
|
||||
Metaspace.registerJavaClass(klass);
|
||||
return klass;
|
||||
}
|
||||
|
||||
public Klass loadClassWithAbsolutePath(String absolutePath) throws IOException {
|
||||
ClassParser classParser = new ClassParser(absolutePath);
|
||||
JavaClass javaClass = classParser.parse();
|
||||
Klass klass = new Klass(this, javaClass);
|
||||
Metaspace.registerJavaClass(klass);
|
||||
return klass;
|
||||
}
|
||||
|
||||
private String getRtJarPath() {
|
||||
// String javaHome = System.getenv("JAVA_HOME");
|
||||
// Path rtJarPath = Paths.get(javaHome, "jre", "lib", "rt.jar");
|
||||
return rtJarPath;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
49
src/main/java/haidnor/jvm/core/Interpreter.java
Normal file
49
src/main/java/haidnor/jvm/core/Interpreter.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package haidnor.jvm.core;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.instruction.InstructionFactory;
|
||||
import haidnor.jvm.instruction.control.RETURN;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字节码执行解释器
|
||||
*/
|
||||
@Slf4j
|
||||
public class Interpreter {
|
||||
|
||||
@SneakyThrows
|
||||
public static void executeFrame(Frame frame) {
|
||||
log.debug("------------------------------ Frame START {}", frame.hashCode());
|
||||
Map<Integer, Instruction> instructionMap = new HashMap<>();
|
||||
|
||||
// 解析方法中的字节码指令
|
||||
log.debug(">>>>>>>>>>>>>>>> PARSE INST START");
|
||||
CodeStream codeStream = frame.getCodeStream();
|
||||
while (codeStream.available() > 0) {
|
||||
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
|
||||
log.debug("{}", instruction);
|
||||
instructionMap.put(instruction.index(), instruction);
|
||||
}
|
||||
log.debug(">>>>>>>>>>>>>>>> PARSE INST END");
|
||||
|
||||
// 执行方法中的字节码指令
|
||||
// int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“
|
||||
for (int i = 0; i < frame.getCodeLength(); ) {
|
||||
Instruction instruction = instructionMap.get(i);
|
||||
log.debug("{}", instruction);
|
||||
instruction.execute(frame);
|
||||
if (instruction instanceof RETURN) {
|
||||
break;
|
||||
}
|
||||
i += instruction.offSet();
|
||||
}
|
||||
log.debug("------------------------------ Frame End {}", frame.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
57
src/main/java/haidnor/jvm/core/JavaExecutionEngine.java
Normal file
57
src/main/java/haidnor/jvm/core/JavaExecutionEngine.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package haidnor.jvm.core;
|
||||
|
||||
|
||||
import haidnor.jvm.rtda.heap.KlassMethod;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.JvmThread;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.JvmThreadHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.bcel.classfile.LocalVariable;
|
||||
import org.apache.bcel.classfile.LocalVariableTable;
|
||||
import org.apache.bcel.classfile.Method;
|
||||
import org.apache.bcel.classfile.Utility;
|
||||
|
||||
@Slf4j
|
||||
public class JavaExecutionEngine {
|
||||
|
||||
public static void callMainStaticMethod(KlassMethod klassMethod) {
|
||||
JvmThread jvmThread = JvmThreadHolder.get();
|
||||
// 每个栈帧中包含一个指向运行时常量池中该栈帧所属的方法的引用。包含这个引用的目的就是为了支持当前方法实现动态链接
|
||||
// 有了这个引用,执行引擎就可以找到指定的方法,加载字节码指令
|
||||
Frame frame = new Frame(jvmThread, klassMethod);
|
||||
jvmThread.push(frame);
|
||||
Interpreter.executeFrame(frame);
|
||||
}
|
||||
|
||||
public static void callMethod(Frame lastFrame, KlassMethod klassMethod) {
|
||||
JvmThread jvmThread = JvmThreadHolder.get();
|
||||
Frame newFrame = new Frame(jvmThread, klassMethod);
|
||||
|
||||
Method method = klassMethod.javaMethod;
|
||||
String signature = method.getSignature();
|
||||
String[] argumentTypes = Utility.methodSignatureArgumentTypes(signature);
|
||||
|
||||
int argumentSlotSize = argumentTypes.length;
|
||||
if (!method.isStatic()) {
|
||||
argumentSlotSize++;
|
||||
}
|
||||
|
||||
// 静态方法调用传参
|
||||
// 将上一个栈帧操作数栈中数据弹出,存入下一个栈帧的局部变量表中
|
||||
LocalVariableTable localVariableTable = method.getLocalVariableTable();
|
||||
if (localVariableTable != null) {
|
||||
for (int i = argumentSlotSize - 1; i >= 0; i--) {
|
||||
LocalVariable[] localVariableArr = localVariableTable.getLocalVariableTable();
|
||||
LocalVariable localVariable = localVariableArr[i];
|
||||
int slotIndex = localVariable.getIndex();
|
||||
StackValue stackValue = lastFrame.pop();
|
||||
newFrame.slotSet(slotIndex, stackValue);
|
||||
}
|
||||
}
|
||||
jvmThread.push(newFrame);
|
||||
Interpreter.executeFrame(newFrame);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
40
src/main/java/haidnor/jvm/instruction/Instruction.java
Normal file
40
src/main/java/haidnor/jvm/instruction/Instruction.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package haidnor.jvm.instruction;
|
||||
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public abstract class Instruction {
|
||||
/**
|
||||
* 指令坐在 code 数组中的索引下标
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
/**
|
||||
* 执行下一个执行的偏移量
|
||||
*/
|
||||
private int offSet = 1;
|
||||
|
||||
public Instruction(CodeStream codeStream) {
|
||||
this.index = codeStream.index();
|
||||
}
|
||||
|
||||
public abstract void execute(Frame frame);
|
||||
|
||||
public int index() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public final int offSet() {
|
||||
return this.offSet;
|
||||
}
|
||||
|
||||
public void setOffSet(int offSet) {
|
||||
this.offSet = offSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return index + " " + this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
}
|
||||
631
src/main/java/haidnor/jvm/instruction/InstructionFactory.java
Normal file
631
src/main/java/haidnor/jvm/instruction/InstructionFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
28
src/main/java/haidnor/jvm/instruction/comparisons/DCMPG.java
Normal file
28
src/main/java/haidnor/jvm/instruction/comparisons/DCMPG.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class DCMPG extends Instruction {
|
||||
|
||||
public DCMPG(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
double v2 = frame.popDouble();
|
||||
double v1 = frame.popDouble();
|
||||
if (v1 == v2) {
|
||||
frame.pushInt(0);
|
||||
return;
|
||||
}
|
||||
if (v1 < v2) {
|
||||
frame.pushInt(-1);
|
||||
return;
|
||||
}
|
||||
frame.pushInt(1);
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/haidnor/jvm/instruction/comparisons/DCMPL.java
Normal file
28
src/main/java/haidnor/jvm/instruction/comparisons/DCMPL.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class DCMPL extends Instruction {
|
||||
|
||||
public DCMPL(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
Double v2 = frame.popDouble();
|
||||
Double v1 = frame.popDouble();
|
||||
if (v1.equals(v2)) {
|
||||
frame.pushInt(0);
|
||||
return;
|
||||
}
|
||||
if (v1 < v2) {
|
||||
frame.pushInt(-1);
|
||||
return;
|
||||
}
|
||||
frame.pushInt(1);
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/haidnor/jvm/instruction/comparisons/FCMPG.java
Normal file
28
src/main/java/haidnor/jvm/instruction/comparisons/FCMPG.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class FCMPG extends Instruction {
|
||||
|
||||
public FCMPG(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
float v2 = frame.popFloat();
|
||||
float v1 = frame.popFloat();
|
||||
if (v1 == v2) {
|
||||
frame.pushInt(0);
|
||||
return;
|
||||
}
|
||||
if (v1 < v2) {
|
||||
frame.pushInt(-1);
|
||||
return;
|
||||
}
|
||||
frame.pushInt(1);
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/haidnor/jvm/instruction/comparisons/FCMPL.java
Normal file
28
src/main/java/haidnor/jvm/instruction/comparisons/FCMPL.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class FCMPL extends Instruction {
|
||||
|
||||
public FCMPL(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
float v2 = frame.popFloat();
|
||||
float v1 = frame.popFloat();
|
||||
if (v1 == v2) {
|
||||
frame.pushInt(0);
|
||||
return;
|
||||
}
|
||||
if (v1 < v2) {
|
||||
frame.pushInt(-1);
|
||||
return;
|
||||
}
|
||||
frame.pushInt(1);
|
||||
}
|
||||
|
||||
}
|
||||
34
src/main/java/haidnor/jvm/instruction/comparisons/IFEQ.java
Normal file
34
src/main/java/haidnor/jvm/instruction/comparisons/IFEQ.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IFEQ extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IFEQ(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
if ((int) v1.getValue() == 0) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/main/java/haidnor/jvm/instruction/comparisons/IFGE.java
Normal file
34
src/main/java/haidnor/jvm/instruction/comparisons/IFGE.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IFGE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IFGE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
if ((int) v1.getValue() >= 0) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/main/java/haidnor/jvm/instruction/comparisons/IFGT.java
Normal file
34
src/main/java/haidnor/jvm/instruction/comparisons/IFGT.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IFGT extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IFGT(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
if ((int) v1.getValue() > 0) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/main/java/haidnor/jvm/instruction/comparisons/IFLE.java
Normal file
34
src/main/java/haidnor/jvm/instruction/comparisons/IFLE.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IFLE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IFLE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
if ((int) v1.getValue() <= 0) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/main/java/haidnor/jvm/instruction/comparisons/IFLT.java
Normal file
34
src/main/java/haidnor/jvm/instruction/comparisons/IFLT.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IFLT extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IFLT(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
if ((int) v1.getValue() < 0) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/main/java/haidnor/jvm/instruction/comparisons/IFNE.java
Normal file
34
src/main/java/haidnor/jvm/instruction/comparisons/IFNE.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IFNE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IFNE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
if ((int) v1.getValue() != 0) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IF_ACMPEQ extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ACMPEQ(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
Object val2 = frame.popRef();
|
||||
Object val1 = frame.popRef();
|
||||
if (val1 == val2) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class IF_ACMPNE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ACMPNE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
Object val2 = frame.popRef();
|
||||
Object val1 = frame.popRef();
|
||||
if (val1 != val2) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.if_icmp_cond"> Opcode
|
||||
* definitions in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class IF_ICMPEQ extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ICMPEQ(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
StackValue v2 = frame.pop();
|
||||
|
||||
if ((int) v1.getValue() == (int) v2.getValue()) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.if_icmp_cond"> Opcode
|
||||
* definitions in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class IF_ICMPGE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ICMPGE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v2 = frame.pop();
|
||||
StackValue v1 = frame.pop();
|
||||
|
||||
if ((int) v1.getValue() >= (int) v2.getValue()) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.if_icmp_cond"> Opcode
|
||||
* definitions in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class IF_ICMPGT extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ICMPGT(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v2 = frame.pop();
|
||||
StackValue v1 = frame.pop();
|
||||
|
||||
if ((int) v1.getValue() > (int) v2.getValue()) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.if_icmp_cond"> Opcode
|
||||
* definitions in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class IF_ICMPLE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ICMPLE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v2 = frame.pop();
|
||||
StackValue v1 = frame.pop();
|
||||
|
||||
if ((int) v1.getValue() <= (int) v2.getValue()) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.if_icmp_cond"> Opcode
|
||||
* definitions in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class IF_ICMPLT extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ICMPLT(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v2 = frame.pop();
|
||||
StackValue v1 = frame.pop();
|
||||
|
||||
if ((int) v1.getValue() < (int) v2.getValue()) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.if_icmp_cond"> Opcode
|
||||
* definitions in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class IF_ICMPNE extends Instruction {
|
||||
/**
|
||||
* 下次再执行的偏移量
|
||||
*/
|
||||
private final int offSet;
|
||||
|
||||
public IF_ICMPNE(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.offSet = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
StackValue v1 = frame.pop();
|
||||
StackValue v2 = frame.pop();
|
||||
|
||||
if ((int) v1.getValue() != (int) v2.getValue()) {
|
||||
super.setOffSet(offSet);
|
||||
} else {
|
||||
super.setOffSet(3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.index() + " " + this.getClass().getSimpleName() + " " + offSet;
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/haidnor/jvm/instruction/comparisons/LCMP.java
Normal file
28
src/main/java/haidnor/jvm/instruction/comparisons/LCMP.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package haidnor.jvm.instruction.comparisons;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
public class LCMP extends Instruction {
|
||||
|
||||
public LCMP(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
Long v2 = frame.popLong();
|
||||
Long v1 = frame.popLong();
|
||||
if (v1.equals(v2)) {
|
||||
frame.pushInt(0);
|
||||
return;
|
||||
}
|
||||
if (v1 < v2) {
|
||||
frame.pushInt(-1);
|
||||
return;
|
||||
}
|
||||
frame.pushInt(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
public class ACONST_NULL extends Instruction {
|
||||
|
||||
public ACONST_NULL(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_OBJECT, null));
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/java/haidnor/jvm/instruction/constants/BIPUSH.java
Normal file
29
src/main/java/haidnor/jvm/instruction/constants/BIPUSH.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.bipush"> Opcode definitions in
|
||||
* The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class BIPUSH extends Instruction {
|
||||
|
||||
private final int value;
|
||||
|
||||
public BIPUSH(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.value = codeStream.readByte(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.dconst_d"> Opcode definitions
|
||||
* in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class DCONST_0 extends Instruction {
|
||||
|
||||
public DCONST_0(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_DOUBLE, 0.0D));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.dconst_d"> Opcode definitions
|
||||
* in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class DCONST_1 extends Instruction {
|
||||
|
||||
public DCONST_1(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_DOUBLE, 1.0D));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.fconst_f"> Opcode definitions
|
||||
* in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class FCONST_1 extends Instruction {
|
||||
|
||||
public FCONST_1(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_FLOAT, 1.0f));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.fconst_f"> Opcode definitions
|
||||
* in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class FCONST_2 extends Instruction {
|
||||
|
||||
public FCONST_2(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_FLOAT, 2.0f));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_0 extends Instruction {
|
||||
|
||||
public ICONST_0(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, 0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_1 extends Instruction {
|
||||
|
||||
public ICONST_1(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, 1));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_2 extends Instruction {
|
||||
|
||||
public ICONST_2(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, 2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_3 extends Instruction {
|
||||
|
||||
public ICONST_3(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, 3));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_4 extends Instruction {
|
||||
|
||||
public ICONST_4(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, 4));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_5 extends Instruction {
|
||||
|
||||
public ICONST_5(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, 5));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i
|
||||
*/
|
||||
public class ICONST_M1 extends Instruction {
|
||||
|
||||
public ICONST_M1(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, -1));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.lconst_l"> Opcode definitions
|
||||
* in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class LCONST_0 extends Instruction {
|
||||
|
||||
public LCONST_0(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_LONG, 0L));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.lconst_l"> Opcode definitions
|
||||
* in The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class LCONST_1 extends Instruction {
|
||||
|
||||
public LCONST_1(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_LONG, 1L));
|
||||
}
|
||||
|
||||
}
|
||||
58
src/main/java/haidnor/jvm/instruction/constants/LDC.java
Normal file
58
src/main/java/haidnor/jvm/instruction/constants/LDC.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.bcel.Const;
|
||||
import org.apache.bcel.classfile.*;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.ldc"> Opcode definitions in The
|
||||
* Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class LDC extends Instruction {
|
||||
|
||||
private final int constantIndex;
|
||||
|
||||
public LDC(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.constantIndex = codeStream.readUnsignedByte(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void execute(Frame frame) {
|
||||
ConstantPool constantPool = frame.getConstantPool();
|
||||
|
||||
// 从常量池中获取值
|
||||
Constant constant = constantPool.getConstant(constantIndex);
|
||||
|
||||
switch (constant.getTag()) {
|
||||
case Const.CONSTANT_Integer: {
|
||||
ConstantInteger constantInteger = (ConstantInteger) constant;
|
||||
Object value = constantInteger.getConstantValue(constantPool);
|
||||
frame.push(new StackValue(Const.T_INT, value));
|
||||
break;
|
||||
}
|
||||
case Const.CONSTANT_Float: {
|
||||
ConstantFloat constantFloat = (ConstantFloat) constant;
|
||||
Object value = constantFloat.getConstantValue(constantPool);
|
||||
frame.push(new StackValue(Const.T_FLOAT, value));
|
||||
break;
|
||||
}
|
||||
case Const.CONSTANT_String: {
|
||||
ConstantString constString = (ConstantString) constant;
|
||||
Object value = constString.getConstantValue(constantPool);
|
||||
frame.push(new StackValue(Const.T_OBJECT, value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("not supported LDC type" + constant.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/java/haidnor/jvm/instruction/constants/LDC2W.java
Normal file
48
src/main/java/haidnor/jvm/instruction/constants/LDC2W.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
import org.apache.bcel.classfile.Constant;
|
||||
import org.apache.bcel.classfile.ConstantDouble;
|
||||
import org.apache.bcel.classfile.ConstantLong;
|
||||
import org.apache.bcel.classfile.ConstantPool;
|
||||
|
||||
/**
|
||||
* 将 long 或 double 型常量从常量池中推送至栈顶 (宽索引)
|
||||
*/
|
||||
public class LDC2W extends Instruction {
|
||||
|
||||
private final byte constantTag;
|
||||
|
||||
private long longValue;
|
||||
|
||||
private double doubleValue;
|
||||
|
||||
public LDC2W(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
int index = codeStream.readUnsignedShort(this);
|
||||
ConstantPool constantPool = codeStream.getCode().getConstantPool();
|
||||
Constant constant = constantPool.getConstant(index);
|
||||
this.constantTag = constant.getTag();
|
||||
if (constantTag == Const.CONSTANT_Long) {
|
||||
ConstantLong constantLong = (ConstantLong) constant;
|
||||
this.longValue = constantLong.getBytes();
|
||||
} else if (constantTag == Const.CONSTANT_Double) {
|
||||
ConstantDouble constantDouble = (ConstantDouble) constant;
|
||||
this.doubleValue = constantDouble.getBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
if (constantTag == Const.CONSTANT_Long) {
|
||||
frame.push(new StackValue(Const.T_LONG, this.longValue));
|
||||
} else if (constantTag == Const.CONSTANT_Double) {
|
||||
frame.push(new StackValue(Const.T_DOUBLE, this.doubleValue));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
58
src/main/java/haidnor/jvm/instruction/constants/LDC_W.java
Normal file
58
src/main/java/haidnor/jvm/instruction/constants/LDC_W.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.bcel.Const;
|
||||
import org.apache.bcel.classfile.*;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.ldc_w"> Opcode definitions in
|
||||
* The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class LDC_W extends Instruction {
|
||||
|
||||
private final int constantIndex;
|
||||
|
||||
public LDC_W(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.constantIndex = codeStream.readUnsignedShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void execute(Frame frame) {
|
||||
ConstantPool constantPool = frame.getConstantPool();
|
||||
|
||||
// 从常量池中获取值
|
||||
Constant constant = constantPool.getConstant(constantIndex);
|
||||
|
||||
switch (constant.getTag()) {
|
||||
case Const.CONSTANT_Integer: {
|
||||
ConstantInteger constantInteger = (ConstantInteger) constant;
|
||||
Object value = constantInteger.getConstantValue(constantPool);
|
||||
frame.push(new StackValue(Const.T_INT, value));
|
||||
break;
|
||||
}
|
||||
case Const.CONSTANT_Float: {
|
||||
ConstantFloat constantFloat = (ConstantFloat) constant;
|
||||
Object value = constantFloat.getConstantValue(constantPool);
|
||||
frame.push(new StackValue(Const.T_FLOAT, value));
|
||||
break;
|
||||
}
|
||||
case Const.CONSTANT_String: {
|
||||
ConstantString constString = (ConstantString) constant;
|
||||
Object value = constString.getConstantValue(constantPool);
|
||||
frame.push(new StackValue(Const.T_OBJECT, value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("not supported LDCW type" + constant.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
23
src/main/java/haidnor/jvm/instruction/constants/NOP.java
Normal file
23
src/main/java/haidnor/jvm/instruction/constants/NOP.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.nop"> Opcode definitions in The
|
||||
* Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class NOP extends Instruction {
|
||||
|
||||
public NOP(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/java/haidnor/jvm/instruction/constants/SIPUSH.java
Normal file
29
src/main/java/haidnor/jvm/instruction/constants/SIPUSH.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package haidnor.jvm.instruction.constants;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import org.apache.bcel.Const;
|
||||
|
||||
/**
|
||||
* Java VM opcode.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.sipush"> Opcode definitions in
|
||||
* The Java Virtual Machine Specification</a>
|
||||
*/
|
||||
public class SIPUSH extends Instruction {
|
||||
|
||||
private final int value;
|
||||
|
||||
public SIPUSH(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
this.value = codeStream.readShort(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.push(new StackValue(Const.T_INT, value));
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/haidnor/jvm/instruction/control/DRETURN.java
Normal file
26
src/main/java/haidnor/jvm/instruction/control/DRETURN.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.control;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import haidnor.jvm.util.JvmThreadHolder;
|
||||
|
||||
public class DRETURN extends Instruction {
|
||||
|
||||
public DRETURN(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
// 弹出操作数栈中的值
|
||||
StackValue stackValue = frame.pop();
|
||||
// 将当前栈帧从 jvm 线程栈中弹出
|
||||
JvmThreadHolder.get().pop();
|
||||
// 将方法返回值压入前一个栈帧的操作数栈中
|
||||
Frame topFrame = JvmThreadHolder.get().peek();
|
||||
topFrame.push(stackValue);
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/haidnor/jvm/instruction/control/FRETURN.java
Normal file
26
src/main/java/haidnor/jvm/instruction/control/FRETURN.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.control;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import haidnor.jvm.util.JvmThreadHolder;
|
||||
|
||||
public class FRETURN extends Instruction {
|
||||
|
||||
public FRETURN(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
// 弹出操作数栈中的值
|
||||
StackValue stackValue = frame.pop();
|
||||
// 将当前栈帧从 jvm 线程栈中弹出
|
||||
JvmThreadHolder.get().pop();
|
||||
// 将方法返回值压入前一个栈帧的操作数栈中
|
||||
Frame topFrame = JvmThreadHolder.get().peek();
|
||||
topFrame.push(stackValue);
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/haidnor/jvm/instruction/control/IRETURN.java
Normal file
26
src/main/java/haidnor/jvm/instruction/control/IRETURN.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.control;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import haidnor.jvm.util.JvmThreadHolder;
|
||||
|
||||
public class IRETURN extends Instruction {
|
||||
|
||||
public IRETURN(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
// 弹出操作数栈中的值
|
||||
StackValue stackValue = frame.pop();
|
||||
// 将当前栈帧从 jvm 线程栈中弹出
|
||||
JvmThreadHolder.get().pop();
|
||||
// 将方法返回值压入前一个栈帧的操作数栈中
|
||||
Frame topFrame = JvmThreadHolder.get().peek();
|
||||
topFrame.push(stackValue);
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/haidnor/jvm/instruction/control/LRETURN.java
Normal file
26
src/main/java/haidnor/jvm/instruction/control/LRETURN.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package haidnor.jvm.instruction.control;
|
||||
|
||||
import haidnor.jvm.instruction.Instruction;
|
||||
import haidnor.jvm.runtime.Frame;
|
||||
import haidnor.jvm.runtime.StackValue;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import haidnor.jvm.util.JvmThreadHolder;
|
||||
|
||||
public class LRETURN extends Instruction {
|
||||
|
||||
public LRETURN(CodeStream codeStream) {
|
||||
super(codeStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
// 弹出操作数栈中的值
|
||||
StackValue stackValue = frame.pop();
|
||||
// 将当前栈帧从 jvm 线程栈中弹出
|
||||
JvmThreadHolder.get().pop();
|
||||
// 将方法返回值压入前一个栈帧的操作数栈中
|
||||
Frame topFrame = JvmThreadHolder.get().peek();
|
||||
topFrame.push(stackValue);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user