зеркало из https://github.com/mozilla/pjs.git
Fix bugs:
56318 function literals with names don't work right 57045 negative integers as object properties: weird behavior 58479 functions defined within conditional phrases are always crea
This commit is contained in:
Родитель
a1da49183a
Коммит
fa72e89acf
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -174,8 +174,8 @@ public class Interpreter extends LabelTable {
|
||||||
boolean needsActivation = theFunction.requiresActivation() ||
|
boolean needsActivation = theFunction.requiresActivation() ||
|
||||||
cx.isGeneratingDebug();
|
cx.isGeneratingDebug();
|
||||||
generateICodeFromTree(theFunction.getLastChild(),
|
generateICodeFromTree(theFunction.getLastChild(),
|
||||||
varTable, needsActivation,
|
varTable, needsActivation,
|
||||||
securityDomain);
|
securityDomain);
|
||||||
|
|
||||||
itsData.itsName = theFunction.getFunctionName();
|
itsData.itsName = theFunction.getFunctionName();
|
||||||
itsData.itsSourceFile = (String) theFunction.getProp(
|
itsData.itsSourceFile = (String) theFunction.getProp(
|
||||||
|
@ -1204,6 +1204,7 @@ public class Interpreter extends LabelTable {
|
||||||
case TokenStream.ONE :
|
case TokenStream.ONE :
|
||||||
case TokenStream.NULL :
|
case TokenStream.NULL :
|
||||||
case TokenStream.THIS :
|
case TokenStream.THIS :
|
||||||
|
case TokenStream.THISFN :
|
||||||
case TokenStream.FALSE :
|
case TokenStream.FALSE :
|
||||||
case TokenStream.TRUE :
|
case TokenStream.TRUE :
|
||||||
case TokenStream.UNDEFINED :
|
case TokenStream.UNDEFINED :
|
||||||
|
@ -1802,6 +1803,9 @@ public class Interpreter extends LabelTable {
|
||||||
case TokenStream.THIS :
|
case TokenStream.THIS :
|
||||||
stack[++stackTop] = thisObj;
|
stack[++stackTop] = thisObj;
|
||||||
break;
|
break;
|
||||||
|
case TokenStream.THISFN :
|
||||||
|
stack[++stackTop] = fnOrScript;
|
||||||
|
break;
|
||||||
case TokenStream.FALSE :
|
case TokenStream.FALSE :
|
||||||
stack[++stackTop] = Boolean.FALSE;
|
stack[++stackTop] = Boolean.FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Netscape 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/NPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS
|
|
||||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
|
||||||
* implied. See the License for the specific language governing
|
|
||||||
* rights and limitations under the License.
|
|
||||||
*
|
|
||||||
* The Original Code is Rhino code, released
|
|
||||||
* May 6, 1999.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is Netscape
|
|
||||||
* Communications Corporation. Portions created by Netscape are
|
|
||||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
|
||||||
* Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Norris Boyd
|
|
||||||
* Roger Lawrence
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the
|
|
||||||
* terms of the GNU Public License (the "GPL"), in which case the
|
|
||||||
* provisions of the GPL are applicable instead of those above.
|
|
||||||
* If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of the GPL and not to allow others to use your
|
|
||||||
* version of this file under the NPL, indicate your decision by
|
|
||||||
* deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this
|
|
||||||
* file under either the NPL or the GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.mozilla.javascript;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
class InterpreterData {
|
|
||||||
|
|
||||||
static final int INITIAL_MAX_ICODE_LENGTH = 1024;
|
|
||||||
static final int INITIAL_STRINGTABLE_SIZE = 64;
|
|
||||||
static final int INITIAL_NUMBERTABLE_SIZE = 64;
|
|
||||||
|
|
||||||
InterpreterData(int lastICodeTop, int lastStringTableIndex,
|
|
||||||
int lastNumberTableIndex, Object securityDomain,
|
|
||||||
boolean useDynamicScope)
|
|
||||||
{
|
|
||||||
itsICodeTop = lastICodeTop == 0
|
|
||||||
? INITIAL_MAX_ICODE_LENGTH
|
|
||||||
: lastICodeTop * 2;
|
|
||||||
itsICode = new byte[itsICodeTop];
|
|
||||||
|
|
||||||
itsStringTable = new String[lastStringTableIndex == 0
|
|
||||||
? INITIAL_STRINGTABLE_SIZE
|
|
||||||
: lastStringTableIndex * 2];
|
|
||||||
|
|
||||||
itsNumberTable = new Number[lastNumberTableIndex == 0
|
|
||||||
? INITIAL_NUMBERTABLE_SIZE
|
|
||||||
: lastNumberTableIndex * 2];
|
|
||||||
|
|
||||||
itsUseDynamicScope = useDynamicScope;
|
|
||||||
if (securityDomain == null)
|
|
||||||
Context.checkSecurityDomainRequired();
|
|
||||||
this.securityDomain = securityDomain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean placeBreakpoint(int line) { // XXX throw exn?
|
|
||||||
int offset = getOffset(line);
|
|
||||||
if (offset != -1 && (itsICode[offset] == (byte)TokenStream.LINE ||
|
|
||||||
itsICode[offset] == (byte)TokenStream.BREAKPOINT))
|
|
||||||
{
|
|
||||||
itsICode[offset] = (byte) TokenStream.BREAKPOINT;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean removeBreakpoint(int line) {
|
|
||||||
int offset = getOffset(line);
|
|
||||||
if (offset != -1 && itsICode[offset] == TokenStream.BREAKPOINT)
|
|
||||||
{
|
|
||||||
itsICode[offset] = (byte) TokenStream.LINE;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getOffset(int line) {
|
|
||||||
Object offset = itsLineNumberTable.get(new Integer(line));
|
|
||||||
if (offset != null && offset instanceof Integer) {
|
|
||||||
int i = ((Integer)offset).intValue();
|
|
||||||
if (i >= 0 && i < itsICode.length)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableTable itsVariableTable;
|
|
||||||
|
|
||||||
String itsName;
|
|
||||||
String itsSource;
|
|
||||||
String itsSourceFile;
|
|
||||||
boolean itsNeedsActivation;
|
|
||||||
boolean itsFromEvalCode;
|
|
||||||
boolean itsUseDynamicScope;
|
|
||||||
byte itsFunctionType;
|
|
||||||
|
|
||||||
String[] itsStringTable;
|
|
||||||
int itsStringTableIndex;
|
|
||||||
|
|
||||||
Number[] itsNumberTable;
|
|
||||||
int itsNumberTableIndex;
|
|
||||||
|
|
||||||
InterpretedFunction[] itsNestedFunctions;
|
|
||||||
|
|
||||||
Object[] itsRegExpLiterals;
|
|
||||||
|
|
||||||
byte[] itsICode;
|
|
||||||
int itsICodeTop;
|
|
||||||
|
|
||||||
int itsMaxLocals;
|
|
||||||
int itsMaxArgs;
|
|
||||||
int itsMaxStack;
|
|
||||||
int itsMaxTryDepth;
|
|
||||||
|
|
||||||
java.util.Hashtable itsLineNumberTable;
|
|
||||||
|
|
||||||
Object securityDomain;
|
|
||||||
}
|
|
|
@ -449,7 +449,7 @@ public class NodeTransformer {
|
||||||
((FunctionNode) tree).setRequiresActivation(true);
|
((FunctionNode) tree).setRequiresActivation(true);
|
||||||
}
|
}
|
||||||
VariableTable vars = getVariableTable(tree);
|
VariableTable vars = getVariableTable(tree);
|
||||||
if (vars.get(name) != null) {
|
if (vars.getVariable(name) != null) {
|
||||||
if (type == TokenStream.SETNAME) {
|
if (type == TokenStream.SETNAME) {
|
||||||
node.setType(TokenStream.SETVAR);
|
node.setType(TokenStream.SETVAR);
|
||||||
bind.setType(TokenStream.STRING);
|
bind.setType(TokenStream.STRING);
|
||||||
|
@ -489,7 +489,7 @@ public class NodeTransformer {
|
||||||
((FunctionNode) tree).setRequiresActivation(true);
|
((FunctionNode) tree).setRequiresActivation(true);
|
||||||
}
|
}
|
||||||
VariableTable vars = getVariableTable(tree);
|
VariableTable vars = getVariableTable(tree);
|
||||||
if (vars.get(name) != null) {
|
if (vars.getVariable(name) != null) {
|
||||||
node.setType(TokenStream.GETVAR);
|
node.setType(TokenStream.GETVAR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -510,7 +510,9 @@ public class NodeTransformer {
|
||||||
while ((node = iterator.nextNode()) != null) {
|
while ((node = iterator.nextNode()) != null) {
|
||||||
int nodeType = node.getType();
|
int nodeType = node.getType();
|
||||||
if (inFunction && nodeType == TokenStream.FUNCTION &&
|
if (inFunction && nodeType == TokenStream.FUNCTION &&
|
||||||
node != tree)
|
node != tree &&
|
||||||
|
((FunctionNode) node.getProp(Node.FUNCTION_PROP)).getFunctionType() ==
|
||||||
|
FunctionNode.FUNCTION_EXPRESSION_STATEMENT)
|
||||||
{
|
{
|
||||||
// In a function with both "var x" and "function x",
|
// In a function with both "var x" and "function x",
|
||||||
// disregard the var statement, independent of order.
|
// disregard the var statement, independent of order.
|
||||||
|
@ -531,6 +533,26 @@ public class NodeTransformer {
|
||||||
vars.addLocal(n.getString());
|
vars.addLocal(n.getString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String name = (String) tree.getDatum();
|
||||||
|
if (inFunction && ((FunctionNode) tree).getFunctionType() ==
|
||||||
|
FunctionNode.FUNCTION_EXPRESSION &&
|
||||||
|
name != null && name.length() > 0 &&
|
||||||
|
vars.getVariable(name) == null)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
vars.addLocal(name);
|
||||||
|
Node block = tree.getLastChild();
|
||||||
|
Node setFn = new Node(TokenStream.POP,
|
||||||
|
new Node(TokenStream.SETVAR,
|
||||||
|
new Node(TokenStream.STRING, name),
|
||||||
|
new Node(TokenStream.PRIMARY,
|
||||||
|
new Integer(TokenStream.THISFN))));
|
||||||
|
block.addChildrenToFront(setFn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addParameters(FunctionNode fnNode) {
|
protected void addParameters(FunctionNode fnNode) {
|
||||||
|
@ -580,7 +602,9 @@ public class NodeTransformer {
|
||||||
if (left.getType() == TokenStream.NAME) {
|
if (left.getType() == TokenStream.NAME) {
|
||||||
VariableTable vars = getVariableTable(tree);
|
VariableTable vars = getVariableTable(tree);
|
||||||
String name = left.getString();
|
String name = left.getString();
|
||||||
if (inFunction && vars.get(name) != null && !inWithStatement()) {
|
if (inFunction && vars.getVariable(name) != null &&
|
||||||
|
!inWithStatement())
|
||||||
|
{
|
||||||
// call to a var. Transform to Call(GetVar("a"), b, c)
|
// call to a var. Transform to Call(GetVar("a"), b, c)
|
||||||
left.setType(TokenStream.GETVAR);
|
left.setType(TokenStream.GETVAR);
|
||||||
// fall through to code to add GetParent
|
// fall through to code to add GetParent
|
||||||
|
|
|
@ -854,12 +854,18 @@ public class ScriptRuntime {
|
||||||
/* It must be a string. */
|
/* It must be a string. */
|
||||||
int len = str.length();
|
int len = str.length();
|
||||||
char c;
|
char c;
|
||||||
if (len > 0 && '0' <= (c = str.charAt(0)) && c <= '9' &&
|
boolean negate = false;
|
||||||
|
int i = 0;
|
||||||
|
if (len > 0 && (c = str.charAt(0)) == '-') {
|
||||||
|
negate = true;
|
||||||
|
i = 1;
|
||||||
|
}
|
||||||
|
if (len > 0 && '0' <= (c = str.charAt(i)) && c <= '9' &&
|
||||||
len <= MAX_VALUE_LENGTH)
|
len <= MAX_VALUE_LENGTH)
|
||||||
{
|
{
|
||||||
int index = c - '0';
|
int index = c - '0';
|
||||||
int oldIndex = 0;
|
int oldIndex = 0;
|
||||||
int i = 1;
|
i++;
|
||||||
if (index != 0) {
|
if (index != 0) {
|
||||||
while (i < len && '0' <= (c = str.charAt(i)) && c <= '9') {
|
while (i < len && '0' <= (c = str.charAt(i)) && c <= '9') {
|
||||||
oldIndex = index;
|
oldIndex = index;
|
||||||
|
@ -875,7 +881,7 @@ public class ScriptRuntime {
|
||||||
(oldIndex == (Integer.MAX_VALUE / 10) &&
|
(oldIndex == (Integer.MAX_VALUE / 10) &&
|
||||||
c < (Integer.MAX_VALUE % 10))))
|
c < (Integer.MAX_VALUE % 10))))
|
||||||
{
|
{
|
||||||
return index;
|
return negate ? -index : index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NO_INDEX;
|
return NO_INDEX;
|
||||||
|
@ -1159,9 +1165,14 @@ public class ScriptRuntime {
|
||||||
} while (next != null);
|
} while (next != null);
|
||||||
|
|
||||||
bound.put(id, bound, value);
|
bound.put(id, bound, value);
|
||||||
|
/*
|
||||||
|
This code is causing immense performance problems in
|
||||||
|
scripts that assign to the variables as a way of creating them.
|
||||||
|
XXX need strict mode
|
||||||
String[] args = { id };
|
String[] args = { id };
|
||||||
String message = getMessage("msg.assn.create", args);
|
String message = getMessage("msg.assn.create", args);
|
||||||
Context.reportWarning(message);
|
Context.reportWarning(message);
|
||||||
|
*/
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return setProp(bound, id, value, scope);
|
return setProp(bound, id, value, scope);
|
||||||
|
@ -1947,11 +1958,12 @@ public class ScriptRuntime {
|
||||||
public static NativeFunction initFunction(NativeFunction fn,
|
public static NativeFunction initFunction(NativeFunction fn,
|
||||||
Scriptable scope,
|
Scriptable scope,
|
||||||
String fnName,
|
String fnName,
|
||||||
Context cx)
|
Context cx,
|
||||||
|
boolean doSetName)
|
||||||
{
|
{
|
||||||
fn.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));
|
fn.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));
|
||||||
fn.setParentScope(scope);
|
fn.setParentScope(scope);
|
||||||
if (fnName != null && fnName.length() != 0)
|
if (doSetName)
|
||||||
setName(scope, fn, scope, fnName);
|
setName(scope, fn, scope, fnName);
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,47 +168,48 @@ public class TokenStream {
|
||||||
SETPARENT = 84,
|
SETPARENT = 84,
|
||||||
SCOPE = 85,
|
SCOPE = 85,
|
||||||
GETSCOPEPARENT = 86,
|
GETSCOPEPARENT = 86,
|
||||||
JTHROW = 87,
|
THISFN = 87,
|
||||||
|
JTHROW = 88,
|
||||||
// End of interpreter bytecodes
|
// End of interpreter bytecodes
|
||||||
SEMI = 88, // semicolon
|
SEMI = 89, // semicolon
|
||||||
LB = 89, // left and right brackets
|
LB = 90, // left and right brackets
|
||||||
RB = 90,
|
RB = 91,
|
||||||
LC = 91, // left and right curlies (braces)
|
LC = 92, // left and right curlies (braces)
|
||||||
RC = 92,
|
RC = 93,
|
||||||
LP = 93, // left and right parentheses
|
LP = 94, // left and right parentheses
|
||||||
RP = 94,
|
RP = 95,
|
||||||
COMMA = 95, // comma operator
|
COMMA = 96, // comma operator
|
||||||
ASSIGN = 96, // assignment ops (= += -= etc.)
|
ASSIGN = 97, // assignment ops (= += -= etc.)
|
||||||
HOOK = 97, // conditional (?:)
|
HOOK = 98, // conditional (?:)
|
||||||
COLON = 98,
|
COLON = 99,
|
||||||
OR = 99, // logical or (||)
|
OR = 100, // logical or (||)
|
||||||
AND = 100, // logical and (&&)
|
AND = 101, // logical and (&&)
|
||||||
EQOP = 101, // equality ops (== !=)
|
EQOP = 102, // equality ops (== !=)
|
||||||
RELOP = 102, // relational ops (< <= > >=)
|
RELOP = 103, // relational ops (< <= > >=)
|
||||||
SHOP = 103, // shift ops (<< >> >>>)
|
SHOP = 104, // shift ops (<< >> >>>)
|
||||||
UNARYOP = 104, // unary prefix operator
|
UNARYOP = 105, // unary prefix operator
|
||||||
INC = 105, // increment/decrement (++ --)
|
INC = 106, // increment/decrement (++ --)
|
||||||
DEC = 106,
|
DEC = 107,
|
||||||
DOT = 107, // member operator (.)
|
DOT = 108, // member operator (.)
|
||||||
PRIMARY = 108, // true, false, null, this
|
PRIMARY = 109, // true, false, null, this
|
||||||
FUNCTION = 109, // function keyword
|
FUNCTION = 110, // function keyword
|
||||||
EXPORT = 110, // export keyword
|
EXPORT = 111, // export keyword
|
||||||
IMPORT = 111, // import keyword
|
IMPORT = 112, // import keyword
|
||||||
IF = 112, // if keyword
|
IF = 113, // if keyword
|
||||||
ELSE = 113, // else keyword
|
ELSE = 114, // else keyword
|
||||||
SWITCH = 114, // switch keyword
|
SWITCH = 115, // switch keyword
|
||||||
CASE = 115, // case keyword
|
CASE = 116, // case keyword
|
||||||
DEFAULT = 116, // default keyword
|
DEFAULT = 117, // default keyword
|
||||||
WHILE = 117, // while keyword
|
WHILE = 118, // while keyword
|
||||||
DO = 118, // do keyword
|
DO = 119, // do keyword
|
||||||
FOR = 119, // for keyword
|
FOR = 120, // for keyword
|
||||||
BREAK = 120, // break keyword
|
BREAK = 121, // break keyword
|
||||||
CONTINUE = 121, // continue keyword
|
CONTINUE = 122, // continue keyword
|
||||||
VAR = 122, // var keyword
|
VAR = 123, // var keyword
|
||||||
WITH = 123, // with keyword
|
WITH = 124, // with keyword
|
||||||
CATCH = 124, // catch keyword
|
CATCH = 125, // catch keyword
|
||||||
FINALLY = 125, // finally keyword
|
FINALLY = 126, // finally keyword
|
||||||
RESERVED = 126, // reserved keywords
|
RESERVED = 127, // reserved keywords
|
||||||
|
|
||||||
/** Added by Mike - these are JSOPs in the jsref, but I
|
/** Added by Mike - these are JSOPs in the jsref, but I
|
||||||
* don't have them yet in the java implementation...
|
* don't have them yet in the java implementation...
|
||||||
|
@ -217,45 +218,45 @@ public class TokenStream {
|
||||||
* Most of these go in the 'op' field when returning
|
* Most of these go in the 'op' field when returning
|
||||||
* more general token types, eg. 'DIV' as the op of 'ASSIGN'.
|
* more general token types, eg. 'DIV' as the op of 'ASSIGN'.
|
||||||
*/
|
*/
|
||||||
NOP = 127, // NOP
|
NOP = 128, // NOP
|
||||||
NOT = 128, // etc.
|
NOT = 129, // etc.
|
||||||
PRE = 129, // for INC, DEC nodes.
|
PRE = 130, // for INC, DEC nodes.
|
||||||
POST = 130,
|
POST = 131,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For JSOPs associated with keywords...
|
* For JSOPs associated with keywords...
|
||||||
* eg. op = THIS; token = PRIMARY
|
* eg. op = THIS; token = PRIMARY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VOID = 131,
|
VOID = 132,
|
||||||
|
|
||||||
/* types used for the parse tree - these never get returned
|
/* types used for the parse tree - these never get returned
|
||||||
* by the scanner.
|
* by the scanner.
|
||||||
*/
|
*/
|
||||||
BLOCK = 132, // statement block
|
BLOCK = 133, // statement block
|
||||||
ARRAYLIT = 133, // array literal
|
ARRAYLIT = 134, // array literal
|
||||||
OBJLIT = 134, // object literal
|
OBJLIT = 135, // object literal
|
||||||
LABEL = 135, // label
|
LABEL = 136, // label
|
||||||
TARGET = 136,
|
TARGET = 137,
|
||||||
LOOP = 137,
|
LOOP = 138,
|
||||||
ENUMDONE = 138,
|
ENUMDONE = 139,
|
||||||
EXPRSTMT = 139,
|
EXPRSTMT = 140,
|
||||||
PARENT = 140,
|
PARENT = 141,
|
||||||
CONVERT = 141,
|
CONVERT = 142,
|
||||||
JSR = 142,
|
JSR = 143,
|
||||||
NEWLOCAL = 143,
|
NEWLOCAL = 144,
|
||||||
USELOCAL = 144,
|
USELOCAL = 145,
|
||||||
SCRIPT = 145, // top-level node for entire script
|
SCRIPT = 146, // top-level node for entire script
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the interpreted mode indicating a line number change in icodes.
|
* For the interpreted mode indicating a line number change in icodes.
|
||||||
*/
|
*/
|
||||||
LINE = 146,
|
LINE = 147,
|
||||||
SOURCEFILE = 147,
|
SOURCEFILE = 148,
|
||||||
|
|
||||||
// For debugger
|
// For debugger
|
||||||
|
|
||||||
BREAKPOINT = 148;
|
BREAKPOINT = 149;
|
||||||
// end enum
|
// end enum
|
||||||
|
|
||||||
|
|
||||||
|
@ -354,6 +355,7 @@ public class TokenStream {
|
||||||
"setparent",
|
"setparent",
|
||||||
"scope",
|
"scope",
|
||||||
"getscopeparent",
|
"getscopeparent",
|
||||||
|
"thisfn",
|
||||||
"jthrow",
|
"jthrow",
|
||||||
"semi",
|
"semi",
|
||||||
"lb",
|
"lb",
|
||||||
|
|
|
@ -49,4 +49,6 @@ public interface DebuggableEngine {
|
||||||
public Debugger getDebugger();
|
public Debugger getDebugger();
|
||||||
|
|
||||||
public Frame getFrame(int frameNumber);
|
public Frame getFrame(int frameNumber);
|
||||||
|
|
||||||
|
//public void haltExecution();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ import java.util.Enumeration;
|
||||||
* code (either functions or top-level scripts).
|
* code (either functions or top-level scripts).
|
||||||
*/
|
*/
|
||||||
public interface DebuggableScript {
|
public interface DebuggableScript {
|
||||||
|
|
||||||
|
//public boolean isFunction(); // XXX
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Scriptable object (Function or Script) that is
|
* Get the Scriptable object (Function or Script) that is
|
||||||
|
|
|
@ -1,696 +0,0 @@
|
||||||
/*
|
|
||||||
* The contents of this file are subject to the Netscape 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/NPL/
|
|
||||||
*
|
|
||||||
* 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 Rhino code, released
|
|
||||||
* May 6, 1999.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is Netscape
|
|
||||||
* Communications Corporation. Portions created by Netscape are
|
|
||||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
|
||||||
* Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Norris Boyd
|
|
||||||
* Roger Lawrence
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the
|
|
||||||
* terms of the GNU Public License (the "GPL"), in which case the
|
|
||||||
* provisions of the GPL are applicable instead of those above.
|
|
||||||
* If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of the GPL and not to allow others to use your
|
|
||||||
* version of this file under the NPL, indicate your decision by
|
|
||||||
* deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this
|
|
||||||
* file under either the NPL or the GPL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.mozilla.javascript.optimizer;
|
|
||||||
|
|
||||||
import org.mozilla.javascript.*;
|
|
||||||
import org.mozilla.classfile.*;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
public class Block {
|
|
||||||
|
|
||||||
public Block(int startNodeIndex, int endNodeIndex, Node[] statementNodes)
|
|
||||||
{
|
|
||||||
itsStartNodeIndex = startNodeIndex;
|
|
||||||
itsEndNodeIndex = endNodeIndex;
|
|
||||||
itsStatementNodes = statementNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockID(int id) { itsBlockID = id; }
|
|
||||||
public int getBlockID() { return itsBlockID; }
|
|
||||||
public Node getStartNode() { return itsStatementNodes[itsStartNodeIndex]; }
|
|
||||||
public Node getEndNode() { return itsStatementNodes[itsEndNodeIndex]; }
|
|
||||||
|
|
||||||
public Block[] getPredecessorList() { return itsPredecessors; }
|
|
||||||
public Block[] getSuccessorList() { return itsSuccessors; }
|
|
||||||
|
|
||||||
public static Block[] buildBlocks(Node[] statementNodes)
|
|
||||||
{
|
|
||||||
// a mapping from each target node to the block it begins
|
|
||||||
Hashtable theTargetBlocks = new Hashtable();
|
|
||||||
Vector theBlocks = new Vector();
|
|
||||||
|
|
||||||
// there's a block that starts at index 0
|
|
||||||
int beginNodeIndex = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < statementNodes.length; i++) {
|
|
||||||
switch (statementNodes[i].getType()) {
|
|
||||||
case TokenStream.TARGET :
|
|
||||||
{
|
|
||||||
if (i != beginNodeIndex) {
|
|
||||||
FatBlock fb = new FatBlock(beginNodeIndex,
|
|
||||||
i - 1, statementNodes);
|
|
||||||
if (statementNodes[beginNodeIndex].getType()
|
|
||||||
== TokenStream.TARGET)
|
|
||||||
theTargetBlocks.put(statementNodes[beginNodeIndex], fb);
|
|
||||||
theBlocks.addElement(fb);
|
|
||||||
// start the next block at this node
|
|
||||||
beginNodeIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.IFNE :
|
|
||||||
case TokenStream.IFEQ :
|
|
||||||
case TokenStream.GOTO :
|
|
||||||
{
|
|
||||||
FatBlock fb = new FatBlock(beginNodeIndex,
|
|
||||||
i, statementNodes);
|
|
||||||
if (statementNodes[beginNodeIndex].getType()
|
|
||||||
== TokenStream.TARGET)
|
|
||||||
theTargetBlocks.put(statementNodes[beginNodeIndex], fb);
|
|
||||||
theBlocks.addElement(fb);
|
|
||||||
// start the next block at the next node
|
|
||||||
beginNodeIndex = i + 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((beginNodeIndex != statementNodes.length)) {
|
|
||||||
FatBlock fb = new FatBlock(beginNodeIndex,
|
|
||||||
statementNodes.length - 1,
|
|
||||||
statementNodes);
|
|
||||||
if (statementNodes[beginNodeIndex].getType() == TokenStream.TARGET)
|
|
||||||
theTargetBlocks.put(statementNodes[beginNodeIndex], fb);
|
|
||||||
theBlocks.addElement(fb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// build successor and predecessor links
|
|
||||||
|
|
||||||
for (int i = 0; i < theBlocks.size(); i++) {
|
|
||||||
FatBlock fb = (FatBlock)(theBlocks.elementAt(i));
|
|
||||||
|
|
||||||
Node blockEndNode = fb.getEndNode();
|
|
||||||
int blockEndNodeType = blockEndNode.getType();
|
|
||||||
|
|
||||||
if ((blockEndNodeType != TokenStream.GOTO)
|
|
||||||
&& (i < (theBlocks.size() - 1))) {
|
|
||||||
FatBlock fallThruTarget = (FatBlock)(theBlocks.elementAt(i + 1));
|
|
||||||
fb.addSuccessor(fallThruTarget);
|
|
||||||
fallThruTarget.addPredecessor(fb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( (blockEndNodeType == TokenStream.IFNE)
|
|
||||||
|| (blockEndNodeType == TokenStream.IFEQ)
|
|
||||||
|| (blockEndNodeType == TokenStream.GOTO) ) {
|
|
||||||
Node target = (Node)(blockEndNode.getProp(Node.TARGET_PROP));
|
|
||||||
FatBlock branchTargetBlock
|
|
||||||
= (FatBlock)(theTargetBlocks.get(target));
|
|
||||||
target.putProp(Node.TARGETBLOCK_PROP,
|
|
||||||
branchTargetBlock.getSlimmerSelf());
|
|
||||||
fb.addSuccessor(branchTargetBlock);
|
|
||||||
branchTargetBlock.addPredecessor(fb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Block[] result = new Block[theBlocks.size()];
|
|
||||||
|
|
||||||
for (int i = 0; i < theBlocks.size(); i++) {
|
|
||||||
FatBlock fb = (FatBlock)(theBlocks.elementAt(i));
|
|
||||||
result[i] = fb.diet();
|
|
||||||
result[i].setBlockID(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toString(Block[] blockList, Node[] statementNodes)
|
|
||||||
{
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
|
||||||
|
|
||||||
pw.println(blockList.length + " Blocks");
|
|
||||||
for (int i = 0; i < blockList.length; i++) {
|
|
||||||
Block b = blockList[i];
|
|
||||||
pw.println("#" + b.itsBlockID);
|
|
||||||
pw.println("from " + b.itsStartNodeIndex
|
|
||||||
+ " "
|
|
||||||
+ statementNodes[b.itsStartNodeIndex].toString());
|
|
||||||
pw.println("thru " + b.itsEndNodeIndex
|
|
||||||
+ " "
|
|
||||||
+ statementNodes[b.itsEndNodeIndex].toString());
|
|
||||||
pw.print("Predecessors ");
|
|
||||||
if (b.itsPredecessors != null) {
|
|
||||||
for (int j = 0; j < b.itsPredecessors.length; j++)
|
|
||||||
pw.print(b.itsPredecessors[j].getBlockID() + " ");
|
|
||||||
pw.println();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pw.println("none");
|
|
||||||
pw.print("Successors ");
|
|
||||||
if (b.itsSuccessors != null) {
|
|
||||||
for (int j = 0; j < b.itsSuccessors.length; j++)
|
|
||||||
pw.print(b.itsSuccessors[j].getBlockID() + " ");
|
|
||||||
pw.println();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pw.println("none");
|
|
||||||
}
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
We maintain the liveSet as each statement executes, identifying
|
|
||||||
those variables that are live across function calls
|
|
||||||
|
|
||||||
*/
|
|
||||||
void lookForVariablesAndCalls(Node n, boolean liveSet[],
|
|
||||||
VariableTable theVariables)
|
|
||||||
{
|
|
||||||
switch (n.getType()) {
|
|
||||||
case TokenStream.SETVAR :
|
|
||||||
{
|
|
||||||
Node lhs = n.getFirstChild();
|
|
||||||
Node rhs = lhs.getNextSibling();
|
|
||||||
lookForVariablesAndCalls(rhs, liveSet, theVariables);
|
|
||||||
Object theVarProp = n.getProp(Node.VARIABLE_PROP);
|
|
||||||
if (theVarProp != null) {
|
|
||||||
int theVarIndex = ((OptLocalVariable)theVarProp).getIndex();
|
|
||||||
liveSet[theVarIndex] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.CALL : {
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
|
||||||
lookForVariablesAndCalls(child, liveSet, theVariables);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < liveSet.length; i++) {
|
|
||||||
if (liveSet[i])
|
|
||||||
((OptLocalVariable)theVariables.get(i)).markLiveAcrossCall();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.GETVAR :
|
|
||||||
{
|
|
||||||
Object theVarProp = n.getProp(Node.VARIABLE_PROP);
|
|
||||||
if (theVarProp != null) {
|
|
||||||
int theVarIndex = ((OptLocalVariable)theVarProp).getIndex();
|
|
||||||
if ((n.getProp(Node.LASTUSE_PROP) != null)
|
|
||||||
&& !itsLiveOnExitSet.test(theVarIndex))
|
|
||||||
liveSet[theVarIndex] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
|
||||||
lookForVariablesAndCalls(child, liveSet, theVariables);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void markAnyTypeVariables(VariableTable theVariables)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < theVariables.size(); i++)
|
|
||||||
if (itsLiveOnEntrySet.test(i))
|
|
||||||
((OptLocalVariable)theVariables.get(i)).assignType(TypeEvent.AnyType);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void markVolatileVariables(VariableTable theVariables)
|
|
||||||
{
|
|
||||||
boolean liveSet[] = new boolean[theVariables.size()];
|
|
||||||
for (int i = 0; i < liveSet.length; i++)
|
|
||||||
liveSet[i] = itsLiveOnEntrySet.test(i);
|
|
||||||
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
|
|
||||||
Node n = itsStatementNodes[i];
|
|
||||||
lookForVariablesAndCalls(n, liveSet, theVariables);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
We're tracking uses and defs - in order to
|
|
||||||
build the def set and to identify the last use
|
|
||||||
nodes.
|
|
||||||
|
|
||||||
The itsNotDefSet is built reversed then flipped later.
|
|
||||||
|
|
||||||
*/
|
|
||||||
void lookForVariableAccess(Node n, Node lastUse[])
|
|
||||||
{
|
|
||||||
switch (n.getType()) {
|
|
||||||
case TokenStream.DEC :
|
|
||||||
case TokenStream.INC :
|
|
||||||
{
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
if (child.getType() == TokenStream.GETVAR) {
|
|
||||||
Object theVarProp = child.getProp(Node.VARIABLE_PROP);
|
|
||||||
if (theVarProp != null) {
|
|
||||||
int theVarIndex = ((OptLocalVariable)theVarProp).getIndex();
|
|
||||||
if (!itsNotDefSet.test(theVarIndex))
|
|
||||||
itsUseBeforeDefSet.set(theVarIndex);
|
|
||||||
itsNotDefSet.set(theVarIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.SETVAR :
|
|
||||||
{
|
|
||||||
Node lhs = n.getFirstChild();
|
|
||||||
Node rhs = lhs.getNextSibling();
|
|
||||||
lookForVariableAccess(rhs, lastUse);
|
|
||||||
Object theVarProp = n.getProp(Node.VARIABLE_PROP);
|
|
||||||
if (theVarProp != null) {
|
|
||||||
int theVarIndex = ((OptLocalVariable)theVarProp).getIndex();
|
|
||||||
itsNotDefSet.set(theVarIndex);
|
|
||||||
if (lastUse[theVarIndex] != null)
|
|
||||||
lastUse[theVarIndex].putProp(Node.LASTUSE_PROP,
|
|
||||||
theVarProp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.GETVAR :
|
|
||||||
{
|
|
||||||
Object theVarProp = n.getProp(Node.VARIABLE_PROP);
|
|
||||||
if (theVarProp != null) {
|
|
||||||
int theVarIndex = ((OptLocalVariable)theVarProp).getIndex();
|
|
||||||
if (!itsNotDefSet.test(theVarIndex))
|
|
||||||
itsUseBeforeDefSet.set(theVarIndex);
|
|
||||||
lastUse[theVarIndex] = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
|
||||||
lookForVariableAccess(child, lastUse);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
build the live on entry/exit sets.
|
|
||||||
Then walk the trees looking for defs/uses of variables
|
|
||||||
and build the def and useBeforeDef sets.
|
|
||||||
*/
|
|
||||||
public void initLiveOnEntrySets(VariableTable theVariables)
|
|
||||||
{
|
|
||||||
int listLength = theVariables.size();
|
|
||||||
Node lastUse[] = new Node[listLength];
|
|
||||||
itsUseBeforeDefSet = new DataFlowBitSet(listLength);
|
|
||||||
itsNotDefSet = new DataFlowBitSet(listLength);
|
|
||||||
itsLiveOnEntrySet = new DataFlowBitSet(listLength);
|
|
||||||
itsLiveOnExitSet = new DataFlowBitSet(listLength);
|
|
||||||
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
|
|
||||||
Node n = itsStatementNodes[i];
|
|
||||||
lookForVariableAccess(n, lastUse);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < listLength; i++) {
|
|
||||||
if (lastUse[i] != null)
|
|
||||||
lastUse[i].putProp(Node.LASTUSE_PROP, this);
|
|
||||||
}
|
|
||||||
itsNotDefSet.not(); // truth in advertising
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
the liveOnEntry of each successor is the liveOnExit for this block.
|
|
||||||
The liveOnEntry for this block is -
|
|
||||||
liveOnEntry = liveOnExit - defsInThisBlock + useBeforeDefsInThisBlock
|
|
||||||
|
|
||||||
*/
|
|
||||||
boolean doReachedUseDataFlow()
|
|
||||||
{
|
|
||||||
itsLiveOnExitSet.clear();
|
|
||||||
if (itsSuccessors != null)
|
|
||||||
for (int i = 0; i < itsSuccessors.length; i++)
|
|
||||||
itsLiveOnExitSet.or(itsSuccessors[i].itsLiveOnEntrySet);
|
|
||||||
return itsLiveOnEntrySet.df2(itsLiveOnExitSet,
|
|
||||||
itsUseBeforeDefSet, itsNotDefSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
the type of an expression is relatively unknown. Cases we can be sure
|
|
||||||
about are -
|
|
||||||
Literals,
|
|
||||||
Arithmetic operations - always return a Number
|
|
||||||
*/
|
|
||||||
int findExpressionType(Node n)
|
|
||||||
{
|
|
||||||
switch (n.getType()) {
|
|
||||||
case TokenStream.NUMBER : {
|
|
||||||
/* distinguish between integers & f.p.s ?
|
|
||||||
Number num = ((NumberNode)n).getNumber();
|
|
||||||
if ((num instanceof Byte)
|
|
||||||
|| (num instanceof Short)
|
|
||||||
|| (num instanceof Integer)) {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return TypeEvent.NumberType;
|
|
||||||
}
|
|
||||||
case TokenStream.NEW :
|
|
||||||
case TokenStream.CALL :
|
|
||||||
return TypeEvent.NoType;
|
|
||||||
|
|
||||||
case TokenStream.GETELEM :
|
|
||||||
return TypeEvent.AnyType;
|
|
||||||
|
|
||||||
case TokenStream.GETVAR : {
|
|
||||||
OptLocalVariable theVar = (OptLocalVariable)
|
|
||||||
(n.getProp(Node.VARIABLE_PROP));
|
|
||||||
if (theVar != null)
|
|
||||||
return theVar.getTypeUnion();
|
|
||||||
}
|
|
||||||
|
|
||||||
case TokenStream.INC :
|
|
||||||
case TokenStream.DEC :
|
|
||||||
case TokenStream.DIV:
|
|
||||||
case TokenStream.MOD:
|
|
||||||
case TokenStream.BITOR:
|
|
||||||
case TokenStream.BITXOR:
|
|
||||||
case TokenStream.BITAND:
|
|
||||||
case TokenStream.LSH:
|
|
||||||
case TokenStream.RSH:
|
|
||||||
case TokenStream.URSH:
|
|
||||||
case TokenStream.SUB : {
|
|
||||||
return TypeEvent.NumberType;
|
|
||||||
}
|
|
||||||
case TokenStream.ADD : {
|
|
||||||
// if the lhs & rhs are known to be numbers, we can be sure that's
|
|
||||||
// the result, otherwise it could be a string.
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
int lType = findExpressionType(child);
|
|
||||||
int rType = findExpressionType(child.getNextSibling());
|
|
||||||
return lType | rType; // we're not distinguishng strings yet
|
|
||||||
}
|
|
||||||
default : {
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
if (child == null)
|
|
||||||
return TypeEvent.AnyType;
|
|
||||||
else {
|
|
||||||
int result = TypeEvent.NoType;
|
|
||||||
while (child != null) {
|
|
||||||
result |= findExpressionType(child);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean findDefPoints(Node n)
|
|
||||||
{
|
|
||||||
boolean result = false;
|
|
||||||
switch (n.getType()) {
|
|
||||||
default : {
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
|
||||||
result |= findDefPoints(child);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.DEC :
|
|
||||||
case TokenStream.INC : {
|
|
||||||
Node firstChild = n.getFirstChild();
|
|
||||||
OptLocalVariable theVar = (OptLocalVariable)
|
|
||||||
(firstChild.getProp(Node.VARIABLE_PROP));
|
|
||||||
if (theVar != null) {
|
|
||||||
// theVar is a Number now
|
|
||||||
result |= theVar.assignType(TypeEvent.NumberType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TokenStream.SETPROP : {
|
|
||||||
Node baseChild = n.getFirstChild();
|
|
||||||
Node nameChild = baseChild.getNextSibling();
|
|
||||||
Node rhs = nameChild.getNextSibling();
|
|
||||||
if (baseChild != null) {
|
|
||||||
if (baseChild.getType() == TokenStream.GETVAR) {
|
|
||||||
OptLocalVariable theVar = (OptLocalVariable)
|
|
||||||
(baseChild.getProp(Node.VARIABLE_PROP));
|
|
||||||
if (theVar != null)
|
|
||||||
theVar.assignType(TypeEvent.AnyType);
|
|
||||||
}
|
|
||||||
result |= findDefPoints(baseChild);
|
|
||||||
}
|
|
||||||
if (nameChild != null) result |= findDefPoints(nameChild);
|
|
||||||
if (rhs != null) result |= findDefPoints(rhs);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TokenStream.SETVAR : {
|
|
||||||
Node firstChild = n.getFirstChild();
|
|
||||||
OptLocalVariable theVar = (OptLocalVariable)
|
|
||||||
(n.getProp(Node.VARIABLE_PROP));
|
|
||||||
if (theVar != null) {
|
|
||||||
Node rValue = firstChild.getNextSibling();
|
|
||||||
int theType = findExpressionType(rValue);
|
|
||||||
result |= theVar.assignType(theType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a total misnomer for now. To start with we're only trying to find
|
|
||||||
// duplicate getProp calls on 'this' that can be merged
|
|
||||||
void localCSE(Node parent, Node n, Hashtable theCSETable, OptFunctionNode theFunction)
|
|
||||||
{
|
|
||||||
switch (n.getType()) {
|
|
||||||
default : {
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
|
||||||
localCSE(n, child, theCSETable, theFunction);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.DEC :
|
|
||||||
case TokenStream.INC : {
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
if (child.getType() == TokenStream.GETPROP) {
|
|
||||||
Node nameChild = child.getFirstChild().getNextSibling();
|
|
||||||
if (nameChild.getType() == TokenStream.STRING)
|
|
||||||
theCSETable.remove(nameChild.getString());
|
|
||||||
else
|
|
||||||
theCSETable.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (child.getType() != TokenStream.GETVAR)
|
|
||||||
theCSETable.clear();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.SETPROP : {
|
|
||||||
Node baseChild = n.getFirstChild();
|
|
||||||
Node nameChild = baseChild.getNextSibling();
|
|
||||||
Node rhs = nameChild.getNextSibling();
|
|
||||||
if (baseChild != null) localCSE(n, baseChild, theCSETable, theFunction);
|
|
||||||
if (nameChild != null) localCSE(n, nameChild, theCSETable, theFunction);
|
|
||||||
if (rhs != null) localCSE(n, rhs, theCSETable, theFunction);
|
|
||||||
if (nameChild.getType() == TokenStream.STRING) {
|
|
||||||
theCSETable.remove(nameChild.getString());
|
|
||||||
// System.out.println("clear at SETPROP " + ((StringNode)nameChild).getString());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
theCSETable.clear();
|
|
||||||
// System.out.println("clear all at SETPROP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.GETPROP : {
|
|
||||||
Node baseChild = n.getFirstChild();
|
|
||||||
if (baseChild != null) localCSE(n, baseChild, theCSETable, theFunction);
|
|
||||||
if ((baseChild.getType() == TokenStream.PRIMARY)
|
|
||||||
&& (baseChild.getInt() == TokenStream.THIS)) {
|
|
||||||
Node nameChild = baseChild.getNextSibling();
|
|
||||||
if (nameChild.getType() == TokenStream.STRING) {
|
|
||||||
String theName = nameChild.getString();
|
|
||||||
// System.out.println("considering " + theName);
|
|
||||||
Object cse = theCSETable.get(theName);
|
|
||||||
if (cse == null) {
|
|
||||||
theCSETable.put(theName, new CSEHolder(parent, n));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (parent != null) {
|
|
||||||
// System.out.println("Yay for " + theName);
|
|
||||||
Node theCSE;
|
|
||||||
if (cse instanceof CSEHolder) {
|
|
||||||
CSEHolder cseHolder = (CSEHolder)cse;
|
|
||||||
Node nextChild = cseHolder.getPropChild.getNextSibling();
|
|
||||||
cseHolder.getPropParent.removeChild(cseHolder.getPropChild);
|
|
||||||
theCSE = itsIRFactory.createNewLocal(cseHolder.getPropChild);
|
|
||||||
theFunction.incrementLocalCount();
|
|
||||||
if (nextChild == null)
|
|
||||||
cseHolder.getPropParent.addChildToBack(theCSE);
|
|
||||||
else
|
|
||||||
cseHolder.getPropParent.addChildBefore(theCSE, nextChild);
|
|
||||||
theCSETable.put(theName, theCSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
theCSE = (Node)cse;
|
|
||||||
Node nextChild = n.getNextSibling();
|
|
||||||
parent.removeChild(n);
|
|
||||||
Node cseUse = itsIRFactory.createUseLocal(theCSE);
|
|
||||||
if (nextChild == null)
|
|
||||||
parent.addChildToBack(cseUse);
|
|
||||||
else
|
|
||||||
parent.addChildBefore(cseUse, nextChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.SETELEM : {
|
|
||||||
Node lhsBase = n.getFirstChild();
|
|
||||||
Node lhsIndex = lhsBase.getNextSibling();
|
|
||||||
Node rhs = lhsIndex.getNextSibling();
|
|
||||||
if (lhsBase != null) localCSE(n, lhsBase, theCSETable, theFunction);
|
|
||||||
if (lhsIndex != null) localCSE(n, lhsIndex, theCSETable, theFunction);
|
|
||||||
if (rhs != null) localCSE(n, rhs, theCSETable, theFunction);
|
|
||||||
theCSETable.clear();
|
|
||||||
//System.out.println("clear all at SETELEM");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TokenStream.CALL : {
|
|
||||||
Node child = n.getFirstChild();
|
|
||||||
while (child != null) {
|
|
||||||
localCSE(n, child, theCSETable, theFunction);
|
|
||||||
child = child.getNextSibling();
|
|
||||||
}
|
|
||||||
theCSETable.clear();
|
|
||||||
//System.out.println("clear all at CALL");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
if (n != null)
|
|
||||||
localCSE(null, n, theCSETable, theFunction);
|
|
||||||
}
|
|
||||||
return theCSETable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findDefs()
|
|
||||||
{
|
|
||||||
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
|
|
||||||
Node n = itsStatementNodes[i];
|
|
||||||
if (n != null)
|
|
||||||
findDefPoints(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean doTypeFlow()
|
|
||||||
{
|
|
||||||
boolean changed = false;
|
|
||||||
|
|
||||||
for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) {
|
|
||||||
Node n = itsStatementNodes[i];
|
|
||||||
if (n != null)
|
|
||||||
changed |= findDefPoints(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLiveOnEntry(int index)
|
|
||||||
{
|
|
||||||
return (itsLiveOnEntrySet != null) && (itsLiveOnEntrySet.test(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printLiveOnEntrySet(PrintWriter pw, VariableTable theVariables)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < theVariables.size(); i++) {
|
|
||||||
if (itsUseBeforeDefSet.test(i))
|
|
||||||
pw.println(theVariables.get(i).getName() + " is used before def'd");
|
|
||||||
if (itsNotDefSet.test(i))
|
|
||||||
pw.println(theVariables.get(i).getName() + " is not def'd");
|
|
||||||
if (itsLiveOnEntrySet.test(i))
|
|
||||||
pw.println(theVariables.get(i).getName() + " is live on entry");
|
|
||||||
if (itsLiveOnExitSet.test(i))
|
|
||||||
pw.println(theVariables.get(i).getName() + " is live on exit");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSuccessorList(Block[] b) { itsSuccessors = b; }
|
|
||||||
public void setPredecessorList(Block[] b) { itsPredecessors = b; }
|
|
||||||
|
|
||||||
// all the Blocks that come immediately after this
|
|
||||||
private Block[] itsSuccessors;
|
|
||||||
// all the Blocks that come immediately before this
|
|
||||||
private Block[] itsPredecessors;
|
|
||||||
|
|
||||||
private int itsStartNodeIndex; // the Node at the start of the block
|
|
||||||
private int itsEndNodeIndex; // the Node at the end of the block
|
|
||||||
private Node itsStatementNodes[]; // the list of all statement nodes
|
|
||||||
|
|
||||||
private int itsBlockID; // a unique index for each block
|
|
||||||
|
|
||||||
// reaching def bit sets -
|
|
||||||
private DataFlowBitSet itsLiveOnEntrySet;
|
|
||||||
private DataFlowBitSet itsLiveOnExitSet;
|
|
||||||
private DataFlowBitSet itsUseBeforeDefSet;
|
|
||||||
private DataFlowBitSet itsNotDefSet;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class CSEHolder {
|
|
||||||
|
|
||||||
CSEHolder(Node parent, Node child)
|
|
||||||
{
|
|
||||||
getPropParent = parent;
|
|
||||||
getPropChild = child;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node getPropParent;
|
|
||||||
Node getPropChild;
|
|
||||||
|
|
||||||
}
|
|
|
@ -457,7 +457,7 @@ public class Codegen extends Interpreter {
|
||||||
// make sure that all parameters are objects
|
// make sure that all parameters are objects
|
||||||
itsForcedObjectParameters = true;
|
itsForcedObjectParameters = true;
|
||||||
for (int i = 0; i < vars.getParameterCount(); i++) {
|
for (int i = 0; i < vars.getParameterCount(); i++) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) vars.get(i);
|
OptLocalVariable lVar = (OptLocalVariable) vars.getVariable(i);
|
||||||
aload(lVar.getJRegister());
|
aload(lVar.getJRegister());
|
||||||
classFile.add(ByteCode.GETSTATIC,
|
classFile.add(ByteCode.GETSTATIC,
|
||||||
"java/lang/Void",
|
"java/lang/Void",
|
||||||
|
@ -1347,12 +1347,18 @@ public class Codegen extends Interpreter {
|
||||||
addByteCode(ByteCode.ACONST_NULL);
|
addByteCode(ByteCode.ACONST_NULL);
|
||||||
}
|
}
|
||||||
// load 'cx'
|
// load 'cx'
|
||||||
aload(contextLocal);
|
aload(contextLocal);
|
||||||
|
// load boolean indicating whether fn name should be set in scope
|
||||||
|
boolean setFnName = str != null && str.length() > 0 &&
|
||||||
|
((FunctionNode) def).getFunctionType() !=
|
||||||
|
FunctionNode.FUNCTION_EXPRESSION;
|
||||||
|
addByteCode(setFnName ? ByteCode.ICONST_1 : ByteCode.ICONST_0);
|
||||||
|
|
||||||
addScriptRuntimeInvoke("initFunction",
|
addScriptRuntimeInvoke("initFunction",
|
||||||
"(Lorg/mozilla/javascript/NativeFunction;" +
|
"(Lorg/mozilla/javascript/NativeFunction;" +
|
||||||
"Lorg/mozilla/javascript/Scriptable;" +
|
"Lorg/mozilla/javascript/Scriptable;" +
|
||||||
"Ljava/lang/String;" +
|
"Ljava/lang/String;" +
|
||||||
"Lorg/mozilla/javascript/Context;)",
|
"Lorg/mozilla/javascript/Context;Z)",
|
||||||
"Lorg/mozilla/javascript/NativeFunction;");
|
"Lorg/mozilla/javascript/NativeFunction;");
|
||||||
def.putProp(Node.FUNCTION_PROP, new Short(i));
|
def.putProp(Node.FUNCTION_PROP, new Short(i));
|
||||||
addByteCode(ByteCode.AASTORE); // store NativeFunction
|
addByteCode(ByteCode.AASTORE); // store NativeFunction
|
||||||
|
@ -1447,7 +1453,7 @@ public class Codegen extends Interpreter {
|
||||||
// before the next call and are used in the function
|
// before the next call and are used in the function
|
||||||
short firstUndefVar = -1;
|
short firstUndefVar = -1;
|
||||||
for (int i = 0; i < vars.size(); i++) {
|
for (int i = 0; i < vars.size(); i++) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) vars.get(i);
|
OptLocalVariable lVar = (OptLocalVariable) vars.getVariable(i);
|
||||||
if (lVar.isNumber()) {
|
if (lVar.isNumber()) {
|
||||||
lVar.assignJRegister(getNewWordPairLocal());
|
lVar.assignJRegister(getNewWordPairLocal());
|
||||||
push(0.0);
|
push(0.0);
|
||||||
|
@ -1547,7 +1553,7 @@ public class Codegen extends Interpreter {
|
||||||
if (cx.isGeneratingDebug()) {
|
if (cx.isGeneratingDebug()) {
|
||||||
debugVars = new OptVariableTable();
|
debugVars = new OptVariableTable();
|
||||||
debugVars.addLocal(debugVariableName);
|
debugVars.addLocal(debugVariableName);
|
||||||
OptLocalVariable lv = (OptLocalVariable) debugVars.get(debugVariableName);
|
OptLocalVariable lv = (OptLocalVariable) debugVars.getVariable(debugVariableName);
|
||||||
lv.assignJRegister(variableObjectLocal);
|
lv.assignJRegister(variableObjectLocal);
|
||||||
lv.setStartPC(classFile.getCurrentCodeOffset());
|
lv.setStartPC(classFile.getCurrentCodeOffset());
|
||||||
}
|
}
|
||||||
|
@ -1876,7 +1882,6 @@ public class Codegen extends Interpreter {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (true) {
|
|
||||||
Node callBase = callNode.getFirstChild();
|
Node callBase = callNode.getFirstChild();
|
||||||
if (callBase.getType() == TokenStream.GETPROP) {
|
if (callBase.getType() == TokenStream.GETPROP) {
|
||||||
Node callBaseChild = callBase.getFirstChild();
|
Node callBaseChild = callBase.getFirstChild();
|
||||||
|
@ -1903,7 +1908,6 @@ if (true) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2425,7 +2429,7 @@ if (true) {
|
||||||
}
|
}
|
||||||
String name = node.getString();
|
String name = node.getString();
|
||||||
if (hasVarsInRegs) {
|
if (hasVarsInRegs) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) vars.get(name);
|
OptLocalVariable lVar = (OptLocalVariable) vars.getVariable(name);
|
||||||
if (lVar != null) {
|
if (lVar != null) {
|
||||||
if (lVar.isNumber()) {
|
if (lVar.isNumber()) {
|
||||||
push("number");
|
push("number");
|
||||||
|
@ -2463,7 +2467,7 @@ if (true) {
|
||||||
String routine = (isInc) ? "postIncrement" : "postDecrement";
|
String routine = (isInc) ? "postIncrement" : "postDecrement";
|
||||||
if (hasVarsInRegs && child.getType() == TokenStream.GETVAR) {
|
if (hasVarsInRegs && child.getType() == TokenStream.GETVAR) {
|
||||||
if (lVar == null)
|
if (lVar == null)
|
||||||
lVar = (OptLocalVariable) vars.get(child.getString());
|
lVar = (OptLocalVariable) vars.getVariable(child.getString());
|
||||||
if (lVar.getJRegister() == -1)
|
if (lVar.getJRegister() == -1)
|
||||||
lVar.assignJRegister(getNewWordLocal());
|
lVar.assignJRegister(getNewWordLocal());
|
||||||
aload(lVar.getJRegister());
|
aload(lVar.getJRegister());
|
||||||
|
@ -3173,6 +3177,10 @@ if (true) {
|
||||||
aload(thisObjLocal);
|
aload(thisObjLocal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TokenStream.THISFN:
|
||||||
|
classFile.add(ByteCode.ALOAD_0);
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenStream.NULL:
|
case TokenStream.NULL:
|
||||||
addByteCode(ByteCode.ACONST_NULL);
|
addByteCode(ByteCode.ACONST_NULL);
|
||||||
break;
|
break;
|
||||||
|
@ -3232,7 +3240,7 @@ if (true) {
|
||||||
{
|
{
|
||||||
// TODO: Clean up use of lVar here and in set.
|
// TODO: Clean up use of lVar here and in set.
|
||||||
if (hasVarsInRegs && lVar == null)
|
if (hasVarsInRegs && lVar == null)
|
||||||
lVar = (OptLocalVariable) vars.get(name);
|
lVar = (OptLocalVariable) vars.getVariable(name);
|
||||||
if (lVar != null) {
|
if (lVar != null) {
|
||||||
if (lVar.getJRegister() == -1)
|
if (lVar.getJRegister() == -1)
|
||||||
if (lVar.isNumber())
|
if (lVar.isNumber())
|
||||||
|
@ -3303,7 +3311,7 @@ if (true) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable)(node.getProp(Node.VARIABLE_PROP));
|
OptLocalVariable lVar = (OptLocalVariable)(node.getProp(Node.VARIABLE_PROP));
|
||||||
// XXX is this right? If so, clean up.
|
// XXX is this right? If so, clean up.
|
||||||
if (hasVarsInRegs && lVar == null)
|
if (hasVarsInRegs && lVar == null)
|
||||||
lVar = (OptLocalVariable) vars.get(child.getString());
|
lVar = (OptLocalVariable) vars.getVariable(child.getString());
|
||||||
if (lVar != null) {
|
if (lVar != null) {
|
||||||
generateCodeFromNode(child.getNextSibling(), node, -1, -1);
|
generateCodeFromNode(child.getNextSibling(), node, -1, -1);
|
||||||
if (lVar.getJRegister() == -1) {
|
if (lVar.getJRegister() == -1) {
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -362,7 +362,8 @@ public class ClassFileWriter extends LabelTable {
|
||||||
codeAttribute[index++] = (byte)(varCount >> 8);
|
codeAttribute[index++] = (byte)(varCount >> 8);
|
||||||
codeAttribute[index++] = (byte)varCount;
|
codeAttribute[index++] = (byte)varCount;
|
||||||
for (int i = 0; i < varCount; i++) {
|
for (int i = 0; i < varCount; i++) {
|
||||||
LocalVariable lvar = vars.get(i);
|
LocalVariable lvar = vars.getVariable(i);
|
||||||
|
|
||||||
// start pc
|
// start pc
|
||||||
int startPc = lvar.getStartPC();
|
int startPc = lvar.getStartPC();
|
||||||
codeAttribute[index++] = (byte)(startPc >> 8);
|
codeAttribute[index++] = (byte)(startPc >> 8);
|
||||||
|
|
|
@ -174,8 +174,8 @@ public class Interpreter extends LabelTable {
|
||||||
boolean needsActivation = theFunction.requiresActivation() ||
|
boolean needsActivation = theFunction.requiresActivation() ||
|
||||||
cx.isGeneratingDebug();
|
cx.isGeneratingDebug();
|
||||||
generateICodeFromTree(theFunction.getLastChild(),
|
generateICodeFromTree(theFunction.getLastChild(),
|
||||||
varTable, needsActivation,
|
varTable, needsActivation,
|
||||||
securityDomain);
|
securityDomain);
|
||||||
|
|
||||||
itsData.itsName = theFunction.getFunctionName();
|
itsData.itsName = theFunction.getFunctionName();
|
||||||
itsData.itsSourceFile = (String) theFunction.getProp(
|
itsData.itsSourceFile = (String) theFunction.getProp(
|
||||||
|
@ -1204,6 +1204,7 @@ public class Interpreter extends LabelTable {
|
||||||
case TokenStream.ONE :
|
case TokenStream.ONE :
|
||||||
case TokenStream.NULL :
|
case TokenStream.NULL :
|
||||||
case TokenStream.THIS :
|
case TokenStream.THIS :
|
||||||
|
case TokenStream.THISFN :
|
||||||
case TokenStream.FALSE :
|
case TokenStream.FALSE :
|
||||||
case TokenStream.TRUE :
|
case TokenStream.TRUE :
|
||||||
case TokenStream.UNDEFINED :
|
case TokenStream.UNDEFINED :
|
||||||
|
@ -1802,6 +1803,9 @@ public class Interpreter extends LabelTable {
|
||||||
case TokenStream.THIS :
|
case TokenStream.THIS :
|
||||||
stack[++stackTop] = thisObj;
|
stack[++stackTop] = thisObj;
|
||||||
break;
|
break;
|
||||||
|
case TokenStream.THISFN :
|
||||||
|
stack[++stackTop] = fnOrScript;
|
||||||
|
break;
|
||||||
case TokenStream.FALSE :
|
case TokenStream.FALSE :
|
||||||
stack[++stackTop] = Boolean.FALSE;
|
stack[++stackTop] = Boolean.FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -80,7 +80,7 @@ class InterpreterData {
|
||||||
|
|
||||||
public boolean removeBreakpoint(int line) {
|
public boolean removeBreakpoint(int line) {
|
||||||
int offset = getOffset(line);
|
int offset = getOffset(line);
|
||||||
if (offset != -1 && itsICode[offset] == TokenStream.BREAKPOINT)
|
if (offset != -1 && itsICode[offset] == (byte) TokenStream.BREAKPOINT)
|
||||||
{
|
{
|
||||||
itsICode[offset] = (byte) TokenStream.LINE;
|
itsICode[offset] = (byte) TokenStream.LINE;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -449,7 +449,7 @@ public class NodeTransformer {
|
||||||
((FunctionNode) tree).setRequiresActivation(true);
|
((FunctionNode) tree).setRequiresActivation(true);
|
||||||
}
|
}
|
||||||
VariableTable vars = getVariableTable(tree);
|
VariableTable vars = getVariableTable(tree);
|
||||||
if (vars.get(name) != null) {
|
if (vars.getVariable(name) != null) {
|
||||||
if (type == TokenStream.SETNAME) {
|
if (type == TokenStream.SETNAME) {
|
||||||
node.setType(TokenStream.SETVAR);
|
node.setType(TokenStream.SETVAR);
|
||||||
bind.setType(TokenStream.STRING);
|
bind.setType(TokenStream.STRING);
|
||||||
|
@ -489,7 +489,7 @@ public class NodeTransformer {
|
||||||
((FunctionNode) tree).setRequiresActivation(true);
|
((FunctionNode) tree).setRequiresActivation(true);
|
||||||
}
|
}
|
||||||
VariableTable vars = getVariableTable(tree);
|
VariableTable vars = getVariableTable(tree);
|
||||||
if (vars.get(name) != null) {
|
if (vars.getVariable(name) != null) {
|
||||||
node.setType(TokenStream.GETVAR);
|
node.setType(TokenStream.GETVAR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -510,7 +510,9 @@ public class NodeTransformer {
|
||||||
while ((node = iterator.nextNode()) != null) {
|
while ((node = iterator.nextNode()) != null) {
|
||||||
int nodeType = node.getType();
|
int nodeType = node.getType();
|
||||||
if (inFunction && nodeType == TokenStream.FUNCTION &&
|
if (inFunction && nodeType == TokenStream.FUNCTION &&
|
||||||
node != tree)
|
node != tree &&
|
||||||
|
((FunctionNode) node.getProp(Node.FUNCTION_PROP)).getFunctionType() ==
|
||||||
|
FunctionNode.FUNCTION_EXPRESSION_STATEMENT)
|
||||||
{
|
{
|
||||||
// In a function with both "var x" and "function x",
|
// In a function with both "var x" and "function x",
|
||||||
// disregard the var statement, independent of order.
|
// disregard the var statement, independent of order.
|
||||||
|
@ -531,6 +533,26 @@ public class NodeTransformer {
|
||||||
vars.addLocal(n.getString());
|
vars.addLocal(n.getString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String name = (String) tree.getDatum();
|
||||||
|
if (inFunction && ((FunctionNode) tree).getFunctionType() ==
|
||||||
|
FunctionNode.FUNCTION_EXPRESSION &&
|
||||||
|
name != null && name.length() > 0 &&
|
||||||
|
vars.getVariable(name) == null)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
vars.addLocal(name);
|
||||||
|
Node block = tree.getLastChild();
|
||||||
|
Node setFn = new Node(TokenStream.POP,
|
||||||
|
new Node(TokenStream.SETVAR,
|
||||||
|
new Node(TokenStream.STRING, name),
|
||||||
|
new Node(TokenStream.PRIMARY,
|
||||||
|
new Integer(TokenStream.THISFN))));
|
||||||
|
block.addChildrenToFront(setFn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addParameters(FunctionNode fnNode) {
|
protected void addParameters(FunctionNode fnNode) {
|
||||||
|
@ -580,7 +602,9 @@ public class NodeTransformer {
|
||||||
if (left.getType() == TokenStream.NAME) {
|
if (left.getType() == TokenStream.NAME) {
|
||||||
VariableTable vars = getVariableTable(tree);
|
VariableTable vars = getVariableTable(tree);
|
||||||
String name = left.getString();
|
String name = left.getString();
|
||||||
if (inFunction && vars.get(name) != null && !inWithStatement()) {
|
if (inFunction && vars.getVariable(name) != null &&
|
||||||
|
!inWithStatement())
|
||||||
|
{
|
||||||
// call to a var. Transform to Call(GetVar("a"), b, c)
|
// call to a var. Transform to Call(GetVar("a"), b, c)
|
||||||
left.setType(TokenStream.GETVAR);
|
left.setType(TokenStream.GETVAR);
|
||||||
// fall through to code to add GetParent
|
// fall through to code to add GetParent
|
||||||
|
|
|
@ -854,12 +854,18 @@ public class ScriptRuntime {
|
||||||
/* It must be a string. */
|
/* It must be a string. */
|
||||||
int len = str.length();
|
int len = str.length();
|
||||||
char c;
|
char c;
|
||||||
if (len > 0 && '0' <= (c = str.charAt(0)) && c <= '9' &&
|
boolean negate = false;
|
||||||
|
int i = 0;
|
||||||
|
if (len > 0 && (c = str.charAt(0)) == '-') {
|
||||||
|
negate = true;
|
||||||
|
i = 1;
|
||||||
|
}
|
||||||
|
if (len > 0 && '0' <= (c = str.charAt(i)) && c <= '9' &&
|
||||||
len <= MAX_VALUE_LENGTH)
|
len <= MAX_VALUE_LENGTH)
|
||||||
{
|
{
|
||||||
int index = c - '0';
|
int index = c - '0';
|
||||||
int oldIndex = 0;
|
int oldIndex = 0;
|
||||||
int i = 1;
|
i++;
|
||||||
if (index != 0) {
|
if (index != 0) {
|
||||||
while (i < len && '0' <= (c = str.charAt(i)) && c <= '9') {
|
while (i < len && '0' <= (c = str.charAt(i)) && c <= '9') {
|
||||||
oldIndex = index;
|
oldIndex = index;
|
||||||
|
@ -875,7 +881,7 @@ public class ScriptRuntime {
|
||||||
(oldIndex == (Integer.MAX_VALUE / 10) &&
|
(oldIndex == (Integer.MAX_VALUE / 10) &&
|
||||||
c < (Integer.MAX_VALUE % 10))))
|
c < (Integer.MAX_VALUE % 10))))
|
||||||
{
|
{
|
||||||
return index;
|
return negate ? -index : index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NO_INDEX;
|
return NO_INDEX;
|
||||||
|
@ -1159,9 +1165,14 @@ public class ScriptRuntime {
|
||||||
} while (next != null);
|
} while (next != null);
|
||||||
|
|
||||||
bound.put(id, bound, value);
|
bound.put(id, bound, value);
|
||||||
|
/*
|
||||||
|
This code is causing immense performance problems in
|
||||||
|
scripts that assign to the variables as a way of creating them.
|
||||||
|
XXX need strict mode
|
||||||
String[] args = { id };
|
String[] args = { id };
|
||||||
String message = getMessage("msg.assn.create", args);
|
String message = getMessage("msg.assn.create", args);
|
||||||
Context.reportWarning(message);
|
Context.reportWarning(message);
|
||||||
|
*/
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return setProp(bound, id, value, scope);
|
return setProp(bound, id, value, scope);
|
||||||
|
@ -1947,11 +1958,12 @@ public class ScriptRuntime {
|
||||||
public static NativeFunction initFunction(NativeFunction fn,
|
public static NativeFunction initFunction(NativeFunction fn,
|
||||||
Scriptable scope,
|
Scriptable scope,
|
||||||
String fnName,
|
String fnName,
|
||||||
Context cx)
|
Context cx,
|
||||||
|
boolean doSetName)
|
||||||
{
|
{
|
||||||
fn.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));
|
fn.setPrototype(ScriptableObject.getClassPrototype(scope, "Function"));
|
||||||
fn.setParentScope(scope);
|
fn.setParentScope(scope);
|
||||||
if (fnName != null && fnName.length() != 0)
|
if (doSetName)
|
||||||
setName(scope, fn, scope, fnName);
|
setName(scope, fn, scope, fnName);
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,47 +168,48 @@ public class TokenStream {
|
||||||
SETPARENT = 84,
|
SETPARENT = 84,
|
||||||
SCOPE = 85,
|
SCOPE = 85,
|
||||||
GETSCOPEPARENT = 86,
|
GETSCOPEPARENT = 86,
|
||||||
JTHROW = 87,
|
THISFN = 87,
|
||||||
|
JTHROW = 88,
|
||||||
// End of interpreter bytecodes
|
// End of interpreter bytecodes
|
||||||
SEMI = 88, // semicolon
|
SEMI = 89, // semicolon
|
||||||
LB = 89, // left and right brackets
|
LB = 90, // left and right brackets
|
||||||
RB = 90,
|
RB = 91,
|
||||||
LC = 91, // left and right curlies (braces)
|
LC = 92, // left and right curlies (braces)
|
||||||
RC = 92,
|
RC = 93,
|
||||||
LP = 93, // left and right parentheses
|
LP = 94, // left and right parentheses
|
||||||
RP = 94,
|
RP = 95,
|
||||||
COMMA = 95, // comma operator
|
COMMA = 96, // comma operator
|
||||||
ASSIGN = 96, // assignment ops (= += -= etc.)
|
ASSIGN = 97, // assignment ops (= += -= etc.)
|
||||||
HOOK = 97, // conditional (?:)
|
HOOK = 98, // conditional (?:)
|
||||||
COLON = 98,
|
COLON = 99,
|
||||||
OR = 99, // logical or (||)
|
OR = 100, // logical or (||)
|
||||||
AND = 100, // logical and (&&)
|
AND = 101, // logical and (&&)
|
||||||
EQOP = 101, // equality ops (== !=)
|
EQOP = 102, // equality ops (== !=)
|
||||||
RELOP = 102, // relational ops (< <= > >=)
|
RELOP = 103, // relational ops (< <= > >=)
|
||||||
SHOP = 103, // shift ops (<< >> >>>)
|
SHOP = 104, // shift ops (<< >> >>>)
|
||||||
UNARYOP = 104, // unary prefix operator
|
UNARYOP = 105, // unary prefix operator
|
||||||
INC = 105, // increment/decrement (++ --)
|
INC = 106, // increment/decrement (++ --)
|
||||||
DEC = 106,
|
DEC = 107,
|
||||||
DOT = 107, // member operator (.)
|
DOT = 108, // member operator (.)
|
||||||
PRIMARY = 108, // true, false, null, this
|
PRIMARY = 109, // true, false, null, this
|
||||||
FUNCTION = 109, // function keyword
|
FUNCTION = 110, // function keyword
|
||||||
EXPORT = 110, // export keyword
|
EXPORT = 111, // export keyword
|
||||||
IMPORT = 111, // import keyword
|
IMPORT = 112, // import keyword
|
||||||
IF = 112, // if keyword
|
IF = 113, // if keyword
|
||||||
ELSE = 113, // else keyword
|
ELSE = 114, // else keyword
|
||||||
SWITCH = 114, // switch keyword
|
SWITCH = 115, // switch keyword
|
||||||
CASE = 115, // case keyword
|
CASE = 116, // case keyword
|
||||||
DEFAULT = 116, // default keyword
|
DEFAULT = 117, // default keyword
|
||||||
WHILE = 117, // while keyword
|
WHILE = 118, // while keyword
|
||||||
DO = 118, // do keyword
|
DO = 119, // do keyword
|
||||||
FOR = 119, // for keyword
|
FOR = 120, // for keyword
|
||||||
BREAK = 120, // break keyword
|
BREAK = 121, // break keyword
|
||||||
CONTINUE = 121, // continue keyword
|
CONTINUE = 122, // continue keyword
|
||||||
VAR = 122, // var keyword
|
VAR = 123, // var keyword
|
||||||
WITH = 123, // with keyword
|
WITH = 124, // with keyword
|
||||||
CATCH = 124, // catch keyword
|
CATCH = 125, // catch keyword
|
||||||
FINALLY = 125, // finally keyword
|
FINALLY = 126, // finally keyword
|
||||||
RESERVED = 126, // reserved keywords
|
RESERVED = 127, // reserved keywords
|
||||||
|
|
||||||
/** Added by Mike - these are JSOPs in the jsref, but I
|
/** Added by Mike - these are JSOPs in the jsref, but I
|
||||||
* don't have them yet in the java implementation...
|
* don't have them yet in the java implementation...
|
||||||
|
@ -217,45 +218,45 @@ public class TokenStream {
|
||||||
* Most of these go in the 'op' field when returning
|
* Most of these go in the 'op' field when returning
|
||||||
* more general token types, eg. 'DIV' as the op of 'ASSIGN'.
|
* more general token types, eg. 'DIV' as the op of 'ASSIGN'.
|
||||||
*/
|
*/
|
||||||
NOP = 127, // NOP
|
NOP = 128, // NOP
|
||||||
NOT = 128, // etc.
|
NOT = 129, // etc.
|
||||||
PRE = 129, // for INC, DEC nodes.
|
PRE = 130, // for INC, DEC nodes.
|
||||||
POST = 130,
|
POST = 131,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For JSOPs associated with keywords...
|
* For JSOPs associated with keywords...
|
||||||
* eg. op = THIS; token = PRIMARY
|
* eg. op = THIS; token = PRIMARY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VOID = 131,
|
VOID = 132,
|
||||||
|
|
||||||
/* types used for the parse tree - these never get returned
|
/* types used for the parse tree - these never get returned
|
||||||
* by the scanner.
|
* by the scanner.
|
||||||
*/
|
*/
|
||||||
BLOCK = 132, // statement block
|
BLOCK = 133, // statement block
|
||||||
ARRAYLIT = 133, // array literal
|
ARRAYLIT = 134, // array literal
|
||||||
OBJLIT = 134, // object literal
|
OBJLIT = 135, // object literal
|
||||||
LABEL = 135, // label
|
LABEL = 136, // label
|
||||||
TARGET = 136,
|
TARGET = 137,
|
||||||
LOOP = 137,
|
LOOP = 138,
|
||||||
ENUMDONE = 138,
|
ENUMDONE = 139,
|
||||||
EXPRSTMT = 139,
|
EXPRSTMT = 140,
|
||||||
PARENT = 140,
|
PARENT = 141,
|
||||||
CONVERT = 141,
|
CONVERT = 142,
|
||||||
JSR = 142,
|
JSR = 143,
|
||||||
NEWLOCAL = 143,
|
NEWLOCAL = 144,
|
||||||
USELOCAL = 144,
|
USELOCAL = 145,
|
||||||
SCRIPT = 145, // top-level node for entire script
|
SCRIPT = 146, // top-level node for entire script
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the interpreted mode indicating a line number change in icodes.
|
* For the interpreted mode indicating a line number change in icodes.
|
||||||
*/
|
*/
|
||||||
LINE = 146,
|
LINE = 147,
|
||||||
SOURCEFILE = 147,
|
SOURCEFILE = 148,
|
||||||
|
|
||||||
// For debugger
|
// For debugger
|
||||||
|
|
||||||
BREAKPOINT = 148;
|
BREAKPOINT = 149;
|
||||||
// end enum
|
// end enum
|
||||||
|
|
||||||
|
|
||||||
|
@ -354,6 +355,7 @@ public class TokenStream {
|
||||||
"setparent",
|
"setparent",
|
||||||
"scope",
|
"scope",
|
||||||
"getscopeparent",
|
"getscopeparent",
|
||||||
|
"thisfn",
|
||||||
"jthrow",
|
"jthrow",
|
||||||
"semi",
|
"semi",
|
||||||
"lb",
|
"lb",
|
||||||
|
|
|
@ -49,4 +49,6 @@ public interface DebuggableEngine {
|
||||||
public Debugger getDebugger();
|
public Debugger getDebugger();
|
||||||
|
|
||||||
public Frame getFrame(int frameNumber);
|
public Frame getFrame(int frameNumber);
|
||||||
|
|
||||||
|
//public void haltExecution();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ import java.util.Enumeration;
|
||||||
* code (either functions or top-level scripts).
|
* code (either functions or top-level scripts).
|
||||||
*/
|
*/
|
||||||
public interface DebuggableScript {
|
public interface DebuggableScript {
|
||||||
|
|
||||||
|
//public boolean isFunction(); // XXX
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Scriptable object (Function or Script) that is
|
* Get the Scriptable object (Function or Script) that is
|
||||||
|
|
|
@ -217,7 +217,7 @@ public class Block {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < liveSet.length; i++) {
|
for (int i = 0; i < liveSet.length; i++) {
|
||||||
if (liveSet[i])
|
if (liveSet[i])
|
||||||
((OptLocalVariable)theVariables.get(i)).markLiveAcrossCall();
|
((OptLocalVariable)theVariables.getVariable(i)).markLiveAcrossCall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -246,7 +246,7 @@ public class Block {
|
||||||
{
|
{
|
||||||
for (int i = 0; i < theVariables.size(); i++)
|
for (int i = 0; i < theVariables.size(); i++)
|
||||||
if (itsLiveOnEntrySet.test(i))
|
if (itsLiveOnEntrySet.test(i))
|
||||||
((OptLocalVariable)theVariables.get(i)).assignType(TypeEvent.AnyType);
|
((OptLocalVariable)theVariables.getVariable(i)).assignType(TypeEvent.AnyType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,13 +650,13 @@ public class Block {
|
||||||
{
|
{
|
||||||
for (int i = 0; i < theVariables.size(); i++) {
|
for (int i = 0; i < theVariables.size(); i++) {
|
||||||
if (itsUseBeforeDefSet.test(i))
|
if (itsUseBeforeDefSet.test(i))
|
||||||
pw.println(theVariables.get(i).getName() + " is used before def'd");
|
pw.println(theVariables.getVariable(i).getName() + " is used before def'd");
|
||||||
if (itsNotDefSet.test(i))
|
if (itsNotDefSet.test(i))
|
||||||
pw.println(theVariables.get(i).getName() + " is not def'd");
|
pw.println(theVariables.getVariable(i).getName() + " is not def'd");
|
||||||
if (itsLiveOnEntrySet.test(i))
|
if (itsLiveOnEntrySet.test(i))
|
||||||
pw.println(theVariables.get(i).getName() + " is live on entry");
|
pw.println(theVariables.getVariable(i).getName() + " is live on entry");
|
||||||
if (itsLiveOnExitSet.test(i))
|
if (itsLiveOnExitSet.test(i))
|
||||||
pw.println(theVariables.get(i).getName() + " is live on exit");
|
pw.println(theVariables.getVariable(i).getName() + " is live on exit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -457,7 +457,7 @@ public class Codegen extends Interpreter {
|
||||||
// make sure that all parameters are objects
|
// make sure that all parameters are objects
|
||||||
itsForcedObjectParameters = true;
|
itsForcedObjectParameters = true;
|
||||||
for (int i = 0; i < vars.getParameterCount(); i++) {
|
for (int i = 0; i < vars.getParameterCount(); i++) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) vars.get(i);
|
OptLocalVariable lVar = (OptLocalVariable) vars.getVariable(i);
|
||||||
aload(lVar.getJRegister());
|
aload(lVar.getJRegister());
|
||||||
classFile.add(ByteCode.GETSTATIC,
|
classFile.add(ByteCode.GETSTATIC,
|
||||||
"java/lang/Void",
|
"java/lang/Void",
|
||||||
|
@ -1347,12 +1347,18 @@ public class Codegen extends Interpreter {
|
||||||
addByteCode(ByteCode.ACONST_NULL);
|
addByteCode(ByteCode.ACONST_NULL);
|
||||||
}
|
}
|
||||||
// load 'cx'
|
// load 'cx'
|
||||||
aload(contextLocal);
|
aload(contextLocal);
|
||||||
|
// load boolean indicating whether fn name should be set in scope
|
||||||
|
boolean setFnName = str != null && str.length() > 0 &&
|
||||||
|
((FunctionNode) def).getFunctionType() !=
|
||||||
|
FunctionNode.FUNCTION_EXPRESSION;
|
||||||
|
addByteCode(setFnName ? ByteCode.ICONST_1 : ByteCode.ICONST_0);
|
||||||
|
|
||||||
addScriptRuntimeInvoke("initFunction",
|
addScriptRuntimeInvoke("initFunction",
|
||||||
"(Lorg/mozilla/javascript/NativeFunction;" +
|
"(Lorg/mozilla/javascript/NativeFunction;" +
|
||||||
"Lorg/mozilla/javascript/Scriptable;" +
|
"Lorg/mozilla/javascript/Scriptable;" +
|
||||||
"Ljava/lang/String;" +
|
"Ljava/lang/String;" +
|
||||||
"Lorg/mozilla/javascript/Context;)",
|
"Lorg/mozilla/javascript/Context;Z)",
|
||||||
"Lorg/mozilla/javascript/NativeFunction;");
|
"Lorg/mozilla/javascript/NativeFunction;");
|
||||||
def.putProp(Node.FUNCTION_PROP, new Short(i));
|
def.putProp(Node.FUNCTION_PROP, new Short(i));
|
||||||
addByteCode(ByteCode.AASTORE); // store NativeFunction
|
addByteCode(ByteCode.AASTORE); // store NativeFunction
|
||||||
|
@ -1447,7 +1453,7 @@ public class Codegen extends Interpreter {
|
||||||
// before the next call and are used in the function
|
// before the next call and are used in the function
|
||||||
short firstUndefVar = -1;
|
short firstUndefVar = -1;
|
||||||
for (int i = 0; i < vars.size(); i++) {
|
for (int i = 0; i < vars.size(); i++) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) vars.get(i);
|
OptLocalVariable lVar = (OptLocalVariable) vars.getVariable(i);
|
||||||
if (lVar.isNumber()) {
|
if (lVar.isNumber()) {
|
||||||
lVar.assignJRegister(getNewWordPairLocal());
|
lVar.assignJRegister(getNewWordPairLocal());
|
||||||
push(0.0);
|
push(0.0);
|
||||||
|
@ -1547,7 +1553,7 @@ public class Codegen extends Interpreter {
|
||||||
if (cx.isGeneratingDebug()) {
|
if (cx.isGeneratingDebug()) {
|
||||||
debugVars = new OptVariableTable();
|
debugVars = new OptVariableTable();
|
||||||
debugVars.addLocal(debugVariableName);
|
debugVars.addLocal(debugVariableName);
|
||||||
OptLocalVariable lv = (OptLocalVariable) debugVars.get(debugVariableName);
|
OptLocalVariable lv = (OptLocalVariable) debugVars.getVariable(debugVariableName);
|
||||||
lv.assignJRegister(variableObjectLocal);
|
lv.assignJRegister(variableObjectLocal);
|
||||||
lv.setStartPC(classFile.getCurrentCodeOffset());
|
lv.setStartPC(classFile.getCurrentCodeOffset());
|
||||||
}
|
}
|
||||||
|
@ -1876,7 +1882,6 @@ public class Codegen extends Interpreter {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (true) {
|
|
||||||
Node callBase = callNode.getFirstChild();
|
Node callBase = callNode.getFirstChild();
|
||||||
if (callBase.getType() == TokenStream.GETPROP) {
|
if (callBase.getType() == TokenStream.GETPROP) {
|
||||||
Node callBaseChild = callBase.getFirstChild();
|
Node callBaseChild = callBase.getFirstChild();
|
||||||
|
@ -1903,7 +1908,6 @@ if (true) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2425,7 +2429,7 @@ if (true) {
|
||||||
}
|
}
|
||||||
String name = node.getString();
|
String name = node.getString();
|
||||||
if (hasVarsInRegs) {
|
if (hasVarsInRegs) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) vars.get(name);
|
OptLocalVariable lVar = (OptLocalVariable) vars.getVariable(name);
|
||||||
if (lVar != null) {
|
if (lVar != null) {
|
||||||
if (lVar.isNumber()) {
|
if (lVar.isNumber()) {
|
||||||
push("number");
|
push("number");
|
||||||
|
@ -2463,7 +2467,7 @@ if (true) {
|
||||||
String routine = (isInc) ? "postIncrement" : "postDecrement";
|
String routine = (isInc) ? "postIncrement" : "postDecrement";
|
||||||
if (hasVarsInRegs && child.getType() == TokenStream.GETVAR) {
|
if (hasVarsInRegs && child.getType() == TokenStream.GETVAR) {
|
||||||
if (lVar == null)
|
if (lVar == null)
|
||||||
lVar = (OptLocalVariable) vars.get(child.getString());
|
lVar = (OptLocalVariable) vars.getVariable(child.getString());
|
||||||
if (lVar.getJRegister() == -1)
|
if (lVar.getJRegister() == -1)
|
||||||
lVar.assignJRegister(getNewWordLocal());
|
lVar.assignJRegister(getNewWordLocal());
|
||||||
aload(lVar.getJRegister());
|
aload(lVar.getJRegister());
|
||||||
|
@ -3173,6 +3177,10 @@ if (true) {
|
||||||
aload(thisObjLocal);
|
aload(thisObjLocal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TokenStream.THISFN:
|
||||||
|
classFile.add(ByteCode.ALOAD_0);
|
||||||
|
break;
|
||||||
|
|
||||||
case TokenStream.NULL:
|
case TokenStream.NULL:
|
||||||
addByteCode(ByteCode.ACONST_NULL);
|
addByteCode(ByteCode.ACONST_NULL);
|
||||||
break;
|
break;
|
||||||
|
@ -3232,7 +3240,7 @@ if (true) {
|
||||||
{
|
{
|
||||||
// TODO: Clean up use of lVar here and in set.
|
// TODO: Clean up use of lVar here and in set.
|
||||||
if (hasVarsInRegs && lVar == null)
|
if (hasVarsInRegs && lVar == null)
|
||||||
lVar = (OptLocalVariable) vars.get(name);
|
lVar = (OptLocalVariable) vars.getVariable(name);
|
||||||
if (lVar != null) {
|
if (lVar != null) {
|
||||||
if (lVar.getJRegister() == -1)
|
if (lVar.getJRegister() == -1)
|
||||||
if (lVar.isNumber())
|
if (lVar.isNumber())
|
||||||
|
@ -3303,7 +3311,7 @@ if (true) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable)(node.getProp(Node.VARIABLE_PROP));
|
OptLocalVariable lVar = (OptLocalVariable)(node.getProp(Node.VARIABLE_PROP));
|
||||||
// XXX is this right? If so, clean up.
|
// XXX is this right? If so, clean up.
|
||||||
if (hasVarsInRegs && lVar == null)
|
if (hasVarsInRegs && lVar == null)
|
||||||
lVar = (OptLocalVariable) vars.get(child.getString());
|
lVar = (OptLocalVariable) vars.getVariable(child.getString());
|
||||||
if (lVar != null) {
|
if (lVar != null) {
|
||||||
generateCodeFromNode(child.getNextSibling(), node, -1, -1);
|
generateCodeFromNode(child.getNextSibling(), node, -1, -1);
|
||||||
if (lVar.getJRegister() == -1) {
|
if (lVar.getJRegister() == -1) {
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class Optimizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < theVariables.size(); i++) {
|
for (int i = 0; i < theVariables.size(); i++) {
|
||||||
OptLocalVariable lVar = (OptLocalVariable) theVariables.get(i);
|
OptLocalVariable lVar = (OptLocalVariable) theVariables.getVariable(i);
|
||||||
if (!lVar.isParameter()) {
|
if (!lVar.isParameter()) {
|
||||||
int theType = lVar.getTypeUnion();
|
int theType = lVar.getTypeUnion();
|
||||||
if (theType == TypeEvent.NumberType) {
|
if (theType == TypeEvent.NumberType) {
|
||||||
|
@ -1043,7 +1043,7 @@ public class Optimizer {
|
||||||
case TokenStream.SETVAR : {
|
case TokenStream.SETVAR : {
|
||||||
String name = n.getFirstChild().getString();
|
String name = n.getFirstChild().getString();
|
||||||
OptLocalVariable theVar = (OptLocalVariable)
|
OptLocalVariable theVar = (OptLocalVariable)
|
||||||
theVariables.get(name);
|
theVariables.getVariable(name);
|
||||||
if (theVar != null)
|
if (theVar != null)
|
||||||
n.putProp(Node.VARIABLE_PROP, theVar);
|
n.putProp(Node.VARIABLE_PROP, theVar);
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1051,7 @@ public class Optimizer {
|
||||||
case TokenStream.GETVAR : {
|
case TokenStream.GETVAR : {
|
||||||
String name = n.getString();
|
String name = n.getString();
|
||||||
OptLocalVariable theVar = (OptLocalVariable)
|
OptLocalVariable theVar = (OptLocalVariable)
|
||||||
theVariables.get(name);
|
theVariables.getVariable(name);
|
||||||
if (theVar != null)
|
if (theVar != null)
|
||||||
n.putProp(Node.VARIABLE_PROP, theVar);
|
n.putProp(Node.VARIABLE_PROP, theVar);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче