From fb7ceb0178040f64978d050094d169c8bc0930f3 Mon Sep 17 00:00:00 2001 From: Michael Bebenita Date: Mon, 15 Dec 2014 15:53:39 -0800 Subject: [PATCH] Prepare for JIT bailouts. --- jit/c4/backend.ts | 2 +- jit/compiler.ts | 5 +-- jit/jvm.ir.ts | 79 +++++++---------------------------------------- jsc.ts | 28 +++++++++++------ runtime.ts | 13 ++++++++ 5 files changed, 46 insertions(+), 81 deletions(-) diff --git a/jit/c4/backend.ts b/jit/c4/backend.ts index e75dd001..0d5bf4dd 100644 --- a/jit/c4/backend.ts +++ b/jit/c4/backend.ts @@ -410,7 +410,7 @@ module J2ME.C4.Backend { return array instanceof Array; } - function compileValues(values, cx: Context) { + export function compileValues(values, cx: Context) { release || assert (isArray(values)); return values.map(function (value) { return compileValue(value, cx); diff --git a/jit/compiler.ts b/jit/compiler.ts index 451c9753..5110a113 100644 --- a/jit/compiler.ts +++ b/jit/compiler.ts @@ -185,8 +185,9 @@ module J2ME { }); writer.leave("}"); - // Emit class static initializer if it has any static fields. - if (classInfo.fields.some(f => f.isStatic)) { + // Emit class static initializer if it has any static fields. We don't emit this for now + // since it probably doesn't pay off to emit code that only gets executed once. + if (false && classInfo.fields.some(f => f.isStatic)) { writer.enter(mangledClassName + ".staticInitializer = function() {"); emitFields(classInfo.fields, true); writer.leave("}"); diff --git a/jit/jvm.ir.ts b/jit/jvm.ir.ts index bbca873a..4556d943 100644 --- a/jit/jvm.ir.ts +++ b/jit/jvm.ir.ts @@ -489,7 +489,7 @@ module J2ME.C4.Backend { throw "Unimplemented conversion"; } - function compileStateValues(cx: Context, values: IR.Value []): AST.Node [] { + function compileStateValues(values: IR.Value [], cx: Context): AST.Node { var compiledValues = []; for (var i = 0; i < values.length; i++) { if (values[i] === null) { @@ -502,72 +502,14 @@ module J2ME.C4.Backend { } } } - return compiledValues; + return new AST.ArrayExpression(compiledValues); } - /* - IR.JVMCallProperty.prototype.compile = function (cx: Context): AST.Node { - - var localValues = compileStateValues(cx, this.state.local); - var stackValues = compileStateValues(cx, this.state.stack); - var object = compileValue(this.object, cx); - var name = compileValue(this.name, cx); - var callee = property(object, name); - var args = this.args.map(function (arg) { - return compileValue(arg, cx); - }); - - var objCheck = null; - if (this.objectCheck) { - var vmc = new AST.MemberExpression(object, new AST.Identifier("class"), false); - objCheck = new AST.IfStatement(new AST.UnaryExpression("!", true, new AST.BinaryExpression("in", name, vmc)), - new AST.ExpressionStatement( - new AST.CallExpression(new AST.Identifier("J2ME.buildCompiledCall"), [ - vmc, - name, - new AST.CallExpression(new AST.Identifier("CLASSES.getMethod"), [ - new AST.MemberExpression(object, new AST.Identifier("class"), false), name])])), - null); - callee = property(vmc, name); - } - - var callNode = call(callee, args); - - var exception = new AST.Identifier("e"); - - var body = []; - if (objCheck) { - body.push(objCheck); - } - if (this.variable) { - body.push(assignment(id(this.variable.name), callNode)); - cx.useVariable(this.variable); - } else { - body.push(callNode); - } - - // body.push(assignment(to, callNode)); - - return new AST.TryStatement( - new AST.BlockStatement(body), - new AST.CatchClause(exception, null, - new AST.BlockStatement([ // Ask mbx: is it bug I need ExpressionStatement here to get the semicolon inserted. - new AST.ExpressionStatement(new AST.CallExpression(new AST.Identifier("ctx.JVMBailout"), [ - exception, - new AST.Literal(this.callerMethodInfoId), - new AST.Identifier("compiledDepth"), - new AST.Literal(this.state.bci), - new AST.ArrayExpression(localValues), - new AST.ArrayExpression(stackValues) - ])), - new AST.ThrowStatement(exception) - ]) - ), - [], - null - ); - }; - */ + function compileState(state: State, cx: Context): AST.Node [] { + var local = compileStateValues(state.local, cx); + var stack = compileStateValues(state.stack, cx); + return [new AST.Literal(state.bci), local, stack]; + } IR.JVMInvoke.prototype.compile = function (cx: Context): AST.Node { var object = this.object ? compileValue(this.object, cx) : null; @@ -592,13 +534,14 @@ module J2ME.C4.Backend { } result = call(callee, args); } - if (false && this.state) { + + if (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"), [])), + var ifYield = new AST.IfStatement(property(id("$"), "Y"), new AST.BlockStatement([ + new AST.ExpressionStatement(call(property(id("$"), "B"), compileState(this.state, cx))), new AST.ReturnStatement(undefined) ])); block.body.push(ifYield); diff --git a/jsc.ts b/jsc.ts index 05079d30..14599485 100644 --- a/jsc.ts +++ b/jsc.ts @@ -80,6 +80,7 @@ module J2ME { var verboseOption: Options.Option; var classpathOption: Options.Option; var callGraphOption: Options.Option; + var classFileFilterOption: Options.Option; var classFilterOption: Options.Option; var fileFilterOption: Options.Option; var debuggerOption: Options.Option; @@ -96,6 +97,7 @@ module J2ME { callGraphOption = shellOptions.register(new Options.Option("cg", "callGraph", "string []", [], "Call Grpah Files")); + classFileFilterOption = shellOptions.register(new Options.Option("cff", "classFileFilter", "string", "", "Compile Class File Filter")); classFilterOption = shellOptions.register(new Options.Option("cf", "classFilter", "string", ".*", "Compile Class Filter")); fileFilterOption = shellOptions.register(new Options.Option("ff", "fileFilter", "string", ".*", "Compile File Filter")); debuggerOption = shellOptions.register(new Options.Option("d", "debugger", "boolean", false, "Emit Debug Information")); @@ -176,21 +178,27 @@ module J2ME { } CLASSES.initializeBuiltinClasses(); if (verboseOption.value) { - writer.writeLn("Compiling Pattern: " + classFilterOption.value); + writer.writeLn("Compiling Pattern: " + classFilterOption.value + " " + classFileFilterOption.value); } - var classPattern; - var file = snarf(classFilterOption.value, "text"); - if (file) { - classPattern = file.split("\n"); - } else { - classPattern = classFilterOption.value; + var classNameList; + if (classFileFilterOption.value) { + var file; + try { + file = snarf(classFileFilterOption.value, "text"); + } catch (e) { + + } + if (file) { + classNameList = file.split("\n"); + } } function classFilter(classInfo: ClassInfo): boolean { - if (typeof classPattern === "string") { + if (classNameList) { + return classNameList.indexOf(classInfo.className) >= 0; + } else if (classFilterOption.value) { return !!classInfo.className.match(classFilterOption.value); - } else { - return classPattern.indexOf(classInfo.className) >= 0; } + return false; } compile(jvm, classFilter, fileFilterOption.value, debuggerOption.value, definitionOption.value); if (verboseOption.value) { diff --git a/runtime.ts b/runtime.ts index a5dcd8f1..28545dca 100644 --- a/runtime.ts +++ b/runtime.ts @@ -288,6 +288,19 @@ module J2ME { export class Runtime extends RuntimeTemplate { private static _nextId: number = 0; id: number; + + /** + * Are we currently unwinding the stack because of a Yield? + */ + Y: boolean = false; + + /** + * Bailout callback whenever a JIT frame is unwound. + */ + B(bci: number, local: any [], stack: any []) { + + } + constructor(jvm: JVM) { super(jvm); this.id = Runtime._nextId ++;