112 lines
3.1 KiB
JavaScript
112 lines
3.1 KiB
JavaScript
function canonicalName(ref){
|
|
return ref.str.replace(/\//g,".")
|
|
}
|
|
|
|
var JVM = function(params,args){
|
|
this.heap = {};
|
|
this.params = params;
|
|
this.args = args;
|
|
this.method_area = {};
|
|
this.level = 0;
|
|
this.classpath = params.classes_to_load;
|
|
|
|
this.classForName = function (name){
|
|
var superClass, loaded_class = this.method_area[name];
|
|
|
|
if (!loaded_class){
|
|
loaded_class = LoadClassFile(name, this);
|
|
this.method_area[className] = loaded_class;
|
|
this.verifyAndLoadClass(loaded_class);
|
|
|
|
log("[Loaded " + className + " from runtime/" + classFile + "]");
|
|
}
|
|
|
|
return loaded_class;
|
|
|
|
}
|
|
|
|
this.verifyAndLoadClass = function(classFile){
|
|
var superClass;
|
|
if(loaded_class.super_class){
|
|
superClass = canonicalName(loaded_class.super_class.name_ref);
|
|
}else{
|
|
superClass = "java.lang.Object";
|
|
}
|
|
this.classForName(superClass);
|
|
|
|
// this doesn't seem right. doing this will cause the entire JRE to be loaded
|
|
// as soon as you start JVM.
|
|
|
|
/*
|
|
var that = this;
|
|
|
|
loaded_class.constantPool.each(function(constant){
|
|
if (constant.name_ref.str.charAt(0) == "[") {
|
|
return;
|
|
}
|
|
that.verifyAndLoadClass(canonicalName(constant.name_ref));
|
|
}, CONSTANT_Class);*/
|
|
};
|
|
|
|
this.run = function (){
|
|
this.java_lang_object = this.classForName("java.lang.Object");
|
|
this.java_lang_cloneable = this.classForName("java.lang.Cloneable");
|
|
this.java_io_serializable = this.classForName("java.io.Serializable");
|
|
|
|
var mainClass = this.args[0];
|
|
this.classForName(mainClass);
|
|
};
|
|
};
|
|
|
|
var JVMThread = function(){
|
|
this.pc = null;
|
|
this.stack = [];
|
|
}
|
|
|
|
var JVMFrame = function(){
|
|
this.local_variables = [];
|
|
this.operand_stack = [];
|
|
|
|
}
|
|
|
|
function JVM_THROWS_NEW(exception){
|
|
throw "VER: throws new " + exception;
|
|
}
|
|
|
|
function (frame){
|
|
var operand_stack = frame.operand_stack;
|
|
|
|
switch(opcode){
|
|
case 0x32: // aaload
|
|
var index = operand_stack.pop();
|
|
var arrayref = operand_stack.pop();
|
|
|
|
if (arrayref == NULL){
|
|
JVM_THROWS_NEW("java.lang.NullPointerException");
|
|
}
|
|
if (index >= arrayref.length){
|
|
JVM_THROWS_NEW("java.lang.ArrayIndexOutOfBoundsException");
|
|
}
|
|
operand_stack.push(arrayref.value[index.value]);
|
|
break;
|
|
|
|
case 0x53: // aastore
|
|
var value = operand_stack.pop();
|
|
var index = operand_stack.pop();
|
|
var arrayref = operand_stack.pop();
|
|
|
|
if (arrayref == NULL){
|
|
JVM_THROWS_NEW("java.lang.NullPointerException");
|
|
}
|
|
if (index >= arrayref.length){
|
|
JVM_THROWS_NEW("java.lang.ArrayIndexOutOfBoundsException");
|
|
}
|
|
|
|
if (value.ref_of == REF_TYPE_class){
|
|
if (isSubClass(value.ref_of,arrayref.of));
|
|
}
|
|
|
|
|
|
|
|
}
|
|
} |