From 3cab5b3e26be9cbbf6307a9822b0c6a1577c7ad6 Mon Sep 17 00:00:00 2001 From: "igor%mir2.org" Date: Sat, 27 Dec 2003 21:32:35 +0000 Subject: [PATCH] Decompling parsing from code generation: compiler instances are created only when parsing tree is build. --- .../mozilla/javascript/CompilerEnvirons.java | 128 ++++++++++++++++++ .../src/org/mozilla/javascript/Context.java | 57 ++++---- .../src/org/mozilla/javascript/IRFactory.java | 126 ++++++++++------- .../org/mozilla/javascript/Interpreter.java | 52 ++----- .../mozilla/javascript/NodeTransformer.java | 4 +- .../src/org/mozilla/javascript/Parser.java | 34 ++--- .../org/mozilla/javascript/TokenStream.java | 27 ++-- .../mozilla/javascript/optimizer/Codegen.java | 81 ++++++----- .../javascript/optimizer/OptFunctionNode.java | 64 +++++---- .../javascript/optimizer/OptTransformer.java | 16 ++- .../javascript/optimizer/Optimizer.java | 10 +- 11 files changed, 352 insertions(+), 247 deletions(-) create mode 100644 js/rhino/src/org/mozilla/javascript/CompilerEnvirons.java diff --git a/js/rhino/src/org/mozilla/javascript/CompilerEnvirons.java b/js/rhino/src/org/mozilla/javascript/CompilerEnvirons.java new file mode 100644 index 000000000000..a88616aee9ba --- /dev/null +++ b/js/rhino/src/org/mozilla/javascript/CompilerEnvirons.java @@ -0,0 +1,128 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is representation of compiler options for Rhino. + * + * The Initial Developer of the Original Code is + * RUnit Software AS. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Igor Bukanov, igor@fastmail.fm + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript; + +public class CompilerEnvirons +{ + public void initFromContext(Context cx, ErrorReporter syntaxErrorReporter) + { + setSyntaxErrorReporter(syntaxErrorReporter); + this.languageVersion = cx.getLanguageVersion(); + useDynamicScope = cx.hasCompileFunctionsWithDynamicScope(); + generateDebugInfo = (!cx.isGeneratingDebugChanged() + || cx.isGeneratingDebug()); + this.reservedKeywordAsIdentifier + = cx.hasFeature(Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER); + this.allowMemberExprAsFunctionName + = cx.hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME); + } + + public final int getSyntaxErrorCount() + { + return syntaxErrorCount; + } + + public void setSyntaxErrorReporter(ErrorReporter syntaxErrorReporter) + { + if (syntaxErrorReporter == null) Kit.argBug(); + this.syntaxErrorReporter = syntaxErrorReporter; + } + + public final void reportSyntaxError(boolean isError, + String messageProperty, Object[] args, + String sourceName, int lineno, + String line, int lineOffset) + { + String message = Context.getMessage(messageProperty, args); + if (isError) { + ++syntaxErrorCount; + if (fromEval) { + // We're probably in an eval. Need to throw an exception. + throw ScriptRuntime.constructError( + "SyntaxError", message, sourceName, + lineno, line, lineOffset); + } else { + syntaxErrorReporter.error(message, sourceName, + lineno, line, lineOffset); + } + } else { + syntaxErrorReporter.warning(message, sourceName, + lineno, line, lineOffset); + } + } + + public final boolean isFromEval() + { + return fromEval; + } + + public void setFromEval(boolean fromEval) + { + this.fromEval = fromEval; + } + + public final int getLanguageVersion() + { + return languageVersion; + } + + public final boolean isGenerateDebugInfo() + { + return generateDebugInfo; + } + + public final boolean isUseDynamicScope() + { + return useDynamicScope; + } + + private ErrorReporter syntaxErrorReporter; + private int syntaxErrorCount; + + private boolean fromEval; + + int languageVersion = Context.VERSION_DEFAULT; + boolean generateDebugInfo; + boolean useDynamicScope; + boolean reservedKeywordAsIdentifier; + boolean allowMemberExprAsFunctionName; + + +} + diff --git a/js/rhino/src/org/mozilla/javascript/Context.java b/js/rhino/src/org/mozilla/javascript/Context.java index d97101b670a8..14ef69c9d0ea 100644 --- a/js/rhino/src/org/mozilla/javascript/Context.java +++ b/js/rhino/src/org/mozilla/javascript/Context.java @@ -977,17 +977,17 @@ public class Context public boolean stringIsCompilableUnit(String source) { boolean errorseen = false; - Interpreter compiler = new Interpreter(); - compiler.setSyntaxErrorReporter(new DefaultErrorReporter(), false); + CompilerEnvirons compilerEnv = new CompilerEnvirons(); + compilerEnv.initFromContext(this, new DefaultErrorReporter()); // no source name or source text manager, because we're just // going to throw away the result. - TokenStream ts = new TokenStream(this, compiler, null, source, null, 1); + TokenStream ts = new TokenStream(compilerEnv, + null, source, null, 1); - IRFactory irf = new IRFactory(compiler, ts); - Parser p = createParser(); + Parser p = new Parser(compilerEnv); Decompiler decompiler = new Decompiler(); try { - p.parse(ts, irf, decompiler); + p.parse(ts, decompiler); } catch (IOException ioe) { errorseen = true; } catch (EvaluatorException ee) { @@ -2014,16 +2014,10 @@ public class Context // scope should be given if and only if compiling function if (!(scope == null ^ returnFunction)) Kit.codeBug(); - Interpreter compiler = createCompiler(); + CompilerEnvirons compilerEnv = new CompilerEnvirons(); ErrorReporter reporter = getErrorReporter(); - compiler.setSyntaxErrorReporter(reporter, fromEval); - - if (securityController != null) { - securityDomain = securityController. - getDynamicSecurityDomain(securityDomain); - } else { - securityDomain = null; - } + compilerEnv.initFromContext(this, reporter); + compilerEnv.setFromEval(fromEval); if (debugger != null) { if (sourceReader != null) { @@ -2032,15 +2026,23 @@ public class Context } } - TokenStream ts = new TokenStream(this, compiler, + TokenStream ts = new TokenStream(compilerEnv, sourceReader, sourceString, sourceName, lineno); - Parser p = createParser(); - - IRFactory irf = new IRFactory(compiler, ts); + Parser p = new Parser(compilerEnv); Decompiler decompiler = new Decompiler(); - ScriptOrFnNode tree = p.parse(ts, irf, decompiler); - if (compiler.syntaxErrorCount == 0) { + ScriptOrFnNode tree = p.parse(ts, decompiler); + int syntaxErrorCount = compilerEnv.getSyntaxErrorCount(); + if (syntaxErrorCount == 0) { + Interpreter compiler = createCompiler(); + compiler.compilerEnv = compilerEnv; + if (securityController != null) { + securityDomain = securityController. + getDynamicSecurityDomain(securityDomain); + } else { + securityDomain = null; + } + String encodedSource = null; if (isGeneratingSource()) { encodedSource = decompiler.getEncodedSource(); @@ -2063,7 +2065,8 @@ public class Context Object result = compiler.compile(this, scope, tree, securityController, securityDomain, encodedSource); - if (compiler.syntaxErrorCount == 0) { + syntaxErrorCount = compilerEnv.getSyntaxErrorCount(); + if (syntaxErrorCount == 0) { if (debugger != null) { if (sourceString == null) Kit.codeBug(); compiler.notifyDebuggerCompilationDone(this, result, @@ -2073,7 +2076,7 @@ public class Context } } String msg = Context.getMessage1("msg.got.syntax.errors", - String.valueOf(compiler.syntaxErrorCount)); + String.valueOf(syntaxErrorCount)); throw reporter.runtimeError(msg, sourceName, lineno, null, 0); } @@ -2091,14 +2094,6 @@ public class Context return result; } - private Parser createParser() { - Parser parser = new Parser(); - parser.setLanguageVersion(getLanguageVersion()); - parser.setAllowMemberExprAsFunctionName( - hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)); - return parser; - } - static String getSourcePositionFromStack(int[] linep) { Context cx = getCurrentContext(); if (cx == null) diff --git a/js/rhino/src/org/mozilla/javascript/IRFactory.java b/js/rhino/src/org/mozilla/javascript/IRFactory.java index a1e686cadbc8..43cfeb0ea406 100644 --- a/js/rhino/src/org/mozilla/javascript/IRFactory.java +++ b/js/rhino/src/org/mozilla/javascript/IRFactory.java @@ -43,21 +43,22 @@ package org.mozilla.javascript; * @author Mike McCabe * @author Norris Boyd */ -public class IRFactory { - - public IRFactory(Interpreter compiler, TokenStream ts) { - this.compiler = compiler; +class IRFactory +{ + IRFactory(TokenStream ts) + { this.ts = ts; } - public ScriptOrFnNode createScript() { + ScriptOrFnNode createScript() + { return new ScriptOrFnNode(Token.SCRIPT); } /** * Script (for associating file/url names with toplevel scripts.) */ - public void initScript(ScriptOrFnNode scriptNode, Object body) + void initScript(ScriptOrFnNode scriptNode, Object body) { Node children = ((Node) body).getFirstChild(); if (children != null) { scriptNode.addChildrenToBack(children); } @@ -66,11 +67,13 @@ public class IRFactory { /** * Leaf */ - public Object createLeaf(int nodeType) { + Object createLeaf(int nodeType) + { return new Node(nodeType); } - public Object createLeaf(int nodeType, int nodeOp) { + Object createLeaf(int nodeType, int nodeOp) + { return new Node(nodeType, nodeOp); } @@ -78,40 +81,47 @@ public class IRFactory { * Statement leaf nodes. */ - public Object createSwitch(int lineno) { + Object createSwitch(int lineno) + { return new Node.Jump(Token.SWITCH, lineno); } - public Object createVariables(int lineno) { + Object createVariables(int lineno) + { return new Node(Token.VAR, lineno); } - public Object createExprStatement(Object expr, int lineno) { + Object createExprStatement(Object expr, int lineno) + { return new Node(Token.EXPRSTMT, (Node) expr, lineno); } - public Object createExprStatementNoReturn(Object expr, int lineno) { + Object createExprStatementNoReturn(Object expr, int lineno) + { return new Node(Token.POP, (Node) expr, lineno); } /** * Name */ - public Object createName(String name) { + Object createName(String name) + { return Node.newString(Token.NAME, name); } /** * String (for literals) */ - public Object createString(String string) { + Object createString(String string) + { return Node.newString(string); } /** * Number (for literals) */ - public Object createNumber(double number) { + Object createNumber(double number) + { return Node.newNumber(number); } @@ -123,8 +133,8 @@ public class IRFactory { * @param stmts the statements in the catch clause * @param lineno the starting line number of the catch clause */ - public Object createCatch(String varName, Object catchCond, Object stmts, - int lineno) + Object createCatch(String varName, Object catchCond, Object stmts, + int lineno) { if (catchCond == null) { catchCond = new Node(Token.EMPTY); @@ -136,14 +146,16 @@ public class IRFactory { /** * Throw */ - public Object createThrow(Object expr, int lineno) { + Object createThrow(Object expr, int lineno) + { return new Node(Token.THROW, (Node)expr, lineno); } /** * Return */ - public Object createReturn(Object expr, int lineno) { + Object createReturn(Object expr, int lineno) + { return expr == null ? new Node(Token.RETURN, lineno) : new Node(Token.RETURN, (Node)expr, lineno); @@ -152,7 +164,7 @@ public class IRFactory { /** * Label */ - public Object createLabel(String label, int lineno) + Object createLabel(String label, int lineno) { Node.Jump n = new Node.Jump(Token.LABEL, lineno); n.setLabel(label); @@ -162,7 +174,7 @@ public class IRFactory { /** * Break (possibly labeled) */ - public Object createBreak(String label, int lineno) + Object createBreak(String label, int lineno) { Node.Jump n = new Node.Jump(Token.BREAK, lineno); if (label != null) { @@ -174,7 +186,7 @@ public class IRFactory { /** * Continue (possibly labeled) */ - public Object createContinue(String label, int lineno) + Object createContinue(String label, int lineno) { Node.Jump n = new Node.Jump(Token.CONTINUE, lineno); if (label != null) { @@ -188,16 +200,18 @@ public class IRFactory { * Creates the empty statement block * Must make subsequent calls to add statements to the node */ - public Object createBlock(int lineno) { + Object createBlock(int lineno) + { return new Node(Token.BLOCK, lineno); } - public FunctionNode createFunction(String name) { - return compiler.createFunctionNode(name); + FunctionNode createFunction(String name) + { + return new FunctionNode(name); } - public Object initFunction(FunctionNode fnNode, int functionIndex, - Object statements, int functionType) + Object initFunction(FunctionNode fnNode, int functionIndex, + Object statements, int functionType) { Node stmts = (Node)statements; fnNode.setFunctionType(functionType); @@ -256,14 +270,16 @@ public class IRFactory { * breaks the Factory abstraction, but it removes a requirement * from implementors of Node. */ - public void addChildToBack(Object parent, Object child) { + void addChildToBack(Object parent, Object child) + { ((Node)parent).addChildToBack((Node)child); } /** * While */ - public Object createWhile(Object cond, Object body, int lineno) { + Object createWhile(Object cond, Object body, int lineno) + { return createLoop(LOOP_WHILE, (Node)body, (Node)cond, null, null, lineno); } @@ -271,7 +287,8 @@ public class IRFactory { /** * DoWhile */ - public Object createDoWhile(Object body, Object cond, int lineno) { + Object createDoWhile(Object body, Object cond, int lineno) + { return createLoop(LOOP_DO_WHILE, (Node)body, (Node)cond, null, null, lineno); } @@ -279,8 +296,8 @@ public class IRFactory { /** * For */ - public Object createFor(Object init, Object test, Object incr, - Object body, int lineno) + Object createFor(Object init, Object test, Object incr, Object body, + int lineno) { return createLoop(LOOP_FOR, (Node)body, (Node)test, (Node)init, (Node)incr, lineno); @@ -344,7 +361,8 @@ public class IRFactory { * For .. In * */ - public Object createForIn(Object lhs, Object obj, Object body, int lineno) { + Object createForIn(Object lhs, Object obj, Object body, int lineno) + { String name; Node lhsNode = (Node) lhs; Node objNode = (Node) obj; @@ -415,8 +433,8 @@ public class IRFactory { * ... and a goto to GOTO around these handlers. */ - public Object createTryCatchFinally(Object tryblock, Object catchblocks, - Object finallyblock, int lineno) + Object createTryCatchFinally(Object tryblock, Object catchblocks, + Object finallyblock, int lineno) { Node trynode = (Node)tryblock; boolean hasFinally = false; @@ -581,7 +599,8 @@ public class IRFactory { /** * With */ - public Object createWith(Object obj, Object body, int lineno) { + Object createWith(Object obj, Object body, int lineno) + { Node result = new Node(Token.BLOCK, lineno); result.addChildToBack(new Node(Token.ENTERWITH, (Node)obj)); Node bodyNode = new Node(Token.WITH, (Node) body, lineno); @@ -596,7 +615,8 @@ public class IRFactory { * plus a series of array element entries, so later compiler * stages don't need to know about array literals. */ - public Object createArrayLiteral(Object obj) { + Object createArrayLiteral(Object obj) + { Node array; array = new Node(Token.NEW, Node.newString(Token.NAME, "Array")); Node list = new Node(Token.INIT_LIST, array); @@ -628,7 +648,7 @@ public class IRFactory { * (Which will make Array optimizations involving allocating a * Java array to back the javascript array work better.) */ - if (ts.cx.getLanguageVersion() == Context.VERSION_1_2) { + if (ts.compilerEnv.languageVersion == Context.VERSION_1_2) { /* When last array element is empty, we need to set the * length explicitly, because we can't depend on SETELEM * to do it for us - because empty [,,] array elements @@ -652,7 +672,8 @@ public class IRFactory { * creation plus object property entries, so later compiler * stages don't need to know about object literals. */ - public Object createObjectLiteral(Object obj) { + Object createObjectLiteral(Object obj) + { Node result = new Node(Token.NEW, Node.newString(Token.NAME, "Object")); Node list = new Node(Token.INIT_LIST, result); @@ -675,7 +696,8 @@ public class IRFactory { /** * Regular expressions */ - public Object createRegExp(int regexpIndex) { + Object createRegExp(int regexpIndex) + { Node n = new Node(Token.REGEXP); n.putIntProp(Node.REGEXP_PROP, regexpIndex); return n; @@ -684,8 +706,7 @@ public class IRFactory { /** * If statement */ - public Object createIf(Object condObj, Object ifTrue, Object ifFalse, - int lineno) + Object createIf(Object condObj, Object ifTrue, Object ifFalse, int lineno) { Node cond = (Node)condObj; int condStatus = isAlwaysDefinedBoolean(cond); @@ -722,7 +743,7 @@ public class IRFactory { return result; } - public Object createCondExpr(Object condObj, Object ifTrue, Object ifFalse) + Object createCondExpr(Object condObj, Object ifTrue, Object ifFalse) { Node cond = (Node)condObj; int condStatus = isAlwaysDefinedBoolean(cond); @@ -737,7 +758,8 @@ public class IRFactory { /** * Unary */ - public Object createUnary(int nodeType, Object child) { + Object createUnary(int nodeType, Object child) + { Node childNode = (Node) child; int childType = childNode.getType(); switch (nodeType) { @@ -802,7 +824,7 @@ public class IRFactory { return new Node(nodeType, childNode); } - public Object createIncDec(int nodeType, boolean post, Object child) + Object createIncDec(int nodeType, boolean post, Object child) { Node childNode = (Node)child; int childType = childNode.getType(); @@ -854,7 +876,7 @@ public class IRFactory { /** * Binary */ - public Object createBinary(int nodeType, Object leftObj, Object rightObj) + Object createBinary(int nodeType, Object leftObj, Object rightObj) { Node left = (Node)leftObj; Node right = (Node)rightObj; @@ -1026,7 +1048,7 @@ public class IRFactory { return new Node(nodeType, left, right); } - public Object createAssignment(Object leftObj, Object rightObj) + Object createAssignment(Object leftObj, Object rightObj) { Node left = (Node)leftObj; Node right = (Node)rightObj; @@ -1064,7 +1086,7 @@ public class IRFactory { } } - public Object createAssignmentOp(int assignOp, Object left, Object right) + Object createAssignmentOp(int assignOp, Object left, Object right) { return createAssignmentOp(assignOp, (Node)left, (Node)right, false); } @@ -1111,7 +1133,8 @@ public class IRFactory { } } - public Node createUseLocal(Node localBlock) { + Node createUseLocal(Node localBlock) + { if (Token.LOCAL_BLOCK != localBlock.getType()) Kit.codeBug(); Node result = new Node(Token.LOCAL_LOAD); result.putProp(Node.LOCAL_BLOCK_PROP, localBlock); @@ -1140,7 +1163,8 @@ public class IRFactory { return 0; } - private static boolean hasSideEffects(Node exprTree) { + private static boolean hasSideEffects(Node exprTree) + { switch (exprTree.getType()) { case Token.INC: case Token.DEC: @@ -1162,8 +1186,6 @@ public class IRFactory { return false; } - private Interpreter compiler; - // Only needed to call reportCurrentLineError. private TokenStream ts; diff --git a/js/rhino/src/org/mozilla/javascript/Interpreter.java b/js/rhino/src/org/mozilla/javascript/Interpreter.java index 280425af95ad..ef5506a0b77e 100644 --- a/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -110,42 +110,6 @@ public class Interpreter // Last icode END_ICODE = BASE_ICODE + 30; - final void setSyntaxErrorReporter(ErrorReporter syntaxErrorReporter, - boolean fromEval) - { - this.syntaxErrorReporter = syntaxErrorReporter; - this.fromEval = fromEval; - this.syntaxErrorCount = 0; - } - - public void reportSyntaxError(boolean isError, - String messageProperty, Object[] args, - String sourceName, int lineno, - String line, int lineOffset) - { - String message = Context.getMessage(messageProperty, args); - if (isError) { - ++syntaxErrorCount; - if (fromEval) { - // We're probably in an eval. Need to throw an exception. - throw ScriptRuntime.constructError( - "SyntaxError", message, sourceName, - lineno, line, lineOffset); - } else { - syntaxErrorReporter.error(message, sourceName, - lineno, line, lineOffset); - } - } else { - syntaxErrorReporter.warning(message, sourceName, - lineno, line, lineOffset); - } - } - - public FunctionNode createFunctionNode(String name) - { - return new FunctionNode(name); - } - public ScriptOrFnNode transform(Context cx, ScriptOrFnNode tree) { (new NodeTransformer(this)).transform(tree); @@ -157,7 +121,8 @@ public class Interpreter Object securityDomain, String encodedSource) { scriptOrFn = tree; - itsData = new InterpreterData(securityDomain, cx.getLanguageVersion()); + itsData = new InterpreterData(securityDomain, + compilerEnv.getLanguageVersion()); itsData.itsSourceFile = scriptOrFn.getSourceName(); itsData.encodedSource = encodedSource; itsData.topLevel = true; @@ -166,7 +131,7 @@ public class Interpreter return createFunction(cx, scope, itsData, false); } else { generateICodeFromTree(cx, scriptOrFn); - itsData.itsFromEvalCode = fromEval; + itsData.itsFromEvalCode = compilerEnv.isFromEval(); return new InterpretedScript(itsData); } } @@ -207,7 +172,7 @@ public class Interpreter itsData.itsNeedsActivation = true; } if (!theFunction.getIgnoreDynamicScope()) { - if (cx.hasCompileFunctionsWithDynamicScope()) { + if (compilerEnv.isUseDynamicScope()) { itsData.useDynamicScope = true; } } @@ -295,6 +260,7 @@ public class Interpreter for (int i = 0; i != functionCount; i++) { FunctionNode def = scriptOrFn.getFunctionNode(i); Interpreter jsi = new Interpreter(); + jsi.compilerEnv = compilerEnv; jsi.scriptOrFn = def; jsi.itsData = new InterpreterData(itsData.securityDomain, itsData.languageVersion); @@ -3316,11 +3282,9 @@ public class Interpreter return pc; } - private ErrorReporter syntaxErrorReporter; - private boolean fromEval; - int syntaxErrorCount; - - private boolean itsInFunctionFlag; + protected CompilerEnvirons compilerEnv; + + private boolean itsInFunctionFlag; private InterpreterData itsData; private ScriptOrFnNode scriptOrFn; diff --git a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java index 399b88465bf9..a8e929754920 100644 --- a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java +++ b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java @@ -534,8 +534,8 @@ public class NodeTransformer { int lineno = stmt.getLineno(); String sourceName = tree.getSourceName(); - compiler.reportSyntaxError(true, messageId, messageArgs, - sourceName, lineno, null, 0); + compiler.compilerEnv.reportSyntaxError( + true, messageId, messageArgs, sourceName, lineno, null, 0); } private ObjArray loops; diff --git a/js/rhino/src/org/mozilla/javascript/Parser.java b/js/rhino/src/org/mozilla/javascript/Parser.java index 515b75cde025..8e867a1b5c2a 100644 --- a/js/rhino/src/org/mozilla/javascript/Parser.java +++ b/js/rhino/src/org/mozilla/javascript/Parser.java @@ -53,15 +53,10 @@ import java.io.IOException; class Parser { - public Parser() { } - - public void setLanguageVersion(int languageVersion) { - this.languageVersion = languageVersion; - } - - public void setAllowMemberExprAsFunctionName(boolean flag) { - this.allowMemberExprAsFunctionName = flag; - } + public Parser(CompilerEnvirons compilerEnv) + { + this.compilerEnv = compilerEnv; + } private void mustMatchToken(TokenStream ts, int toMatch, String messageId) throws IOException, ParserException @@ -95,11 +90,10 @@ class Parser { * parse failure will result in a call to the current Context's * ErrorReporter.) */ - public ScriptOrFnNode parse(TokenStream ts, IRFactory nf, - Decompiler decompiler) + public ScriptOrFnNode parse(TokenStream ts, Decompiler decompiler) throws IOException { - this.nf = nf; + this.nf = new IRFactory(ts); currentScriptOrFn = nf.createScript(); this.decompiler = decompiler; int sourceStartOffset = decompiler.getCurrentOffset(); @@ -211,7 +205,7 @@ class Parser { if (ts.matchToken(Token.NAME)) { name = ts.getString(); if (!ts.matchToken(Token.LP)) { - if (allowMemberExprAsFunctionName) { + if (compilerEnv.allowMemberExprAsFunctionName) { // Extension to ECMA: if 'function ' does not follow // by '(', assume starts memberExpr decompiler.addName(name); @@ -226,7 +220,7 @@ class Parser { name = ""; } else { name = ""; - if (allowMemberExprAsFunctionName) { + if (compilerEnv.allowMemberExprAsFunctionName) { // Note that memberExpr can not start with '(' like // in function (1+2).toString(), because 'function (' already // processed as anonymous function @@ -385,7 +379,7 @@ class Parser { return; case Token.FUNCTION: - if (languageVersion < Context.VERSION_1_2) { + if (compilerEnv.languageVersion < Context.VERSION_1_2) { /* * Checking against version < 1.2 and version >= 1.0 * in the above line breaks old javascript, so we keep it @@ -400,7 +394,7 @@ class Parser { private void checkWellTerminatedFunction(TokenStream ts) throws IOException, ParserException { - if (languageVersion < Context.VERSION_1_2) { + if (compilerEnv.languageVersion < Context.VERSION_1_2) { // See comments in checkWellTerminated return; } @@ -1021,7 +1015,7 @@ class Parser { ts.getToken(); int decompilerToken = tt; int parseToken = tt; - if (languageVersion == Context.VERSION_1_2) { + if (compilerEnv.languageVersion == Context.VERSION_1_2) { // JavaScript 1.2 uses shallow equality for == and != . // In addition, convert === and !== for decompiler into // == and != since the decompiler is supposed to show @@ -1483,9 +1477,9 @@ class Parser { return null; // should never reach here } - private IRFactory nf; - private int languageVersion = Context.VERSION_DEFAULT; - private boolean allowMemberExprAsFunctionName = false; + private CompilerEnvirons compilerEnv; + + private IRFactory nf; private boolean ok; // Did the parse encounter an error? diff --git a/js/rhino/src/org/mozilla/javascript/TokenStream.java b/js/rhino/src/org/mozilla/javascript/TokenStream.java index af6457e5db81..1d6d310529ac 100644 --- a/js/rhino/src/org/mozilla/javascript/TokenStream.java +++ b/js/rhino/src/org/mozilla/javascript/TokenStream.java @@ -75,12 +75,11 @@ public class TokenStream private final static int EOF_CHAR = -1; - public TokenStream(Context cx, Interpreter compiler, + public TokenStream(CompilerEnvirons compilerEnv, Reader sourceReader, String sourceString, String sourceName, int lineno) { - this.cx = cx; - this.compiler = compiler; + this.compilerEnv = compilerEnv; this.pushbackToken = Token.EOF; this.sourceName = sourceName; this.lineno = lineno; @@ -296,17 +295,17 @@ public class TokenStream public final void reportCurrentLineError(String messageProperty, Object[] args) { - compiler.reportSyntaxError(true, messageProperty, args, - getSourceName(), getLineno(), - getLine(), getOffset()); + compilerEnv.reportSyntaxError(true, messageProperty, args, + getSourceName(), getLineno(), + getLine(), getOffset()); } public final void reportCurrentLineWarning(String messageProperty, Object[] args) { - compiler.reportSyntaxError(false, messageProperty, args, - getSourceName(), getLineno(), - getLine(), getOffset()); + compilerEnv.reportSyntaxError(false, messageProperty, args, + getSourceName(), getLineno(), + getLine(), getOffset()); } public final String getSourceName() { return sourceName; } @@ -476,13 +475,10 @@ public class TokenStream if (result != Token.EOF) { if (result != Token.RESERVED) { return result; - } - else if (!cx.hasFeature( - Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER)) + } else if (!compilerEnv.reservedKeywordAsIdentifier) { return result; - } - else { + } else { // If implementation permits to use future reserved // keywords in violation with the EcmaScript, // treat it as name but issue warning @@ -1207,6 +1203,5 @@ public class TokenStream private int sourceEnd; private int sourceCursor; - private Interpreter compiler; - Context cx; + CompilerEnvirons compilerEnv; } diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 671fd62b5254..3413cb75512d 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -58,18 +58,9 @@ public class Codegen extends Interpreter { { } - public FunctionNode createFunctionNode(String name) - { - return new OptFunctionNode(name); - } - public ScriptOrFnNode transform(Context cx, ScriptOrFnNode tree) { nameHelper = (OptClassNameHelper)ClassNameHelper.get(cx); - itsUseDynamicScope = cx.hasCompileFunctionsWithDynamicScope(); - generateDebugInfo = (!cx.isGeneratingDebugChanged() - || cx.isGeneratingDebug()); - languageVersion = cx.getLanguageVersion(); initOptFunctions_r(tree); @@ -86,10 +77,10 @@ public class Codegen extends Interpreter { int functionCount = tree.getFunctionCount(); for (int i = 0; i != functionCount; ++i) { OptFunctionNode ofn = OptFunctionNode.get(tree, i); - if (ofn.getFunctionType() + if (ofn.fnode.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { - String name = ofn.getFunctionName(); + String name = ofn.fnode.getFunctionName(); if (name.length() != 0) { if (possibleDirectCalls == null) { possibleDirectCalls = new Hashtable(); @@ -119,9 +110,9 @@ public class Codegen extends Interpreter { private static void initOptFunctions_r(ScriptOrFnNode scriptOrFn) { for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) { - OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, i); - ofn.init(); - initOptFunctions_r(ofn); + FunctionNode fn = scriptOrFn.getFunctionNode(i); + new OptFunctionNode(fn); + initOptFunctions_r(fn); } } @@ -271,7 +262,7 @@ public class Codegen extends Interpreter { boolean hasFunctions = (scriptOrFnNodes.length > 1 || !hasScript); String sourceFile = null; - if (generateDebugInfo) { + if (compilerEnv.isGenerateDebugInfo()) { sourceFile = scriptOrFnNodes[0].getSourceName(); } @@ -309,6 +300,7 @@ public class Codegen extends Interpreter { BodyCodegen bodygen = new BodyCodegen(); bodygen.cfw = cfw; bodygen.codegen = this; + bodygen.compilerEnv = compilerEnv; bodygen.scriptOrFn = n; bodygen.generateBodyCode(); @@ -351,12 +343,12 @@ public class Codegen extends Interpreter { return newInstance; } */ - cfw.startMethod(getDirectCtorName(ofn), - getBodyMethodSignature(ofn), + cfw.startMethod(getDirectCtorName(ofn.fnode), + getBodyMethodSignature(ofn.fnode), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); - int argCount = ofn.getParamCount(); + int argCount = ofn.fnode.getParamCount(); int firstLocal = (4 + argCount * 3) + 1; cfw.addALoad(0); // this @@ -381,8 +373,8 @@ public class Codegen extends Interpreter { cfw.addALoad(4 + argCount * 3); cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, - getBodyMethodName(ofn), - getBodyMethodSignature(ofn)); + getBodyMethodName(ofn.fnode), + getBodyMethodSignature(ofn.fnode)); int exitLabel = cfw.acquireLabel(); cfw.add(ByteCode.DUP); // make a copy of direct call result cfw.add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Scriptable"); @@ -445,7 +437,7 @@ public class Codegen extends Interpreter { if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); if (ofn.isTargetOfDirectCall()) { - int pcount = ofn.getParamCount(); + int pcount = ofn.fnode.getParamCount(); if (pcount != 0) { // loop invariant: // stack top == arguments array from addALoad4() @@ -552,7 +544,7 @@ public class Codegen extends Interpreter { // NativeFunction.initScriptFunction(version, "", varNamesArray, 0) cfw.addLoadThis(); - cfw.addPush(languageVersion); + cfw.addPush(compilerEnv.getLanguageVersion()); cfw.addPush(""); // Function name pushParamNamesArray(cfw, script); cfw.addPush(0); // No parameters, only varnames @@ -634,10 +626,10 @@ public class Codegen extends Interpreter { // Call NativeFunction.initScriptFunction cfw.addLoadThis(); - cfw.addPush(languageVersion); - cfw.addPush(ofn.getFunctionName()); - pushParamNamesArray(cfw, ofn); - cfw.addPush(ofn.getParamCount()); + cfw.addPush(compilerEnv.getLanguageVersion()); + cfw.addPush(ofn.fnode.getFunctionName()); + pushParamNamesArray(cfw, ofn.fnode); + cfw.addPush(ofn.fnode.getParamCount()); cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "org/mozilla/javascript/NativeFunction", "initScriptFunction", @@ -651,10 +643,10 @@ public class Codegen extends Interpreter { "(Lorg/mozilla/javascript/Scriptable;)V"); // precompile all regexp literals - int regexpCount = ofn.getRegexpCount(); + int regexpCount = ofn.fnode.getRegexpCount(); if (regexpCount != 0) { cfw.addLoadThis(); - pushRegExpArray(cfw, ofn, CONTEXT_ARG, SCOPE_ARG); + pushRegExpArray(cfw, ofn.fnode, CONTEXT_ARG, SCOPE_ARG); cfw.add(ByteCode.PUTFIELD, mainClassName, REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE); } @@ -1007,7 +999,7 @@ public class Codegen extends Interpreter { if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); if (ofn.isTargetOfDirectCall()) { - int pCount = ofn.getParamCount(); + int pCount = ofn.fnode.getParamCount(); for (int i = 0; i != pCount; i++) { sb.append("Ljava/lang/Object;D"); } @@ -1019,7 +1011,7 @@ public class Codegen extends Interpreter { String getFunctionInitMethodName(OptFunctionNode ofn) { - return "_i"+getIndex(ofn); + return "_i"+getIndex(ofn.fnode); } String getCompiledRegexpName(ScriptOrFnNode n, int regexpIndex) @@ -1067,7 +1059,6 @@ public class Codegen extends Interpreter { private byte[] mainClassBytes; boolean itsUseDynamicScope; - boolean generateDebugInfo; int languageVersion; private double[] itsConstantList; @@ -1114,7 +1105,8 @@ class BodyCodegen inDirectCallFunction = (fnCurrent == null) ? false : fnCurrent.isTargetOfDirectCall(); - hasVarsInRegs = (fnCurrent != null && !fnCurrent.requiresActivation()); + hasVarsInRegs = (fnCurrent != null + && !fnCurrent.fnode.requiresActivation()); locals = new boolean[MAX_LOCALS]; @@ -1172,8 +1164,8 @@ class BodyCodegen } if (fnCurrent != null && directParameterCount == -1 - && (!codegen.itsUseDynamicScope - || fnCurrent.getIgnoreDynamicScope())) + && (!compilerEnv.isUseDynamicScope() + || fnCurrent.fnode.getIgnoreDynamicScope())) { // Unless we're either in a direct call or using dynamic scope, // use the enclosing scope of the function as our variable object. @@ -1203,7 +1195,7 @@ class BodyCodegen } } - if (fnCurrent != null && fnCurrent.getCheckThis()) { + if (fnCurrent != null && fnCurrent.fnode.getCheckThis()) { // Nested functions must check their 'this' value to // insure it is not an activation object: // see 10.1.6 Activation Object @@ -1327,13 +1319,15 @@ class BodyCodegen int functionCount = scriptOrFn.getFunctionCount(); for (int i = 0; i != functionCount; i++) { OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, i); - if (ofn.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { + if (ofn.fnode.getFunctionType() + == FunctionNode.FUNCTION_STATEMENT) + { visitFunction(ofn, FunctionNode.FUNCTION_STATEMENT); } } // default is to generate debug info - if (codegen.generateDebugInfo) { + if (compilerEnv.isGenerateDebugInfo()) { OptLocalVariable lv = new OptLocalVariable(debugVariableName, false); lv.assignJRegister(variableObjectLocal); @@ -1440,7 +1434,7 @@ class BodyCodegen int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, fnIndex); - int t = ofn.getFunctionType(); + int t = ofn.fnode.getFunctionType(); if (t != FunctionNode.FUNCTION_STATEMENT) { visitFunction(ofn, t); } @@ -2029,7 +2023,7 @@ class BodyCodegen private void visitFunction(OptFunctionNode ofn, int functionType) { - int fnIndex = codegen.getIndex(ofn); + int fnIndex = codegen.getIndex(ofn.fnode); cfw.add(ByteCode.NEW, codegen.mainClassName); // Call function constructor cfw.add(ByteCode.DUP); @@ -2223,7 +2217,7 @@ class BodyCodegen cfw.add(ByteCode.SWAP); cfw.add(ByteCode.POP); - if (!codegen.itsUseDynamicScope) { + if (!compilerEnv.isUseDynamicScope()) { cfw.add(ByteCode.DUP); cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/Scriptable", @@ -2286,9 +2280,9 @@ class BodyCodegen cfw.addInvoke(ByteCode.INVOKESTATIC, codegen.mainClassName, (type == Token.NEW) - ? codegen.getDirectCtorName(target) - : codegen.getBodyMethodName(target), - codegen.getBodyMethodSignature(target)); + ? codegen.getDirectCtorName(target.fnode) + : codegen.getBodyMethodName(target.fnode), + codegen.getBodyMethodSignature(target.fnode)); int beyond = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, beyond); @@ -3887,6 +3881,7 @@ class BodyCodegen ClassFileWriter cfw; Codegen codegen; + CompilerEnvirons compilerEnv; ScriptOrFnNode scriptOrFn; private OptFunctionNode fnCurrent; diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java b/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java index 97ae33ab27e9..a68d5bd0b0c9 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java @@ -39,81 +39,91 @@ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import java.util.*; -final class OptFunctionNode extends FunctionNode { - - OptFunctionNode(String name) { - super(name); +final class OptFunctionNode +{ + OptFunctionNode(FunctionNode fnode) + { + this.fnode = fnode; + int N = fnode.getParamAndVarCount(); + int parameterCount = fnode.getParamCount(); + optVars = new OptLocalVariable[N]; + for (int i = 0; i != N; ++i) { + String name = fnode.getParamOrVarName(i); + optVars[i] = new OptLocalVariable(name, i < parameterCount); + } + fnode.setCompilerData(this); } static OptFunctionNode get(ScriptOrFnNode scriptOrFn, int i) { - return (OptFunctionNode)scriptOrFn.getFunctionNode(i); + FunctionNode fnode = scriptOrFn.getFunctionNode(i); + return (OptFunctionNode)fnode.getCompilerData(); } static OptFunctionNode get(ScriptOrFnNode scriptOrFn) { - return (OptFunctionNode)scriptOrFn; + return (OptFunctionNode)scriptOrFn.getCompilerData(); } - void init() + boolean isTargetOfDirectCall() { - int N = getParamAndVarCount(); - int parameterCount = getParamCount(); - optVars = new OptLocalVariable[N]; - for (int i = 0; i != N; ++i) { - String name = getParamOrVarName(i); - optVars[i] = new OptLocalVariable(name, i < parameterCount); - } - } - - boolean isTargetOfDirectCall() { return directTargetIndex >= 0; } - int getDirectTargetIndex() { + int getDirectTargetIndex() + { return directTargetIndex; } - void setDirectTargetIndex(int directTargetIndex) { + void setDirectTargetIndex(int directTargetIndex) + { // One time action if (directTargetIndex < 0 || this.directTargetIndex >= 0) Kit.codeBug(); this.directTargetIndex = directTargetIndex; } - void setParameterNumberContext(boolean b) { + void setParameterNumberContext(boolean b) + { itsParameterNumberContext = b; } - boolean getParameterNumberContext() { + boolean getParameterNumberContext() + { return itsParameterNumberContext; } - int getVarCount() { + int getVarCount() + { return optVars.length; } - OptLocalVariable getVar(int index) { + OptLocalVariable getVar(int index) + { return optVars[index]; } - OptLocalVariable getVar(String name) { - int index = getParamOrVarIndex(name); + OptLocalVariable getVar(String name) + { + int index = fnode.getParamOrVarIndex(name); if (index < 0) { return null; } return optVars[index]; } - void establishVarsIndices() { + void establishVarsIndices() + { int N = optVars.length; for (int i = 0; i != N; i++) { optVars[i].setIndex(i); } } - OptLocalVariable[] getVarsArray() { + OptLocalVariable[] getVarsArray() + { return optVars; } + FunctionNode fnode; private OptLocalVariable[] optVars; private int directTargetIndex = -1; private boolean itsParameterNumberContext; diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java b/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java index 4726482c861f..e57af3d1b973 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java @@ -176,18 +176,20 @@ class OptTransformer extends NodeTransformer { targetName = left.getFirstChild().getNext().getString(); } if (targetName != null) { - OptFunctionNode fn; - fn = (OptFunctionNode)possibleDirectCalls.get(targetName); - if (fn != null && argCount == fn.getParamCount()) { + OptFunctionNode ofn; + ofn = (OptFunctionNode)possibleDirectCalls.get(targetName); + if (ofn != null + && argCount == ofn.fnode.getParamCount()) + { // Refuse to directCall any function with more // than 32 parameters - prevent code explosion // for wacky test cases if (argCount <= 32) { - node.putProp(Node.DIRECTCALL_PROP, fn); - if (!fn.isTargetOfDirectCall()) { + node.putProp(Node.DIRECTCALL_PROP, ofn); + if (!ofn.isTargetOfDirectCall()) { int index = directCallTargets.size(); - directCallTargets.add(fn); - fn.setDirectTargetIndex(index); + directCallTargets.add(ofn); + ofn.setDirectTargetIndex(index); } } } diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java b/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java index 1413e5a0b2cf..134673d00d4d 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java @@ -72,12 +72,12 @@ class Optimizer private void optimizeFunction(OptFunctionNode theFunction) { - if (theFunction.requiresActivation()) return; + if (theFunction.fnode.requiresActivation()) return; inDirectCallFunction = theFunction.isTargetOfDirectCall(); ObjArray statementsArray = new ObjArray(); - buildStatementList_r(theFunction, statementsArray); + buildStatementList_r(theFunction.fnode, statementsArray); Node[] theStatementNodes = new Node[statementsArray.size()]; statementsArray.toArray(theStatementNodes); @@ -101,7 +101,7 @@ class Optimizer typeFlow(theFunction, theBlocks); findSinglyTypedVars(theFunction, theBlocks); localCSE(theBlocks, theFunction); - if (!theFunction.requiresActivation()) { + if (!theFunction.fnode.requiresActivation()) { /* * Now that we know which local vars are in fact always * Numbers, we re-write the tree to take advantage of @@ -634,8 +634,8 @@ class Optimizer } case Token.CALL : { - FunctionNode target - = (FunctionNode)n.getProp(Node.DIRECTCALL_PROP); + OptFunctionNode target + = (OptFunctionNode)n.getProp(Node.DIRECTCALL_PROP); if (target != null) { /* we leave each child as a Number if it can be. The codegen will