Moving parsing code from FunctionNode.finishParsing to IRFactory to have better overview of parsing code. The optimizer now calls explicitly OptFunctionNode initialization instead of overriding FunctionNode.finishParsing in OptFunctionNode.

This commit is contained in:
igor%mir2.org 2003-12-26 17:17:21 +00:00
parent 10e91b97ff
commit 65aea23579
5 changed files with 63 additions and 63 deletions

View File

@ -53,7 +53,7 @@ public class FunctionNode extends ScriptOrFnNode {
return itsNeedsActivation;
}
public boolean setRequiresActivation(boolean b) {
boolean setRequiresActivation(boolean b) {
return itsNeedsActivation = b;
}
@ -61,7 +61,7 @@ public class FunctionNode extends ScriptOrFnNode {
return itsCheckThis;
}
public void setCheckThis() {
void setCheckThis() {
itsCheckThis = true;
}
@ -69,7 +69,7 @@ public class FunctionNode extends ScriptOrFnNode {
return itsIgnoreDynamicScope;
}
public void setIgnoreDynamicScope() {
void setIgnoreDynamicScope() {
itsIgnoreDynamicScope = true;
}
@ -96,55 +96,10 @@ public class FunctionNode extends ScriptOrFnNode {
return itsFunctionType;
}
public void setFunctionType(int functionType) {
void setFunctionType(int functionType) {
itsFunctionType = functionType;
}
protected void finishParsing(IRFactory irFactory) {
super.finishParsing(irFactory);
int functionCount = getFunctionCount();
if (functionCount != 0) {
for (int i = 0; i != functionCount; ++i) {
FunctionNode fn = getFunctionNode(i);
// nested function expression statements overrides var
if (fn.getFunctionType() == FUNCTION_EXPRESSION_STATEMENT) {
String name = fn.getFunctionName();
if (name != null && name.length() != 0) {
removeParamOrVar(name);
}
}
}
// Functions containing other functions require activation objects
setRequiresActivation(true);
}
Node stmts = getLastChild();
if (getFunctionType() == FUNCTION_EXPRESSION) {
String name = getFunctionName();
if (name != null && name.length() != 0 && !hasParamOrVar(name))
{
// A function expression needs to have its name as a
// variable (if it isn't already allocated as a variable).
// See ECMA Ch. 13. We add code to the beginning of the
// function to initialize a local variable of the
// function's name to the function value.
addVar(name);
Node setFn = new Node(Token.POP,
new Node(Token.SETVAR, Node.newString(name),
new Node(Token.THISFN)));
stmts.addChildrenToFront(setFn);
}
}
// Add return to end if needed.
Node lastStmt = stmts.getLastChild();
if (lastStmt == null || lastStmt.getType() != Token.RETURN) {
stmts.addChildToBack(new Node(Token.RETURN));
}
}
private String functionName;
private boolean itsNeedsActivation;
private boolean itsCheckThis;

View File

@ -61,7 +61,6 @@ public class IRFactory {
{
Node children = ((Node) body).getFirstChild();
if (children != null) { scriptNode.addChildrenToBack(children); }
scriptNode.finishParsing(this);
}
/**
@ -200,9 +199,51 @@ public class IRFactory {
public Object initFunction(FunctionNode fnNode, int functionIndex,
Object statements, int functionType)
{
Node stmts = (Node)statements;
fnNode.setFunctionType(functionType);
fnNode.addChildToBack((Node)statements);
fnNode.finishParsing(this);
fnNode.addChildToBack(stmts);
int functionCount = fnNode.getFunctionCount();
if (functionCount != 0) {
// Functions containing other functions require activation objects
fnNode.setRequiresActivation(true);
for (int i = 0; i != functionCount; ++i) {
FunctionNode fn = fnNode.getFunctionNode(i);
// nested function expression statements overrides var
if (fn.getFunctionType()
== FunctionNode.FUNCTION_EXPRESSION_STATEMENT)
{
String name = fn.getFunctionName();
if (name != null && name.length() != 0) {
fnNode.removeParamOrVar(name);
}
}
}
}
if (functionType == FunctionNode.FUNCTION_EXPRESSION) {
String name = fnNode.getFunctionName();
if (name != null && name.length() != 0
&& !fnNode.hasParamOrVar(name))
{
// A function expression needs to have its name as a
// variable (if it isn't already allocated as a variable).
// See ECMA Ch. 13. We add code to the beginning of the
// function to initialize a local variable of the
// function's name to the function value.
fnNode.addVar(name);
Node setFn = new Node(Token.POP,
new Node(Token.SETVAR, Node.newString(name),
new Node(Token.THISFN)));
stmts.addChildrenToFront(setFn);
}
}
// Add return to end if needed.
Node lastStmt = stmts.getLastChild();
if (lastStmt == null || lastStmt.getType() != Token.RETURN) {
stmts.addChildToBack(new Node(Token.RETURN));
}
Node result = Node.newString(Token.FUNCTION,
fnNode.getFunctionName());
@ -1123,10 +1164,8 @@ public class IRFactory {
private Interpreter compiler;
// Only needed to call reportSyntaxError. Could create an interface
// that TokenStream implements if we want to make the connection less
// direct.
TokenStream ts;
// Only needed to call reportCurrentLineError.
private TokenStream ts;
private static final int LOOP_DO_WHILE = 0;
private static final int LOOP_WHILE = 1;

View File

@ -174,8 +174,6 @@ public class ScriptOrFnNode extends Node {
}
}
protected void finishParsing(IRFactory irFactory) { }
private int encodedSourceStart;
private int encodedSourceEnd;
private String sourceName;

View File

@ -77,6 +77,7 @@ public class Codegen extends Interpreter {
public ScriptOrFnNode transform(Context cx, ScriptOrFnNode tree)
{
initOptFunctions_r(tree);
int optLevel = cx.getOptimizationLevel();
Hashtable possibleDirectCalls = null;
if (optLevel > 0) {
@ -120,6 +121,15 @@ public class Codegen extends Interpreter {
return tree;
}
private static void initOptFunctions_r(ScriptOrFnNode scriptOrFn)
{
for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) {
OptFunctionNode fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i);
fn.init();
initOptFunctions_r(fn);
}
}
public Object compile(Context cx, Scriptable scope,
ScriptOrFnNode scriptOrFn,
SecurityController securityController,
@ -301,8 +311,6 @@ public class Codegen extends Interpreter {
for (int i = 0; i != count; ++i) {
ScriptOrFnNode n = scriptOrFnNodes[i];
boolean isFunction = (n.getType() == Token.FUNCTION);
BodyCodegen bodygen = new BodyCodegen();
bodygen.cfw = cfw;
bodygen.codegen = this;

View File

@ -39,14 +39,14 @@ package org.mozilla.javascript.optimizer;
import org.mozilla.javascript.*;
import java.util.*;
class OptFunctionNode extends FunctionNode {
final class OptFunctionNode extends FunctionNode {
OptFunctionNode(String name) {
super(name);
}
protected void finishParsing(IRFactory irFactory) {
super.finishParsing(irFactory);
void init()
{
int N = getParamAndVarCount();
int parameterCount = getParamCount();
optVars = new OptLocalVariable[N];