зеркало из https://github.com/mozilla/pluotsorbet.git
Changes mangling scheme for field names.
Cleans up a bit the tracing system. Fixes throws in compiled code. Adds a way to specify a text file to filter the classes that need to be compiled.
This commit is contained in:
Родитель
873ad77ac2
Коммит
29b2f0e84f
77
actors.ts
77
actors.ts
|
@ -30,14 +30,14 @@ module J2ME {
|
|||
export class FieldInfo {
|
||||
private static _nextiId = 0;
|
||||
id: number;
|
||||
isStatic: boolean;
|
||||
mangledName: string;
|
||||
isStatic: boolean ;
|
||||
constantValue: any;
|
||||
mangledName: string;
|
||||
|
||||
constructor(public classInfo: ClassInfo, public access_flags: number, public name: string, public signature: string) {
|
||||
this.id = FieldInfo._nextiId++;
|
||||
this.isStatic = ACCESS_FLAGS.isStatic(access_flags);
|
||||
this.mangledName = J2ME.C4.Backend.mangleField(this);
|
||||
this.mangledName = undefined;
|
||||
}
|
||||
|
||||
get(object: java.lang.Object) {
|
||||
|
@ -141,8 +141,8 @@ module J2ME {
|
|||
this.implKey = this.classInfo.className + "." + this.name + "." + this.signature;
|
||||
|
||||
|
||||
this.mangledName = J2ME.C4.Backend.mangleMethod(this);
|
||||
this.mangledClassAndMethodName = J2ME.C4.Backend.mangleClassAndMethod(this);
|
||||
this.mangledName = mangleMethod(this);
|
||||
this.mangledClassAndMethodName = mangleClassAndMethod(this);
|
||||
|
||||
this.signatureDescriptor = SignatureDescriptor.makeSignatureDescriptor(this.signature);
|
||||
this.consumes = this.signatureDescriptor.getArgumentSlotCount();
|
||||
|
@ -206,21 +206,7 @@ module J2ME {
|
|||
this.vmc = {};
|
||||
this.vfc = {};
|
||||
|
||||
this.mangledName = J2ME.C4.Backend.mangleClass(this);
|
||||
|
||||
/*
|
||||
if (jsGlobal[this.mangledName]) {
|
||||
this.constructor = jsGlobal[this.mangledName];
|
||||
} else {
|
||||
this.constructor = function () {};
|
||||
}
|
||||
|
||||
this.constructor.prototype.class = this;
|
||||
this.constructor.prototype.toString = function() {
|
||||
return '[instance ' + this.class.className + ']';
|
||||
};
|
||||
*/
|
||||
|
||||
this.mangledName = mangleClass(this);
|
||||
|
||||
var self = this;
|
||||
|
||||
|
@ -269,6 +255,57 @@ module J2ME {
|
|||
});
|
||||
}
|
||||
|
||||
public complete() {
|
||||
this._mangleFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class hierarchy in derived -> base order.
|
||||
*/
|
||||
private _getClassHierarchy(): ClassInfo [] {
|
||||
var classHierarchy = [];
|
||||
var classInfo = this;
|
||||
do {
|
||||
classHierarchy.push(classInfo);
|
||||
classInfo = classInfo.superClass;
|
||||
} while (classInfo);
|
||||
return classHierarchy;
|
||||
}
|
||||
|
||||
private _mangleFields() {
|
||||
if (false) {
|
||||
// Safe mangling that includes className, fieldName and signature.
|
||||
var fields = this.fields;
|
||||
for (var j = 0; j < fields.length; j++) {
|
||||
var fieldInfo = fields[j];
|
||||
fieldInfo.mangledName = "$" + escapeString(fieldInfo.classInfo.className + "_" + fieldInfo.name + "_" + fieldInfo.signature);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep track of how many times a field name was used and resolve conflicts by
|
||||
// prefixing filed names with numbers.
|
||||
var classHierarchy = this._getClassHierarchy();
|
||||
var count = Object.create(null);
|
||||
for (var i = classHierarchy.length - 1; i >= 0; i--) {
|
||||
classInfo = classHierarchy[i];
|
||||
var fields = classInfo.fields;
|
||||
for (var j = 0; j < fields.length; j++) {
|
||||
var field = fields[j];
|
||||
var fieldName = field.name;
|
||||
if (count[field.name] === undefined) {
|
||||
count[fieldName] = 0;
|
||||
}
|
||||
var fieldCount = count[fieldName];
|
||||
// Only mangle this classInfo's fields.
|
||||
if (i === 0) {
|
||||
field.mangledName = "$" + (fieldCount ? "$" + fieldCount : "") + field.name;
|
||||
}
|
||||
count[fieldName] ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get isInterface() : boolean {
|
||||
return ACCESS_FLAGS.isInterface(this.access_flags);
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@ module J2ME {
|
|||
classes.forEach(function (c, n) {
|
||||
classes[n] = self.loadClass(c);
|
||||
});
|
||||
classInfo.complete();
|
||||
if (J2ME.phase === J2ME.ExecutionPhase.Runtime) {
|
||||
J2ME.linkKlass(classInfo);
|
||||
}
|
||||
|
|
10
context.ts
10
context.ts
|
@ -115,15 +115,15 @@ module J2ME {
|
|||
lockTimeout: number;
|
||||
lockLevel: number;
|
||||
thread: java.lang.Thread;
|
||||
traceWriter: IndentingWriter;
|
||||
writer: IndentingWriter;
|
||||
constructor(public runtime: Runtime) {
|
||||
var id = this.id = Context._nextId ++;
|
||||
this.frames = [];
|
||||
this.frameSets = [];
|
||||
this.runtime = runtime;
|
||||
this.runtime.addContext(this);
|
||||
this.traceWriter = new IndentingWriter(false, function (s) {
|
||||
dumpLine(id + " | " + s);
|
||||
this.writer = new IndentingWriter(false, function (s) {
|
||||
dumpLine(runtime.id + ":" + id + " | " + s);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,9 @@ module J2ME {
|
|||
return;
|
||||
}
|
||||
$.ctx = this;
|
||||
traceWriter = null; // this.traceWriter;
|
||||
traceWriter = null; // this.writer;
|
||||
linkWriter = null; // this.writer;
|
||||
initWriter = this.writer;
|
||||
}
|
||||
|
||||
execute() {
|
||||
|
|
|
@ -37,11 +37,6 @@ module J2ME {
|
|||
import BytecodeStream = Bytecode.BytecodeStream;
|
||||
import Condition = Bytecode.Condition;
|
||||
|
||||
|
||||
import mangleMethod = J2ME.C4.Backend.mangleMethod;
|
||||
import mangleClass = J2ME.C4.Backend.mangleClass;
|
||||
import mangleField = J2ME.C4.Backend.mangleField;
|
||||
|
||||
function kindsFromSignature(signature: string) {
|
||||
|
||||
}
|
||||
|
@ -1131,7 +1126,8 @@ module J2ME {
|
|||
}
|
||||
|
||||
genThrow(bci: number) {
|
||||
var _throw = new IR.JVMThrow(this.region, this.state.store);
|
||||
var object = this.state.peek();
|
||||
var _throw = new IR.JVMThrow(this.region, this.state.store, object);
|
||||
this.recordStore(_throw);
|
||||
this.methodReturnInfos.push(new ReturnInfo(
|
||||
this.region,
|
||||
|
|
|
@ -134,14 +134,6 @@ module J2ME.C4.Backend {
|
|||
return new Identifier(name);
|
||||
}
|
||||
|
||||
export function isIdentifierStart(c) {
|
||||
return (c === '$') || (c === '_') || (c === '\\') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
export function isIdentifierPart(c) {
|
||||
return (c === '$') || (c === '_') || (c === '\\') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || ((c >= '0') && (c <= '9'));
|
||||
}
|
||||
|
||||
export function isIdentifierName(s) {
|
||||
if (!isIdentifierStart(s[0])) {
|
||||
return false;
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
module J2ME {
|
||||
|
||||
import mangleClass = J2ME.C4.Backend.mangleClass;
|
||||
import mangleField = J2ME.C4.Backend.mangleField;
|
||||
import mangleMethod = J2ME.C4.Backend.mangleMethod;
|
||||
import mangleClassAndMethod = J2ME.C4.Backend.mangleClassAndMethod;
|
||||
|
||||
declare var release;
|
||||
|
||||
export class Emitter {
|
||||
|
@ -166,9 +161,9 @@ module J2ME {
|
|||
emitFieldDefinition(emitter, fieldInfo);
|
||||
} else {
|
||||
if (emitter.closure) {
|
||||
writer.writeLn("this[" + quote(mangleField(fieldInfo)) + "] = " + defaultValue + ";");
|
||||
writer.writeLn("this[" + quote(fieldInfo.mangledName) + "] = " + defaultValue + ";");
|
||||
} else {
|
||||
writer.writeLn("this." + mangleField(fieldInfo) + " = " + defaultValue + ";");
|
||||
writer.writeLn("this." + fieldInfo.mangledName + " = " + defaultValue + ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +300,7 @@ module J2ME {
|
|||
return compiledMethods;
|
||||
}
|
||||
|
||||
export function compile(jvm: any, classFilter: string, fileFilter: string, debugInfo: boolean, tsDefinitions: boolean) {
|
||||
export function compile(jvm: any, classFilter: (classInfo: ClassInfo) => boolean, fileFilter: string, debugInfo: boolean, tsDefinitions: boolean) {
|
||||
var runtime = new Runtime(jvm);
|
||||
var classFiles = CLASSES.classFiles;
|
||||
var ctx = new Context(runtime);
|
||||
|
@ -332,7 +327,7 @@ module J2ME {
|
|||
if (classInfo.sourceFile && !classInfo.sourceFile.match(fileFilter)) {
|
||||
return true;
|
||||
}
|
||||
if (!classInfo.className.match(classFilter)) {
|
||||
if (!classFilter(classInfo)) {
|
||||
return true;
|
||||
}
|
||||
classInfoList.push(classInfo);
|
||||
|
|
|
@ -205,13 +205,14 @@ module J2ME.C4.IR {
|
|||
JVMNew.prototype.nodeName = "JVMNew";
|
||||
|
||||
export class JVMThrow extends StoreDependent {
|
||||
constructor(control: Control, store: Store) {
|
||||
constructor(control: Control, store: Store, public object: Value) {
|
||||
super(control, store);
|
||||
this.handlesAssignment = true;
|
||||
}
|
||||
visitInputs(visitor: NodeVisitor) {
|
||||
this.control && visitor(this.control);
|
||||
this.store && visitor(this.store);
|
||||
visitor(this.object);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,7 +356,12 @@ module J2ME.C4.Backend {
|
|||
};
|
||||
|
||||
IR.JVMNewObjectArray.prototype.compile = function (cx: Context): AST.Node {
|
||||
return call(id("$NA"), [id(mangleClass(this.classInfo)), compileValue(this.length, cx)]);
|
||||
var emitClassInitializationCheck = true;
|
||||
var callee: AST.Node = call(id("$NA"), [id(mangleClass(this.classInfo)), compileValue(this.length, cx)]);
|
||||
if (emitClassInitializationCheck) {
|
||||
callee = new AST.SequenceExpression([getRuntimeClass(this.classInfo), callee]);
|
||||
}
|
||||
return callee;
|
||||
};
|
||||
|
||||
IR.JVMStoreIndexed.prototype.compile = function (cx: Context): AST.Node {
|
||||
|
@ -580,7 +586,8 @@ module J2ME.C4.Backend {
|
|||
} else {
|
||||
release || assert (this.opcode === J2ME.Bytecode.Bytecodes.INVOKESTATIC);
|
||||
callee = id(mangleClassAndMethod(this.methodInfo));
|
||||
if (true) {
|
||||
var emitClassInitializationCheck = true;
|
||||
if (emitClassInitializationCheck) {
|
||||
callee = new AST.SequenceExpression([getRuntimeClass(this.methodInfo.classInfo), callee]);
|
||||
}
|
||||
result = call(callee, args);
|
||||
|
@ -600,77 +607,6 @@ module J2ME.C4.Backend {
|
|||
return result;
|
||||
};
|
||||
|
||||
function hashString(s: string) {
|
||||
var data = new Int32Array(s.length);
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
data[i] = s.charCodeAt(i);
|
||||
}
|
||||
return HashUtilities.hashBytesTo32BitsMD5(data, 0, s.length);
|
||||
}
|
||||
|
||||
var friendlyMangledNames = true;
|
||||
|
||||
export function escapeString(s: string) {
|
||||
var invalidChars = "[];/<>()";
|
||||
var replaceChars = "abc_defg";
|
||||
var result = "";
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
if ((i === 0 && isIdentifierStart(s[i])) || (i > 0 && isIdentifierPart(s[i]))) {
|
||||
result += s[i];
|
||||
} else {
|
||||
release || assert (invalidChars.indexOf(s[i]) >= 0, s[i] + " " + s);
|
||||
result += replaceChars[invalidChars.indexOf(s[i])];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mangleClassAndMethod(methodInfo: MethodInfo) {
|
||||
var name = methodInfo.classInfo.className + methodInfo.name + methodInfo.signature;
|
||||
if (friendlyMangledNames) {
|
||||
return escapeString(name);
|
||||
}
|
||||
var hash = hashString(name);
|
||||
return StringUtilities.variableLengthEncodeInt32(hash);
|
||||
}
|
||||
|
||||
export function mangleMethod(methodInfo: MethodInfo) {
|
||||
var name = methodInfo.name + methodInfo.signature;
|
||||
if (friendlyMangledNames) {
|
||||
return escapeString(name);
|
||||
}
|
||||
var hash = hashString(name);
|
||||
return StringUtilities.variableLengthEncodeInt32(hash);
|
||||
}
|
||||
|
||||
export function mangleClass(classInfo: ClassInfo) {
|
||||
if (classInfo instanceof PrimitiveClassInfo) {
|
||||
switch (classInfo.mangledName) {
|
||||
case "int":
|
||||
return "Int32Array";
|
||||
case "boolean":
|
||||
case "byte":
|
||||
return "Int8Array";
|
||||
break;
|
||||
case "char":
|
||||
return "Int16Array";
|
||||
break;
|
||||
}
|
||||
return classInfo.mangledName;
|
||||
} else if (classInfo.isArrayClass) {
|
||||
return "$AK(" + mangleClass(classInfo.elementClass) + ")";
|
||||
} else {
|
||||
if (friendlyMangledNames) {
|
||||
return "$" + escapeString(classInfo.className);
|
||||
}
|
||||
var hash = hashString(classInfo.className);
|
||||
return "$" + StringUtilities.variableLengthEncodeInt32(hash);
|
||||
}
|
||||
}
|
||||
|
||||
export function mangleField(fieldInfo: FieldInfo) {
|
||||
return "$" + escapeString(fieldInfo.classInfo.className + "_" + fieldInfo.name + "_" + fieldInfo.signature);
|
||||
}
|
||||
|
||||
function getRuntimeClass(classInfo: ClassInfo) {
|
||||
return new AST.MemberExpression(id("$"), id(mangleClass(classInfo)), false);
|
||||
|
@ -679,10 +615,10 @@ module J2ME.C4.Backend {
|
|||
IR.JVMGetField.prototype.compile = function (cx: Context): AST.Node {
|
||||
if (this.object) {
|
||||
var object = compileValue(this.object, cx);
|
||||
return new AST.MemberExpression(object, id(mangleField(this.fieldInfo)), false);
|
||||
return new AST.MemberExpression(object, id(this.fieldInfo.mangledName), false);
|
||||
} else {
|
||||
assert(this.fieldInfo.isStatic);
|
||||
return new AST.MemberExpression(getRuntimeClass(this.fieldInfo.classInfo), id(mangleField(this.fieldInfo)), false);
|
||||
return new AST.MemberExpression(getRuntimeClass(this.fieldInfo.classInfo), id(this.fieldInfo.mangledName), false);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -690,22 +626,24 @@ module J2ME.C4.Backend {
|
|||
var value = compileValue(this.value, cx);
|
||||
if (this.object) {
|
||||
var object = compileValue(this.object, cx);
|
||||
return assignment(new AST.MemberExpression(object, id(mangleField(this.fieldInfo)), false), value);
|
||||
return assignment(new AST.MemberExpression(object, id(this.fieldInfo.mangledName), false), value);
|
||||
} else {
|
||||
assert(this.fieldInfo.isStatic);
|
||||
return assignment(new AST.MemberExpression(getRuntimeClass(this.fieldInfo.classInfo), id(mangleField(this.fieldInfo)), false), value);
|
||||
return assignment(new AST.MemberExpression(getRuntimeClass(this.fieldInfo.classInfo), id(this.fieldInfo.mangledName), false), value);
|
||||
}
|
||||
};
|
||||
|
||||
IR.JVMNew.prototype.compile = function (cx: Context): AST.Node {
|
||||
var callee: AST.Node = id(mangleClass(this.classInfo));
|
||||
if (true) {
|
||||
var emitClassInitializationCheck = true;
|
||||
if (emitClassInitializationCheck) {
|
||||
callee = new AST.SequenceExpression([getRuntimeClass(this.classInfo), callee]);
|
||||
}
|
||||
return new AST.NewExpression(callee, []);
|
||||
};
|
||||
|
||||
IR.JVMThrow.prototype.compile = function (cx: Context): AST.Node {
|
||||
return new AST.ThrowStatement(constant(null));
|
||||
var object = compileValue(this.object, cx);
|
||||
return new AST.ThrowStatement(object);
|
||||
};
|
||||
}
|
||||
|
|
17
jsc.ts
17
jsc.ts
|
@ -55,7 +55,6 @@ jsGlobal.urlParams = {
|
|||
module J2ME {
|
||||
declare var load: (string) => void;
|
||||
declare var process, require, global, quit, help, scriptArgs, arguments, snarf;
|
||||
declare var JVM, Runtime, CLASSES, Context, release;
|
||||
|
||||
var isNode = typeof process === 'object';
|
||||
var writer: IndentingWriter;
|
||||
|
@ -179,7 +178,21 @@ module J2ME {
|
|||
if (verboseOption.value) {
|
||||
writer.writeLn("Compiling Pattern: " + classFilterOption.value);
|
||||
}
|
||||
compile(jvm, classFilterOption.value, fileFilterOption.value, debuggerOption.value, definitionOption.value);
|
||||
var classPattern;
|
||||
var file = snarf(classFilterOption.value, "text");
|
||||
if (file) {
|
||||
classPattern = file.split("\n");
|
||||
} else {
|
||||
classPattern = classFilterOption.value;
|
||||
}
|
||||
function classFilter(classInfo: ClassInfo): boolean {
|
||||
if (typeof classPattern === "string") {
|
||||
return !!classInfo.className.match(classFilterOption.value);
|
||||
} else {
|
||||
return classPattern.indexOf(classInfo.className) >= 0;
|
||||
}
|
||||
}
|
||||
compile(jvm, classFilter, fileFilterOption.value, debuggerOption.value, definitionOption.value);
|
||||
if (verboseOption.value) {
|
||||
printResults();
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ try {
|
|||
"string.js", "libs/console.js", "midp/midp.js",
|
||||
"libs/long.js", "midp/crypto.js", "libs/forge/md5.js", "libs/forge/util.js", "build/compiled.js");
|
||||
|
||||
var dump = print;
|
||||
var dump = putstr;
|
||||
var console = window.console;
|
||||
|
||||
CLASSES.addSourceDirectory("java/cldc1.1.1");
|
||||
|
|
187
runtime.ts
187
runtime.ts
|
@ -13,13 +13,9 @@ module J2ME {
|
|||
declare var VM;
|
||||
declare var Long;
|
||||
|
||||
|
||||
// If you want to enable trace logging, do so in context.ts.
|
||||
export var traceWriter = null;
|
||||
|
||||
export var linkingWriter = new IndentingWriter(false, function (s) {
|
||||
dumpLine(s);
|
||||
});
|
||||
export var linkWriter = null;
|
||||
export var initWriter = null;
|
||||
|
||||
export var Klasses = {
|
||||
java: {
|
||||
|
@ -122,6 +118,76 @@ module J2ME {
|
|||
Compiled
|
||||
}
|
||||
|
||||
function hashString(s: string) {
|
||||
var data = new Int32Array(s.length);
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
data[i] = s.charCodeAt(i);
|
||||
}
|
||||
return HashUtilities.hashBytesTo32BitsMD5(data, 0, s.length);
|
||||
}
|
||||
|
||||
var friendlyMangledNames = true;
|
||||
|
||||
export function escapeString(s: string) {
|
||||
var invalidChars = "[];/<>()";
|
||||
var replaceChars = "abc_defg";
|
||||
var result = "";
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
if ((i === 0 && isIdentifierStart(s[i])) || (i > 0 && isIdentifierPart(s[i]))) {
|
||||
result += s[i];
|
||||
} else {
|
||||
release || assert (invalidChars.indexOf(s[i]) >= 0, s[i] + " " + s);
|
||||
result += replaceChars[invalidChars.indexOf(s[i])];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function hashStringToString(s: string) {
|
||||
return StringUtilities.variableLengthEncodeInt32(hashString(s));
|
||||
}
|
||||
|
||||
export function mangleClassAndMethod(methodInfo: MethodInfo) {
|
||||
var name = methodInfo.classInfo.className + "_" + methodInfo.name + "_" + hashStringToString(methodInfo.signature);
|
||||
if (friendlyMangledNames) {
|
||||
return escapeString(name);
|
||||
}
|
||||
var hash = hashString(name);
|
||||
return StringUtilities.variableLengthEncodeInt32(hash);
|
||||
}
|
||||
|
||||
export function mangleMethod(methodInfo: MethodInfo) {
|
||||
var name = methodInfo.name + "_" + hashStringToString(methodInfo.signature);
|
||||
if (friendlyMangledNames) {
|
||||
return escapeString(name);
|
||||
}
|
||||
var hash = hashString(name);
|
||||
return StringUtilities.variableLengthEncodeInt32(hash);
|
||||
}
|
||||
|
||||
export function mangleClass(classInfo: ClassInfo) {
|
||||
if (classInfo instanceof PrimitiveArrayClassInfo) {
|
||||
switch (classInfo) {
|
||||
case PrimitiveArrayClassInfo.Z: return "Uint8Array";
|
||||
case PrimitiveArrayClassInfo.C: return "Uint16Array";
|
||||
case PrimitiveArrayClassInfo.F: return "Float32Array";
|
||||
case PrimitiveArrayClassInfo.D: return "Float64Array";
|
||||
case PrimitiveArrayClassInfo.B: return "Int8Array";
|
||||
case PrimitiveArrayClassInfo.S: return "Int16Array";
|
||||
case PrimitiveArrayClassInfo.I: return "Int32Array";
|
||||
case PrimitiveArrayClassInfo.J: return "Int64Array";
|
||||
}
|
||||
} else if (classInfo.isArrayClass) {
|
||||
return "$AK(" + mangleClass(classInfo.elementClass) + ")";
|
||||
} else {
|
||||
if (friendlyMangledNames) {
|
||||
return "$" + escapeString(classInfo.className);
|
||||
}
|
||||
var hash = hashString(classInfo.className);
|
||||
return "$" + StringUtilities.variableLengthEncodeInt32(hash);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is abstract and should never be initialized. It only acts as a template for
|
||||
* actual runtime objects.
|
||||
|
@ -220,8 +286,11 @@ module J2ME {
|
|||
}
|
||||
|
||||
export class Runtime extends RuntimeTemplate {
|
||||
private static _nextId: number = 0;
|
||||
id: number;
|
||||
constructor(jvm: JVM) {
|
||||
super(jvm);
|
||||
this.id = Runtime._nextId ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,11 +337,6 @@ module J2ME {
|
|||
|
||||
classSymbols: string [];
|
||||
|
||||
/**
|
||||
* Initializes static fields to their default values, not all klasses have one.
|
||||
*/
|
||||
staticInitializer: () => void;
|
||||
|
||||
/**
|
||||
* Static constructor, not all klasses have one.
|
||||
*/
|
||||
|
@ -366,7 +430,7 @@ module J2ME {
|
|||
}
|
||||
|
||||
function initializeClassObject(runtimeKlass: RuntimeKlass) {
|
||||
linkingWriter && linkingWriter.writeLn("Initializing Class Object For: " + runtimeKlass.templateKlass);
|
||||
linkWriter && linkWriter.writeLn("Initializing Class Object For: " + runtimeKlass.templateKlass);
|
||||
assert(!runtimeKlass.classObject);
|
||||
runtimeKlass.classObject = <java.lang.Class><any>runtimeKlass;
|
||||
// TODO: Make this look like a Class instance but don't change the __proto__
|
||||
|
@ -396,22 +460,23 @@ module J2ME {
|
|||
}
|
||||
}
|
||||
|
||||
export function registerRuntimeKlass(klass: Klass, classInfo: ClassInfo) {
|
||||
// Ensure each Runtime instance receives its own copy of the class
|
||||
// constructor, hoisted off the current runtime.
|
||||
linkingWriter && linkingWriter.writeLn("Registering Runtime Klass: " + classInfo.className + " as " + classInfo.mangledName);
|
||||
/**
|
||||
* Registers the klass as a getter on the runtime template. On first access, the getter creates a runtime klass and
|
||||
* adds it to the runtime.
|
||||
*/
|
||||
export function registerKlass(klass: Klass, classInfo: ClassInfo) {
|
||||
linkWriter && linkWriter.writeLn("Registering Klass: " + classInfo.className);
|
||||
Object.defineProperty(RuntimeTemplate.prototype, classInfo.mangledName, {
|
||||
configurable: true,
|
||||
get: function () {
|
||||
linkingWriter && linkingWriter.writeLn("Initializing Runtime Klass: " + classInfo.className);
|
||||
linkWriter && linkWriter.writeLn("Creating Runtime Klass: " + classInfo.className);
|
||||
assert(!(klass instanceof RuntimeKlass));
|
||||
var runtimeKlass = new RuntimeKlass(klass);
|
||||
initializeClassObject(runtimeKlass);
|
||||
// this[classInfo.mangledName] = runtimeKlass;
|
||||
Object.defineProperty(this, classInfo.mangledName, {
|
||||
value: runtimeKlass
|
||||
});
|
||||
linkingWriter && linkingWriter.writeLn("Running Static Initializer: " + classInfo.className);
|
||||
initWriter && initWriter.writeLn("Running Static Constructor: " + classInfo.className);
|
||||
$.ctx.pushClassInitFrame(classInfo);
|
||||
//// TODO: monitorEnter
|
||||
//if (klass.staticInitializer) {
|
||||
|
@ -425,21 +490,45 @@ module J2ME {
|
|||
});
|
||||
}
|
||||
|
||||
var unresolvedSymbols = Object.create(null);
|
||||
|
||||
function findKlass(classInfo: ClassInfo) {
|
||||
if (unresolvedSymbols[classInfo.mangledName]) {
|
||||
return null;
|
||||
}
|
||||
return jsGlobal[classInfo.mangledName];
|
||||
}
|
||||
|
||||
export function registerKlassSymbol(className: string) {
|
||||
linkingWriter && linkingWriter.writeLn("Registering Klass: " + className);
|
||||
linkWriter && linkWriter.writeLn("Registering Klass: " + className);
|
||||
// TODO: This needs to be kept in sync to how mangleClass works.
|
||||
var mangledName = "$" + J2ME.C4.Backend.escapeString(className);
|
||||
var mangledName = "$" + escapeString(className);
|
||||
if (RuntimeTemplate.prototype.hasOwnProperty(mangledName)) {
|
||||
return;
|
||||
}
|
||||
Object.defineProperty(RuntimeTemplate.prototype, mangledName, {
|
||||
configurable: true,
|
||||
get: function () {
|
||||
linkingWriter && linkingWriter.writeLn("Initializing Klass: " + className);
|
||||
CLASSES.getClass(className);
|
||||
return this[mangledName]; // This should not be recursive.
|
||||
}
|
||||
});
|
||||
|
||||
if (!RuntimeTemplate.prototype.hasOwnProperty(mangledName)) {
|
||||
Object.defineProperty(RuntimeTemplate.prototype, mangledName, {
|
||||
configurable: true,
|
||||
get: function lazyKlass() {
|
||||
linkWriter && linkWriter.writeLn("Initializing Klass: " + className);
|
||||
CLASSES.getClass(className);
|
||||
return this[mangledName]; // This should not be recursive at this point.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!jsGlobal.hasOwnProperty(mangledName)) {
|
||||
unresolvedSymbols[mangledName] = true;
|
||||
Object.defineProperty(jsGlobal, mangledName, {
|
||||
configurable: true,
|
||||
get: function () {
|
||||
linkWriter && linkWriter.writeLn("Initializing Klass: " + className);
|
||||
CLASSES.getClass(className);
|
||||
return this[mangledName]; // This should not be recursive at this point.
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function registerKlassSymbols(classNames: string []) {
|
||||
|
@ -464,9 +553,9 @@ module J2ME {
|
|||
if (classInfo.klass) {
|
||||
return classInfo.klass;
|
||||
}
|
||||
var klass = jsGlobal[classInfo.mangledName];
|
||||
var klass = findKlass(classInfo);
|
||||
if (klass) {
|
||||
linkingWriter && linkingWriter.greenLn("Found Compiled Klass: " + classInfo.className);
|
||||
linkWriter && linkWriter.greenLn("Found Compiled Klass: " + classInfo.className);
|
||||
release || assert(!classInfo.klass);
|
||||
classInfo.klass = klass;
|
||||
klass.toString = function () {
|
||||
|
@ -508,7 +597,7 @@ module J2ME {
|
|||
(1, eval)(source);
|
||||
// consoleWriter.writeLn("Synthesizing Klass: " + classInfo.className);
|
||||
// consoleWriter.writeLn(source);
|
||||
var mangledName = J2ME.C4.Backend.mangleClass(classInfo);
|
||||
var mangledName = mangleClass(classInfo);
|
||||
klass = jsGlobal[mangledName];
|
||||
assert(klass, mangledName);
|
||||
klass.toString = function () {
|
||||
|
@ -525,7 +614,7 @@ module J2ME {
|
|||
var superKlass = getKlass(classInfo.superClass);
|
||||
|
||||
extendKlass(klass, superKlass);
|
||||
registerRuntimeKlass(klass, classInfo);
|
||||
registerKlass(klass, classInfo);
|
||||
|
||||
if (!classInfo.isInterface) {
|
||||
initializeInterfaces(klass, classInfo);
|
||||
|
@ -535,7 +624,7 @@ module J2ME {
|
|||
}
|
||||
|
||||
export function linkKlass(classInfo: ClassInfo) {
|
||||
var mangledName = J2ME.C4.Backend.mangleClass(classInfo);
|
||||
var mangledName = mangleClass(classInfo);
|
||||
var klass;
|
||||
classInfo.klass = klass = getKlass(classInfo);
|
||||
classInfo.klass.classInfo = classInfo;
|
||||
|
@ -559,8 +648,7 @@ module J2ME {
|
|||
case "java/lang/Thread": Klasses.java.lang.Thread = klass; break;
|
||||
}
|
||||
}
|
||||
|
||||
linkingWriter && linkingWriter.writeLn("Link: " + classInfo.className + " -> " + klass);
|
||||
linkWriter && linkWriter.writeLn("Link: " + classInfo.className + " -> " + klass);
|
||||
|
||||
linkKlassMethods(classInfo.klass);
|
||||
}
|
||||
|
@ -630,7 +718,7 @@ module J2ME {
|
|||
}
|
||||
|
||||
function linkKlassMethods(klass: Klass) {
|
||||
linkingWriter && linkingWriter.enter("Link Klass Methods: " + klass);
|
||||
linkWriter && linkWriter.enter("Link Klass Methods: " + klass);
|
||||
var methods = klass.classInfo.methods;
|
||||
for (var i = 0; i < methods.length; i++) {
|
||||
var methodInfo = methods[i];
|
||||
|
@ -639,19 +727,19 @@ module J2ME {
|
|||
var nativeMethod = findNativeMethodImplementation(methods[i]);
|
||||
var methodDescription = methods[i].name + methods[i].signature;
|
||||
if (nativeMethod) {
|
||||
linkingWriter && linkingWriter.writeLn("Method: " + methodDescription + " -> Native / Override");
|
||||
linkWriter && linkWriter.writeLn("Method: " + methodDescription + " -> Native / Override");
|
||||
fn = nativeMethod;
|
||||
methodType = MethodType.Native;
|
||||
} else {
|
||||
fn = findCompiledMethod(klass, methodInfo);
|
||||
if (fn) {
|
||||
linkingWriter && linkingWriter.greenLn("Method: " + methodDescription + " -> Compiled");
|
||||
if (fn && !methodInfo.isSynchronized) {
|
||||
linkWriter && linkWriter.greenLn("Method: " + methodDescription + " -> Compiled");
|
||||
methodType = MethodType.Compiled;
|
||||
if (!traceWriter) {
|
||||
linkingWriter && linkingWriter.outdent();
|
||||
linkWriter && linkWriter.outdent();
|
||||
}
|
||||
} else {
|
||||
linkingWriter && linkingWriter.warnLn("Method: " + methodDescription + " -> Interpreter");
|
||||
linkWriter && linkWriter.warnLn("Method: " + methodDescription + " -> Interpreter");
|
||||
methodType = MethodType.Interpreted;
|
||||
fn = prepareInterpretedMethod(methodInfo);
|
||||
}
|
||||
|
@ -668,7 +756,7 @@ module J2ME {
|
|||
}
|
||||
}
|
||||
|
||||
linkingWriter && linkingWriter.outdent();
|
||||
linkWriter && linkWriter.outdent();
|
||||
|
||||
function tracingWrapper(fn: Function, methodInfo: MethodInfo, methodType: MethodType) {
|
||||
return function() {
|
||||
|
@ -724,7 +812,7 @@ module J2ME {
|
|||
klass.superKlass = superKlass;
|
||||
if (superKlass) {
|
||||
if (isPrototypeOfFunctionMutable(klass)) {
|
||||
linkingWriter && linkingWriter.writeLn("Extending: " + klass + " -> " + superKlass);
|
||||
linkWriter && linkWriter.writeLn("Extending: " + klass + " -> " + superKlass);
|
||||
klass.prototype = Object.create(superKlass.prototype);
|
||||
// (<any>Object).setPrototypeOf(klass.prototype, superKlass.prototype);
|
||||
assert((<any>Object).getPrototypeOf(klass.prototype) === superKlass.prototype);
|
||||
|
@ -824,6 +912,9 @@ module J2ME {
|
|||
(<any>array).klass = klass;
|
||||
return array;
|
||||
};
|
||||
klass.toString = function () {
|
||||
return "[Array of " + elementKlass + "]";
|
||||
};
|
||||
if (elementKlass === Klasses.java.lang.Object) {
|
||||
extendKlass(klass, Klasses.java.lang.Object);
|
||||
extendKlass(<ArrayKlass><any>Array, Klasses.java.lang.Object);
|
||||
|
@ -834,11 +925,11 @@ module J2ME {
|
|||
assert(!klass.prototype.hasOwnProperty("klass"));
|
||||
klass.prototype.klass = klass;
|
||||
extendKlass(klass, Klasses.java.lang.Object);
|
||||
klass.toString = function () {
|
||||
return "[Array of " + elementKlass + "]";
|
||||
};
|
||||
}
|
||||
klass.isArrayKlass = true;
|
||||
klass.toString = function () {
|
||||
return "[Array of " + elementKlass + "]";
|
||||
};
|
||||
elementKlass.arrayKlass = klass;
|
||||
klass.elementKlass = elementKlass;
|
||||
var className = elementKlass.classInfo.className;
|
||||
|
@ -847,7 +938,7 @@ module J2ME {
|
|||
className = "[" + className;
|
||||
klass.classInfo = CLASSES.getClass(className);
|
||||
|
||||
registerRuntimeKlass(klass, klass.classInfo);
|
||||
registerKlass(klass, klass.classInfo);
|
||||
return klass;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,14 @@ declare var Uint8ClampedArray: {
|
|||
|
||||
module J2ME {
|
||||
|
||||
export function isIdentifierStart(c) {
|
||||
return (c === '$') || (c === '_') || (c === '\\') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
export function isIdentifierPart(c) {
|
||||
return (c === '$') || (c === '_') || (c === '\\') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || ((c >= '0') && (c <= '9'));
|
||||
}
|
||||
|
||||
export enum CharacterCodes {
|
||||
_0 = 48,
|
||||
_1 = 49,
|
||||
|
|
Загрузка…
Ссылка в новой задаче