primordial memory structure and bytecode execution
This commit is contained in:
parent
4bba81c3f0
commit
edb0b77a61
73
class.js
73
class.js
@ -52,7 +52,7 @@ var log = function (msg){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ClassDefinition = function (file){
|
var ClassDefinition = function (file,jvm){
|
||||||
var dataStream = new DataStream(slurpFile(file)[1]);
|
var dataStream = new DataStream(slurpFile(file)[1]);
|
||||||
this.magic = dataStream.getU4();
|
this.magic = dataStream.getU4();
|
||||||
if (this.magic != 0xCAFEBABE){
|
if (this.magic != 0xCAFEBABE){
|
||||||
@ -75,7 +75,6 @@ var ClassDefinition = function (file){
|
|||||||
}
|
}
|
||||||
this.interface_count = dataStream.getU2();
|
this.interface_count = dataStream.getU2();
|
||||||
|
|
||||||
// VER: interfaces refs must be classes
|
|
||||||
this.interfaces = [];
|
this.interfaces = [];
|
||||||
for(var i=0; i<this.interface_count; i++){
|
for(var i=0; i<this.interface_count; i++){
|
||||||
this.interfaces[i] = ConstantPoolRef(dataStream.getU2(), this.constantPool,CONSTANT_Class);
|
this.interfaces[i] = ConstantPoolRef(dataStream.getU2(), this.constantPool,CONSTANT_Class);
|
||||||
@ -93,8 +92,72 @@ var ClassDefinition = function (file){
|
|||||||
for(var i=0; i<this.methods_count; i++){
|
for(var i=0; i<this.methods_count; i++){
|
||||||
this.methods[i] = new MethodInfo(dataStream, this.constantPool);
|
this.methods[i] = new MethodInfo(dataStream, this.constantPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Post added info;
|
||||||
|
this.jvm = jvm;
|
||||||
|
this className = this.this_class.name_ref.str.replace(/\//g,".");
|
||||||
}
|
}
|
||||||
|
|
||||||
function LoadClassFile (x){
|
ClassDefinition.prototype.isInterface = function () {
|
||||||
return new ClassDefinition(x);
|
return ACC_INTERFACE & this.access_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClassDefinition.prototype.isArrayClass = function (){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassDefinition.prototype.isAssignable = function (T) {
|
||||||
|
// 2.6.7 Assignment Conversion
|
||||||
|
if (this.isInterface()){
|
||||||
|
if (T.isInterface()){
|
||||||
|
return this.isInterfaceOrSuperInterface(T);
|
||||||
|
}else{
|
||||||
|
return T == this.jvm.java_lang_object;
|
||||||
|
}
|
||||||
|
}else if(this.isArrayClass()){
|
||||||
|
if (T.isInterface()){
|
||||||
|
return (T == this.jvm.java_lang_cloneable || T == this.jvm.java_io_serializable);
|
||||||
|
}else if (T.isArrayClass()){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return T == this.jvm.java_lang_object;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (T.isInterface()){
|
||||||
|
return this.isInterfaceOrSuperInterface(T);
|
||||||
|
}else{
|
||||||
|
return this.isClassOrSuperClass(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassDefinition.prototype.isClassOrSuperClass = function(C){
|
||||||
|
if (this == C){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
if (this.jvm.java_lang_object == this){
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
this.jvm.classForName(this.super_class.name_ref).isClassOrSuperClass(C);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassDefinition.prototype.isInterfaceOrSuperInterface = function(I){
|
||||||
|
if (this == I){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
for(var i; i<this.interface_count; i++){
|
||||||
|
if (this.interfaces[i].isInterfaceOrSuperInterface(I)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function LoadClassFile (x,jvm){
|
||||||
|
return new ClassDefinition(x,jvm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
93
cpu.js
93
cpu.js
@ -9,37 +9,52 @@ var JVM = function(params,args){
|
|||||||
this.method_area = {};
|
this.method_area = {};
|
||||||
this.level = 0;
|
this.level = 0;
|
||||||
this.classpath = params.classes_to_load;
|
this.classpath = params.classes_to_load;
|
||||||
this.verifyAndLoadClass = function(classFile){
|
|
||||||
if (!this.method_area[classFile]){
|
|
||||||
// log(">>>>>> " + classFile);
|
|
||||||
var loaded_class = LoadClassFile(classFile);
|
|
||||||
var className = loaded_class.this_class.name_ref.str.replace(/\//g,".");
|
|
||||||
|
|
||||||
|
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.method_area[className] = loaded_class;
|
||||||
var superClass;
|
this.verifyAndLoadClass(loaded_class);
|
||||||
if(loaded_class.super_class){
|
|
||||||
superClass = canonicalName(loaded_class.super_class.name_ref);
|
|
||||||
}else{
|
|
||||||
superClass = "java.lang.Object";
|
|
||||||
}
|
|
||||||
this.verifyAndLoadClass(superClass);
|
|
||||||
|
|
||||||
|
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;
|
var that = this;
|
||||||
|
|
||||||
loaded_class.constantPool.each(function(constant){
|
loaded_class.constantPool.each(function(constant){
|
||||||
if (constant.name_ref.str.charAt(0) == "[") {
|
if (constant.name_ref.str.charAt(0) == "[") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
that.verifyAndLoadClass(canonicalName(constant.name_ref));
|
that.verifyAndLoadClass(canonicalName(constant.name_ref));
|
||||||
}, CONSTANT_Class);
|
}, CONSTANT_Class);*/
|
||||||
|
|
||||||
log("[Loaded " + className + " from runtime/" + classFile + "]");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.run = function (){
|
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];
|
var mainClass = this.args[0];
|
||||||
this.verifyAndLoadClass(mainClass);
|
this.classForName(mainClass);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,4 +67,46 @@ var JVMFrame = function(){
|
|||||||
this.local_variables = [];
|
this.local_variables = [];
|
||||||
this.operand_stack = [];
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
39
types.js
Normal file
39
types.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
// Local Variables Types
|
||||||
|
var LOC_VAR_boolean = 0x001;
|
||||||
|
var LOC_VAR_byte = 0x002;
|
||||||
|
var LOC_VAR_char = 0x004;
|
||||||
|
var LOC_VAR_short = 0x008;
|
||||||
|
var LOC_VAR_int = 0x010;
|
||||||
|
var LOC_VAR_float = 0x020;
|
||||||
|
var LOC_VAR_reference = 0x040;
|
||||||
|
var LOC_VAR_returnAddress = 0x080;
|
||||||
|
var LOC_VAR_long = 0x100;
|
||||||
|
var LOC_VAR_double = 0x200;
|
||||||
|
|
||||||
|
// Reference Types
|
||||||
|
var REF_TYPE_class = 0x1;
|
||||||
|
var REF_TYPE_interface = 0x2;
|
||||||
|
var REF_TYPE_array = 0x4
|
||||||
|
|
||||||
|
function makeLocalVar(kind){
|
||||||
|
return {id:kind};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRefClass(ref){
|
||||||
|
if (ref.type == REF_TYPE_array){
|
||||||
|
return getArrayClass();
|
||||||
|
}else{
|
||||||
|
return ref.classRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var NULL = makeLocalVar(LOC_VAR_reference);
|
||||||
|
|
||||||
|
function isSubClass(refS,refT){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function implements(refS,refT){
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user