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 @Slf4j
public class Interpreter { public class Interpreter {
private static int frameCount = -1;
@SneakyThrows @SneakyThrows
public static void executeFrame(Frame frame) { public static void executeFrame(Frame frame) {
frameCount++; int stackSize = frame.getJvmThread().stackSize();
StringBuilder blank = new StringBuilder(); StringBuilder blank = new StringBuilder();
blank.append(" ".repeat(Math.max(0, frameCount))); blank.append(" ".repeat(stackSize - 1));
int index = 0; int index = 0;
for (int i = 0; i < frameCount; i++) { for (int i = 0; i < stackSize - 1; i++) {
blank.replace(index, index + 1, ""); blank.replace(index, index + 1, "");
index += 20; index += 20;
} }
log.debug("{}┌──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod()); log.debug("{}┌──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
Map<Integer, Instruction> instructionMap = new HashMap<>();
// 解析方法中的字节码指令 // 解析方法中的字节码指令
Map<Integer, Instruction> instructionMap = new HashMap<>();
CodeStream codeStream = frame.getCodeStream(); CodeStream codeStream = frame.getCodeStream();
while (codeStream.available() > 0) { while (codeStream.available() > 0) {
Instruction instruction = InstructionFactory.creatInstruction(codeStream); Instruction instruction = InstructionFactory.creatInstruction(codeStream);
// log.debug("{}│>{}", blank, instruction); log.debug("{}│> {}", blank, instruction);
instructionMap.put(instruction.index(), instruction); instructionMap.put(instruction.index(), instruction);
} }
// log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
// 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“) // 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
for (int i = 0; i < frame.getCodeLength(); ) { for (int i = 0; i < frame.getCodeLength(); ) {
@@ -54,8 +54,8 @@ public class Interpreter {
} }
i += instruction.offSet(); 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.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
/**
* @author wang xiang
*/
public abstract class Instruction { public abstract class Instruction {
/** /**
* 指令坐在 code 数组中的索引下标 * 指令坐在 code 数组中的索引下标
@@ -10,7 +13,7 @@ public abstract class Instruction {
private final int index; private final int index;
/** /**
* 执行下一个执行的偏移量 * 执行下一个指令的偏移量
*/ */
private int offSet = 1; private int offSet = 1;

View File

@@ -598,7 +598,7 @@ public abstract class InstructionFactory {
return new CHECKCAST(codeStream); return new CHECKCAST(codeStream);
} }
case Const.INSTANCEOF -> { case Const.INSTANCEOF -> {
throw new Error("Not support JavaVM opcode INSTANCEOF"); return new INSTANCEOF(codeStream);
} }
case Const.MONITORENTER -> { case Const.MONITORENTER -> {
throw new Error("Not support JavaVM opcode 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; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
@@ -18,7 +17,7 @@ public class ASTORE extends Instruction {
@Override @Override
public void execute(Frame frame) { public void execute(Frame frame) {
StackValue value = frame.pop(); 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; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
@@ -15,7 +14,7 @@ public class ASTORE_0 extends Instruction {
@Override @Override
public void execute(Frame frame) { public void execute(Frame frame) {
StackValue value = frame.pop(); 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; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
@@ -15,7 +14,7 @@ public class ASTORE_3 extends Instruction {
@Override @Override
public void execute(Frame frame) { public void execute(Frame frame) {
StackValue value = frame.pop(); 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; 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) { public Frame(JvmThread jvmThread, KlassMethod klassMethod) {
this.jvmThread = jvmThread; this.jvmThread = jvmThread;
this.aKlass = klassMethod.aKlass; this.klass = klassMethod.aKlass;
this.klassMethod = klassMethod; this.klassMethod = klassMethod;
this.method = klassMethod.javaMethod; this.method = klassMethod.javaMethod;
this.code = method.getCode(); this.code = method.getCode();
@@ -103,7 +103,7 @@ public class Frame {
} }
public Klass getMetaClass() { public Klass getMetaClass() {
return aKlass; return klass;
} }
/* 操作数栈操作 --------------------------------------------------------------------------------------------------- */ /* 操作数栈操作 --------------------------------------------------------------------------------------------------- */

View File

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

View File

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