Native Interface, Static invocation, several bug fixes, 40% opcode coverage

This commit is contained in:
Artur Ventura 2011-08-09 00:39:43 +01:00
parent 7dec232268
commit 8630cf0e59
8 changed files with 173 additions and 49 deletions

View File

@ -22,7 +22,7 @@ function slurpFile (filename, fa) {
} else if ('responseType' in xmlHttpRequest) {
xmlHttpRequest.responseType = 'arraybuffer';
} else {
xmlHttpRequest.overrideMimeType('text/plain; charset=x-user-defined');
//xmlHttpRequest.overrideMimeType('text/plain; charset=x-user-defined');
}
xmlHttpRequest.send(null);
if (xmlHttpRequest.status != 200 && xmlHttpRequest.status != 0) {
@ -42,6 +42,11 @@ function slurpFile (filename, fa) {
if (bf) {
result = [response.byteLength, response];
} else {
var a = "";
for(var k in xmlHttpRequest){
a+=k+",";
}
alert(a)
throw "No typed arrays";
}
return result;

View File

@ -16,7 +16,9 @@
/** @constructor */
var JVM = function(params,args){
this.nativeMappingTable = {}
this.JNITable = params.JNITable || {}
this.internalJNITable =
#include "internalJNI.jsh"
this.params = params;
this.args = args;
this.method_area = {};
@ -40,7 +42,10 @@ var JVM = function(params,args){
this.makeInstanceOfStringFromJSSTring = function(string){
var inst = this.java_lang_string.makeInstance();
inst["java/lang/String value"] = string;
inst["java/lang/String count"] = string.length;
var x = make1DNativeArray(string.length,true,T_CHAR);
x.value = string.toArray();
inst["java/lang/String value"] = x;
inst["java/lang/String hash"] = this.stringHashCode(string)
return inst;
}
@ -56,7 +61,7 @@ var JVM = function(params,args){
LOG("[Loaded " + name + "]");
}
loaded_class.initializeClass();
return loaded_class;
}

View File

@ -11,11 +11,48 @@
#include "constantPool.jsh"
function parseArgs(description){
// "([Ljava/lang/String;)V"
var length = description.length
var sides = description.substr(1,length).split(")")
return {args:sides[0].split(","),ret:sides[1]};
#define DSCRPT_DEFAULT 0
#define DSCRPT_ARRAY 1
#define DSCRPT_OBJ 2
function parseArgs(descriptor){
var sides = descriptor.substr(1,descriptor.length).split(")")
var result = sides[1];
var args = sides[0];
var argsA = []
var state = DSCRPT_DEFAULT;
var temp = "";
for (var i=0; i<args.length; i++){
switch(args[i]){
case "[":
state = DSCRPT_ARRAY;
temp += args[i];
break;
case "L":
state = DSCRPT_OBJ;
temp += args[i]
break;
case ";":
if (state != DSCRPT_OBJ){
PANIC("DESCRIPTOR ERROR");
}
temp += args[i]
argsA.push(args[i]);
temp ="";
state = DSCRPT_DEFAULT;
break;
default:
if (state == DSCRPT_ARRAY){
temp += args[i];
argsA.push(temp);
temp = "";
state = DSCRPT_DEFAULT;
}else{
argsA.push(args[i]);
}
}
}
return {args:argsA,ret:result};
}
/** @constructor */
@ -45,7 +82,7 @@ var MethodInfo = function(dStream, constantPool){
}
this.invoke = function (local_var,xl){
#ifdef DEBUG_INTRP
LOG("Calling " + this.name_ref.str + this.descriptor_ref.str)
LOG("Calling " + xl.className+ " " + this.name_ref.str + this.descriptor_ref.str)
#endif
local_var = local_var||[];
var frame = { operand_stack: [], local_variables:local_var };
@ -54,7 +91,7 @@ var MethodInfo = function(dStream, constantPool){
if (attr.id == ATTR_CODE){
var result = interpret(frame,attr.code,this,xl);
#ifdef DEBUG_INTRP
LOG("Returing from " + this.name_ref.str + this.descriptor_ref.str)
LOG("Returing from " + xl.className+ " " + this.name_ref.str + this.descriptor_ref.str)
#endif
return result;
}

16
src/internalJNI.jsh Normal file
View File

@ -0,0 +1,16 @@
/* -*- Mode: Javascript -*-
* -*- coding: UTF-8 -*-
* Copyright (C) 2011 by Artur Ventura
*
* File: types.js
* Time-stamp: Fri Jul 15 02:46:27 2011
*
* Author: Artur Ventura
*
*/
{
'java.lang.System' : {
'method arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V' : java_lang_System_arraycopy
}
}

View File

@ -73,6 +73,9 @@ ENDDEF
DEFOP(ARRAYLENGTH)
var arrayref = OPPOP();
if (!(arrayref.primitive == true || arrayref.primitive == false)){
PANIC("NOT AN ARRAY");
}
OPPUSH(arrayref.length);
ENDDEF
@ -516,9 +519,10 @@ DEFOP(GETFIELD)
var objectref = OPPOP();
CHECK_NULL(objectref)
var field = objectref["class"].constantPool.get((indexbyte1 << 8) | indexbyte2);
var field = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
//check if static
OPPUSH(objectref[canonicalName(field.class_ref.name_ref) + " " + field.name_and_type_ref.name_ref.str]);
OPPUSH(objectref[field.class_ref.name_ref.str + " " + field.name_and_type_ref.name_ref.str]);
LOG(field.class_ref.name_ref.str + " " + field.name_and_type_ref.name_ref.str);
ENDDEF
DEFOP(GETSTATIC)
@ -538,7 +542,7 @@ DEFOP(GOTO)
var branchbyte2 = READ_NEXT();
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
ENDDEF
DEFOP(GOTO_W)
@ -548,7 +552,7 @@ DEFOP(GOTO_W)
var branchbyte4 = READ_NEXT();
var branchoffset = (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4;
PC = PC + branchoffset;
PC = PC + branchoffset - 5;
ENDDEF
DEFOP(I2B)
@ -651,7 +655,7 @@ DEFOP(IF_ACMPEQ)
var value2 = OPPOP();
if (value1 == value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -662,7 +666,7 @@ DEFOP(IF_ACMPNE)
var value2 = OPPOP();
if (value1 != value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -673,7 +677,7 @@ DEFOP(IF_ICMPEQ)
var value2 = OPPOP();
if (value1 == value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -684,51 +688,51 @@ DEFOP(IF_ICMPNE)
var value2 = OPPOP();
if (value1 != value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
DEFOP(IF_ICMPLT)
var branchbyte1 = READ_NEXT();
var branchbyte2 = READ_NEXT();
var value1 = OPPOP();
var value2 = OPPOP();
var value1 = OPPOP();
if (value1 < value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
DEFOP(IF_ICMPLE)
var branchbyte1 = READ_NEXT();
var branchbyte2 = READ_NEXT();
var value1 = OPPOP();
var value2 = OPPOP();
var value1 = OPPOP();
if (value1 <= value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
DEFOP(IF_ICMPGT)
var branchbyte1 = READ_NEXT();
var branchbyte2 = READ_NEXT();
var value1 = OPPOP();
var value2 = OPPOP();
var value1 = OPPOP();
if (value1 > value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
DEFOP(IF_ICMPGE)
var branchbyte1 = READ_NEXT();
var branchbyte2 = READ_NEXT();
var value1 = OPPOP();
var value2 = OPPOP();
var value1 = OPPOP();
if (value1 >= value2){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -739,7 +743,7 @@ DEFOP(IFEQ)
if (value == 0){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -750,7 +754,7 @@ DEFOP(IFNE)
if (value != 0){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -761,7 +765,7 @@ DEFOP(IFLT)
if (value < 0){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -772,7 +776,7 @@ DEFOP(IFLE)
if (value <= 0){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -783,7 +787,7 @@ DEFOP(IFGT)
if (value > 0){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -794,7 +798,7 @@ DEFOP(IFGE)
if (value >= 0){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -805,7 +809,7 @@ DEFOP(IFNONNULL)
if (value != NULL){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -816,7 +820,7 @@ DEFOP(IFNULL)
if (value != NULL){
var branchoffset = (branchbyte1 << 8) | branchbyte2;
PC = PC + branchoffset;
PC = PC + branchoffset - 3;
}
ENDDEF
@ -836,7 +840,7 @@ DEFALIAS(ILOAD_1)
DEFALIAS(ILOAD_2)
DEFALIAS(ILOAD_3)
DEFNOP()
OPPUSH(OPCODE - ILOAD_0);
OPPUSH(LOCAL_VAR(OPCODE - ILOAD_0));
ENDDEF
DEFOP(IMUL)
@ -923,12 +927,31 @@ DEFOP(INVOKESTATIC)
var indexbyte2 = READ_NEXT();
var args = [];
var method = xl.constantPool.get((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){
LOG("Calling " + xl.className+ " " + method.name_ref.str + method.descriptor_ref.str)
LOG("!! NATIVE !!")
if (methodId in xl.jvm.internalJNITable[canonicalName(cl.this_class.name_ref)]){
result = xl.jvm.internalJNITable[canonicalName(cl.this_class.name_ref)][methodId].apply(cl,args);
LOG("Returing from " + xl.className+ " " + method.name_ref.str + method.descriptor_ref.str)
}else if (methodId in xl.jvm.JNITable[canonicalName(cl.this_class.name_ref)][methodId]){
result = xl.jvm.JNITable[canonicalName(cl.this_class.name_ref)][methodId].apply(cl,args)
}else{
PANIC(methodId + " declared as native but not mapped");
}
LOG("Returing from " + xl.className+ " " + method.name_ref.str + method.descriptor_ref.str)
}else{
result = method.invoke(args,cl);
}
if (result != undefined){
OPPUSH(result.return_object);
}
PANIC("NOT IMPLEMENTED YET");
ENDDEF
DEFOP(INVOKEVIRTUAL)
@ -940,7 +963,7 @@ DEFOP(INVOKEVIRTUAL)
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 args = OPSTACK_MULTIPOP(OPSTACK_LENGTH() - method.descriptor.args.length - 1);
var result;
if(method.access_flags & ACC_NATIVE){
PANIC("INVOKEVIRTUAL NATIVE CALL")
@ -1017,10 +1040,10 @@ DEFNOP()
ENDDEF
DEFOP(ISUB)
var value1 = OPPOP();
var value2 = OPPOP();
var value1 = OPPOP();
var result = value1 - value2;
if (IS_UNDERFLOW(result,INT_MAX_VALUE)){
if (IS_UNDERFLOW(result,INT_MIN_VALUE)){
OPPUSH(INT_OVERFLOW(result));
}else{
OPPUSH(result);
@ -1417,9 +1440,9 @@ DEFOP(PUTFIELD)
var objectref = OPPOP();
CHECK_NULL(objectref)
var field = objectref["class"].constantPool.get((indexbyte1 << 8) | indexbyte2);
var field = xl.constantPool.get((indexbyte1 << 8) | indexbyte2);
//check if static
objectref[canonicalName(field.class_ref.name_ref) + " " + field.name_and_type_ref.name_ref.str] = value;
objectref[field.class_ref.name_ref.str + " " + field.name_and_type_ref.name_ref.str] = value;
ENDDEF
DEFOP(GETSTATIC)

View File

@ -0,0 +1,18 @@
/* -*- Mode: Javascript -*-
* -*- coding: UTF-8 -*-
* Copyright (C) 2011 by Artur Ventura
*
* File: javaNativeInterface.js
* Time-stamp: Fri Jul 15 02:46:27 2011
*
* Author: Artur Ventura
*
*/
//arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V
function java_lang_System_arraycopy(src,srcPos,dest,destPos,length){
var temp = src.value.slice(srcPos,length);
for (var i = 0; i < temp.length; i++){
dest.value[destPos + i] = temp[i];
}
}

View File

@ -10,7 +10,15 @@
*/
#include "cpu.jsh"
String.prototype.toArray = function(){
var result =[];
for(i =0; i < this.length; i++){
result.push(this.charCodeAt(i));
}
return result;
}
function printNativeArray(){
var result = "[";
if(this.primitive){
@ -49,4 +57,4 @@ function printNativeArray(){
function make1DNativeArray(count,primitive,type){
var inst = {toString: printNativeArray,length:count, dimensions:1, value:[], primitive:primitive, 'class':type};
return inst;
}
}

View File

@ -2,9 +2,13 @@
<head>
<title>JS JVM</title>
<script>
var lident = -1;
write = function(msg){
var l = document.getElementById("log");
var match;
if (msg.match(/Calling/)){
lident++;
}
if ((match = msg.match(/(\d+): (\w+) (op:\[[^\]]*]) (.*)/))){
var space3 = "";
for(var i=0; i<3-(match[1].length); i++){space3 += " " }
@ -16,7 +20,15 @@
}else{
msg=htmlentities(msg);
}
l.innerHTML = l.innerHTML + msg + "\n";
if (msg.match(/!! NATIVE !!/)){
msg = "<span style='color:green'>" + msg + "</span>"
}
var spac = ""
for (var i =0; i<lident; i++){ spac += " ";}
if (msg.match(/Returing/)){
lident--;
}
l.innerHTML = l.innerHTML + spac + msg + "\n";
}
</script>