BicaVM/constantPool.js
2011-07-15 02:50:47 +01:00

323 lines
8.5 KiB
JavaScript

/* -*- 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
var constUtf8 = function(){
this.str = null;
this.id = CONSTANT_Utf8;
this.read = function ( dStream ) {
var strBuf;
var charCnt;
var byte_x,byte_y,byte_z;
var result;
one_char = '\u0000';
this.length = dStream.getU2();
strBuf = "";
charCnt = 0;
while (charCnt < this.length) {
byte_x = dStream .getU1();
charCnt++;
if ((byte_x >> 7) == 1){
byte_y = dStream .getU1();
charCnt++;
if ((byte_x >> 5) == 7){
byte_z = dStream .getU1();
charCnt++;
result = ((byte_x & 0xf) << 12) + ((byte_y & 0x3f) << 6) + (byte_z & 0x3f)
}else{
result = ((byte_x & 0x1f) << 6) + (byte_y & 0x3f)
}
}else{
result = byte_x
}
strBuf += String.fromCharCode(byte_x);
} // while
this.str = strBuf.toString();
} // read
return this;
};
var constInt = function(){
this.value = null;
this.id = CONSTANT_Integer;
this.read = function ( dStream ){
this.value = dStream.getU4();
}
};
var constFloat = function(){
this.value = null;
this.id = CONSTANT_Float;
this.read = function ( dStream ){
this.value = dStream.getU4();
}
};
var constLong = function(){
this.high = null;
this.low = null;
this.id = CONSTANT_Long;
this.read = function (dStream){
this.high = dStream.getU4();
this.low = dStream.getU4();
}
};
var constDouble = function(){
this.high = null;
this.low = null;
this.id = CONSTANT_Double;
this.read = function (dStream){
this.high = dStream.getU4();
this.low = dStream.getU4();
}
};
var constClass = function(){
this.name_index = null;
this.id = CONSTANT_Class;
this.read = function(dStream){
this.name_index = dStream.getU2();
}
this.set_ref = function(pool){
var ref = pool[this.name_index - 1];
if (!ref || ref.id != CONSTANT_Utf8){
throw "Class name index doesn't point to Utf8 in the Constant Pool";
}
this.name_ref = ref;
}
};
var constString = function(){
this.string_index = null;
this.id = CONSTANT_String;
this.read = function(dStream){
this.string_index = dStream.getU2();
}
this.set_ref = function(pool){
var ref = pool[this.string_index - 1];
if (!ref && ref.id != CONSTANT_Utf8){
throw "String index doesn't point to Utf8 in the Constant Pool";
}
this.string_ref = ref;
}
};
var constRef = function(){
this.class_index = null;
this.name_and_type_index = null;
this.read = function(dStream){
this.class_index = dStream.getU2();
this.name_and_type_index = dStream.getU2();
};
this.set_ref = function(pool){
var classRef = pool[this.class_index - 1];
if (!classRef || classRef.id != CONSTANT_Class){
throw constTagName(this.id) + " class index doesn't point to Class in the Constant Pool";
}
this.class_ref = classRef;
var nAiRef = pool[this.name_and_type_index - 1];
if (!nAiRef || nAiRef.id != CONSTANT_NameAndType){
throw constTagName(this.id) + " name and type index doesn't point to Name and Type in the Constant Pool, got " + constTagName(nAiRef.id);
}
this.name_and_type_ref = nAiRef;
}
};
var constFieldRef = function(){
var temp = new constRef();
temp.id = CONSTANT_Fieldref;
return temp;
};
var constMethodRef = function(){
var temp = new constRef();
temp.id = CONSTANT_Methodref;
return temp;
};
var constInterfaceMethodRef = function(){
var temp = new constRef();
temp.id = CONSTANT_InterfaceMethodref;
return temp;
};
var constName_and_Type_info = function(){
this.name_index = null;
this.descriptor_index = null;
this.id = CONSTANT_NameAndType;
this.read = function(dStream){
this.name_index = dStream.getU2();
this.descriptor_index = dStream.getU2();
};
this.set_ref = function(pool){
var nameRef = pool[this.name_index - 1];
if (!nameRef || nameRef.id != CONSTANT_Utf8){
throw "Name_and_Type name index doesn't point to Utf8 in the Constant Pool";
}
this.name_ref = nameRef;
var descriptorRef = pool[this.descriptor_index - 1];
if(!descriptorRef || descriptorRef.id != CONSTANT_Utf8){
throw "Name_and_Type descriptior index doesn't point to Utf8 in the Constant Pool";
}
this.descriptor_ref = descriptorRef;
}
}
var allocConstEntry = function(tag){
var obj = null;
switch ( tag ) {
case CONSTANT_Utf8:
obj = new constUtf8();
break;
case CONSTANT_Integer:
obj = new constInt();
break;
case CONSTANT_Float:
obj = new constFloat();
break;
case CONSTANT_Long:
obj = new constLong();
break;
case CONSTANT_Double:
obj = new constDouble();
break;
case CONSTANT_Class:
obj = new constClass();
break;
case CONSTANT_String:
obj = new constString();
break;
case CONSTANT_Fieldref:
obj = new constFieldRef();
break;
case CONSTANT_Methodref:
obj = new constMethodRef();
break;
case CONSTANT_InterfaceMethodref:
obj = new constInterfaceMethodRef();
break;
case CONSTANT_NameAndType:
obj = new constName_and_Type_info();
break;
default:
throw "allocConstEntry: bad tag value = " + tag;
break;
} // switch
return obj;
}
var constTagName = function (info){
switch(info){
case 7:
return "Class";
case 9:
return "FieldRef";
case 10:
return "MethodRef";
case 11:
return "InterfaceMethodRef";
case 8:
return "String";
case 3:
return "Integer";
case 4:
return "Float";
case 5:
return "Long";
case 6:
return "Double";
case 12:
return "NameAndType";
case 1:
return "Utf8";
default:
return "??0x" + info.toString(16) + "??";
}
return null;
}
var ConstantPoolRef = function(index, constantPool, expected){
if (index-1 < 0 || index-1 >= constantPool.constantPool.length){
throw "ConstantPoolRef: ref out of bounds: " + (index-1).toString() + ", length: " + constantPool.constantPool.length;
}
var result = constantPool.constantPool[index - 1];
if (expected && result.id != expected){
throw "ConstantPoolRef: ref was expected to be " + constTagName(expected) + " but at " + index + " there's a " + constTagName(result.id);
}
return result;
}
var ConstantPool = function(){
}
ConstantPool.prototype.loadFromStream = function(dStream){
this.constantPoolCount = dStream.getU2();
this.constantPool = [];
for(var i = 1; i < this.constantPoolCount; i++){
var tag = dStream.getU1();
var alloc = allocConstEntry(tag);
alloc.read(dStream);
this.constantPool[(i-1)] = alloc;
if (alloc.id == CONSTANT_Long || alloc.id == CONSTANT_Double) {
i++;
this.constantPool[(i-1)] = null;
}
}
for(var i = 1; i < this.constantPoolCount; i++){
var obj = this.constantPool[(i-1)];
if (obj && obj.set_ref){
obj.set_ref(this.constantPool);
}
}
this.each = function(fn,kind){
for(var i = 1; i < this.constantPoolCount; i++){
var obj = this.constantPool[(i-1)];
if (obj){
if (obj.id != kind) {continue;}
fn(obj);
}
}
}
}
ConstantPool.prototype.get = function (i){
return this.constantPoll[i];
}