Remove code duplication when reporting syntax errors in NodeTransformer, ToekStream, IRFactory and Parser and add a method to create FunctionNode to Interpreter/Codegen to remove the need to have OptIRFactory.

This commit is contained in:
igor%mir2.org 2003-02-16 20:28:56 +00:00
parent 9ad003b9a0
commit 19e12f45e4
12 changed files with 158 additions and 179 deletions

View File

@ -845,9 +845,10 @@ public class Context {
setErrorReporter(new DefaultErrorReporter());
boolean errorseen = false;
Interpreter compiler = new Interpreter();
IRFactory irf = compiler.createIRFactory(this, ts);
Parser p = createParser(irf);
try {
IRFactory irf = new IRFactory(ts, null);
Parser p = createParser(irf);
p.parse(ts);
} catch (IOException ioe) {
errorseen = true;
@ -1999,13 +2000,13 @@ public class Context {
Interpreter compiler = createCompiler();
errorCount = 0;
IRFactory irf = compiler.createIRFactory(this, ts, scope);
IRFactory irf = compiler.createIRFactory(this, ts);
Parser p = createParser(irf);
Node tree = (Node) p.parse(ts);
if (tree == null)
return null;
tree = compiler.transform(tree, ts, scope);
tree = compiler.transform(this, irf, tree);
if (printTrees) { System.out.println(tree.toStringTree()); }
@ -2024,7 +2025,7 @@ public class Context {
}
Object result = compiler.compile(this, scope, tree,
securityDomain, securityController);
securityController, securityDomain);
return errorCount == 0 ? result : null;
}

View File

@ -40,8 +40,8 @@ import java.util.*;
public class FunctionNode extends Node {
public FunctionNode(String name, Node statements) {
super(TokenStream.FUNCTION, statements);
public FunctionNode(String name) {
super(TokenStream.FUNCTION);
functionName = name;
}

View File

@ -44,9 +44,9 @@ package org.mozilla.javascript;
*/
public class IRFactory {
public IRFactory(TokenStream ts, Scriptable scope) {
public IRFactory(Interpreter compiler, TokenStream ts) {
this.compiler = compiler;
this.ts = ts;
this.scope = scope;
}
/**
@ -72,7 +72,7 @@ public class IRFactory {
* Leaf
*/
public Object createLeaf(int nodeType) {
return new Node(nodeType);
return new Node(nodeType);
}
public Object createLeaf(int nodeType, int nodeOp) {
@ -202,23 +202,19 @@ public class IRFactory {
return new Node(TokenStream.BLOCK, lineno);
}
public Object createFunctionNode(String name, Object statements)
{
return new FunctionNode(name, (Node) statements);
}
public Object createFunction(String name, VariableTable vars,
Object statements,
String sourceName, int baseLineno,
int endLineno, Object source,
int endLineno, String source,
int functionType)
{
if (name == null) {
name = "";
}
FunctionNode f = (FunctionNode) createFunctionNode(name, statements);
FunctionNode f = compiler.createFunctionNode(this, name);
f.itsVariableTable = vars;
f.setFunctionType(functionType);
f.addChildToBack((Node)statements);
f.putProp(Node.SOURCENAME_PROP, sourceName);
f.putIntProp(Node.BASE_LINENO_PROP, baseLineno);
f.putIntProp(Node.END_LINENO_PROP, endLineno);
@ -341,13 +337,13 @@ public class IRFactory {
*/
Node lastChild = lhsNode.getLastChild();
if (lhsNode.getFirstChild() != lastChild) {
reportError("msg.mult.index");
ts.reportCurrentLineError("msg.mult.index", null);
}
lvalue = Node.newString(TokenStream.NAME, lastChild.getString());
break;
default:
reportError("msg.bad.for.in.lhs");
ts.reportCurrentLineError("msg.bad.for.in.lhs", null);
return objNode;
}
@ -845,7 +841,7 @@ public class IRFactory {
default:
// TODO: This should be a ReferenceError--but that's a runtime
// exception. Should we compile an exception into the code?
reportError("msg.bad.lhs.assign");
ts.reportCurrentLineError("msg.bad.lhs.assign", null);
return left;
}
}
@ -1014,28 +1010,12 @@ public class IRFactory {
return result;
}
private void reportError(String msgResource) {
private Interpreter compiler;
if (scope != null)
throw NativeGlobal.constructError(
Context.getContext(), "SyntaxError",
ScriptRuntime.getMessage0(msgResource),
scope, ts.getSourceName(), ts.getLineno(),
ts.getOffset(), ts.getLine());
else {
String message = Context.getMessage0(msgResource);
Context.reportError(message, ts.getSourceName(), ts.getLineno(),
ts.getLine(), ts.getOffset());
}
}
// Only needed to get file/line information. Could create an interface
// Only needed to call reportSyntaxError. Could create an interface
// that TokenStream implements if we want to make the connection less
// direct.
private TokenStream ts;
// Only needed to pass to the Erorr exception constructors
private Scriptable scope;
TokenStream ts;
private static final int LOOP_DO_WHILE = 0;
private static final int LOOP_WHILE = 1;

View File

@ -60,19 +60,25 @@ public class Interpreter {
// Last icode
END_ICODE = TokenStream.LAST_TOKEN + 6;
public IRFactory createIRFactory(Context cx, TokenStream ts,
Scriptable scope)
public IRFactory createIRFactory(Context cx, TokenStream ts)
{
return new IRFactory(ts, scope);
return new IRFactory(this, ts);
}
public Node transform(Node tree, TokenStream ts, Scriptable scope) {
return (new NodeTransformer()).transform(tree, null, ts, scope);
public FunctionNode createFunctionNode(IRFactory irFactory, String name)
{
return new FunctionNode(name);
}
public Object compile(Context cx, Scriptable scope, Node tree,
Object securityDomain,
SecurityController securityController)
public Node transform(Context cx, IRFactory irFactory, Node tree)
{
tree = (new NodeTransformer(irFactory)).transform(tree, null);
return tree;
}
public Object
compile(Context cx, Scriptable scope, Node tree,
SecurityController securityController, Object securityDomain)
{
version = cx.getLanguageVersion();
itsData = new InterpreterData(securityDomain);

View File

@ -46,35 +46,28 @@ package org.mozilla.javascript;
public class NodeTransformer {
public NodeTransformer(IRFactory irFactory) {
this.irFactory = irFactory;
}
/**
* Return new instance of this class. So that derived classes
* can override methods of the transformer.
*/
public NodeTransformer newInstance() {
return new NodeTransformer();
return new NodeTransformer(irFactory);
}
public IRFactory createIRFactory(TokenStream ts, Scriptable scope) {
return new IRFactory(ts, scope);
}
public Node transform(Node tree, Node enclosing, TokenStream ts,
Scriptable scope)
public Node transform(Node tree, Node enclosing)
{
loops = new ObjArray();
loopEnds = new ObjArray();
inFunction = tree.getType() == TokenStream.FUNCTION;
VariableTable vars;
if (!inFunction) {
vars = (VariableTable)tree.getProp(Node.VARS_PROP);
checkVariables(tree, vars);
} else {
FunctionNode fnNode = (FunctionNode)tree;
vars = fnNode.getVariableTable();
checkVariables(tree, vars);
fnNode.markVariableTableReady();
VariableTable vars = getVariableTable(tree);
checkVariables(tree, vars);
if (inFunction) {
((FunctionNode)tree).markVariableTableReady();
}
irFactory = createIRFactory(ts, scope);
// to save against upchecks if no finally blocks are used.
boolean hasFinally = false;
@ -112,8 +105,7 @@ public class NodeTransformer {
fnNode.setCheckThis(true);
}
NodeTransformer inner = newInstance();
fnNode = (FunctionNode)
inner.transform(fnNode, tree, ts, scope);
fnNode = (FunctionNode)inner.transform(fnNode, tree);
node.putProp(Node.FUNCTION_PROP, fnNode);
ObjArray fns = (ObjArray) tree.getProp(Node.FUNCTION_PROP);
if (fns == null) {
@ -136,10 +128,9 @@ public class NodeTransformer {
if (n.getType() == TokenStream.LABEL) {
String otherId = (String)n.getProp(Node.LABEL_PROP);
if (id.equals(otherId)) {
String message = Context.getMessage1(
"msg.dup.label", id);
reportMessage(Context.getContext(), message, node,
tree, true, scope);
Object[] messageArgs = { id };
reportError("msg.dup.label", messageArgs,
node, tree);
break typeswitch;
}
}
@ -336,25 +327,22 @@ public class NodeTransformer {
? null
: (Node) loop.getProp(propType);
if (loop == null || target == null) {
String message;
String messageId;
Object[] messageArgs = null;
if (!labelled) {
// didn't find an appropriate target
if (type == TokenStream.CONTINUE) {
message = Context.getMessage
("msg.continue.outside", null);
messageId = "msg.continue.outside";
} else {
message = Context.getMessage
("msg.bad.break", null);
messageId = "msg.bad.break";
}
} else if (loop != null) {
message = Context.getMessage0("msg.continue.nonloop");
messageId = "msg.continue.nonloop";
} else {
Object[] errArgs = { id };
message = Context.getMessage
("msg.undef.label", errArgs);
messageArgs = new Object[] { id };
messageId = "msg.undef.label";
}
reportMessage(Context.getContext(), message, node,
tree, true, scope);
reportError(messageId, messageArgs, node, tree);
node.setType(TokenStream.NOP);
break;
}
@ -457,8 +445,7 @@ public class NodeTransformer {
Context cx = Context.getCurrentContext();
if ((cx != null && cx.isActivationNeeded(name)) ||
(name.equals("length") &&
Context.getContext().getLanguageVersion() ==
Context.VERSION_1_2))
cx.getLanguageVersion() == Context.VERSION_1_2))
{
// Use of "arguments" or "length" in 1.2 requires
// an activation object.
@ -657,24 +644,13 @@ public class NodeTransformer {
}
}
protected void reportMessage(Context cx, String msg, Node stmt,
Node tree, boolean isError,
Scriptable scope)
private void
reportError(String messageId, Object[] messageArgs, Node stmt, Node tree)
{
int lineno = stmt.getLineno();
Object prop = tree == null
? null
: tree.getProp(Node.SOURCENAME_PROP);
if (isError) {
if (scope != null)
throw NativeGlobal.constructError(
cx, "SyntaxError", msg, scope,
(String) prop, lineno, 0, null);
else
cx.reportError(msg, (String) prop, lineno, null, 0);
}
else
cx.reportWarning(msg, (String) prop, lineno, null, 0);
String sourceName = (String)tree.getProp(Node.SOURCENAME_PROP);
irFactory.ts.reportSyntaxError(true, messageId, messageArgs,
sourceName, lineno, null, 0);
}
protected ObjArray loops;

View File

@ -65,7 +65,7 @@ class Parser {
}
private void mustMatchToken(TokenStream ts, int toMatch, String messageId)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
if ((tt = ts.getToken()) != toMatch) {
@ -75,17 +75,14 @@ class Parser {
}
private void reportError(TokenStream ts, String messageId)
throws JavaScriptException
throws ParserException
{
this.ok = false;
ts.reportSyntaxError(messageId, null);
ts.reportCurrentLineError(messageId, null);
/* Throw an exception to unwind the recursive descent parse.
* We use JavaScriptException here even though it is really
* a different use of the exception than it is usually used
* for.
*/
throw new JavaScriptException(messageId);
// Throw a ParserException exception to unwind the recursive descent
// parse.
throw new ParserException();
}
/*
@ -129,7 +126,7 @@ class Parser {
if (tt == ts.FUNCTION) {
try {
n = function(ts, FunctionNode.FUNCTION_STATEMENT);
} catch (JavaScriptException e) {
} catch (ParserException e) {
this.ok = false;
break;
}
@ -179,7 +176,7 @@ class Parser {
}
nf.addChildToBack(pn, n);
}
} catch (JavaScriptException e) {
} catch (ParserException e) {
this.ok = false;
} finally {
// also in finally block:
@ -192,7 +189,7 @@ class Parser {
}
private Object function(TokenStream ts, int functionType)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int baseLineno = ts.getLineno(); // line number where source starts
@ -266,7 +263,7 @@ class Parser {
String s = ts.getString();
if (new_vars.hasVariable(s)) {
Object[] msgArgs = { s };
ts.reportSyntaxWarning("msg.dup.parms", msgArgs);
ts.reportCurrentLineWarning("msg.dup.parms", msgArgs);
}
new_vars.addParameter(s);
sourceAddString(ts.NAME, s);
@ -345,7 +342,7 @@ class Parser {
}
private Object condition(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn;
mustMatchToken(ts, ts.LP, "msg.no.paren.cond");
@ -360,7 +357,7 @@ class Parser {
}
private void checkWellTerminated(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt = ts.peekTokenSameLine();
switch (tt) {
@ -385,7 +382,7 @@ class Parser {
}
private void checkWellTerminatedFunction(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
if (languageVersion < Context.VERSION_1_2) {
// See comments in checkWellTerminated
@ -396,7 +393,7 @@ class Parser {
// match a NAME; return null if no match.
private String matchLabel(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int lineno = ts.getLineno();
@ -419,7 +416,7 @@ class Parser {
{
try {
return statementHelper(ts);
} catch (JavaScriptException e) {
} catch (ParserException e) {
// skip to end of statement
int lineno = ts.getLineno();
int t;
@ -437,7 +434,7 @@ class Parser {
*/
private Object statementHelper(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = null;
@ -868,7 +865,7 @@ class Parser {
}
private Object variables(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = nf.createVariables(ts.getLineno());
boolean first = true;
@ -909,7 +906,7 @@ class Parser {
}
private Object expr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = assignExpr(ts, inForInit);
while (ts.matchToken(ts.COMMA)) {
@ -920,7 +917,7 @@ class Parser {
}
private Object assignExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = condExpr(ts, inForInit);
@ -936,7 +933,7 @@ class Parser {
}
private Object condExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object ifTrue;
Object ifFalse;
@ -956,7 +953,7 @@ class Parser {
}
private Object orExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = andExpr(ts, inForInit);
if (ts.matchToken(ts.OR)) {
@ -968,7 +965,7 @@ class Parser {
}
private Object andExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = bitOrExpr(ts, inForInit);
if (ts.matchToken(ts.AND)) {
@ -980,7 +977,7 @@ class Parser {
}
private Object bitOrExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = bitXorExpr(ts, inForInit);
while (ts.matchToken(ts.BITOR)) {
@ -991,7 +988,7 @@ class Parser {
}
private Object bitXorExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = bitAndExpr(ts, inForInit);
while (ts.matchToken(ts.BITXOR)) {
@ -1002,7 +999,7 @@ class Parser {
}
private Object bitAndExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = eqExpr(ts, inForInit);
while (ts.matchToken(ts.BITAND)) {
@ -1013,7 +1010,7 @@ class Parser {
}
private Object eqExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = relExpr(ts, inForInit);
while (ts.matchToken(ts.EQOP)) {
@ -1026,7 +1023,7 @@ class Parser {
}
private Object relExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = shiftExpr(ts);
while (ts.matchToken(ts.RELOP)) {
@ -1043,7 +1040,7 @@ class Parser {
}
private Object shiftExpr(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
Object pn = addExpr(ts);
while (ts.matchToken(ts.SHOP)) {
@ -1055,7 +1052,7 @@ class Parser {
}
private Object addExpr(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
Object pn = mulExpr(ts);
@ -1071,7 +1068,7 @@ class Parser {
}
private Object mulExpr(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
@ -1090,7 +1087,7 @@ class Parser {
}
private Object unaryExpr(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
@ -1153,7 +1150,7 @@ class Parser {
}
private Object argumentList(TokenStream ts, Object listNode)
throws IOException, JavaScriptException
throws IOException, ParserException
{
boolean matched;
ts.flags |= ts.TSF_REGEXP;
@ -1175,7 +1172,7 @@ class Parser {
}
private Object memberExpr(TokenStream ts, boolean allowCallSyntax)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
@ -1222,7 +1219,7 @@ class Parser {
private Object memberExprTail(TokenStream ts, boolean allowCallSyntax,
Object pn)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
while ((tt = ts.getToken()) > ts.EOF) {
@ -1261,7 +1258,7 @@ class Parser {
}
private Object primaryExpr(TokenStream ts)
throws IOException, JavaScriptException
throws IOException, ParserException
{
int tt;
@ -2298,3 +2295,6 @@ class Parser {
}
// Exception to unwind
class ParserException extends Exception { }

View File

@ -46,8 +46,10 @@ import java.io.StringWriter;
public class Block {
public Block(int startNodeIndex, int endNodeIndex, Node[] statementNodes)
public Block(IRFactory irFactory, int startNodeIndex, int endNodeIndex,
Node[] statementNodes)
{
itsIRFactory = irFactory;
itsStartNodeIndex = startNodeIndex;
itsEndNodeIndex = endNodeIndex;
itsStatementNodes = statementNodes;
@ -61,7 +63,8 @@ public class Block {
public Block[] getPredecessorList() { return itsPredecessors; }
public Block[] getSuccessorList() { return itsSuccessors; }
public static Block[] buildBlocks(Node[] statementNodes)
public static Block[]
buildBlocks(IRFactory irFactory, Node[] statementNodes)
{
// a mapping from each target node to the block it begins
Hashtable theTargetBlocks = new Hashtable();
@ -75,8 +78,9 @@ public class Block {
case TokenStream.TARGET :
{
if (i != beginNodeIndex) {
FatBlock fb = new FatBlock(beginNodeIndex,
i - 1, statementNodes);
FatBlock fb = new FatBlock(irFactory,
beginNodeIndex, i - 1,
statementNodes);
if (statementNodes[beginNodeIndex].getType()
== TokenStream.TARGET)
theTargetBlocks.put(statementNodes[beginNodeIndex], fb);
@ -90,8 +94,9 @@ public class Block {
case TokenStream.IFEQ :
case TokenStream.GOTO :
{
FatBlock fb = new FatBlock(beginNodeIndex,
i, statementNodes);
FatBlock fb = new FatBlock(irFactory,
beginNodeIndex, i,
statementNodes);
if (statementNodes[beginNodeIndex].getType()
== TokenStream.TARGET)
theTargetBlocks.put(statementNodes[beginNodeIndex], fb);
@ -104,9 +109,10 @@ public class Block {
}
if ((beginNodeIndex != statementNodes.length)) {
FatBlock fb = new FatBlock(beginNodeIndex,
statementNodes.length - 1,
statementNodes);
FatBlock fb = new FatBlock(irFactory,
beginNodeIndex,
statementNodes.length - 1,
statementNodes);
if (statementNodes[beginNodeIndex].getType() == TokenStream.TARGET)
theTargetBlocks.put(statementNodes[beginNodeIndex], fb);
theBlocks.add(fb);
@ -607,11 +613,8 @@ public class Block {
}
}
private IRFactory itsIRFactory;
Hashtable localCSE(Hashtable theCSETable, OptFunctionNode theFunction)
{
itsIRFactory = new IRFactory(null, null);
if (theCSETable == null) theCSETable = new Hashtable(5);
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
Node n = itsStatementNodes[i];
@ -666,6 +669,8 @@ public class Block {
public void setSuccessorList(Block[] b) { itsSuccessors = b; }
public void setPredecessorList(Block[] b) { itsPredecessors = b; }
private IRFactory itsIRFactory;
// all the Blocks that come immediately after this
private Block[] itsSuccessors;
// all the Blocks that come immediately before this

View File

@ -53,38 +53,46 @@ import java.lang.reflect.Constructor;
public class Codegen extends Interpreter {
public Codegen() {
}
public Codegen() { }
private Codegen(Codegen parent) {
private Codegen(Codegen parent)
{
this.nameHelper = parent.nameHelper;
this.classNames = parent.classNames;
}
public IRFactory createIRFactory(Context cx, TokenStream ts,
Scriptable scope)
public IRFactory createIRFactory(Context cx, TokenStream ts)
{
if (nameHelper == null) {
nameHelper = (OptClassNameHelper)ClassNameHelper.get(cx);
classNames = new ObjToIntMap();
}
return new OptIRFactory(ts, scope, this);
return new IRFactory(this, ts);
}
public Node transform(Node tree, TokenStream ts, Scriptable scope) {
OptTransformer opt = new OptTransformer(new Hashtable(11));
return opt.transform(tree, null, ts, scope);
public FunctionNode createFunctionNode(IRFactory irFactory, String name)
{
String className = getScriptClassName(name, false);
return new OptFunctionNode(name, className);
}
public Object compile(Context cx, Scriptable scope, Node tree,
Object securityDomain,
SecurityController securityController)
public Node transform(Context cx, IRFactory irFactory, Node tree)
{
int optimizationLevel = cx.getOptimizationLevel();
OptTransformer opt = new OptTransformer(irFactory, new Hashtable(11));
tree = opt.transform(tree, null);
if (optimizationLevel > 0) {
(new Optimizer(irFactory)).optimize(tree, optimizationLevel);
}
return tree;
}
public Object
compile(Context cx, Scriptable scope, Node tree,
SecurityController securityController, Object securityDomain)
{
ObjArray classFiles = new ObjArray();
ObjArray names = new ObjArray();
if (cx.getOptimizationLevel() > 0) {
(new Optimizer()).optimize(tree, cx.getOptimizationLevel());
}
generateCode(tree, names, classFiles);
String generatedName = name;

View File

@ -40,9 +40,11 @@ import org.mozilla.javascript.*;
public class FatBlock {
public FatBlock(int startNodeIndex, int endNodeIndex, Node[] statementNodes)
public FatBlock(IRFactory irFactory, int startNodeIndex, int endNodeIndex,
Node[] statementNodes)
{
itsShadowOfFormerSelf = new Block(startNodeIndex, endNodeIndex, statementNodes);
itsShadowOfFormerSelf = new Block(irFactory, startNodeIndex,
endNodeIndex, statementNodes);
}
public Node getEndNode()

View File

@ -41,9 +41,8 @@ import java.util.*;
class OptFunctionNode extends FunctionNode {
OptFunctionNode(String name, Node statements, String className)
{
super(name, statements);
OptFunctionNode(String name, String className) {
super(name);
itsClassName = className;
}

View File

@ -49,27 +49,24 @@ import java.util.Hashtable;
class OptTransformer extends NodeTransformer {
private Hashtable theFnClassNameList;
OptTransformer(Hashtable theFnClassNameList) {
OptTransformer(IRFactory irFactory, Hashtable theFnClassNameList) {
super(irFactory);
this.theFnClassNameList = theFnClassNameList;
}
public NodeTransformer newInstance() {
return new OptTransformer((Hashtable) theFnClassNameList.clone());
Hashtable listCopy = (Hashtable) theFnClassNameList.clone();
return new OptTransformer(irFactory, listCopy);
}
public IRFactory createIRFactory(TokenStream ts, Scriptable scope) {
return new IRFactory(ts, scope);
}
public Node transform(Node tree, Node enclosing, TokenStream ts,
Scriptable scope) {
public Node transform(Node tree, Node enclosing) {
// Collect all of the contained functions into a hashtable
// so that the call optimizer can access the class name & parameter
// count for any call it encounters
collectContainedFunctions(tree.getFirstChild());
return super.transform(tree, enclosing, ts, scope);
return super.transform(tree, enclosing);
}
private int detectDirectCall(Node node, Node tree)

View File

@ -49,6 +49,10 @@ import java.util.Hashtable;
class Optimizer {
Optimizer(IRFactory irFactory) {
this.irFactory = irFactory;
}
void optimize(Node tree, int optLevel)
{
itsOptLevel = optLevel;
@ -74,7 +78,7 @@ class Optimizer {
inDirectCallFunction = theFunction.isTargetOfDirectCall();
Node[] theStatementNodes = buildStatementList(theFunction);
Block[] theBlocks = Block.buildBlocks(theStatementNodes);
Block[] theBlocks = Block.buildBlocks(irFactory, theStatementNodes);
PrintWriter pw = null;
try {
if (DEBUG_OPTIMIZER) {
@ -1040,6 +1044,7 @@ class Optimizer {
private static final int ALWAYS_TRUE_BOOLEAN = 1;
private static final int ALWAYS_FALSE_BOOLEAN = -1;
private IRFactory irFactory;
private int itsOptLevel;
private boolean inDirectCallFunction;
private boolean parameterUsedInNumberContext;