зеркало из https://github.com/mozilla/pjs.git
Backout 5cdf9574bede for build failures.
This commit is contained in:
Родитель
b4e803c892
Коммит
0cb815a367
|
@ -1946,6 +1946,32 @@ EmitElemOpBase(JSContext *cx, BytecodeEmitter *bce, JSOp op)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitSpecialPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
/*
|
||||
* Special case for obj.__proto__ to deoptimize away from fast paths in the
|
||||
* interpreter and trace recorder, which skip dense array instances by
|
||||
* going up to Array.prototype before looking up the property name.
|
||||
*/
|
||||
jsatomid index;
|
||||
if (!bce->makeAtomIndex(pn->pn_atom, &index))
|
||||
return false;
|
||||
if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce))
|
||||
return false;
|
||||
|
||||
if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0)
|
||||
return false;
|
||||
|
||||
if (!EmitElemOpBase(cx, bce, op))
|
||||
return false;
|
||||
|
||||
if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_SWAP) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce,
|
||||
JSBool callContext, JSOp *psuffix = NULL)
|
||||
|
@ -1956,6 +1982,14 @@ EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce,
|
|||
JS_ASSERT(pn->isArity(PN_NAME));
|
||||
pn2 = pn->maybeExpr();
|
||||
|
||||
/* Special case deoptimization for __proto__. */
|
||||
if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) &&
|
||||
pn->pn_atom == cx->runtime->atomState.protoAtom) {
|
||||
if (pn2 && !EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
return EmitSpecialPropOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, bce);
|
||||
}
|
||||
|
||||
if (callContext) {
|
||||
JS_ASSERT(pn->isKind(PNK_DOT));
|
||||
JS_ASSERT(op == JSOP_GETPROP);
|
||||
|
@ -1997,8 +2031,13 @@ EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce,
|
|||
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pndown->pn_offset) < 0)
|
||||
return false;
|
||||
|
||||
if (!EmitAtomOp(cx, pndot, pndot->getOp(), bce))
|
||||
/* Special case deoptimization on __proto__, as above. */
|
||||
if (pndot->isArity(PN_NAME) && pndot->pn_atom == cx->runtime->atomState.protoAtom) {
|
||||
if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, bce))
|
||||
return false;
|
||||
} else if (!EmitAtomOp(cx, pndot, pndot->getOp(), bce)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Reverse the pn_expr link again. */
|
||||
pnup = pndot->pn_expr;
|
||||
|
@ -3739,13 +3778,19 @@ EmitAssignment(JSContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp op, Par
|
|||
EMIT_UINT16_IMM_OP(lhs->isOp(JSOP_SETARG) ? JSOP_GETARG : JSOP_GETLOCAL, atomIndex);
|
||||
}
|
||||
break;
|
||||
case PNK_DOT: {
|
||||
case PNK_DOT:
|
||||
if (Emit1(cx, bce, JSOP_DUP) < 0)
|
||||
return false;
|
||||
bool isLength = (lhs->pn_atom == cx->runtime->atomState.lengthAtom);
|
||||
EMIT_INDEX_OP(isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex);
|
||||
if (lhs->pn_atom == cx->runtime->atomState.protoAtom) {
|
||||
if (!EmitIndexOp(cx, JSOP_QNAMEPART, atomIndex, bce))
|
||||
return false;
|
||||
if (!EmitElemOpBase(cx, bce, JSOP_GETELEM))
|
||||
return false;
|
||||
} else {
|
||||
bool isLength = (lhs->pn_atom == cx->runtime->atomState.lengthAtom);
|
||||
EMIT_INDEX_OP(isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PNK_LB:
|
||||
case PNK_LP:
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
// |jit-test| error: TypeError
|
||||
[].__proto__();
|
|
@ -74,6 +74,28 @@ js_IdIsIndex(jsid id, jsuint *indexp)
|
|||
return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dense arrays are not native -- aobj->isNative() for a dense array aobj
|
||||
* results in false, meaning aobj->map does not point to a js::Shape.
|
||||
*
|
||||
* But Array methods are called via aobj.sort(), e.g., and the interpreter and
|
||||
* the trace recorder must consult the property cache in order to perform well.
|
||||
* The cache works only for native objects.
|
||||
*
|
||||
* Therefore the interpreter (js_Interpret in JSOP_GETPROP and JSOP_CALLPROP)
|
||||
* and js_GetPropertyHelper use this inline function to skip up one link in the
|
||||
* prototype chain when obj is a dense array, in order to find a native object
|
||||
* (to wit, Array.prototype) in which to probe for cached methods.
|
||||
*
|
||||
* Note that setting aobj.__proto__ for a dense array aobj turns aobj into a
|
||||
* slow array, avoiding the neede to skip.
|
||||
*
|
||||
* Callers of js_GetProtoIfDenseArray must take care to use the original object
|
||||
* (obj) for the |this| value of a getter, setter, or method call (bug 476447).
|
||||
*/
|
||||
inline JSObject *
|
||||
js_GetProtoIfDenseArray(JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_InitArrayClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
|
|
@ -5359,15 +5359,16 @@ static JS_ALWAYS_INLINE JSBool
|
|||
js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id,
|
||||
uint32_t getHow, Value *vp)
|
||||
{
|
||||
JSObject *obj2;
|
||||
JSObject *aobj, *obj2;
|
||||
JSProperty *prop;
|
||||
const Shape *shape;
|
||||
|
||||
/* Convert string indices to integers if appropriate. */
|
||||
id = js_CheckForStringIndex(id);
|
||||
|
||||
aobj = js_GetProtoIfDenseArray(obj);
|
||||
/* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */
|
||||
if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &prop))
|
||||
if (!LookupPropertyWithFlagsInline(cx, aobj, id, cx->resolveFlags, &obj2, &prop))
|
||||
return false;
|
||||
|
||||
if (!prop) {
|
||||
|
@ -5441,7 +5442,7 @@ js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsi
|
|||
shape = (Shape *) prop;
|
||||
|
||||
if (getHow & JSGET_CACHE_RESULT)
|
||||
JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, obj2, shape);
|
||||
JS_PROPERTY_CACHE(cx).fill(cx, aobj, 0, obj2, shape);
|
||||
|
||||
/* This call site is hot -- use the always-inlined variant of js_NativeGet(). */
|
||||
if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp))
|
||||
|
|
|
@ -1995,6 +1995,12 @@ js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
|
|||
JSObject **ctorp = NULL,
|
||||
js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);
|
||||
|
||||
inline JSObject *
|
||||
js_GetProtoIfDenseArray(JSObject *obj)
|
||||
{
|
||||
return obj->isDenseArray() ? obj->getProto() : obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
|
||||
* scope, else it reshapes the scope and prototype chains it links. It calls
|
||||
|
|
|
@ -761,19 +761,7 @@ struct GetPropHelper {
|
|||
}
|
||||
|
||||
LookupStatus lookup() {
|
||||
/*
|
||||
* Skip to the prototype of dense arrays, which are non-native objects
|
||||
* and otherwise uncacheable. This is not valid to do for indexed
|
||||
* properties (which will not be a PropertyName), nor for __proto__,
|
||||
* which needs to be filtered here.
|
||||
*/
|
||||
JSObject *aobj = obj;
|
||||
if (obj->isDenseArray()) {
|
||||
if (name == cx->runtime->atomState.protoAtom)
|
||||
return ic.disable(cx, "__proto__");
|
||||
aobj = obj->getProto();
|
||||
}
|
||||
|
||||
JSObject *aobj = js_GetProtoIfDenseArray(obj);
|
||||
if (!aobj->isNative())
|
||||
return ic.disable(f, "non-native");
|
||||
|
||||
|
@ -2616,8 +2604,8 @@ GetElementIC::update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *
|
|||
/*
|
||||
* Only treat this as a GETPROP for non-numeric string identifiers. The
|
||||
* GETPROP IC assumes the id has already gone through filtering for string
|
||||
* indexes in the emitter, i.e. skipping to the prototype of dense arrays
|
||||
* is only valid to do when looking up non-integer identifiers.
|
||||
* indexes in the emitter, i.e. js_GetProtoIfDenseArray is only valid to
|
||||
* use when looking up non-integer identifiers.
|
||||
*/
|
||||
if (v.isString() && js_CheckForStringIndex(id) == id)
|
||||
return attachGetProp(f, obj, v, JSID_TO_ATOM(id)->asPropertyName(), vp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче