NativeArrays, Strings working

This commit is contained in:
Artur Ventura 2011-08-06 01:03:21 +01:00
parent 6df45ebf93
commit 7dec232268
9 changed files with 182 additions and 39 deletions

View File

@ -267,6 +267,10 @@ ClassDefinition.prototype.calculateEffectiveMembers = function(){
return [this.effectiveFields,this.effectiveMethods];
}
function instanceToString(){
return "<" + this["class"].className + ">";
}
ClassDefinition.prototype.makeInstance = function(){
if (!this.inited) { this.initializeClass(); }
var newInstance = {};
@ -276,6 +280,7 @@ ClassDefinition.prototype.makeInstance = function(){
}
}
newInstance["class"] = this;
newInstance["toString"] = instanceToString;
return newInstance;
}

View File

@ -72,7 +72,9 @@ var constLong = function(){
this.low = null;
this.id = CONSTANT_Long;
this.read = function (dStream){
this.value = dStream.getInt64();
var high = dStream.getU4();
var low = dStream.getU4();
this.value = math.Long.fromBits(low,high)
}
};
@ -124,6 +126,7 @@ var constClass = function(){
throw "Class name index doesn't point to Utf8 in the Constant Pool";
}
this.name_ref = ref;
this.jvmClassName = canonicalName(this.name_ref);
}
};

View File

