зеркало из https://github.com/mozilla/gecko-dev.git
Reverting Ref to the original implementation which did not pass an additional
"Scriptable target" argument to Ref.(get|set|has|delete) methods. The idea was to optimize away in many cases creation of Ref instances, but given that modern JVM can GC short-lived objects efficiently it does not sound right to have code complexity now in the hope of slightly more efficient implementation later.
This commit is contained in:
Родитель
6d5f26df27
Коммит
31d9030dd0
|
@ -2561,7 +2561,4 @@ public class Context
|
|||
|
||||
// It can be used to return the second Scriptable result from function
|
||||
Scriptable scratchScriptable;
|
||||
|
||||
// It is used to return the target component for Ref instance
|
||||
Scriptable scratchRefTarget;
|
||||
}
|
||||
|
|
|
@ -857,7 +857,6 @@ public class Interpreter
|
|||
int type = node.getType();
|
||||
Node child = node.getFirstChild();
|
||||
int savedStackDepth = itsStackDepth;
|
||||
int expectedStackDelta = 1;
|
||||
switch (type) {
|
||||
|
||||
case Token.FUNCTION:
|
||||
|
@ -902,9 +901,6 @@ public class Interpreter
|
|||
break;
|
||||
|
||||
case Token.REF_CALL:
|
||||
// account for the reference represented as pair (ref, target)
|
||||
expectedStackDelta = 2;
|
||||
// fallthrough
|
||||
case Token.CALL:
|
||||
case Token.NEW:
|
||||
{
|
||||
|
@ -1043,7 +1039,6 @@ public class Interpreter
|
|||
case Token.DEL_REF:
|
||||
visitExpression(child, 0);
|
||||
addToken(type);
|
||||
stackChange(-1);
|
||||
break;
|
||||
|
||||
case Token.SETPROP:
|
||||
|
@ -1090,16 +1085,15 @@ public class Interpreter
|
|||
visitExpression(child, 0);
|
||||
child = child.getNext();
|
||||
if (type == Token.SET_REF_OP) {
|
||||
addIcode(Icode_DUP2);
|
||||
stackChange(2);
|
||||
addIcode(Icode_DUP);
|
||||
stackChange(1);
|
||||
addToken(Token.GET_REF);
|
||||
stackChange(-1);
|
||||
// Compensate for the following USE_STACK
|
||||
stackChange(-1);
|
||||
}
|
||||
visitExpression(child, 0);
|
||||
addToken(Token.SET_REF);
|
||||
stackChange(-2);
|
||||
stackChange(-1);
|
||||
break;
|
||||
|
||||
case Token.SETNAME:
|
||||
|
@ -1225,8 +1219,6 @@ public class Interpreter
|
|||
case Token.REF_SPECIAL:
|
||||
visitExpression(child, 0);
|
||||
addStringOp(type, (String)node.getProp(Node.NAME_PROP));
|
||||
stackChange(1);
|
||||
expectedStackDelta = 2;
|
||||
break;
|
||||
|
||||
case Token.REF_MEMBER:
|
||||
|
@ -1243,8 +1235,7 @@ public class Interpreter
|
|||
child = child.getNext();
|
||||
} while (child != null);
|
||||
addIndexOp(type, memberTypeFlags);
|
||||
stackChange(2 - childCount);
|
||||
expectedStackDelta = 2;
|
||||
stackChange(1 - childCount);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1271,7 +1262,7 @@ public class Interpreter
|
|||
default:
|
||||
throw badTree(node);
|
||||
}
|
||||
if (savedStackDepth + expectedStackDelta != itsStackDepth) {
|
||||
if (savedStackDepth + 1 != itsStackDepth) {
|
||||
Kit.codeBug();
|
||||
}
|
||||
}
|
||||
|
@ -1359,7 +1350,6 @@ public class Interpreter
|
|||
visitExpression(ref, 0);
|
||||
addIcode(Icode_REF_INC_DEC);
|
||||
addUint8(incrDecrMask);
|
||||
stackChange(-1);
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
|
@ -2763,35 +2753,26 @@ switch (op) {
|
|||
continue Loop;
|
||||
}
|
||||
case Token.GET_REF : {
|
||||
Scriptable target = (Scriptable)stack[stackTop];
|
||||
--stackTop;
|
||||
Ref ref = (Ref)stack[stackTop];
|
||||
stack[stackTop] = ScriptRuntime.refGet(ref, target, cx);
|
||||
stack[stackTop] = ScriptRuntime.refGet(ref, cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Token.SET_REF : {
|
||||
Object value = stack[stackTop];
|
||||
if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
|
||||
--stackTop;
|
||||
Scriptable target = (Scriptable)stack[stackTop];
|
||||
--stackTop;
|
||||
Ref ref = (Ref)stack[stackTop];
|
||||
stack[stackTop] = ScriptRuntime.refSet(ref, target, value, cx);
|
||||
stack[stackTop] = ScriptRuntime.refSet(ref, value, cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Token.DEL_REF : {
|
||||
Scriptable target = (Scriptable)stack[stackTop];
|
||||
--stackTop;
|
||||
Ref ref = (Ref)stack[stackTop];
|
||||
stack[stackTop] = ScriptRuntime.refDel(ref, target, cx);
|
||||
stack[stackTop] = ScriptRuntime.refDel(ref, cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Icode_REF_INC_DEC : {
|
||||
Scriptable target = (Scriptable)stack[stackTop];
|
||||
--stackTop;
|
||||
Ref ref = (Ref)stack[stackTop];
|
||||
stack[stackTop] = ScriptRuntime.refIncrDecr(ref, target, cx,
|
||||
iCode[frame.pc]);
|
||||
stack[stackTop] = ScriptRuntime.refIncrDecr(ref, cx, iCode[frame.pc]);
|
||||
++frame.pc;
|
||||
continue Loop;
|
||||
}
|
||||
|
@ -2902,8 +2883,6 @@ switch (op) {
|
|||
indexReg);
|
||||
stack[stackTop] = ScriptRuntime.callRef(fun, funThisObj, outArgs,
|
||||
cx, calleeScope);
|
||||
++stackTop;
|
||||
stack[stackTop] = Ref.popTarget(cx);
|
||||
continue Loop;
|
||||
}
|
||||
|
||||
|
@ -3195,8 +3174,6 @@ switch (op) {
|
|||
Object obj = stack[stackTop];
|
||||
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
|
||||
stack[stackTop] = ScriptRuntime.specialRef(obj, stringReg, cx);
|
||||
++stackTop;
|
||||
stack[stackTop] = Ref.popTarget(cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Token.REF_MEMBER: {
|
||||
|
@ -3207,8 +3184,6 @@ switch (op) {
|
|||
Object obj = stack[stackTop];
|
||||
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
|
||||
stack[stackTop] = ScriptRuntime.memberRef(obj, elem, cx, indexReg);
|
||||
++stackTop;
|
||||
stack[stackTop] = Ref.popTarget(cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Token.REF_NS_MEMBER: {
|
||||
|
@ -3222,8 +3197,6 @@ switch (op) {
|
|||
Object obj = stack[stackTop];
|
||||
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
|
||||
stack[stackTop] = ScriptRuntime.memberRef(obj, ns, elem, cx, indexReg);
|
||||
++stackTop;
|
||||
stack[stackTop] = Ref.popTarget(cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Token.REF_NAME: {
|
||||
|
@ -3232,8 +3205,6 @@ switch (op) {
|
|||
if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]);
|
||||
stack[stackTop] = ScriptRuntime.nameRef(name, cx, frame.scope,
|
||||
indexReg);
|
||||
++stackTop;
|
||||
stack[stackTop] = Ref.popTarget(cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Token.REF_NS_NAME: {
|
||||
|
@ -3245,8 +3216,6 @@ switch (op) {
|
|||
if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]);
|
||||
stack[stackTop] = ScriptRuntime.nameRef(ns, name, cx, frame.scope,
|
||||
indexReg);
|
||||
++stackTop;
|
||||
stack[stackTop] = Ref.popTarget(cx);
|
||||
continue Loop;
|
||||
}
|
||||
case Icode_SCOPE_LOAD :
|
||||
|
|
|
@ -43,30 +43,16 @@ import java.io.Serializable;
|
|||
*/
|
||||
public abstract class Ref implements Serializable
|
||||
{
|
||||
public static Ref pushTarget(Context cx, Ref ref, Scriptable target)
|
||||
{
|
||||
if (cx.scratchRefTarget != null) throw new IllegalStateException();
|
||||
cx.scratchRefTarget = target;
|
||||
return ref;
|
||||
}
|
||||
|
||||
public static Scriptable popTarget(Context cx)
|
||||
{
|
||||
Scriptable target = cx.scratchRefTarget;
|
||||
cx.scratchRefTarget = null;
|
||||
return target;
|
||||
}
|
||||
|
||||
public boolean has(Context cx, Scriptable target)
|
||||
public boolean has(Context cx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract Object get(Context cx, Scriptable target);
|
||||
public abstract Object get(Context cx);
|
||||
|
||||
public abstract Object set(Context cx, Scriptable target, Object value);
|
||||
public abstract Object set(Context cx, Object value);
|
||||
|
||||
public boolean delete(Context cx, Scriptable target)
|
||||
public boolean delete(Context cx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1505,20 +1505,19 @@ public class ScriptRuntime {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static Object refGet(Ref ref, Scriptable target, Context cx)
|
||||
public static Object refGet(Ref ref, Context cx)
|
||||
{
|
||||
return ref.get(cx, target);
|
||||
return ref.get(cx);
|
||||
}
|
||||
|
||||
public static Object refSet(Ref ref, Scriptable target,
|
||||
Object value, Context cx)
|
||||
public static Object refSet(Ref ref, Object value, Context cx)
|
||||
{
|
||||
return ref.set(cx, target, value);
|
||||
return ref.set(cx, value);
|
||||
}
|
||||
|
||||
public static Object refDel(Ref ref, Scriptable target, Context cx)
|
||||
public static Object refDel(Ref ref, Context cx)
|
||||
{
|
||||
return wrapBoolean(ref.delete(cx, target));
|
||||
return wrapBoolean(ref.delete(cx));
|
||||
}
|
||||
|
||||
static boolean isSpecialProperty(String s)
|
||||
|
@ -2035,7 +2034,6 @@ public class ScriptRuntime {
|
|||
BaseFunction bf = (BaseFunction)function;
|
||||
Ref ref = bf.callRef(cx, scope, thisObj, args);
|
||||
if (ref != null) {
|
||||
storeScriptable(cx, thisObj);
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
@ -2405,10 +2403,9 @@ public class ScriptRuntime {
|
|||
}
|
||||
}
|
||||
|
||||
public static Object refIncrDecr(Ref ref, Scriptable target,
|
||||
Context cx, int incrDecrMask)
|
||||
public static Object refIncrDecr(Ref ref, Context cx, int incrDecrMask)
|
||||
{
|
||||
Object value = ref.get(cx, target);
|
||||
Object value = ref.get(cx);
|
||||
boolean post = ((incrDecrMask & Node.POST_FLAG) != 0);
|
||||
double number;
|
||||
if (value instanceof Number) {
|
||||
|
@ -2426,7 +2423,7 @@ public class ScriptRuntime {
|
|||
--number;
|
||||
}
|
||||
Number result = wrapNumber(number);
|
||||
ref.set(cx, target, result);
|
||||
ref.set(cx, result);
|
||||
if (post) {
|
||||
return value;
|
||||
} else {
|
||||
|
|
|
@ -41,11 +41,13 @@ class SpecialRef extends Ref
|
|||
private static final int SPECIAL_PROTO = 1;
|
||||
private static final int SPECIAL_PARENT = 2;
|
||||
|
||||
private Scriptable target;
|
||||
private int type;
|
||||
private String name;
|
||||
|
||||
private SpecialRef(int type, String name)
|
||||
private SpecialRef(Scriptable target, int type, String name)
|
||||
{
|
||||
this.target = target;
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -71,10 +73,10 @@ class SpecialRef extends Ref
|
|||
type = SPECIAL_NONE;
|
||||
}
|
||||
|
||||
return Ref.pushTarget(cx, new SpecialRef(type, name), target);
|
||||
return new SpecialRef(target, type, name);
|
||||
}
|
||||
|
||||
public Object get(Context cx, Scriptable target)
|
||||
public Object get(Context cx)
|
||||
{
|
||||
switch (type) {
|
||||
case SPECIAL_NONE:
|
||||
|
@ -88,7 +90,7 @@ class SpecialRef extends Ref
|
|||
}
|
||||
}
|
||||
|
||||
public Object set(Context cx, Scriptable target, Object value)
|
||||
public Object set(Context cx, Object value)
|
||||
{
|
||||
switch (type) {
|
||||
case SPECIAL_NONE:
|
||||
|
@ -125,7 +127,7 @@ class SpecialRef extends Ref
|
|||
}
|
||||
}
|
||||
|
||||
public boolean has(Context cx, Scriptable target)
|
||||
public boolean has(Context cx)
|
||||
{
|
||||
if (type == SPECIAL_NONE) {
|
||||
return ScriptRuntime.hasObjectElem(target, name, cx);
|
||||
|
@ -133,7 +135,7 @@ class SpecialRef extends Ref
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean delete(Context cx, Scriptable target)
|
||||
public boolean delete(Context cx)
|
||||
{
|
||||
if (type == SPECIAL_NONE) {
|
||||
return ScriptRuntime.deleteObjectElem(target, name, cx);
|
||||
|
|
|
@ -1785,8 +1785,6 @@ class BodyCodegen
|
|||
+"Lorg/mozilla/javascript/Context;"
|
||||
+"Lorg/mozilla/javascript/Scriptable;"
|
||||
+")Ljava/lang/Object;");
|
||||
// Load reference target stored in cx by refCal
|
||||
refTargetToStack();
|
||||
break;
|
||||
|
||||
case Token.NUMBER:
|
||||
|
@ -2101,12 +2099,11 @@ class BodyCodegen
|
|||
break;
|
||||
|
||||
case Token.GET_REF:
|
||||
generateExpression(child, node); // reference and target
|
||||
generateExpression(child, node); // reference
|
||||
cfw.addALoad(contextLocal);
|
||||
addScriptRuntimeInvoke(
|
||||
"refGet",
|
||||
"(Lorg/mozilla/javascript/Ref;"
|
||||
+"Lorg/mozilla/javascript/Scriptable;"
|
||||
+"Lorg/mozilla/javascript/Context;"
|
||||
+")Ljava/lang/Object;");
|
||||
break;
|
||||
|
@ -2139,12 +2136,11 @@ class BodyCodegen
|
|||
generateExpression(child, node);
|
||||
child = child.getNext();
|
||||
if (type == Token.SET_REF_OP) {
|
||||
cfw.add(ByteCode.DUP2);
|
||||
cfw.add(ByteCode.DUP);
|
||||
cfw.addALoad(contextLocal);
|
||||
addScriptRuntimeInvoke(
|
||||
"refGet",
|
||||
"(Lorg/mozilla/javascript/Ref;"
|
||||
+"Lorg/mozilla/javascript/Scriptable;"
|
||||
+"Lorg/mozilla/javascript/Context;"
|
||||
+")Ljava/lang/Object;");
|
||||
}
|
||||
|
@ -2153,7 +2149,6 @@ class BodyCodegen
|
|||
addScriptRuntimeInvoke(
|
||||
"refSet",
|
||||
"(Lorg/mozilla/javascript/Ref;"
|
||||
+"Lorg/mozilla/javascript/Scriptable;"
|
||||
+"Ljava/lang/Object;"
|
||||
+"Lorg/mozilla/javascript/Context;"
|
||||
+")Ljava/lang/Object;");
|
||||
|
@ -2165,7 +2160,6 @@ class BodyCodegen
|
|||
cfw.addALoad(contextLocal);
|
||||
addScriptRuntimeInvoke("refDel",
|
||||
"(Lorg/mozilla/javascript/Ref;"
|
||||
+"Lorg/mozilla/javascript/Scriptable;"
|
||||
+"Lorg/mozilla/javascript/Context;"
|
||||
+")Ljava/lang/Object;");
|
||||
break;
|
||||
|
@ -2217,8 +2211,6 @@ class BodyCodegen
|
|||
+"Ljava/lang/String;"
|
||||
+"Lorg/mozilla/javascript/Context;"
|
||||
+")Lorg/mozilla/javascript/Ref;");
|
||||
// Load reference target stored in cx by specialRef
|
||||
refTargetToStack();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2277,8 +2269,6 @@ class BodyCodegen
|
|||
}
|
||||
cfw.addPush(memberTypeFlags);
|
||||
addScriptRuntimeInvoke(methodName, signature);
|
||||
// Load reference target stored in cx by methodName
|
||||
refTargetToStack();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3258,7 +3248,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
|
|||
addScriptRuntimeInvoke(
|
||||
"refIncrDecr",
|
||||
"(Lorg/mozilla/javascript/Ref;"
|
||||
+"Lorg/mozilla/javascript/Scriptable;"
|
||||
+"Lorg/mozilla/javascript/Context;"
|
||||
+"I)Ljava/lang/Object;");
|
||||
break;
|
||||
|
@ -3932,16 +3921,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
|
|||
}
|
||||
}
|
||||
|
||||
private void refTargetToStack()
|
||||
{
|
||||
cfw.addALoad(contextLocal);
|
||||
cfw.addInvoke(ByteCode.INVOKESTATIC,
|
||||
"org.mozilla.javascript.Ref",
|
||||
"popTarget",
|
||||
"(Lorg/mozilla/javascript/Context;"
|
||||
+")Lorg/mozilla/javascript/Scriptable;");
|
||||
}
|
||||
|
||||
private void addScriptRuntimeInvoke(String methodName,
|
||||
String methodSignature)
|
||||
{
|
||||
|
|
|
@ -678,7 +678,10 @@ public final class XMLLibImpl extends XMLLib
|
|||
|
||||
// xmlObj == null corresponds to undefined as the target of
|
||||
// the reference
|
||||
return Ref.pushTarget(cx, xmlName, xmlObj);
|
||||
if (xmlObj != null) {
|
||||
xmlName.initXMLObject(xmlObj);
|
||||
}
|
||||
return xmlName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@ class XMLName extends Ref
|
|||
private String localName;
|
||||
private boolean isAttributeName;
|
||||
private boolean isDescendants;
|
||||
private XMLObjectImpl xmlObject;
|
||||
|
||||
private XMLName(String uri, String localName)
|
||||
{
|
||||
|
@ -65,6 +66,13 @@ class XMLName extends Ref
|
|||
{
|
||||
return new XMLName(uri, localName);
|
||||
}
|
||||
|
||||
void initXMLObject(XMLObjectImpl xmlObject)
|
||||
{
|
||||
if (xmlObject == null) throw new IllegalArgumentException();
|
||||
if (this.xmlObject != null) throw new IllegalStateException();
|
||||
this.xmlObject = xmlObject;
|
||||
}
|
||||
|
||||
String uri()
|
||||
{
|
||||
|
@ -98,18 +106,16 @@ class XMLName extends Ref
|
|||
isDescendants = true;
|
||||
}
|
||||
|
||||
public boolean has(Context cx, Scriptable target)
|
||||
public boolean has(Context cx)
|
||||
{
|
||||
XMLObjectImpl xmlObject = (XMLObjectImpl)target;
|
||||
if (xmlObject == null) {
|
||||
return false;
|
||||
}
|
||||
return xmlObject.hasXMLProperty(this);
|
||||
}
|
||||
|
||||
public Object get(Context cx, Scriptable target)
|
||||
public Object get(Context cx)
|
||||
{
|
||||
XMLObjectImpl xmlObject = (XMLObjectImpl)target;
|
||||
if (xmlObject == null) {
|
||||
throw ScriptRuntime.undefReadError(Undefined.instance,
|
||||
toString());
|
||||
|
@ -117,9 +123,8 @@ class XMLName extends Ref
|
|||
return xmlObject.getXMLProperty(this);
|
||||
}
|
||||
|
||||
public Object set(Context cx, Scriptable target, Object value)
|
||||
public Object set(Context cx, Object value)
|
||||
{
|
||||
XMLObjectImpl xmlObject = (XMLObjectImpl)target;
|
||||
if (xmlObject == null) {
|
||||
throw ScriptRuntime.undefWriteError(Undefined.instance,
|
||||
toString(),
|
||||
|
@ -132,9 +137,8 @@ class XMLName extends Ref
|
|||
return value;
|
||||
}
|
||||
|
||||
public boolean delete(Context cx, Scriptable target)
|
||||
public boolean delete(Context cx)
|
||||
{
|
||||
XMLObjectImpl xmlObject = (XMLObjectImpl)target;
|
||||
if (xmlObject == null) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -267,7 +267,8 @@ abstract class XMLObjectImpl extends XMLObject
|
|||
if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) {
|
||||
xmlName.setIsDescendants();
|
||||
}
|
||||
return Ref.pushTarget(cx, xmlName, this);
|
||||
xmlName.initXMLObject(this);
|
||||
return xmlName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,7 +286,8 @@ abstract class XMLObjectImpl extends XMLObject
|
|||
if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) {
|
||||
xmlName.setIsDescendants();
|
||||
}
|
||||
return Ref.pushTarget(cx, xmlName, this);
|
||||
xmlName.initXMLObject(this);
|
||||
return xmlName;
|
||||
}
|
||||
|
||||
public NativeWith enterWith(Scriptable scope)
|
||||
|
|
Загрузка…
Ссылка в новой задаче