Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
Signed-off-by: jvilk <jvilk@cs.umass.edu>
  • Loading branch information
jvilk committed May 28, 2012
0 parents commit 794adca
Show file tree
Hide file tree
Showing 2,798 changed files with 8,065 additions and 0 deletions.
562 changes: 562 additions & 0 deletions Attributes.js

Large diffs are not rendered by default.

1,441 changes: 1,441 additions & 0 deletions ByteCode.js

Large diffs are not rendered by default.

469 changes: 469 additions & 0 deletions Class.js

Large diffs are not rendered by default.

347 changes: 347 additions & 0 deletions ConstantPoolInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@
/**
* Object for the entire constant pool for a class.
*/
function ConstantPool(javaClassReader) {
//This global is used by the parsing process as a convenient location
//for getting constant pool data.
CONSTANTPOOL = this;

/**
* METHODS
*/

/**
* Get the string from a UTF8 info object at the given index.
* Asserts that it is, in fact, a UTF8 info object.
*/
this.getUTF8Info = function(index) {
if (index == 0) return undefined;
assert(this[index].tag == ConstantPoolInfo.tags.UTF8);
return this[index].string;
};

/**
* Resolve a class info object at the given index to its UTF8 name.
* Asserts that it is, in fact, a class info object.
*/
this.getClassInfo = function(index) {
if (index == 0) return undefined;
if (!(index in this)) assert(false);
assert(this[index].tag == ConstantPoolInfo.tags.CLASS);
return this[index].name;
};

/**
* Print the constant pool contents to the terminal.
*/
this.print = function() {
addTextToConsole("Constant Pool Contents:");
for (var i = 1; i < this.count; i++)
{
addTextToConsole("\t" + i + " ");
this[i].print();
}
};

/**
* PARSING
*/

//u2 constant_pool_count;
this.count = javaClassReader.getUintField(2);
//cp_info constant_pool[constant_pool_count-1];
//NOTE: Index 0 of the constant pool is reserved for use by the JVM, and is not
//in the class file.
for(var i = 1; i < this.count; i++) {
var tag = javaClassReader.getUintField(1);

switch(tag) {
case ConstantPoolInfo.tags.CLASS:
var name_index = javaClassReader.getUintField(2);
this[i] = new ConstantClassInfo(name_index);
break;
case ConstantPoolInfo.tags.FIELDREF:
case ConstantPoolInfo.tags.METHODREF:
case ConstantPoolInfo.tags.INTERFACEMETHODREF:
var class_index = javaClassReader.getUintField(2);
var name_and_type_index = javaClassReader.getUintField(2);
this[i] = new ConstantRefInfo(tag, class_index, name_and_type_index);
break;
case ConstantPoolInfo.tags.STRING:
var string_index = javaClassReader.getUintField(2);
this[i] = new ConstantStringInfo(string_index);
break;
case ConstantPoolInfo.tags.INTEGER:
var bytes = new Integer(javaClassReader.getIntField(4));
this[i] = new ConstantNumberInfo(tag, bytes);
break;
case ConstantPoolInfo.tags.FLOAT:
var bytes = new Float(javaClassReader.getFloatField(4));
this[i] = new ConstantNumberInfo(tag, bytes);
break;
case ConstantPoolInfo.tags.LONG:
var high = javaClassReader.getUintField(4);
var low = javaClassReader.getUintField(4);
var long_value = new Long(low, high);
this[i] = new ConstantBigNumberInfo(tag, long_value);
//8 byte constants take up two slots.
i++
break;
case ConstantPoolInfo.tags.DOUBLE:
var double_field = new Double(javaClassReader.getDoubleField(8));
this[i] = new ConstantBigNumberInfo(tag, double_field);
//8 byte constants take up two slots.
i++;
break;
case ConstantPoolInfo.tags.NAMEANDTYPE:
var name_index = javaClassReader.getUintField(2);
var descriptor_index = javaClassReader.getUintField(2);
this[i] = new ConstantNameAndTypeInfo(name_index, descriptor_index);
break;
case ConstantPoolInfo.tags.UTF8:
var length = javaClassReader.getUintField(2);
var string = javaClassReader.getUTF8Field(length);
this[i] = new ConstantUTF8Info(length, string);
break;
default:
addErrorToConsole("ERROR: Unable to determine the 'tag' element of a cp_info struct: " + tag + ".");
break;
}
}

//Constant pool items sometimes refer to other constant pool items, and
//we cannot resolve these references until the constant pool is completely
//assembled. So, we do it after the fact.
for (var i = 1; i < this.count; i++)
{
if (i in this) //This may be false for the second items for double/long constants.
{
this[i].resolveReferences(this);
}
}
}

/*The parent object for all the Constant Pool objects
*Paramaters
* tagType - What type is this information for
*/
function ConstantPoolInfo(tagType) {
this.tag = tagType;
//Part of the "interface" of this type. Resolves references to the constant pool to objects.
this.resolveReferences = function(constantPool) { };
this.print = function() { };
}

ConstantPoolInfo.tags = {
CLASS : 7,
FIELDREF : 9,
METHODREF : 10,
INTERFACEMETHODREF : 11,
STRING : 8,
INTEGER : 3,
FLOAT : 4,
LONG : 5,
DOUBLE : 6,
NAMEANDTYPE : 12,
UTF8 : 1
};

