Backed out changeset 7246c4dcf997 (
bug 469625) due to trace-test.js failures.
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -828,16 +828,18 @@ array_defineProperty(JSContext *cx, JSOb
if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
return JS_TRUE;
isIndex = js_IdIsIndex(ID_TO_VALUE(id), &i);
if (!isIndex || attrs != JSPROP_ENUMERATE) {
if (!ENSURE_SLOW_ARRAY(cx, obj))
return JS_FALSE;
+ if (isIndex && STOBJ_IS_DELEGATE(obj))
+ cx->runtime->anyArrayProtoHasElement = JS_TRUE;
return js_DefineProperty(cx, obj, id, value, getter, setter, attrs, propp);
}
return array_setProperty(cx, obj, id, &value);
}
static JSBool
array_getAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -1700,16 +1700,17 @@ EmitIndexOp(JSContext *cx, JSOp op, uint
* caller's lexical environment, and embedding a false return on error.
*/
#define EMIT_INDEX_OP(op, index) \
JS_BEGIN_MACRO \
if (!EmitIndexOp(cx, op, index, cg)) \
return JS_FALSE; \
JS_END_MACRO
+
static JSBool
EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{
JSAtomListElement *ale;
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
if (op == JSOP_GETPROP &&
pn->pn_atom == cx->runtime->atomState.lengthAtom) {
@@ -2334,33 +2335,22 @@ EmitXMLName(JSContext *cx, JSParseNode *
return JS_FALSE;
}
return js_Emit1(cx, cg, op) >= 0;
}
#endif
static JSBool
-EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg);
-
-static JSBool
EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
JSBool callContext)
{
JSParseNode *pn2, *pndot, *pnup, *pndown;
ptrdiff_t top;
- /*
- * 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.
- */
- if (pn->pn_atom == cx->runtime->atomState.protoAtom)
- return EmitElemOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, cg);
-
pn2 = pn->pn_expr;
if (callContext) {
JS_ASSERT(pn->pn_type == TOK_DOT);
JS_ASSERT(op == JSOP_GETPROP);
op = JSOP_CALLPROP;
} else if (op == JSOP_GETPROP && pn->pn_type == TOK_DOT) {
if (pn2->pn_op == JSOP_THIS) {
if (pn->pn_atom != cx->runtime->atomState.lengthAtom) {
@@ -5343,21 +5333,16 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
EMIT_INDEX_OP(JSOP_GETXPROP, atomIndex);
break;
case TOK_DOT:
if (js_Emit1(cx, cg, JSOP_DUP) < 0)
return JS_FALSE;
if (pn2->pn_atom == cx->runtime->atomState.lengthAtom) {
if (js_Emit1(cx, cg, JSOP_LENGTH) < 0)
return JS_FALSE;
- } else if (pn2->pn_atom == cx->runtime->atomState.protoAtom) {
- if (!EmitIndexOp(cx, JSOP_QNAMEPART, atomIndex, cg))
- return JS_FALSE;
- if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
- return JS_FALSE;
} else {
EMIT_INDEX_OP(JSOP_GETPROP, atomIndex);
}
break;
case TOK_LB:
#if JS_HAS_LVALUE_RETURN
case TOK_LP:
#endif
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -321,30 +321,20 @@ js_SetProtoOrParent(JSContext *cx, JSObj
(slot == JSSLOT_PROTO) ? js_proto_str
: js_parent_str
#endif
);
}
return JS_FALSE;
}
- /*
- * Maintain the "any Array prototype has indexed properties hazard" flag by
- * conservatively setting it. We simply don't know what pobj has in the way
- * of indexed properties, either directly or along its prototype chain, and
- * we won't expend effort here to find out. We do know that if obj is not
- * an array or a prototype (delegate), then we're ok. And, of course, pobj
- * must be non-null.
- *
- * This pessimistic approach could be improved, but setting __proto__ is
- * quite rare and arguably deserving of deoptimization.
- */
+ // Maintain the "any Array prototype has indexed properties hazard" flag.
if (slot == JSSLOT_PROTO &&
- pobj &&
- (OBJ_IS_ARRAY(cx, obj) || OBJ_IS_DELEGATE(cx, obj))) {
+ OBJ_IS_ARRAY(cx, pobj) &&
+ pobj->fslots[JSSLOT_ARRAY_LENGTH] != 0) {
rt->anyArrayProtoHasElement = JS_TRUE;
}
return JS_TRUE;
}
static JSHashNumber
js_hash_object(const void *key)
{
@@ -3393,34 +3383,29 @@ js_DefineProperty(JSContext *cx, JSObjec
0, 0, propp);
}
/*
* Backward compatibility requires allowing addProperty hooks to mutate the
* nominal initial value of a slot-full property, while GC safety wants that
* value to be stored before the call-out through the hook. Optimize to do
* both while saving cycles for classes that stub their addProperty hook.
- *
- * As in js_SetProtoOrParent (see above), we maintain the "any Array prototype
- * has indexed properties hazard" flag by conservatively setting it.
*/
#define ADD_PROPERTY_HELPER(cx,clasp,obj,scope,sprop,vp,cleanup) \
JS_BEGIN_MACRO \
if ((clasp)->addProperty != JS_PropertyStub) { \
jsval nominal_ = *(vp); \
if (!(clasp)->addProperty(cx, obj, SPROP_USERID(sprop), vp)) { \
cleanup; \
} \
if (*(vp) != nominal_) { \
if (SPROP_HAS_VALID_SLOT(sprop, scope)) \
LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *(vp)); \
} \
} \
- if (STOBJ_IS_DELEGATE(obj) && JSID_IS_INT(sprop->id)) \
- cx->runtime->anyArrayProtoHasElement = JS_TRUE; \
JS_END_MACRO
JSBool
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
uintN flags, intN shortid, JSProperty **propp)
{
JSClass *clasp;
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -8096,16 +8096,17 @@ JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_GOTOX()
{
return true;
}
JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_IFEQX()
{
+ trackCfgMerges(cx->fp->regs->pc);
return record_JSOP_IFEQ();
}
JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_IFNEX()
{
return record_JSOP_IFNE();
}
@@ -8882,17 +8883,17 @@ TraceRecorder::record_JSOP_INT32()
}
JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_LENGTH()
{
jsval& l = stackval(-1);
if (JSVAL_IS_PRIMITIVE(l)) {
if (!JSVAL_IS_STRING(l))
- ABORT_TRACE("non-string primitive JSOP_LENGTH unsupported");
+ ABORT_TRACE("non-string primitives unsupported");
LIns* str_ins = get(&l);
LIns* len_ins = lir->insLoad(LIR_ldp, str_ins, (int)offsetof(JSString, length));
LIns* masked_len_ins = lir->ins2(LIR_piand,
len_ins,
INS_CONSTPTR(JSSTRING_LENGTH_MASK));
LIns *choose_len_ins =