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:
Michael Bebenita 2014-12-12 15:00:34 -08:00
Родитель 873ad77ac2
Коммит 29b2f0e84f
11 изменённых файлов: 251 добавлений и 178 удалений

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

@ -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);
}

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

@ -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
Просмотреть файл

@ -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");

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

@ -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,