2014-09-09 00:18:28 +04:00
|
|
|
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var Instrument = {
|
|
|
|
enter: {},
|
|
|
|
exit: {},
|
2014-09-09 06:13:52 +04:00
|
|
|
|
2014-09-22 12:05:03 +04:00
|
|
|
profiling: false,
|
|
|
|
profile: null,
|
2014-10-24 13:18:11 +04:00
|
|
|
asyncProfile: null,
|
2014-09-21 02:13:26 +04:00
|
|
|
|
2015-01-14 00:33:17 +03:00
|
|
|
enabled: "instrument" in config && !/no|0/.test(config.instrument),
|
2014-10-24 03:04:23 +04:00
|
|
|
|
2014-09-09 06:00:05 +04:00
|
|
|
callEnterHooks: function(methodInfo, caller, callee) {
|
2014-10-31 02:07:29 +03:00
|
|
|
if (this.enabled) {
|
|
|
|
var key = methodInfo.implKey;
|
|
|
|
if (Instrument.enter[key]) {
|
|
|
|
Instrument.enter[key](caller, callee);
|
|
|
|
}
|
2014-09-09 06:00:05 +04:00
|
|
|
}
|
2014-09-21 02:13:26 +04:00
|
|
|
|
2014-09-22 12:05:03 +04:00
|
|
|
if (this.profiling) {
|
2014-09-22 21:50:36 +04:00
|
|
|
var now = performance.now();
|
2014-09-22 10:51:19 +04:00
|
|
|
|
2014-09-23 12:52:33 +04:00
|
|
|
if (caller.profileData && caller.profileData.then) {
|
2014-09-23 13:06:51 +04:00
|
|
|
caller.profileData.cost += now - caller.profileData.then;
|
|
|
|
caller.profileData.then = null;
|
2014-09-22 12:05:03 +04:00
|
|
|
}
|
2014-09-22 10:51:19 +04:00
|
|
|
|
2014-09-22 12:05:03 +04:00
|
|
|
callee.profileData = {
|
|
|
|
cost: 0,
|
|
|
|
then: now,
|
|
|
|
};
|
|
|
|
}
|
2014-09-09 06:00:05 +04:00
|
|
|
},
|
2014-09-09 06:13:52 +04:00
|
|
|
|
2014-09-09 06:00:05 +04:00
|
|
|
callExitHooks: function(methodInfo, caller, callee) {
|
2014-10-07 22:14:05 +04:00
|
|
|
var key = methodInfo.implKey;
|
2014-09-22 10:51:19 +04:00
|
|
|
|
2014-09-22 12:05:03 +04:00
|
|
|
if (this.profiling) {
|
2014-09-22 21:50:36 +04:00
|
|
|
var now = performance.now();
|
2014-09-22 10:51:19 +04:00
|
|
|
|
2014-09-22 12:05:03 +04:00
|
|
|
if (callee.profileData) {
|
2014-09-23 12:52:33 +04:00
|
|
|
if (callee.profileData.then) {
|
|
|
|
callee.profileData.cost += now - callee.profileData.then;
|
|
|
|
callee.profileData.then = null;
|
|
|
|
}
|
|
|
|
|
2014-09-22 22:29:35 +04:00
|
|
|
var methodProfileData = this.profile[key] || (this.profile[key] = { count: 0, cost: 0 });
|
|
|
|
methodProfileData.count++;
|
|
|
|
methodProfileData.cost += callee.profileData.cost;
|
2014-09-22 12:05:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (caller.profileData) {
|
|
|
|
caller.profileData.then = now;
|
|
|
|
}
|
2014-09-22 10:51:19 +04:00
|
|
|
}
|
|
|
|
|
2014-10-31 02:07:29 +03:00
|
|
|
if (this.enabled) {
|
|
|
|
if (Instrument.exit[key]) {
|
|
|
|
Instrument.exit[key](caller, callee);
|
|
|
|
}
|
2014-09-09 06:00:05 +04:00
|
|
|
}
|
|
|
|
},
|
2014-09-21 02:13:26 +04:00
|
|
|
|
2014-09-22 10:59:15 +04:00
|
|
|
callPauseHooks: function(frame) {
|
2014-09-23 12:52:33 +04:00
|
|
|
if (this.profiling && frame.profileData && frame.profileData.then) {
|
|
|
|
frame.profileData.cost += performance.now() - frame.profileData.then;
|
|
|
|
frame.profileData.then = null;
|
2014-09-22 10:59:15 +04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
callResumeHooks: function(frame) {
|
2014-09-22 12:05:03 +04:00
|
|
|
if (this.profiling && frame.profileData) {
|
2014-09-22 21:50:36 +04:00
|
|
|
frame.profileData.then = performance.now();
|
2014-09-22 10:59:15 +04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2014-11-14 20:03:12 +03:00
|
|
|
enterAsyncNative: function(key, promise) {
|
2014-10-24 13:18:11 +04:00
|
|
|
var profileData = this.asyncProfile[key] || (this.asyncProfile[key] = { count: 0, cost: 0 });
|
2014-11-14 20:03:12 +03:00
|
|
|
promise.startTime = performance.now();
|
2014-10-24 13:18:11 +04:00
|
|
|
},
|
|
|
|
|
2014-11-14 20:03:12 +03:00
|
|
|
exitAsyncNative: function(key, promise) {
|
2014-10-24 13:18:11 +04:00
|
|
|
var profileData = this.asyncProfile[key];
|
2014-11-14 20:03:12 +03:00
|
|
|
if (!profileData || !promise.startTime) {
|
2014-10-31 01:15:03 +03:00
|
|
|
// Ignore native without profile data, which can happen when you start
|
|
|
|
// profiling while the native is pending.
|
|
|
|
return;
|
|
|
|
}
|
2014-10-24 13:18:11 +04:00
|
|
|
profileData.count++;
|
2014-11-14 20:03:12 +03:00
|
|
|
profileData.cost += performance.now() - promise.startTime;
|
2014-10-24 13:18:11 +04:00
|
|
|
},
|
|
|
|
|
2014-09-22 12:05:03 +04:00
|
|
|
startProfile: function() {
|
|
|
|
this.profile = {};
|
2014-10-24 13:18:11 +04:00
|
|
|
this.asyncProfile = {};
|
2014-09-22 12:05:03 +04:00
|
|
|
this.profiling = true;
|
|
|
|
},
|
|
|
|
|
2014-10-24 13:18:11 +04:00
|
|
|
printProfile: function(aProfile, aProfileName) {
|
2014-09-21 02:13:26 +04:00
|
|
|
var methods = [];
|
|
|
|
|
2014-10-24 13:18:11 +04:00
|
|
|
for (var key in aProfile) {
|
2014-09-21 02:13:26 +04:00
|
|
|
methods.push({
|
|
|
|
key: key,
|
2014-10-24 13:18:11 +04:00
|
|
|
count: aProfile[key].count,
|
|
|
|
cost: aProfile[key].cost,
|
2014-09-21 02:13:26 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-09-22 22:29:35 +04:00
|
|
|
methods.sort(function(a, b) { return b.cost - a.cost });
|
2014-09-21 02:13:26 +04:00
|
|
|
|
2014-10-24 13:18:11 +04:00
|
|
|
console.log(aProfileName + ":");
|
2014-09-21 02:13:26 +04:00
|
|
|
methods.forEach(function(method) {
|
2014-09-22 22:29:35 +04:00
|
|
|
console.log(Math.round(method.cost) + "ms " + method.count + " " + method.key);
|
2014-09-21 02:13:26 +04:00
|
|
|
});
|
2014-10-24 13:18:11 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
stopProfile: function() {
|
|
|
|
this.printProfile(this.profile, "Profile");
|
|
|
|
this.printProfile(this.asyncProfile, "Async natives profile");
|
2014-09-22 12:05:03 +04:00
|
|
|
|
|
|
|
this.profiling = false;
|
|
|
|
},
|
2014-09-25 02:11:46 +04:00
|
|
|
|
2014-10-07 22:14:05 +04:00
|
|
|
measure: function(alternateImpl, ctx, methodInfo) {
|
|
|
|
var key = methodInfo.implKey;
|
2014-09-25 02:11:46 +04:00
|
|
|
if (this.profiling) {
|
|
|
|
var then = performance.now();
|
2014-10-15 03:38:16 +04:00
|
|
|
alternateImpl.call(null, ctx, ctx.current().stack, methodInfo.isStatic);
|
2014-09-25 02:11:46 +04:00
|
|
|
var methodProfileData = this.profile[key] || (this.profile[key] = { count: 0, cost: 0 });
|
|
|
|
methodProfileData.count++;
|
|
|
|
methodProfileData.cost += performance.now() - then;
|
|
|
|
} else {
|
2014-10-15 03:38:16 +04:00
|
|
|
alternateImpl.call(null, ctx, ctx.current().stack, methodInfo.isStatic);
|
2014-09-25 02:11:46 +04:00
|
|
|
}
|
|
|
|
},
|
2014-09-09 00:18:28 +04:00
|
|
|
};
|
|
|
|
|
2014-10-24 03:04:23 +04:00
|
|
|
Instrument.enter["com/sun/midp/ssl/SSLStreamConnection.<init>.(Ljava/lang/String;ILjava/io/InputStream;Ljava/io/OutputStream;Lcom/sun/midp/pki/CertStore;)V"] = function(caller, callee) {
|
2014-12-13 00:30:22 +03:00
|
|
|
var _this = callee.locals.read(6), port = callee.locals.read(4), host = util.fromJavaString(callee.locals.read(5));
|
2014-10-24 03:04:23 +04:00
|
|
|
_this.logBuffer = "SSLStreamConnection to " + host + ":" + port + ":\n";
|
|
|
|
};
|
|
|
|
|
|
|
|
Instrument.enter["com/sun/midp/ssl/Out.write.(I)V"] = function(caller, callee) {
|
2014-12-13 00:30:22 +03:00
|
|
|
var _this = callee.locals.read(3);
|
2014-11-27 05:40:02 +03:00
|
|
|
var connection = _this.klass.classInfo.getField("I.ssc.Lcom/sun/midp/ssl/SSLStreamConnection;").get(_this);
|
2014-10-24 03:04:23 +04:00
|
|
|
connection.logBuffer += String.fromCharCode(callee.stack.read(1));
|
|
|
|
};
|
|
|
|
|
|
|
|
Instrument.enter["com/sun/midp/ssl/Out.write.([BII)V"] = function(caller, callee) {
|
2014-12-13 00:30:22 +03:00
|
|
|
var len = callee.locals.read(1), off = callee.locals.read(2), b = callee.locals.read(3), _this = callee.locals.read(4);
|
2014-11-27 05:40:02 +03:00
|
|
|
var connection = _this.klass.classInfo.getField("I.ssc.Lcom/sun/midp/ssl/SSLStreamConnection;").get(_this);
|
2014-10-24 03:04:23 +04:00
|
|
|
var range = b.subarray(off, off + len);
|
|
|
|
for (var i = 0; i < range.length; i++) {
|
2014-12-05 22:29:10 +03:00
|
|
|
if (range[i] == 0) {
|
|
|
|
break;
|
|
|
|
}
|
2014-10-24 03:04:23 +04:00
|
|
|
connection.logBuffer += String.fromCharCode(range[i] & 0xff);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Instrument.exit["com/sun/midp/ssl/In.read.()I"] = function(caller, callee) {
|
|
|
|
// We can't use caller.stack.read() here, because the length of the caller's
|
|
|
|
// stack differs depending on whether or not In.read threw an exception.
|
|
|
|
var _this = caller.stack[2];
|
|
|
|
|
2014-11-27 05:40:02 +03:00
|
|
|
var connection = _this.klass.classInfo.getField("I.ssc.Lcom/sun/midp/ssl/SSLStreamConnection;").get(_this);
|
2014-10-24 03:04:23 +04:00
|
|
|
connection.logBuffer += String.fromCharCode(callee.stack.read(1));
|
|
|
|
};
|
|
|
|
|
|
|
|
Instrument.exit["com/sun/midp/ssl/In.read.([BII)I"] = function(caller, callee) {
|
2014-12-13 00:30:22 +03:00
|
|
|
var len = callee.locals.read(4), off = callee.locals.read(5), b = callee.locals.read(6), _this = callee.locals.read(7);
|
2014-11-27 05:40:02 +03:00
|
|
|
var connection = _this.klass.classInfo.getField("I.ssc.Lcom/sun/midp/ssl/SSLStreamConnection;").get(_this);
|
2014-10-24 03:04:23 +04:00
|
|
|
var range = b.subarray(off, off + len);
|
|
|
|
for (var i = 0; i < range.length; i++) {
|
2014-12-05 22:29:10 +03:00
|
|
|
if (range[i] == 0) {
|
|
|
|
break;
|
|
|
|
}
|
2014-10-24 03:04:23 +04:00
|
|
|
connection.logBuffer += String.fromCharCode(range[i] & 0xff);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Instrument.enter["com/sun/midp/ssl/SSLStreamConnection.close.()V"] = function(caller, callee) {
|
2014-12-13 00:30:22 +03:00
|
|
|
var _this = callee.locals.read(1);
|
2014-10-24 03:04:23 +04:00
|
|
|
if ("logBuffer" in _this) {
|
|
|
|
console.log(_this.logBuffer);
|
|
|
|
delete _this.logBuffer;
|
|
|
|
}
|
|
|
|
};
|