Moved most of the top level code generation in the compiler file, and lots of other smaller things.

This commit is contained in:
Michael Bebenita 2014-11-20 00:34:15 -08:00
Родитель 5e2712ca22
Коммит a6eeab5c39
10 изменённых файлов: 359 добавлений и 200 удалений

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

@ -11,6 +11,7 @@ var FieldInfo = (function() {
this.name = name;
this.signature = signature;
this.id = idgen++;
this.isStatic = ACCESS_FLAGS.isStatic(access_flags);
}
})();

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

@ -85,7 +85,6 @@ try {
start = dateNow();
var runtime = jvm.startIsolate0(scriptArgs[0], urlParams.args);
J2ME.printResults();
print("RUNNING TIME: " + (dateNow() - start));
} catch (x) {
print(x);

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

@ -1,7 +1,7 @@
module J2ME {
var debug = false;
var writer = new IndentingWriter(!debug);
var writer = null; // new IndentingWriter(true);
var consoleWriter = new IndentingWriter();
export var counter = new J2ME.Metrics.Counter(true);
@ -81,6 +81,7 @@ module J2ME {
classInfo: ClassInfo;
access_flags: any;
id: number;
isStatic: boolean;
}
export enum TAGS {
@ -153,6 +154,12 @@ module J2ME {
declare var Frame;
export class CompiledMethodInfo {
constructor(public args: string [], public body: string, public referencedClasses: ClassInfo []) {
// ...
}
}
function assertKind(kind: Kind, x: Node): Node {
assert(stackKind(x.kind) === stackKind(kind), "Got " + kindCharacter(stackKind(x.kind)) + " expected " + kindCharacter(stackKind(kind)));
return x;
@ -464,7 +471,7 @@ module J2ME {
return "\"" + s + "\"";
}
export function compileMethodInfo(methodInfo: MethodInfo, ctx: Context, target: CompilationTarget) {
export function compileMethodInfo(methodInfo: MethodInfo, ctx: Context, target: CompilationTarget): CompiledMethodInfo {
if (!methodInfo.code) {
counter.count("Cannot Compile: Method has no code.");
return;
@ -486,14 +493,15 @@ module J2ME {
var parameter = builder.parameters[i];
args.push(parameter.name);
}
var fnSource = compilation.body;
var body = compilation.body;
// consoleWriter.writeLn(fnSource);
fn = new Function(args.join(","), fnSource);
// var fn = new Function(args.join(","), body);
// consoleWriter.writeLn(fn.toString());
// debug && writer.writeLn(fn.toString());
counter.count("Compiled");
} catch (e) {
counter.count("Failed to Compile " + e);
// consoleWriter.writeLn(e);
// consoleWriter.writeLns(e.stack);
debug && Debug.warning("Failed to compile " + methodInfo.implKey + " " + e + " " + e.stack);
if (e.message.indexOf("Not Implemented ") === -1) {
@ -501,7 +509,7 @@ module J2ME {
}
}
return fn;
return new CompiledMethodInfo(args, body, builder.referencedClasses);
}
interface WorklistItem {
@ -588,16 +596,17 @@ module J2ME {
*/
blockMap: BlockMap;
ctxValue: IR.Parameter;
parameters: IR.Parameter [];
referencedClasses: ClassInfo [];
constructor(public methodInfo: MethodInfo, public ctx: Context, public target: CompilationTarget) {
// ...
this.peepholeOptimizer = new PeepholeOptimizer();
this.signatureDescriptor = SignatureDescriptor.makeSignatureDescriptor(methodInfo.signature);
this.methodReturnInfos = [];
this.parameters = [];
this.referencedClasses = [];
}
build(): C4.Backend.Compilation {
@ -605,16 +614,18 @@ module J2ME {
var methodInfo = this.methodInfo;
writer.enter("Compiling Method: " + methodInfo.name + " " + methodInfo.signature + " {");
writer.writeLn("Size: " + methodInfo.code.length);
writer && writer.enter("Compiling Method: " + methodInfo.name + " " + methodInfo.signature + " {");
writer && writer.writeLn("Size: " + methodInfo.code.length);
var blockMap = this.blockMap = new BlockMap(methodInfo);
blockMap.build();
debug && blockMap.trace(writer, true);
// consoleWriter.writeLn("Compiling Method: " + methodInfo.name + " " + methodInfo.signature + " {");
// blockMap.trace(consoleWriter, false);
var start = this.buildStart();
var dfg = this.buildGraph(start, start.entryState.clone());
debug && dfg.trace(writer);
writer && dfg.trace(writer);
enterTimeline("Build CFG");
var cfg = dfg.buildCFG();
@ -632,7 +643,7 @@ module J2ME {
cfg.scheduleEarly();
leaveTimeline();
debug && cfg.trace(writer);
writer && cfg.trace(writer);
enterTimeline("Verify IR");
cfg.verify();
@ -649,7 +660,7 @@ module J2ME {
Node.stopNumbering();
leaveTimeline();
writer.leave("}");
writer && writer.leave("}");
IR.Node.stopNumbering();
return result;
@ -668,15 +679,10 @@ module J2ME {
state.store.kind = Kind.Store;
var signatureDescriptor = this.signatureDescriptor;
writer.writeLn("SIG: " + signatureDescriptor);
writer && writer.writeLn("SIG: " + signatureDescriptor);
var typeDescriptors = signatureDescriptor.typeDescriptors;
assert (!this.ctxValue);
this.ctxValue = new IR.Parameter(start, 0, "$");
this.parameters.push(this.ctxValue);
var localIndex = 0;
var parameterIndex = 1;
if (!methodInfo.isStatic) {
@ -721,7 +727,7 @@ module J2ME {
}
this.blockStopInfos.forEach(function (stop: StopInfo) {
var target = stop.target;
writer.writeLn(String(target));
writer && writer.writeLn(String(target));
var region = target.region;
if (region) {
writer && writer.enter("Merging into region: " + region + " @ " + target.startBci + ", block " + target.blockID + " {");
@ -977,7 +983,7 @@ module J2ME {
}
genNewInstance(cpi: number) {
var classInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, false);
var classInfo = this.lookupClass(cpi);
var jvmNew = new IR.JVMNew(this.region, this.state.store, classInfo);
this.recordStore(jvmNew);
this.state.apush(jvmNew);
@ -992,7 +998,7 @@ module J2ME {
}
genNewObjectArray(cpi: number) {
var classInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, false);
var classInfo = this.lookupClass(cpi);
var length = this.state.ipop();
var result = new IR.JVMNewObjectArray(this.region, this.state.store, classInfo, length);
this.recordStore(result);
@ -1025,14 +1031,14 @@ module J2ME {
}
genCheckCast(cpi: Bytecodes) {
var classInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, false);
var classInfo = this.lookupClass(cpi);
var object = this.state.peek();
var checkCast = new IR.JVMCheckCast(this.region, this.state.store, object, classInfo);
this.recordStore(checkCast);
}
genInstanceOf(cpi: Bytecodes) {
var classInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, false);
var classInfo = this.lookupClass(cpi);
var object = this.state.apop();
var instanceOf = new IR.JVMInstanceOf(this.region, this.state.store, object, classInfo);
this.recordStore(instanceOf);
@ -1119,12 +1125,22 @@ module J2ME {
));
}
lookupClass(cpi: number): ClassInfo {
var classInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, false);
ArrayUtilities.pushUnique(this.referencedClasses, classInfo);
return classInfo;
}
lookupMethod(cpi: number, opcode: Bytecodes, isStatic: boolean): MethodInfo {
return this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, isStatic);
var methodInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, isStatic);
ArrayUtilities.pushUnique(this.referencedClasses, methodInfo.classInfo);
return methodInfo;
}
lookupField(cpi: number, opcode: Bytecodes, isStatic: boolean): FieldInfo {
return this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, isStatic);
var fieldInfo = this.ctx.resolve(this.methodInfo.classInfo.constant_pool, cpi, isStatic);
ArrayUtilities.pushUnique(this.referencedClasses, fieldInfo.classInfo);
return fieldInfo;
}
/**
@ -1154,7 +1170,6 @@ module J2ME {
}
genThrow(bci: number) {
// this.ctx.methodInfos[this.methodInfo.implKey] = this.methodInfo;
var _throw = new IR.JVMThrow(this.region, this.state.store);
this.recordStore(_throw);
this.methodReturnInfos.push(new ReturnInfo(
@ -1177,12 +1192,11 @@ module J2ME {
for (var i = types.length - 1; i > 0; i--) {
args.unshift(this.state.pop(types[i].kind));
}
args.unshift(this.ctxValue);
var object = null;
if (opcode !== Bytecodes.INVOKESTATIC) {
object = this.state.pop(Kind.Reference);
}
var call = new IR.JVMInvoke(this.region, this.state.store, opcode, object, methodInfo, args);
var call = new IR.JVMInvoke(this.region, this.state.store, this.state.clone(nextBCI), opcode, object, methodInfo, args);
this.recordStore(call);
if (types[0].kind !== Kind.Void) {
this.state.push(types[0].kind, call);
@ -1213,6 +1227,7 @@ module J2ME {
}
genClass(classInfo: ClassInfo): Value {
ArrayUtilities.pushUnique(this.referencedClasses, classInfo);
return new IR.JVMClass(classInfo);
}
@ -1235,7 +1250,7 @@ module J2ME {
processBytecode(stream: BytecodeStream, state: State) {
var cpi: number;
var opcode: Bytecodes = stream.currentBC();
writer.enter("State Before: " + Bytecodes[opcode].padRight(" ", 12) + " " + state.toString());
writer && writer.enter("State Before: " + Bytecodes[opcode].padRight(" ", 12) + " " + state.toString());
switch (opcode) {
case Bytecodes.NOP : break;
case Bytecodes.ACONST_NULL : state.apush(genConstant(null, Kind.Reference)); break;
@ -1457,8 +1472,8 @@ module J2ME {
default:
throw new Error("Not Implemented " + Bytecodes[opcode]);
}
writer.leave("State After: " + Bytecodes[opcode].padRight(" ", 12) + " " + state.toString());
writer.writeLn("");
writer && writer.leave("State After: " + Bytecodes[opcode].padRight(" ", 12) + " " + state.toString());
writer && writer.writeLn("");
}
}
}

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

@ -276,6 +276,9 @@ module J2ME.C4.AST {
if (value === null) {
return 'null';
}
if (value === undefined) {
return 'undefined';
}
if (typeof value === 'string') {
return escapeString(value);
}
@ -343,7 +346,7 @@ module J2ME.C4.AST {
super();
}
toSource(precedence: number) : string {
return "{\n" + nodesToSource(this.body, precedence) + "}";
return "{" + nodesToSource(this.body, precedence, "\n") + "}";
}
}
@ -352,12 +355,12 @@ module J2ME.C4.AST {
super();
}
toSource(precedence: number) : string {
return this.expression.toSource(Precedence.Sequence) + ";\n";
return this.expression.toSource(Precedence.Sequence) + ";";
}
}
export class IfStatement extends Statement {
constructor (public test: Expression, public consequent: Statement, public alternate: Statement) {
constructor (public test: Expression, public consequent: Statement, public alternate?: Statement) {
super();
}
toSource(precedence: number) : string {
@ -421,11 +424,11 @@ module J2ME.C4.AST {
super();
}
toSource(precedence: number) : string {
var result = "return ";
var result = "return";
if (this.argument) {
result += this.argument.toSource(Precedence.Sequence);
result += " " + this.argument.toSource(Precedence.Sequence);
}
return result + ";\n";
return result + ";";
}
}

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

@ -368,13 +368,18 @@ module J2ME.C4.Backend {
this.useVariable(node.to);
from = compileValue(node.from, this);
} else {
if (node.variable && !node.handlesAssignment) {
to = id(node.variable.name);
this.useVariable(node.variable);
} else {
to = null;
}
from = compileValue(node, this, true);
if (from instanceof AST.Statement) {
body.push(from);
continue;
} else {
if (node.variable) {
to = id(node.variable.name);
this.useVariable(node.variable);
} else {
to = null;
}
}
}
if (to) {
statement = new ExpressionStatement(assignment(to, from));

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

@ -265,7 +265,7 @@ module J2ME.C4.IR {
Store.prototype.nodeName = "Store";
export class StoreDependent extends Value {
loads: Node [];
public loads: Node [];
constructor(public control: Control, public store: Store) {
super();
}

240
opt/compiler.ts Normal file
Просмотреть файл

@ -0,0 +1,240 @@
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 JVM, Runtime, CLASSES, Context, release;
var consoleWriter = new IndentingWriter();
export class Emitter {
constructor(
public writer: IndentingWriter,
public closure: boolean,
public debugInfo: boolean
) {
// ...
}
}
function getClassInheritanceChain(classInfo: ClassInfo): ClassInfo [] {
var list = [];
var klass = classInfo;
while (klass) {
list.unshift(klass);
klass = klass.superClass;
}
return list;
}
function compileConstructor(emitter: Emitter, classInfo: ClassInfo) {
var writer = emitter.writer;
var mangledClassName = mangleClass(classInfo);
if (emitter.closure) {
writer.writeLn("/** @constructor */");
}
writer.enter("function " + mangledClassName + "() {");
getClassInheritanceChain(classInfo).forEach(function (klass) {
for (var i = 0; i < klass.fields.length; i++) {
var fieldInfo = klass.fields[i];
if (fieldInfo.isStatic) {
continue;
}
var signature = TypeDescriptor.makeTypeDescriptor(fieldInfo.signature);
var kind = signature.kind;
var defaultValue;
switch (kind) {
case Kind.Reference:
defaultValue = "null";
break;
case Kind.Long:
defaultValue = "Long.ZERO";
break;
default:
defaultValue = "0";
break;
}
if (emitter.closure) {
writer.writeLn("this[" + quote(mangleField(fieldInfo)) + "] = " + defaultValue + ";");
} else {
writer.writeLn("this." + mangleField(fieldInfo) + " = " + defaultValue + ";");
}
}
});
writer.leave("}");
if (emitter.closure) {
writer.writeLn("window[" + quote(mangledClassName) + "] = " + mangledClassName + ";");
}
if (classInfo.superClass) {
var mangledSuperClassName = mangleClass(classInfo.superClass);
writer.writeLn(mangledClassName + ".prototype = Object.create(" + mangledSuperClassName + ".prototype);");
}
}
function compileClassInfo(emitter: Emitter, classInfo: ClassInfo, ctx: Context): CompiledMethodInfo [] {
var writer = emitter.writer;
var mangledClassName = mangleClass(classInfo);
if (!J2ME.C4.Backend.isIdentifierName(mangledClassName)) {
mangledClassName = quote(mangledClassName);
}
compileConstructor(emitter, classInfo);
var methods = classInfo.methods;
var compiledMethods: CompiledMethodInfo [] = [];
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
var mangledMethodName = mangleMethod(method);
if (!J2ME.C4.Backend.isIdentifierName(mangledMethodName)) {
mangledMethodName = quote(mangledMethodName);
}
try {
if (emitter.debugInfo) {
writer.writeLn("// " + classInfo.className + "/" + method.name);
}
var mangledClassAndMethodName = mangleClassAndMethod(method);
var compiledMethod = compileMethodInfo(method, ctx, CompilationTarget.Static);
if (compiledMethod && compiledMethod.body) {
writer.enter("function " + mangledClassAndMethodName + "(" + compiledMethod.args.join(",") + ") {");
writer.writeLns(compiledMethod.body);
writer.leave("}");
if (emitter.closure) {
writer.writeLn(mangledClassName + ".prototype[" + quote(mangledMethodName) + "] = " + mangledClassAndMethodName + ";");
} else {
writer.writeLn(mangledClassName + ".prototype." + mangledMethodName + " = " + mangledClassAndMethodName + ";");
}
if (emitter.closure) {
writer.writeLn("window[" + quote(mangledClassAndMethodName) + "] = " + mangledClassAndMethodName + ";");
}
compiledMethods.push(compiledMethod);
}
} catch (x) {
consoleWriter.writeLn("XXXX: " + x);
}
}
return compiledMethods;
}
export function compile(jvm: any, classFilter: string, debugInfo: boolean) {
var runtime = new Runtime(jvm);
var classFiles = CLASSES.classfiles;
var ctx = new Context(runtime);
var code = "";
var writer = new J2ME.IndentingWriter(false, function (s) {
code += s + "\n";
});
var emitter = new Emitter(writer, false, debugInfo);
var compiledMethods: CompiledMethodInfo [] = [];
var classInfoList: ClassInfo [] = [];
Object.keys(classFiles).every(function (path) {
if (path.substr(-4) !== ".jar") {
return true;
}
var zipFile = classFiles[path];
Object.keys(zipFile.directory).every(function (fileName) {
if (fileName.substr(-6) !== '.class') {
return true;
}
var classInfo = CLASSES.loadClassFile(fileName);
if (!classInfo.className.match(classFilter)) {
return true;
}
classInfoList.push(classInfo);
return true;
}.bind(this));
return true;
}.bind(this));
var orderedClassInfoList: ClassInfo [] = [];
function indexOf(list, classInfo) {
if (!classInfo) {
return -1;
}
for (var i = 0; i < list.length; i++) {
if (list[i].className === classInfo.className) {
return i;
}
}
return -1;
}
while (classInfoList.length) {
for (var i = 0; i < classInfoList.length; i++) {
var classInfo = classInfoList[i];
// writer.writeLn(nameOf(classInfo) + " " + nameOf(classInfo.superClass) + " " + classInfoList.indexOf(classInfo.superClass));
if (indexOf(classInfoList, classInfo.superClass) < 0) {
orderedClassInfoList.push(classInfo);
classInfoList.splice(i--, 1);
break;
}
}
}
for (var i = 0; i < orderedClassInfoList.length; i++) {
var classInfo = orderedClassInfoList[i];
if (emitter.debugInfo) {
writer.writeLn("// " + classInfo.className + (classInfo.superClass ? " extends " + classInfo.superClass.className : ""));
}
ArrayUtilities.pushMany(compiledMethods, compileClassInfo(emitter, classInfo, ctx));
}
/*
writer.enter("referencedClasses: [");
var referencedClasses = Object.create(null);
compiledMethods.forEach(compiledMethod => {
compiledMethod.referencedClasses.forEach(classInfo => {
referencedClasses[classInfo.className] = true;
});
});
var classNames = Object.keys(referencedClasses);
for (var i = 0; i < classNames.length; i++) {
writer.writeLn(quote(classNames[i]) + (i < classNames.length - 1 ? "," : ""));
}
writer.leave("]");
*/
consoleWriter.writeLn(code);
}
}

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

@ -165,34 +165,8 @@ module J2ME.C4.IR {
}
}
export class JVMCallProperty extends StoreDependent {
constructor(control: Control, store: Store, public state: State, public object: Value, public name: Value, public args: Value [], public callerMethodInfoId: string, public objectCheck?: boolean) {
super(control, store);
this.handlesAssignment = true;
}
visitInputs(visitor: NodeVisitor) {
this.control && visitor(this.control);
this.store && visitor(this.store);
this.loads && visitArrayInputs(this.loads, visitor);
visitor(this.object);
visitor(this.name);
visitArrayInputs(this.args, visitor);
visitStateInputs(this.state.local, visitor);
visitStateInputs(this.state.stack, visitor);
}
replaceInput(oldInput: Node, newInput: Node) {
var count = super.replaceInput(oldInput, newInput);
count += (<any>this.state.local).replace(oldInput, newInput);
count += (<any>this.state.stack).replace(oldInput, newInput);
return count;
}
}
JVMCallProperty.prototype.nodeName = "JVMCallProperty";
export class JVMInvoke extends StoreDependent {
constructor(control: Control, store: Store, public opcode: J2ME.Bytecode.Bytecodes, public object: Value, public methodInfo: MethodInfo, public args: Value []) {
constructor(control: Control, store: Store, public state: State, public opcode: J2ME.Bytecode.Bytecodes, public object: Value, public methodInfo: MethodInfo, public args: Value []) {
super(control, store);
}
visitInputs(visitor: NodeVisitor) {
@ -201,6 +175,18 @@ module J2ME.C4.IR {
this.loads && visitArrayInputs(this.loads, visitor);
this.object && visitor(this.object);
visitArrayInputs(this.args, visitor);
if (this.state) {
visitStateInputs(this.state.local, visitor);
visitStateInputs(this.state.stack, visitor);
}
}
replaceInput(oldInput: Node, newInput: Node) {
var count = super.replaceInput(oldInput, newInput);
if (this.state) {
count += (<any>this.state.local).replace(oldInput, newInput);
count += (<any>this.state.stack).replace(oldInput, newInput);
}
return count;
}
}
@ -505,6 +491,7 @@ module J2ME.C4.Backend {
return compiledValues;
}
/*
IR.JVMCallProperty.prototype.compile = function (cx: Context): AST.Node {
var localValues = compileStateValues(cx, this.state.local);
@ -566,6 +553,7 @@ module J2ME.C4.Backend {
null
);
};
*/
IR.JVMInvoke.prototype.compile = function (cx: Context): AST.Node {
var object = this.object ? compileValue(this.object, cx) : null;
@ -573,19 +561,32 @@ module J2ME.C4.Backend {
return compileValue(arg, cx);
});
var callee = null;
var result = null;
if (object) {
if (this.opcode === J2ME.Bytecode.Bytecodes.INVOKESPECIAL) {
var classPrototype = property(id(mangleClass(this.methodInfo.classInfo)), "prototype");
var callee = property(classPrototype, mangleMethod(this.methodInfo));
return callCall(callee, object, args);
result = callCall(id(mangleClassAndMethod(this.methodInfo)), object, args);
} else {
callee = property(object, mangleMethod(this.methodInfo));
result = call(callee, args);
}
callee = property(object, mangleMethod(this.methodInfo));
} else {
release || assert (this.opcode === J2ME.Bytecode.Bytecodes.INVOKESTATIC);
callee = id(mangleMethod(this.methodInfo));
result = call(callee, args);
}
return call(callee, args);
if (false && this.state) {
var block = new AST.BlockStatement([]);
var to = id(this.variable.name);
cx.useVariable(this.variable);
block.body.push(new AST.ExpressionStatement(assignment(to, result)));
var ifYield = new AST.IfStatement(id("$Y"), new AST.BlockStatement([
new AST.ExpressionStatement(call(property(id("$"), "B"), [])),
new AST.ReturnStatement(undefined)
]));
block.body.push(ifYield);
return block;
}
return result;
};
function hashString(s: string) {
@ -613,11 +614,21 @@ module J2ME.C4.Backend {
return result;
}
export function mangleMethod(methodInfo: MethodInfo) {
export function mangleClassAndMethod(methodInfo: MethodInfo) {
var name = methodInfo.classInfo.className + methodInfo.name + methodInfo.signature;
if (friendlyMangledNames) {
return mangleString(methodInfo.name + methodInfo.signature);
return mangleString(name);
}
var hash = hashString(methodInfo.name + methodInfo.signature);
var hash = hashString(name);
return StringUtilities.variableLengthEncodeInt32(hash);
}
export function mangleMethod(methodInfo: MethodInfo) {
var name = methodInfo.name + methodInfo.signature;
if (friendlyMangledNames) {
return mangleString(name);
}
var hash = hashString(name);
return StringUtilities.variableLengthEncodeInt32(hash);
}

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

@ -11,4 +11,5 @@
///<reference path='jvm.ir.ts' />
///<reference path='types.ts' />
///<reference path='blockMap.ts' />
///<reference path='builder.ts' />
///<reference path='builder.ts' />
///<reference path='compiler.ts' />

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

@ -175,127 +175,11 @@ module J2ME {
if (verboseOption.value) {
writer.writeLn("Compiling Pattern: " + classFilterOption.value);
}
compile(jvm, classFilterOption.value);
compile(jvm, classFilterOption.value, debuggerOption.value);
}
jvm.initializeBuiltinClasses();
}
function getClassInheritanceChain(classInfo: ClassInfo): ClassInfo [] {
var list = [];
var klass = classInfo;
while (klass) {
list.unshift(klass);
klass = klass.superClass;
}
return list;
}
function compileClassInfo(codeWriter: IndentingWriter, classInfo: ClassInfo, ctx: Context) {
var mangledClassName = J2ME.C4.Backend.mangleClass(classInfo);
if (!J2ME.C4.Backend.isIdentifierName(mangledClassName)) {
mangledClassName = quote(mangledClassName);
}
codeWriter.enter(mangledClassName + ": {");
codeWriter.enter("initializer: function () {");
getClassInheritanceChain(classInfo).forEach(function (klass) {
if (debuggerOption.value) {
codeWriter.writeLn("// " + klass.className);
}
for (var i = 0; i < klass.fields.length; i++) {
var fieldInfo = klass.fields[i];
var signature = TypeDescriptor.makeTypeDescriptor(fieldInfo.signature);
var kind = signature.kind;
var defaultValue;
switch (kind) {
case Kind.Reference:
defaultValue = "null";
break;
case Kind.Long:
defaultValue = "Long.ZERO";
break;
default:
defaultValue = "0";
break;
}
codeWriter.writeLn("this." + J2ME.C4.Backend.mangleField(fieldInfo) + " = " + defaultValue + ";");
}
});
codeWriter.leave("},");
codeWriter.enter("methods: {");
var methods = classInfo.methods;
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
var mangledMethodName = J2ME.C4.Backend.mangleMethod(method);
if (!J2ME.C4.Backend.isIdentifierName(mangledMethodName)) {
mangledMethodName = quote(mangledMethodName);
}
try {
var fn = compileMethodInfo(method, ctx, CompilationTarget.Static);
if (fn) {
if (debuggerOption.value) {
codeWriter.writeLn("// " + method.name);
}
codeWriter.enter(mangledMethodName + ": ");
codeWriter.write(fn);
codeWriter.leave(",");
if (verboseOption.value) {
writer.write(fn);
}
}
} catch (x) {
codeWriter.writeLn(mangledMethodName + ": undefined,");
}
}
codeWriter.leave("}");
codeWriter.leave("},");
}
function compile(jvm: any, classFilter: string) {
var runtime = new Runtime(jvm);
var classFiles = CLASSES.classfiles;
var ctx = new Context(runtime);
var code = "";
var codeWriter = new J2ME.IndentingWriter(false, function (s) {
code += s + "\n";
});
codeWriter.enter("var CC = {");
Object.keys(classFiles).every(function (name) {
if (name.substr(-4) !== ".jar") {
return true;
}
var zip = classFiles[name];
// codeWriter.enter(J2ME.quote(name) + ": {");
Object.keys(zip.directory).every(function (fileName) {
if (fileName.substr(-6) !== '.class') {
return true;
}
if (!fileName.match(classFilter)) {
return true;
}
if (verboseOption.value) {
writer.writeLn("Compiling Class: " + fileName);
}
if (debuggerOption.value) {
codeWriter.writeLn("// " + fileName);
}
compileClassInfo(codeWriter, CLASSES.loadClassFile(fileName), ctx);
// codeWriter.leave("},");
return true;
}.bind(this));
// codeWriter.leave("},");
return true;
}.bind(this));
codeWriter.leave("}");
writer.writeLn(code);
if (verboseOption.value) {
J2ME.printResults();
}
}
var commandLineArguments: string [];
// Shell Entry Point
if (typeof help === "function") {