cleanup classinfo, resolve it earlier, don't keep classImage in memory

This commit is contained in:
Andreas Gal 2014-07-13 09:28:19 -07:00
Родитель 191585115e
Коммит 7401fda65d
4 изменённых файлов: 32 добавлений и 56 удалений

Просмотреть файл

@ -41,7 +41,7 @@ Classes.prototype.loadFile = function(fileName) {
Classes.prototype.loadClassBytes = function(bytes) { Classes.prototype.loadClassBytes = function(bytes) {
var classInfo = new ClassInfo(bytes); var classInfo = new ClassInfo(bytes);
this.classes[classInfo.getClassName()] = classInfo; this.classes[classInfo.className] = classInfo;
return classInfo; return classInfo;
} }
@ -51,7 +51,7 @@ Classes.prototype.loadClassFile = function(fileName) {
if (!bytes) if (!bytes)
return null; return null;
var classInfo = this.loadClassBytes(bytes); var classInfo = this.loadClassBytes(bytes);
var classes = classInfo.getClasses(); var classes = classInfo.classes;
for (var i=0; i<classes.length; i++) { for (var i=0; i<classes.length; i++) {
if (!this.classes[classes[i]]) { if (!this.classes[classes[i]]) {
this.loadClassFile(path.dirname(fileName) + path.sep + classes[i] + ".class"); this.loadClassFile(path.dirname(fileName) + path.sep + classes[i] + ".class");
@ -64,10 +64,10 @@ Classes.prototype.getEntryPoint = function(className, methodName) {
for(var name in this.classes) { for(var name in this.classes) {
var classInfo = this.classes[name]; var classInfo = this.classes[name];
if (classInfo instanceof ClassInfo) { if (classInfo instanceof ClassInfo) {
if (!className || (className === classInfo.getClassName())) { if (!className || (className === classInfo.className)) {
if (ACCESS_FLAGS.isPublic(classInfo.getAccessFlags())) { if (ACCESS_FLAGS.isPublic(classInfo.access_flags)) {
var methods = classInfo.getMethods(); var methods = classInfo.methods;
var cp = classInfo.getConstantPool(); var cp = classInfo.constant_pool;
for (var i=0; i<methods.length; i++) { for (var i=0; i<methods.length; i++) {
if (ACCESS_FLAGS.isPublic(methods[i].access_flags) && if (ACCESS_FLAGS.isPublic(methods[i].access_flags) &&
ACCESS_FLAGS.isStatic(methods[i].access_flags) && ACCESS_FLAGS.isStatic(methods[i].access_flags) &&
@ -116,8 +116,8 @@ Classes.prototype.getMethod = function(caller, className, methodName, signature,
console.log(className, methodName, signature); console.log(className, methodName, signature);
// Only force initialization when accessing a static method. // Only force initialization when accessing a static method.
var classInfo = this.getClass(caller, className, staticFlag); var classInfo = this.getClass(caller, className, staticFlag);
var methods = classInfo.getMethods(); var methods = classInfo.methods;
var cp = classInfo.getConstantPool(); var cp = classInfo.constant_pool;
for (var i=0; i<methods.length; i++) { for (var i=0; i<methods.length; i++) {
if (ACCESS_FLAGS.isStatic(methods[i].access_flags) === !!staticFlag) { if (ACCESS_FLAGS.isStatic(methods[i].access_flags) === !!staticFlag) {
if (cp[methods[i].name_index].bytes === methodName) { if (cp[methods[i].name_index].bytes === methodName) {
@ -127,7 +127,7 @@ Classes.prototype.getMethod = function(caller, className, methodName, signature,
} }
} }
} }
return inheritFlag ? this.getMethod(caller, classInfo.getSuperClassName(), methodName, signature, staticFlag, inheritFlag) : null; return inheritFlag ? this.getMethod(caller, classInfo.superClassName, methodName, signature, staticFlag, inheritFlag) : null;
}; };
Classes.prototype.getStaticMethod = function(caller, className, methodName, signature) { Classes.prototype.getStaticMethod = function(caller, className, methodName, signature) {

Просмотреть файл

@ -5,52 +5,28 @@
var ClassInfo = function(classBytes) { var ClassInfo = function(classBytes) {
if (this instanceof ClassInfo) { if (this instanceof ClassInfo) {
this.classImage = getClassImage(classBytes, this); var classImage = getClassImage(classBytes, this);
var cp = classImage.constant_pool;
this.className = cp[cp[classImage.this_class].name_index].bytes;
this.superClassName = classImage.super_class ? cp[cp[classImage.super_class].name_index].bytes : null;
this.access_flags = classImage.access_flags;
this.constant_pool = cp;
this.fields = classImage.fields;
this.methods = classImage.methods;
this.classes = [];
classImage.attributes.forEach(function(a) {
if (a.info.type === ATTRIBUTE_TYPES.InnerClasses) {
a.info.classes.forEach(function(c) {
classes.push(cp[cp[c.inner_class_info_index].name_index].bytes);
classes.push(cp[cp[c.outer_class_info_index].name_index].bytes);
});
}
});
} else { } else {
return new ClassInfo(classBytes); return new ClassInfo(classBytes);
} }
} }
ClassInfo.prototype.getClassName = function() {
return this.classImage.constant_pool[this.classImage.constant_pool[this.classImage.this_class].name_index].bytes;
}
ClassInfo.prototype.getSuperClassName = function() {
if (!this.classImage.super_class)
return null;
return this.classImage.constant_pool[this.classImage.constant_pool[this.classImage.super_class].name_index].bytes;
}
ClassInfo.prototype.getAccessFlags = function() {
return this.classImage.access_flags;
}
ClassInfo.prototype.getConstantPool = function() {
return this.classImage.constant_pool;
}
ClassInfo.prototype.getFields = function() {
return this.classImage.fields;
}
ClassInfo.prototype.getMethods = function() {
return this.classImage.methods;
}
ClassInfo.prototype.getClasses = function() {
var self = this;
var classes = [];
this.classImage.attributes.forEach(function(a) {
if (a.info.type === ATTRIBUTE_TYPES.InnerClasses) {
a.info.classes.forEach(function(c) {
classes.push(self.classImage.constant_pool[self.classImage.constant_pool[c.inner_class_info_index].name_index].bytes);
classes.push(self.classImage.constant_pool[self.classImage.constant_pool[c.outer_class_info_index].name_index].bytes);
});
}
});
return classes;
}
var FieldInfo = function(classInfo, access_flags, name_index, descriptor_index) { var FieldInfo = function(classInfo, access_flags, name_index, descriptor_index) {
this.classInfo = classInfo; this.classInfo = classInfo;
this.access_flags = access_flags; this.access_flags = access_flags;

Просмотреть файл

@ -20,7 +20,7 @@ Array.prototype.top = function () {
var Frame = function(methodInfo) { var Frame = function(methodInfo) {
if (methodInfo) { if (methodInfo) {
this.methodInfo = methodInfo; this.methodInfo = methodInfo;
this.cp = methodInfo.classInfo.getConstantPool(); this.cp = methodInfo.classInfo.constant_pool;
this.code = methodInfo.code; this.code = methodInfo.code;
this.ip = 0; this.ip = 0;
} }
@ -76,7 +76,7 @@ Frame.prototype.throw = function(ex) {
handler_pc = this.exception_table[i].handler_pc; handler_pc = this.exception_table[i].handler_pc;
} else { } else {
var name = this.cp[this.cp[this.exception_table[i].catch_type].name_index].bytes; var name = this.cp[this.cp[this.exception_table[i].catch_type].name_index].bytes;
if (name === ex.getClassName()) { if (name === ex.className) {
handler_pc = this.exception_table[i].handler_pc; handler_pc = this.exception_table[i].handler_pc;
break; break;
} }
@ -137,7 +137,7 @@ Frame.prototype.invoke = function(methodInfo) {
while (true) { while (true) {
var op = callee.read8(); var op = callee.read8();
console.log(callee.methodInfo.classInfo.getClassName(), console.log(callee.methodInfo.classInfo.className,
callee.cp[callee.methodInfo.name_index].bytes, callee.cp[callee.methodInfo.name_index].bytes,
callee.ip - 1, OPCODES[op], callee.stack.length); callee.ip - 1, OPCODES[op], callee.stack.length);
switch (op) { switch (op) {
@ -1114,7 +1114,7 @@ Frame.prototype.instanceof = function() {
var idx = this.read16(); var idx = this.read16();
var className = this.cp[this.cp[idx].name_index].bytes; var className = this.cp[this.cp[idx].name_index].bytes;
var obj = this.stack.pop(); var obj = this.stack.pop();
this.stack.push(obj.class.getClassName() === className); this.stack.push(obj.class.className === className);
} }
Frame.prototype.checkcast = function() { Frame.prototype.checkcast = function() {

Просмотреть файл

@ -42,8 +42,8 @@ Native.prototype.invokeNative = function(caller, methodInfo) {
Native.prototype.getMethod = function (methodInfo) { Native.prototype.getMethod = function (methodInfo) {
var classInfo = methodInfo.classInfo; var classInfo = methodInfo.classInfo;
var cp = classInfo.getConstantPool(); var cp = classInfo.constant_pool;
var className = classInfo.getClassName(); var className = classInfo.className;
var methodName = cp[methodInfo.name_index].bytes; var methodName = cp[methodInfo.name_index].bytes;
var signature = cp[methodInfo.signature_index].bytes; var signature = cp[methodInfo.signature_index].bytes;
console.log("Native.getMethod", className, methodName, signature); console.log("Native.getMethod", className, methodName, signature);