diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 0be9e79c8ab..cf922e3cd10 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -11352,6 +11352,26 @@ TraceRecorder::setProp(jsval &l, PropertyCacheEntry* entry, JSScopeProperty* spr return nativeSet(obj, obj_ins, sprop, v, v_ins); } +JS_REQUIRES_STACK RecordingStatus +TraceRecorder::setUpwardTrackedVar(jsval* stackVp, jsval v, LIns* v_ins) +{ + TraceType stackT = determineSlotType(stackVp); + TraceType otherT = getCoercedType(v); + + bool promote = true; + + if (stackT != otherT) { + if (stackT == TT_DOUBLE && otherT == TT_INT32 && isPromoteInt(v_ins)) + promote = false; + else + RETURN_STOP("can't trace this upvar mutation"); + } + + set(stackVp, v_ins, promote); + + return RECORD_CONTINUE; +} + JS_REQUIRES_STACK RecordingStatus TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty *sprop, LIns *v_ins, jsval v) @@ -11363,14 +11383,14 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty JS_ASSERT(sprop->hasShortID()); uintN slot = uint16(sprop->shortid); jsval *vp2 = &fp->argv[slot]; - set(vp2, v_ins); + CHECK_STATUS(setUpwardTrackedVar(vp2, v, v_ins)); return RECORD_CONTINUE; } if (sprop->setterOp() == SetCallVar) { JS_ASSERT(sprop->hasShortID()); uintN slot = uint16(sprop->shortid); jsval *vp2 = &fp->slots[slot]; - set(vp2, v_ins); + CHECK_STATUS(setUpwardTrackedVar(vp2, v, v_ins)); return RECORD_CONTINUE; } RETURN_STOP("can't trace special CallClass setter"); diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 3b99aeaa30f..794e58c970f 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1351,6 +1351,9 @@ class TraceRecorder JS_REQUIRES_STACK TraceType determineSlotType(jsval* vp); + JS_REQUIRES_STACK RecordingStatus setUpwardTrackedVar(jsval* stackVp, jsval v, + nanojit::LIns* v_ins); + JS_REQUIRES_STACK AbortableRecordingStatus compile(); JS_REQUIRES_STACK AbortableRecordingStatus closeLoop(); JS_REQUIRES_STACK AbortableRecordingStatus closeLoop(VMSideExit* exit);