can make instances, without <init>
This commit is contained in:
parent
4beb1403ab
commit
3ea052a707
59
class.js
59
class.js
@ -9,6 +9,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define CLASS_MAGIC 0xCAFEBABE
|
||||||
|
|
||||||
#define ACC_PUBLIC 0x0001 // Declared public; may be accessed from outside its package.
|
#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_PRIVATE 0x0002 // Declared private; usable only within the defining class.
|
||||||
#define ACC_PROTECTED 0x0004 // Declared protected; may be accessed within subclasses.
|
#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!
|
// bad bad code! This shouldn't be done this way!
|
||||||
ClassDefinition.prototype.makeForArray = function(arrayDef){
|
ClassDefinition.prototype.makeForArray = function(arrayDef){
|
||||||
this.magic = 0xCAFEBABE;
|
this.magic = CLASS_MAGIC;
|
||||||
this.minorVersion = 0;
|
this.minorVersion = 0;
|
||||||
this.majorVersion = 50;
|
this.majorVersion = 50;
|
||||||
this.constantPool = [];
|
this.constantPool = [];
|
||||||
@ -110,7 +112,7 @@ ClassDefinition.prototype.makeForArray = function(arrayDef){
|
|||||||
ClassDefinition.prototype.loadFromFile = function (file){
|
ClassDefinition.prototype.loadFromFile = function (file){
|
||||||
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 != CLASS_MAGIC){
|
||||||
throw "Invalid Class Magic (" + this.magic + ")" ;
|
throw "Invalid Class Magic (" + this.magic + ")" ;
|
||||||
}
|
}
|
||||||
this.minorVersion = dataStream.getU2();
|
this.minorVersion = dataStream.getU2();
|
||||||
@ -208,7 +210,7 @@ ClassDefinition.prototype.isClassOrSuperClass = function(C){
|
|||||||
if (this.jvm.java_lang_object == this){
|
if (this.jvm.java_lang_object == this){
|
||||||
return false;
|
return false;
|
||||||
}else{
|
}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){
|
function LoadClassFile (x,jvm){
|
||||||
var def = new ClassDefinition(jvm);
|
var def = new ClassDefinition(jvm);
|
||||||
if (x.charAt(0) != "[" ){
|
if (x.charAt(0) != "[" ){
|
||||||
|
11
cpu.js
11
cpu.js
@ -26,7 +26,7 @@ function canonicalName(ref){
|
|||||||
}
|
}
|
||||||
|
|
||||||
var JVM = function(params,args){
|
var JVM = function(params,args){
|
||||||
this.heap = {};
|
this.nativeMappingTable = {}
|
||||||
this.params = params;
|
this.params = params;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
this.method_area = {};
|
this.method_area = {};
|
||||||
@ -34,6 +34,7 @@ var JVM = function(params,args){
|
|||||||
this.classpath = params.classes_to_load;
|
this.classpath = params.classes_to_load;
|
||||||
|
|
||||||
this.classForName = function (name){
|
this.classForName = function (name){
|
||||||
|
if (!name) { PANIC("undefined className")}
|
||||||
var superClass, loaded_class = this.method_area[name];
|
var superClass, loaded_class = this.method_area[name];
|
||||||
|
|
||||||
if (!loaded_class){
|
if (!loaded_class){
|
||||||
@ -52,8 +53,8 @@ var JVM = function(params,args){
|
|||||||
var superClass;
|
var superClass;
|
||||||
if(loaded_class.super_class){
|
if(loaded_class.super_class){
|
||||||
// if super_class not java.lang.Object
|
// if super_class not java.lang.Object
|
||||||
superClass = canonicalName(loaded_class.super_class.name_ref);
|
superClass = canonicalName(loaded_class.super_class.name_ref);
|
||||||
this.classForName(superClass);
|
loaded_class.super_class_ref = this.classForName(superClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this doesn't seem right. doing this will cause the entire JRE to be loaded
|
// 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_object = this.classForName("java.lang.Object");
|
||||||
this.java_lang_cloneable = this.classForName("java.lang.Cloneable");
|
this.java_lang_cloneable = this.classForName("java.lang.Cloneable");
|
||||||
this.java_io_serializable = this.classForName("java.io.Serializable");
|
this.java_io_serializable = this.classForName("java.io.Serializable");
|
||||||
var mainClass = this.args[0];
|
this.mainClass = this.args[0];
|
||||||
this.classForName(mainClass);
|
this.classForName(this.mainClass).makeInstance();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
10
infos.js
10
infos.js
@ -11,8 +11,10 @@
|
|||||||
|
|
||||||
var FieldInfo = function(dStream,constantPool){
|
var FieldInfo = function(dStream,constantPool){
|
||||||
this.access_flags = dStream.getU2();
|
this.access_flags = dStream.getU2();
|
||||||
this.name_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
|
this.name_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
|
||||||
this.descriptor_index = 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_count = dStream.getU2();
|
||||||
this.attributes = [];
|
this.attributes = [];
|
||||||
for (var i=0; i<this.attributes_count; i++){
|
for (var i=0; i<this.attributes_count; i++){
|
||||||
@ -22,8 +24,8 @@ var FieldInfo = function(dStream,constantPool){
|
|||||||
|
|
||||||
var MethodInfo = function(dStream, constantPool){
|
var MethodInfo = function(dStream, constantPool){
|
||||||
this.access_flags = dStream.getU2();
|
this.access_flags = dStream.getU2();
|
||||||
this.name_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
|
this.name_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
|
||||||
this.descriptor_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
|
this.descriptor_ref = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8);
|
||||||
this.attributes_count = dStream.getU2();
|
this.attributes_count = dStream.getU2();
|
||||||
this.attributes = [];
|
this.attributes = [];
|
||||||
for (var i=0; i<this.attributes_count; i++){
|
for (var i=0; i<this.attributes_count; i++){
|
||||||
|
4
intrp.js
4
intrp.js
@ -62,13 +62,13 @@ DEFOP(ANEWARRAY)
|
|||||||
JVM_THROWS_NEW(java.lang.NegativeArraySizeException);
|
JVM_THROWS_NEW(java.lang.NegativeArraySizeException);
|
||||||
}
|
}
|
||||||
var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2);
|
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);
|
operand_stack.push(instance);
|
||||||
ENDDEF
|
ENDDEF
|
||||||
|
|
||||||
DEFOP(ARETURN)
|
DEFOP(ARETURN)
|
||||||
var objectref = operand_stack.pop();
|
var objectref = operand_stack.pop();
|
||||||
return {return_object) objectref}
|
return {return_object: objectref}
|
||||||
ENDDEF
|
ENDDEF
|
||||||
|
|
||||||
DEFOP(ARRAYLENGTH)
|
DEFOP(ARRAYLENGTH)
|
||||||
|
2
main.js
2
main.js
@ -31,6 +31,6 @@
|
|||||||
|
|
||||||
var test_jvm;
|
var test_jvm;
|
||||||
function main (args){
|
function main (args){
|
||||||
test_jvm = new JVM({},["[I"])
|
test_jvm = new JVM({},["foo"])
|
||||||
test_jvm.run();
|
test_jvm.run();
|
||||||
}
|
}
|
83
types.js
83
types.js
@ -10,25 +10,74 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Local Variables Types
|
// Local Variables Types
|
||||||
var LOC_VAR_boolean = 0x001;
|
#define LOC_VAR_boolean 0x001;
|
||||||
var LOC_VAR_byte = 0x002;
|
#define LOC_VAR_byte 0x002;
|
||||||
var LOC_VAR_char = 0x004;
|
#define LOC_VAR_char 0x004;
|
||||||
var LOC_VAR_short = 0x008;
|
#define LOC_VAR_short 0x008;
|
||||||
var LOC_VAR_int = 0x010;
|
#define LOC_VAR_int 0x010;
|
||||||
var LOC_VAR_float = 0x020;
|
#define LOC_VAR_float 0x020;
|
||||||
var LOC_VAR_reference = 0x040;
|
#define LOC_VAR_reference 0x040;
|
||||||
var LOC_VAR_returnAddress = 0x080;
|
#define LOC_VAR_returnAddress 0x080;
|
||||||
var LOC_VAR_long = 0x100;
|
#define LOC_VAR_long 0x100;
|
||||||
var LOC_VAR_double = 0x200;
|
#define LOC_VAR_double 0x200;
|
||||||
|
|
||||||
// Reference Types
|
// Reference Types
|
||||||
var REF_TYPE_class = 0x1;
|
#define REF_TYPE_class 0x1
|
||||||
var REF_TYPE_interface = 0x2;
|
#define REF_TYPE_interface 0x2
|
||||||
var REF_TYPE_array = 0x4
|
#define REF_TYPE_array 0x4
|
||||||
|
|
||||||
function makeLocalVar(kind){
|
//primitive max Max values
|
||||||
return {id:kind};
|
#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){
|
function getRefClass(ref){
|
||||||
if (ref.type == REF_TYPE_array){
|
if (ref.type == REF_TYPE_array){
|
||||||
@ -38,5 +87,5 @@ function getRefClass(ref){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var NULL = makeLocalVar(LOC_VAR_reference);
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user