Native Interface, Static invocation, several bug fixes, 40% opcode coverage
This commit is contained in:
parent
7dec232268
commit
8630cf0e59
@ -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;
|
||||
|
11
src/cpu.js
11
src/cpu.js
@ -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;
|
||||
|
||||
}
|
||||
|
51
src/infos.js
51
src/infos.js
@ -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
16
src/internalJNI.jsh
Normal 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
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
18
src/javaNativeInterface.js
Normal file
18
src/javaNativeInterface.js
Normal 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];
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user