add Instruction

This commit is contained in:
wangxiang
2023-07-22 10:21:51 +08:00
parent 5f8d9567bc
commit 7682b70aca
11 changed files with 99 additions and 23 deletions

View File

@@ -19,30 +19,30 @@ import java.util.Map;
@Slf4j
public class Interpreter {
private static int frameCount = -1;
@SneakyThrows
public static void executeFrame(Frame frame) {
frameCount++;
int stackSize = frame.getJvmThread().stackSize();
StringBuilder blank = new StringBuilder();
blank.append(" ".repeat(Math.max(0, frameCount)));
blank.append(" ".repeat(stackSize - 1));
int index = 0;
for (int i = 0; i < frameCount; i++) {
for (int i = 0; i < stackSize - 1; i++) {
blank.replace(index, index + 1, "");
index += 20;
}
log.debug("{}┌──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod());
Map<Integer, Instruction> instructionMap = new HashMap<>();
log.debug("{}┌──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
// 解析方法中的字节码指令
Map<Integer, Instruction> instructionMap = new HashMap<>();
CodeStream codeStream = frame.getCodeStream();
while (codeStream.available() > 0) {
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
// log.debug("{}│>{}", blank, instruction);
log.debug("{}│> {}", blank, instruction);
instructionMap.put(instruction.index(), instruction);
}
// log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
// 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
for (int i = 0; i < frame.getCodeLength(); ) {
@@ -54,8 +54,8 @@ public class Interpreter {
}
i += instruction.offSet();
}
log.debug("{}└──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod());
frameCount--;
log.debug("{}└──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
}
}

View File

@@ -3,6 +3,9 @@ package haidnor.jvm.instruction;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream;
/**
* @author wang xiang
*/
public abstract class Instruction {
/**
* 指令坐在 code 数组中的索引下标
@@ -10,7 +13,7 @@ public abstract class Instruction {
private final int index;
/**
* 执行下一个执行的偏移量
* 执行下一个指令的偏移量
*/
private int offSet = 1;

View File

@@ -598,7 +598,7 @@ public abstract class InstructionFactory {
return new CHECKCAST(codeStream);
}
case Const.INSTANCEOF -> {
throw new Error("Not support JavaVM opcode INSTANCEOF");
return new INSTANCEOF(codeStream);
}
case Const.MONITORENTER -> {
throw new Error("Not support JavaVM opcode MONITORENTER");

View File

@@ -0,0 +1,56 @@
package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.ConstantPoolUtil;
import lombok.SneakyThrows;
import org.apache.bcel.Const;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.Utility;
/**
* @author wang xiang
*/
public class INSTANCEOF extends Instruction {
private final int constantClassIndex;
public INSTANCEOF(CodeStream codeStream) {
super(codeStream);
this.constantClassIndex = codeStream.readUnsignedShort(this);
}
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getConstantPool();
ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil();
ConstantClass constantClass = constantPool.getConstant(constantClassIndex);
String className = constantPoolUtil.getClassName(constantClass);
className = Utility.compactClassName(className);
StackValue stackValue = frame.pop();
Object obj = stackValue.getValue();
Class<?> objClass = obj.getClass();
if (obj instanceof Instance instance) {
String instanceClassName = instance.klass.getClassName();
if (instanceClassName.equals(className)) {
frame.push(new StackValue(Const.T_INT, 1));
} else {
frame.push(new StackValue(Const.T_INT, 0));
}
} else {
if (objClass.getName().equals(className)) {
frame.push(new StackValue(Const.T_INT, 1));
} else {
frame.push(new StackValue(Const.T_INT, 0));
}
}
}
}

View File

@@ -1,7 +1,6 @@
package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
@@ -18,7 +17,7 @@ public class ASTORE extends Instruction {
@Override
public void execute(Frame frame) {
StackValue value = frame.pop();
frame.slotSetRef(index, (Instance) value.getValue());
frame.slotSetRef(index, value.getValue());
}
}

View File

@@ -1,7 +1,6 @@
package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
@@ -15,7 +14,7 @@ public class ASTORE_0 extends Instruction {
@Override
public void execute(Frame frame) {
StackValue value = frame.pop();
frame.slotSetRef(0, (Instance) value.getValue());
frame.slotSetRef(0, value.getValue());
}
}

View File

@@ -1,7 +1,6 @@
package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
@@ -15,7 +14,7 @@ public class ASTORE_3 extends Instruction {
@Override
public void execute(Frame frame) {
StackValue value = frame.pop();
frame.slotSetRef(3, (Instance) value.getValue());
frame.slotSetRef(3, value.getValue());
}
}

View File

@@ -33,7 +33,7 @@ public class Frame {
private final KlassMethod klassMethod;
public final Klass aKlass;
public final Klass klass;
/**
* 栈帧所属的方法代码对象
@@ -63,7 +63,7 @@ public class Frame {
public Frame(JvmThread jvmThread, KlassMethod klassMethod) {
this.jvmThread = jvmThread;
this.aKlass = klassMethod.aKlass;
this.klass = klassMethod.aKlass;
this.klassMethod = klassMethod;
this.method = klassMethod.javaMethod;
this.code = method.getCode();
@@ -103,7 +103,7 @@ public class Frame {
}
public Klass getMetaClass() {
return aKlass;
return klass;
}
/* 操作数栈操作 --------------------------------------------------------------------------------------------------- */

View File

@@ -59,6 +59,11 @@ public class TestJVM {
runMainClass(Demo5.class);
}
@Test
public void test_6() throws Exception {
runMainClass(Demo6.class);
}
@Test
public void test_NEW() throws Exception {
runMainClass(NEW.class);

View File

@@ -11,7 +11,7 @@ public class Demo3 {
Student sut2 = new Student();
HashMap<Student, String> hashMap = new HashMap<>();
hashMap.put(sut1, "张三");
hashMap.put(sut1, "张三123");
hashMap.put(sut2, "张三");
System.out.println(hashMap.get(sut1)); // 1

View File

@@ -0,0 +1,15 @@
package haidnor.jvm.test.demo;
import haidnor.jvm.test.clazz.Student;
public class Demo6 {
public static void main(String[] args) {
Student student = new Student();
if (student instanceof Student) {
System.out.println("instanceof");
}
}
}