зеркало из https://github.com/mozilla/pluotsorbet.git
iteratively find methods up along the inheritance chain
This commit is contained in:
Родитель
3236838dbf
Коммит
cccd855674
21
classes.js
21
classes.js
|
@ -89,7 +89,7 @@ Classes.prototype.getClass = function(caller, className) {
|
||||||
return this.getArrayClass(caller, className);
|
return this.getArrayClass(caller, className);
|
||||||
if (!!(classInfo = this.loadClassFile(className + ".class"))) {
|
if (!!(classInfo = this.loadClassFile(className + ".class"))) {
|
||||||
classInfo.staticFields = {};
|
classInfo.staticFields = {};
|
||||||
var clinit = this.getMethod(classInfo, "<clinit>", "()V", true);
|
var clinit = this.getMethod(caller, classInfo, "<clinit>", "()V", true, false);
|
||||||
if (clinit)
|
if (clinit)
|
||||||
caller.invoke(OPCODES.invokestatic, clinit);
|
caller.invoke(OPCODES.invokestatic, clinit);
|
||||||
classInfo.constructor = function () {
|
classInfo.constructor = function () {
|
||||||
|
@ -128,17 +128,22 @@ Classes.prototype.setStaticField = function(caller, className, fieldName, value)
|
||||||
this.getClass(caller, className).staticFields[fieldName] = value;
|
this.getClass(caller, className).staticFields[fieldName] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Classes.prototype.getMethod = function(classInfo, methodName, signature, staticFlag) {
|
Classes.prototype.getMethod = function(caller, classInfo, methodName, signature, staticFlag, inheritFlag) {
|
||||||
console.log(classInfo.className, methodName, signature);
|
console.log(classInfo.className, methodName, signature);
|
||||||
var methods = classInfo.methods;
|
while (true) {
|
||||||
for (var i=0; i<methods.length; i++) {
|
var methods = classInfo.methods;
|
||||||
if (ACCESS_FLAGS.isStatic(methods[i].access_flags) === !!staticFlag) {
|
for (var i=0; i<methods.length; i++) {
|
||||||
if (methods[i].name === methodName && methods[i].signature === signature) {
|
if (ACCESS_FLAGS.isStatic(methods[i].access_flags) === !!staticFlag) {
|
||||||
return methods[i];
|
if (methods[i].name === methodName && methods[i].signature === signature) {
|
||||||
|
return methods[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var superClassName = classInfo.superClassName;
|
||||||
|
if (!superClassName)
|
||||||
|
return null;
|
||||||
|
classInfo = this.getClass(caller, superClassName);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Classes.prototype.newObject = function(caller, className) {
|
Classes.prototype.newObject = function(caller, className) {
|
||||||
|
|
10
frame.js
10
frame.js
|
@ -98,7 +98,7 @@ Frame.prototype.throw = function(ex) {
|
||||||
|
|
||||||
Frame.prototype.raiseException = function(className, message) {
|
Frame.prototype.raiseException = function(className, message) {
|
||||||
var ex = CLASSES.newObject(this, className);
|
var ex = CLASSES.newObject(this, className);
|
||||||
var ctor = CLASSES.getMethod(ex.class, "<init>", "(Ljava/lang/String;)V", false);
|
var ctor = CLASSES.getMethod(this, ex.class, "<init>", "(Ljava/lang/String;)V", false, false);
|
||||||
this.stack.push(ex);
|
this.stack.push(ex);
|
||||||
this.stack.push(message);
|
this.stack.push(message);
|
||||||
this.invoke(OPCODES.invokespecial, ctor);
|
this.invoke(OPCODES.invokespecial, ctor);
|
||||||
|
@ -124,7 +124,7 @@ Frame.prototype.invoke = function(op, methodInfo) {
|
||||||
case OPCODES.invokevirtual:
|
case OPCODES.invokevirtual:
|
||||||
console.log("virtual dispatch", methodInfo.classInfo.className, obj.class.className, methodInfo.name, methodInfo.signature);
|
console.log("virtual dispatch", methodInfo.classInfo.className, obj.class.className, methodInfo.name, methodInfo.signature);
|
||||||
if (methodInfo.classInfo != obj.class)
|
if (methodInfo.classInfo != obj.class)
|
||||||
methodInfo = CLASSES.getMethod(obj.class, methodInfo.name, methodInfo.signature, op === OPCODES.invokestatic);
|
methodInfo = CLASSES.getMethod(this, obj.class, methodInfo.name, methodInfo.signature, op === OPCODES.invokestatic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,11 @@ Frame.prototype.invoke = function(op, methodInfo) {
|
||||||
callee.locals = this.stack;
|
callee.locals = this.stack;
|
||||||
callee.localsBase = this.stack.length - consumes;
|
callee.localsBase = this.stack.length - consumes;
|
||||||
|
|
||||||
|
console.log("consumes:", consumes, "localsBase:", callee.localsBase);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var op = callee.read8();
|
var op = callee.read8();
|
||||||
console.log(callee.methodInfo.classInfo.className, callee.methodInfo.name, callee.ip - 1, OPCODES[op], callee.stack.length);
|
console.log(callee.methodInfo.classInfo.className, callee.methodInfo.name, callee.ip - 1, OPCODES[op], callee.stack.join(","));
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OPCODES.return:
|
case OPCODES.return:
|
||||||
this.stack.length -= consumes;
|
this.stack.length -= consumes;
|
||||||
|
@ -1000,7 +1002,7 @@ Frame.prototype.invokestatic = Frame.prototype.invokevirtual = Frame.prototype.i
|
||||||
var signature = cp[cp[cp[idx].name_and_type_index].signature_index].bytes;
|
var signature = cp[cp[cp[idx].name_and_type_index].signature_index].bytes;
|
||||||
|
|
||||||
var classInfo = CLASSES.getClass(this, className);
|
var classInfo = CLASSES.getClass(this, className);
|
||||||
var method = CLASSES.getMethod(classInfo, methodName, signature, op === OPCODES.invokestatic);
|
var method = CLASSES.getMethod(this, classInfo, methodName, signature, op === OPCODES.invokestatic);
|
||||||
|
|
||||||
this.invoke(op, method);
|
this.invoke(op, method);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче