--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2580,17 +2580,17 @@ AssertValidPropertyCacheHit(JSContext *c
} else if (PCVAL_IS_SPROP(entry->vword)) {
JS_ASSERT(PCVAL_TO_SPROP(entry->vword) == sprop);
JS_ASSERT_IF(sprop->isMethod(),
sprop->methodValue() == LOCKED_OBJ_GET_SLOT(pobj, sprop->slot));
} else {
jsval v;
JS_ASSERT(PCVAL_IS_OBJECT(entry->vword));
JS_ASSERT(entry->vword != PCVAL_NULL);
- JS_ASSERT(OBJ_SCOPE(pobj)->branded() || OBJ_SCOPE(pobj)->hasMethodBarrier());
+ JS_ASSERT(OBJ_SCOPE(pobj)->brandedOrHasMethodBarrier());
JS_ASSERT(SPROP_HAS_STUB_GETTER_OR_IS_METHOD(sprop));
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
JS_ASSERT(VALUE_IS_FUNCTION(cx, v));
JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v));
if (sprop->isMethod()) {
JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_CALLOP);
--- a/js/src/jsops.cpp
+++ b/js/src/jsops.cpp
@@ -624,17 +624,17 @@ END_CASE(JSOP_PICK)
} \
JS_END_MACRO
#define NATIVE_SET(cx,obj,sprop,entry,vp) \
JS_BEGIN_MACRO \
TRACE_2(SetPropHit, entry, sprop); \
if (SPROP_HAS_STUB_SETTER(sprop) && \
(sprop)->slot != SPROP_INVALID_SLOT && \
- !OBJ_SCOPE(obj)->branded()) { \
+ !OBJ_SCOPE(obj)->brandedOrHasMethodBarrier()) { \
/* Fast path for, e.g., plain Object instance properties. */ \
LOCKED_OBJ_SET_SLOT(obj, (sprop)->slot, *vp); \
} else { \
if (!js_NativeSet(cx, obj, sprop, false, vp)) \
goto error; \
} \
JS_END_MACRO
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -382,16 +382,25 @@ struct JSScope : public JSObjectMap
*
* The BRANDED write barrier, JSScope::methodWriteBarrer, must check for
* METHOD_BARRIER too, and regenerate this scope's shape if the method's
* value is in fact changing.
*/
bool hasMethodBarrier() { return flags & METHOD_BARRIER; }
void setMethodBarrier() { flags |= METHOD_BARRIER; }
+ /*
+ * Test whether this scope may be branded due to method calls, which means
+ * any assignment to a function-valued property must regenerate shape; else
+ * test whether this scope has method properties, which require a method
+ * write barrier.
+ */
+ bool
+ brandedOrHasMethodBarrier() { return flags & (BRANDED | METHOD_BARRIER); }
+
bool owned() { return object != NULL; }
};
struct JSEmptyScope : public JSScope
{
JSClass * const clasp;
explicit JSEmptyScope(const JSObjectOps *ops, JSClass *clasp)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -11177,17 +11177,17 @@ TraceRecorder::setProp(jsval &l, JSPropC
JS_ASSERT_IF(obj2 != obj, sprop->attrs & JSPROP_SHARED);
/*
* Setting a function-valued property might need to rebrand the object, so
* we emit a call to the method write barrier. There's no need to guard on
* this, because functions have distinct trace-type from other values and
* branded-ness is implied by the shape, which we've already guarded on.
*/
- if (scope->branded() && VALUE_IS_FUNCTION(cx, v) && entry->directHit()) {
+ if (scope->brandedOrHasMethodBarrier() && VALUE_IS_FUNCTION(cx, v) && entry->directHit()) {
if (obj == globalObj)
RETURN_STOP("can't trace function-valued property set in branded global scope");
enterDeepBailCall();
LIns* args[] = { v_ins, INS_CONSTSPROP(sprop), obj_ins, cx_ins };
LIns* ok_ins = lir->insCall(&MethodWriteBarrier_ci, args);
guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
leaveDeepBailCall();