author | Nicholas Nethercote <nnethercote@mozilla.com> |
Wed, 12 May 2010 19:34:01 -0700 | |
changeset 42694 | 48082710c12f379ca6f9c077c7824dec333589e7 |
parent 42693 | 744611b4f3d98eea5b51e87c90b2036b5a0ab09e |
child 42695 | dbeffed4edb0941665fdb3a30e0f9f1908fda3b3 |
push id | 13436 |
push user | rsayre@mozilla.com |
push date | Mon, 24 May 2010 23:31:12 +0000 |
treeherder | mozilla-central@23b20b0eb9f3 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | brendan |
bugs | 564581 |
milestone | 1.9.3a5pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
|
js/src/jsbuiltins.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsbuiltins.h | file | annotate | diff | comparison | revisions | |
js/src/jsscope.h | file | annotate | diff | comparison | revisions | |
js/src/jsscopeinlines.h | file | annotate | diff | comparison | revisions | |
js/src/jstracer.cpp | file | annotate | diff | comparison | revisions | |
js/src/jstracer.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -189,18 +189,19 @@ JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_ int32 FASTCALL js_StringToInt32(JSContext* cx, JSString* str) { return StringToNumberType<int32>(cx, str); } JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, ACC_NONE) -JSBool FASTCALL -js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) +/* Nb: it's always safe to set isDefinitelyAtom to false if you're unsure or don't know. */ +static inline JSBool +AddPropertyHelper(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, bool isDefinitelyAtom) { JS_LOCK_OBJ(cx, obj); uint32 slot = sprop->slot; JSScope* scope = obj->scope(); if (slot != scope->freeslot) goto exit_trace; JS_ASSERT(sprop->parent == scope->lastProperty()); @@ -222,17 +223,17 @@ js_AddProperty(JSContext* cx, JSObject* goto exit_trace; if (slot != sprop->slot) { js_FreeSlot(cx, obj, slot); goto exit_trace; } } - scope->extend(cx, sprop); + scope->extend(cx, sprop, isDefinitelyAtom); } else { JSScopeProperty *sprop2 = scope->addProperty(cx, sprop->id, sprop->getter(), sprop->setter(), SPROP_INVALID_SLOT, sprop->attributes(), sprop->getFlags(), sprop->shortid); if (sprop2 != sprop) goto exit_trace; } @@ -242,18 +243,31 @@ js_AddProperty(JSContext* cx, JSObject* JS_UNLOCK_SCOPE(cx, scope); return JS_TRUE; exit_trace: JS_UNLOCK_SCOPE(cx, scope); return JS_FALSE; } + +JSBool FASTCALL +js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) +{ + return AddPropertyHelper(cx, obj, sprop, /* isDefinitelyAtom = */false); +} JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, ACC_STORE_ANY) +JSBool FASTCALL +js_AddAtomProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) +{ + return AddPropertyHelper(cx, obj, sprop, /* isDefinitelyAtom = */true); +} +JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddAtomProperty, CONTEXT, OBJECT, SCOPEPROP, 0, ACC_STORE_ANY) + static JSBool HasProperty(JSContext* cx, JSObject* obj, jsid id) { // Check that we know how the lookup op will behave. for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) { if (pobj->map->ops->lookupProperty != js_LookupProperty) return JSVAL_TO_SPECIAL(JSVAL_VOID); JSClass* clasp = pobj->getClass();
--- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -529,16 +529,17 @@ JS_DECLARE_CALLINFO(js_UnboxInt32) JS_DECLARE_CALLINFO(js_TryUnboxInt32) JS_DECLARE_CALLINFO(js_dmod) JS_DECLARE_CALLINFO(js_imod) JS_DECLARE_CALLINFO(js_DoubleToInt32) JS_DECLARE_CALLINFO(js_DoubleToUint32) JS_DECLARE_CALLINFO(js_StringToNumber) JS_DECLARE_CALLINFO(js_StringToInt32) JS_DECLARE_CALLINFO(js_AddProperty) +JS_DECLARE_CALLINFO(js_AddAtomProperty) JS_DECLARE_CALLINFO(js_HasNamedProperty) JS_DECLARE_CALLINFO(js_HasNamedPropertyInt32) JS_DECLARE_CALLINFO(js_TypeOfObject) JS_DECLARE_CALLINFO(js_TypeOfBoolean) JS_DECLARE_CALLINFO(js_BooleanIntToString) JS_DECLARE_CALLINFO(js_NewNullClosure) JS_DECLARE_CALLINFO(js_PopInterpFrame) JS_DECLARE_CALLINFO(js_ConcatN)
--- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -264,17 +264,17 @@ struct JSScope : public JSObjectMap /* These four inline methods are defined further below in this .h file. */ inline void setLastProperty(JSScopeProperty *sprop); inline void removeLastProperty(); inline void removeDictionaryProperty(JSScopeProperty *sprop); inline void insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **childp); /* Defined in jsscopeinlines.h to avoid including implementation dependencies here. */ inline void updateShape(JSContext *cx); - inline void updateFlags(const JSScopeProperty *sprop); + inline void updateFlags(const JSScopeProperty *sprop, bool isDefinitelyAtom = false); protected: void initMinimal(JSContext *cx, uint32 newShape); private: bool createTable(JSContext *cx, bool report); bool changeTable(JSContext *cx, int change); void reportReadOnlyScope(JSContext *cx); @@ -346,17 +346,17 @@ struct JSScope : public JSObjectMap /* Remove id from this scope. */ bool removeProperty(JSContext *cx, jsid id); /* Clear the scope, making it empty. */ void clear(JSContext *cx); /* Extend this scope to have sprop as its last-added property. */ - void extend(JSContext *cx, JSScopeProperty *sprop); + void extend(JSContext *cx, JSScopeProperty *sprop, bool isDefinitelyAtom = false); /* * Read barrier to clone a joined function object stored as a method. * Defined in jsscopeinlines.h, but not declared inline per standard style * in order to avoid gcc warnings. */ bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp);
--- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -85,33 +85,33 @@ inline void JSScope::updateShape(JSContext *cx) { JS_ASSERT(object); js::LeaveTraceIfGlobalObject(cx, object); shape = (hasOwnShape() || !lastProp) ? js_GenerateShape(cx, false) : lastProp->shape; } inline void -JSScope::updateFlags(const JSScopeProperty *sprop) +JSScope::updateFlags(const JSScopeProperty *sprop, bool isDefinitelyAtom) { jsuint index; - if (js_IdIsIndex(sprop->id, &index)) + if (!isDefinitelyAtom && js_IdIsIndex(sprop->id, &index)) setIndexedProperties(); if (sprop->isMethod()) setMethodBarrier(); } inline void -JSScope::extend(JSContext *cx, JSScopeProperty *sprop) +JSScope::extend(JSContext *cx, JSScopeProperty *sprop, bool isDefinitelyAtom) { ++entryCount; setLastProperty(sprop); updateShape(cx); - updateFlags(sprop); + updateFlags(sprop, isDefinitelyAtom); } /* * Property read barrier for deferred cloning of compiler-created function * objects optimized as typically non-escaping, ad-hoc methods in obj. */ inline bool JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp)
--- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -11263,17 +11263,17 @@ MethodWriteBarrier(JSContext* cx, JSObje return obj->scope()->methodWriteBarrier(cx, sprop, tvr.value()); } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, MethodWriteBarrier, CONTEXT, OBJECT, SCOPEPROP, OBJECT, 0, ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::setProp(jsval &l, PropertyCacheEntry* entry, JSScopeProperty* sprop, - jsval &v, LIns*& v_ins) + jsval &v, LIns*& v_ins, bool isDefinitelyAtom) { if (entry == JS_NO_PROP_CACHE_FILL) RETURN_STOP("can't trace uncacheable property set"); JS_ASSERT_IF(entry->vcapTag() >= 1, !sprop->hasSlot()); if (!sprop->hasDefaultSetter() && sprop->slot != SPROP_INVALID_SLOT) RETURN_STOP("can't trace set of property with setter and slot"); if (sprop->hasSetterValue()) RETURN_STOP("can't trace JavaScript function setter"); @@ -11330,17 +11330,18 @@ TraceRecorder::setProp(jsval &l, Propert // Add a property to the object if necessary. if (entry->adding()) { JS_ASSERT(sprop->hasSlot()); if (obj == globalObj) RETURN_STOP("adding a property to the global object"); LIns* args[] = { INS_CONSTSPROP(sprop), obj_ins, cx_ins }; - LIns* ok_ins = lir->insCall(&js_AddProperty_ci, args); + const CallInfo *ci = isDefinitelyAtom ? &js_AddAtomProperty_ci : &js_AddProperty_ci; + LIns* ok_ins = lir->insCall(ci, args); guard(false, lir->insEqI_0(ok_ins), OOM_EXIT); } return nativeSet(obj, obj_ins, sprop, v, v_ins); } JS_REQUIRES_STACK RecordingStatus TraceRecorder::setUpwardTrackedVar(jsval* stackVp, jsval v, LIns* v_ins) @@ -11490,19 +11491,22 @@ TraceRecorder::setCallProp(JSObject *cal } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_SetPropHit(PropertyCacheEntry* entry, JSScopeProperty* sprop) { jsval& r = stackval(-1); jsval& l = stackval(-2); LIns* v_ins; - CHECK_STATUS_A(setProp(l, entry, sprop, r, v_ins)); jsbytecode* pc = cx->fp->regs->pc; + + bool isDefinitelyAtom = (*pc == JSOP_SETPROP); + CHECK_STATUS_A(setProp(l, entry, sprop, r, v_ins, isDefinitelyAtom)); + switch (*pc) { case JSOP_SETPROP: case JSOP_SETNAME: case JSOP_SETMETHOD: if (pc[JSOP_SETPROP_LENGTH] != JSOP_POP) set(&l, v_ins); break;
--- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1306,17 +1306,18 @@ class TraceRecorder nanojit::LIns* obj_ins, JSScopeProperty* sprop); JS_REQUIRES_STACK RecordingStatus nativeSet(JSObject* obj, nanojit::LIns* obj_ins, JSScopeProperty* sprop, jsval v, nanojit::LIns* v_ins); JS_REQUIRES_STACK RecordingStatus setProp(jsval &l, PropertyCacheEntry* entry, JSScopeProperty* sprop, - jsval &v, nanojit::LIns*& v_ins); + jsval &v, nanojit::LIns*& v_ins, + bool isDefinitelyAtom); JS_REQUIRES_STACK RecordingStatus setCallProp(JSObject *callobj, nanojit::LIns *callobj_ins, JSScopeProperty *sprop, nanojit::LIns *v_ins, jsval v); JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByName(nanojit::LIns* obj_ins, jsval* idvalp, jsval* rvalp, bool init); JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByIndex(nanojit::LIns* obj_ins, nanojit::LIns* index_ins,