diff --git a/js/rhino/src/org/mozilla/javascript/FunctionNode.java b/js/rhino/src/org/mozilla/javascript/FunctionNode.java index 8d580436a49..06535b595fb 100644 --- a/js/rhino/src/org/mozilla/javascript/FunctionNode.java +++ b/js/rhino/src/org/mozilla/javascript/FunctionNode.java @@ -107,7 +107,7 @@ public class FunctionNode extends ScriptOrFnNode { if (fn.getFunctionType() == FUNCTION_EXPRESSION_STATEMENT) { String name = fn.getFunctionName(); if (name != null && name.length() != 0) { - removeParameterOrVar(name); + removeParamOrVar(name); } } } @@ -119,7 +119,7 @@ public class FunctionNode extends ScriptOrFnNode { Node stmts = getLastChild(); if (getFunctionType() == FUNCTION_EXPRESSION) { String name = getFunctionName(); - if (name != null && name.length() != 0 && !hasParameterOrVar(name)) + 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). diff --git a/js/rhino/src/org/mozilla/javascript/Interpreter.java b/js/rhino/src/org/mozilla/javascript/Interpreter.java index 55bb921db6f..01ff0b70613 100644 --- a/js/rhino/src/org/mozilla/javascript/Interpreter.java +++ b/js/rhino/src/org/mozilla/javascript/Interpreter.java @@ -218,7 +218,7 @@ public class Interpreter { itsData.itsDoubleTable = tmp; } - itsData.itsMaxVars = scriptOrFn.getParameterAndVarCount(); + itsData.itsMaxVars = scriptOrFn.getParamAndVarCount(); // itsMaxFrameArray: interpret method needs this amount for its // stack and sDbl arrays itsData.itsMaxFrameArray = itsData.itsMaxVars @@ -226,8 +226,8 @@ public class Interpreter { + itsData.itsMaxTryDepth + itsData.itsMaxStack; - itsData.argNames = scriptOrFn.getParameterAndVarNames(); - itsData.argCount = scriptOrFn.getParameterCount(); + itsData.argNames = scriptOrFn.getParamAndVarNames(); + itsData.argCount = scriptOrFn.getParamCount(); } private int updateLineNumber(Node node, int iCodeTop) { @@ -674,7 +674,7 @@ public class Interpreter { // use typeofname if an activation frame exists // since the vars all exist there instead of in jregs if (itsInFunctionFlag && !itsData.itsNeedsActivation) - index = scriptOrFn.getParameterOrVarIndex(name); + index = scriptOrFn.getParamOrVarIndex(name); if (index == -1) { iCodeTop = addByte(TokenStream.TYPEOFNAME, iCodeTop); iCodeTop = addString(name, iCodeTop); @@ -724,7 +724,7 @@ public class Interpreter { iCodeTop); itsStackDepth--; } else { - int i = scriptOrFn.getParameterOrVarIndex(name); + int i = scriptOrFn.getParamOrVarIndex(name); iCodeTop = addByte(type == TokenStream.INC ? TokenStream.VARINC : TokenStream.VARDEC, @@ -930,7 +930,7 @@ public class Interpreter { iCodeTop = addByte(TokenStream.GETPROP, iCodeTop); itsStackDepth--; } else { - int index = scriptOrFn.getParameterOrVarIndex(name); + int index = scriptOrFn.getParamOrVarIndex(name); iCodeTop = addByte(TokenStream.GETVAR, iCodeTop); iCodeTop = addByte(index, iCodeTop); itsStackDepth++; @@ -949,7 +949,7 @@ public class Interpreter { String name = child.getString(); child = child.getNext(); iCodeTop = generateICode(child, iCodeTop); - int index = scriptOrFn.getParameterOrVarIndex(name); + int index = scriptOrFn.getParamOrVarIndex(name); iCodeTop = addByte(TokenStream.SETVAR, iCodeTop); iCodeTop = addByte(index, iCodeTop); } diff --git a/js/rhino/src/org/mozilla/javascript/JavaAdapter.java b/js/rhino/src/org/mozilla/javascript/JavaAdapter.java index 357b1a7cfbf..bd700374bbb 100644 --- a/js/rhino/src/org/mozilla/javascript/JavaAdapter.java +++ b/js/rhino/src/org/mozilla/javascript/JavaAdapter.java @@ -305,7 +305,7 @@ public class JavaAdapter extends ScriptableObject { ScriptableObject.getProperty(p, "length")); } else if (f instanceof FunctionNode) { // This is used only by optimizer/Codegen - length = ((FunctionNode)f).getParameterCount(); + length = ((FunctionNode)f).getParamCount(); } else { continue; } diff --git a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java index c247158dd04..181d720952e 100644 --- a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java +++ b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java @@ -376,7 +376,7 @@ public class NodeTransformer { // use of "arguments" requires an activation object. ((FunctionNode) tree).setRequiresActivation(true); } - if (tree.hasParameterOrVar(name)) { + if (tree.hasParamOrVar(name)) { if (type == TokenStream.SETNAME) { node.setType(TokenStream.SETVAR); bind.setType(TokenStream.STRING); @@ -416,7 +416,7 @@ public class NodeTransformer { // Use of "arguments" requires an activation object. ((FunctionNode) tree).setRequiresActivation(true); } - if (tree.hasParameterOrVar(name)) { + if (tree.hasParamOrVar(name)) { node.setType(TokenStream.GETVAR); } break; @@ -458,7 +458,7 @@ public class NodeTransformer { boolean addGetThis = false; if (left.getType() == TokenStream.NAME) { String name = left.getString(); - if (inFunction && tree.hasParameterOrVar(name) + if (inFunction && tree.hasParamOrVar(name) && !inWithStatement()) { // call to a var. Transform to Call(GetVar("a"), b, c) diff --git a/js/rhino/src/org/mozilla/javascript/Parser.java b/js/rhino/src/org/mozilla/javascript/Parser.java index c4df685dce3..2529c31ce9a 100644 --- a/js/rhino/src/org/mozilla/javascript/Parser.java +++ b/js/rhino/src/org/mozilla/javascript/Parser.java @@ -261,11 +261,11 @@ class Parser { first = false; mustMatchToken(ts, ts.NAME, "msg.no.parm"); String s = ts.getString(); - if (fnNode.hasParameterOrVar(s)) { + if (fnNode.hasParamOrVar(s)) { Object[] msgArgs = { s }; ts.reportCurrentLineWarning("msg.dup.parms", msgArgs); } - fnNode.addParameter(s); + fnNode.addParam(s); sourceAddString(ts.NAME, s); } while (ts.matchToken(ts.COMMA)); diff --git a/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java b/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java index 0c9850b6b03..87d66216df1 100644 --- a/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java +++ b/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java @@ -117,48 +117,65 @@ public class ScriptOrFnNode extends Node { return regexps.size() / 2 - 1; } - public final boolean hasParameterOrVar(String name) { - if (variableTable == null) { return false; } - return variableTable.hasVariable(name); + public final boolean hasParamOrVar(String name) { + return itsVariableNames.has(name); } - public final int getParameterOrVarIndex(String name) { - if (variableTable == null) { return -1; } - return variableTable.getOrdinal(name); + public final int getParamOrVarIndex(String name) { + return itsVariableNames.get(name, -1); } - public final String getParameterOrVarName(int index) { - return variableTable.getVariable(index); + public final String getParamOrVarName(int index) { + return (String)itsVariables.get(index); } - public final int getParameterCount() { - if (variableTable == null) { return 0; } - return variableTable.getParameterCount(); + public final int getParamCount() { + return varStart; } - public final int getParameterAndVarCount() { - if (variableTable == null) { return 0; } - return variableTable.size(); + public final int getParamAndVarCount() { + return itsVariables.size(); } - public final String[] getParameterAndVarNames() { - if (variableTable == null) { return new String[0]; } - return variableTable.getAllVariables(); + public final String[] getParamAndVarNames() { + String[] array = new String[itsVariables.size()]; + itsVariables.toArray(array); + return array; } - public final void addParameter(String name) { - if (variableTable == null) { variableTable = new VariableTable(); } - variableTable.addParameter(name); + public final void addParam(String name) { + // Check addparam is not called after addLocal + if (varStart != itsVariables.size()) Context.codeBug(); + // Allow non-unique parameter names: use the last occurrence + int index = varStart++; + itsVariables.add(name); + itsVariableNames.put(name, index); } public final void addVar(String name) { - if (variableTable == null) { variableTable = new VariableTable(); } - variableTable.addLocal(name); + int vIndex = itsVariableNames.get(name, -1); + if (vIndex != -1) { + // There's already a variable or parameter with this name. + return; + } + int index = itsVariables.size(); + itsVariables.add(name); + itsVariableNames.put(name, index); } - public final void removeParameterOrVar(String name) { - if (variableTable == null) { return; } - variableTable.removeLocal(name); + public final void removeParamOrVar(String name) { + int i = itsVariableNames.get(name, -1); + if (i != -1) { + itsVariables.remove(i); + itsVariableNames.remove(name); + ObjToIntMap.Iterator iter = itsVariableNames.newIterator(); + for (iter.start(); !iter.done(); iter.next()) { + int v = iter.getValue(); + if (v > i) { + iter.setValue(v - 1); + } + } + } } public final int getLocalCount() { return localCount; } @@ -174,9 +191,19 @@ public class ScriptOrFnNode extends Node { private String sourceName; private int baseLineno = -1; private int endLineno = -1; + private ObjArray functions; + private ObjArray regexps; - private VariableTable variableTable; + + // a list of the formal parameters and local variables + private ObjArray itsVariables = new ObjArray(); + + // mapping from name to index in list + private ObjToIntMap itsVariableNames = new ObjToIntMap(11); + + private int varStart; // index in list of first variable + private int localCount; } diff --git a/js/rhino/src/org/mozilla/javascript/VariableTable.java b/js/rhino/src/org/mozilla/javascript/VariableTable.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 91b361408f3..eb3bf09d778 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -333,7 +333,7 @@ public class Codegen extends Interpreter { + "Ljava/lang/Object;", flags); - int argCount = fnCurrent.getParameterCount(); + int argCount = fnCurrent.getParamCount(); int firstLocal = (4 + argCount * 3) + 1; aload((short)0); // this @@ -429,7 +429,7 @@ public class Codegen extends Interpreter { addByteCode(ByteCode.ALOAD_1); addByteCode(ByteCode.ALOAD_2); addByteCode(ByteCode.ALOAD_3); - for (int i = 0; i < scriptOrFn.getParameterCount(); i++) { + for (int i = 0; i < scriptOrFn.getParamCount(); i++) { push(i); addByteCode(ByteCode.ALOAD, 4); addByteCode(ByteCode.ARRAYLENGTH); @@ -465,7 +465,7 @@ public class Codegen extends Interpreter { if (!fnCurrent.getParameterNumberContext()) { // make sure that all parameters are objects itsForcedObjectParameters = true; - for (int i = 0; i < fnCurrent.getParameterCount(); i++) { + for (int i = 0; i < fnCurrent.getParamCount(); i++) { OptLocalVariable lVar = fnCurrent.getVar(i); aload(lVar.getJRegister()); classFile.add(ByteCode.GETSTATIC, @@ -482,7 +482,7 @@ public class Codegen extends Interpreter { markLabel(isObjectLabel); } } - generatePrologue(cx, true, scriptOrFn.getParameterCount()); + generatePrologue(cx, true, scriptOrFn.getParamCount()); } else { startNewMethod("call", "(Lorg/mozilla/javascript/Context;" + @@ -544,7 +544,7 @@ public class Codegen extends Interpreter { // 2 is reserved for parentScope // 3 is reserved for script 'this' short jReg = 4; - int parameterCount = fnCurrent.getParameterCount(); + int parameterCount = fnCurrent.getParamCount(); for (int i = 0; i < parameterCount; i++) { OptLocalVariable lVar = fnCurrent.getVar(i); lVar.assignJRegister(jReg); @@ -1145,7 +1145,7 @@ public class Codegen extends Interpreter { "functionName", "Ljava/lang/String;"); } - int N = scriptOrFn.getParameterAndVarCount(); + int N = scriptOrFn.getParamAndVarCount(); if (N != 0) { setNonTrivialInit(methodName); push(N); @@ -1153,7 +1153,7 @@ public class Codegen extends Interpreter { for (int i = 0; i != N; i++) { addByteCode(ByteCode.DUP); push(i); - push(scriptOrFn.getParameterOrVarName(i)); + push(scriptOrFn.getParamOrVarName(i)); addByteCode(ByteCode.AASTORE); } addByteCode(ByteCode.ALOAD_0); @@ -1163,7 +1163,7 @@ public class Codegen extends Interpreter { "argNames", "[Ljava/lang/String;"); } - int parmCount = scriptOrFn.getParameterCount(); + int parmCount = scriptOrFn.getParamCount(); if (parmCount != 0) { setNonTrivialInit(methodName); addByteCode(ByteCode.ALOAD_0); @@ -1373,7 +1373,7 @@ public class Codegen extends Interpreter { !((OptFunctionNode)scriptOrFn).requiresActivation(); if (hasVarsInRegs) { // No need to create activation. Pad arguments if need be. - int parmCount = scriptOrFn.getParameterCount(); + int parmCount = scriptOrFn.getParamCount(); if (inFunction && parmCount > 0 && directParameterCount < 0) { // Set up args array // check length of arguments, pad if need be diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java b/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java index e8ca97c2974..9d3d6f6f163 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java @@ -48,17 +48,17 @@ class OptFunctionNode extends FunctionNode { protected void finishParsing(IRFactory irFactory) { super.finishParsing(irFactory); - int N = getParameterAndVarCount(); - int parameterCount = getParameterCount(); + int N = getParamAndVarCount(); + int parameterCount = getParamCount(); optVars = new OptLocalVariable[N]; for (int i = 0; i != N; ++i) { - String name = getParameterOrVarName(i); + String name = getParamOrVarName(i); optVars[i] = new OptLocalVariable(name, i < parameterCount); } } String getDirectCallParameterSignature() { - int pCount = getParameterCount(); + int pCount = getParamCount(); switch (pCount) { case 0: return ZERO_PARAM_SIG; case 1: return ONE_PARAM_SIG; @@ -129,7 +129,7 @@ class OptFunctionNode extends FunctionNode { } OptLocalVariable getVar(String name) { - int index = getParameterOrVarIndex(name); + int index = getParamOrVarIndex(name); if (index < 0) { return null; } return optVars[index]; } diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java b/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java index aa71ad868cd..da87aa32672 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java @@ -129,7 +129,7 @@ class OptTransformer extends NodeTransformer { OptFunctionNode theFunction = (OptFunctionNode)theFnClassNameList.get(targetName); if (theFunction != null) { - int N = theFunction.getParameterCount(); + int N = theFunction.getParamCount(); // Refuse to directCall any function with more // than 32 parameters - prevent code explosion // for wacky test cases