diff --git a/app.py b/app.py index 6d88a59..28a31b8 100644 --- a/app.py +++ b/app.py @@ -27,6 +27,7 @@ class index: return "" if filename.endswith(".js"): web.header('Content-Type', 'text/javascript') + return commands.getstatusoutput("/usr/bin/cpp -P -undef -Wundef -std=c99 -nostdinc -Wtrigraphs -fdollars-in-identifiers " + filename)[1] if "testRuntime" in filename: alphex = filename[filename.rfind("/") + 1:]; return file("runtime/" + alphex.replace(".","/") + ".class"); diff --git a/attributes.js b/attributes.js index f7080ea..194c327 100644 --- a/attributes.js +++ b/attributes.js @@ -1,3 +1,14 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: attributes.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + var ExceptionTableEntry = function(dStream, constantPool){ this.start_pc = dStream.getU2(); this.end_pc = dStream.getU2(); diff --git a/class.js b/class.js index e6cd811..c350a23 100644 --- a/class.js +++ b/class.js @@ -1,15 +1,25 @@ -// access flags DEFINE -var ACC_PUBLIC = 0x0001; // Declared public; may be accessed from outside its package. -var ACC_PRIVATE = 0x0002; // Declared private; usable only within the defining class. -var ACC_PROTECTED = 0x0004; // Declared protected; may be accessed within subclasses. -var ACC_STATIC = 0x0008; // Declared static. -var ACC_FINAL = 0x0010; // Declared final; no subclasses allowed. -var ACC_SUPER = 0x0020; // Treat superclass methods specially when invoked by the invokespecial instruction. -var ACC_VOLATILE = 0x0040; // Declared volatile; cannot be cached. -var ACC_NATIVE = 0x0100; // Declared native; implemented in a language other than Java. -var ACC_INTERFACE = 0x0200; // Is an interface, not a class. -var ACC_ABSTRACT = 0x0400; // Declared abstract; may not be instantiated. -var ACC_TRANSIENT = 0x0080; // Declared transient; not written or read by a persistent object manager. +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: class.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + +#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. +#define ACC_STATIC 0x0008 // Declared static. +#define ACC_FINAL 0x0010 // Declared final; no subclasses allowed. +#define ACC_SUPER 0x0020 // Treat superclass methods specially when invoked by the invokespecial instruction. +#define ACC_VOLATILE 0x0040 // Declared volatile; cannot be cached. +#define ACC_NATIVE 0x0100 // Declared native; implemented in a language other than Java. +#define ACC_INTERFACE 0x0200 // Is an interface, not a class. +#define ACC_ABSTRACT 0x0400 // Declared abstract; may not be instantiated. +#define ACC_TRANSIENT 0x0080 // Declared transient; not written or read by a persistent object manager. function slurpFile (filename, fa) { var xmlHttpRequest, response, result ; @@ -45,12 +55,6 @@ function slurpFile (filename, fa) { } return result; }; -var log = function (msg){ - write(msg); - if (console){ - console.log(msg); - } -} var ClassDefinition = function(jvm) { this.jvm = jvm; diff --git a/constantPool.js b/constantPool.js index 663595a..ad4e0bc 100644 --- a/constantPool.js +++ b/constantPool.js @@ -1,14 +1,26 @@ -var CONSTANT_Class = 7; -var CONSTANT_Fieldref = 9; -var CONSTANT_Methodref = 10; -var CONSTANT_InterfaceMethodref = 11; -var CONSTANT_String = 8; -var CONSTANT_Integer = 3; -var CONSTANT_Float = 4; -var CONSTANT_Long = 5; -var CONSTANT_Double = 6; -var CONSTANT_NameAndType = 12; -var CONSTANT_Utf8 = 1; +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: constantPool.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + +#define CONSTANT_Utf8 1 +//what is CONSTANT_????? 2 +#define CONSTANT_Integer 3 +#define CONSTANT_Float 4 +#define CONSTANT_Long 5 +#define CONSTANT_Double 6 +#define CONSTANT_Class 7 +#define CONSTANT_String 8 +#define CONSTANT_Fieldref 9 +#define CONSTANT_Methodref 10 +#define CONSTANT_InterfaceMethodref 11 +#define CONSTANT_NameAndType 12 // constant pool members diff --git a/cpu.js b/cpu.js index 337715d..685aa9d 100644 --- a/cpu.js +++ b/cpu.js @@ -1,3 +1,26 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: cpu.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + +#import "opcodes.js" + +#define JVM_THROWS_NEW(exception) throw "VER: throws new exception" +#ifdef DEBUG_INTRP +#define LOG_INTRP(x) LOG(x) +#else +#define LOG_INTRP(x) +#endif + +#define DEFOP(opcode) case opcode: LOG_INTRP("opcode pc: " + pc); +#define ENDDEF break; + function canonicalName(ref){ return ref.str.replace(/\//g,".") } @@ -18,7 +41,7 @@ var JVM = function(params,args){ this.method_area[name] = loaded_class; this.verifyAndLoadClass(loaded_class); - log("[Loaded " + name + "]"); + LOG("[Loaded " + name + "]"); } return loaded_class; @@ -67,9 +90,13 @@ var JVMFrame = function(){ } -function JVM_THROWS_NEW(exception){ - throw "VER: throws new " + exception; -} +function JVMPanic(message){ + this.toString = function(){ + return "JVMPanic: " + message + } +}; + +#define PANIC(msg) throw new JVMPanic(msg) function interpret(frame){ var operand_stack = frame.operand_stack; @@ -77,129 +104,6 @@ function interpret(frame){ var code = 0; //resolve code from method; 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 (!arrayref.classRef.isAssignable(value.cl)){ - JVM_THROWS_NEW("java.lang.ArrayStoreException"); - } - break; - - case 0x1: //aconst_null - operand_stack.push(null); - break; - case 0x19: //aload - var i = operand_stack.pop(); - operand_stack.push(local_variables[i]) - break; - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: // aload_ - operand_stack.push(local_variables[opcode - 0x2a]); - break; - case 0xbd: // anewarray - var indexbyte1 = code.pop(); - var indexbyte2 = code.pop(); - var count = operand_stack.pop(); - 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); - break; - case 0xb0: // areturn - var objectref = operand_stack.pop(); - return {return_object: objectref} - case 0xbe: // arraylength - var arrayref = operand_stack.pop(); - operand_stack.push(arrayref.length); - break; - case 0x3a: // astore - var objectref = operand_stack.pop(); - local_variables[code.pop()] = objectref; - break; - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4e: // astore_ - var objectref = operand_stack.pop(); - local_variables[opcode-0x4b] = objectref; - break; - case 0xbf: // athrow - var objectref = operand_stack.pop(); - if (objectref == null){ - JVM_THROWS_NEW("java.lang.NullPointerException"); - } - throw [objectref.classRef.name_ref.str,objectref]; - case 0x33: // baload - 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"); - } - arrayref.value[index] = value; - break; - case 0x10: // bipush - operand_stack.push(code.pop()); - break; - case 0x34: // caload - var index = operand_stack.pop(); - var arrayref = operand_stack.pop(); - - operand_stack.push(arrayref.value[index]); - break; - case 0x55: // castore - 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"); - } - arrayref.value[index] = value; - break; - case 0xc0: // checkcast - var objectref = operand_stack.pop(); - var indexbyte1 = code.pop(); - var indexbyte2 = code.pop(); - var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2); - if (objectref.classRef.isAssignable(clRef)){ - operand_stack.push(objectref); - }else{ - JVM_THROWS_NEW("java.lang.ClassCastException"); - } +#include "intrp.js" } } \ No newline at end of file diff --git a/infos.js b/infos.js index 6b48bda..df5ae0c 100644 --- a/infos.js +++ b/infos.js @@ -1,3 +1,14 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: infos.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + var FieldInfo = function(dStream,constantPool){ this.access_flags = dStream.getU2(); this.name_index = ConstantPoolRef(dStream.getU2(), constantPool, CONSTANT_Utf8); diff --git a/intrp.js b/intrp.js new file mode 100644 index 0000000..1bf97eb --- /dev/null +++ b/intrp.js @@ -0,0 +1,169 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: intrp.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + +DEFOP(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]); +ENDDEF + +DEFOP(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 (!arrayref.classRef.isAssignable(value.cl)){ + JVM_THROWS_NEW(java.lang.ArrayStoreException); + } +ENDDEF + +DEFOP(ACONST_NULL) + operand_stack.push(null); +ENDDEF + +DEFOP(ALOAD) + var i = operand_stack.pop(); + operand_stack.push(local_variables[i]) +ENDDEF + +DEFOP(ALOAD_0) +DEFOP(ALOAD_1) +DEFOP(ALOAD_2) +DEFOP(ALOAD_3) + operand_stack.push(local_variables[opcode - 0x2a]); +ENDDEF + +DEFOP(ANEWARRAY) + var indexbyte1 = code.pop(); + var indexbyte2 = code.pop(); + var count = operand_stack.pop(); + 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); +ENDDEF + +DEFOP(ARETURN) + var objectref = operand_stack.pop(); + return {return_object) objectref} +ENDDEF + +DEFOP(ARRAYLENGTH) + var arrayref = operand_stack.pop(); + operand_stack.push(arrayref.length); +ENDDEF + +DEFOP(ASTORE) + var objectref = operand_stack.pop(); + local_variables[code.pop()] = objectref; +ENDDEF + +DEFOP(ASTORE_0) +DEFOP(ASTORE_1) +DEFOP(ASTORE_2) +DEFOP(ASTORE_3) + var objectref = operand_stack.pop(); + local_variables[opcode-0x4b] = objectref; +ENDDEF + + +DEFOP(ATHROW) + var objectref = operand_stack.pop(); + if (objectref == null){ + JVM_THROWS_NEW(java.lang.NullPointerException); + } + throw [objectref.classRef.name_ref.str,objectref]; +ENDDEF + +DEFOP(BALOAD) + 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); + } + arrayref.value[index] = value; +ENDDEF + +DEFOP(BIPUSH) + operand_stack.push(code.pop()); +ENDDEF + +DEFOP(CALOAD) + var index = operand_stack.pop(); + var arrayref = operand_stack.pop(); + + operand_stack.push(arrayref.value[index]); +ENDDEF + +DEFOP(CASTORE) + 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); + } + arrayref.value[index] = value; +ENDDEF + +DEFOP(CHECKCAST) + var objectref = operand_stack.pop(); + var indexbyte1 = code.pop(); + var indexbyte2 = code.pop(); + var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2); + if (objectref.classRef.isAssignable(clRef)){ + operand_stack.push(objectref); + }else{ + JVM_THROWS_NEW(java.lang.ClassCastException); + } +ENDDEF + +DEFOP(D2F) + PANIC("Not Implemented Yet"); +ENDDEF + +DEFOP(D2F) + PANIC("Not Implemented Yet"); +ENDDEF + +DEFOP(D2L) + PANIC("Not Implemented Yet"); +ENDDEF + +DEFOP(DADD) + PANIC("Not Implemented Yet"); +ENDDEF + +DEFOP(DALOAD) \ No newline at end of file diff --git a/linearDatastream.js b/linearDatastream.js index 142c409..7a6a3ca 100644 --- a/linearDatastream.js +++ b/linearDatastream.js @@ -1,3 +1,14 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: linearDatastream.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + var DataStream = function(data){ this.i = 0; diff --git a/main.js b/main.js index 8a04b12..711b11d 100644 --- a/main.js +++ b/main.js @@ -1,10 +1,34 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: main.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + +#define DEBUG +#define DEBUG_INTRP + +#ifndef DEBUG +#define log(msg) +#else +#define LOG(msg) write(msg);\ + if (console){\ + console.log(msg);\ + } +#endif + +#include "linearDataStream.js" +#include "constantPool.js" +#include "attributes.js" +#include "infos.js" +#include "class.js" +#include "cpu.js" + -include("linearDataStream.js"); -include("constantPool.js"); -include("attributes.js"); -include("infos.js"); -include("class.js"); -include("cpu.js"); var test_jvm; function main (args){ test_jvm = new JVM({},["[I"]) diff --git a/opcodes.js b/opcodes.js new file mode 100644 index 0000000..845012e --- /dev/null +++ b/opcodes.js @@ -0,0 +1,212 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: opcodes.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + +#define NOP 0 +#define ACONST_NULL 1 +#define ICONST_M1 2 +#define ICONST_0 3 +#define ICONST_1 4 +#define ICONST_2 5 +#define ICONST_3 6 +#define ICONST_4 7 +#define ICONST_5 8 +#define LCONST_0 9 +#define LCONST_1 10 +#define FCONST_0 11 +#define FCONST_1 12 +#define FCONST_2 13 +#define DCONST_0 14 +#define DCONST_1 15 +#define BIPUSH 16 +#define SIPUSH 17 +#define LDC 18 +#define LDC_W 19 +#define LDC2_W 20 +#define ILOAD 21 +#define LLOAD 22 +#define FLOAD 23 +#define DLOAD 24 +#define ALOAD 25 +#define ILOAD_0 26 +#define ILOAD_1 27 +#define ILOAD_2 28 +#define ILOAD_3 29 +#define LLOAD_0 30 +#define LLOAD_1 31 +#define LLOAD_2 32 +#define LLOAD_3 33 +#define FLOAD_0 34 +#define FLOAD_1 35 +#define FLOAD_2 36 +#define FLOAD_3 37 +#define DLOAD_0 38 +#define DLOAD_1 39 +#define DLOAD_2 40 +#define DLOAD_3 41 +#define ALOAD_0 42 +#define ALOAD_1 43 +#define ALOAD_2 44 +#define ALOAD_3 45 +#define IALOAD 46 +#define LALOAD 47 +#define FALOAD 48 +#define DALOAD 49 +#define AALOAD 50 +#define BALOAD 51 +#define CALOAD 52 +#define SALOAD 53 +#define ISTORE 54 +#define LSTORE 55 +#define FSTORE 56 +#define DSTORE 57 +#define ASTORE 58 +#define ISTORE_0 59 +#define ISTORE_1 60 +#define ISTORE_2 61 +#define ISTORE_3 62 +#define LSTORE_0 63 +#define LSTORE_1 64 +#define LSTORE_2 65 +#define LSTORE_3 66 +#define FSTORE_0 67 +#define FSTORE_1 68 +#define FSTORE_2 69 +#define FSTORE_3 70 +#define DSTORE_0 71 +#define DSTORE_1 72 +#define DSTORE_2 73 +#define DSTORE_3 74 +#define ASTORE_0 75 +#define ASTORE_1 76 +#define ASTORE_2 77 +#define ASTORE_3 78 +#define IASTORE 79 +#define LASTORE 80 +#define FASTORE 81 +#define DASTORE 82 +#define AASTORE 83 +#define BASTORE 84 +#define CASTORE 85 +#define SASTORE 86 +#define POP 87 +#define POP2 88 +#define DUP 89 +#define DUP_X1 90 +#define DUP_X2 91 +#define DUP2 92 +#define DUP2_X1 93 +#define DUP2_X2 94 +#define SWAP 95 +#define IADD 96 +#define LADD 97 +#define FADD 98 +#define DADD 99 +#define ISUB 100 +#define LSUB 101 +#define FSUB 102 +#define DSUB 103 +#define IMUL 104 +#define LMUL 105 +#define FMUL 106 +#define DMUL 107 +#define IDIV 108 +#define LDIV 109 +#define FDIV 110 +#define DDIV 111 +#define IREM 112 +#define LREM 113 +#define FREM 114 +#define DREM 115 +#define INEG 116 +#define LNEG 117 +#define FNEG 118 +#define DNEG 119 +#define ISHL 120 +#define LSHL 121 +#define ISHR 122 +#define LSHR 123 +#define IUSHR 124 +#define LUSHR 125 +#define IAND 126 +#define LAND 127 +#define IOR 128 +#define LOR 129 +#define IXOR 130 +#define LXOR 131 +#define IINC 132 +#define I2L 133 +#define I2F 134 +#define I2D 135 +#define L2I 136 +#define L2F 137 +#define L2D 138 +#define F2I 139 +#define F2L 140 +#define F2D 141 +#define D2I 142 +#define D2L 143 +#define D2F 144 +#define I2B 145 +#define I2C 146 +#define I2S 147 +#define LCMP 148 +#define FCMPL 149 +#define FCMPG 150 +#define DCMPL 151 +#define DCMPG 152 +#define IFEQ 153 +#define IFNE 154 +#define IFLT 155 +#define IFGE 156 +#define IFGT 157 +#define IFLE 158 +#define IF_ICMPEQ 159 +#define IF_ICMPNE 160 +#define IF_ICMPLT 161 +#define IF_ICMPGE 162 +#define IF_ICMPGT 163 +#define IF_ICMPLE 164 +#define IF_ACMPEQ 165 +#define IF_ACMPNE 166 +#define GOTO 167 +#define JSR 168 +#define RET 169 +#define TABLESWITCH 170 +#define LOOKUPSWITCH 171 +#define IRETURN 172 +#define LRETURN 173 +#define FRETURN 174 +#define DRETURN 175 +#define ARETURN 176 +#define RETURN 177 +#define GETSTATIC 178 +#define PUTSTATIC 179 +#define GETFIELD 180 +#define PUTFIELD 181 +#define INVOKEVIRTUAL 182 +#define INVOKESPECIAL 183 +#define INVOKESTATIC 184 +#define INVOKEINTERFACE 185 +#define NEW 187 +#define NEWARRAY 188 +#define ANEWARRAY 189 +#define ARRAYLENGTH 190 +#define ATHROW 191 +#define CHECKCAST 192 +#define INSTANCEOF 193 +#define MONITORENTER 194 +#define MONITOREXIT 195 +#define WIDE 196 +#define MULTIANEWARRAY 197 +#define IFNULL 198 +#define IFNONNULL 199 +#define GOTO_W 200 +#define JSR_W 201 diff --git a/preload.js b/preload.js index c7f1281..e88af80 100644 --- a/preload.js +++ b/preload.js @@ -1,3 +1,14 @@ +/* -*- Mode: Javascript -*- + * -*- coding: UTF-8 -*- + * Copyright (C) 2011 by Artur Ventura + * + * File: preload.js + * Time-stamp: Fri Jul 15 02:46:27 2011 + * + * Author: Artur Ventura + * + */ + function include(filename) { document.write('