@ -22,6 +22,28 @@ var JVM = function(params,args){
this.method_area = {};
this.level = 0;
this.classpath = params.classes_to_load;
for (var i=0; i<this.args; i++){
if (typeof this.args[i] != "string"){
throw "Argument " + i + " is not a string.";;
}
}
this.stringHashCode = function(string){
var hash = 0;
if (string.length == 0) return hash;
for (i = 0; i < string.length; i++) {
Char = string.charCodeAt(i);
hash = ((hash<<5)-hash)+Char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
this.makeInstanceOfStringFromJSSTring = function(string){
var inst = this.java_lang_string.makeInstance();
inst["java/lang/String value"] = string;
inst["java/lang/String hash"] = this.stringHashCode(string)
return inst;
}
this.classForName = function (name){
if (!name) { PANIC("undefined className")}
@ -72,7 +94,11 @@ var JVM = function(params,args){
if (method == null){
PANIC(this.args[0] + " doesn't have a a main method");
}
method.invoke(null,this.main_class);
var array = make1DNativeArray(this.args.length,false,this.java_lang_string);
for (var i=0; i<this.args.length; i++){
array.value[i] = this.makeInstanceOfStringFromJSSTring(this.args[i]);
}
method.invoke([array],this.main_class);
};
};
/** @constructor */

View File

@ -13,6 +13,16 @@
#include "log.jsh"
#define T_BOOLEAN 4
#define T_CHAR 5
#define T_FLOAT 6
#define T_DOUBLE 7
#define T_BYTE 8
#define T_SHORT 9
#define T_INT 10
#define T_LONG 11
#define JVM_THROWS_NEW(exception) throw "VER: throws new exception"
#ifdef DEBUG_INTRP
#define LOG_INTRP(x) LOG(x)
@ -36,6 +46,7 @@
#define OPPUSHD(v) (operand_stack.push(v) && operand_stack.push(null))
#define OPSTACK(v) operand_stack[v]
#define OPSTACK_MULTIPOP(x) operand_stack.splice(x)
#define OPSTACK_LENGTH() operand_stack.length
#define LOCAL_VAR(v) local_variables[v]

View File

@ -52,7 +52,11 @@ var MethodInfo = function(dStream, constantPool){
for (var i=0; i<this.attributes_count; i++){
var attr = this.attributes[i];
if (attr.id == ATTR_CODE){
interpret(frame,attr.code,this,xl);
var result = interpret(frame,attr.code,this,xl);
#ifdef DEBUG_INTRP
LOG("Returing from " + this.name_ref.str + this.descriptor_ref.str)
#endif
return result;
}
}
}

View File

@ -42,7 +42,7 @@ DEFOP(ACONST_NULL)
ENDDEF
DEFOP(ALOAD)
var i = OPPOP();
var i = READ_NEXT();
OPPUSH(LOCAL_VAR(i))
ENDDEF
@ -61,8 +61,8 @@ DEFOP(ANEWARRAY)
if (count < 0){
JVM_THROWS_NEW(java.lang.NegativeArraySizeException);
}
var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2);
var instance = {length:count, dimensions:1, value:[], 'class':xl.jvm.classForName(clRef)};
var clRef = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var instance = make1DNativeArray(count,false,xl.jvm.classForName(clRef));
OPPUSH(instance);
ENDDEF
@ -516,9 +516,9 @@ DEFOP(GETFIELD)
var objectref = OPPOP();
CHECK_NULL(objectref)
var field = objectref["class"].constantPool[(indexbyte1 << 8) | indexbyte2];
var field = objectref["class"].constantPool.get((indexbyte1 << 8) | indexbyte2);
//check if static
OPPUSH(objectref[canonicalName(field.class_ref.name_ref.str) + " " + field.name_and_type_ref.name_ref.str]);
OPPUSH(objectref[canonicalName(field.class_ref.name_ref) + " " + field.name_and_type_ref.name_ref.str]);
ENDDEF
DEFOP(GETSTATIC)
@ -526,11 +526,11 @@ DEFOP(GETSTATIC)
var indexbyte2 = READ_NEXT();
CHECK_NULL(objectref)
var field = this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2];
var field = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var aClass = field.class_ref.name_ref.str;
//check if static
OPPUSH(jvm.classForName(aClass)[canonicalName(field.class_ref.name_ref.str) + " " + field.name_and_type_ref.name_ref.str]);
OPPUSH(jvm.classForName(aClass)[canonicalName(field.class_ref.name_ref) + " " + field.name_and_type_ref.name_ref.str]);
ENDDEF
DEFOP(GOTO)
@ -612,10 +612,10 @@ DEFOP(IAND)
ENDDEF
DEFOP(IASTORE)
var value = OPPOP();
var index = OPPOP();
var arrayref = OPPOP();
var value = OPPOP();
CHECK_NULL(arrayref);
CHECK_ARRAY_INDEX(index,arrayref);
@ -869,7 +869,7 @@ DEFOP(INSTANCEOF)
OPPUSH(0);
break;
}
var className = canonicalName(this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2].name_ref.str);
var className = canonicalName(xl.constantPool.get((indexbyte1 << 8) | indexbyte2).name_ref);
if(objectref["class"].isAssignable(jvm.classForName(className))){
OPPUSH(1);
@ -889,7 +889,7 @@ DEFOP(INVOKEINTERFACE)
/* expected 0*/ READ_NEXT();
var args = [];
var method = this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2];
var method = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
for(var i=0; i<method.descriptor.args.length; i++){
args.push(OPPOP());
}
@ -901,15 +901,21 @@ ENDDEF
DEFOP(INVOKESPECIAL)
var indexbyte1 = READ_NEXT();
var indexbyte2 = READ_NEXT();
var args = [];
var method = this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2];
for(var i=0; i<method.descriptor.args.length; i++){
args.push(OPPOP());
var methodDesrc = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var cl = xl.jvm.classForName(methodDesrc.class_ref.jvmClassName);
var methodId = "method " + methodDesrc.name_and_type_ref.name_ref.str + methodDesrc.name_and_type_ref.descriptor_ref.str
var method = cl[methodId];
var args = OPSTACK_MULTIPOP(OPSTACK_LENGTH() - method.descriptor.args.length-1);
var result;
if(method.access_flags & ACC_NATIVE){
PANIC("INVOKESPECIAL NATIVE CALL")
}else{
result = method.invoke(args,cl);
}
if (result != undefined){
OPPUSH(result.return_object);
}
var objectref = OPPOP();
PANIC("NOT IMPLEMENTED YET");
ENDDEF
DEFOP(INVOKESTATIC)
@ -917,7 +923,7 @@ DEFOP(INVOKESTATIC)
var indexbyte2 = READ_NEXT();
var args = [];
var method = this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2];
var method = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
for(var i=0; i<method.descriptor.args.length; i++){
args.push(OPPOP());
}
@ -930,13 +936,20 @@ DEFOP(INVOKEVIRTUAL)
var indexbyte2 = READ_NEXT();
var args = [];
var method = this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2];
for(var i=0; i<method.descriptor.args.length; i++){
args.push(OPPOP());
var methodDesrc = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var cl = xl.jvm.classForName(methodDesrc.class_ref.jvmClassName);
var methodId = "method " + methodDesrc.name_and_type_ref.name_ref.str + methodDesrc.name_and_type_ref.descriptor_ref.str
var method = cl[methodId];
var args = OPSTACK_MULTIPOP(OPSTACK_LENGTH() - method.descriptor.args.length);
var result;
if(method.access_flags & ACC_NATIVE){
PANIC("INVOKEVIRTUAL NATIVE CALL")
}else{
result = method.invoke(args,cl);
}
if (result != undefined){
OPPUSH(result.return_object);
}
method.invoke([])
ENDDEF
DEFOP(IOR)
@ -1122,14 +1135,14 @@ ENDDEF
DEFOP(LDC)
var index = READ_NEXT();
var cstt = this_method_class.constantPool.get(index);
var cstt = xl.constantPool.get(index);
switch(cstt.id){
case CONSTANT_Integer:
case CONSTANT_Float:
OPPUSH(cstt.value);
break;
case CONSTANT_String:
PANIC("NEW STRING FROM CONSTANT POOL NOT IMPLEMENTED");
OPPUSH(xl.jvm.makeInstanceOfStringFromJSSTring(cstt.string_ref.str));
break;
default:
PANIC("What now?");
@ -1141,7 +1154,7 @@ DEFOP(LDC_W)
var index1 = READ_NEXT();
var index2 = READ_NEXT();
var index = (indexbyte1 << 8) | indexbyte2
var cstt = this_method_class.constantPool.get(index);
var cstt = xl.constantPool.get(index);
switch(cstt.id){
case CONSTANT_Integer:
OPPUSHD(cstt.value);
@ -1360,7 +1373,7 @@ DEFOP(MULTIANEWARRAY)
for(var i=0; i<dimensions; i++){
counts.add(OPPOP());
}
var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2);
var clRef = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var instance = {length:counts, dimensions:dimensions, value:[], 'class':xl.jvm.classForName(clRef)};
OPPUSH(instance);
ENDDEF
@ -1369,14 +1382,25 @@ DEFOP(NEW)
var indexbyte1 = READ_NEXT();
var indexbyte2 = READ_NEXT();
var clRef = frame.classRef.constantPool.get((indexbyte1 << 8) | indexbyte2);
var newInstance = xl.jvm.classForName(clRef).makeInstance();
var clRef = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var newInstance = xl.jvm.classForName(clRef.jvmClassName).makeInstance();
OPPUSH(newInstance);
ENDDEF
DEFOP(NOP)
ENDDEF
DEFOP(NEWARRAY)
var atype = READ_NEXT();
var count = OPPOP();
if (count < 0){
JVM_THROWS_NEW(java.lang.NegativeArraySizeException);
}
var clRef = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var instance = make1DNativeArray(count,true,atype);
OPPUSH(instance);
ENDDEF
DEFOP(POP)
OPPOP();
ENDDEF
@ -1393,9 +1417,9 @@ DEFOP(PUTFIELD)
var objectref = OPPOP();
CHECK_NULL(objectref)
var field = objectref["class"].constantPool[(indexbyte1 << 8) | indexbyte2];
var field = objectref["class"].constantPool.get((indexbyte1 << 8) | indexbyte2);
//check if static
objectref[canonicalName(field.class_ref.name_ref.str) + " " + field.name_and_type_ref.name_ref.str] = value;
objectref[canonicalName(field.class_ref.name_ref) + " " + field.name_and_type_ref.name_ref.str] = value;
ENDDEF
DEFOP(GETSTATIC)
@ -1404,11 +1428,11 @@ DEFOP(GETSTATIC)
var value = OPPOP();
CHECK_NULL(objectref)
var field = this_method_class.constantPool[(indexbyte1 << 8) | indexbyte2];
var field = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
var aClass = field.class_ref.name_ref.str;
//check if static
jvm.classForName(aClass)[canonicalName(field.class_ref.name_ref.str) + " " + field.name_and_type_ref.name_ref.str] = value;
jvm.classForName(aClass)[canonicalName(field.class_ref.name_ref) + " " + field.name_and_type_ref.name_ref.str] = value;
ENDDEF
DEFOP(RET)

View File

@ -7,10 +7,15 @@
* Author: Artur Ventura
*
*/
#ifndef DEBUG
#define LOG(msg)
#else
function htmlentities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
#define LOG(msg) write(msg);\
if (console){\
console.log(msg);\

52
src/nativeArrays.js Normal file
View File

@ -0,0 +1,52 @@
/* -*- Mode: Javascript -*-
* -*- coding: UTF-8 -*-
* Copyright (C) 2011 by Artur Ventura
*
* File: nativeArray.js
* Time-stamp: Fri Jul 15 02:46:27 2011
*
* Author: Artur Ventura
*
*/
#include "cpu.jsh"
function printNativeArray(){
var result = "[";
if(this.primitive){
switch(this['class']){
case T_BOOLEAN:
result += "Z";
break;
case T_BYTE:
result += "B";
break;
case T_CHAR:
result += "C";
break;
case T_DOUBLE:
result += "D";
break;
case T_FLOAT:
result += "F";
break
case T_INT:
result += "I";
break
case T_LONG:
result += "J";
break
case T_SHORT:
result += "B";
break
}
}else{
result+="L" + this['class'].className + ";";
}
return result + "#" + this.length;
}
function make1DNativeArray(count,primitive,type){
var inst = {toString: printNativeArray,length:count, dimensions:1, value:[], primitive:primitive, 'class':type};
return inst;
}

View File

@ -4,7 +4,20 @@
<script>
write = function(msg){
var l = document.getElementById("log");
var match;
if ((match = msg.match(/(\d+): (\w+) (op:\[[^\]]*]) (.*)/))){
var space3 = "";
for(var i=0; i<3-(match[1].length); i++){space3 += " " }
var space1 = "";
for(var i=0; i<23-(match[1].length + space3.length + match[2].length);i++ ){space1 += " " }
var space2 = "";
for(var i=0; i<30-(match[3].length); i++ ){space2 += " " }
msg = "<span style='color:DarkOrchid '>" + match[1] + "</span>:"+ space3 +"<a style='color:red;' href='http://homepages.inf.ed.ac.uk/kwxm/JVM/" + match[2].toLowerCase().replace(/\d+/,"n") + ".html'>" + match[2] + "</a>" + space1 + htmlentities(match[3]) + space2 +" "+ htmlentities(match[4]) ;
}else{
msg=htmlentities(msg);
}
l.innerHTML = l.innerHTML + msg + "\n";
}
</script>
<script src="jvm.js" type="text/javascript"></script>