can make instances, without <init>

This commit is contained in:
Artur Ventura 2011-07-17 18:42:58 +01:00
parent 4beb1403ab
commit 3ea052a707
6 changed files with 137 additions and 32 deletions

View File

@ -9,6 +9,8 @@
*
*/
#define CLASS_MAGIC 0xCAFEBABE
#define ACC_PUBLIC 0x0001 // Declared public; may be accessed from outside its package.
#define ACC_PRIVATE 0x0002 // Declared private; usable only within the defining class.
#define ACC_PROTECTED 0x0004 // Declared protected; may be accessed within subclasses.
@ -62,7 +64,7 @@ var ClassDefinition = function(jvm) {
// bad bad code! This shouldn't be done this way!
ClassDefinition.prototype.makeForArray = function(arrayDef){
this.magic = 0xCAFEBABE;
this.magic = CLASS_MAGIC;
this.minorVersion = 0;
this.majorVersion = 50;
this.constantPool = [];
@ -110,7 +112,7 @@ ClassDefinition.prototype.makeForArray = function(arrayDef){
ClassDefinition.prototype.loadFromFile = function (file){
var dataStream = new DataStream(slurpFile(file)[1]);
this.magic = dataStream.getU4();
if (this.magic != 0xCAFEBABE){
if (this.magic != CLASS_MAGIC){
throw "Invalid Class Magic (" + this.magic + ")" ;
}
this.minorVersion = dataStream.getU2();
@ -208,7 +210,7 @@ ClassDefinition.prototype.isClassOrSuperClass = function(C){
if (this.jvm.java_lang_object == this){
return false;
}else{
this.jvm.classForName(this.super_class.name_ref).isClassOrSuperClass(C);
this.super_class_ref.isClassOrSuperClass(C);
}
}
}
@ -226,6 +228,57 @@ ClassDefinition.prototype.isInterfaceOrSuperInterface = function(I){
}
}
ClassDefinition.prototype.initializeClass = function(){
if (this.super_class && !this.super_class_ref.inited){
this.super_class_ref.initializeClass();
}
this.calculateEffectiveMembers();
// call <cinit>
this.inited = true;
}
ClassDefinition.prototype.calculateEffectiveMembers = function(){
if (!this.effectiveMethods){
var superEffective = (this.super_class)? this.super_class_ref.calculateEffectiveMembers() : [{},{}];
// fields
this.effectiveFields = {}
for(var k in superEffective[0]){
this.effectiveFields[k] = superEffective[0][k];
}
for(var i=0; i<this.fields_count; i++){
var field = this.fields[i]
this.effectiveFields[this.this_class.name_ref.str + " " + field.name_ref.str] = field;
}
// methods
this.effectiveMethods = {}
for(var k in superEffective[1]){
this.effectiveMethods[k] = superEffective[1][k];
}
for(var i=0; i<this.methods_count; i++){
var method = this.methods[i]
this.effectiveMethods[this.this_class.name_ref.str + " " + method.name_ref.str + method.descriptor_ref.str] = method;
}
}
return [this.effectiveFields,this.effectiveMethods];
}
ClassDefinition.prototype.makeInstance = function(){
if (!this.inited) { this.initializeClass(); }
var newInstance = {};
for(var k in this.effectiveFields){
newInstance[k] = (this.effectiveFields[k].primitive)?0:null;
}
newInstance["class"] = this;
return newInstance;
}
function LoadClassFile (x,jvm){
var def = new ClassDefinition(jvm);
if (x.charAt(0) != "[" ){

11
cpu.js
View File

@ -26,7 +26,7 @@ function canonicalName(ref){
}
var JVM = function(params,args){
this.heap = {};
this.nativeMappingTable = {}
this.params = params;
this.args = args;
this.method_area = {};
@ -34,6 +34,7 @@ var JVM = function(params,args){
this.classpath = params.classes_to_load;
this.classForName = function (name){
if (!name) { PANIC("undefined className")}
var superClass, loaded_class = this.method_area[name];
if (!loaded_class){
@ -52,8 +53,8 @@ var JVM = function(params,args){
var superClass;
if(loaded_class.super_class){
// if super_class not java.lang.Object
superClass = canonicalName(loaded_class.super_class.name_ref);
this.classForName(superClass);
superClass = canonicalName(loaded_class.super_class.name_ref);
loaded_class.super_class_ref = this.classForName(superClass);
}
// this doesn't seem right. doing this will cause the entire JRE to be loaded
@ -74,8 +75,8 @@ var JVM = function(params,args){
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);
this.mainClass = this.args[0];
this.classForName(this.mainClass).makeInstance();
};
};

View File

@ -11,8 +11,10 @@
var FieldInfo = function(dStream,constantPool){
this.access_flags = dStream.getU2();
this.name_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.descriptor_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.name_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.descriptor_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
var type = this.descriptor_ref.str.charAt(0);
this.primitive = (type == "L" || type == "[")?false:true;
this.attributes_count = dStream.getU2();
this.attributes = [];
for (var i=0; i<this.attributes_count; i++){
@ -22,8 +24,8 @@ var FieldInfo = function(dStream,constantPool){
var MethodInfo = function(dStream, constantPool){
this.access_flags = dStream.getU2();
this.name_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.descriptor_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.name_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.descriptor_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
this.attributes_count = dStream.getU2();
this.attributes = [];
for (var i=0; i<this.attributes_count; i++){

View File

@ -62,13 +62,13 @@ DEFOP(ANEWARRAY)
JVM_THROWS_NEW(java.lang.NegativeArraySizeException);
}
var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2);
var instance = {length)count, value)[], classRef)this.jvm.classForName(clRef)};
var instance = {length:count, value:[], classRef:this.jvm.classForName(clRef)};
operand_stack.push(instance);
ENDDEF
DEFOP(ARETURN)
var objectref = operand_stack.pop();
return {return_object) objectref}
return {return_object: objectref}
ENDDEF
DEFOP(ARRAYLENGTH)

View File

@ -31,6 +31,6 @@
var test_jvm;
function main (args){
test_jvm = new JVM({},["[I"])
test_jvm = new JVM({},["foo"])
test_jvm.run();
}

View File

@ -10,25 +10,74 @@
*/
// 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;
#define LOC_VAR_boolean 0x001;
#define LOC_VAR_byte 0x002;
#define LOC_VAR_char 0x004;
#define LOC_VAR_short 0x008;
#define LOC_VAR_int 0x010;
#define LOC_VAR_float 0x020;
#define LOC_VAR_reference 0x040;
#define LOC_VAR_returnAddress 0x080;
#define LOC_VAR_long 0x100;
#define LOC_VAR_double 0x200;
// Reference Types
var REF_TYPE_class = 0x1;
var REF_TYPE_interface = 0x2;
var REF_TYPE_array = 0x4
#define REF_TYPE_class 0x1
#define REF_TYPE_interface 0x2
#define REF_TYPE_array 0x4
function makeLocalVar(kind){
return {id:kind};
}
//primitive max Max values
#define CHAR_MAX_VALUE 0x0000
#define CHAR_MIN_VALUE 0xFFFF
#define BYTE_MAX_VALUE 127
#define BYTE_MIN_VALUE -128
#define BYTE_USIZE 128
#define SHORT_MAX_VALUE 32767
#define SHORT_MIN_VALUE -32768
#define SHORT_USIZE 32768
#define INT_MAX_VALUE 2147483647
#define INT_MIN_VALUE -2147483648
#define INT_USIZE 2147483648
#define LONG_MAX_VALUE 9223372036854776000
#define LONG_MIN_VALUE -9223372036854776000
#define LONG_USIZE 9223372036854776000
#define FLOAT_MAX_VALUE (2-Math.pow(2,-23))*Math.pow(2,127)
#define FLOAT_MIN_VALUE (2-Math.pow(2,-149))
#define DOUBLE_MAX_VALUE (2-Math.pow(2,-52))*Math.pow(2,1023)
#define DOUBLE_MIN_VALUE Math.pow(2,-1074)
#define NULL null
#define CHAR_OVERFLOW(value) ((value % (2*CHAR_MIN_VALUE)) - (CHAR_MIN_VALUE))
#define BYTE_OVERFLOW(value) ((value % (2*BYTE_USIZE)) - (BYTE_USIZE))
#define SHORT_OVERFLOW(value) ((value % (2*SHORT_USIZE)) - (SHORT_USIZE))
#define INT_OVERFLOW(value) ((value % (2*INT_USIZE)) - (INT_USIZE))
#define LONG_OVERFLOW(value) ((value % (2*LONG_USIZE)) - (LONG_USIZE))
#define POSITIVE_INF Number.POSITIVE_INFINITY
#define NEGATIVE_INF Number.NEGATIVE_INFINITY
#define NAN NaN
#define IS_OVERFLOW(value,mark) (value > mark)
#define IS_UNDERFLOW(value,mark) (value < mark)
#define ADD(value1,value2) (value1)+(value2)
#define AND(value1,value2) (value1)&(value2)
#define DIV(value1,value2) (value1)/(value2)
#define MUL(value1,value2) (value1)*(value2)
#define NEG(value1) -(value1)
#define OR(value1,value2) (value1)|(value2)
#define REM(value1,value2) (value1)%(value2)
#define SHL(value1,value2) (value1)<<(0x001f&(value2))
#define SHR(value1,value2) (value1)>>(0x001f&(value2))
#define SUB(value1,value2) ((value1)-(value2))
#define USHR(value1,value2) ((value1)>0?(value1)>>s:((value1)>>s) + (2<<~s))
#define XOR(value1,value2) ((value1)^(value2))
function getRefClass(ref){
if (ref.type == REF_TYPE_array){
@ -38,5 +87,5 @@ function getRefClass(ref){
}
}
var NULL = makeLocalVar(LOC_VAR_reference);