From 2be0a5b730edbb1cac8c845b2080ec15f27b2c01 Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Wed, 8 Oct 2014 12:20:48 -0700 Subject: [PATCH] Revert "Move alternateImpl detection into MethodInfo constructor." --- classinfo.js | 24 ++++-------------------- instrument.js | 15 ++++++++++----- native.js | 12 ++++++++++++ override.js | 20 ++++++++++++++++++++ vm.js | 4 ++++ 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/classinfo.js b/classinfo.js index 478433e6b..258cefe0a 100644 --- a/classinfo.js +++ b/classinfo.js @@ -30,10 +30,6 @@ FieldInfo.prototype.toString = function() { return "[field " + this.name + "]"; } -function missingNativeImpl(key, ctx, stack) { - console.error("Attempted to invoke missing native:", key); -} - function MethodInfo(m, classInfo, constantPool) { this.classInfo = classInfo; this.name = constantPool[m.name_index].bytes; @@ -54,22 +50,10 @@ function MethodInfo(m, classInfo, constantPool) { this.isPublic = ACCESS_FLAGS.isPublic(m.access_flags); this.isStatic = ACCESS_FLAGS.isStatic(m.access_flags); this.isSynchronized = ACCESS_FLAGS.isSynchronized(m.access_flags); - this.key = (this.isStatic ? "S." : "I.") + this.name + "." + this.signature; - this.implKey = this.classInfo.className + "." + this.name + "." + this.signature; - - if (this.isNative) { - if (this.implKey in Native) { - this.alternateImpl = Native[this.implKey]; - } else { - // Some Native MethodInfos are constructed but never called; - // that's fine, unless we actually try to call them. - this.alternateImpl = missingNativeImpl.bind(null, this.implKey); - } - } else if (this.implKey in Override) { - this.alternateImpl = Override[this.implKey]; - } else { - this.alternateImpl = null; - } + + this.alternateImpl = (this.isNative ? Native : + Override.hasMethod(this) ? Override : + null); } var ClassInfo = function(classBytes) { diff --git a/instrument.js b/instrument.js index ab77e8530..92d7da4a2 100644 --- a/instrument.js +++ b/instrument.js @@ -10,8 +10,12 @@ var Instrument = { profiling: false, profile: null, + getKey: function(methodInfo) { + return methodInfo.classInfo.className + "." + methodInfo.name + "." + methodInfo.signature; + }, + callEnterHooks: function(methodInfo, caller, callee) { - var key = methodInfo.implKey; + var key = this.getKey(methodInfo); if (Instrument.enter[key]) { Instrument.enter[key](caller, callee); } @@ -32,7 +36,7 @@ var Instrument = { }, callExitHooks: function(methodInfo, caller, callee) { - var key = methodInfo.implKey; + var key = this.getKey(methodInfo); if (this.profiling) { var now = performance.now(); @@ -97,15 +101,16 @@ var Instrument = { this.profiling = false; }, - measure: function(alternateImpl, ctx, methodInfo) { + measure: function(Alt, ctx, methodInfo) { if (this.profiling) { var then = performance.now(); - alternateImpl.call(null, ctx, ctx.current().stack); + Alt.invoke(ctx, methodInfo); + var key = this.getKey(methodInfo); var methodProfileData = this.profile[key] || (this.profile[key] = { count: 0, cost: 0 }); methodProfileData.count++; methodProfileData.cost += performance.now() - then; } else { - alternateImpl.call(null, ctx, ctx.current().stack); + Alt.invoke(ctx, methodInfo); } }, }; diff --git a/native.js b/native.js index 03c6ee47a..6fe8da761 100644 --- a/native.js +++ b/native.js @@ -5,6 +5,18 @@ var Native = {}; +Native.invoke = function(ctx, methodInfo) { + if (!methodInfo.native) { + var key = methodInfo.classInfo.className + "." + methodInfo.name + "." + methodInfo.signature; + methodInfo.native = Native[key]; + if (!methodInfo.native) { + console.error("Missing native: " + key); + ctx.raiseExceptionAndYield("java/lang/RuntimeException", key + " not found"); + } + } + methodInfo.native.call(null, ctx, ctx.current().stack); +} + Native["java/lang/System.arraycopy.(Ljava/lang/Object;ILjava/lang/Object;II)V"] = function(ctx, stack) { var length = stack.pop(), dstOffset = stack.pop(), dst = stack.pop(), srcOffset = stack.pop(), src = stack.pop(); if (!src || !dst) diff --git a/override.js b/override.js index fd5a1c68a..73749b144 100644 --- a/override.js +++ b/override.js @@ -5,6 +5,26 @@ var Override = {}; +Override.getKey = function(methodInfo) { + return methodInfo.classInfo.className + "." + methodInfo.name + "." + methodInfo.signature; +} + +Override.hasMethod = function(methodInfo) { + return ("override" in methodInfo || Override.getKey(methodInfo) in Override); +} + +Override.invoke = function(ctx, methodInfo) { + if (!methodInfo.override) { + var key = Override.getKey(methodInfo); + methodInfo.override = Override[key]; + if (!methodInfo.override) { + console.error("Missing override: " + key); + ctx.raiseExceptionAndYield("java/lang/RuntimeException", key + " not found"); + } + } + methodInfo.override.call(null, ctx, ctx.current().stack); +} + Override["com/ibm/oti/connection/file/Connection.decode.(Ljava/lang/String;)Ljava/lang/String;"] = function(ctx, stack) { var string = util.fromJavaString(stack.pop()); stack.push(ctx.newString(decodeURIComponent(string))); diff --git a/vm.js b/vm.js index 1bb27802a..07848c9b9 100644 --- a/vm.js +++ b/vm.js @@ -1040,6 +1040,10 @@ VM.execute = function(ctx) { case OPCODES.invokevirtual: case OPCODES.invokeinterface: if (methodInfo.classInfo != obj.class) { + if (!methodInfo.key) { + methodInfo.key = "I." + methodInfo.name + "." + methodInfo.signature; + } + // Check if the method is already in the virtual method cache if (obj.class.vmc[methodInfo.key]) { methodInfo = obj.class.vmc[methodInfo.key];