Merge commit '6a01c526c2e7f616407a7a7ee15ee348ad9fedec' into jitopt3

Conflicts:
	runtime.ts
This commit is contained in:
Michael Bebenita 2015-01-27 17:40:25 -08:00
Родитель 99d11b80fc 6a01c526c2
Коммит 3c2833b59a
7 изменённых файлов: 184 добавлений и 56 удалений

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

@ -3,6 +3,7 @@ BASIC_SRCS=$(shell find . -maxdepth 2 -name "*.ts" -not -path "./build/*")
JIT_SRCS=$(shell find jit -name "*.ts" -not -path "./build/*")
SHUMWAY_SRCS=$(shell find shumway -name "*.ts")
RELEASE ?= 0
VERSION ?=$(shell date +%s)
all: config-build java jasmin tests j2me shumway aot
@ -51,7 +52,9 @@ build/shumway.js: $(SHUMWAY_SRCS)
node tools/tsc.js --sourcemap --target ES5 shumway/references.ts --out build/shumway.js
config-build:
echo "config.release = ${RELEASE};" > config/build.js
echo "// generated, build-specific configuration" > config/build.js
echo "config.release = ${RELEASE};" >> config/build.js
echo "config.version = \"${VERSION}\";" >> config/build.js
tests/tests.jar: tests
tests:

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

@ -0,0 +1,93 @@
// IndexedDB-getAll-shim v1.1 - https://github.com/jdscheff/IndexedDB-getAll-shim
//
// Copyright (c) 2012 Jeremy Scheff
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(function () {
"use strict";
var Event, IDBIndex, IDBObjectStore, IDBRequest, getAll;
IDBObjectStore = window.IDBObjectStore || window.webkitIDBObjectStore || window.mozIDBObjectStore || window.msIDBObjectStore;
IDBIndex = window.IDBIndex || window.webkitIDBIndex || window.mozIDBIndex || window.msIDBIndex;
if (typeof IDBObjectStore === "undefined" || typeof IDBIndex === "undefined" || (IDBObjectStore.prototype.getAll !== undefined && IDBIndex.prototype.getAll !== undefined)) {
return;
}
if (IDBObjectStore.prototype.mozGetAll !== undefined && IDBIndex.prototype.mozGetAll !== undefined) {
IDBObjectStore.prototype.getAll = IDBObjectStore.prototype.mozGetAll;
IDBIndex.prototype.getAll = IDBIndex.prototype.mozGetAll;
return;
}
// https://github.com/axemclion/IndexedDBShim/blob/gh-pages/src/IDBRequest.js
IDBRequest = function () {
this.onsuccess = null;
this.readyState = "pending";
};
// https://github.com/axemclion/IndexedDBShim/blob/gh-pages/src/Event.js
Event = function (type, debug) {
return {
"type": type,
debug: debug,
bubbles: false,
cancelable: false,
eventPhase: 0,
timeStamp: new Date()
};
};
getAll = function (key) {
var request, result;
key = key !== undefined ? key : null;
request = new IDBRequest();
result = [];
// this is either an IDBObjectStore or an IDBIndex, depending on the context.
this.openCursor(key).onsuccess = function (event) {
var cursor, e;
cursor = event.target.result;
if (cursor) {
result.push(cursor.value);
cursor.continue();
} else {
if (typeof request.onsuccess === "function") {
e = new Event("success");
e.target = {
readyState: "done",
result: result
};
request.result = result;
request.onsuccess(e);
}
}
};
return request;
};
IDBObjectStore.prototype.getAll = getAll;
IDBIndex.prototype.getAll = getAll;
}());

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

