From 0ea95efb98e26a9dc271a1f55c024f8877e9f28a Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Feb 2015 12:10:39 +0100 Subject: [PATCH 01/12] Fix InterIsolateMutex bug --- midp/midp.js | 1 + 1 file changed, 1 insertion(+) diff --git a/midp/midp.js b/midp/midp.js index 9a631878..44e91f10 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -890,6 +890,7 @@ Native["com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V"] = function(id) } mutex.waiting.push(function() { + ctx.setAsCurrentContext(); mutex.locked = true; mutex.holder = ctx.runtime.isolate.id; resolve(); From 0ea3f7d0ed1fe48b02e3b5f818937d4d5d16c648 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Feb 2015 12:10:57 +0100 Subject: [PATCH 02/12] Make RecordStore natives sync again --- jit/analyze.ts | 3 --- midp/fs.js | 17 ++++------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/jit/analyze.ts b/jit/analyze.ts index 952e1d23..a69213bb 100644 --- a/jit/analyze.ts +++ b/jit/analyze.ts @@ -32,10 +32,7 @@ module J2ME { "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, - "com/sun/midp/rms/RecordStoreUtil.exists.(Ljava/lang/String;Ljava/lang/String;I)Z": YieldReason.Root, "com/sun/midp/rms/RecordStoreFile.openRecordStoreFile.(Ljava/lang/String;Ljava/lang/String;I)I": YieldReason.Root, - "com/sun/midp/rms/RecordStoreFile.commitWrite.(I)V": YieldReason.Root, - "com/sun/midp/rms/RecordStoreFile.closeFile.(I)V": YieldReason.Root, "com/ibm/oti/connection/file/Connection.truncateImpl.([BJ)V": YieldReason.Root, "com/ibm/oti/connection/file/FCInputStream.openImpl.([B)I": YieldReason.Root, "com/ibm/oti/connection/file/FCOutputStream.openImpl.([B)I": YieldReason.Root, diff --git a/midp/fs.js b/midp/fs.js index 8845ccee..3a8f53a0 100644 --- a/midp/fs.js +++ b/midp/fs.js @@ -38,11 +38,8 @@ Native["com/sun/midp/midletsuite/MIDletSuiteStorage.getSecureFilenameBase.(I)Lja Native["com/sun/midp/rms/RecordStoreUtil.exists.(Ljava/lang/String;Ljava/lang/String;I)Z"] = function(filenameBase, name, ext) { - asyncImpl("Z", new Promise(function(resolve, reject) { - var path = RECORD_STORE_BASE + "/" + util.fromJavaString(filenameBase) + "/" + util.fromJavaString(name) + "." + ext; - // return fs.exists(path) ? 1 : 0; - resolve(fs.exists(path) ? 1 : 0); - })); + var path = RECORD_STORE_BASE + "/" + util.fromJavaString(filenameBase) + "/" + util.fromJavaString(name) + "." + ext; + return fs.exists(path) ? 1 : 0; }; Native["com/sun/midp/rms/RecordStoreUtil.deleteFile.(Ljava/lang/String;Ljava/lang/String;I)V"] = @@ -134,17 +131,11 @@ Native["com/sun/midp/rms/RecordStoreFile.writeBytes.(I[BII)V"] = function(handle }; Native["com/sun/midp/rms/RecordStoreFile.commitWrite.(I)V"] = function(handle) { - asyncImpl("V", new Promise(function(resolve, reject) { - fs.flush(handle); - resolve(); - })); + fs.flush(handle); }; Native["com/sun/midp/rms/RecordStoreFile.closeFile.(I)V"] = function(handle) { - asyncImpl("V", new Promise(function(resolve, reject) { - fs.close(handle); - resolve(); - })); + fs.close(handle); }; Native["com/sun/midp/rms/RecordStoreFile.truncateFile.(II)V"] = function(handle, size) { From 5a50eae4fa3c843d959bbf96b736f0e7abc99621 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Feb 2015 23:35:11 +0100 Subject: [PATCH 03/12] Fix issues with the context in InterIsolateMutex::lock0 --- midp/midp.js | 61 ++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/midp/midp.js b/midp/midp.js index 9a14666e..51b841fb 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -861,41 +861,36 @@ Native["com/sun/midp/util/isolate/InterIsolateMutex.getID0.(Ljava/lang/String;)I }; Native["com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V"] = function(id) { + var mutex; + for (var i = 0; i < MIDP.InterIsolateMutexes.length; i++) { + if (MIDP.InterIsolateMutexes[i].id == id) { + mutex = MIDP.InterIsolateMutexes[i]; + break; + } + } + + if (!mutex) { + throw $.newIllegalStateException("Invalid mutex ID"); + } + + if (!mutex.locked) { + mutex.locked = true; + mutex.holder = $.ctx.runtime.isolate.id; + return; + } + + if (mutex.holder == $.ctx.runtime.isolate.id) { + throw $.newRuntimeException("Attempting to lock mutex twice within the same Isolate"); + } + var ctx = $.ctx; - asyncImpl("V", new Promise(function(resolve, reject) { - ctx.setAsCurrentContext(); - var mutex; - for (var i = 0; i < MIDP.InterIsolateMutexes.length; i++) { - if (MIDP.InterIsolateMutexes[i].id == id) { - mutex = MIDP.InterIsolateMutexes[i]; - break; - } - } + mutex.waiting.push(function() { + mutex.locked = true; + mutex.holder = ctx.runtime.isolate.id; + Runtime.scheduleRunningContext(ctx); + }); - if (!mutex) { - reject($.newIllegalStateException("Invalid mutex ID")); - return; - } - - if (!mutex.locked) { - mutex.locked = true; - mutex.holder = ctx.runtime.isolate.id; - resolve(); - return; - } - - if (mutex.holder == ctx.runtime.isolate.id) { - reject($.newRuntimeException("Attempting to lock mutex twice within the same Isolate")); - return; - } - - mutex.waiting.push(function() { - ctx.setAsCurrentContext(); - mutex.locked = true; - mutex.holder = ctx.runtime.isolate.id; - resolve(); - }); - })); + $.pause("Async"); }; Native["com/sun/midp/util/isolate/InterIsolateMutex.unlock0.(I)V"] = function(id) { From 22ffe74498ddaac87458d03267143ef1e59915e9 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Feb 2015 23:35:30 +0100 Subject: [PATCH 04/12] Add some more complex scenarios to TestInterIsolateMutex --- .../util/isolate/TestInterIsolateMutex.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java b/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java index 579520fd..98a7fee9 100644 --- a/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java +++ b/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java @@ -46,6 +46,21 @@ class LockerIsolate2 { Thread.sleep(1000); } catch (Exception e) {} m.unlock(); + System.out.println("UNLOCKED"); + } +} + +class LockerThread extends Thread { + public void run() { + SecurityToken t = SecurityTokenProvider.getToken(); + InterIsolateMutex m = InterIsolateMutex.getInstance(t, "mutex"); + + m.lock(); + try { + // Give the test some time to test waiting for the lock + Thread.sleep(1000); + } catch (Exception e) {} + m.unlock(); } } @@ -128,5 +143,59 @@ public class TestInterIsolateMutex implements Testlet { } catch (Exception e) { th.fail("Unexpected exception: " + e); } + + m.unlock(); + + try { + Isolate iso1 = new Isolate("com.sun.midp.util.isolate.LockerIsolate1", new String[] {}); + Isolate iso2 = new Isolate("com.sun.midp.util.isolate.LockerIsolate2", new String[] {}); + + iso2.start(); + iso1.start(); + + m.lock(); + m.unlock(); + + iso2.waitForExit(); + iso1.waitForExit(); + } catch (Exception e) { + th.fail("Unexpected exception: " + e); + } + + try { + Isolate iso = new Isolate("com.sun.midp.util.isolate.LockerIsolate2", new String[] {}); + LockerThread lockerThread = new LockerThread(); + + lockerThread.start(); + + try { + Thread.yield(); + } catch (Exception e) {} + + iso.start(); + + iso.waitForExit(); + lockerThread.join(); + } catch (Exception e) { + th.fail("Unexpected exception: " + e); + } + + try { + Isolate iso = new Isolate("com.sun.midp.util.isolate.LockerIsolate2", new String[] {}); + LockerThread lockerThread = new LockerThread(); + + iso.start(); + + try { + Thread.yield(); + } catch (Exception e) {} + + lockerThread.start(); + + iso.waitForExit(); + lockerThread.join(); + } catch (Exception e) { + th.fail("Unexpected exception: " + e); + } } } From 36fe0aceac53d89d081ff7d9727dafdfdc2586b1 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Feb 2015 23:51:03 +0100 Subject: [PATCH 05/12] Remove debug logging from TestInterIsolateMutex --- tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java b/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java index 98a7fee9..5d127c2b 100644 --- a/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java +++ b/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java @@ -46,7 +46,6 @@ class LockerIsolate2 { Thread.sleep(1000); } catch (Exception e) {} m.unlock(); - System.out.println("UNLOCKED"); } } From bc24769138f34519d663bcbb8a4dcadb812269c1 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 3 Feb 2015 00:18:51 +0100 Subject: [PATCH 06/12] Add comment explaining why we can't use asyncImpl in InterIsolateMutex --- midp/midp.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/midp/midp.js b/midp/midp.js index 51b841fb..1a4afa11 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -885,6 +885,10 @@ Native["com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V"] = function(id) var ctx = $.ctx; mutex.waiting.push(function() { + // We can't use asyncImpl in this native because we can't simply execute + // the context that called lock0 without pausing the context that called unlock0. + // So, we're scheduling the context that called lock0. + mutex.locked = true; mutex.holder = ctx.runtime.isolate.id; Runtime.scheduleRunningContext(ctx); From 528d25999765425c044f2791ad8b8586b252b705 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 3 Feb 2015 01:56:53 +0100 Subject: [PATCH 07/12] Use Int8Array instead of Uint8Array throughout the codebase --- midp/codec.js | 2 +- midp/crypto.js | 4 ++-- midp/localmsg.js | 26 +++++++++++++------------- midp/media.js | 8 ++++---- midp/midp.js | 4 ++-- midp/socket.js | 8 ++++---- native.js | 4 ++-- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/midp/codec.js b/midp/codec.js index 4228e51b..735ff70e 100644 --- a/midp/codec.js +++ b/midp/codec.js @@ -66,7 +66,7 @@ DataEncoder.prototype.getData = function() { } var DataDecoder = function(data, offset, length) { - this.data = JSON.parse(util.decodeUtf8(new Uint8Array(data.buffer, offset, length))); + this.data = JSON.parse(util.decodeUtf8(new Int8Array(data.buffer, offset, length))); this.current = []; } diff --git a/midp/crypto.js b/midp/crypto.js index 11f8e0cc..95916e18 100644 --- a/midp/crypto.js +++ b/midp/crypto.js @@ -99,7 +99,7 @@ Native["com/sun/midp/crypto/SHA.nativeFinal.([BII[BI[I[I[I[I)V"] = function(inBu } var hash = hasher.digest(); - outBuf.set(new Uint8Array(hash.buffer), outOff); + outBuf.set(new Int8Array(hash.buffer), outOff); // XXX Call the reset method instead to completely reset the object. data.set(MIDP.emptyDataArray); @@ -120,7 +120,7 @@ Native["com/sun/midp/crypto/SHA.nativeClone.([I)V"] = function(data) { }; Native["com/sun/midp/crypto/MD5.nativeUpdate.([BII[I[I[I[I)V"] = function(inBuf, inOff, inLen, state, num, count, data) { - MIDP.getMD5Hasher(data).update(MIDP.bin2String(new Uint8Array(inBuf.subarray(inOff, inOff + inLen)))); + MIDP.getMD5Hasher(data).update(MIDP.bin2String(new Int8Array(inBuf.subarray(inOff, inOff + inLen)))); }; Native["com/sun/midp/crypto/MD5.nativeFinal.([BII[BI[I[I[I[I)V"] = function(inBuf, inOff, inLen, outBuf, outOff, state, num, count, data) { diff --git a/midp/localmsg.js b/midp/localmsg.js index 0733a11c..37aba1ea 100644 --- a/midp/localmsg.js +++ b/midp/localmsg.js @@ -174,7 +174,7 @@ NokiaMessagingLocalMsgConnection.prototype.sendMessageToServer = function(messag default: console.error("(nokia.messaging) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } @@ -381,7 +381,7 @@ NokiaPhoneStatusLocalMsgConnection.prototype.sendMessageToServer = function(mess default: console.error("(nokia.phone-status) Query " + decoder.getName() + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); break; } } else if (queryKind === "Disable") { @@ -407,7 +407,7 @@ NokiaPhoneStatusLocalMsgConnection.prototype.sendMessageToServer = function(mess default: console.error("(nokia.phone-status) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -526,7 +526,7 @@ NokiaContactsLocalMsgConnection.prototype.sendMessageToServer = function(message var numEntries = decoder.getValue(DataType.ULONG); if (numEntries !== 1) { console.error("(nokia.contacts) event getFirst with numEntries != 1 not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); } this.getFirstOrNext(trans_id, "getFirst"); @@ -542,12 +542,12 @@ NokiaContactsLocalMsgConnection.prototype.sendMessageToServer = function(message var includeStartEntry = decoder.getValue(DataType.BOOLEAN); if (includeStartEntry == 1) { console.error("(nokia.contacts) event getNext with includeStartEntry == true not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); } var numEntries = decoder.getValue(DataType.ULONG); if (numEntries !== 1) { console.error("(nokia.contacts) event getNext with numEntries != 1 not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); } this.getFirstOrNext(trans_id, "getNext"); @@ -555,7 +555,7 @@ NokiaContactsLocalMsgConnection.prototype.sendMessageToServer = function(message default: console.error("(nokia.contacts) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } } @@ -684,7 +684,7 @@ NokiaFileUILocalMsgConnection.prototype.sendMessageToServer = function(message) default: console.error("(nokia.file-ui) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -756,7 +756,7 @@ NokiaImageProcessingLocalMsgConnection.prototype.sendMessageToServer = function( if (aspect != "FullImage" && aspect != "LockToPartialView") { console.error("(nokia.image-processing) event " + name + " with aspect != 'FullImage' or 'LockToPartialView' not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } @@ -859,7 +859,7 @@ NokiaImageProcessingLocalMsgConnection.prototype.sendMessageToServer = function( default: console.error("(nokia.image-processing) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -913,7 +913,7 @@ NokiaProductInfoLocalMsgConnection.prototype.sendMessageToServer = function(mess break; default: console.error("(nokia.status-info) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -1038,7 +1038,7 @@ NokiaActiveStandbyLocalMsgConnection.prototype.sendMessageToServer = function(me default: console.error("(nokia.active-standby) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } } @@ -1124,7 +1124,7 @@ Native["org/mozilla/io/LocalMsgConnection.sendData.([BII)V"] = function(data, of this.connection.sendMessageToClient(message); } else { if (MIDP.FakeLocalMsgServers.indexOf(this.protocolName) != -1) { - console.warn("sendData (" + util.decodeUtf8(new Uint8Array(data.buffer, offset, length)) + ") to an unimplemented localmsg server (" + this.protocolName + ")"); + console.warn("sendData (" + util.decodeUtf8(new Int8Array(data.buffer, offset, length)) + ") to an unimplemented localmsg server (" + this.protocolName + ")"); } this.connection.sendMessageToServer(message); diff --git a/midp/media.js b/midp/media.js index 91e858ea..aba269d1 100644 --- a/midp/media.js +++ b/midp/media.js @@ -714,7 +714,7 @@ PlayerContainer.prototype.getRecordedSize = function() { PlayerContainer.prototype.getRecordedData = function(offset, size, buffer) { var toRead = (size < this.audioRecorder.data.length) ? size : this.audioRecorder.data.byteLength; buffer.set(this.audioRecorder.data.subarray(0, toRead), offset); - this.audioRecorder.data = new Uint8Array(this.audioRecorder.data.buffer.slice(toRead)); + this.audioRecorder.data = new Int8Array(this.audioRecorder.data.buffer.slice(toRead)); }; PlayerContainer.prototype.startSnapshot = function(imageType) { @@ -732,7 +732,7 @@ PlayerContainer.prototype.getDuration = function() { var AudioRecorder = function(aMimeType) { this.mimeType = aMimeType || "audio/3gpp"; this.eventListeners = {}; - this.data = new Uint8Array(); + this.data = new Int8Array(); this.sender = DumbPipe.open("audiorecorder", { mimeType: this.mimeType }, this.recipient.bind(this)); @@ -816,7 +816,7 @@ AudioRecorder.prototype.stop = function() { // The audio data we received are encoded with a proper format, it doesn't // make sense to concatenate them like the socket, so let just override // the buffered data here. - var data = new Uint8Array(message.data); + var data = new Int8Array(message.data); if (this.getContentType() === "audio/amr") { data = Media.convert3gpToAmr(data); } @@ -854,7 +854,7 @@ AudioRecorder.prototype.pause = function() { // The audio data we received are encoded with a proper format, it doesn't // make sense to concatenate them like the socket, so let just override // the buffered data here. - this.data = new Uint8Array(message.data); + this.data = new Int8Array(message.data); resolve(1); }.bind(this); diff --git a/midp/midp.js b/midp/midp.js index a9f93f10..1fd01023 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -97,7 +97,7 @@ Native["com/sun/midp/jarutil/JarReader.readJarEntry0.(Ljava/lang/String;Ljava/la if (!bytes) throw $.newIOException(); var length = bytes.byteLength; - var data = new Uint8Array(bytes); + var data = new Int8Array(bytes); var array = J2ME.newByteArray(length); for (var n = 0; n < length; ++n) array[n] = data[n]; @@ -535,7 +535,7 @@ Native["com/sun/midp/util/ResourceHandler.loadRomizedResource0.(Ljava/lang/Strin } var len = data.byteLength; var bytes = J2ME.newByteArray(len); - var src = new Uint8Array(data); + var src = new Int8Array(data); for (var n = 0; n < bytes.byteLength; ++n) bytes[n] = src[n]; return bytes; diff --git a/midp/socket.js b/midp/socket.js index d558e8b0..60196c9f 100644 --- a/midp/socket.js +++ b/midp/socket.js @@ -65,7 +65,7 @@ Native["com/sun/midp/io/j2me/socket/Protocol.open0.([BI)V"] = function(ipBytes, this.options[SOCKET_OPT.RCVBUF] = 8192; this.options[SOCKET_OPT.SNDBUF] = 8192; - this.data = new Uint8Array(); + this.data = new Int8Array(); this.waitingData = null; this.socket.onopen = function() { @@ -88,11 +88,11 @@ Native["com/sun/midp/io/j2me/socket/Protocol.open0.([BI)V"] = function(ipBytes, this.socket.ondata = (function(message) { // console.log("this.socket.ondata: " + JSON.stringify(message)); if (this.data.byteLength === 0) { - this.data = new Uint8Array(message.data); + this.data = new Int8Array(message.data); } else { - var newArray = new Uint8Array(this.data.byteLength + message.data.byteLength); + var newArray = new Int8Array(this.data.byteLength + message.data.byteLength); newArray.set(this.data); - newArray.set(new Uint8Array(message.data), this.data.byteLength); + newArray.set(new Int8Array(message.data), this.data.byteLength); this.data = newArray; } diff --git a/native.js b/native.js index e96a4685..55459d26 100644 --- a/native.js +++ b/native.js @@ -797,7 +797,7 @@ Native["com/sun/cldc/i18n/j2me/UTF_8_Reader.readNative.([CII)I"] = function(cbuf }; Native["java/io/DataInputStream.bytesToUTF.([B)Ljava/lang/String;"] = function(bytearr) { - var array = new Uint8Array(bytearr.buffer); + var array = new Int8Array(bytearr.buffer); try { return J2ME.newString(util.decodeUtf8Array(array)); } catch(e) { @@ -860,7 +860,7 @@ Native["com/sun/cldc/i18n/j2me/UTF_8_Writer.encodeUTF8.([CII)[B"] = function(cbu var count = 0; while (count < len) { - var outputByte = new Uint8Array(4); // Never more than 4 encoded bytes + var outputByte = new Int8Array(4); // Never more than 4 encoded bytes inputChar = 0xffff & cbuf[off + count]; if (0 != pendingSurrogate) { if (0xdc00 <= inputChar && inputChar <= 0xdfff) { From 16d941008b7869ed5faca0a689785cd4af972690 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 3 Feb 2015 23:13:39 +0100 Subject: [PATCH 08/12] Remove duplicate native (already implemented in bindings.ts) --- native.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/native.js b/native.js index e96a4685..799ded11 100644 --- a/native.js +++ b/native.js @@ -280,13 +280,6 @@ Native["java/lang/Object.getClass.()Ljava/lang/Class;"] = function() { return J2ME.getRuntimeKlass($.ctx.runtime, this.klass).classObject; }; -Native["java/lang/Object.hashCode.()I"] = function() { - var hashCode = this.hashCode; - while (!hashCode) - hashCode = this.hashCode = util.id(); - return hashCode; -}; - Native["java/lang/Object.wait.(J)V"] = function(timeout) { $.ctx.wait(this, timeout.toNumber()); }; From ee67b5bd85c1ac70799b470f94c4a59badb878dd Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Tue, 3 Feb 2015 15:15:53 -0800 Subject: [PATCH 09/12] point to custom version of compiler --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9af221ac..596748c2 100644 --- a/README.md +++ b/README.md @@ -205,8 +205,8 @@ To use it, first install a recent version of the `make closure` compiles some JavaScript code with the Closure compiler. -To use it, first download Shumway's version of the compiler to tools/closure.jar: +To use it, first download this custom version of the compiler to tools/closure.jar: ``` -wget https://github.com/mozilla/shumway/raw/master/utils/closure.jar -P tools/ +wget https://github.com/mykmelez/closure-compiler/releases/download/v0.1/closure.jar -P tools/ ``` From 1fb43c99644a2a5ed04c353dbea533a6b101d5f4 Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Tue, 3 Feb 2015 15:17:51 -0800 Subject: [PATCH 10/12] use j2me.js-specific optimizations flag --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 53ec2f45..4c0b0ef6 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ build/program.jar.js: program.jar build/jsc.js aot-methods.txt js build/jsc.js -cp java/classes.jar program.jar -d -jf program.jar -mff aot-methods.txt > build/program.jar.js closure: build/classes.jar.js build/j2me.js - java -jar tools/closure.jar --language_in ECMASCRIPT5 -O SHUMWAY_OPTIMIZATIONS build/j2me.js > build/j2me.cc.js \ + java -jar tools/closure.jar --language_in ECMASCRIPT5 -O J2ME_OPTIMIZATIONS build/j2me.js > build/j2me.cc.js \ && mv build/j2me.cc.js build/j2me.js java -jar tools/closure.jar --language_in ECMASCRIPT5 -O SIMPLE build/classes.jar.js > build/classes.jar.cc.js \ && mv build/classes.jar.cc.js build/classes.jar.js From bf3bd15217ef42db880a1896717ba9fe47eba9de Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Tue, 3 Feb 2015 15:34:06 -0800 Subject: [PATCH 11/12] Use asyncImpl for isolate locks. --- midp/midp.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/midp/midp.js b/midp/midp.js index 1a4afa11..81fa2a7a 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -861,6 +861,7 @@ Native["com/sun/midp/util/isolate/InterIsolateMutex.getID0.(Ljava/lang/String;)I }; Native["com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V"] = function(id) { + var ctx = $.ctx; var mutex; for (var i = 0; i < MIDP.InterIsolateMutexes.length; i++) { if (MIDP.InterIsolateMutexes[i].id == id) { @@ -875,26 +876,21 @@ Native["com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V"] = function(id) if (!mutex.locked) { mutex.locked = true; - mutex.holder = $.ctx.runtime.isolate.id; + mutex.holder = ctx.runtime.isolate.id; return; } - if (mutex.holder == $.ctx.runtime.isolate.id) { + if (mutex.holder == ctx.runtime.isolate.id) { throw $.newRuntimeException("Attempting to lock mutex twice within the same Isolate"); } - var ctx = $.ctx; - mutex.waiting.push(function() { - // We can't use asyncImpl in this native because we can't simply execute - // the context that called lock0 without pausing the context that called unlock0. - // So, we're scheduling the context that called lock0. - - mutex.locked = true; - mutex.holder = ctx.runtime.isolate.id; - Runtime.scheduleRunningContext(ctx); - }); - - $.pause("Async"); + asyncImpl("V", new Promise(function(resolve, reject) { + mutex.waiting.push(function() { + mutex.locked = true; + mutex.holder = ctx.runtime.isolate.id; + resolve(); + }); + })); }; Native["com/sun/midp/util/isolate/InterIsolateMutex.unlock0.(I)V"] = function(id) { From 39219a3e980e05420ab1e8bf55e294ea44c36d85 Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Tue, 3 Feb 2015 21:38:00 -0800 Subject: [PATCH 12/12] use Int8Array in fs --- libs/fs.js | 4 ++-- midp/fs.js | 4 ++-- tests/automation.js | 2 +- tests/com/sun/midp/publickeystore/TestInputOutputStorage.java | 4 +++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/fs.js b/libs/fs.js index 676b45ec..021c26a4 100644 --- a/libs/fs.js +++ b/libs/fs.js @@ -383,7 +383,7 @@ var fs = (function() { } } - var newArray = new Uint8Array(newBufferSize); + var newArray = new Int8Array(newBufferSize); newArray.set(this.array); this.array = newArray; @@ -463,7 +463,7 @@ var fs = (function() { var fd = openedFiles.push({ dirty: false, path: path, - buffer: new FileBuffer(new Uint8Array(reader.result)), + buffer: new FileBuffer(new Int8Array(reader.result)), mtime: record.mtime, size: record.size, position: 0, diff --git a/midp/fs.js b/midp/fs.js index 8845ccee..76249209 100644 --- a/midp/fs.js +++ b/midp/fs.js @@ -493,7 +493,7 @@ Native["com/ibm/oti/connection/file/FCInputStream.readByteImpl.(I)I"] = function var data = fs.read(fd, curpos, curpos+1); - return (data.byteLength > 0) ? data[0] : -1; + return (data.byteLength > 0) ? (data[0] & 0xFF) : -1; }; Native["com/ibm/oti/connection/file/FCInputStream.closeImpl.(I)V"] = function(fd) { @@ -551,7 +551,7 @@ Native["com/ibm/oti/connection/file/FCOutputStream.syncImpl.(I)V"] = function(fd }; Native["com/ibm/oti/connection/file/FCOutputStream.writeByteImpl.(II)V"] = function(val, fd) { - var buf = new Uint8Array(1); + var buf = new Int8Array(1); buf[0] = val; fs.write(fd, buf); }; diff --git a/tests/automation.js b/tests/automation.js index 3127c647..b455e09c 100644 --- a/tests/automation.js +++ b/tests/automation.js @@ -70,7 +70,7 @@ var gfxTests = [ ]; var expectedUnitTestResults = [ - { name: "pass", number: 71566 }, + { name: "pass", number: 71565 }, { name: "fail", number: 0 }, { name: "known fail", number: 215 }, { name: "unknown pass", number: 0 } diff --git a/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java b/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java index 8ea00257..f408e209 100644 --- a/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java +++ b/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java @@ -33,7 +33,9 @@ public class TestInputOutputStorage implements Testlet { public void test(TestHarness th) { try { FileConnection file = (FileConnection)Connector.open("file:////prova"); - th.check(!file.exists()); + if (file.exists()) { + file.delete(); + } file.create(); RandomAccessStream ras = new RandomAccessStream();