Update some natives to the new mangling scheme.

This commit is contained in:
Michael Bebenita 2014-11-25 17:46:41 -08:00
Родитель ec70b204a3
Коммит d216ded20e
6 изменённых файлов: 94 добавлений и 56 удалений

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

@ -263,16 +263,9 @@ module J2ME {
return this.superClass ? this.superClass.isAssignableTo(toClass) : false;
}
getClassObject(ctx: Context) {
var className = this.className;
var classObjects = ctx.runtime.classObjects;
var classObject = classObjects[className];
if (!classObject) {
classObject = util.newObject(CLASSES.java_lang_Class);
classObject.vmClass = this;
classObjects[className] = classObject;
}
return classObject;
getClassObject(ctx: Context): java.lang.Class {
// TODO: Check to make sure that it doesn't matter if this is done eagerly.
return runtimeKlass(ctx.runtime, this.klass).classObject;
}
getField(fieldKey: string) : FieldInfo {

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

@ -12,7 +12,7 @@ module J2ME {
frameSets: any [];
lockTimeout: number;
lockLevel: number;
thread: any;
thread: java.lang.Thread;
constructor(public runtime: Runtime) {
this.frames = [];
@ -248,7 +248,7 @@ module J2ME {
window.clearTimeout(this.lockTimeout);
this.lockTimeout = null;
}
if (obj.lock) {
if (obj.__lock__) {
if (!obj.ready)
obj.ready = [];
obj.ready.push(this);
@ -259,10 +259,10 @@ module J2ME {
}
}
monitorEnter(obj) {
var lock = obj.lock;
monitorEnter(obj: java.lang.Object) {
var lock = obj.__lock__;
if (!lock) {
obj.lock = {thread: this.thread, level: 1};
obj.__lock__ = new Lock(this.thread, 1);
return;
}
if (lock.thread === this.thread) {
@ -273,20 +273,20 @@ module J2ME {
}
monitorExit(obj) {
var lock = obj.lock;
var lock = obj.__lock__;
if (lock.thread !== this.thread)
this.raiseExceptionAndYield("java/lang/IllegalMonitorStateException");
if (--lock.level > 0) {
return;
}
obj.lock = null;
obj.__lock__ = null;
this.unblock(obj, "ready", false, function (ctx) {
ctx.wakeup(obj);
});
}
wait(obj, timeout) {
var lock = obj.lock;
var lock = obj.__lock__;
if (timeout < 0)
this.raiseExceptionAndYield("java/lang/IllegalArgumentException");
if (!lock || lock.thread !== this.thread)
@ -311,7 +311,7 @@ module J2ME {
}
notify(obj, notifyAll) {
if (!obj.lock || obj.lock.thread !== this.thread)
if (!obj.__lock__ || obj.__lock__.thread !== this.thread)
this.raiseExceptionAndYield("java/lang/IllegalMonitorStateException");
this.unblock(obj, "waiting", notifyAll, function (ctx) {
ctx.wakeup(obj);

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

@ -607,7 +607,7 @@ module J2ME.C4.Backend {
var friendlyMangledNames = true;
export function mangleString(s: string) {
export function escapeString(s: string) {
var invalidChars = "[];/<>()";
var replaceChars = "abc_defg";
var result = "";
@ -625,7 +625,7 @@ module J2ME.C4.Backend {
export function mangleClassAndMethod(methodInfo: MethodInfo) {
var name = methodInfo.classInfo.className + methodInfo.name + methodInfo.signature;
if (friendlyMangledNames) {
return mangleString(name);
return escapeString(name);
}
var hash = hashString(name);
return StringUtilities.variableLengthEncodeInt32(hash);
@ -634,7 +634,7 @@ module J2ME.C4.Backend {
export function mangleMethod(methodInfo: MethodInfo) {
var name = methodInfo.name + methodInfo.signature;
if (friendlyMangledNames) {
return mangleString(name);
return escapeString(name);
}
var hash = hashString(name);
return StringUtilities.variableLengthEncodeInt32(hash);
@ -645,24 +645,15 @@ module J2ME.C4.Backend {
return "$AK(" + mangleClass(classInfo.elementClass) + ")";
} else {
if (friendlyMangledNames) {
return mangleString(classInfo.className);
return escapeString(classInfo.className);
}
var hash = hashString(classInfo.className);
return StringUtilities.variableLengthEncodeInt32(hash);
}
}
export function mangleClassAndField(fieldInfo: FieldInfo) {
var name = fieldInfo.classInfo.className + fieldInfo.name;
if (friendlyMangledNames) {
return mangleString(name);
}
var hash = hashString(name);
return StringUtilities.variableLengthEncodeInt32(hash);
}
export function mangleField(fieldInfo: FieldInfo) {
return mangleString(fieldInfo.name);
return "$" + escapeString(fieldInfo.name);
}
function getRuntimeClass(classInfo: ClassInfo) {

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

@ -229,7 +229,7 @@ Native.create("java/lang/Object.notifyAll.()V", function(ctx) {
});
Native.create("java/lang/Class.invoke_clinit.()V", function(ctx) {
var classInfo = this.vmClass;
var classInfo = this.runtimeKlass.classInfo;
var className = classInfo.className;
var runtime = ctx.runtime;
if (runtime.initialized[className] || runtime.pending[className])
@ -256,7 +256,7 @@ Native.create("java/lang/Class.invoke_clinit.()V", function(ctx) {
});
Native.create("java/lang/Class.init9.()V", function(ctx) {
var classInfo = this.vmClass;
var classInfo = this.runtimeKlass.classInfo;
var className = classInfo.className;
var runtime = ctx.runtime;
if (runtime.initialized[className])
@ -266,7 +266,7 @@ Native.create("java/lang/Class.init9.()V", function(ctx) {
});
Native.create("java/lang/Class.getName.()Ljava/lang/String;", function() {
return this.vmClass.className.replace(/\//g, ".");
return this.runtimeKlass.classInfo.className.replace(/\//g, ".");
});
Native.create("java/lang/Class.forName.(Ljava/lang/String;)Ljava/lang/Class;", function(name, ctx) {
@ -285,7 +285,7 @@ Native.create("java/lang/Class.forName.(Ljava/lang/String;)Ljava/lang/Class;", f
});
Native.create("java/lang/Class.newInstance.()Ljava/lang/Object;", function(ctx) {
var className = this.vmClass.className;
var className = this.runtimeKlass.classInfo.className;
var syntheticMethod = new MethodInfo({
name: "ClassNewInstanceSynthetic",
signature: "()Ljava/lang/Object;",
@ -315,21 +315,21 @@ Native.create("java/lang/Class.newInstance.()Ljava/lang/Object;", function(ctx)
});
Native.create("java/lang/Class.isInterface.()Z", function() {
return ACCESS_FLAGS.isInterface(this.vmClass.access_flags);
return ACCESS_FLAGS.isInterface(this.runtimeKlass.classInfo.access_flags);
});
Native.create("java/lang/Class.isArray.()Z", function() {
return !!this.vmClass.isArrayClass;
return !!this.runtimeKlass.classInfo.isArrayClass;
});
Native.create("java/lang/Class.isAssignableFrom.(Ljava/lang/Class;)Z", function(fromClass) {
if (!fromClass)
throw new JavaException("java/lang/NullPointerException");
return fromClass.vmClass.isAssignableTo(this.vmClass);
return fromClass.runtimeKlass.classInfo.isAssignableTo(this.runtimeKlass.classInfo);
});
Native.create("java/lang/Class.isInstance.(Ljava/lang/Object;)Z", function(obj) {
return obj && obj.class.isAssignableTo(this.vmClass);
return obj && obj.class.isAssignableTo(this.runtimeKlass.classInfo);
});
Native.create("java/lang/Float.floatToIntBits.(F)I", (function() {
@ -551,7 +551,7 @@ Native.create("com/sun/cldc/io/ResourceInputStream.open.(Ljava/lang/String;)Ljav
});
Override.create("com/sun/cldc/io/ResourceInputStream.available.()I", function() {
var handle = this.class.getField("I.fileDecoder.Ljava/lang/Object;").get(this);
var handle = this.$fileDecoder;
if (!handle) {
throw new JavaException("java/io/IOException");
@ -561,7 +561,7 @@ Override.create("com/sun/cldc/io/ResourceInputStream.available.()I", function()
});
Override.create("com/sun/cldc/io/ResourceInputStream.read.()I", function() {
var handle = this.class.getField("I.fileDecoder.Ljava/lang/Object;").get(this);
var handle = this.$fileDecoder;
if (!handle) {
throw new JavaException("java/io/IOException");
@ -674,8 +674,8 @@ Native.create("com/sun/midp/links/LinkPortal.getLinks0.([Lcom/sun/midp/links/Lin
var isolateId = ctx.runtime.isolate.id;
for (var i = 0; i < links[isolateId].length; i++) {
var nativePointer = links[isolateId][i].class.getField("I.nativePointer.I").get(links[isolateId][i]);
linkArray[i].class.getField("I.nativePointer.I").set(linkArray[i], nativePointer);
var nativePointer = links[isolateId][i].$nativePointer;
linkArray[i].$nativePointer = nativePointer;
linkArray[i].sender = links[isolateId][i].sender;
linkArray[i].receiver = links[isolateId][i].receiver;
}
@ -692,7 +692,7 @@ Native.create("com/sun/midp/links/LinkPortal.setLinks0.(I[Lcom/sun/midp/links/Li
Native.create("com/sun/midp/links/Link.init0.(II)V", function(sender, receiver) {
this.sender = sender;
this.receiver = receiver;
this.class.getField("I.nativePointer.I").set(this, util.id());
this.$nativePointer = util.id();
});
Native.create("com/sun/midp/links/Link.receive0.(Lcom/sun/midp/links/LinkMessage;Lcom/sun/midp/links/Link;)V", function(linkMessage, link) {
@ -735,7 +735,7 @@ Native.create("java/io/DataInputStream.bytesToUTF.([B)Ljava/lang/String;", funct
Native.create("com/sun/cldc/i18n/j2me/UTF_8_Writer.encodeUTF8.([CII)[B", function(cbuf, off, len) {
var outputArray = [];
var pendingSurrogate = this.class.getField("I.pendingSurrogate.I").get(this);
var pendingSurrogate = this.$pendingSurrogate;
var inputChar = 0;
var outputSize = 0;
@ -792,7 +792,7 @@ Native.create("com/sun/cldc/i18n/j2me/UTF_8_Writer.encodeUTF8.([CII)[B", functio
count++;
}
this.class.getField("I.pendingSurrogate.I").set(this, pendingSurrogate);
this.$pendingSurrogate = pendingSurrogate;
var totalSize = outputArray.reduce(function(total, cur) {
return total + cur.length;
@ -812,7 +812,7 @@ Native.create("com/sun/cldc/i18n/j2me/UTF_8_Writer.sizeOf.([CII)I", function(cbu
var outputSize = 0;
var outputCount = 0;
var count = 0;
var localPendingSurrogate = this.class.getField("I.pendingSurrogate.I").get(this);
var localPendingSurrogate = this.$pendingSurrogate;
while (count < length) {
inputChar = 0xffff & cbuf[offset + count];
if (0 != localPendingSurrogate) {

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

@ -151,7 +151,7 @@ module J2ME {
new (): java.lang.Object;
/**
* Array klass of this klass constructed via \arrayKlass\.
* Array klass of this klass, constructed via \arrayKlass\.
*/
arrayKlass: ArrayKlass;
@ -186,12 +186,22 @@ module J2ME {
/**
* Java class object. This is only available on runtime klasses.
*/
class: java.lang.Class
classObject: java.lang.Class;
/**
* Wether this class is a runtime class.
*/
isRuntimeKlass: boolean;
}
export interface ArrayKlass extends Klass {
elementKlass: Klass;
}
export class Lock {
constructor(public thread: java.lang.Thread, public level: number) {
// ...
}
}
export module java.lang {
@ -206,6 +216,11 @@ module J2ME {
*/
__hashCode__: number;
/**
* Some objects may have a lock.
*/
__lock__: Lock;
clone(): java.lang.Object;
equals(obj: java.lang.Object): boolean;
finalize(): void;
@ -220,16 +235,27 @@ module J2ME {
}
export interface Class extends java.lang.Object {
runtimeKlass: Klass;
}
export interface String extends java.lang.Object {
}
export interface Thread extends java.lang.Object {
}
}
declare var CLASSES;
function initializeClassObject(klass: Klass) {
assert(klass.isRuntimeKlass, "Can only create class objects for runtime klasses.");
assert(!klass.classObject);
klass.classObject = <java.lang.Class>newObject(Klasses.java.lang.Class);
klass.classObject.runtimeKlass = klass;
}
/**
* Called by compiled code to initialize the klass. Klass initializers are reflected as
* memoizing getters on the |RuntimeTemplate.prototype|. Once they are first accessed,
@ -241,9 +267,11 @@ module J2ME {
Object.defineProperty(RuntimeTemplate.prototype, mangledClassName, {
configurable: true,
get: function () {
assert(!klass.isRuntimeKlass);
var runtimeKlass = klass.bind(null);
runtimeKlass.klass = klass;
runtimeKlass.class = new Class(runtimeKlass);
runtimeKlass.isRuntimeKlass = true;
initializeClassObject(runtimeKlass);
var classInfo = CLASSES.getClass(className);
Object.defineProperty(this, mangledClassName, {
configurable: false,
@ -261,6 +289,13 @@ module J2ME {
});
}
export function runtimeKlass(runtime: Runtime, klass: Klass): Klass {
assert(!klass.isRuntimeKlass);
var runtimeKlass = runtime[klass.classInfo.mangledName];
assert(runtimeKlass.isRuntimeKlass);
return runtimeKlass;
}
export function createKlass(classInfo: ClassInfo): Klass {
if (!classInfo) {
return null;
@ -390,11 +425,20 @@ module J2ME {
return arrayKlass;
}
export function toDebugString(object: java.lang.Object): string {
if (!object) {
export function toDebugString(value: any): string {
if (typeof value !== "object") {
return String(value);
}
if (!value) {
return "null";
}
return "[" + object.klass.classInfo.className + " 0x" + object.__hashCode__.toString(16).toUpperCase() + "]";
if (!value.klass) {
return "no klass";
}
if (!value.klass.classInfo) {
return value.klass + " no classInfo"
}
return "[" + value.klass.classInfo.className + " 0x" + value.__hashCode__.toString(16).toUpperCase() + "]";
}
}

10
vm.js
Просмотреть файл

@ -18,6 +18,8 @@ VM.trace = function(type, pid, methodInfo, returnVal) {
(returnVal ? (" " + returnVal) : "") + "\n";
}
var traceWriter = new J2ME.IndentingWriter();
VM.execute = function(ctx) {
var frame = ctx.current();
@ -27,6 +29,13 @@ VM.execute = function(ctx) {
function pushFrame(methodInfo) {
var caller = frame;
if (traceWriter) {
var args = stack.slice(stack.length - methodInfo.consumes).map(function (x) {
return J2ME.toDebugString(x);
}).join(", ")
traceWriter.enter(methodInfo.implKey + " " + args);
}
frame = ctx.pushFrame(methodInfo);
stack = frame.stack;
cp = frame.cp;
@ -43,6 +52,7 @@ VM.execute = function(ctx) {
}
function popFrame(consumes) {
traceWriter && traceWriter.outdent();
if (frame.lockObject)
ctx.monitorExit(frame.lockObject);
var callee = frame;