@ -4,7 +4,7 @@
'use strict';
var CompiledMethodCache = (function() {
var DEBUG = true;
var DEBUG = false;
var DATABASE = "CompiledMethodCache";
var VERSION = 1;
var OBJECT_STORE = "methods";
@ -25,13 +25,13 @@ var CompiledMethodCache = (function() {
};
function restore() {
return new Promise(function(resolve, reject) {
return openDatabase.then(new Promise(function(resolve, reject) {
DEBUG && debug("restore");
var then = performance.now();
var transaction = database.transaction(OBJECT_STORE, "readonly");
var objectStore = transaction.objectStore(OBJECT_STORE);
var request = objectStore.mozGetAll();
var request = objectStore.getAll();
request.onerror = function() {
console.error("Error restoring: " + request.error.name);
@ -39,15 +39,39 @@ var CompiledMethodCache = (function() {
};
request.onsuccess = function() {
for (var i = 0; i < request.result.length; i++) {
var count = request.result.length;
for (var i = 0; i < count; i++) {
cache.set(request.result[i][KEY_PATH], request.result[i]);
}
DEBUG && debug("restore complete: " + count + " methods in " + (performance.now() - then) + "ms");
resolve();
};
}));
}
function clear() {
return openDatabase.then(new Promise(function(resolve, reject) {
DEBUG && debug("clear");
// First clear the in-memory cache, in case we've already restored it
// from the database.
cache.clear();
var then = performance.now();
var transaction = database.transaction(OBJECT_STORE, "readwrite");
var objectStore = transaction.objectStore(OBJECT_STORE);
var request = objectStore.clear();
request.onerror = function() {
console.error("Error clearing: " + request.error.name);
reject(request.error.name);
};
transaction.oncomplete = function() {
DEBUG && debug("restore complete");
request.onsuccess = function() {
DEBUG && debug("clear complete in " + (performance.now() - then) + "ms");
resolve();
};
});
}));
}
var openDatabase = new Promise(function(resolve, reject) {
@ -77,8 +101,19 @@ var CompiledMethodCache = (function() {
request.onsuccess = function() {
DEBUG && debug("open success");
database = request.result;
restore();
var oldVersion = localStorage.getItem("lastAppVersion");
if (config.version === oldVersion) {
DEBUG && debug("app version " + config.version + " === " + oldVersion + "; restore");
restore().catch(console.error.bind(console));
} else {
DEBUG && debug("app version " + config.version + " !== " + oldVersion + "; clear");
clear().catch(console.error.bind(console));
localStorage.setItem("lastAppVersion", config.version);
}
resolve();
};
});
@ -104,38 +139,9 @@ var CompiledMethodCache = (function() {
};
request.onsuccess = function() {
resolve();
};
transaction.oncomplete = function() {
DEBUG && debug("put " + obj[KEY_PATH] + " complete");
};
}));
}
function clear() {
DEBUG && debug("clear");
cache.clear();
return openDatabase.then(new Promise(function(resolve, reject) {
var transaction = database.transaction(OBJECT_STORE, "readwrite");
var objectStore = transaction.objectStore(OBJECT_STORE);
var request = objectStore.clear();
request.onerror = function() {
console.error("Error clearing store: " + request.error.name);
reject(request.error.name);
};
request.onsuccess = function() {
resolve();
};
transaction.oncomplete = function() {
DEBUG && debug("clear complete");
};
}));
}

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

@ -30,6 +30,7 @@
<script type="text/javascript" src="native.js" defer></script>
<script type="text/javascript" src="string.js" defer></script>
<script type="text/javascript" src="instrument.js" defer></script>
<script type="text/javascript" src="libs/IndexedDB-getAll-shim.js" defer></script>
<script type="text/javascript" src="libs/compiled-method-cache.js" defer></script>
<script type="text/javascript" src="libs/load.js" defer></script>
<script type="text/javascript" src="libs/zipfile.js" defer></script>
@ -117,12 +118,12 @@
</section>
<section>
<button id="deleteDatabase">Delete Database</button>
<button id="clearMethodCache">Clear Code Cache</button>
<button id="exportstorage">Export storage</button>
<div>Import storage:</div>
<input type="file" id="importstoragefile">
<input type="text" id="importstorageurl" placeholder="URL to FS backup">
<button id="importstorage">Import</button>
<button id="clearCompiledMethodCache">Clear Compiled Method Cache</button>
<button id="trace">Trace: OFF</button>
<button id="printAllExceptions">Print all exceptions: OFF</button>
<button id="profile">Profile: OFF</button>

11
main.js
Просмотреть файл

@ -175,6 +175,11 @@ function toggle(button) {
var bigBang = 0;
function start() {
if (MIDP.manifest["MIDlet-Version"] && MIDP.manifest["MIDlet-Version"] !== localStorage.getItem("lastMidletVersion")) {
CompiledMethodCache.clear().catch(console.error.bind(console));
localStorage.setItem("lastMidletVersion", MIDP.manifest["MIDlet-Version"]);
}
J2ME.Context.setWriters(new J2ME.IndentingWriter());
CLASSES.initializeBuiltinClasses();
profiler && profiler.start(2000, false);
@ -205,9 +210,6 @@ window.onload = function() {
document.getElementById("deleteDatabase").onclick = function() {
indexedDB.deleteDatabase("asyncStorage");
};
document.getElementById("clearMethodCache").onclick = function() {
CompiledMethodCache.clear();
};
document.getElementById("exportstorage").onclick = function() {
fs.exportStore(function(blob) {
saveAs(blob, "fs-" + Date.now() + ".json");
@ -229,6 +231,9 @@ window.onload = function() {
});
}
};
document.getElementById("clearCompiledMethodCache").onclick = function() {
CompiledMethodCache.clear().then(function() { console.log("cleared compiled method cache") });
};
document.getElementById("trace").onclick = function() {
VM.DEBUG = !VM.DEBUG;
toggle(this);

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

@ -34,6 +34,11 @@ module J2ME {
*/
export var enableOnStackReplacement = true;
/**
* Turns on caching of JIT-compiled methods.
*/
export var enableCompiledMethodCache = true;
/**
* Enables more compact mangled names. This helps reduce code size but may cause naming collisions.
*/
@ -1072,6 +1077,10 @@ module J2ME {
* callers should be calling that instead of this.
*/
export function linkKlass(classInfo: ClassInfo) {
// We shouldn't do any linking if we're not in the runtime phase.
if (phase !== ExecutionPhase.Runtime) {
return;
}
if (classInfo.klass) {
return;
}
@ -1226,6 +1235,14 @@ module J2ME {
}
function findCompiledMethod(klass: Klass, methodInfo: MethodInfo): Function {
if (enableCompiledMethodCache) {
var cachedMethod;
if (!jsGlobal[methodInfo.mangledClassAndMethodName] && (cachedMethod = CompiledMethodCache.get(methodInfo.implKey))) {
cachedMethodCount ++;
linkMethod(methodInfo, cachedMethod.source, cachedMethod.referencedClasses);
}
}
return jsGlobal[methodInfo.mangledClassAndMethodName];
}
@ -1452,12 +1469,13 @@ module J2ME {
return;
}
var compiledMethod;
if (compiledMethod = CompiledMethodCache.get(methodInfo.implKey)) {
cachedMethodCount ++;
jitWriter && jitWriter.writeLn("Getting " + methodInfo.implKey + " from compiled method cache");
return linkMethod(methodInfo, compiledMethod.source, compiledMethod.referencedClasses);
if (enableCompiledMethodCache) {
var cachedMethod;
if (cachedMethod = CompiledMethodCache.get(methodInfo.implKey)) {
cachedMethodCount ++;
jitWriter && jitWriter.writeLn("Getting " + methodInfo.implKey + " from compiled method cache");
return linkMethod(methodInfo, cachedMethod.source, cachedMethod.referencedClasses);
}
}
var mangledClassAndMethodName = methodInfo.mangledClassAndMethodName;
@ -1465,10 +1483,11 @@ module J2ME {
jitWriter && jitWriter.enter("Compiling: " + methodInfo.implKey + ", currentBytecodeCount: " + methodInfo.bytecodeCount);
var s = performance.now();
compiledMethodCount ++;
var compiledMethod;
enterTimeline("Compiling");
try {
compiledMethod = baselineCompileMethod(methodInfo, CompilationTarget.Runtime);
compiledMethod = baselineCompileMethod(methodInfo, CompilationTarget[enableCompiledMethodCache ? "Static" : "Runtime"]);
compiledMethodCount ++;
} catch (e) {
methodInfo.state = MethodState.CannotCompile;
jitWriter && jitWriter.writeLn("Cannot compile: " + methodInfo.implKey + " because of " + e);
@ -1484,14 +1503,12 @@ module J2ME {
var referencedClasses = compiledMethod.referencedClasses.map(function(v) { return v.className });
try {
if (enableCompiledMethodCache) {
CompiledMethodCache.put({
key: methodInfo.implKey,
source: source,
referencedClasses: referencedClasses,
});
} catch(e) {
jitWriter && jitWriter.writeLn("Cannot cache: " + methodInfo.implKey + " because of " + e);
}).catch(stderrWriter.errorLn.bind(stderrWriter));
}
linkMethod(methodInfo, source, referencedClasses);
@ -1511,6 +1528,8 @@ module J2ME {
* Links up compiled method at runtime.
*/
export function linkMethod(methodInfo: MethodInfo, source: string, referencedClasses: string[]) {
jitWriter && jitWriter.writeLn("Link method: " + methodInfo.implKey);
enterTimeline("Eval Compiled Code");
// This overwrites the method on the global object.
(1, eval)(source);

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

@ -150,8 +150,9 @@ casper.test.begin("unit tests", 16 + gfxTests.length, function(test) {
.thenOpen("http://localhost:8000/index.html?logConsole=web,page")
.withFrame(0, basicUnitTests);
// Run the same unit tests again to test the compiled method cache.
casper
.thenOpen("http://localhost:8000/index.html?numCalled=1000&logConsole=web,page")
.thenOpen("http://localhost:8000/index.html?logConsole=web,page")
.withFrame(0, basicUnitTests);
casper