diff --git a/cpu.js b/cpu.js index 96acfaf..85ac57f 100644 --- a/cpu.js +++ b/cpu.js @@ -14,13 +14,26 @@ #define JVM_THROWS_NEW(exception) throw "VER: throws new exception" #ifdef DEBUG_INTRP #define LOG_INTRP(x) LOG(x) +#define DEFALIAS(opx) case opx: if(temp!=null) { temp = pc + ": opx" } #else #define LOG_INTRP(x) +#define DEFALIAS(opx) case opx: #endif -#define DEFOP(opcode) case opcode: LOG_INTRP("opcode pc: " + pc); +#define DEFOP(opx) case opx: LOG_INTRP(pc + ": opx"); +#define DEFNOP() LOG_INTRP(temp); #define ENDDEF break; +#define OPPOP() operand_stack.pop() +#define OPPUSH(v) operand_stack.push(v) + +#define LOCAL_VAR(v) local_variables[v] +#define OPCODE opcode +#define PC pc +#define READ_NEXT() code[++pc] + + + function canonicalName(ref){ return ref.str.replace(/\//g,".") } @@ -104,7 +117,10 @@ function interpret(frame){ var local_variables = frame.local_variables; var code = 0; //resolve code from method; - switch(opcode){ +#ifdef DEBUG_INTRP + var temp = null; +#endif + switch(OPCODE){ #include "intrp.js" } } \ No newline at end of file diff --git a/intrp.js b/intrp.js index 265fc5a..8fdbce1 100644 --- a/intrp.js +++ b/intrp.js @@ -9,9 +9,11 @@ * */ +#include "opcodes.js" + DEFOP(AALOAD) - var index = operand_stack.pop(); - var arrayref = operand_stack.pop(); + var index = OPPOP(); + var arrayref = OPPOP(); if (arrayref == NULL){ JVM_THROWS_NEW(java.lang.NullPointerException); @@ -19,13 +21,13 @@ DEFOP(AALOAD) if (index >= arrayref.length){ JVM_THROWS_NEW(java.lang.ArrayIndexOutOfBoundsException); } - operand_stack.push(arrayref.value[index.value]); + OPPUSH(arrayref.value[index.value]); ENDDEF DEFOP(AASTORE) - var value = operand_stack.pop(); - var index = operand_stack.pop(); - var arrayref = operand_stack.pop(); + var value = OPPOP(); + var index = OPPOP(); + var arrayref = OPPOP(); if (arrayref == NULL){ JVM_THROWS_NEW(java.lang.NullPointerException); @@ -39,59 +41,61 @@ DEFOP(AASTORE) ENDDEF DEFOP(ACONST_NULL) - operand_stack.push(null); + OPPUSH(null); ENDDEF DEFOP(ALOAD) - var i = operand_stack.pop(); - operand_stack.push(local_variables[i]) + var i = OPPOP(); + OPPUSH(LOCAL_VAR(i)) ENDDEF -DEFOP(ALOAD_0) -DEFOP(ALOAD_1) -DEFOP(ALOAD_2) -DEFOP(ALOAD_3) - operand_stack.push(local_variables[opcode - 0x2a]); +DEFALIAS(ALOAD_0) +DEFALIAS(ALOAD_1) +DEFALIAS(ALOAD_2) +DEFALIAS(ALOAD_3) +DEFNOP() + OPPUSH(LOCAL_VAR(OPCODE - ALOAD_0)); ENDDEF DEFOP(ANEWARRAY) - var indexbyte1 = code.pop(); - var indexbyte2 = code.pop(); - var count = operand_stack.pop(); + var indexbyte1 = READ_NEXT(); + var indexbyte2 = READ_NEXT(); + var count = OPPOP(); if (count < 0){ 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)}; - operand_stack.push(instance); + var instance = {length:count, value:[], 'class':this.jvm.classForName(clRef)}; + OPPUSH(instance); ENDDEF DEFOP(ARETURN) - var objectref = operand_stack.pop(); + var objectref = OPPOP(); return {return_object: objectref} ENDDEF DEFOP(ARRAYLENGTH) - var arrayref = operand_stack.pop(); - operand_stack.push(arrayref.length); + var arrayref = OPPOP(); + OPPUSH(arrayref.length); ENDDEF DEFOP(ASTORE) - var objectref = operand_stack.pop(); - local_variables[code.pop()] = objectref; + var objectref = OPPOP(); + LOCAL_VAR(READ_NEXT()) = objectref; ENDDEF -DEFOP(ASTORE_0) -DEFOP(ASTORE_1) -DEFOP(ASTORE_2) -DEFOP(ASTORE_3) - var objectref = operand_stack.pop(); - local_variables[opcode-0x4b] = objectref; +DEFALIAS(ASTORE_0) +DEFALIAS(ASTORE_1) +DEFALIAS(ASTORE_2) +DEFALIAS(ASTORE_3) +DEFNOP() + var objectref = OPPOP(); + LOCAL_VAR(OPCODE-ASTORE_0) = objectref; ENDDEF DEFOP(ATHROW) - var objectref = operand_stack.pop(); + var objectref = OPPOP(); if (objectref == null){ JVM_THROWS_NEW(java.lang.NullPointerException); } @@ -99,9 +103,9 @@ DEFOP(ATHROW) ENDDEF DEFOP(BALOAD) - var value = operand_stack.pop(); - var index = operand_stack.pop(); - var arrayref = operand_stack.pop(); + var value = OPPOP(); + var index = OPPOP(); + var arrayref = OPPOP(); if (arrayref == NULL){ JVM_THROWS_NEW(java.lang.NullPointerException); @@ -113,21 +117,20 @@ DEFOP(BALOAD) ENDDEF DEFOP(BIPUSH) - operand_stack.push(code.pop()); + OPPUSH(code.pop()); ENDDEF DEFOP(CALOAD) - var index = operand_stack.pop(); - var arrayref = operand_stack.pop(); + var index = OPPOP(); + var arrayref = OPPOP(); - operand_stack.push(arrayref.value[index]); + OPPUSH(arrayref.value[index]); ENDDEF DEFOP(CASTORE) - var value = operand_stack.pop(); - var index = operand_stack.pop(); - var arrayref = operand_stack.pop(); - + var value = OPPOP(); + var index = OPPOP(); + var arrayref = OPPOP(); if (arrayref == NULL){ JVM_THROWS_NEW(java.lang.NullPointerException); @@ -139,31 +142,112 @@ DEFOP(CASTORE) ENDDEF DEFOP(CHECKCAST) - var objectref = operand_stack.pop(); - var indexbyte1 = code.pop(); - var indexbyte2 = code.pop(); + var objectref = OPPOP(); + var indexbyte1 = READ_NEXT(); + var indexbyte2 = READ_NEXT(); var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2); if (objectref.classRef.isAssignable(clRef)){ - operand_stack.push(objectref); + OPPUSH(objectref); }else{ JVM_THROWS_NEW(java.lang.ClassCastException); } ENDDEF DEFOP(D2F) - PANIC("Not Implemented Yet"); + var value = OPPOP(); + if (isNaN(value)){ + OPPUSH(NaN); + }else if(IS_OVERFLOW(value,FLOAT_MAX_VALUE)){ + OPPUSH(POSITIVE_INF); + }else if (IS_UNDEFLOW(value,FLOAT_MIN_VALUE)){ + OPPUSH(NEGATIVE_INF); + }else{ + OPPUSH(value); + } ENDDEF -DEFOP(D2F) - PANIC("Not Implemented Yet"); +DEFOP(D2I) + var value = OPPOP(); + if (isNaN(value)){ + OPPUSH(0); + }else if(IS_OVERFLOW(value,INT_MAX_VALUE)){ + OPPUSH(INT_MAX_VALUE); + }else if(IS_UNDERFLOW(value,INT_MIN_VALUE)){ + OPPUSH(INT_MIN_VALUE); + }else{ + OPPUSH(Math.round(value)); + } ENDDEF DEFOP(D2L) - PANIC("Not Implemented Yet"); + var value = OPPOP(); + if (isNaN(value)){ + OPPUSH(0); + }else if(IS_OVERFLOW(value,LONG_MAX_VALUE)){ + OPPUSH(LONG_MAX_VALUE); + }else if(IS_UNDERFLOW(value,LONG_MIN_VALUE)){ + OPPUSH(LONG_MIN_VALUE); + }else{ + OPPUSH(Math.round(value)); + } ENDDEF DEFOP(DADD) - PANIC("Not Implemented Yet"); + var value1 = OPPOP(); + var value2 = OPPOP(); + var result = value1 + value2; + if (IS_OVERFLOW(result,DOUBLE_MAX_VALUE)){ + OPPUSH(POSITIVE_INF); + }else if(IS_UNDERFLOW(result,DOUBLE_MIN_VALUE)){ + OPPUSH(NEGATIVE_INF); + }else{ + OPPUSH(result); + } +ENDDEF + +DEFOP(DALOAD) + var index = OPPOP(); + var arrayref = OPPOP(); + if (arrayref == NULL){ + JVM_THROWS_NEW(java.lang.NullPointerException); + } + if (index >= arrayref.length){ + JVM_THROWS_NEW(java.lang.ArrayIndexOutOfBoundsException); + } + OPPUSH(arrayref.value[index]); +ENDDEF + +DEFOP(DASTORE) + var value = OPPOP(); + var index = OPPOP(); + var arrayref = OPPOP(); + if (arrayref == NULL){ + JVM_THROWS_NEW(java.lang.NullPointerException); + } + if (index >= arrayref.length){ + JVM_THROWS_NEW(java.lang.ArrayIndexOutOfBoundsException); + } + arrayref.value[index] = value; +ENDDEF + +DEFALIAS(DCMPG) +DEFALIAS(DCMPL) +DEFNOP() + var value2 = OPPOP(); + var value1 = OPPOP(); + if (isNaN(value1) || isNaN(value2)) { OPPUSH((OPCODE == DCMPG)?1:0)} + if (value1 > value2){ + OPPUSH(1); + }else if(value1 == value2){ + OPPUSH(0); + }else{ + OPPUSH(-1); + } +ENDDEF + +DEFALIAS(DCONST_1) +DEFALIAS(DCONST_0) +DEFNOP() + OPPUSH(OPCODE-DCONST_0); ENDDEF -DEFOP(DALOAD) \ No newline at end of file diff --git a/lib/compiler.jar b/lib/compiler.jar new file mode 100644 index 0000000..694808c Binary files /dev/null and b/lib/compiler.jar differ diff --git a/linearDatastream.js b/linearDatastream.js index 7a6a3ca..67c9f96 100644 --- a/linearDatastream.js +++ b/linearDatastream.js @@ -8,8 +8,9 @@ * Author: Artur Ventura * */ - -var DataStream = function(data){ + +/** @constructor */ +function DataStream(data){ this.i = 0; this.getF = function(size){ diff --git a/main.js b/main.js index 9c6e541..b827f76 100644 --- a/main.js +++ b/main.js @@ -27,6 +27,7 @@ #include "infos.js" #include "class.js" #include "cpu.js" +#include "types.js" var test_jvm; diff --git a/opcodes.js b/opcodes.js index 845012e..e3edbd4 100644 --- a/opcodes.js +++ b/opcodes.js @@ -8,6 +8,9 @@ * Author: Artur Ventura * */ + +#ifndef _TYPES_JS_ +#define _TYPES_JS_ #define NOP 0 #define ACONST_NULL 1 @@ -210,3 +213,5 @@ #define IFNONNULL 199 #define GOTO_W 200 #define JSR_W 201 + +#endif // _TYPES_JS_ \ No newline at end of file diff --git a/types.js b/types.js index 7bbbb14..ff5abab 100644 --- a/types.js +++ b/types.js @@ -8,6 +8,9 @@ * Author: Artur Ventura * */ + +#ifndef _TYPES_JS_ +#define _TYPES_JS_ // Local Variables Types #define LOC_VAR_boolean 0x001; @@ -61,7 +64,6 @@ #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) @@ -86,6 +88,6 @@ function getRefClass(ref){ return ref.classRef; } } - +#endif //_TYPES_JS_