Inline small functions used for code generation to produce intepreter or JVM bytecode for particular parser tree node: they just add to jar file size without readability benefits.

This commit is contained in:
igor%mir2.org 2004-09-07 09:08:31 +00:00
Родитель 96aed722f8
Коммит d29f6cb477
3 изменённых файлов: 632 добавлений и 709 удалений

Просмотреть файл

@ -535,24 +535,26 @@ public class Interpreter
Node child = node.getFirstChild(); Node child = node.getFirstChild();
switch (type) { switch (type) {
case Token.FUNCTION: { case Token.FUNCTION:
int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); {
int fnType = scriptOrFn.getFunctionNode(fnIndex).getFunctionType(); int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
// Only function expressions or function expression int fnType = scriptOrFn.getFunctionNode(fnIndex).
// statements needs closure code creating new function getFunctionType();
// object on stack as function statements are initialized // Only function expressions or function expression
// at script/function start // statements needs closure code creating new function
// In addition function expression can not present here // object on stack as function statements are initialized
// at statement level, they must only present as expressions. // at script/function start
if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { // In addition function expression can not present here
addIndexOp(Icode_CLOSURE_STMT, fnIndex); // at statement level, they must only present as expressions.
} else { if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
if (fnType != FunctionNode.FUNCTION_STATEMENT) { addIndexOp(Icode_CLOSURE_STMT, fnIndex);
throw Kit.codeBug(); } else {
if (fnType != FunctionNode.FUNCTION_STATEMENT) {
throw Kit.codeBug();
}
} }
} }
break; break;
}
case Token.SCRIPT: case Token.SCRIPT:
case Token.LABEL: case Token.LABEL:
@ -600,7 +602,32 @@ public class Interpreter
break; break;
case Token.SWITCH: case Token.SWITCH:
visitSwitch((Node.Jump)node); updateLineNumber(node);
// See comments in IRFactory.createSwitch() for description
// of SWITCH node
{
Node switchNode = (Node.Jump)node;
visitExpression(child, 0);
for (Node.Jump caseNode = (Node.Jump)child.getNext();
caseNode != null;
caseNode = (Node.Jump)caseNode.getNext())
{
if (caseNode.getType() != Token.CASE)
throw badTree(caseNode);
Node test = caseNode.getFirstChild();
addIcode(Icode_DUP);
stackChange(1);
visitExpression(test, 0);
addToken(Token.SHEQ);
stackChange(-1);
// If true, Icode_IFEQ_POP will jump and remove case
// value from stack
addGoto(caseNode.target, Icode_IFEQ_POP);
stackChange(-1);
}
addIcode(Icode_POP);
stackChange(-1);
}
break; break;
case Token.TARGET: case Token.TARGET:
@ -608,25 +635,28 @@ public class Interpreter
break; break;
case Token.IFEQ : case Token.IFEQ :
case Token.IFNE : { case Token.IFNE :
Node.Target target = ((Node.Jump)node).target; {
visitExpression(child, 0); Node.Target target = ((Node.Jump)node).target;
addGoto(target, type); visitExpression(child, 0);
stackChange(-1); addGoto(target, type);
stackChange(-1);
}
break; break;
}
case Token.GOTO: { case Token.GOTO:
Node.Target target = ((Node.Jump)node).target; {
addGoto(target, type); Node.Target target = ((Node.Jump)node).target;
addGoto(target, type);
}
break; break;
}
case Token.JSR: { case Token.JSR:
Node.Target target = ((Node.Jump)node).target; {
addGoto(target, Icode_GOSUB); Node.Target target = ((Node.Jump)node).target;
addGoto(target, Icode_GOSUB);
}
break; break;
}
case Token.FINALLY: case Token.FINALLY:
{ {
@ -652,7 +682,33 @@ public class Interpreter
break; break;
case Token.TRY: case Token.TRY:
visitTry((Node.Jump)node, child); {
Node.Jump tryNode = (Node.Jump)node;
int exceptionObjectLocal = getLocalBlockRef(tryNode);
int tryStart = itsICodeTop;
while (child != null) {
visitStatement(child);
child = child.getNext();
}
Node.Target catchTarget = tryNode.target;
if (catchTarget != null) {
int catchStartPC
= itsLabelTable[getTargetLabel(catchTarget)];
addExceptionHandler(
tryStart, catchStartPC, catchStartPC,
false, itsWithDepth, exceptionObjectLocal);
}
Node.Target finallyTarget = tryNode.getFinally();
if (finallyTarget != null) {
int finallyStartPC
= itsLabelTable[getTargetLabel(finallyTarget)];
addExceptionHandler(
tryStart, finallyStartPC, finallyStartPC,
true, itsWithDepth, exceptionObjectLocal);
}
}
break; break;
case Token.CATCH_SCOPE: case Token.CATCH_SCOPE:
@ -722,37 +778,40 @@ public class Interpreter
int savedStackDepth = itsStackDepth; int savedStackDepth = itsStackDepth;
switch (type) { switch (type) {
case Token.FUNCTION: { case Token.FUNCTION:
int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); {
FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex); int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
// See comments in visitStatement for Token.FUNCTION case FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex);
if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) { // See comments in visitStatement for Token.FUNCTION case
throw Kit.codeBug(); if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) {
throw Kit.codeBug();
}
addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
stackChange(1);
} }
addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
stackChange(1);
break; break;
}
case Token.LOCAL_LOAD: { case Token.LOCAL_LOAD:
int localIndex = getLocalBlockRef(node); {
addIndexOp(Token.LOCAL_LOAD, localIndex); int localIndex = getLocalBlockRef(node);
stackChange(1); addIndexOp(Token.LOCAL_LOAD, localIndex);
break; stackChange(1);
} }
break;
case Token.COMMA: {
Node lastChild = node.getLastChild(); case Token.COMMA:
while (child != lastChild) { {
visitExpression(child, 0); Node lastChild = node.getLastChild();
addIcode(Icode_POP); while (child != lastChild) {
stackChange(-1); visitExpression(child, 0);
child = child.getNext(); addIcode(Icode_POP);
stackChange(-1);
child = child.getNext();
}
// Preserve tail context flag if any
visitExpression(child, contextFlags & ECF_TAIL);
} }
// Preserve tail context flag if any
visitExpression(child, contextFlags & ECF_TAIL);
break; break;
}
case Token.USE_STACK: case Token.USE_STACK:
// Indicates that stack was modified externally, // Indicates that stack was modified externally,
@ -763,56 +822,103 @@ public class Interpreter
case Token.CALL: case Token.CALL:
case Token.NEW: case Token.NEW:
case Token.REF_CALL: case Token.REF_CALL:
visitCall(node, contextFlags); {
if (type == Token.NEW) {
visitExpression(child, 0);
} else {
generateCallFunAndThis(child);
}
int argCount = 0;
while ((child = child.getNext()) != null) {
visitExpression(child, 0);
++argCount;
}
int callType = node.getIntProp(Node.SPECIALCALL_PROP,
Node.NON_SPECIALCALL);
if (callType != Node.NON_SPECIALCALL) {
// embed line number and source filename
addIndexOp(Icode_CALLSPECIAL, argCount);
addUint8(callType);
addUint8(type == Token.NEW ? 1 : 0);
addUint16(itsLineNumber & 0xFFFF);
} else {
if (type == Token.CALL) {
if ((contextFlags & ECF_TAIL) != 0) {
type = Icode_TAIL_CALL;
}
}
addIndexOp(type, argCount);
}
// adjust stack
if (type == Token.NEW) {
// f, args -> results
stackChange(-argCount);
} else {
// f, thisObj, args -> results
stackChange(-1 - argCount);
}
if (argCount > itsData.itsMaxCalleeArgs) {
itsData.itsMaxCalleeArgs = argCount;
}
}
break; break;
case Token.AND: case Token.AND:
case Token.OR: { case Token.OR:
visitExpression(child, 0); {
addIcode(Icode_DUP); visitExpression(child, 0);
stackChange(1); addIcode(Icode_DUP);
int afterSecondJumpStart = itsICodeTop; stackChange(1);
int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ; int afterSecondJumpStart = itsICodeTop;
addForwardGoto(jump); int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
stackChange(-1); addForwardGoto(jump);
addIcode(Icode_POP); stackChange(-1);
stackChange(-1); addIcode(Icode_POP);
child = child.getNext(); stackChange(-1);
// Preserve tail context flag if any child = child.getNext();
visitExpression(child, contextFlags & ECF_TAIL); // Preserve tail context flag if any
resolveForwardGoto(afterSecondJumpStart); visitExpression(child, contextFlags & ECF_TAIL);
resolveForwardGoto(afterSecondJumpStart);
}
break; break;
}
case Token.HOOK: { case Token.HOOK:
Node ifThen = child.getNext(); {
Node ifElse = ifThen.getNext(); Node ifThen = child.getNext();
visitExpression(child, 0); Node ifElse = ifThen.getNext();
int elseJumpStart = itsICodeTop; visitExpression(child, 0);
addForwardGoto(Token.IFNE); int elseJumpStart = itsICodeTop;
stackChange(-1); addForwardGoto(Token.IFNE);
// Preserve tail context flag if any stackChange(-1);
visitExpression(ifThen, contextFlags & ECF_TAIL); // Preserve tail context flag if any
int afterElseJumpStart = itsICodeTop; visitExpression(ifThen, contextFlags & ECF_TAIL);
addForwardGoto(Token.GOTO); int afterElseJumpStart = itsICodeTop;
resolveForwardGoto(elseJumpStart); addForwardGoto(Token.GOTO);
itsStackDepth = savedStackDepth; resolveForwardGoto(elseJumpStart);
// Preserve tail context flag if any itsStackDepth = savedStackDepth;
visitExpression(ifElse, contextFlags & ECF_TAIL); // Preserve tail context flag if any
resolveForwardGoto(afterElseJumpStart); visitExpression(ifElse, contextFlags & ECF_TAIL);
resolveForwardGoto(afterElseJumpStart);
}
break; break;
}
case Token.GETPROP: case Token.GETPROP:
visitGetProp(node, child); visitExpression(child, 0);
child = child.getNext();
addStringOp(Token.GETPROP, child.getString());
break; break;
case Token.GETELEM: case Token.GETELEM:
visitGetElem(node, child); visitExpression(child, 0);
child = child.getNext();
visitExpression(child, 0);
addToken(Token.GETELEM);
stackChange(-1);
break; break;
case Token.GET_REF: case Token.GET_REF:
visitGetRef(node, child); visitExpression(child, 0);
addToken(Token.GET_REF);
break; break;
case Token.DELPROP: case Token.DELPROP:
@ -860,24 +966,25 @@ public class Interpreter
} }
break; break;
case Token.SETPROP: case Token.SETPROP:
case Token.SETPROP_OP: { case Token.SETPROP_OP:
visitExpression(child, 0); {
child = child.getNext(); visitExpression(child, 0);
String property = child.getString(); child = child.getNext();
child = child.getNext(); String property = child.getString();
if (type == Token.SETPROP_OP) { child = child.getNext();
addIcode(Icode_DUP); if (type == Token.SETPROP_OP) {
stackChange(1); addIcode(Icode_DUP);
addStringOp(Token.GETPROP, property); stackChange(1);
// Compensate for the following USE_STACK addStringOp(Token.GETPROP, property);
// Compensate for the following USE_STACK
stackChange(-1);
}
visitExpression(child, 0);
addStringOp(Token.SETPROP, property);
stackChange(-1); stackChange(-1);
} }
visitExpression(child, 0);
addStringOp(Token.SETPROP, property);
stackChange(-1);
break; break;
}
case Token.SETELEM: case Token.SETELEM:
case Token.SETELEM_OP: case Token.SETELEM_OP:
@ -914,33 +1021,35 @@ public class Interpreter
stackChange(-1); stackChange(-1);
break; break;
case Token.SETNAME: { case Token.SETNAME:
String name = child.getString(); {
visitExpression(child, 0); String name = child.getString();
child = child.getNext(); visitExpression(child, 0);
visitExpression(child, 0); child = child.getNext();
addStringOp(Token.SETNAME, name); visitExpression(child, 0);
stackChange(-1); addStringOp(Token.SETNAME, name);
break; stackChange(-1);
} }
break;
case Token.TYPEOFNAME: {
String name = node.getString(); case Token.TYPEOFNAME:
int index = -1; {
// use typeofname if an activation frame exists String name = node.getString();
// since the vars all exist there instead of in jregs int index = -1;
if (itsInFunctionFlag && !itsData.itsNeedsActivation) // use typeofname if an activation frame exists
index = scriptOrFn.getParamOrVarIndex(name); // since the vars all exist there instead of in jregs
if (index == -1) { if (itsInFunctionFlag && !itsData.itsNeedsActivation)
addStringOp(Icode_TYPEOFNAME, name); index = scriptOrFn.getParamOrVarIndex(name);
stackChange(1); if (index == -1) {
} else { addStringOp(Icode_TYPEOFNAME, name);
addVarOp(Token.GETVAR, index); stackChange(1);
stackChange(1); } else {
addToken(Token.TYPEOF); addVarOp(Token.GETVAR, index);
stackChange(1);
addToken(Token.TYPEOF);
}
} }
break; break;
}
case Token.BINDNAME: case Token.BINDNAME:
case Token.NAME: case Token.NAME:
@ -955,41 +1064,68 @@ public class Interpreter
break; break;
case Token.NUMBER: case Token.NUMBER:
visitNumber(node); {
break; double num = node.getDouble();
int inum = (int)num;
case Token.GETVAR: { if (inum == num) {
String name = node.getString(); if (inum == 0) {
if (itsData.itsNeedsActivation) { addIcode(Icode_ZERO);
// SETVAR handled this by turning into a SETPROP, but // Check for negative zero
// we can't do that to a GETVAR without manufacturing if (1.0 / num < 0.0) {
// bogus children. Instead we use a special op to addToken(Token.NEG);
// push the current scope. }
addIcode(Icode_SCOPE); } else if (inum == 1) {
stackChange(1); addIcode(Icode_ONE);
addStringOp(Token.GETPROP, name); } else if ((short)inum == inum) {
} else { addIcode(Icode_SHORTNUMBER);
int index = scriptOrFn.getParamOrVarIndex(name); // write short as uin16 bit pattern
addVarOp(Token.GETVAR, index); addUint16(inum & 0xFFFF);
} else {
addIcode(Icode_INTNUMBER);
addInt(inum);
}
} else {
int index = getDoubleIndex(num);
addIndexOp(Token.NUMBER, index);
}
stackChange(1); stackChange(1);
} }
break; break;
}
case Token.SETVAR: { case Token.GETVAR:
if (itsData.itsNeedsActivation) { {
child.setType(Token.BINDNAME); String name = node.getString();
node.setType(Token.SETNAME); if (itsData.itsNeedsActivation) {
visitExpression(node, 0); // SETVAR handled this by turning into a SETPROP, but
} else { // we can't do that to a GETVAR without manufacturing
String name = child.getString(); // bogus children. Instead we use a special op to
child = child.getNext(); // push the current scope.
visitExpression(child, 0); addIcode(Icode_SCOPE);
int index = scriptOrFn.getParamOrVarIndex(name); stackChange(1);
addVarOp(Token.SETVAR, index); addStringOp(Token.GETPROP, name);
} else {
int index = scriptOrFn.getParamOrVarIndex(name);
addVarOp(Token.GETVAR, index);
stackChange(1);
}
}
break;
case Token.SETVAR:
{
if (itsData.itsNeedsActivation) {
child.setType(Token.BINDNAME);
node.setType(Token.SETNAME);
visitExpression(node, 0);
} else {
String name = child.getString();
child = child.getNext();
visitExpression(child, 0);
int index = scriptOrFn.getParamOrVarIndex(name);
addVarOp(Token.SETVAR, index);
}
} }
break; break;
}
case Token.NULL: case Token.NULL:
case Token.THIS: case Token.THIS:
@ -1006,24 +1142,26 @@ public class Interpreter
stackChange(1); stackChange(1);
break; break;
case Token.REGEXP: { case Token.REGEXP:
int index = node.getExistingIntProp(Node.REGEXP_PROP); {
addIndexOp(Token.REGEXP, index); int index = node.getExistingIntProp(Node.REGEXP_PROP);
stackChange(1); addIndexOp(Token.REGEXP, index);
stackChange(1);
}
break; break;
}
case Token.ARRAYLIT: case Token.ARRAYLIT:
case Token.OBJECTLIT: case Token.OBJECTLIT:
visitLiteral(node, child); visitLiteral(node, child);
break; break;
case Token.SPECIAL_REF: { case Token.SPECIAL_REF:
visitExpression(child, 0); {
String special = (String)node.getProp(Node.SPECIAL_PROP_PROP); String special = (String)node.getProp(Node.SPECIAL_PROP_PROP);
addStringOp(Token.SPECIAL_REF, special); visitExpression(child, 0);
addStringOp(Token.SPECIAL_REF, special);
}
break; break;
}
case Token.XML_REF: case Token.XML_REF:
visitExpression(child, 0); visitExpression(child, 0);
@ -1031,7 +1169,16 @@ public class Interpreter
break; break;
case Token.DOTQUERY: case Token.DOTQUERY:
visitDotQery(node, child); {
int queryPC;
updateLineNumber(node);
visitExpression(child, 0);
addIcode(Icode_ENTERDQ);
stackChange(-1);
queryPC = itsICodeTop;
visitExpression(child.getNext(), 0);
addBackwardGoto(Icode_LEAVEDQ, queryPC);
}
break; break;
case Token.DEFAULTNAMESPACE : case Token.DEFAULTNAMESPACE :
@ -1043,16 +1190,16 @@ public class Interpreter
addToken(type); addToken(type);
break; break;
case Token.COLONCOLON : { case Token.COLONCOLON :
if (child.getType() != Token.STRING) {
throw badTree(child); if (child.getType() != Token.STRING)
String namespace = child.getString(); throw badTree(child);
child = child.getNext(); String namespace = child.getString();
visitExpression(child, 0); child = child.getNext();
addStringOp(Token.COLONCOLON, namespace); visitExpression(child, 0);
addStringOp(Token.COLONCOLON, namespace);
}
break; break;
}
default: default:
throw badTree(node); throw badTree(node);
@ -1062,103 +1209,6 @@ public class Interpreter
} }
} }
private void visitSwitch(Node.Jump switchNode)
{
// See comments in IRFactory.createSwitch() for description
// of SWITCH node
updateLineNumber(switchNode);
Node child = switchNode.getFirstChild();
visitExpression(child, 0);
for (Node.Jump caseNode = (Node.Jump)child.getNext();
caseNode != null;
caseNode = (Node.Jump)caseNode.getNext())
{
if (caseNode.getType() != Token.CASE)
throw badTree(caseNode);
Node test = caseNode.getFirstChild();
addIcode(Icode_DUP);
stackChange(1);
visitExpression(test, 0);
addToken(Token.SHEQ);
stackChange(-1);
// If true, Icode_IFEQ_POP will jump and remove case value
// from stack
addGoto(caseNode.target, Icode_IFEQ_POP);
stackChange(-1);
}
addIcode(Icode_POP);
stackChange(-1);
}
private void visitTry(Node.Jump tryNode, Node child)
{
int tryStart = itsICodeTop;
while (child != null) {
visitStatement(child);
child = child.getNext();
}
int exceptionObjectLocal = getLocalBlockRef(tryNode);
Node.Target catchTarget = tryNode.target;
if (catchTarget != null) {
int catchStartPC = itsLabelTable[getTargetLabel(catchTarget)];
addExceptionHandler(tryStart, catchStartPC, catchStartPC,
false, itsWithDepth, exceptionObjectLocal);
}
Node.Target finallyTarget = tryNode.getFinally();
if (finallyTarget != null) {
int finallyStartPC = itsLabelTable[getTargetLabel(finallyTarget)];
addExceptionHandler(tryStart, finallyStartPC, finallyStartPC,
true, itsWithDepth, exceptionObjectLocal);
}
}
private void visitCall(Node node, int contextFlags)
{
int type = node.getType();
Node child = node.getFirstChild();
if (type == Token.NEW) {
visitExpression(child, 0);
} else {
generateCallFunAndThis(child);
}
int argCount = 0;
while ((child = child.getNext()) != null) {
visitExpression(child, 0);
++argCount;
}
int callType = node.getIntProp(Node.SPECIALCALL_PROP,
Node.NON_SPECIALCALL);
if (callType != Node.NON_SPECIALCALL) {
// embed line number and source filename
addIndexOp(Icode_CALLSPECIAL, argCount);
addUint8(callType);
addUint8(type == Token.NEW ? 1 : 0);
addUint16(itsLineNumber & 0xFFFF);
} else {
if (type == Token.CALL) {
if ((contextFlags & ECF_TAIL) != 0) {
type = Icode_TAIL_CALL;
}
}
addIndexOp(type, argCount);
}
// adjust stack
if (type == Token.NEW) {
// f, args -> results
stackChange(-argCount);
} else {
// f, thisObj, args -> results
stackChange(-1 - argCount);
}
if (argCount > itsData.itsMaxCalleeArgs)
itsData.itsMaxCalleeArgs = argCount;
}
private void generateCallFunAndThis(Node left) private void generateCallFunAndThis(Node left)
{ {
// Generate code to place on stack function and thisObj // Generate code to place on stack function and thisObj
@ -1198,29 +1248,6 @@ public class Interpreter
} }
} }
private void visitGetProp(Node node, Node child)
{
visitExpression(child, 0);
child = child.getNext();
String property = child.getString();
addStringOp(Token.GETPROP, property);
}
private void visitGetElem(Node node, Node child)
{
visitExpression(child, 0);
child = child.getNext();
visitExpression(child, 0);
addToken(Token.GETELEM);
stackChange(-1);
}
private void visitGetRef(Node node, Node child)
{
visitExpression(child, 0);
addToken(Token.GET_REF);
}
private void visitIncDec(Node node, Node child) private void visitIncDec(Node node, Node child)
{ {
int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP); int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP);
@ -1279,34 +1306,6 @@ public class Interpreter
} }
} }
private void visitNumber(Node node)
{
double num = node.getDouble();
int inum = (int)num;
if (inum == num) {
if (inum == 0) {
addIcode(Icode_ZERO);
// Check for negative zero
if (1.0 / num < 0.0) {
addToken(Token.NEG);
}
} else if (inum == 1) {
addIcode(Icode_ONE);
} else if ((short)inum == inum) {
addIcode(Icode_SHORTNUMBER);
// write short as uin16 bit pattern
addUint16(inum & 0xFFFF);
} else {
addIcode(Icode_INTNUMBER);
addInt(inum);
}
} else {
int index = getDoubleIndex(num);
addIndexOp(Token.NUMBER, index);
}
stackChange(1);
}
private void visitLiteral(Node node, Node child) private void visitLiteral(Node node, Node child)
{ {
int type = node.getType(); int type = node.getType();
@ -1347,17 +1346,6 @@ public class Interpreter
} }
} }
private void visitDotQery(Node node, Node child)
{
updateLineNumber(node);
visitExpression(child, 0);
addIcode(Icode_ENTERDQ);
stackChange(-1);
int queryPC = itsICodeTop;
visitExpression(child.getNext(), 0);
addBackwardGoto(Icode_LEAVEDQ, queryPC);
}
private int getLocalBlockRef(Node node) private int getLocalBlockRef(Node node)
{ {
Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP); Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP);