/* Represents a constant_pool_class_info.
* parameters:
* nameIndex - The index into the constant pool that represents the class
*/
function ConstantClassInfo(nameIndex) {
inherits(this,"ConstantPoolInfo", ConstantPoolInfo.tags.CLASS);
this.nameIndex = nameIndex;
//Index into the constant pool for the class 'u2'

//Resolve all references to other constant pool objects.
this.resolveReferences = function(constantPool) {
this.name = CONSTANTPOOL.getUTF8Info(this.nameIndex);
};

this.print = function() {
addTextToCurrentLine("class " + this.name);
};
}

/* Represents a constant_pool_info for FieldRef, MethodRef, or InterfaceMethodRef.
* parameters:
* refType - A tag from ConstantPoolInfo, which has to be either FIELDREF, METHODREF, INTERFACEMETHODREF
* nameIndex - The index into the constant pool that represents the class
*/
function ConstantRefInfo(refType, classIndex, nameAndTypeIndex) {
inherits(this,"ConstantPoolInfo", refType);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
//Lazily resolve; do not access directly.
this._class = undefined;
this._ref = undefined;

//Resolve all references to other constant pool objects.
this.resolveReferences = function(constantPool) {
//Make sure the class has resolved its references first.
CONSTANTPOOL[this.classIndex].resolveReferences();
this.className = CONSTANTPOOL.getClassInfo(this.classIndex);
this.nameAndType = CONSTANTPOOL[this.nameAndTypeIndex];
assert(this.nameAndType.tag == ConstantPoolInfo.tags.NAMEANDTYPE);
};

/**
* Get the field/method/interface method object.
*/
this.getRef = function() {
if (this._ref != undefined)
return this._ref;

var _class = this.getClass();
var name = this.nameAndType.name;
var descriptor = this.nameAndType.descriptor;

switch(this.tag) {
case ConstantPoolInfo.tags.FIELDREF:
this._ref = _class.getField(name, descriptor);
break;
case ConstantPoolInfo.tags.METHODREF:
case ConstantPoolInfo.tags.INTERFACEMETHODREF:
//TODO: Verify that interfaces work in the same way!
//e.g. I don't have to peer through the interfaces in getMethod.
this._ref = _class.getMethod(name, descriptor);
break;
defualt:
break;
}

return this._ref;
};

/**
* Get the class object representing the class that this reference is from.
*/
this.getClass = function() {
if (this._class != undefined)
return this._class;

//addTextToConsole("CPRef ClassIndex: " + this.classIndex);
this._class = Class.getClass(this.className);

return this._class;
};

this.toString = function() {
var output = "";

switch(this.tag)
{
case ConstantPoolInfo.tags.FIELDREF:
output += "fieldref ";
break;
case ConstantPoolInfo.tags.METHODREF:
output += "methodref ";
break;
case ConstantPoolInfo.tags.INTERFACEMETHODREF:
output += "interfacemethodref ";
break;
default:
output += "unknownref ";
break;
}

return output + this.className + " " + this.nameAndType.name + " " + this.nameAndType.descriptor;
}

this.print = function() {
addTextToCurrentLine(this.toString());
};
}

//Used for Strings
function ConstantStringInfo(stringIndex) {
inherits(this,"ConstantPoolInfo", ConstantPoolInfo.tags.STRING);
this.stringIndex = stringIndex;

//Resolve all references to other constant pool objects.
this.resolveReferences = function(constantPool) {
this.string = CONSTANTPOOL.getUTF8Info(this.stringIndex);
};

this.print = function() {
addTextToCurrentLine("string " + this.string);
}
}

//Used for INTEGER OR FLOATING REFERENCES
function ConstantNumberInfo(refType, value) {
inherits(this,"ConstantPoolInfo", refType);
this.value = value;

this.print = function() {
var output = "";

switch(this.tag)
{
case ConstantPoolInfo.tags.INTEGER:
output += "int ";
break;
case ConstantPoolInfo.tags.FLOAT:
output += "float ";
break;
default:
output += "unknownnumber ";
break;
}

addTextToCurrentLine(output + this.value);
};
}

//Used for LONGS and DOUBLES
function ConstantBigNumberInfo(refType, value) {
inherits(this,"ConstantPoolInfo", refType);
this.value = value;

this.print = function() {
var output = "";
switch(this.tag)
{
case ConstantPoolInfo.tags.LONG:
output += "long ";
break;
case ConstantPoolInfo.tags.DOUBLE:
output += "double ";
break;
default:
output += "unknownbignumber ";
break;
}

addTextToCurrentLine(output + this.value);
};
}

function ConstantNameAndTypeInfo(nameIndex, descriptorIndex) {
inherits(this,"ConstantPoolInfo", ConstantPoolInfo.tags.NAMEANDTYPE);
this.nameIndex = nameIndex;
this.descriptorIndex = descriptorIndex;

//Resolve all references to other constant pool objects.
this.resolveReferences = function(constantPool) {
this.name = CONSTANTPOOL.getUTF8Info(this.nameIndex);

this.descriptor = CONSTANTPOOL.getUTF8Info(this.descriptorIndex);
};

this.print = function() {
addTextToCurrentLine("NameAndTypeInfo" + this.name + " " + this.descriptor);
};
}

function ConstantUTF8Info(length, string) {
inherits(this,"ConstantPoolInfo", ConstantPoolInfo.tags.UTF8);
this.length = length;
this.string = string;

this.print = function() {
addTextToCurrentLine("UTF8 " + this.string);
};
}
Loading

0 comments on commit 794adca

Please sign in to comment.