2011-07-15 02:50:47 +01:00
|
|
|
/* -*- 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2011-07-20 18:19:50 +01:00
|
|
|
#include "constantPool.jsh"
|
|
|
|
#include "opcodes.jsh"
|
|
|
|
#include "types.jsh"
|
|
|
|
#include "cpu.jsh"
|
2011-07-15 02:50:47 +01:00
|
|
|
|
2011-07-19 15:17:34 +01:00
|
|
|
/** @constructor */
|
2011-07-04 18:20:27 +01:00
|
|
|
var JVM = function(params,args){
|
2011-07-17 18:42:58 +01:00
|
|
|
this.nativeMappingTable = {}
|
2011-07-04 18:20:27 +01:00
|
|
|
this.params = params;
|
|
|
|
this.args = args;
|
|
|
|
this.method_area = {};
|
|
|
|
this.level = 0;
|
|
|
|
this.classpath = params.classes_to_load;
|
|
|
|
|
2011-07-06 16:30:18 +01:00
|
|
|
this.classForName = function (name){
|
2011-07-17 18:42:58 +01:00
|
|
|
if (!name) { PANIC("undefined className")}
|
2011-07-06 16:30:18 +01:00
|
|
|
var superClass, loaded_class = this.method_area[name];
|
2011-07-08 17:29:57 +01:00
|
|
|
|
2011-07-06 16:30:18 +01:00
|
|
|
if (!loaded_class){
|
|
|
|
loaded_class = LoadClassFile(name, this);
|
2011-07-08 17:29:57 +01:00
|
|
|
this.method_area[name] = loaded_class;
|
2011-07-06 16:30:18 +01:00
|
|
|
this.verifyAndLoadClass(loaded_class);
|
2011-07-04 18:20:27 +01:00
|
|
|
|
2011-07-15 02:50:47 +01:00
|
|
|
LOG("[Loaded " + name + "]");
|
2011-07-06 16:30:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return loaded_class;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-07-08 17:29:57 +01:00
|
|
|
this.verifyAndLoadClass = function(loaded_class){
|
2011-07-06 16:30:18 +01:00
|
|
|
var superClass;
|
|
|
|
if(loaded_class.super_class){
|
2011-07-08 17:29:57 +01:00
|
|
|
// if super_class not java.lang.Object
|
2011-07-17 18:42:58 +01:00
|
|
|
superClass = canonicalName(loaded_class.super_class.name_ref);
|
|
|
|
loaded_class.super_class_ref = this.classForName(superClass);
|
2011-07-06 16:30:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// this doesn't seem right. doing this will cause the entire JRE to be loaded
|
|
|
|
// as soon as you start JVM.
|
2011-07-04 18:20:27 +01:00
|
|
|
|
2011-07-06 16:30:18 +01:00
|
|
|
/*
|
|
|
|
var that = this;
|
|
|
|
|
2011-07-04 18:20:27 +01:00
|
|
|
loaded_class.constantPool.each(function(constant){
|
|
|
|
if (constant.name_ref.str.charAt(0) == "[") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
that.verifyAndLoadClass(canonicalName(constant.name_ref));
|
2011-07-06 16:30:18 +01:00
|
|
|
}, CONSTANT_Class);*/
|
2011-07-04 18:20:27 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
this.run = function (){
|
2011-07-06 16:30:18 +01:00
|
|
|
this.java_lang_object = this.classForName("java.lang.Object");
|
|
|
|
this.java_lang_cloneable = this.classForName("java.lang.Cloneable");
|
|
|
|
this.java_io_serializable = this.classForName("java.io.Serializable");
|
2011-07-21 19:03:57 +01:00
|
|
|
this.java_lang_string = this.classForName("java.lang.String");
|
2011-08-03 00:32:54 +01:00
|
|
|
this.main_class = this.classForName(this.args[0])
|
|
|
|
this.main_class.initializeClass();
|
|
|
|
var method = this.main_class["method main([Ljava/lang/String;)V"];
|
|
|
|
if (method == null){
|
|
|
|
PANIC(this.args[0] + " doesn't have a a main method");
|
|
|
|
}
|
|
|
|
method.invoke(null,this.main_class);
|
2011-07-04 18:20:27 +01:00
|
|
|
};
|
|
|
|
};
|
2011-07-19 15:17:34 +01:00
|
|
|
/** @constructor */
|
2011-07-04 18:20:27 +01:00
|
|
|
var JVMThread = function(){
|
|
|
|
this.pc = null;
|
|
|
|
this.stack = [];
|
|
|
|
}
|
2011-07-19 15:17:34 +01:00
|
|
|
/** @constructor */
|
2011-07-04 18:20:27 +01:00
|
|
|
var JVMFrame = function(){
|
|
|
|
this.local_variables = [];
|
|
|
|
this.operand_stack = [];
|
|
|
|
|
2011-07-06 16:30:18 +01:00
|
|
|
}
|
2011-07-19 15:17:34 +01:00
|
|
|
/** @constructor */
|
2011-07-15 02:50:47 +01:00
|
|
|
function JVMPanic(message){
|
|
|
|
this.toString = function(){
|
|
|
|
return "JVMPanic: " + message
|
|
|
|
}
|
2011-08-03 00:32:54 +01:00
|
|
|
}
|
2011-07-15 02:50:47 +01:00
|
|
|
|
2011-08-03 00:32:54 +01:00
|
|
|
function interpret(frame,code,method,xl){
|
2011-07-06 16:30:18 +01:00
|
|
|
var operand_stack = frame.operand_stack;
|
2011-07-08 17:29:57 +01:00
|
|
|
var local_variables = frame.local_variables;
|
2011-07-19 15:17:34 +01:00
|
|
|
var opcode;
|
2011-08-03 00:32:54 +01:00
|
|
|
var pc = 0;
|
|
|
|
|
2011-07-18 00:56:41 +01:00
|
|
|
#ifdef DEBUG_INTRP
|
|
|
|
var temp = null;
|
|
|
|
#endif
|
2011-08-03 00:32:54 +01:00
|
|
|
while(pc < code.length){
|
|
|
|
opcode = READ_NEXT();
|
2011-07-18 00:56:41 +01:00
|
|
|
switch(OPCODE){
|
2011-08-02 14:08:37 +01:00
|
|
|
#include "intrp.def"
|
2011-08-03 00:32:54 +01:00
|
|
|
default:
|
|
|
|
PANIC("Invalid OPCODE " + opcode);
|
2011-07-06 16:30:18 +01:00
|
|
|
}
|
2011-08-03 00:32:54 +01:00
|
|
|
#ifdef DEBUG_INTRP
|
|
|
|
temp = null;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
PANIC("PC overran CODE");
|
2011-07-20 18:19:50 +01:00
|
|
|
}
|
2011-08-03 00:32:54 +01:00
|
|
|
|
|
|
|
|