Просмотреть файл

@ -1022,90 +1022,6 @@ public class ScriptRuntime {
return (char)i; return (char)i;
} }
/**
* Converts Java exceptions that JS can catch into an object the script
* will see as the catch argument.
*/
private static Object getCatchObject(Context cx, Scriptable scope,
Throwable t)
throws JavaScriptException
{
EvaluatorException evaluator = null;
if (t instanceof EvaluatorException) {
evaluator = (EvaluatorException)t;
while (t instanceof WrappedException) {
t = ((WrappedException)t).getWrappedException();
}
}
if (t instanceof JavaScriptException) {
return ((JavaScriptException)t).getValue();
} else if (t instanceof EcmaError) {
EcmaError ee = (EcmaError)t;
String errorName = ee.getName();
return makeErrorObject(cx, scope, errorName, ee.getErrorMessage(),
ee.sourceName(), ee.lineNumber());
} else if (evaluator == null) {
// Script can catch only instances of JavaScriptException,
// EcmaError and EvaluatorException
Kit.codeBug();
}
if (t != evaluator && t instanceof EvaluatorException) {
// ALERT: it should not happen as throwAsUncheckedException
// takes care about it when exception is propagated through Java
// reflection calls, but for now check for it
evaluator = (EvaluatorException)t;
}
String errorName;
String message;
if (t == evaluator) {
// Pure evaluator exception
if (evaluator instanceof WrappedException) Kit.codeBug();
message = evaluator.getMessage();
errorName = "InternalError";
} else {
errorName = "JavaException";
message = t.getClass().getName()+": "+t.getMessage();
}
Scriptable errorObject = makeErrorObject(cx, scope, errorName,
message,
evaluator.sourceName(),
evaluator.lineNumber());
if (t != evaluator) {
Object twrap = cx.getWrapFactory().wrap(cx, scope, t, null);
ScriptableObject.putProperty(errorObject, "javaException", twrap);
}
return errorObject;
}
private static Scriptable makeErrorObject(Context cx, Scriptable scope,
String errorName, String message,
String fileName, int lineNumber)
throws JavaScriptException
{
int argLength;
if (lineNumber > 0) {
argLength = 3;
} else {
argLength = 2;
}
Object args[] = new Object[argLength];
args[0] = message;
args[1] = (fileName != null) ? fileName : "";
if (lineNumber > 0) {
args[2] = new Integer(lineNumber);
}
Scriptable errorObject = cx.newObject(scope, errorName, args);
ScriptableObject.putProperty(errorObject, "name", errorName);
return errorObject;
}
// XXX: this is until setDefaultNamespace will learn how to store NS // XXX: this is until setDefaultNamespace will learn how to store NS
// properly and separates namespace form Scriptable.get etc. // properly and separates namespace form Scriptable.get etc.
private static final String DEFAULT_NS_TAG = "__default_namespace__"; private static final String DEFAULT_NS_TAG = "__default_namespace__";
@ -2982,26 +2898,95 @@ public class ScriptRuntime {
return null; return null;
} }
public static Scriptable newCatchScope(Throwable exception, public static Scriptable newCatchScope(Throwable t,
Scriptable lastCatchScope, Scriptable lastCatchScope,
String exceptionName, String exceptionName,
Context cx, Scriptable scope) Context cx, Scriptable scope)
{ {
Object obj; Object obj;
if (lastCatchScope == null) { boolean cacheObj;
obj = getCatchObject(cx, scope, exception);
getObj:
if (t instanceof JavaScriptException) {
cacheObj = false;
obj = ((JavaScriptException)t).getValue();
} else { } else {
NativeObject last = (NativeObject)lastCatchScope; cacheObj = true;
obj = last.getAssociatedValue(exception);
if (obj == null) Kit.codeBug(); // Create wrapper object unless it was associated with
// the previous scope object
if (lastCatchScope != null) {
NativeObject last = (NativeObject)lastCatchScope;
obj = last.getAssociatedValue(t);
if (obj == null) Kit.codeBug();
break getObj;
}
RhinoException re;
String errorName;
String errorMsg;
Throwable javaException = null;
if (t instanceof EcmaError) {
EcmaError ee = (EcmaError)t;
re = ee;
errorName = ee.getName();
errorMsg = ee.getErrorMessage();
} else if (t instanceof WrappedException) {
WrappedException we = (WrappedException)t;
re = we;
javaException = we.getWrappedException();
errorName = "JavaException";
errorMsg = javaException.getClass().getName()
+": "+javaException.getMessage();
} else if (t instanceof EvaluatorException) {
// Pure evaluator exception, nor WrappedException instance
EvaluatorException ee = (EvaluatorException)t;
re = ee;
errorName = "InternalError";
errorMsg = ee.getMessage();
} else {
// Script can catch only instances of JavaScriptException,
// EcmaError and EvaluatorException
throw Kit.codeBug();
}
String sourceUri = re.sourceName();
if (sourceUri == null) {
sourceUri = "";
}
int line = re.lineNumber();
Object args[];
if (line > 0) {
args = new Object[] { errorMsg, sourceUri, new Integer(line) };
} else {
args = new Object[] { errorMsg, sourceUri };
}
Scriptable errorObject = cx.newObject(scope, errorName, args);
ScriptableObject.putProperty(errorObject, "name", errorName);
if (javaException != null) {
Object wrap = cx.getWrapFactory().wrap(cx, scope, javaException,
null);
ScriptableObject.defineProperty(
errorObject, "javaException", wrap,
ScriptableObject.PERMANENT | ScriptableObject.READONLY);
}
obj = errorObject;
} }
NativeObject catchScope = new NativeObject();
NativeObject catchScopeObject = new NativeObject();
// See ECMA 12.4 // See ECMA 12.4
catchScope.defineProperty( catchScopeObject.defineProperty(
exceptionName, obj, ScriptableObject.PERMANENT); exceptionName, obj, ScriptableObject.PERMANENT);
catchScope.associateValue(exception, obj); if (cacheObj) {
return catchScope; catchScopeObject.associateValue(t, obj);
}
return catchScopeObject;
} }
public static Scriptable enterWith(Object value, Scriptable scope) public static Scriptable enterWith(Object value, Scriptable scope)

