diff --git a/.gitignore b/.gitignore index fb1d8817..39994380 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ main.html config/build.js manifest.webapp index.js +style/main.css # These are generated by the Java pre-processor. They're generated from # their *.jpp equivalents. Keep them up-to-date when you add *.jpp files! diff --git a/Makefile b/Makefile index 2758c92c..74c6fa7e 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ RELEASE ?= 0 VERSION ?=$(shell date +%s) PROFILE ?= 0 BENCHMARK ?= 0 +CONSOLE ?= 1 VERBOSE ?= 0 # Sensor support @@ -37,7 +38,6 @@ ifeq ($(VERBOSE),1) endif MAIN_JS_SRCS = \ - libs/console.js \ polyfill/canvas-toblob.js \ polyfill/fromcodepoint.js \ polyfill/codepointat.js \ @@ -97,6 +97,10 @@ ifeq ($(BENCHMARK),1) MAIN_JS_SRCS += benchmark.js libs/ttest.js endif +ifeq ($(CONSOLE),1) + MAIN_JS_SRCS += libs/console.js +endif + # Add main.js last, as it depends on some of the other scripts. MAIN_JS_SRCS += main.js @@ -104,7 +108,7 @@ MAIN_JS_SRCS += main.js # If the configuration has changed, we update the checksum file to let the files # which depend on it to regenerate. -CHECKSUM := "$(RELEASE)$(PROFILE)$(BENCHMARK)$(JSR_256)$(JSR_082)$(JSR_179)" +CHECKSUM := "$(RELEASE)$(PROFILE)$(BENCHMARK)$(CONSOLE)$(JSR_256)$(JSR_082)$(JSR_179)" OLD_CHECKSUM := "$(shell [ -f .checksum ] && cat .checksum)" $(shell [ $(CHECKSUM) != $(OLD_CHECKSUM) ] && echo $(CHECKSUM) > .checksum) @@ -113,6 +117,7 @@ PREPROCESS = python tools/preprocess-1.1.0/lib/preprocess.py -s \ -D RELEASE=$(call toBool,$(RELEASE)) \ -D PROFILE=$(PROFILE) \ -D BENCHMARK=$(call toBool,$(BENCHMARK)) \ + -D CONSOLE=$(call toBool,$(CONSOLE)) \ -D JSR_256=$(JSR_256) \ -D JSR_179=$(JSR_179) \ -D VERSION=$(VERSION) diff --git a/bench/ImageProcessingBench.java b/bench/ImageProcessingBench.java new file mode 100644 index 00000000..054eb4a1 --- /dev/null +++ b/bench/ImageProcessingBench.java @@ -0,0 +1,102 @@ +package benchmark; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import javax.microedition.io.Connector; +import javax.microedition.io.file.FileConnection; +import com.nokia.mid.s40.io.LocalMessageProtocolMessage; +import com.nokia.mid.s40.io.LocalMessageProtocolConnection; +import com.nokia.mid.s40.codec.DataEncoder; +import com.nokia.mid.s40.codec.DataDecoder; +import gnu.testlet.TestUtils; +import org.mozilla.MemorySampler; +import com.sun.cldchi.jvm.JVM; + +public class ImageProcessingBench { + LocalMessageProtocolConnection client; + + String scaleImage() throws IOException { + DataEncoder dataEncoder = new DataEncoder("Conv-BEB"); + dataEncoder.putStart(14, "event"); + dataEncoder.put(13, "name", "Scale"); + dataEncoder.put(2, "trans_id", 42); + dataEncoder.put(11, "filename", "test.jpg"); + dataEncoder.putStart(15, "limits"); + dataEncoder.put(5, "max_hres", 100); + dataEncoder.put(5, "max_vres", 100); + dataEncoder.putEnd(15, "limits"); + dataEncoder.put(10, "aspect", "FullImage"); + dataEncoder.put(2, "quality", 80); + dataEncoder.putEnd(14, "event"); + byte[] sendData = dataEncoder.getData(); + client.send(sendData, 0, sendData.length); + + LocalMessageProtocolMessage msg = client.newMessage(null); + client.receive(msg); + byte[] clientData = msg.getData(); + + DataDecoder dataDecoder = new DataDecoder("Conv-BEB", clientData, 0, clientData.length); + dataDecoder.getStart(14); + dataDecoder.getString(13); + dataDecoder.getInteger(2); + dataDecoder.getString(10); + return "file:////" + dataDecoder.getString(11); + } + + void runBenchmark() { + try { + long start, time = 0; + + client = (LocalMessageProtocolConnection)Connector.open("localmsg://nokia.image-processing"); + + DataEncoder dataEncoder = new DataEncoder("Conv-BEB"); + dataEncoder.putStart(14, "event"); + dataEncoder.put(13, "name", "Common"); + dataEncoder.putStart(14, "message"); + dataEncoder.put(13, "name", "ProtocolVersion"); + dataEncoder.put(10, "version", "1.[0-10]"); + dataEncoder.putEnd(14, "message"); + dataEncoder.putEnd(14, "event"); + byte[] sendData = dataEncoder.getData(); + client.send(sendData, 0, sendData.length); + + LocalMessageProtocolMessage msg = client.newMessage(null); + client.receive(msg); + + FileConnection originalImage = (FileConnection)Connector.open("file:////test.jpg", Connector.READ_WRITE); + if (!originalImage.exists()) { + originalImage.create(); + } + OutputStream os = originalImage.openDataOutputStream(); + InputStream is = getClass().getResourceAsStream("/org/mozilla/io/test.jpg"); + os.write(TestUtils.read(is)); + os.close(); + + MemorySampler.sampleMemory("Memory before nokia.image-processing benchmark"); + for (int i = 0; i < 1000; i++) { + start = JVM.monotonicTimeMillis(); + String path = scaleImage(); + time += JVM.monotonicTimeMillis() - start; + + FileConnection file = (FileConnection)Connector.open(path); + file.delete(); + file.close(); + } + System.out.println("scaleImage: " + time); + MemorySampler.sampleMemory("Memory after nokia.image-processing benchmark"); + + originalImage.delete(); + originalImage.close(); + + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void main(String args[]) { + ImageProcessingBench bench = new ImageProcessingBench(); + bench.runBenchmark(); + } +} diff --git a/bench/SystemOutBench.java b/bench/SystemOutBench.java index 7abbd605..0a5a74f0 100644 --- a/bench/SystemOutBench.java +++ b/bench/SystemOutBench.java @@ -18,6 +18,7 @@ public class SystemOutBench { for (int j = 0; j < 100; j++) { System.out.print(j % 10); } + System.out.println(); } time = JVM.monotonicTimeMillis() - start; System.out.println(); diff --git a/config/urlparams.js b/config/urlparams.js index a6a29973..b6dbe962 100644 --- a/config/urlparams.js +++ b/config/urlparams.js @@ -23,6 +23,7 @@ * autosize * fontSize * language + * forceRuntimeCompilation * * Keep this list up-to-date! */ diff --git a/interpreter.ts b/interpreter.ts index 4ff107fb..488a3229 100644 --- a/interpreter.ts +++ b/interpreter.ts @@ -1,5 +1,5 @@ module J2ME { - declare var util; + declare var util, config; declare var Promise; import BytecodeStream = Bytecode.BytecodeStream; @@ -243,9 +243,10 @@ module J2ME { // for synthetic method frames which have bad max_local counts. // Inline heuristics that trigger JIT compilation here. - if (enableRuntimeCompilation && - mi.state < MethodState.Compiled && // Give up if we're at this state. - mi.stats.backwardsBranchCount + mi.stats.interpreterCallCount > 10) { + if ((enableRuntimeCompilation && + mi.state < MethodState.Compiled && // Give up if we're at this state. + mi.stats.backwardsBranchCount + mi.stats.interpreterCallCount > 10) || + config.forceRuntimeCompilation) { compileAndLinkMethod(mi); } diff --git a/java/Makefile b/java/Makefile index 514b1372..ef3f79de 100644 --- a/java/Makefile +++ b/java/Makefile @@ -26,8 +26,10 @@ classes.jar: $(SRCS) $(JPP_DESTS) $(EXTRA) $(foreach dir,$(SRC_DIRS),cp -a $(dir)/. build-src/;) find ./build-src -name *.java > build-srcs.txt javac -cp build-src -g:none -source 1.3 -target 1.3 -bootclasspath "" -extdirs "" -d ./build @build-srcs.txt > /dev/null - java -jar ../build_tools/soot-trunk.jar -j2me -process-dir build -no-output-source-file-attribute -no-output-inner-classes-attribute -force-overwrite -include-all 2>&1 > /dev/null - cp -a sootOutput/. build/ + # TODO: Re-enable Soot optimizations once tests with baseline JIT enabled + # for all methods pass. + #java -jar ../build_tools/soot-trunk.jar -j2me -process-dir build -no-output-source-file-attribute -no-output-inner-classes-attribute -force-overwrite -include-all 2>&1 > /dev/null + #cp -a sootOutput/. build/ cd build && jar cf0 ../classes.jar * jar uf0 classes.jar $(EXTRA) diff --git a/jit/analyze.ts b/jit/analyze.ts index ee149ea8..5a5f801f 100644 --- a/jit/analyze.ts +++ b/jit/analyze.ts @@ -36,7 +36,6 @@ module J2ME { "com/sun/javame/sensor/NativeChannel.doMeasureData.(II)[B": YieldReason.Root, "com/sun/midp/links/LinkPortal.getLinkCount0.()I": YieldReason.Root, "com/sun/midp/links/Link.receive0.(Lcom/sun/midp/links/LinkMessage;Lcom/sun/midp/links/Link;)V": YieldReason.Root, - "com/nokia/mid/impl/jms/core/Launcher.handleContent.(Ljava/lang/String;)V": YieldReason.Root, "com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V": YieldReason.Root, "com/sun/midp/events/NativeEventMonitor.waitForNativeEvent.(Lcom/sun/midp/events/NativeEvent;)I": YieldReason.Root, "com/sun/midp/io/j2me/push/ConnectionRegistry.poll0.(J)I": YieldReason.Root, diff --git a/jsshell.js b/jsshell.js index 310756ee..a768230b 100755 --- a/jsshell.js +++ b/jsshell.js @@ -12,10 +12,6 @@ if (typeof console === "undefined") { } } -console.print = function (c) { - putstr(String.fromCharCode(c)); -}; - console.info = function (c) { putstr(String.fromCharCode(c)); }; @@ -125,6 +121,11 @@ try { // load("bld/program.jar.js"); // load("bld/tests.jar.js"); + // Define this down here so it overrides the version defined by native.js. + console.print = function (c) { + putstr(String.fromCharCode(c)); + }; + var dump = putstr; CLASSES.addSourceDirectory("java/cldc1.1.1"); diff --git a/libs/console.js b/libs/console.js index 6ee10597..7028e6a2 100644 --- a/libs/console.js +++ b/libs/console.js @@ -166,33 +166,18 @@ * WebConsole: The standard console.log() and friends. */ function WebConsole() { - this.buffer = ""; } WebConsole.prototype = { - flush: function() { - if (this.buffer.length) { - var temp = this.buffer; - this.buffer = ""; - console.info(temp); - } - }, - push: function(item) { if (item.matchesCurrentFilters()) { - this.flush(); // Preserve order w/r/t console.print(). + if (consoleBuffer.length) { + // Preserve order w/r/t console.print(). + flushConsoleBuffer(); + } windowConsole[item.levelName].apply(windowConsole, [item.message]); } }, - - /** Print one character to the output (buffered). */ - print: function(ch) { - if (ch === 10) { - this.flush(); - } else { - this.buffer += String.fromCharCode(ch); - } - } }; /** @@ -299,12 +284,9 @@ terminal: typeof Terminal === "undefined" ? new WebConsole() : new TerminalConsole("#consoleContainer") }; - var print = CONSOLES.web.print.bind(CONSOLES.web); - // If we're only printing to the web console, then use the original console // object, so that file/line number references show up correctly in it. if (ENABLED_CONSOLE_TYPES.length === 1 && ENABLED_CONSOLE_TYPES[0] === "web") { - windowConsole.print = print; return; } @@ -345,15 +327,12 @@ }); }; - window.console = { - trace: logAtLevel.bind(null, "trace"), - log: logAtLevel.bind(null, "log"), - info: logAtLevel.bind(null, "info"), - warn: logAtLevel.bind(null, "warn"), - error: logAtLevel.bind(null, "error"), - print: print, - profile: typeof console !== "undefined" && console.profile ? console.profile.bind(console) : null, - profileEnd: typeof console !== "undefined" && console.profileEnd ? console.profileEnd.bind(console) : null, - }; + window.console = Object.create(windowConsole, { + trace: { value: logAtLevel.bind(null, "trace") }, + log: { value: logAtLevel.bind(null, "log") }, + info: { value: logAtLevel.bind(null, "info") }, + warn: { value: logAtLevel.bind(null, "warn") }, + error: { value: logAtLevel.bind(null, "error") }, + }); })(); diff --git a/libs/fs.js b/libs/fs.js index 98800e32..7d3eb648 100644 --- a/libs/fs.js +++ b/libs/fs.js @@ -434,6 +434,11 @@ var fs = (function() { var openedFiles = new Map(); var lastId = 2; + function getBlob(path) { + var record = store.getItem(normalizePath(path)); + return record ? record.data : null; + } + function open(path, cb) { path = normalizePath(path); if (DEBUG_FS) { console.log("fs open " + path); } @@ -919,5 +924,6 @@ var fs = (function() { exportStore: exportStore, importStore: importStore, createUniqueFile: createUniqueFile, + getBlob: getBlob, }; })(); diff --git a/main.html.in b/main.html.in index 979f0d3d..9a865b2a 100644 --- a/main.html.in +++ b/main.html.in @@ -56,8 +56,9 @@
-