This commit is contained in:
Andreas Gal 2014-07-09 01:07:14 -07:00
Родитель 1be8b65ee4
Коммит ee080b93ef
2 изменённых файлов: 39 добавлений и 61 удалений

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

@ -85,14 +85,14 @@ Classes.prototype.getEntryPoint = function(className, methodName) {
Classes.prototype.initClass = function(className) {
var clinit = this.getStaticMethod(className, "<clinit>", "()V");
if (clinit instanceof Frame) {
SCHEDULER.sync(function() {
LOG.debug("call " + className + ".<clinit> ...");
clinit.run([], function() {
LOG.debug("call " + className + ".<clinit> ... done");
});
if (!clinit)
return;
SCHEDULER.sync(function() {
LOG.debug("call " + className + ".<clinit> ...");
clinit.run([], function() {
LOG.debug("call " + className + ".<clinit> ... done");
});
}
});
}
Classes.prototype.getClass = function(className, initialize) {
@ -117,16 +117,18 @@ Classes.prototype.setStaticField = function(className, fieldName, value) {
this.getClass(className, true).staticFields[fieldName] = value;
}
Classes.prototype.getStaticMethod = function(className, methodName, signature) {
var ca = this.getClass(className, true);
Classes.prototype.getMethod = function(className, methodName, signature, staticFlag) {
// Only force initialization when accessing a static method.
var ca = this.getClass(className, staticFlag);
if (ca instanceof ClassArea) {
var methods = ca.getMethods();
var cp = ca.getConstantPool();
for(var i=0; i<methods.length; i++)
if (ACCESS_FLAGS.isStatic(methods[i].access_flags))
for(var i=0; i<methods.length; i++) {
if (ACCESS_FLAGS.isStatic(methods[i].access_flags) === !!staticFlag)
if (cp[methods[i].name_index].bytes === methodName)
if (signature.toString() === cp[methods[i].signature_index].bytes)
return new Frame(ca, methods[i]);
}
} else {
if (methodName in ca) {
return ca[methodName];
@ -134,48 +136,14 @@ Classes.prototype.getStaticMethod = function(className, methodName, signature) {
}
return null;
};
Classes.prototype.getMethod = function(className, methodName, signature) {
// We won't get here without a call to newObject, so no need to force
// class initialization.
var ca = this.getClass(className, false);
if (ca instanceof ClassArea) {
var methods = ca.getMethods();
var cp = ca.getConstantPool();
for(var i=0; i<methods.length; i++)
if (!ACCESS_FLAGS.isStatic(methods[i].access_flags))
if (cp[methods[i].name_index].bytes === methodName)
if (signature.toString() === cp[methods[i].signature_index].bytes)
return new Frame(ca, methods[i]);
} else {
var o = new ca();
if (methodName in o) {
return o[methodName];
}
}
return null;
};
Classes.prototype.newObject = function(className) {
var ca = this.getClass(className, true);
var ctor = function() {};
var superClassName = ca.getSuperClassName();
if (superClassName)
ctor.prototype = this.newObject(superClassName);
var o = new ctor();
var cp = ca.getConstantPool();
ca.getFields().forEach(function(field) {
var fieldName = cp[field.name_index].bytes;
o[fieldName] = null;
});
ca.getMethods().forEach(function(method) {
var methodName = cp[method.name_index].bytes;
var signature = cp[method.signature_index].bytes;
o[methodName + "$" + signature] = new Frame(ca, method);
});
return o;
Classes.prototype.getStaticMethod = function(className, methodName, signature) {
return this.getMethod(className, methodName, signature, true);
}
Classes.prototype.newObject = function(className) {
// Force initialization of the class (if not already done).
this.getClass(className, true);
return {};
}

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

@ -80,10 +80,10 @@ Frame.prototype._throw = function(ex) {
}
Frame.prototype._newException = function(className, message) {
var done = arguments[arguments.length-1];
var self = this;
var ex = CLASSES.newObject(className);
var done = arguments[arguments.length-1];
var ctor = ex["<init>$(Ljava/lang/String;)V"];
var ctor = this.getMethod(className, "<init>", "(Ljava/lang/String;)V");
ctor.setPid(self._pid);
ctor.run([ex, message], function () {
self._throw(ex);
@ -105,7 +105,7 @@ Frame.prototype.run = function(args, done) {
var step = function() {
SCHEDULER.tick(self._pid, function() {
var opCode = self._read8();
console.log(OPCODES.toString(opCode), self._stack.length);
console.log(self._ip - 1, OPCODES.toString(opCode), self._stack.length);
switch (opCode) {
case OPCODES.return:
return done();
@ -220,6 +220,7 @@ Frame.prototype.iconst_5 = function(done) {
Frame.prototype.sipush = function(done) {
this._stack.push(this._read16());
return done();
}
Frame.prototype.bipush = function(done) {
@ -1408,6 +1409,9 @@ Frame.prototype.getfield = function(done) {
if (!obj) {
return this._newException("java/lang/NullPointerException", done);
}
if (!(fieldName in obj)) {
return this._newException("java/lang/VirtualMachineError", done);
}
this._stack.push(obj[fieldName]);
return done();
}
@ -1424,7 +1428,9 @@ Frame.prototype.getstatic = function(done) {
var idx = this._read16();
var className = this._cp[this._cp[this._cp[idx].class_index].name_index].bytes;
var fieldName = this._cp[this._cp[this._cp[idx].name_and_type_index].name_index].bytes;
console.log("XXXXXXXXXXXX BEGIN GETSTATIC XXXXXXXXXXXXX", className, fieldName);
this._stack.push(CLASSES.getStaticField(className, fieldName));
console.log("XXXXXXXXXXXX DONE GETSTATIC XXXXXXXXXXXXX", className, fieldName);
return done();
}
@ -1432,6 +1438,7 @@ Frame.prototype.putstatic = function(done) {
var idx = this._read16();
var className = this._cp[this._cp[this._cp[idx].class_index].name_index].bytes;
var fieldName = this._cp[this._cp[this._cp[idx].name_and_type_index].name_index].bytes;
console.log(className, fieldName, CLASSES.getStaticField(className, fieldName));
CLASSES.setStaticField(className, fieldName, this._stack.pop());
return done();
}
@ -1454,9 +1461,9 @@ Frame.prototype.invokestatic = function(done) {
args.unshift(this._stack.pop());
}
}
var method = CLASSES.getStaticMethod(className, methodName, signature);
if (method instanceof Frame) {
method.setPid(self._pid);
method.run(args, function(res) {
@ -1484,6 +1491,8 @@ Frame.prototype.invokevirtual = function(done) {
var methodName = this._cp[this._cp[this._cp[idx].name_and_type_index].name_index].bytes;
var signature = Signature.parse(this._cp[this._cp[this._cp[idx].name_and_type_index].signature_index].bytes);
console.log("invokevirtual", className, methodName, signature);
var args = [];
for (var i=0; i<signature.IN.length; i++) {
if (!signature.IN[i].isArray && ["long", "double"].indexOf(signature.IN[i].type) !== -1) {
@ -1497,7 +1506,7 @@ Frame.prototype.invokevirtual = function(done) {
var instance = this._stack.pop();
var method = CLASSES.getMethod(className, methodName, signature);
if (method instanceof Frame) {
args.unshift(instance);
method.setPid(self._pid);
@ -1525,6 +1534,8 @@ Frame.prototype.invokespecial = function(done) {
var methodName = this._cp[this._cp[this._cp[idx].name_and_type_index].name_index].bytes;
var signature = Signature.parse(this._cp[this._cp[this._cp[idx].name_and_type_index].signature_index].bytes);
console.log("invokespecial", className, methodName, signature);
var args = [];
for (var i=0; i<signature.IN.length; i++) {
if (!signature.IN[i].isArray && ["long", "double"].indexOf(signature.IN[i].type) !== -1) {
@ -1535,7 +1546,6 @@ Frame.prototype.invokespecial = function(done) {
}
}
var instance = this._stack.pop();
var ctor = CLASSES.getMethod(className, methodName, signature);