mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
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:
parent
10e91b97ff
commit
65aea23579
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -174,8 +174,6 @@ public class ScriptOrFnNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
protected void finishParsing(IRFactory irFactory) { }
|
||||
|
||||
private int encodedSourceStart;
|
||||
private int encodedSourceEnd;
|
||||
private String sourceName;
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user