Просмотреть файл

@ -1192,7 +1192,7 @@ class BodyCodegen
localsMax = firstFreeLocal; localsMax = firstFreeLocal;
if (fnCurrent == null) { if (fnCurrent == null) {
// See comments in visitRegexp // See comments in case Token.REGEXP
if (scriptOrFn.getRegexpCount() != 0) { if (scriptOrFn.getRegexpCount() != 0) {
scriptRegexpLocal = getNewWordLocal(); scriptRegexpLocal = getNewWordLocal();
codegen.pushRegExpArray(cfw, scriptOrFn, contextLocal, codegen.pushRegExpArray(cfw, scriptOrFn, contextLocal,
@ -1470,11 +1470,50 @@ class BodyCodegen
break; break;
case Token.CATCH_SCOPE: case Token.CATCH_SCOPE:
visitCatchScope(node, child); {
int local = getLocalBlockRegister(node);
int scopeIndex
= node.getExistingIntProp(Node.CATCH_SCOPE_PROP);
String name = child.getString(); // name of exception
child = child.getNext();
generateExpression(child, node); // load expression object
if (scopeIndex == 0) {
cfw.add(ByteCode.ACONST_NULL);
} else {
// Load previous catch scope object
cfw.addALoad(local);
}
cfw.addPush(name);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"newCatchScope",
"(Ljava/lang/Throwable;"
+"Lorg/mozilla/javascript/Scriptable;"
+"Ljava/lang/String;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Scriptable;");
cfw.addAStore(local);
}
break; break;
case Token.THROW: case Token.THROW:
visitThrow(node, child); generateExpression(child, node);
cfw.add(ByteCode.NEW,
"org/mozilla/javascript/JavaScriptException");
cfw.add(ByteCode.DUP_X1);
cfw.add(ByteCode.SWAP);
cfw.addPush(scriptOrFn.getSourceName());
cfw.addPush(itsLineNumber);
cfw.addInvoke(
ByteCode.INVOKESPECIAL,
"org/mozilla/javascript/JavaScriptException",
"<init>",
"(Ljava/lang/Object;Ljava/lang/String;I)V");
cfw.add(ByteCode.ATHROW);
break; break;
case Token.RETHROW: case Token.RETHROW:
@ -1504,11 +1543,23 @@ class BodyCodegen
break; break;
case Token.ENTERWITH: case Token.ENTERWITH:
visitEnterWith(node, child); generateExpression(child, node);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"enterWith",
"(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Scriptable;");
cfw.addAStore(variableObjectLocal);
break; break;
case Token.LEAVEWITH: case Token.LEAVEWITH:
visitLeaveWith(node, child); cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"leaveWith",
"(Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Scriptable;");
cfw.addAStore(variableObjectLocal);
break; break;
case Token.ENUM_INIT_KEYS: case Token.ENUM_INIT_KEYS:
@ -1547,7 +1598,10 @@ class BodyCodegen
break; break;
case Token.TARGET: case Token.TARGET:
visitTarget((Node.Target)node); {
int label = getTargetLabel((Node.Target)node);
cfw.markLabel(label);
}
break; break;
case Token.JSR: case Token.JSR:
@ -1558,7 +1612,17 @@ class BodyCodegen
break; break;
case Token.FINALLY: case Token.FINALLY:
visitFinally(node, child); {
//Save return address in a new local where
int finallyRegister = getNewWordLocal();
cfw.addAStore(finallyRegister);
while (child != null) {
generateStatement(child, node);
child = child.getNext();
}
cfw.add(ByteCode.RET, finallyRegister);
releaseWordLocal((short)finallyRegister);
}
break; break;
default: default:
@ -1589,27 +1653,68 @@ class BodyCodegen
break; break;
case Token.NAME: case Token.NAME:
visitName(node); {
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
cfw.addPush(node.getString());
addScriptRuntimeInvoke(
"name",
"(Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+"Ljava/lang/String;"
+")Ljava/lang/Object;");
}
break; break;
case Token.CALL: case Token.CALL:
case Token.NEW: { case Token.NEW:
int specialType = node.getIntProp(Node.SPECIALCALL_PROP, {
Node.NON_SPECIALCALL); int specialType = node.getIntProp(Node.SPECIALCALL_PROP,
if (specialType == Node.NON_SPECIALCALL) { Node.NON_SPECIALCALL);
visitCall(node, type, child); if (specialType == Node.NON_SPECIALCALL) {
} else { OptFunctionNode target;
visitSpecialCall(node, type, specialType, child); target = (OptFunctionNode)node.getProp(
Node.DIRECTCALL_PROP);
if (target != null) {
visitOptimizedCall(node, target, type, child);
} else if (type == Token.CALL) {
visitStandardCall(node, child);
} else {
visitStandardNew(node, child);
}
} else {
visitSpecialCall(node, type, specialType, child);
}
} }
break; break;
}
case Token.REF_CALL: case Token.REF_CALL:
visitRefCall(node, type, child); generateFunctionAndThisObj(child, node);
// stack: ... functionObj thisObj
child = child.getNext();
generateCallArgArray(node, child, false);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"referenceCall",
"(Lorg/mozilla/javascript/Function;"
+"Lorg/mozilla/javascript/Scriptable;"
+"[Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
break; break;
case Token.NUMBER: case Token.NUMBER:
visitNumber(node); {
double num = node.getDouble();
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
cfw.addPush(num);
} else {
codegen.pushNumberAsObject(cfw, num);
}
}
break; break;
case Token.STRING: case Token.STRING:
@ -1639,7 +1744,24 @@ class BodyCodegen
break; break;
case Token.REGEXP: case Token.REGEXP:
visitRegexp(node); {
int i = node.getExistingIntProp(Node.REGEXP_PROP);
// Scripts can not use REGEXP_ARRAY_FIELD_NAME since
// it it will make script.exec non-reentrant so they
// store regexp array in a local variable while
// functions always access precomputed
// REGEXP_ARRAY_FIELD_NAME not to consume locals
if (fnCurrent == null) {
cfw.addALoad(scriptRegexpLocal);
} else {
cfw.addALoad(funObjLocal);
cfw.add(ByteCode.GETFIELD, codegen.mainClassName,
Codegen.REGEXP_ARRAY_FIELD_NAME,
Codegen.REGEXP_ARRAY_FIELD_TYPE);
}
cfw.addPush(i);
cfw.add(ByteCode.AALOAD);
}
break; break;
case Token.COMMA: { case Token.COMMA: {
@ -1875,11 +1997,35 @@ class BodyCodegen
break; break;
case Token.GETELEM: case Token.GETELEM:
visitGetElem(node, child); generateExpression(child, node); // object
generateExpression(child.getNext(), node); // id
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
addOptRuntimeInvoke(
"getObjectIndex",
"(Ljava/lang/Object;D"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
else {
addScriptRuntimeInvoke(
"getObjectElem",
"(Ljava/lang/Object;"
+"Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
break; break;
case Token.GET_REF: case Token.GET_REF:
visitGetRef(node, child); generateExpression(child, node); // reference
addScriptRuntimeInvoke(
"getReference",
"(Ljava/lang/Object;"
+")Ljava/lang/Object;");
break; break;
case Token.GETVAR: case Token.GETVAR:
@ -1906,7 +2052,23 @@ class BodyCodegen
case Token.SET_REF: case Token.SET_REF:
case Token.SET_REF_OP: case Token.SET_REF_OP:
visitSetRef(type, node, child); {
generateExpression(child, node);
child = child.getNext();
if (type == Token.SET_REF_OP) {
cfw.add(ByteCode.DUP);
addScriptRuntimeInvoke(
"getReference",
"(Ljava/lang/Object;"
+")Ljava/lang/Object;");
}
generateExpression(child, node);
addScriptRuntimeInvoke(
"setReference",
"(Ljava/lang/Object;"
+"Ljava/lang/Object;"
+")Ljava/lang/Object;");
}
break; break;
case Token.DEL_REF: case Token.DEL_REF:
@ -1931,7 +2093,22 @@ class BodyCodegen
break; break;
case Token.BINDNAME: case Token.BINDNAME:
visitBind(node, child); {
while (child != null) {
generateExpression(child, node);
child = child.getNext();
}
// Generate code for "ScriptRuntime.bind(varObj, "s")"
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
cfw.addPush(node.getString());
addScriptRuntimeInvoke(
"bind",
"(Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+"Ljava/lang/String;"
+")Lorg/mozilla/javascript/Scriptable;");
}
break; break;
case Token.LOCAL_LOAD: case Token.LOCAL_LOAD:
@ -1939,11 +2116,33 @@ class BodyCodegen
break; break;
case Token.SPECIAL_REF: case Token.SPECIAL_REF:
visitSpecialRef(node, child); {
String special
= (String)node.getProp(Node.SPECIAL_PROP_PROP);
generateExpression(child, node);
cfw.addPush(special);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("specialReference",
"(Ljava/lang/Object;"
+"Ljava/lang/String;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
break; break;
case Token.XML_REF: case Token.XML_REF:
visitXMLRef(node, child); {
generateExpression(child, node);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("xmlReference",
"(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
break; break;
case Token.DOTQUERY: case Token.DOTQUERY:
@ -2142,12 +2341,6 @@ class BodyCodegen
return target.labelId; return target.labelId;
} }
private void visitTarget(Node.Target target)
{
int label = getTargetLabel(target);
cfw.markLabel(label);
}
private void visitGOTO(Node.Jump node, int type, Node child) private void visitGOTO(Node.Jump node, int type, Node child)
{ {
Node.Target target = node.target; Node.Target target = node.target;
@ -2168,39 +2361,6 @@ class BodyCodegen
} }
} }
private void visitFinally(Node node, Node child)
{
//Save return address in a new local where
int finallyRegister = getNewWordLocal();
cfw.addAStore(finallyRegister);
while (child != null) {
generateStatement(child, node);
child = child.getNext();
}
cfw.add(ByteCode.RET, finallyRegister);
releaseWordLocal((short)finallyRegister);
}
private void visitEnterWith(Node node, Node child)
{
generateExpression(child, node);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("enterWith",
"(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Scriptable;");
cfw.addAStore(variableObjectLocal);
}
private void visitLeaveWith(Node node, Node child)
{
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("leaveWith",
"(Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Scriptable;");
cfw.addAStore(variableObjectLocal);
}
private void visitArrayLiteral(Node node, Node child) private void visitArrayLiteral(Node node, Node child)
{ {
int count = 0; int count = 0;
@ -2274,20 +2434,6 @@ class BodyCodegen
+")Lorg/mozilla/javascript/Scriptable;"); +")Lorg/mozilla/javascript/Scriptable;");
} }
private void visitCall(Node node, int type, Node child)
{
OptFunctionNode
target = (OptFunctionNode)node.getProp(Node.DIRECTCALL_PROP);
if (target != null) {
visitOptimizedCall(node, target, type, child);
} else if (type == Token.CALL) {
visitStandardCall(node, child);
} else {
visitStandardNew(node, child);
}
}
private void visitSpecialCall(Node node, int type, int specialType, private void visitSpecialCall(Node node, int type, int specialType,
Node child) Node child)
{ {
@ -2341,23 +2487,6 @@ class BodyCodegen
addOptRuntimeInvoke(methodName, callSignature); addOptRuntimeInvoke(methodName, callSignature);
} }
private void visitRefCall(Node node, int type, Node child)
{
generateFunctionAndThisObj(child, node);
// stack: ... functionObj thisObj
child = child.getNext();
generateCallArgArray(node, child, false);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("referenceCall",
"(Lorg/mozilla/javascript/Function;"
+"Lorg/mozilla/javascript/Scriptable;"
+"[Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
private void visitStandardCall(Node node, Node child) private void visitStandardCall(Node node, Node child)
{ {
if (node.getType() != Token.CALL) throw Codegen.badTree(); if (node.getType() != Token.CALL) throw Codegen.badTree();
@ -2867,23 +2996,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
cfw.add(ByteCode.GOTO, catchLabel); cfw.add(ByteCode.GOTO, catchLabel);
} }
private void visitThrow(Node node, Node child)
{
generateExpression(child, node);
cfw.add(ByteCode.NEW,
"org/mozilla/javascript/JavaScriptException");
cfw.add(ByteCode.DUP_X1);
cfw.add(ByteCode.SWAP);
cfw.addPush(scriptOrFn.getSourceName());
cfw.addPush(itsLineNumber);
cfw.addInvoke(ByteCode.INVOKESPECIAL,
"org/mozilla/javascript/JavaScriptException",
"<init>",
"(Ljava/lang/Object;Ljava/lang/String;I)V");
cfw.add(ByteCode.ATHROW);
}
private void visitSwitch(Node.Jump switchNode, Node child) private void visitSwitch(Node.Jump switchNode, Node child)
{ {
// See comments in IRFactory.createSwitch() for description // See comments in IRFactory.createSwitch() for description
@ -3397,77 +3509,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
if (stackInitial != cfw.getStackTop()) throw Codegen.badTree(); if (stackInitial != cfw.getStackTop()) throw Codegen.badTree();
} }
private void visitNumber(Node node)
{
double num = node.getDouble();
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
cfw.addPush(num);
} else {
codegen.pushNumberAsObject(cfw, num);
}
}
private void visitRegexp(Node node)
{
int i = node.getExistingIntProp(Node.REGEXP_PROP);
// Scripts can not use REGEXP_ARRAY_FIELD_NAME since
// it it will make script.exec non-reentrant so they
// store regexp array in a local variable while
// functions always access precomputed REGEXP_ARRAY_FIELD_NAME
// not to consume locals
if (fnCurrent == null) {
cfw.addALoad(scriptRegexpLocal);
} else {
cfw.addALoad(funObjLocal);
cfw.add(ByteCode.GETFIELD, codegen.mainClassName,
Codegen.REGEXP_ARRAY_FIELD_NAME,
Codegen.REGEXP_ARRAY_FIELD_TYPE);
}
cfw.addPush(i);
cfw.add(ByteCode.AALOAD);
}
private void visitCatchScope(Node node, Node child)
{
int local = getLocalBlockRegister(node);
int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP);
String name = child.getString(); // name of exception variable
child = child.getNext();
generateExpression(child, node); // load expression object
if (scopeIndex == 0) {
cfw.add(ByteCode.ACONST_NULL);
} else {
// Load previous catch scope object
cfw.addALoad(local);
}
cfw.addPush(name);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("newCatchScope",
"(Ljava/lang/Throwable;"
+"Lorg/mozilla/javascript/Scriptable;"
+"Ljava/lang/String;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Lorg/mozilla/javascript/Scriptable;");
cfw.addAStore(local);
}
private void visitName(Node node)
{
cfw.addALoad(contextLocal); // push cx
cfw.addALoad(variableObjectLocal); // get variable object
cfw.addPush(node.getString()); // push name
addScriptRuntimeInvoke(
"name",
"(Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+"Ljava/lang/String;"
+")Ljava/lang/Object;");
}
private void visitSetName(Node node, Node child) private void visitSetName(Node node, Node child)
{ {
String name = node.getFirstChild().getString(); String name = node.getFirstChild().getString();
@ -3609,38 +3650,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
} }
} }
private void visitGetElem(Node node, Node child)
{
generateExpression(child, node); // object
generateExpression(child.getNext(), node); // id
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
addOptRuntimeInvoke(
"getObjectIndex",
"(Ljava/lang/Object;D"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
else {
addScriptRuntimeInvoke(
"getObjectElem",
"(Ljava/lang/Object;"
+"Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
}
private void visitGetRef(Node node, Node child)
{
generateExpression(child, node); // reference
addScriptRuntimeInvoke(
"getReference", "(Ljava/lang/Object;)Ljava/lang/Object;");
}
private void visitSetProp(int type, Node node, Node child) private void visitSetProp(int type, Node node, Node child)
{ {
Node objectChild = child; Node objectChild = child;
@ -3754,65 +3763,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
} }
} }
private void visitSetRef(int type, Node node, Node child)
{
generateExpression(child, node);
child = child.getNext();
if (type == Token.SET_REF_OP) {
cfw.add(ByteCode.DUP);
addScriptRuntimeInvoke(
"getReference", "(Ljava/lang/Object;)Ljava/lang/Object;");
}
generateExpression(child, node);
addScriptRuntimeInvoke(
"setReference",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
}
private void visitBind(Node node, Node child)
{
while (child != null) {
generateExpression(child, node);
child = child.getNext();
}
// Generate code for "ScriptRuntime.bind(varObj, "s")"
cfw.addALoad(contextLocal); // push cx
cfw.addALoad(variableObjectLocal); // push variable object
cfw.addPush(node.getString()); // push name
addScriptRuntimeInvoke("bind",
"(Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+"Ljava/lang/String;"
+")Lorg/mozilla/javascript/Scriptable;");
}
private void visitSpecialRef(Node node, Node child)
{
String special = (String)node.getProp(Node.SPECIAL_PROP_PROP);
generateExpression(child, node);
cfw.addPush(special);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("specialReference",
"(Ljava/lang/Object;"
+"Ljava/lang/String;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
private void visitXMLRef(Node node, Node child)
{
generateExpression(child, node);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("xmlReference",
"(Ljava/lang/Object;"
+"Lorg/mozilla/javascript/Context;"
+"Lorg/mozilla/javascript/Scriptable;"
+")Ljava/lang/Object;");
}
private void visitDotQuery(Node node, Node child) private void visitDotQuery(Node node, Node child)
{ {
updateLineNumber(node); updateLineNumber(node);