From af2fba71c3ac932a00327c95ab9a972ca7aac6a9 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 24 Feb 2010 14:05:36 -0800 Subject: [PATCH 01/52] Another followup, deferred nit-pick for 547314. --- js/src/jsapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 279076f30216..b3cffaa97329 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -502,7 +502,7 @@ JS_TypeOfValue(JSContext *cx, jsval v) obj = JSVAL_TO_OBJECT(v); if (obj) return obj->map->ops->typeOf(cx, obj); - return JSTYPE_OBJECT; + type = JSTYPE_OBJECT; } else if (JSVAL_IS_NUMBER(v)) { type = JSTYPE_NUMBER; } else if (JSVAL_IS_STRING(v)) { From 44558b8ac7a6e7573174a48107b184b06af05879 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 24 Feb 2010 15:29:53 -0800 Subject: [PATCH 02/52] Follow-up fix for js::HashTable::Entry trying to access a private operator=. Long story, apparently. Informal r=luke. No bug#. --- js/src/jshashtable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/jshashtable.h b/js/src/jshashtable.h index 75364c9fe5af..dc52d47b0912 100644 --- a/js/src/jshashtable.h +++ b/js/src/jshashtable.h @@ -78,9 +78,9 @@ class HashTable : AllocPolicy NonConstT t; bool isFree() const { return keyHash == 0; } - void setFree() { keyHash = 0; t = T(); } + void setFree() { keyHash = 0; assignT(t, T()); } bool isRemoved() const { return keyHash == 1; } - void setRemoved() { keyHash = 1; t = T(); } + void setRemoved() { keyHash = 1; assignT(t, T()); } bool isLive() const { return keyHash > 1; } void setLive(HashNumber hn) { JS_ASSERT(hn > 1); keyHash = hn; } From ef050b1e1ecdba17351e662e542a7b3e74e62681 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 24 Feb 2010 17:32:46 -0800 Subject: [PATCH 03/52] Bug 547911 - TM: Crash [@ js_CallIteratorNext] or "Assertion failure: !JSVAL_IS_PRIMITIVE(regs.sp[-2]), at ../jsops.cpp" or "Assertion failure: regs.sp == StackBase(fp), at ../jsops.cpp" with defineGetter, StopIteration. r=brendan. --- js/src/jsinterp.cpp | 9 +++++++-- js/src/jstracer.cpp | 7 +++++++ js/src/jstracer.h | 3 +++ js/src/trace-test/tests/basic/bug547911-1.js | 7 +++++++ js/src/trace-test/tests/basic/bug547911-2.js | 7 +++++++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 js/src/trace-test/tests/basic/bug547911-1.js create mode 100644 js/src/trace-test/tests/basic/bug547911-2.js diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 22ee8fcc0bb1..7c1e389b4698 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3110,9 +3110,14 @@ js_Interpret(JSContext *cx) error: if (fp->imacpc && cx->throwing) { // To keep things simple, we hard-code imacro exception handlers here. - if (*fp->imacpc == JSOP_NEXTITER && js_ValueIsStopIteration(cx->exception)) { + if (*fp->imacpc == JSOP_NEXTITER && + InCustomIterNextTryRegion(regs.pc) && + js_ValueIsStopIteration(cx->exception)) { + // If the other NEXTITER imacro, native_iter_next, throws + // StopIteration, do not catch it here. See bug 547911. + // pc may point to JSOP_DUP here due to bug 474854. - JS_ASSERT(*regs.pc == JSOP_CALL || *regs.pc == JSOP_DUP || *regs.pc == JSOP_TRUE); + JS_ASSERT(*regs.pc == JSOP_CALL || *regs.pc == JSOP_DUP); cx->throwing = JS_FALSE; cx->exception = JSVAL_VOID; regs.sp[-1] = JSVAL_HOLE; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 096222b843e6..3f1445b22dca 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -7701,6 +7701,13 @@ DeepBail(JSContext *cx) state->deepBailSp = state->sp; } +extern bool +InCustomIterNextTryRegion(jsbytecode *pc) +{ + return nextiter_imacros.custom_iter_next <= pc && + pc < nextiter_imacros.custom_iter_next + sizeof(nextiter_imacros.custom_iter_next); +} + JS_REQUIRES_STACK jsval& TraceRecorder::argval(unsigned n) const { diff --git a/js/src/jstracer.h b/js/src/jstracer.h index a4c7b7bdc481..e7389cc9ca85 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1518,6 +1518,9 @@ SetMaxCodeCacheBytes(JSContext* cx, uint32 bytes); extern bool NativeToValue(JSContext* cx, jsval& v, TraceType type, double* slot); +extern bool +InCustomIterNextTryRegion(jsbytecode *pc); + #ifdef MOZ_TRACEVIS extern JS_FRIEND_API(bool) diff --git a/js/src/trace-test/tests/basic/bug547911-1.js b/js/src/trace-test/tests/basic/bug547911-1.js new file mode 100644 index 000000000000..5fb27fc7e8fd --- /dev/null +++ b/js/src/trace-test/tests/basic/bug547911-1.js @@ -0,0 +1,7 @@ +a = b = c = d = 0; +__defineGetter__("e", function () { throw StopIteration; }) +try { + for each(f in this) {} +} catch (exc) { + assertEq(exc, StopIteration); +} diff --git a/js/src/trace-test/tests/basic/bug547911-2.js b/js/src/trace-test/tests/basic/bug547911-2.js new file mode 100644 index 000000000000..d29d3303d36b --- /dev/null +++ b/js/src/trace-test/tests/basic/bug547911-2.js @@ -0,0 +1,7 @@ +var obj = {a: 0, b: 0, c: 0, d: 0, get e() { throw StopIteration; }}; +try { + for each (x in obj) {} + FAIL; +} catch (exc) { + assertEq(exc, StopIteration); +} From 965ff567909ca443265f38ff77041bb13acd0c1c Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 24 Feb 2010 17:40:28 -0800 Subject: [PATCH 04/52] Bug 539170 - Encapsulate JSScopeProperty::{getter,setter} and move assertions to init-time. r=Waldo. --- js/src/jsapi.cpp | 8 ++--- js/src/jsbuiltins.cpp | 5 +-- js/src/jsdbgapi.cpp | 22 ++++++------- js/src/jsobj.cpp | 20 ++++++------ js/src/jsops.cpp | 4 +-- js/src/jsscope.cpp | 72 +++++++++++------------------------------ js/src/jsscope.h | 55 +++++++++++++++++++++---------- js/src/jsscopeinlines.h | 17 +++++----- js/src/jstracer.cpp | 36 ++++++++++----------- 9 files changed, 114 insertions(+), 125 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index b3cffaa97329..17f69069cb0e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3029,7 +3029,7 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, } else { sprop = (JSScopeProperty *)prop; ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom), - sprop->getter, sprop->setter, sprop->slot, + sprop->getter(), sprop->setter(), sprop->slot, sprop->attrs, sprop->getFlags() | JSScopeProperty::ALIAS, sprop->shortid) != NULL); @@ -3102,8 +3102,8 @@ GetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, uintN flags, if (OBJ_IS_NATIVE(obj2)) { JSScopeProperty *sprop = (JSScopeProperty *) prop; - desc->getter = sprop->getter; - desc->setter = sprop->setter; + desc->getter = sprop->getter(); + desc->setter = sprop->setter(); desc->value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2)) ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot) : JSVAL_VOID; @@ -3702,7 +3702,7 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias) } sprop = (JSScopeProperty *)prop; ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias), - sprop->getter, sprop->setter, sprop->slot, + sprop->getter(), sprop->setter(), sprop->slot, sprop->attrs, sprop->getFlags() | JSScopeProperty::ALIAS, sprop->shortid) != NULL); diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index e1a00ea7cbcc..5f2e325a4281 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -265,8 +265,9 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) scope->extend(cx, sprop); } else { JSScopeProperty *sprop2 = - scope->addProperty(cx, sprop->id, sprop->getter, sprop->setter, SPROP_INVALID_SLOT, - sprop->attrs, sprop->getFlags(), sprop->shortid); + scope->addProperty(cx, sprop->id, sprop->getter(), sprop->setter(), + SPROP_INVALID_SLOT, sprop->attrs, sprop->getFlags(), + sprop->shortid); if (sprop2 != sprop) goto exit_trace; } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index ff95a76b9b39..644127b34815 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -476,7 +476,7 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag) ((wprop->attrs ^ sprop->attrs) & JSPROP_SETTER) == 0 && IsWatchedProperty(cx, wprop)) { sprop = scope->changeProperty(cx, wprop, 0, wprop->attrs, - wprop->getter, wp->setter); + wprop->getter(), wp->setter); if (!sprop) ok = JS_FALSE; } @@ -772,12 +772,12 @@ static bool IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop) { if (sprop->attrs & JSPROP_SETTER) { - JSObject *funobj = js_CastAsObject(sprop->setter); + JSObject *funobj = sprop->setterObject(); JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); return FUN_NATIVE(fun) == js_watch_set_wrapper; } - return sprop->setter == js_watch_set; + return sprop->setterOp() == js_watch_set; } JSPropertyOp @@ -875,8 +875,8 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)) ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot) : JSVAL_VOID; - getter = sprop->getter; - setter = sprop->setter; + getter = sprop->getter(); + setter = sprop->setter(); attrs = sprop->attrs; flags = sprop->getFlags(); shortid = sprop->shortid; @@ -909,7 +909,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid); if (!wp) { DBG_UNLOCK(rt); - watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter); + watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter()); if (!watcher) { ok = JS_FALSE; goto out; @@ -923,13 +923,13 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, wp->handler = NULL; wp->closure = NULL; wp->object = obj; - JS_ASSERT(sprop->setter != js_watch_set || pobj != obj); - wp->setter = sprop->setter; + JS_ASSERT(sprop->setter() != js_watch_set || pobj != obj); + wp->setter = sprop->setter(); wp->flags = JSWP_LIVE; /* XXXbe nest in obj lock here */ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs, - sprop->getter, watcher); + sprop->getter(), watcher); if (!sprop) { /* Self-link so DropWatchPointAndUnlock can JS_REMOVE_LINK it. */ JS_INIT_CLIST(&wp->links); @@ -1487,10 +1487,10 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, | ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0) | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0); pd->spare = 0; - if (sprop->getter == js_GetCallArg) { + if (sprop->getter() == js_GetCallArg) { pd->slot = sprop->shortid; pd->flags |= JSPD_ARGUMENT; - } else if (sprop->getter == js_GetCallVar) { + } else if (sprop->getter() == js_GetCallVar) { pd->slot = sprop->shortid; pd->flags |= JSPD_VARIABLE; } else { diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 8d1c6d8260df..fa493a3cbefd 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2504,8 +2504,8 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des changed |= JSPROP_ENUMERATE; attrs = (sprop->attrs & ~changed) | (desc.attrs & changed); - getter = sprop->getter; - setter = sprop->setter; + getter = sprop->getter(); + setter = sprop->setter(); } else if (desc.isDataDescriptor()) { uintN unchanged = 0; if (!desc.hasConfigurable) @@ -2548,11 +2548,11 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des if (desc.hasGet) getter = desc.getterObject() ? desc.getter() : JS_PropertyStub; else - getter = sprop->getter; + getter = sprop->getter(); if (desc.hasSet) setter = desc.setterObject() ? desc.setter() : JS_PropertyStub; else - setter = sprop->setter; + setter = sprop->setter(); } *rval = true; @@ -3632,7 +3632,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp) sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProperty(); } while (!sprop->hasShortID()); - JS_ASSERT(sprop->getter == block_getProperty); + JS_ASSERT(sprop->getter() == block_getProperty); propid = sprop->id; JS_ASSERT(JSID_IS_ATOM(propid)); atom = JSID_TO_ATOM(propid); @@ -4474,10 +4474,10 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, JSPROP_GETTER | JSPROP_SETTER, (attrs & JSPROP_GETTER) ? getter - : sprop->getter, + : sprop->getter(), (attrs & JSPROP_SETTER) ? setter - : sprop->setter); + : sprop->setter()); /* NB: obj == pobj, so we can share unlock code at the bottom. */ if (!sprop) @@ -5357,8 +5357,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, if (sprop->hasShortID()) { flags = JSScopeProperty::HAS_SHORTID; shortid = sprop->shortid; - getter = sprop->getter; - setter = sprop->setter; + getter = sprop->getter(); + setter = sprop->setter(); } /* @@ -5506,7 +5506,7 @@ js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, } sprop = (JSScopeProperty *)prop; sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, *attrsp, 0, - sprop->getter, sprop->setter); + sprop->getter(), sprop->setter()); if (noprop) obj->dropProperty(cx, prop); return (sprop != NULL); diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index f7baf066fde4..d1136f00e24b 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -1809,7 +1809,7 @@ BEGIN_CASE(JSOP_SETMETHOD) if (slot != sprop->slot || scope->table) { JSScopeProperty *sprop2 = scope->putProperty(cx, sprop->id, - sprop->getter, sprop->setter, + sprop->getter(), sprop->setter(), slot, sprop->attrs, sprop->getFlags(), sprop->shortid); if (!sprop2) { @@ -3451,7 +3451,7 @@ BEGIN_CASE(JSOP_INITMETHOD) scope->shape == scope->lastProperty()->shape); if (scope->table) { JSScopeProperty *sprop2 = - scope->addProperty(cx, sprop->id, sprop->getter, sprop->setter, slot, + scope->addProperty(cx, sprop->id, sprop->getter(), sprop->setter(), slot, sprop->attrs, sprop->getFlags(), sprop->shortid); if (!sprop2) { js_FreeSlot(cx, obj, slot); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index d54c82932873..fac7a7f567ce 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -922,13 +922,8 @@ locked_not_found: if (!sprop) goto out_of_memory; - sprop->id = child.id; - sprop->getter = child.getter; - sprop->setter = child.setter; - sprop->slot = child.slot; - sprop->attrs = child.attrs; - sprop->flags = child.flags; - sprop->shortid = child.shortid; + new(sprop) JSScopeProperty(child.id, child.rawGetter, child.rawSetter, child.slot, + child.attrs, child.flags, child.shortid); sprop->parent = sprop->kids = NULL; sprop->shape = js_GenerateShape(cx, true); @@ -1103,13 +1098,9 @@ JSScope::newDictionaryProperty(JSContext *cx, const JSScopeProperty &child, return NULL; } - dprop->id = child.id; - dprop->getter = child.getter; - dprop->setter = child.setter; - dprop->slot = child.slot; - dprop->attrs = child.attrs; - dprop->flags = child.flags | JSScopeProperty::IN_DICTIONARY; - dprop->shortid = child.shortid; + new (dprop) JSScopeProperty(child.id, child.rawGetter, child.rawSetter, child.slot, + child.attrs, child.flags | JSScopeProperty::IN_DICTIONARY, + child.shortid); dprop->shape = js_GenerateShape(cx, false); dprop->childp = NULL; @@ -1289,15 +1280,7 @@ JSScope::addPropertyHelper(JSContext *cx, jsid id, /* Find or create a property tree node labeled by our arguments. */ JSScopeProperty *sprop; { - JSScopeProperty child; - - child.id = id; - child.getter = getter; - child.setter = setter; - child.slot = slot; - child.attrs = attrs; - child.flags = flags; - child.shortid = shortid; + JSScopeProperty child(id, getter, setter, slot, attrs, flags, shortid); sprop = getChildProperty(cx, lastProp, child); } @@ -1413,16 +1396,8 @@ JSScope::putProperty(JSContext *cx, jsid id, CHECK_ANCESTOR_LINE(this, true); { - JSScopeProperty child; - /* Find or create a property tree node labeled by our arguments. */ - child.id = id; - child.getter = getter; - child.setter = setter; - child.slot = slot; - child.attrs = attrs; - child.flags = flags; - child.shortid = shortid; + JSScopeProperty child(id, getter, setter, slot, attrs, flags, shortid); sprop = getChildProperty(cx, lastProp, child); } @@ -1454,7 +1429,7 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, uintN attrs, uintN mask, JSPropertyOp getter, JSPropertyOp setter) { - JSScopeProperty child, *newsprop; + JSScopeProperty *newsprop; JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); CHECK_ANCESTOR_LINE(this, true); @@ -1469,26 +1444,17 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, !(attrs & JSPROP_SHARED)); /* Don't allow method properties to be changed to have a getter. */ - JS_ASSERT_IF(getter != sprop->getter, !sprop->isMethod()); + JS_ASSERT_IF(getter != sprop->rawGetter, !sprop->isMethod()); if (getter == JS_PropertyStub) getter = NULL; if (setter == JS_PropertyStub) setter = NULL; - if (sprop->attrs == attrs && - sprop->getter == getter && - sprop->setter == setter) { + if (sprop->attrs == attrs && sprop->getter() == getter && sprop->setter() == setter) return sprop; - } - - child.id = sprop->id; - child.getter = getter; - child.setter = setter; - child.slot = sprop->slot; - child.attrs = attrs; - child.flags = sprop->flags; - child.shortid = sprop->shortid; + JSScopeProperty child(sprop->id, getter, setter, sprop->slot, attrs, sprop->flags, + sprop->shortid); if (inDictionaryMode()) { removeDictionaryProperty(sprop); newsprop = newDictionaryProperty(cx, child, &lastProp); @@ -1516,7 +1482,7 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, * JSScope::removeProperty because it will free a valid sprop->slot and * JSScope::putProperty won't re-allocate it. */ - newsprop = putProperty(cx, child.id, child.getter, child.setter, child.slot, + newsprop = putProperty(cx, child.id, child.rawGetter, child.rawSetter, child.slot, child.attrs, child.flags, child.shortid); } @@ -1667,7 +1633,7 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval) JS_ASSERT(sprop->methodValue() == prev); JS_ASSERT(hasMethodBarrier()); JS_ASSERT(object->getClass() == &js_ObjectClass); - JS_ASSERT(!sprop->setter || sprop->setter == js_watch_set); + JS_ASSERT(!sprop->rawSetter || sprop->rawSetter == js_watch_set); #endif /* @@ -1676,7 +1642,7 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval) * are despecializing from a method memoized in the property tree to a * plain old function-valued property. */ - sprop = putProperty(cx, sprop->id, NULL, sprop->setter, sprop->slot, + sprop = putProperty(cx, sprop->id, NULL, sprop->rawSetter, sprop->slot, sprop->attrs, sprop->getFlags() & ~JSScopeProperty::METHOD, sprop->shortid); @@ -1786,11 +1752,11 @@ JSScopeProperty::trace(JSTracer *trc) #if JS_HAS_GETTER_SETTER if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { - if ((attrs & JSPROP_GETTER) && getter) { + if ((attrs & JSPROP_GETTER) && rawGetter) { JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, this, 0); js_CallGCMarker(trc, getterObject(), JSTRACE_OBJECT); } - if ((attrs & JSPROP_SETTER) && setter) { + if ((attrs & JSPROP_SETTER) && rawSetter) { JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, this, 1); js_CallGCMarker(trc, setterObject(), JSTRACE_OBJECT); } @@ -1876,8 +1842,8 @@ JSScopeProperty::dump(JSContext *cx, FILE *fp) } fprintf(fp, " g/s %p/%p slot %u attrs %x ", - JS_FUNC_TO_DATA_PTR(void *, getter), - JS_FUNC_TO_DATA_PTR(void *, setter), + JS_FUNC_TO_DATA_PTR(void *, rawGetter), + JS_FUNC_TO_DATA_PTR(void *, rawSetter), slot, attrs); if (attrs) { int first = 1; diff --git a/js/src/jsscope.h b/js/src/jsscope.h index d6377949a46b..3e39a95a8d48 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -559,9 +559,11 @@ struct JSScopeProperty { const JSScopeProperty &child); jsid id; /* int-tagged jsval/untagged JSAtom* */ - JSPropertyOp getter; /* getter and setter hooks or objects */ - JSPropertyOp setter; /* getter is JSObject* and setter is 0 +private: + JSPropertyOp rawGetter; /* getter and setter hooks or objects */ + JSPropertyOp rawSetter; /* getter is JSObject* and setter is 0 if sprop->isMethod() */ +public: uint32 slot; /* abstract index in object slots */ uint8 attrs; /* attributes, see jsapi.h JSPROP_* */ private: @@ -596,6 +598,17 @@ private: IN_DICTIONARY = 0x20 }; + JSScopeProperty(jsid id, JSPropertyOp getter, JSPropertyOp setter, uint32 slot, + uintN attrs, uintN flags, intN shortid) + : id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(attrs), + flags(flags), shortid(shortid) + { + JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER), + JSVAL_TO_OBJECT(getterValue())->isCallable()); + JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER), + JSVAL_TO_OBJECT(setterValue())->isCallable()); + } + bool marked() const { return (flags & MARK) != 0; } void mark() { flags |= MARK; } void clearMark() { flags &= ~MARK; } @@ -622,33 +635,41 @@ public: JSObject *methodObject() const { JS_ASSERT(isMethod()); - return js_CastAsObject(getter); + return js_CastAsObject(rawGetter); } jsval methodValue() const { JS_ASSERT(isMethod()); - return js_CastAsObjectJSVal(getter); + return js_CastAsObjectJSVal(rawGetter); } + JSPropertyOp getter() const { return rawGetter; } + bool hasDefaultGetter() const { return !rawGetter; } + JSPropertyOp getterOp() const { + JS_ASSERT(!(attrs & JSPROP_GETTER)); + return rawGetter; + } JSObject *getterObject() const { JS_ASSERT(attrs & JSPROP_GETTER); - return js_CastAsObject(getter); + return js_CastAsObject(rawGetter); } jsval getterValue() const { JS_ASSERT(attrs & JSPROP_GETTER); - jsval getterVal = getter ? js_CastAsObjectJSVal(getter) : JSVAL_VOID; - JS_ASSERT_IF(getter, JSVAL_TO_OBJECT(getterVal)->isCallable()); - return getterVal; + return rawGetter ? js_CastAsObjectJSVal(rawGetter) : JSVAL_VOID; } + JSPropertyOp setter() const { return rawSetter; } + bool hasDefaultSetter() const { return !rawSetter; } + JSPropertyOp setterOp() const { + JS_ASSERT(!(attrs & JSPROP_SETTER)); + return rawSetter; + } JSObject *setterObject() const { - JS_ASSERT((attrs & JSPROP_SETTER) && setter); - return js_CastAsObject(setter); + JS_ASSERT((attrs & JSPROP_SETTER) && rawSetter); + return js_CastAsObject(rawSetter); } jsval setterValue() const { JS_ASSERT(attrs & JSPROP_SETTER); - jsval setterVal = setter ? js_CastAsObjectJSVal(setter) : JSVAL_VOID; - JS_ASSERT_IF(setter, JSVAL_TO_OBJECT(setterVal)->isCallable()); - return setterVal; + return rawSetter ? js_CastAsObjectJSVal(rawSetter) : JSVAL_VOID; } inline JSDHashNumber hash() const; @@ -795,8 +816,8 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil #define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot) #define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope) -#define SPROP_HAS_STUB_GETTER(sprop) (!(sprop)->getter) -#define SPROP_HAS_STUB_SETTER(sprop) (!(sprop)->setter) +#define SPROP_HAS_STUB_GETTER(sprop) ((sprop)->hasDefaultGetter()) +#define SPROP_HAS_STUB_SETTER(sprop) ((sprop)->hasDefaultSetter()) #define SPROP_HAS_STUB_GETTER_OR_IS_METHOD(sprop) \ (SPROP_HAS_STUB_GETTER(sprop) || (sprop)->isMethod()) @@ -898,7 +919,7 @@ JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp) */ if (STOBJ_GET_CLASS(obj) == &js_WithClass) obj = obj->map->ops->thisObject(cx, obj); - return getter(cx, obj, SPROP_USERID(this), vp); + return getterOp()(cx, obj, SPROP_USERID(this), vp); } inline bool @@ -917,7 +938,7 @@ JSScopeProperty::set(JSContext* cx, JSObject* obj, jsval* vp) /* See the comment in JSScopeProperty::get as to why we can check for With. */ if (STOBJ_GET_CLASS(obj) == &js_WithClass) obj = obj->map->ops->thisObject(cx, obj); - return setter(cx, obj, SPROP_USERID(this), vp); + return setterOp()(cx, obj, SPROP_USERID(this), vp); } /* Macro for common expression to test for shared permanent attributes. */ diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index e11bf8910b5b..43065e2400d9 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -208,11 +208,11 @@ JSScopeProperty::hash() const JSDHashNumber hash = 0; /* Accumulate from least to most random so the low bits are most random. */ - JS_ASSERT_IF(isMethod(), !setter || setter == js_watch_set); - if (getter) - hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(getter); - if (setter) - hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(setter); + JS_ASSERT_IF(isMethod(), !rawSetter || rawSetter == js_watch_set); + if (rawGetter) + hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawGetter); + if (rawSetter) + hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawSetter); hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & PUBLIC_FLAGS); hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs; hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid; @@ -227,7 +227,8 @@ JSScopeProperty::matches(const JSScopeProperty *p) const JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT(!JSVAL_IS_NULL(p->id)); return id == p->id && - matchesParamsAfterId(p->getter, p->setter, p->slot, p->attrs, p->flags, p->shortid); + matchesParamsAfterId(p->rawGetter, p->rawSetter, p->slot, p->attrs, p->flags, + p->shortid); } inline bool @@ -235,8 +236,8 @@ JSScopeProperty::matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter uintN aattrs, uintN aflags, intN ashortid) const { JS_ASSERT(!JSVAL_IS_NULL(id)); - return getter == agetter && - setter == asetter && + return rawGetter == agetter && + rawSetter == asetter && slot == aslot && attrs == aattrs && ((flags ^ aflags) & PUBLIC_FLAGS) == 0 && diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 3f1445b22dca..b76ad4cc03ce 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -7880,13 +7880,13 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, uintN upvar_slot = SPROP_INVALID_SLOT; JSStackFrame* cfp = (JSStackFrame*) obj->getPrivate(); if (cfp) { - if (sprop->getter == js_GetCallArg) { + if (sprop->getterOp() == js_GetCallArg) { JS_ASSERT(slot < cfp->fun->nargs); vp = &cfp->argv[slot]; upvar_slot = slot; nr.v = *vp; - } else if (sprop->getter == js_GetCallVar || - sprop->getter == js_GetCallVarChecked) { + } else if (sprop->getterOp() == js_GetCallVar || + sprop->getterOp() == js_GetCallVarChecked) { JS_ASSERT(slot < cfp->script->nslots); vp = &cfp->slots[slot]; upvar_slot = cx->fp->fun->nargs + slot; @@ -7933,11 +7933,11 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, // have a null private in the Call object. So all we need to do is // write the value to the Call object's slot. int32 dslot_index = slot; - if (sprop->getter == js_GetCallArg) { + if (sprop->getterOp() == js_GetCallArg) { JS_ASSERT(dslot_index < ArgClosureTraits::slot_count(obj)); dslot_index += ArgClosureTraits::slot_offset(obj); - } else if (sprop->getter == js_GetCallVar || - sprop->getter == js_GetCallVarChecked) { + } else if (sprop->getterOp() == js_GetCallVar || + sprop->getterOp() == js_GetCallVarChecked) { JS_ASSERT(dslot_index < VarClosureTraits::slot_count(obj)); dslot_index += VarClosureTraits::slot_offset(obj); } else { @@ -7965,10 +7965,10 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, cx_ins }; const CallInfo* ci; - if (sprop->getter == js_GetCallArg) { + if (sprop->getterOp() == js_GetCallArg) { ci = &GetClosureArg_ci; - } else if (sprop->getter == js_GetCallVar || - sprop->getter == js_GetCallVarChecked) { + } else if (sprop->getterOp() == js_GetCallVar || + sprop->getterOp() == js_GetCallVarChecked) { ci = &GetClosureVar_ci; } else { RETURN_STOP("dynamic property of Call object"); @@ -10514,7 +10514,7 @@ TraceRecorder::emitNativePropertyOp(JSScope* scope, JSScopeProperty* sprop, LIns lir->insStorei(boxed_ins, vp_ins, 0); CallInfo* ci = new (traceAlloc()) CallInfo(); - ci->_address = uintptr_t(setflag ? sprop->setter : sprop->getter); + ci->_address = uintptr_t(setflag ? sprop->setterOp() : sprop->getterOp()); ci->_argtypes = ARGSIZE_I << (0*ARGSIZE_SHIFT) | ARGSIZE_P << (1*ARGSIZE_SHIFT) | ARGSIZE_P << (2*ARGSIZE_SHIFT) | @@ -11321,14 +11321,14 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty // Set variables in on-trace-stack call objects by updating the tracker. JSStackFrame *fp = frameIfInRange(callobj); if (fp) { - if (sprop->setter == SetCallArg) { + if (sprop->setterOp() == SetCallArg) { JS_ASSERT(sprop->hasShortID()); uintN slot = uint16(sprop->shortid); jsval *vp2 = &fp->argv[slot]; set(vp2, v_ins); return RECORD_CONTINUE; } - if (sprop->setter == SetCallVar) { + if (sprop->setterOp() == SetCallVar) { JS_ASSERT(sprop->hasShortID()); uintN slot = uint16(sprop->shortid); jsval *vp2 = &fp->slots[slot]; @@ -11345,10 +11345,10 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty // have a null private in the Call object. So all we need to do is // write the value to the Call object's slot. int32 dslot_index = uint16(sprop->shortid); - if (sprop->setter == SetCallArg) { + if (sprop->setterOp() == SetCallArg) { JS_ASSERT(dslot_index < ArgClosureTraits::slot_count(callobj)); dslot_index += ArgClosureTraits::slot_offset(callobj); - } else if (sprop->setter == SetCallVar) { + } else if (sprop->setterOp() == SetCallVar) { JS_ASSERT(dslot_index < VarClosureTraits::slot_count(callobj)); dslot_index += VarClosureTraits::slot_offset(callobj); } else { @@ -11371,9 +11371,9 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty // Set variables in off-trace-stack call objects by calling standard builtins. const CallInfo* ci = NULL; - if (sprop->setter == SetCallArg) + if (sprop->setterOp() == SetCallArg) ci = &js_SetCallArg_ci; - else if (sprop->setter == SetCallVar) + else if (sprop->setterOp() == SetCallVar) ci = &js_SetCallVar_ci; else RETURN_STOP("can't trace special CallClass setter"); @@ -11392,7 +11392,7 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty // Compute native stack slot and address offset we are storing to. unsigned slot = uint16(sprop->shortid); LIns *slot_ins; - if (sprop->setter == SetCallArg) + if (sprop->setterOp() == SetCallArg) slot_ins = ArgClosureTraits::adj_slot_lir(lir, fp_ins, slot); else slot_ins = VarClosureTraits::adj_slot_lir(lir, fp_ins, slot); @@ -11675,7 +11675,7 @@ GetPropertyWithNativeGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop JS_ASSERT(obj->getClass() != &js_WithClass); *vp = JSVAL_VOID; - if (!sprop->getter(cx, obj, SPROP_USERID(sprop), vp)) { + if (!sprop->getterOp()(cx, obj, SPROP_USERID(sprop), vp)) { SetBuiltinError(cx); return JS_FALSE; } From e0ab73aca720b87bf1eaaed154b85aa58601d213 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 25 Feb 2010 07:10:40 -0800 Subject: [PATCH 05/52] Fix ppc breakage due to 337699f6a88a. No bug, r=burning nightly. --- js/src/jsinterp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 7c1e389b4698..b87c735243b9 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3108,6 +3108,7 @@ js_Interpret(JSContext *cx) #endif /* !JS_THREADED_INTERP */ error: +#ifdef JS_TRACER if (fp->imacpc && cx->throwing) { // To keep things simple, we hard-code imacro exception handlers here. if (*fp->imacpc == JSOP_NEXTITER && @@ -3130,6 +3131,7 @@ js_Interpret(JSContext *cx) fp->imacpc = NULL; atoms = script->atomMap.vector; } +#endif JS_ASSERT((size_t)((fp->imacpc ? fp->imacpc : regs.pc) - script->code) < script->length); From 433c352207cd61d51ab74eb3a5ea9e048503f9ae Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 26 Feb 2010 12:11:50 -0800 Subject: [PATCH 06/52] bug 515812 - less vebose enumerastion. r=lw --- js/src/jshashtable.h | 35 +++++++++++++---------------------- js/src/jstracer.cpp | 4 ++-- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/js/src/jshashtable.h b/js/src/jshashtable.h index dc52d47b0912..8771af4b78af 100644 --- a/js/src/jshashtable.h +++ b/js/src/jshashtable.h @@ -179,22 +179,15 @@ class HashTable : AllocPolicy void operator=(const Enum &); public: - /* Type returned from hash table used to initialize Enum object. */ - struct Init { - Init(Range r, HashTable &t) : range(r), table(t) {} - Range range; - HashTable &table; - }; - - /* Initialize with the return value of enumerate. */ - Enum(Init i) : Range(i.range), table(i.table), removed(false) {} + template + Enum(Map &map) : Range(map.all()), table(map.impl), removed(false) {} /* * Removes the |front()| element from the table, leaving |front()| * invalid until the next call to |popFront()|. For example: * * HashSet s; - * for (HashSet::Enum e(s.enumerate()); !e.empty(); e.popFront()) + * for (HashSet::Enum e(s); !e.empty(); e.popFront()) * if (e.front() == 42) * e.removeFront(); */ @@ -529,10 +522,6 @@ class HashTable : AllocPolicy return Range(table, table + tableCapacity); } - typename Enum::Init enumerate() { - return typename Enum::Init(all(), *this); - } - bool empty() const { return !entryCount; } @@ -715,6 +704,8 @@ class HashMap }; typedef detail::HashTable Impl; + friend class Impl::Enum; + /* Not implicitly copyable (expensive). May add explicit |clone| later. */ HashMap(const HashMap &); HashMap &operator=(const HashMap &); @@ -785,12 +776,12 @@ class HashMap size_t count() const { return impl.count(); } /* - * Returns a value that may be used to initialize an Enum. An Enum may be - * used to examine and remove table entries: + * Typedef for the enumeration class. An Enum may be used to examine and + * remove table entries: * * typedef HashMap HM; * HM s; - * for (HM::Enum e(s.enumerate()); !e.empty(); e.popFront()) + * for (HM::Enum e(s); !e.empty(); e.popFront()) * if (e.front().value == 'l') * e.removeFront(); * @@ -798,7 +789,6 @@ class HashMap * Enum in HashTable above (with T = Entry). */ typedef typename Impl::Enum Enum; - typename Enum::Init enumerate() { return impl.enumerate(); } /* Remove all entries. */ void clear() { impl.clear(); } @@ -861,6 +851,8 @@ class HashSet }; typedef detail::HashTable Impl; + friend class Impl::Enum; + /* Not implicitly copyable (expensive). May add explicit |clone| later. */ HashSet(const HashSet &); HashSet &operator=(const HashSet &); @@ -927,12 +919,12 @@ class HashSet size_t count() const { return impl.count(); } /* - * Returns a value that may be used to initialize an Enum. An Enum may be - * used to examine and remove table entries. + * Typedef for the enumeration class. An Enum may be used to examine and + * remove table entries: * * typedef HashSet HS; * HS s; - * for (HS::Enum e(s.enumerate()); !e.empty(); e.popFront()) + * for (HS::Enum e(s); !e.empty(); e.popFront()) * if (e.front() == 42) * e.removeFront(); * @@ -940,7 +932,6 @@ class HashSet * Enum in HashTable above. */ typedef typename Impl::Enum Enum; - typename Enum::Init enumerate() { return impl.enumerate(); } /* Remove all entries. */ void clear() { impl.clear(); } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index b76ad4cc03ce..18758e286594 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -7615,7 +7615,7 @@ PurgeScriptFragments(JSContext* cx, JSScript* script) } RecordAttemptMap &table = *tm->recordAttempts; - for (RecordAttemptMap::Enum e(table.enumerate()); !e.empty(); e.popFront()) { + for (RecordAttemptMap::Enum e(table); !e.empty(); e.popFront()) { if (JS_UPTRDIFF(e.front().key, script->code) < script->length) e.removeFront(); } @@ -9038,7 +9038,7 @@ TraceRecorder::guardShape(LIns* obj_ins, JSObject* obj, uint32 shape, const char void TraceRecorder::forgetGuardedShapesForObject(JSObject* obj) { - for (GuardedShapeTable::Enum e(guardedShapeTable.enumerate()); !e.empty(); e.popFront()) { + for (GuardedShapeTable::Enum e(guardedShapeTable); !e.empty(); e.popFront()) { if (e.front().value == obj) { #if defined DEBUG_notme && defined XP_UNIX DumpShape(entry->obj, "forget"); From 918549ebb08356a236162597ac6d4e0ca3ec62dc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 09:46:17 +1100 Subject: [PATCH 07/52] Bug 535706 - nanojit: fix regstate updates for X64. r=edwsmith. --HG-- extra : convert_revision : 6fb5f71fba861a333e17de644fe49de60bb7a1bd --- js/src/nanojit/Assembler.cpp | 6 +- js/src/nanojit/Assembler.h | 2 +- js/src/nanojit/NativeARM.cpp | 6 +- js/src/nanojit/NativeMIPS.cpp | 2 +- js/src/nanojit/NativePPC.cpp | 2 +- js/src/nanojit/NativeSparc.cpp | 2 +- js/src/nanojit/NativeX64.cpp | 414 ++++++++++++++++++++------------- js/src/nanojit/NativeX64.h | 13 +- js/src/nanojit/Nativei386.cpp | 28 +-- js/src/vprof/vprof.h | 4 +- 10 files changed, 284 insertions(+), 195 deletions(-) diff --git a/js/src/nanojit/Assembler.cpp b/js/src/nanojit/Assembler.cpp index 924937bd78db..a909caf3dbad 100755 --- a/js/src/nanojit/Assembler.cpp +++ b/js/src/nanojit/Assembler.cpp @@ -2088,7 +2088,7 @@ namespace nanojit /** * move regs around so the SavedRegs contains the highest priority regs. */ - void Assembler::evictScratchRegs() + void Assembler::evictScratchRegsExcept(RegisterMask ignore) { // find the top GpRegs that are candidates to put in SavedRegs @@ -2099,7 +2099,7 @@ namespace nanojit int len=0; RegAlloc *regs = &_allocator; for (Register r = FirstReg; r <= LastReg; r = nextreg(r)) { - if (rmask(r) & GpRegs) { + if (rmask(r) & GpRegs & ~ignore) { LIns *ins = regs->getActive(r); if (ins) { if (canRemat(ins)) { @@ -2156,7 +2156,7 @@ namespace nanojit } // now evict everything else. - evictSomeActiveRegs(~SavedRegs); + evictSomeActiveRegs(~(SavedRegs | ignore)); } void Assembler::evictAllActiveRegs() diff --git a/js/src/nanojit/Assembler.h b/js/src/nanojit/Assembler.h index 9955feedaba1..e1d226b6a3c5 100644 --- a/js/src/nanojit/Assembler.h +++ b/js/src/nanojit/Assembler.h @@ -337,7 +337,7 @@ namespace nanojit void registerResetAll(); void evictAllActiveRegs(); void evictSomeActiveRegs(RegisterMask regs); - void evictScratchRegs(); + void evictScratchRegsExcept(RegisterMask ignore); void intersectRegisterState(RegAlloc& saved); void unionRegisterState(RegAlloc& saved); void assignSaved(RegAlloc &saved, RegisterMask skip); diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index 359e95724424..d33c70825ac4 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -826,14 +826,14 @@ Assembler::asm_call(LInsp ins) * sequence we'd get would be something like: * MOV {R0-R3},params [from below] * BL function [from below] - * MOV {R0-R3},spilled data [from evictScratchRegs()] + * MOV {R0-R3},spilled data [from evictScratchRegsExcept()] * MOV Dx,{R0,R1} [from here] * which is clearly broken. * * This is not a problem for non-floating point calls, because the * restoring of spilled data into R0 is done via a call to * deprecated_prepResultReg(R0) in the other branch of this if-then-else, - * meaning that evictScratchRegs() will not modify R0. However, + * meaning that evictScratchRegsExcept() will not modify R0. However, * deprecated_prepResultReg is not aware of the concept of using a register pair * (R0,R1) for the result of a single operation, so it can only be * used here with the ultimate VFP register, and not R0/R1, which @@ -846,7 +846,7 @@ Assembler::asm_call(LInsp ins) // Do this after we've handled the call result, so we don't // force the call result to be spilled unnecessarily. - evictScratchRegs(); + evictScratchRegsExcept(0); const CallInfo* call = ins->callInfo(); ArgSize sizes[MAXARGS]; diff --git a/js/src/nanojit/NativeMIPS.cpp b/js/src/nanojit/NativeMIPS.cpp index 6f651a54e0a4..c7830bf569ea 100644 --- a/js/src/nanojit/NativeMIPS.cpp +++ b/js/src/nanojit/NativeMIPS.cpp @@ -1568,7 +1568,7 @@ namespace nanojit // Do this after we've handled the call result, so we don't // force the call result to be spilled unnecessarily. - evictScratchRegs(); + evictScratchRegsExcept(0); const CallInfo* call = ins->callInfo(); ArgSize sizes[MAXARGS]; diff --git a/js/src/nanojit/NativePPC.cpp b/js/src/nanojit/NativePPC.cpp index ece70e81f5cc..7b84bb7380c8 100644 --- a/js/src/nanojit/NativePPC.cpp +++ b/js/src/nanojit/NativePPC.cpp @@ -688,7 +688,7 @@ namespace nanojit // Do this after we've handled the call result, so we don't // force the call result to be spilled unnecessarily. - evictScratchRegs(); + evictScratchRegsExcept(0); const CallInfo* call = ins->callInfo(); ArgSize sizes[MAXARGS]; diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 99f2d1f72add..50811e400936 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -159,7 +159,7 @@ namespace nanojit // Do this after we've handled the call result, so we don't // force the call result to be spilled unnecessarily. - evictScratchRegs(); + evictScratchRegsExcept(0); const CallInfo* call = ins->callInfo(); diff --git a/js/src/nanojit/NativeX64.cpp b/js/src/nanojit/NativeX64.cpp index afda3938f2bd..883b15813efc 100644 --- a/js/src/nanojit/NativeX64.cpp +++ b/js/src/nanojit/NativeX64.cpp @@ -620,63 +620,35 @@ namespace nanojit } } - // register allocation for 2-address style ops of the form R = R (op) B - void Assembler::regalloc_binary(LIns *ins, RegisterMask allow, Register &rr, Register &ra, Register &rb) { -#ifdef _DEBUG - RegisterMask originalAllow = allow; -#endif - LIns *a = ins->oprnd1(); - LIns *b = ins->oprnd2(); - if (a != b) { - rb = findRegFor(b, allow); - allow &= ~rmask(rb); - } - rr = deprecated_prepResultReg(ins, allow); - // if this is last use of a in reg, we can re-use result reg - if (!a->isInReg()) { - ra = findSpecificRegForUnallocated(a, rr); - } else if (!(allow & rmask(a->getReg()))) { - // 'a' already has a register assigned, but it's not valid. - // To make sure floating point operations stay in FPU registers - // as much as possible, make sure that only a few opcodes are - // reserving GPRs. - NanoAssert(a->isop(LIR_quad) || a->isop(LIR_float) || - a->isop(LIR_ldf) || a->isop(LIR_ldfc) || - a->isop(LIR_ldq) || a->isop(LIR_ldqc) || - a->isop(LIR_ld32f) || a->isop(LIR_ldc32f) || - a->isop(LIR_u2f) || a->isop(LIR_fcall)); - allow &= ~rmask(rr); - ra = findRegFor(a, allow); - } else { - ra = a->getReg(); - } - if (a == b) { - rb = ra; - } - NanoAssert(originalAllow & rmask(rr)); - NanoAssert(originalAllow & rmask(ra)); - NanoAssert(originalAllow & rmask(rb)); - } - void Assembler::asm_qbinop(LIns *ins) { asm_arith(ins); } void Assembler::asm_shift(LIns *ins) { - // shift require rcx for shift count + // Shift requires rcx for shift count. + LIns *a = ins->oprnd1(); LIns *b = ins->oprnd2(); if (b->isconst()) { asm_shift_imm(ins); return; } + Register rr, ra; - if (b != ins->oprnd1()) { + if (a != b) { findSpecificRegFor(b, RCX); - regalloc_unary(ins, GpRegs & ~rmask(RCX), rr, ra); + beginOp1Regs(ins, GpRegs & ~rmask(RCX), rr, ra); } else { - // a == b means both must be in RCX - regalloc_unary(ins, rmask(RCX), rr, ra); + // Nb: this is just like beginOp1Regs() except that it asserts + // that ra is in GpRegs instead of rmask(RCX)) -- this is + // necessary for the a==b case because 'a' might not be in RCX + // (which is ok, the MR(rr, ra) below will move it into RCX). + rr = prepareResultReg(ins, rmask(RCX)); + + // If 'a' isn't in a register, it can be clobbered by 'ins'. + ra = a->isInReg() ? a->getReg() : rr; + NanoAssert(rmask(ra) & GpRegs); } + switch (ins->opcode()) { default: TODO(asm_shift); @@ -689,11 +661,14 @@ namespace nanojit } if (rr != ra) MR(rr, ra); + + endOpRegs(ins, rr, ra); } void Assembler::asm_shift_imm(LIns *ins) { Register rr, ra; - regalloc_unary(ins, GpRegs, rr, ra); + beginOp1Regs(ins, GpRegs, rr, ra); + int shift = ins->oprnd2()->imm32() & 63; switch (ins->opcode()) { default: TODO(shiftimm); @@ -706,6 +681,8 @@ namespace nanojit } if (rr != ra) MR(rr, ra); + + endOpRegs(ins, rr, ra); } static bool isImm32(LIns *ins) { @@ -715,21 +692,22 @@ namespace nanojit return ins->isconst() ? ins->imm32() : int32_t(ins->imm64()); } - // binary op, integer regs, rhs is int32 const + // Binary op, integer regs, rhs is int32 constant. void Assembler::asm_arith_imm(LIns *ins) { LIns *b = ins->oprnd2(); int32_t imm = getImm32(b); LOpcode op = ins->opcode(); Register rr, ra; if (op == LIR_mul || op == LIR_mulxov) { - // imul has true 3-addr form, it doesn't clobber ra - rr = deprecated_prepResultReg(ins, GpRegs); - LIns *a = ins->oprnd1(); - ra = findRegFor(a, GpRegs); + // Special case: imul-by-imm has true 3-addr form. So we don't + // need the MR(rr, ra) after the IMULI. + beginOp1Regs(ins, GpRegs, rr, ra); IMULI(rr, ra, imm); + endOpRegs(ins, rr, ra); return; } - regalloc_unary(ins, GpRegs, rr, ra); + + beginOp1Regs(ins, GpRegs, rr, ra); if (isS8(imm)) { switch (ins->opcode()) { default: TODO(arith_imm8); @@ -765,35 +743,63 @@ namespace nanojit } if (rr != ra) MR(rr, ra); + + endOpRegs(ins, rr, ra); } - void Assembler::asm_div_mod(LIns *ins) { - LIns *div; - if (ins->opcode() == LIR_mod) { - // LIR_mod expects the LIR_div to be near - div = ins->oprnd1(); - deprecated_prepResultReg(ins, rmask(RDX)); - } else { - div = ins; - evictIfActive(RDX); - } - + // Generates code for a LIR_div that doesn't have a subsequent LIR_mod. + void Assembler::asm_div(LIns *div) { NanoAssert(div->isop(LIR_div)); + LIns *a = div->oprnd1(); + LIns *b = div->oprnd2(); - LIns *lhs = div->oprnd1(); - LIns *rhs = div->oprnd2(); + evictIfActive(RDX); + prepareResultReg(div, rmask(RAX)); - deprecated_prepResultReg(div, rmask(RAX)); + Register rb = findRegFor(b, GpRegs & ~(rmask(RAX)|rmask(RDX))); + Register ra = a->isInReg() ? a->getReg() : RAX; - Register rhsReg = findRegFor(rhs, GpRegs & ~(rmask(RAX)|rmask(RDX))); - Register lhsReg = !lhs->isInReg() - ? findSpecificRegForUnallocated(lhs, RAX) - : lhs->getReg(); - IDIV(rhsReg); + IDIV(rb); SARI(RDX, 31); MR(RDX, RAX); - if (RAX != lhsReg) - MR(RAX, lhsReg); + if (RAX != ra) + MR(RAX, ra); + + freeResourcesOf(div); + if (!a->isInReg()) { + NanoAssert(ra == RAX); + findSpecificRegForUnallocated(a, RAX); + } + } + + // Generates code for a LIR_mod(LIR_div(divL, divR)) sequence. + void Assembler::asm_div_mod(LIns *mod) { + LIns *div = mod->oprnd1(); + + NanoAssert(mod->isop(LIR_mod)); + NanoAssert(div->isop(LIR_div)); + + LIns *divL = div->oprnd1(); + LIns *divR = div->oprnd2(); + + prepareResultReg(mod, rmask(RDX)); + prepareResultReg(div, rmask(RAX)); + + Register rDivR = findRegFor(divR, GpRegs & ~(rmask(RAX)|rmask(RDX))); + Register rDivL = divL->isInReg() ? divL->getReg() : RAX; + + IDIV(rDivR); + SARI(RDX, 31); + MR(RDX, RAX); + if (RAX != rDivL) + MR(RAX, rDivL); + + freeResourcesOf(mod); + freeResourcesOf(div); + if (!divL->isInReg()) { + NanoAssert(rDivL == RAX); + findSpecificRegForUnallocated(divL, RAX); + } } // binary op with integer registers @@ -807,9 +813,13 @@ namespace nanojit asm_shift(ins); return; case LIR_mod: - case LIR_div: asm_div_mod(ins); return; + case LIR_div: + // Nb: if the div feeds into a mod it will be handled by + // asm_div_mod() rather than here. + asm_div(ins); + return; default: break; } @@ -819,7 +829,7 @@ namespace nanojit asm_arith_imm(ins); return; } - regalloc_binary(ins, GpRegs, rr, ra, rb); + beginOp2Regs(ins, GpRegs, rr, ra, rb); switch (ins->opcode()) { default: TODO(asm_arith); case LIR_or: ORLRR(rr, rb); break; @@ -838,16 +848,15 @@ namespace nanojit case LIR_qaddp: ADDQRR(rr, rb); break; } if (rr != ra) - MR(rr,ra); + MR(rr, ra); + + endOpRegs(ins, rr, ra); } - // binary op with fp registers + // Binary op with fp registers. void Assembler::asm_fop(LIns *ins) { - // NB, rb is always filled in by regalloc_binary, - // but compilers can't always tell that: init to UnspecifiedReg - // to avoid a warning. - Register rr, ra, rb = UnspecifiedReg; - regalloc_binary(ins, FpRegs, rr, ra, rb); + Register rr, ra, rb = UnspecifiedReg; // init to shut GCC up + beginOp2Regs(ins, FpRegs, rr, ra, rb); switch (ins->opcode()) { default: TODO(asm_fop); case LIR_fdiv: DIVSD(rr, rb); break; @@ -858,28 +867,29 @@ namespace nanojit if (rr != ra) { asm_nongp_copy(rr, ra); } + + endOpRegs(ins, rr, ra); } void Assembler::asm_neg_not(LIns *ins) { Register rr, ra; - regalloc_unary(ins, GpRegs, rr, ra); - NanoAssert(IsGpReg(ra)); + beginOp1Regs(ins, GpRegs, rr, ra); + if (ins->isop(LIR_not)) NOT(rr); else NEG(rr); if (rr != ra) MR(rr, ra); + + endOpRegs(ins, rr, ra); } void Assembler::asm_call(LIns *ins) { - Register retReg = ( ins->isop(LIR_fcall) ? XMM0 : retRegs[0] ); - deprecated_prepResultReg(ins, rmask(retReg)); + Register rr = ( ins->isop(LIR_fcall) ? XMM0 : retRegs[0] ); + prepareResultReg(ins, rmask(rr)); - // Do this after we've handled the call result, so we don't - // force the call result to be spilled unnecessarily. - - evictScratchRegs(); + evictScratchRegsExcept(rmask(rr)); const CallInfo *call = ins->callInfo(); ArgSize sizes[MAXARGS]; @@ -906,6 +916,9 @@ namespace nanojit CALLRAX(); } + // Call this now so that the arg setup can involve 'rr'. + freeResourcesOf(ins); + #ifdef _WIN64 int stk_used = 32; // always reserve 32byte shadow area #else @@ -994,14 +1007,15 @@ namespace nanojit void Assembler::asm_q2i(LIns *ins) { Register rr, ra; - regalloc_unary(ins, GpRegs, rr, ra); + beginOp1Regs(ins, GpRegs, rr, ra); NanoAssert(IsGpReg(ra)); MOVLR(rr, ra); // 32bit mov zeros the upper 32bits of the target + endOpRegs(ins, rr, ra); } void Assembler::asm_promote(LIns *ins) { Register rr, ra; - regalloc_unary(ins, GpRegs, rr, ra); + beginOp1Regs(ins, GpRegs, rr, ra); NanoAssert(IsGpReg(ra)); if (ins->isop(LIR_u2q)) { MOVLR(rr, ra); // 32bit mov zeros the upper 32bits of the target @@ -1009,38 +1023,44 @@ namespace nanojit NanoAssert(ins->isop(LIR_i2q)); MOVSXDR(rr, ra); // sign extend 32->64 } + endOpRegs(ins, rr, ra); } - // the CVTSI2SD instruction only writes to the low 64bits of the target + // The CVTSI2SD instruction only writes to the low 64bits of the target // XMM register, which hinders register renaming and makes dependence // chains longer. So we precede with XORPS to clear the target register. void Assembler::asm_i2f(LIns *ins) { - Register r = deprecated_prepResultReg(ins, FpRegs); - Register b = findRegFor(ins->oprnd1(), GpRegs); - CVTSI2SD(r, b); // cvtsi2sd xmmr, b only writes xmm:0:64 - XORPS(r); // xorps xmmr,xmmr to break dependency chains + LIns *a = ins->oprnd1(); + NanoAssert(ins->isF64() && a->isI32()); + + Register rr = prepareResultReg(ins, FpRegs); + Register ra = findRegFor(a, GpRegs); + CVTSI2SD(rr, ra); // cvtsi2sd xmmr, b only writes xmm:0:64 + XORPS(rr); // xorps xmmr,xmmr to break dependency chains + freeResourcesOf(ins); } void Assembler::asm_u2f(LIns *ins) { - Register r = deprecated_prepResultReg(ins, FpRegs); - Register b = findRegFor(ins->oprnd1(), GpRegs); - NanoAssert(ins->oprnd1()->isI32()); - // since oprnd1 value is 32bit, its okay to zero-extend the value without worrying about clobbering. - CVTSQ2SD(r, b); // convert int64 to double - XORPS(r); // xorps xmmr,xmmr to break dependency chains - MOVLR(b, b); // zero extend u32 to int64 + LIns *a = ins->oprnd1(); + NanoAssert(ins->isF64() && a->isI32()); + + Register rr = prepareResultReg(ins, FpRegs); + Register ra = findRegFor(a, GpRegs); + // Because oprnd1 is 32bit, it's ok to zero-extend it without worrying about clobbering. + CVTSQ2SD(rr, ra); // convert int64 to double + XORPS(rr); // xorps xmmr,xmmr to break dependency chains + MOVLR(ra, ra); // zero extend u32 to int64 + freeResourcesOf(ins); } void Assembler::asm_f2i(LIns *ins) { - LIns *lhs = ins->oprnd1(); - - NanoAssert(ins->isI32() && lhs->isF64()); - Register r = prepareResultReg(ins, GpRegs); - Register b = findRegFor(lhs, FpRegs); - - CVTSD2SI(r, b); + LIns *a = ins->oprnd1(); + NanoAssert(ins->isI32() && a->isF64()); + Register rr = prepareResultReg(ins, GpRegs); + Register rb = findRegFor(a, FpRegs); + CVTSD2SI(rr, rb); freeResourcesOf(ins); } @@ -1052,11 +1072,16 @@ namespace nanojit NanoAssert((ins->isop(LIR_cmov) && iftrue->isI32() && iffalse->isI32()) || (ins->isop(LIR_qcmov) && iftrue->isI64() && iffalse->isI64())); - // this code assumes that neither LD nor MR nor MRcc set any of the condition flags. - // (This is true on Intel, is it true on all architectures?) - const Register rr = deprecated_prepResultReg(ins, GpRegs); - const Register rf = findRegFor(iffalse, GpRegs & ~rmask(rr)); + Register rr = prepareResultReg(ins, GpRegs); + Register rf = findRegFor(iffalse, GpRegs & ~rmask(rr)); + + // If 'iftrue' isn't in a register, it can be clobbered by 'ins'. + Register rt = iftrue->isInReg() ? iftrue->getReg() : rr; + + // WARNING: We cannot generate any code that affects the condition + // codes between the MRcc generation here and the asm_cmp() call + // below. See asm_cmp() for more details. LOpcode condop = cond->opcode(); if (ins->opcode() == LIR_cmov) { switch (condop) { @@ -1085,7 +1110,15 @@ namespace nanojit default: NanoAssert(0); break; } } - /*const Register rt =*/ findSpecificRegFor(iftrue, rr); + if (rr != rt) + MR(rr, rt); + + freeResourcesOf(ins); + if (!iftrue->isInReg()) { + NanoAssert(rt == rr); + findSpecificRegForUnallocated(iftrue, rr); + } + asm_cmp(cond); } @@ -1099,7 +1132,7 @@ namespace nanojit if (condop >= LIR_feq && condop <= LIR_fge) return asm_fbranch(onFalse, cond, target); - // We must ensure there's room for the instr before calculating + // We must ensure there's room for the instruction before calculating // the offset. And the offset determines the opcode (8bit or 32bit). if (target && isTargetWithinS8(target)) { if (onFalse) { @@ -1158,7 +1191,7 @@ namespace nanojit } } } - NIns *patch = _nIns; // addr of instr to patch + NIns *patch = _nIns; // address of instruction to patch asm_cmp(cond); return patch; } @@ -1176,6 +1209,9 @@ namespace nanojit JO( 8, target); } + // WARNING: this function cannot generate code that will affect the + // condition codes prior to the generation of the test/cmp. See + // Nativei386.cpp:asm_cmp() for details. void Assembler::asm_cmp(LIns *cond) { LIns *b = cond->oprnd2(); if (isImm32(b)) { @@ -1220,8 +1256,8 @@ namespace nanojit } } - // compiling floating point branches - // discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=443886 + // Compiling floating point branches. + // Discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=443886. // // fucom/p/pp: c3 c2 c0 jae ja jbe jb je jne // ucomisd: Z P C !C !C&!Z C|Z C Z !Z @@ -1231,7 +1267,7 @@ namespace nanojit // less < 0 0 1 T T T // equal = 1 0 0 T T T // - // here's the cases, using conditionals: + // Here are the cases, using conditionals: // // branch >= > <= < = // ------ --- --- --- --- --- @@ -1281,7 +1317,7 @@ namespace nanojit } patch = _nIns; } - fcmp(a, b); + asm_fcmp(a, b); return patch; } @@ -1292,7 +1328,7 @@ namespace nanojit if (op == LIR_feq) { // result = ZF & !PF, must do logic on flags // r = al|bl|cl|dl, can only use rh without rex prefix - Register r = deprecated_prepResultReg(ins, 1<isop(LIR_alloc)) { int d = arDisp(ins); @@ -1336,11 +1380,10 @@ namespace nanojit } else { int d = findMemFor(ins); - if (IsFpReg(r)) { - NanoAssert(ins->isN64()); - // load 64bits into XMM. don't know if double or int64, assume double. + if (ins->isF64()) { + NanoAssert(IsFpReg(r)); MOVSDRM(r, d, FP); - } else if (ins->isN64()) { + } else if (ins->isI64()) { NanoAssert(IsGpReg(r)); MOVQRM(r, d, FP); } else { @@ -1353,8 +1396,10 @@ namespace nanojit void Assembler::asm_cond(LIns *ins) { LOpcode op = ins->opcode(); + // unlike x86-32, with a rex prefix we can use any GP register as an 8bit target - Register r = deprecated_prepResultReg(ins, GpRegs); + Register r = prepareResultReg(ins, GpRegs); + // SETcc only sets low 8 bits, so extend MOVZX8(r, r); switch (op) { @@ -1379,6 +1424,8 @@ namespace nanojit case LIR_quge: case LIR_uge: SETAE(r); break; } + freeResourcesOf(ins); + asm_cmp(ins); } @@ -1409,18 +1456,17 @@ namespace nanojit } } - void Assembler::regalloc_load(LIns *ins, RegisterMask allow, Register &rr, int32_t &dr, Register &rb) { + // Register setup for load ops. Pairs with endLoadRegs(). + void Assembler::beginLoadRegs(LIns *ins, RegisterMask allow, Register &rr, int32_t &dr, Register &rb) { dr = ins->disp(); LIns *base = ins->oprnd1(); rb = getBaseReg(base, dr, BaseRegs); - if (!ins->isInRegMask(allow)) { - rr = deprecated_prepResultReg(ins, allow & ~rmask(rb)); - } else { - // keep already assigned register - rr = ins->getReg(); - NanoAssert(allow & rmask(rr)); - deprecated_freeRsrcOf(ins, false); - } + rr = prepareResultReg(ins, allow & ~rmask(rb)); + } + + // Register clean-up for load ops. Pairs with beginLoadRegs(). + void Assembler::endLoadRegs(LIns* ins) { + freeResourcesOf(ins); } void Assembler::asm_load64(LIns *ins) { @@ -1429,19 +1475,19 @@ namespace nanojit switch (ins->opcode()) { case LIR_ldq: case LIR_ldqc: - regalloc_load(ins, GpRegs, rr, dr, rb); + beginLoadRegs(ins, GpRegs, rr, dr, rb); NanoAssert(IsGpReg(rr)); MOVQRM(rr, dr, rb); // general 64bit load, 32bit const displacement break; case LIR_ldf: case LIR_ldfc: - regalloc_load(ins, FpRegs, rr, dr, rb); + beginLoadRegs(ins, FpRegs, rr, dr, rb); NanoAssert(IsFpReg(rr)); MOVSDRM(rr, dr, rb); // load 64bits into XMM break; case LIR_ld32f: case LIR_ldc32f: - regalloc_load(ins, FpRegs, rr, dr, rb); + beginLoadRegs(ins, FpRegs, rr, dr, rb); NanoAssert(IsFpReg(rr)); CVTSS2SD(rr, rr); MOVSSRM(rr, dr, rb); @@ -1450,14 +1496,14 @@ namespace nanojit NanoAssertMsg(0, "asm_load64 should never receive this LIR opcode"); break; } - + endLoadRegs(ins); } void Assembler::asm_load32(LIns *ins) { NanoAssert(ins->isI32()); Register r, b; int32_t d; - regalloc_load(ins, GpRegs, r, d, b); + beginLoadRegs(ins, GpRegs, r, d, b); LOpcode op = ins->opcode(); switch(op) { case LIR_ldzb: @@ -1484,6 +1530,7 @@ namespace nanojit NanoAssertMsg(0, "asm_load32 should never receive this LIR opcode"); break; } + endLoadRegs(ins); } void Assembler::asm_store64(LOpcode op, LIns *value, int d, LIns *base) { @@ -1542,8 +1589,6 @@ namespace nanojit NanoAssertMsg(0, "asm_store32 should never receive this LIR opcode"); break; } - - } void Assembler::asm_int(LIns *ins) { @@ -1597,11 +1642,11 @@ namespace nanojit uint32_t a = ins->paramArg(); uint32_t kind = ins->paramKind(); if (kind == 0) { - // ordinary param - // first four or six args always in registers for x86_64 ABI + // Ordinary param. First four or six args always in registers for x86_64 ABI. if (a < (uint32_t)NumArgRegs) { // incoming arg in register - deprecated_prepResultReg(ins, rmask(argRegs[a])); + prepareResultReg(ins, rmask(argRegs[a])); + // No code to generate. } else { // todo: support stack based args, arg 0 is at [FP+off] where off // is the # of regs to be pushed in genProlog() @@ -1609,24 +1654,60 @@ namespace nanojit } } else { - // saved param - deprecated_prepResultReg(ins, rmask(savedRegs[a])); + // Saved param. + prepareResultReg(ins, rmask(savedRegs[a])); + // No code to generate. + } + freeResourcesOf(ins); + } + + // Register setup for 2-address style unary ops of the form R = (op) R. + // Pairs with endOpRegs(). + void Assembler::beginOp1Regs(LIns* ins, RegisterMask allow, Register &rr, Register &ra) { + LIns* a = ins->oprnd1(); + + rr = prepareResultReg(ins, allow); + + // If 'a' isn't in a register, it can be clobbered by 'ins'. + ra = a->isInReg() ? a->getReg() : rr; + NanoAssert(rmask(ra) & allow); + } + + // Register setup for 2-address style binary ops of the form R = R (op) B. + // Pairs with endOpRegs(). + void Assembler::beginOp2Regs(LIns *ins, RegisterMask allow, Register &rr, Register &ra, + Register &rb) { + LIns *a = ins->oprnd1(); + LIns *b = ins->oprnd2(); + if (a != b) { + rb = findRegFor(b, allow); + allow &= ~rmask(rb); + } + rr = prepareResultReg(ins, allow); + + // If 'a' isn't in a register, it can be clobbered by 'ins'. + ra = a->isInReg() ? a->getReg() : rr; + NanoAssert(rmask(ra) & allow); + + if (a == b) { + rb = ra; } } - // register allocation for 2-address style unary ops of the form R = (op) R - void Assembler::regalloc_unary(LIns *ins, RegisterMask allow, Register &rr, Register &ra) { - LIns *a = ins->oprnd1(); - rr = deprecated_prepResultReg(ins, allow); - // if this is last use of a in reg, we can re-use result reg + // Register clean-up for 2-address style unary ops of the form R = (op) R. + // Pairs with beginOp1Regs() and beginOp2Regs(). + void Assembler::endOpRegs(LIns* ins, Register rr, Register ra) { + LIns* a = ins->oprnd1(); + + // We're finished with 'ins'. + NanoAssert(ins->getReg() == rr); + freeResourcesOf(ins); + + // If 'a' isn't in a register yet, that means it's clobbered by 'ins'. if (!a->isInReg()) { - ra = findSpecificRegForUnallocated(a, rr); - } else { - // 'a' already has a register assigned. Caller must emit a copy - // to rr once instr code is generated. (ie mov rr,ra ; op rr) - ra = a->getReg(); - } - NanoAssert(allow & rmask(rr)); + NanoAssert(ra == rr); + findSpecificRegForUnallocated(a, ra); + } } static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0}; @@ -1634,7 +1715,7 @@ namespace nanojit void Assembler::asm_fneg(LIns *ins) { Register rr, ra; if (isS32((uintptr_t)negateMask) || isTargetWithinS32((NIns*)negateMask)) { - regalloc_unary(ins, FpRegs, rr, ra); + beginOp1Regs(ins, FpRegs, rr, ra); if (isS32((uintptr_t)negateMask)) { // builtin code is in bottom or top 2GB addr space, use absolute addressing XORPSA(rr, (int32_t)(uintptr_t)negateMask); @@ -1644,14 +1725,17 @@ namespace nanojit } if (ra != rr) asm_nongp_copy(rr,ra); + endOpRegs(ins, rr, ra); + } else { - // this is just hideous - can't use RIP-relative load, can't use + // This is just hideous - can't use RIP-relative load, can't use // absolute-address load, and cant move imm64 const to XMM. // so do it all in a GPR. hrmph. - rr = deprecated_prepResultReg(ins, GpRegs); + rr = prepareResultReg(ins, GpRegs); ra = findRegFor(ins->oprnd1(), GpRegs & ~rmask(rr)); XORQRR(rr, ra); // xor rr, ra asm_quad(rr, negateMask[0], /*canClobberCCs*/true); // mov rr, 0x8000000000000000 + freeResourcesOf(ins); } } diff --git a/js/src/nanojit/NativeX64.h b/js/src/nanojit/NativeX64.h index ff79b4aed399..67fe76cb8826 100644 --- a/js/src/nanojit/NativeX64.h +++ b/js/src/nanojit/NativeX64.h @@ -399,15 +399,18 @@ namespace nanojit void asm_shift(LIns*);\ void asm_shift_imm(LIns*);\ void asm_arith_imm(LIns*);\ - void regalloc_unary(LIns *ins, RegisterMask allow, Register &rr, Register &ra);\ - void regalloc_binary(LIns *ins, RegisterMask allow, Register &rr, Register &ra, Register &rb);\ - void regalloc_load(LIns *ins, RegisterMask allow, Register &rr, int32_t &d, Register &rb);\ + void beginOp1Regs(LIns *ins, RegisterMask allow, Register &rr, Register &ra);\ + void beginOp2Regs(LIns *ins, RegisterMask allow, Register &rr, Register &ra, Register &rb);\ + void endOpRegs(LIns *ins, Register rr, Register ra);\ + void beginLoadRegs(LIns *ins, RegisterMask allow, Register &rr, int32_t &d, Register &rb);\ + void endLoadRegs(LIns *ins);\ void dis(NIns *p, int bytes);\ void asm_cmp(LIns*);\ void asm_cmp_imm(LIns*);\ - void fcmp(LIns*, LIns*);\ + void asm_fcmp(LIns*, LIns*);\ NIns* asm_fbranch(bool, LIns*, NIns*);\ - void asm_div_mod(LIns *i);\ + void asm_div(LIns *ins);\ + void asm_div_mod(LIns *ins);\ int max_stk_used;\ void PUSHR(Register r);\ void POPR(Register r);\ diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index 564b082e1550..a06dc2a05fc2 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -167,7 +167,7 @@ namespace nanojit // Do this after we've handled the call result, so we don't // force the call result to be spilled unnecessarily. - evictScratchRegs(); + evictScratchRegsExcept(0); const CallInfo* call = ins->callInfo(); // must be signed, not unsigned @@ -393,13 +393,17 @@ namespace nanojit } else { int d = findMemFor(ins); - if (rmask(r) & GpRegs) { + if (ins->isI32()) { + NanoAssert(rmask(r) & GpRegs); LD(r, d, FP); - } else if (rmask(r) & XmmRegs) { - SSE_LDQ(r, d, FP); } else { - NanoAssert(rmask(r) & x87Regs); - FLDQ(d, FP); + NanoAssert(ins->isF64()); + if (rmask(r) & XmmRegs) { + SSE_LDQ(r, d, FP); + } else { + NanoAssert(rmask(r) & x87Regs); + FLDQ(d, FP); + } } } } @@ -976,7 +980,7 @@ namespace nanojit } } - // This is called when we have a mod(div(divL, divR)) sequence. + // Generates code for a LIR_mod(LIR_div(divL, divR)) sequence. void Assembler::asm_div_mod(LInsp mod) { LInsp div = mod->oprnd1(); @@ -992,12 +996,10 @@ namespace nanojit prepareResultReg(div, rmask(EAX)); Register rDivR = findRegFor(divR, (GpRegs & ~(rmask(EAX)|rmask(EDX)))); - Register rDivL = !divL->isInReg() ? EAX : divL->getReg(); DIV(rDivR); CDQ(); // sign-extend EAX into EDX:EAX - if (EAX != rDivL) MR(EAX, rDivL); @@ -1028,7 +1030,6 @@ namespace nanojit // void Assembler::asm_neg_not(LInsp ins) { - LOpcode op = ins->opcode(); LIns* lhs = ins->oprnd1(); Register rr = prepareResultReg(ins, GpRegs); @@ -1036,11 +1037,12 @@ namespace nanojit // If 'lhs' isn't in a register, it can be clobbered by 'ins'. Register ra = !lhs->isInReg() ? rr : lhs->getReg(); - if (op == LIR_not) + if (ins->isop(LIR_not)) { NOT(rr); - else + } else { + NanoAssert(ins->isop(LIR_neg)); NEG(rr); - + } if (rr != ra) MR(rr, ra); diff --git a/js/src/vprof/vprof.h b/js/src/vprof/vprof.h index ac016a66e4c1..a71eea8245f5 100644 --- a/js/src/vprof/vprof.h +++ b/js/src/vprof/vprof.h @@ -121,7 +121,7 @@ extern void* _tprof_before_id; #ifndef DOPROF #ifndef VMCFG_SYMBIAN #define _vprof(v,...) -#define _nvprof(e,v,...) +#define _nvprof(e,v) #define _hprof(h,n,...) #define _nhprof(e,v,n,...) #define _ntprof(e) @@ -139,7 +139,7 @@ extern void* _tprof_before_id; ;\ } -#define _nvprof(e,v,...) \ +#define _nvprof(e,v) \ { \ static void* id = 0; \ (id != 0) ? \ From d830bbbd61bc01511583b8e7d79bc6336ada80a2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 09:52:59 +1100 Subject: [PATCH 08/52] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index d7689bf753a9..c76d75a9f390 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -3fa60904a28ec82b54d7e8a9e9fac6c29e0a5324 +6fb5f71fba861a333e17de644fe49de60bb7a1bd From 7a293a6a676b55ffadb3cbfdd3355a5a94342c07 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 12:02:01 +1100 Subject: [PATCH 09/52] Bug 542932 - nanojit: make opcode range checks safer. r=stejohns. --HG-- extra : convert_revision : a5291bc7b0cef4f41f4180db6388edebdbb4c208 --- js/src/lirasm/lirasm.cpp | 2 +- js/src/nanojit/LIR.cpp | 34 ++-- js/src/nanojit/LIR.h | 141 +++++++++++--- js/src/nanojit/LIRopcode.tbl | 336 ++++++++++++++++----------------- js/src/nanojit/NativeARM.cpp | 6 +- js/src/nanojit/NativeMIPS.cpp | 8 +- js/src/nanojit/NativePPC.cpp | 20 +- js/src/nanojit/NativeSparc.cpp | 6 +- js/src/nanojit/NativeX64.cpp | 10 +- js/src/nanojit/Nativei386.cpp | 4 +- 10 files changed, 324 insertions(+), 243 deletions(-) diff --git a/js/src/lirasm/lirasm.cpp b/js/src/lirasm/lirasm.cpp index 22d6f9fb8298..b8aae9fc7604 100644 --- a/js/src/lirasm/lirasm.cpp +++ b/js/src/lirasm/lirasm.cpp @@ -1990,7 +1990,7 @@ Lirasm::Lirasm(bool verbose) : #endif // Populate the mOpMap table. -#define OP___(op, number, repKind, retType) \ +#define OP___(op, number, repKind, retType, isCse) \ mOpMap[#op] = LIR_##op; #include "nanojit/LIRopcode.tbl" #undef OP___ diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index af7f31e0eec3..e2452766df56 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -45,7 +45,7 @@ namespace nanojit #ifdef FEATURE_NANOJIT const uint8_t repKinds[] = { -#define OP___(op, number, repKind, retType) \ +#define OP___(op, number, repKind, retType, isCse) \ LRK_##repKind, #include "LIRopcode.tbl" #undef OP___ @@ -53,18 +53,26 @@ namespace nanojit }; const LTy retTypes[] = { -#define OP___(op, number, repKind, retType) \ +#define OP___(op, number, repKind, retType, isCse) \ LTy_##retType, #include "LIRopcode.tbl" #undef OP___ LTy_Void }; + const int8_t isCses[] = { +#define OP___(op, number, repKind, retType, isCse) \ + isCse, +#include "LIRopcode.tbl" +#undef OP___ + 0 + }; + // LIR verbose specific #ifdef NJ_VERBOSE const char* lirNames[] = { -#define OP___(op, number, repKind, retType) \ +#define OP___(op, number, repKind, retType, isCse) \ #op, #include "LIRopcode.tbl" #undef OP___ @@ -334,7 +342,7 @@ namespace nanojit { static const uint8_t insSizes[] = { // LIR_start is treated specially -- see below. -#define OP___(op, number, repKind, retType) \ +#define OP___(op, number, repKind, retType, isCse) \ ((number) == LIR_start ? 0 : sizeof(LIns##repKind)), #include "LIRopcode.tbl" #undef OP___ @@ -666,17 +674,12 @@ namespace nanojit oprnd1 = t; break; default: - if (v >= LIR_lt && v <= LIR_uge) { - NanoStaticAssert((LIR_lt ^ 1) == LIR_gt); - NanoStaticAssert((LIR_le ^ 1) == LIR_ge); - NanoStaticAssert((LIR_ult ^ 1) == LIR_ugt); - NanoStaticAssert((LIR_ule ^ 1) == LIR_uge); - + if (isICmpOpcode(v)) { // move const to rhs, swap the operator LIns *t = oprnd2; oprnd2 = oprnd1; oprnd1 = t; - v = LOpcode(v^1); + v = invertICmpOpcode(v); } break; } @@ -810,11 +813,10 @@ namespace nanojit } } else { - NanoStaticAssert((LIR_xt ^ 1) == LIR_xf); while (c->isop(LIR_eq) && c->oprnd1()->isCmp() && c->oprnd2()->isconstval(0)) { // xt(eq(cmp,0)) => xf(cmp) or xf(eq(cmp,0)) => xt(cmp) - v = LOpcode(v^1); + v = invertCondGuardOpcode(v); c = c->oprnd1(); } } @@ -883,7 +885,7 @@ namespace nanojit case LIR_jf: while (c->isop(LIR_eq) && c->oprnd1()->isCmp() && c->oprnd2()->isconstval(0)) { // jt(eq(cmp,0)) => jf(cmp) or jf(eq(cmp,0)) => jt(cmp) - v = LOpcode(v ^ 1); + v = invertCondJmpOpcode(v); c = c->oprnd1(); } break; @@ -2150,7 +2152,7 @@ namespace nanojit LIns* CseFilter::ins3(LOpcode v, LInsp a, LInsp b, LInsp c) { - NanoAssert(isCmovOpcode(v)); + NanoAssert(isCseOpcode(v)); uint32_t k; LInsp ins = exprs->find3(v, a, b, c, k); if (ins) @@ -2392,7 +2394,7 @@ namespace nanojit LIns* SoftFloatFilter::ins2(LOpcode op, LIns *a, LIns *b) { const CallInfo *ci = softFloatOps.opmap[op]; if (ci) { - if ((op >= LIR_feq && op <= LIR_fge)) + if (isFCmpOpcode(op)) return fcmp(ci, a, b); return fcall2(ci, a, b); } diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index 4899a693b0d9..60c8bab32fee 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -48,7 +48,7 @@ namespace nanojit : unsigned #endif { -#define OP___(op, number, repKind, retType) \ +#define OP___(op, number, repKind, retType, isCse) \ LIR_##op = (number), #include "LIRopcode.tbl" LIR_sentinel, @@ -89,6 +89,54 @@ namespace nanojit LIR_pret = PTR_SIZE(LIR_ret, LIR_qret) }; + // 32-bit integer comparisons must be contiguous, as must 64-bit integer + // comparisons and 64-bit float comparisons. + NanoStaticAssert(LIR_eq + 1 == LIR_lt && + LIR_eq + 2 == LIR_gt && + LIR_eq + 3 == LIR_le && + LIR_eq + 4 == LIR_ge && + LIR_eq + 5 == LIR_ult && + LIR_eq + 6 == LIR_ugt && + LIR_eq + 7 == LIR_ule && + LIR_eq + 8 == LIR_uge); +#ifdef NANOJIT_64BIT + NanoStaticAssert(LIR_qeq + 1 == LIR_qlt && + LIR_qeq + 2 == LIR_qgt && + LIR_qeq + 3 == LIR_qle && + LIR_qeq + 4 == LIR_qge && + LIR_qeq + 5 == LIR_qult && + LIR_qeq + 6 == LIR_qugt && + LIR_qeq + 7 == LIR_qule && + LIR_qeq + 8 == LIR_quge); +#endif + NanoStaticAssert(LIR_feq + 1 == LIR_flt && + LIR_feq + 2 == LIR_fgt && + LIR_feq + 3 == LIR_fle && + LIR_feq + 4 == LIR_fge); + + // Various opcodes must be changeable to their opposite with op^1 + // (although we use invertXyz() when possible, ie. outside static + // assertions). + NanoStaticAssert((LIR_jt^1) == LIR_jf && (LIR_jf^1) == LIR_jt); + + NanoStaticAssert((LIR_xt^1) == LIR_xf && (LIR_xf^1) == LIR_xt); + + NanoStaticAssert((LIR_lt^1) == LIR_gt && (LIR_gt^1) == LIR_lt); + NanoStaticAssert((LIR_le^1) == LIR_ge && (LIR_ge^1) == LIR_le); + NanoStaticAssert((LIR_ult^1) == LIR_ugt && (LIR_ugt^1) == LIR_ult); + NanoStaticAssert((LIR_ule^1) == LIR_uge && (LIR_uge^1) == LIR_ule); + +#ifdef NANOJIT_64BIT + NanoStaticAssert((LIR_qlt^1) == LIR_qgt && (LIR_qgt^1) == LIR_qlt); + NanoStaticAssert((LIR_qle^1) == LIR_qge && (LIR_qge^1) == LIR_qle); + NanoStaticAssert((LIR_qult^1) == LIR_qugt && (LIR_qugt^1) == LIR_qult); + NanoStaticAssert((LIR_qule^1) == LIR_quge && (LIR_quge^1) == LIR_qule); +#endif + + NanoStaticAssert((LIR_flt^1) == LIR_fgt && (LIR_fgt^1) == LIR_flt); + NanoStaticAssert((LIR_fle^1) == LIR_fge && (LIR_fge^1) == LIR_fle); + + struct GuardRecord; struct SideExit; @@ -171,14 +219,12 @@ namespace nanojit uint32_t index; }; + // Array holding the 'isCse' field from LIRopcode.tbl. + extern const int8_t isCses[]; // cannot be uint8_t, some values are negative + inline bool isCseOpcode(LOpcode op) { - return -#if defined NANOJIT_64BIT - (op >= LIR_quad && op <= LIR_quge) || -#else - (op >= LIR_i2f && op <= LIR_float) || // XXX: yuk; use a table (bug 542932) -#endif - (op >= LIR_int && op <= LIR_uge); + NanoAssert(isCses[op] != -1); // see LIRopcode.tbl to understand this + return isCses[op] == 1; } inline bool isRetOpcode(LOpcode op) { return @@ -194,6 +240,53 @@ namespace nanojit #endif op == LIR_cmov; } + inline bool isICmpOpcode(LOpcode op) { + return LIR_eq <= op && op <= LIR_uge; + } + inline bool isSICmpOpcode(LOpcode op) { + return LIR_eq <= op && op <= LIR_ge; + } + inline bool isUICmpOpcode(LOpcode op) { + return LIR_eq == op || (LIR_ult <= op && op <= LIR_uge); + } +#ifdef NANOJIT_64BIT + inline bool isQCmpOpcode(LOpcode op) { + return LIR_qeq <= op && op <= LIR_quge; + } + inline bool isSQCmpOpcode(LOpcode op) { + return LIR_qeq <= op && op <= LIR_qge; + } + inline bool isUQCmpOpcode(LOpcode op) { + return LIR_qeq == op || (LIR_qult <= op && op <= LIR_quge); + } +#endif + inline bool isFCmpOpcode(LOpcode op) { + return LIR_feq <= op && op <= LIR_fge; + } + + inline LOpcode invertCondJmpOpcode(LOpcode op) { + NanoAssert(op == LIR_jt || op == LIR_jf); + return LOpcode(op ^ 1); + } + inline LOpcode invertCondGuardOpcode(LOpcode op) { + NanoAssert(op == LIR_xt || op == LIR_xf); + return LOpcode(op ^ 1); + } + inline LOpcode invertICmpOpcode(LOpcode op) { + NanoAssert(isICmpOpcode(op)); + return LOpcode(op ^ 1); + } +#ifdef NANOJIT_64BIT + inline LOpcode invertQCmpOpcode(LOpcode op) { + NanoAssert(isQCmpOpcode(op)); + return LOpcode(op ^ 1); + } +#endif + inline LOpcode invertFCmpOpcode(LOpcode op) { + NanoAssert(isFCmpOpcode(op)); + return LOpcode(op ^ 1); + } + inline LOpcode getCallOpcode(const CallInfo* ci) { LOpcode op = LIR_pcall; switch (ci->returnType()) { @@ -560,37 +653,33 @@ namespace nanojit } // LIns predicates. - bool isCse() const { - return isCseOpcode(opcode()) || (isCall() && callInfo()->_cse); + bool isop(LOpcode o) const { + return opcode() == o; } bool isRet() const { return isRetOpcode(opcode()); } bool isLive() const { - LOpcode op = opcode(); - return + return isop(LIR_live) || #if defined NANOJIT_64BIT - op == LIR_qlive || + isop(LIR_qlive) || #endif - op == LIR_live || op == LIR_flive; - } - bool isop(LOpcode o) const { - return opcode() == o; + isop(LIR_flive); } bool isCmp() const { LOpcode op = opcode(); - return (op >= LIR_eq && op <= LIR_uge) || + return isICmpOpcode(op) || #if defined NANOJIT_64BIT - (op >= LIR_qeq && op <= LIR_quge) || + isQCmpOpcode(op) || #endif - (op >= LIR_feq && op <= LIR_fge); + isFCmpOpcode(op); } bool isCall() const { - return + return isop(LIR_icall) || #if defined NANOJIT_64BIT - isop(LIR_qcall) || + isop(LIR_qcall) || #endif - isop(LIR_icall) || isop(LIR_fcall); + isop(LIR_fcall); } bool isCmov() const { return isCmovOpcode(opcode()); @@ -681,10 +770,10 @@ namespace nanojit // affect the control flow. bool isStmt() { NanoAssert(!isop(LIR_start) && !isop(LIR_skip)); - // All instructions with Void retType are statements. And some - // calls are statements too. + // All instructions with Void retType are statements, as are calls + // to non-CSEable functions. if (isCall()) - return !isCse(); + return !callInfo()->_cse; else return isVoid(); } diff --git a/js/src/nanojit/LIRopcode.tbl b/js/src/nanojit/LIRopcode.tbl index 1f2657ed3955..7c18267caaff 100644 --- a/js/src/nanojit/LIRopcode.tbl +++ b/js/src/nanojit/LIRopcode.tbl @@ -40,18 +40,21 @@ /* * Definitions of LIR opcodes. If you need to allocate an opcode, look - * for a name beginning with "__" and claim it. + * for one defined using OP_UN() and claim it. * * Includers must define an OPxyz macro of the following form: * - * #define OPxyz(op, val, repKind, retType) ... + * #define OPxyz(op, number, repKind, retType) ... * * Selected arguments can then be used within the macro expansions. * - op Bytecode name, token-pasted after "LIR_" to form an LOpcode. - * - val Bytecode value, which is the LOpcode enumerator value. + * - number Bytecode number, used as the LOpcode enum value. * - repKind Indicates how the instruction is represented in memory; XYZ * corresponds to LInsXYZ and LRK_XYZ. * - retType Type (LTy) of the value returned by the instruction. + * - isCse 0 if the opcode can never be CSE'd safely, 1 if it always + * can, -1 if things are more complicated -- in which case + * isCseOpcode() shouldn't be called on this opcode. * * This file is best viewed with 128 columns: 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 @@ -63,239 +66,230 @@ * the following: * * OP___: for opcodes supported on all platforms. + * OP_UN: for opcodes not yet used on any platform. * OP_32: for opcodes supported only on 32-bit platforms. * OP_64: for opcodes supported only on 64-bit platforms. * OP_SF: for opcodes supported only on SoftFloat platforms. * OP_86: for opcodes supported only on i386/X64. */ +#define OP_UN(n) OP___(__##n, n, None, Void, -1) + #ifdef NANOJIT_64BIT -# define OP_32(a, b, c, d) OP___(__##b, b, None, Void) -# define OP_64 OP___ +# define OP_32(a, b, c, d, e) OP_UN(b) +# define OP_64 OP___ #else -# define OP_32 OP___ -# define OP_64(a, b, c, d) OP___(__##b, b, None, Void) +# define OP_32 OP___ +# define OP_64(a, b, c, d, e) OP_UN(b) #endif #if NJ_SOFTFLOAT_SUPPORTED -# define OP_SF OP___ +# define OP_SF OP___ #else -# define OP_SF(a, b, c, d) OP___(__##b, b, None, Void) +# define OP_SF(a, b, c, d, e) OP_UN(b) #endif #if defined NANOJIT_IA32 || defined NANOJIT_X64 -# define OP_86 OP___ +# define OP_86 OP___ #else -# define OP_86(a, b, c, d) OP___(__##b, b, None, Void) +# define OP_86(a, b, c, d, e) OP_UN(b) #endif - -/* special operations */ -OP___(start, 0, Op0, Void) // start of a fragment -OP___(regfence, 1, Op0, Void) // register fence, no register allocation is allowed across this meta instruction -OP___(skip, 2, Sk, Void) // used to link code chunks -/* non-pure operations */ -OP___(ldsb, 3, Ld, I32) // 8-bit integer load, sign-extend to 32-bit -OP___(ldss, 4, Ld, I32) // 16-bit integer load, sign-extend to 32-bit -OP___(ldzb, 5, Ld, I32) // 8-bit integer load, zero extend to 32-bit -OP___(ldzs, 6, Ld, I32) // 16-bit integer load, zero extend to 32-bit -OP_32(iaddp, 7, Op2, I32) // 32-bit integer addition for temporary pointer calculations -OP_32(iparam, 8, P, I32) // load a parameter (32-bit register or stack location) -OP___(stb, 9, Sti, Void) // 8-bit integer store -OP___(ld, 10, Ld, I32) // 32-bit integer load -OP_32(ialloc, 11, I, I32) // allocate some stack space (result is a 32-bit address) -OP___(sti, 12, Sti, Void) // 32-bit integer store -OP___(ret, 13, Op1, Void) // return a 32-bit integer -OP___(live, 14, Op1, Void) // extend live range of a 32-bit integer -OP___(flive, 15, Op1, Void) // extend live range of a 64-bit float -OP___(icall, 16, C, I32) // subroutine call returning a 32-bit value -OP___(sts, 17, Sti, Void) // 16-bit integer store +// Special operations. +OP___(start, 0, Op0, Void, 0) // start of a fragment +OP___(regfence, 1, Op0, Void, 0) // register fence, no register allocation is allowed across this meta instruction +OP___(skip, 2, Sk, Void, 0) // used to link code chunks -/* guards */ -OP___(x, 18, Op2, Void) // exit always +// Impure operations. +OP___(ldsb, 3, Ld, I32, 0) // 8-bit integer load, sign-extend to 32-bit +OP___(ldss, 4, Ld, I32, 0) // 16-bit integer load, sign-extend to 32-bit +OP___(ldzb, 5, Ld, I32, 0) // 8-bit integer load, zero extend to 32-bit +OP___(ldzs, 6, Ld, I32, 0) // 16-bit integer load, zero extend to 32-bit +OP_32(iaddp, 7, Op2, I32, 0) // 32-bit integer addition for temporary pointer calculations +OP_32(iparam, 8, P, I32, 0) // load a parameter (32-bit register or stack location) +OP___(stb, 9, Sti, Void, 0) // 8-bit integer store +OP___(ld, 10, Ld, I32, 0) // 32-bit integer load +OP_32(ialloc, 11, I, I32, 0) // allocate some stack space (result is a 32-bit address) +OP___(sti, 12, Sti, Void, 0) // 32-bit integer store +OP___(ret, 13, Op1, Void, 0) // return a 32-bit integer +OP___(live, 14, Op1, Void, 0) // extend live range of a 32-bit integer +OP___(flive, 15, Op1, Void, 0) // extend live range of a 64-bit float +OP___(icall, 16, C, I32, -1) // subroutine call returning a 32-bit value +OP___(sts, 17, Sti, Void, 0) // 16-bit integer store -/* branches */ -OP___(j, 19, Op2, Void) // jump always -OP___(jt, 20, Op2, Void) // jump if true -OP___(jf, 21, Op2, Void) // jump if false -OP___(label, 22, Op0, Void) // a jump target (no machine code is emitted for this) -OP___(jtbl, 23, Jtbl, Void) // jump to address in table +OP___(x, 18, Op2, Void, 0) // exit always -/* operators */ +// Branches. 'jt' and 'jf' must be adjacent so that (op ^ 1) gives the +// opposite one. Static assertions in LIR.h check this requirement. +OP___(j, 19, Op2, Void, 0) // jump always +OP___(jt, 20, Op2, Void, 0) // jump if true +OP___(jf, 21, Op2, Void, 0) // jump if false +OP___(label, 22, Op0, Void, 0) // a jump target (no machine code is emitted for this) +OP___(jtbl, 23, Jtbl, Void, 0) // jump to address in table -/* - * NB: Opcodes LIR_int through LIR_uge must remain continuous to aid in - * common-subexpression-elimination detection code. - */ - -OP___(int, 24, I, I32) // constant 32-bit integer -OP___(cmov, 25, Op3, I32) // conditional move +OP___(int, 24, I, I32, 1) // constant 32-bit integer +OP___(cmov, 25, Op3, I32, 1) // conditional move // LIR_callh is a hack that's only used on 32-bit platforms that use SoftFloat. // Its operand is always a LIR_icall, but one that specifies a function that // returns a 64-bit float. It indicates that the 64-bit float return value is // being returned via two 32-bit integer registers. The result is always used // as the second operand of a LIR_qjoin. -OP_SF(callh, 26, Op1, I32) +OP_SF(callh, 26, Op1, I32, 1) -// feq though fge must only be used on float arguments. They return integers. -// For all except feq, (op ^ 1) is the op which flips the -// left and right sides of the comparison, so (lt ^ 1) == gt, or the operator -// "<" is xored with 1 to get ">". Similarly, (op ^ 3) is the complement of -// op, so (lt ^ 1) == ge, or the complement of the operator "<" is ">=" xored -// with 3. NB: These opcodes must remain continuous so that comparison-opcode -// detection works correctly. -OP___(feq, 27, Op2, I32) // floating-point equality -OP___(flt, 28, Op2, I32) // floating-point less-than -OP___(fgt, 29, Op2, I32) // floating-point greater-than -OP___(fle, 30, Op2, I32) // floating-point less-than-or-equal -OP___(fge, 31, Op2, I32) // floating-point greater-than-or-equal +// 64-bit float comparisons. Their order must be preserved so that, except for +// 'feq', (op ^ 1) gives the opposite one (eg. flt ^ 1 == fgt). They must also +// remain contiguous so that opcode range checking works correctly. +// Static assertions in LIR.h check these requirements. +OP___(feq, 27, Op2, I32, 1) // floating-point equality +OP___(flt, 28, Op2, I32, 1) // floating-point less-than +OP___(fgt, 29, Op2, I32, 1) // floating-point greater-than +OP___(fle, 30, Op2, I32, 1) // floating-point less-than-or-equal +OP___(fge, 31, Op2, I32, 1) // floating-point greater-than-or-equal -OP___(ldcb, 32, Ld, I32) // non-volatile 8-bit integer load, zero-extended to 32-bit -OP___(ldcs, 33, Ld, I32) // non-volatile 16-bit integer load, zero-extended to 32-bit -OP___(ldc, 34, Ld, I32) // non-volatile 32-bit integer load, zero-extended to 32-bit +OP___(ldcb, 32, Ld, I32, 1) // non-volatile 8-bit integer load, zero-extended to 32-bit +OP___(ldcs, 33, Ld, I32, 1) // non-volatile 16-bit integer load, zero-extended to 32-bit +OP___(ldc, 34, Ld, I32, 1) // non-volatile 32-bit integer load, zero-extended to 32-bit -OP___(neg, 35, Op1, I32) // 32-bit integer negation -OP___(add, 36, Op2, I32) // 32-bit integer addition -OP___(sub, 37, Op2, I32) // 32-bit integer subtraction -OP___(mul, 38, Op2, I32) // 32-bit integer multiplication -OP_86(div, 39, Op2, I32) // 32-bit integer division +OP___(neg, 35, Op1, I32, 1) // 32-bit integer negation +OP___(add, 36, Op2, I32, 1) // 32-bit integer addition +OP___(sub, 37, Op2, I32, 1) // 32-bit integer subtraction +OP___(mul, 38, Op2, I32, 1) // 32-bit integer multiplication +OP_86(div, 39, Op2, I32, 1) // 32-bit integer division // LIR_mod is a hack. It's only used on i386/X64. The operand is the result // of a LIR_div because on i386/X64 div and mod results are computed by the // same instruction. -OP_86(mod, 40, Op1, I32) // 32-bit integer modulus +OP_86(mod, 40, Op1, I32, 1) // 32-bit integer modulus -OP___(and, 41, Op2, I32) // 32-bit bitwise AND -OP___(or, 42, Op2, I32) // 32-bit bitwise OR -OP___(xor, 43, Op2, I32) // 32-bit bitwise XOR -OP___(not, 44, Op1, I32) // 32-bit bitwise NOT -OP___(lsh, 45, Op2, I32) // 32-bit left shift -OP___(rsh, 46, Op2, I32) // 32-bit right shift with sign-extend (>>) -OP___(ush, 47, Op2, I32) // 32-bit unsigned right shift (>>>) +OP___(and, 41, Op2, I32, 1) // 32-bit bitwise AND +OP___(or, 42, Op2, I32, 1) // 32-bit bitwise OR +OP___(xor, 43, Op2, I32, 1) // 32-bit bitwise XOR +OP___(not, 44, Op1, I32, 1) // 32-bit bitwise NOT +OP___(lsh, 45, Op2, I32, 1) // 32-bit left shift +OP___(rsh, 46, Op2, I32, 1) // 32-bit right shift with sign-extend (>>) +OP___(ush, 47, Op2, I32, 1) // 32-bit unsigned right shift (>>>) -// Conditional guards, op^1 to complement. Only things that are -// isCond() can be passed to these. -OP___(xt, 48, Op2, Void) // exit if true (0x30 0011 0000) -OP___(xf, 49, Op2, Void) // exit if false (0x31 0011 0001) +// Conditional guards. 'xt' and 'xf' must be adjacent so that (op ^ 1) gives +// the opposite one. Static assertions in LIR.h check this requirement. +OP___(xt, 48, Op2, Void, 1) // exit if true (0x30 0011 0000) +OP___(xf, 49, Op2, Void, 1) // exit if false (0x31 0011 0001) -OP_SF(qlo, 50, Op1, I32) // get the low 32 bits of a 64-bit value -OP_SF(qhi, 51, Op1, I32) // get the high 32 bits of a 64-bit value +OP_SF(qlo, 50, Op1, I32, 1) // get the low 32 bits of a 64-bit value +OP_SF(qhi, 51, Op1, I32, 1) // get the high 32 bits of a 64-bit value -OP___(ldcsb, 52, Ld, I32) // non-volatile 8-bit integer load, sign-extended to 32-bit -OP___(ldcss, 53, Ld, I32) // non-volatile 16-bit integer load, sign-extended to 32-bit +OP___(ldcsb, 52, Ld, I32, 1) // non-volatile 8-bit integer load, sign-extended to 32-bit +OP___(ldcss, 53, Ld, I32, 1) // non-volatile 16-bit integer load, sign-extended to 32-bit -OP___(addxov, 54, Op3, I32) // 32-bit integer addition; exit if overflow occurred, result is valid on either path -OP___(subxov, 55, Op3, I32) // 32-bit integer subtraction; exit if overflow occurred, result is valid on either path -OP___(mulxov, 56, Op3, I32) // 32-bit integer multiplication; exit if overflow occurred, result is valid on either path +OP___(addxov, 54, Op3, I32, 1) // 32-bit integer addition; exit if overflow occurred, result is valid on either path +OP___(subxov, 55, Op3, I32, 1) // 32-bit integer subtraction; exit if overflow occurred, result is valid on either path +OP___(mulxov, 56, Op3, I32, 1) // 32-bit integer multiplication; exit if overflow occurred, result is valid on either path -// Integer (32-bit) relational operators. (op ^ 1) is the op which flips the -// left and right sides of the comparison, so (lt ^ 1) == gt, or the operator -// "<" is xored with 1 to get ">". 'u' prefix indicates the unsigned integer -// variant. -// NB: These opcodes must remain continuous so that comparison-opcode detection -// works correctly. -OP___(eq, 57, Op2, I32) // integer equality -OP___(lt, 58, Op2, I32) // signed integer less-than (0x38 0011 1000) -OP___(gt, 59, Op2, I32) // signed integer greater-than (0x39 0011 1001) -OP___(le, 60, Op2, I32) // signed integer less-than-or-equal (0x3A 0011 1010) -OP___(ge, 61, Op2, I32) // signed integer greater-than-or-equal (0x3B 0011 1011) -OP___(ult, 62, Op2, I32) // unsigned integer less-than (0x3C 0011 1100) -OP___(ugt, 63, Op2, I32) // unsigned integer greater-than (0x3D 0011 1101) -OP___(ule, 64, Op2, I32) // unsigned integer less-than-or-equal (0x3E 0011 1110) -OP___(uge, 65, Op2, I32) // unsigned integer greater-than-or-equal (0x3F 0011 1111) +// 32-bit integer comparisons. Their order must be preserved so that, except +// for 'eq', (op ^ 1) gives the opposite one (eg. lt ^ 1 == gt). They must +// also remain contiguous so that opcode range checking works correctly. +// Static assertions in LIR.h check these requirements. +OP___(eq, 57, Op2, I32, 1) // integer equality +OP___(lt, 58, Op2, I32, 1) // signed integer less-than (0x38 0011 1000) +OP___(gt, 59, Op2, I32, 1) // signed integer greater-than (0x39 0011 1001) +OP___(le, 60, Op2, I32, 1) // signed integer less-than-or-equal (0x3A 0011 1010) +OP___(ge, 61, Op2, I32, 1) // signed integer greater-than-or-equal (0x3B 0011 1011) +OP___(ult, 62, Op2, I32, 1) // unsigned integer less-than (0x3C 0011 1100) +OP___(ugt, 63, Op2, I32, 1) // unsigned integer greater-than (0x3D 0011 1101) +OP___(ule, 64, Op2, I32, 1) // unsigned integer less-than-or-equal (0x3E 0011 1110) +OP___(uge, 65, Op2, I32, 1) // unsigned integer greater-than-or-equal (0x3F 0011 1111) -OP___(file, 66, Op1, Void) // source filename for debug symbols -OP___(line, 67, Op1, Void) // source line number for debug symbols +OP___(file, 66, Op1, Void, 0) // source filename for debug symbols +OP___(line, 67, Op1, Void, 0) // source line number for debug symbols -OP___(xbarrier, 68, Op2, Void) // memory barrier; doesn't exit, but flushes all values to the stack -OP___(xtbl, 69, Op2, Void) // exit via indirect jump +OP___(xbarrier, 68, Op2, Void, 0) // memory barrier; doesn't exit, but flushes all values to the stack +OP___(xtbl, 69, Op2, Void, 0) // exit via indirect jump -OP_64(qlive, 70, Op1, Void) // extend live range of a 64-bit integer +OP_64(qlive, 70, Op1, Void, 0) // extend live range of a 64-bit integer -OP_64(qaddp, 71, Op2, I64) // 64-bit integer addition for temp pointer calculations -OP_64(qparam, 72, P, I64) // load a parameter (64bit register or stack location) +OP_64(qaddp, 71, Op2, I64, 0) // 64-bit integer addition for temp pointer calculations +OP_64(qparam, 72, P, I64, 0) // load a parameter (64bit register or stack location) -OP___(ldf, 73, Ld, F64) // 64-bit float load -OP_64(ldq, 74, Ld, I64) // 64-bit integer load +OP___(ldf, 73, Ld, F64, 0) // 64-bit float load +OP_64(ldq, 74, Ld, I64, 0) // 64-bit integer load -OP_64(qalloc, 75, I, I64) // allocate some stack space (result is a 64-bit address) +OP_64(qalloc, 75, I, I64, 0) // allocate some stack space (result is a 64-bit address) -OP_64(stqi, 76, Sti, Void) // 64-bit integer store +OP_64(stqi, 76, Sti, Void, 0) // 64-bit integer store -OP___(st32f, 77, Sti, Void) // store 64-bit float as a 32-bit float (dropping precision) -OP___(ld32f, 78, Ld, F64) // load 32-bit float and widen to 64-bit float +OP___(st32f, 77, Sti, Void, 0) // store 64-bit float as a 32-bit float (dropping precision) +OP___(ld32f, 78, Ld, F64, 0) // load 32-bit float and widen to 64-bit float -OP___(fcall, 79, C, F64) // subroutine call returning 64-bit float value -OP_64(qcall, 80, C, I64) // subroutine call returning 64-bit integer value +OP___(fcall, 79, C, F64, -1) // subroutine call returning 64-bit float value +OP_64(qcall, 80, C, I64, -1) // subroutine call returning 64-bit integer value -OP___(stfi, 81, Sti, Void) // 64-bit float store +OP___(stfi, 81, Sti, Void, 0) // 64-bit float store -OP___(fret, 82, Op1, Void) // return a 64-bit float -OP_64(qret, 83, Op1, Void) // return a 64-bit integer +OP___(fret, 82, Op1, Void, 0) // return a 64-bit float +OP_64(qret, 83, Op1, Void, 0) // return a 64-bit integer -OP___(__84, 84, None, Void) -OP___(__85, 85, None, Void) -OP___(__86, 86, None, Void) -OP___(__87, 87, None, Void) +OP_UN(84) +OP_UN(85) +OP_UN(86) +OP_UN(87) -// All opcodes below this marker are subject to CSE. +OP_64(quad, 88, N64, I64, 1) // 64-bit integer constant value +OP_64(qcmov, 89, Op3, I64, 1) // 64-bit conditional move -OP_64(quad, 88, N64, I64) // 64-bit integer constant value -OP_64(qcmov, 89, Op3, I64) // 64-bit conditional move +OP_64(i2q, 90, Op1, I64, 1) // sign-extend i32 to i64 +OP_64(u2q, 91, Op1, I64, 1) // zero-extend u32 to u64 +OP___(i2f, 92, Op1, F64, 1) // convert a signed 32-bit integer to a float +OP___(u2f, 93, Op1, F64, 1) // convert an unsigned 32-bit integer to a float +OP___(f2i, 94, Op1, I32, 1) // f2i conversion, no exception raised, platform rounding rules. -OP_64(i2q, 90, Op1, I64) // sign-extend i32 to i64 -OP_64(u2q, 91, Op1, I64) // zero-extend u32 to u64 -OP___(i2f, 92, Op1, F64) // convert a signed 32-bit integer to a float -OP___(u2f, 93, Op1, F64) // convert an unsigned 32-bit integer to a float -OP___(f2i, 94, Op1, I32) // f2i conversion, no exception raised, platform rounding rules. +OP_UN(95) +OP_UN(96) -OP___(__95, 95, None, Void) -OP___(__96, 96, None, Void) +OP___(ldfc, 97, Ld, F64, 1) // non-volatile 64-bit float load +OP_64(ldqc, 98, Ld, I64, 1) // non-volatile 64-bit integer load -OP___(ldfc, 97, Ld, F64) // non-volatile 64-bit float load -OP_64(ldqc, 98, Ld, I64) // non-volatile 64-bit integer load - -OP___(fneg, 99, Op1, F64) // floating-point negation -OP___(fadd, 100, Op2, F64) // floating-point addition -OP___(fsub, 101, Op2, F64) // floating-point subtraction -OP___(fmul, 102, Op2, F64) // floating-point multiplication -OP___(fdiv, 103, Op2, F64) // floating-point division -// LIR_fmod is just a place-holder opcode, eg. the back-ends cannot generate +OP___(fneg, 99, Op1, F64, 1) // floating-point negation +OP___(fadd, 100, Op2, F64, 1) // floating-point addition +OP___(fsub, 101, Op2, F64, 1) // floating-point subtraction +OP___(fmul, 102, Op2, F64, 1) // floating-point multiplication +OP___(fdiv, 103, Op2, F64, 1) // floating-point division +// LIR_fmod is just a place-holder opcode, ie. the back-ends cannot generate // code for it. It's used in TraceMonkey briefly but is always demoted to a // LIR_mod or converted to a function call before Nanojit has to do anything // serious with it. -OP___(fmod, 104, Op2, F64) // floating-point modulus +OP___(fmod, 104, Op2, F64, 1) // floating-point modulus -OP_64(qiand, 105, Op2, I64) // 64-bit bitwise AND -OP_64(qior, 106, Op2, I64) // 64-bit bitwise OR -OP_64(qxor, 107, Op2, I64) // 64-bit bitwise XOR -OP___(__108, 108, None, Void) -OP_64(qilsh, 109, Op2, I64) // 64-bit left shift; 2nd operand is a 32-bit integer -OP_64(qirsh, 110, Op2, I64) // 64-bit signed right shift; 2nd operand is a 32-bit integer -OP_64(qursh, 111, Op2, I64) // 64-bit unsigned right shift; 2nd operand is a 32-bit integer -OP_64(qiadd, 112, Op2, I64) // 64-bit bitwise ADD +OP_64(qiand, 105, Op2, I64, 1) // 64-bit bitwise AND +OP_64(qior, 106, Op2, I64, 1) // 64-bit bitwise OR +OP_64(qxor, 107, Op2, I64, 1) // 64-bit bitwise XOR +OP_UN(108) +OP_64(qilsh, 109, Op2, I64, 1) // 64-bit left shift; 2nd operand is a 32-bit integer +OP_64(qirsh, 110, Op2, I64, 1) // 64-bit signed right shift; 2nd operand is a 32-bit integer +OP_64(qursh, 111, Op2, I64, 1) // 64-bit unsigned right shift; 2nd operand is a 32-bit integer +OP_64(qiadd, 112, Op2, I64, 1) // 64-bit bitwise ADD -OP___(ldc32f, 113, Ld, F64) // non-volatile load 32-bit float and widen to 64-bit float -OP_SF(qjoin, 114, Op2, F64) // join two 32-bit values (1st arg is low bits, 2nd is high) -OP_64(q2i, 115, Op1, I32) // truncate i64 to i32 -OP___(__116, 116, None, Void) -OP___(__117, 117, None, Void) -OP___(float, 118, N64, F64) // 64-bit float constant value +OP___(ldc32f, 113, Ld, F64, 1) // non-volatile load 32-bit float and widen to 64-bit float +OP_SF(qjoin, 114, Op2, F64, 1) // join two 32-bit values (1st arg is low bits, 2nd is high) +OP_64(q2i, 115, Op1, I32, 1) // truncate i64 to i32 +OP_UN(116) +OP_UN(117) +OP___(float, 118, N64, F64, 1) // 64-bit float constant value -// Integer (64-bit) relational operators. -// NB: These opcodes must remain continuous so that comparison-opcode detection -// works correctly. -OP_64(qeq, 119, Op2, I32) // integer equality -OP_64(qlt, 120, Op2, I32) // signed integer less-than (0x78 0111 1000) -OP_64(qgt, 121, Op2, I32) // signed integer greater-than (0x79 0111 1001) -OP_64(qle, 122, Op2, I32) // signed integer less-than-or-equal (0x7A 0111 1010) -OP_64(qge, 123, Op2, I32) // signed integer greater-than-or-equal (0x7B 0111 1011) -OP_64(qult, 124, Op2, I32) // unsigned integer less-than (0x7C 0111 1100) -OP_64(qugt, 125, Op2, I32) // unsigned integer greater-than (0x7D 0111 1101) -OP_64(qule, 126, Op2, I32) // unsigned integer less-than-or-equal (0x7E 0111 1110) -OP_64(quge, 127, Op2, I32) // unsigned integer greater-than-or-equal (0x7F 0111 1111) +// 64-bit integer comparisons. Their order must be preserved so that, except +// for 'qeq', (op ^ 1) gives the opposite one (eg. qlt ^ 1 == qgt). They must +// also remain contiguous so that opcode range checking works correctly. +// Static assertions in LIR.h check these requirements. +OP_64(qeq, 119, Op2, I32, 1) // integer equality +OP_64(qlt, 120, Op2, I32, 1) // signed integer less-than (0x78 0111 1000) +OP_64(qgt, 121, Op2, I32, 1) // signed integer greater-than (0x79 0111 1001) +OP_64(qle, 122, Op2, I32, 1) // signed integer less-than-or-equal (0x7A 0111 1010) +OP_64(qge, 123, Op2, I32, 1) // signed integer greater-than-or-equal (0x7B 0111 1011) +OP_64(qult, 124, Op2, I32, 1) // unsigned integer less-than (0x7C 0111 1100) +OP_64(qugt, 125, Op2, I32, 1) // unsigned integer greater-than (0x7D 0111 1101) +OP_64(qule, 126, Op2, I32, 1) // unsigned integer less-than-or-equal (0x7E 0111 1110) +OP_64(quge, 127, Op2, I32, 1) // unsigned integer greater-than-or-equal (0x7F 0111 1111) +#undef OP_UN #undef OP_32 #undef OP_64 #undef OP_SF diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index d33c70825ac4..c1f580784a27 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -2135,8 +2135,6 @@ Assembler::asm_fop(LInsp ins) LInsp rhs = ins->oprnd2(); LOpcode op = ins->opcode(); - NanoAssert(op >= LIR_fadd && op <= LIR_fdiv); - // rr = ra OP rb Register rr = deprecated_prepResultReg(ins, FpRegs); @@ -2163,7 +2161,7 @@ Assembler::asm_fcmp(LInsp ins) LInsp rhs = ins->oprnd2(); LOpcode op = ins->opcode(); - NanoAssert(op >= LIR_feq && op <= LIR_fge); + NanoAssert(isFCmpOpcode(op)); Register ra, rb; findRegFor2(FpRegs, lhs, ra, FpRegs, rhs, rb); @@ -2183,7 +2181,7 @@ Assembler::asm_branch(bool branchOnFalse, LInsp cond, NIns* targ) { LOpcode condop = cond->opcode(); NanoAssert(cond->isCmp()); - NanoAssert(_config.arm_vfp || ((condop < LIR_feq) || (condop > LIR_fge))); + NanoAssert(_config.arm_vfp || !isFCmpOpcode(condop)); // The old "never" condition code has special meaning on newer ARM cores, // so use "always" as a sensible default code. diff --git a/js/src/nanojit/NativeMIPS.cpp b/js/src/nanojit/NativeMIPS.cpp index c7830bf569ea..37d90bbfac34 100644 --- a/js/src/nanojit/NativeMIPS.cpp +++ b/js/src/nanojit/NativeMIPS.cpp @@ -603,8 +603,6 @@ namespace nanojit LInsp rhs = ins->oprnd2(); LOpcode op = ins->opcode(); - NanoAssert(op >= LIR_fadd && op <= LIR_fdiv); - // rr = ra OP rb Register rr = deprecated_prepResultReg(ins, FpRegs); @@ -1175,7 +1173,7 @@ namespace nanojit void Assembler::asm_cmp(LOpcode condop, LIns *a, LIns *b, Register cr) { - RegisterMask allow = condop >= LIR_feq && condop <= LIR_fge ? FpRegs : GpRegs; + RegisterMask allow = isFCmpOpcode(condop) ? FpRegs : GpRegs; Register ra = findRegFor(a, allow); Register rb = (b==a) ? ra : findRegFor(b, allow & ~rmask(ra)); @@ -1244,7 +1242,7 @@ namespace nanojit LOpcode condop = cond->opcode(); NanoAssert(cond->isCond()); bool inrange; - RegisterMask allow = condop >= LIR_feq && condop <= LIR_fge ? FpRegs : GpRegs; + RegisterMask allow = isFCmpOpcode(condop) ? FpRegs : GpRegs; LIns *a = cond->oprnd1(); LIns *b = cond->oprnd2(); Register ra = findRegFor(a, allow); @@ -1319,7 +1317,7 @@ namespace nanojit } NIns *patch = NULL; - if (cpu_has_fpu && (condop >= LIR_feq && condop <= LIR_fge)) { + if (cpu_has_fpu && isFCmpOpcode(condop)) { // c.xx.d $ra,$rb // bc1x btarg switch (condop) { diff --git a/js/src/nanojit/NativePPC.cpp b/js/src/nanojit/NativePPC.cpp index 7b84bb7380c8..1c997c48a1dd 100644 --- a/js/src/nanojit/NativePPC.cpp +++ b/js/src/nanojit/NativePPC.cpp @@ -540,19 +540,19 @@ namespace nanojit } void Assembler::asm_cmp(LOpcode condop, LIns *a, LIns *b, ConditionRegister cr) { - RegisterMask allow = condop >= LIR_feq && condop <= LIR_fge ? FpRegs : GpRegs; + RegisterMask allow = isFCmpOpcode(condop) ? FpRegs : GpRegs; Register ra = findRegFor(a, allow); #if !PEDANTIC if (b->isconst()) { int32_t d = b->imm32(); if (isS16(d)) { - if (condop >= LIR_eq && condop <= LIR_ge) { + if (isSICmpOpcode(condop)) { CMPWI(cr, ra, d); return; } #if defined NANOJIT_64BIT - if (condop >= LIR_qeq && condop <= LIR_qge) { + if (isSQCmpOpcode(condop)) { CMPDI(cr, ra, d); TODO(cmpdi); return; @@ -560,12 +560,12 @@ namespace nanojit #endif } if (isU16(d)) { - if ((condop == LIR_eq || condop >= LIR_ult && condop <= LIR_uge)) { + if (isUICmpOpcode(condop)) { CMPLWI(cr, ra, d); return; } #if defined NANOJIT_64BIT - if ((condop == LIR_qeq || condop >= LIR_qult && condop <= LIR_quge)) { + if (isUQCmpOpcode(condop)) { CMPLDI(cr, ra, d); TODO(cmpldi); return; @@ -577,21 +577,21 @@ namespace nanojit // general case Register rb = b==a ? ra : findRegFor(b, allow & ~rmask(ra)); - if (condop >= LIR_eq && condop <= LIR_ge) { + if (isSICmpOpcode(condop)) { CMPW(cr, ra, rb); } - else if (condop >= LIR_ult && condop <= LIR_uge) { + else if (isUICmpOpcode(condop)) { CMPLW(cr, ra, rb); } #if defined NANOJIT_64BIT - else if (condop >= LIR_qeq && condop <= LIR_qge) { + else if (isSQCmpOpcode(condop)) { CMPD(cr, ra, rb); } - else if (condop >= LIR_qult && condop <= LIR_quge) { + else if (isUQCmpOpcode(condop)) { CMPLD(cr, ra, rb); } #endif - else if (condop >= LIR_feq && condop <= LIR_fge) { + else if (isFCmpOpcode(condop)) { // set the lt/gt bit for fle/fge. We don't do this for // int/uint because in those cases we can invert the branch condition. // for float, we can't because of unordered comparisons diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 50811e400936..924445b7905c 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -458,7 +458,7 @@ namespace nanojit NIns* at = 0; LOpcode condop = cond->opcode(); NanoAssert(cond->isCmp()); - if (condop >= LIR_feq && condop <= LIR_fge) + if (isFCmpOpcode(condop)) { return asm_fbranch(branchOnFalse, cond, targ); } @@ -574,7 +574,7 @@ namespace nanojit Register r = deprecated_prepResultReg(ins, AllowableFlagRegs); underrunProtect(8); LOpcode condop = ins->opcode(); - NanoAssert(condop >= LIR_feq && condop <= LIR_fge); + NanoAssert(isFCmpOpcode(condop)); if (condop == LIR_feq) MOVFEI(1, 0, 0, 0, r); else if (condop == LIR_fle) @@ -932,7 +932,7 @@ namespace nanojit { NIns *at = 0; LOpcode condop = cond->opcode(); - NanoAssert(condop >= LIR_feq && condop <= LIR_fge); + NanoAssert(isFCmpOpcode(condop)); underrunProtect(32); intptr_t tt = ((intptr_t)targ - (intptr_t)_nIns + 8) >> 2; // !targ means that it needs patch. diff --git a/js/src/nanojit/NativeX64.cpp b/js/src/nanojit/NativeX64.cpp index 883b15813efc..6cab6ac007de 100644 --- a/js/src/nanojit/NativeX64.cpp +++ b/js/src/nanojit/NativeX64.cpp @@ -1129,7 +1129,7 @@ namespace nanojit } NanoAssert(cond->isCmp()); LOpcode condop = cond->opcode(); - if (condop >= LIR_feq && condop <= LIR_fge) + if (isFCmpOpcode(condop)) return asm_fbranch(onFalse, cond, target); // We must ensure there's room for the instruction before calculating @@ -1228,10 +1228,10 @@ namespace nanojit } LOpcode condop = cond->opcode(); - if (LIR_qeq <= condop && condop <= LIR_quge) { + if (isQCmpOpcode(condop)) { CMPQR(ra, rb); } else { - NanoAssert(LIR_eq <= condop && condop <= LIR_uge); + NanoAssert(isICmpOpcode(condop)); CMPLR(ra, rb); } } @@ -1242,13 +1242,13 @@ namespace nanojit LIns *b = cond->oprnd2(); Register ra = findRegFor(a, GpRegs); int32_t imm = getImm32(b); - if (LIR_qeq <= condop && condop <= LIR_quge) { + if (isQCmpOpcode(condop)) { if (isS8(imm)) CMPQR8(ra, imm); else CMPQRI(ra, imm); } else { - NanoAssert(LIR_eq <= condop && condop <= LIR_uge); + NanoAssert(isICmpOpcode(condop)); if (isS8(imm)) CMPLR8(ra, imm); else diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index a06dc2a05fc2..0e0e8cfebe64 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -657,7 +657,7 @@ namespace nanojit NanoAssert(cond->isCmp()); // Handle float conditions separately. - if (condop >= LIR_feq && condop <= LIR_fge) { + if (isFCmpOpcode(condop)) { return asm_fbranch(branchOnFalse, cond, targ); } @@ -1730,7 +1730,7 @@ namespace nanojit void Assembler::asm_fcmp(LIns *cond) { LOpcode condop = cond->opcode(); - NanoAssert(condop >= LIR_feq && condop <= LIR_fge); + NanoAssert(isFCmpOpcode(condop)); LIns* lhs = cond->oprnd1(); LIns* rhs = cond->oprnd2(); NanoAssert(lhs->isF64() && rhs->isF64()); From 73ff20e7a7b9ffc04cf58c5c2aa89b793938457d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 12:09:04 +1100 Subject: [PATCH 10/52] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index c76d75a9f390..d3df1fd3e5e6 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -6fb5f71fba861a333e17de644fe49de60bb7a1bd +a5291bc7b0cef4f41f4180db6388edebdbb4c208 From b92fe22fa9a3a8903615a481dca9754e3c8b3134 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 12:16:38 +1100 Subject: [PATCH 11/52] Bug 542932 - nanojit: make opcode range checks safer (TM-specific part). r=gal. --- js/src/jstracer.cpp | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 18758e286594..7a818080288e 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1715,7 +1715,7 @@ public: return insImm(1); } } - } else if (LIR_feq <= v && v <= LIR_fge) { + } else if (isFCmpOpcode(v)) { if (isPromoteInt(s0) && isPromoteInt(s1)) { // demote fcmp to cmp v = LOpcode(v + (LIR_eq - LIR_feq)); @@ -8845,7 +8845,7 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond) * compare. */ if (!fp) { - JS_ASSERT(op >= LIR_feq && op <= LIR_fge); + JS_ASSERT(isFCmpOpcode(op)); op = LOpcode(op + (LIR_eq - LIR_feq)); } x = lir->ins2(op, l_ins, r_ins); @@ -8925,23 +8925,19 @@ TraceRecorder::binary(LOpcode op) bool rightIsNumber = isNumber(r); jsdouble rnum = rightIsNumber ? asNumber(r) : 0; - if ((op >= LIR_sub && op <= LIR_ush) || // sub, mul, (callh), or, xor, (not,) lsh, rsh, ush - (op >= LIR_fsub && op <= LIR_fmod)) { // fsub, fmul, fdiv, fmod - LIns* args[2]; - if (JSVAL_IS_STRING(l)) { - args[0] = a; - args[1] = cx_ins; - a = lir->insCall(&js_StringToNumber_ci, args); - lnum = js_StringToNumber(cx, JSVAL_TO_STRING(l)); - leftIsNumber = true; - } - if (JSVAL_IS_STRING(r)) { - args[0] = b; - args[1] = cx_ins; - b = lir->insCall(&js_StringToNumber_ci, args); - rnum = js_StringToNumber(cx, JSVAL_TO_STRING(r)); - rightIsNumber = true; - } + if (JSVAL_IS_STRING(l)) { + NanoAssert(op != LIR_fadd); // LIR_fadd/IS_STRING case handled by record_JSOP_ADD() + LIns* args[] = { a, cx_ins }; + a = lir->insCall(&js_StringToNumber_ci, args); + lnum = js_StringToNumber(cx, JSVAL_TO_STRING(l)); + leftIsNumber = true; + } + if (JSVAL_IS_STRING(r)) { + NanoAssert(op != LIR_fadd); // LIR_fadd/IS_STRING case handled by record_JSOP_ADD() + LIns* args[] = { b, cx_ins }; + b = lir->insCall(&js_StringToNumber_ci, args); + rnum = js_StringToNumber(cx, JSVAL_TO_STRING(r)); + rightIsNumber = true; } if (JSVAL_IS_SPECIAL(l)) { LIns* args[] = { a, cx_ins }; From 42d9dea463ea4bd354597a9a1eddd6b2de7cc64c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 14:57:19 +1100 Subject: [PATCH 12/52] Bug 535705 - nanojit: finish regstate update fixes for i386. r=edwsmith. --HG-- extra : convert_revision : 05949faa5b451d5452c9b5eb95296a53b555dda1 --- js/src/nanojit/Assembler.cpp | 18 +- js/src/nanojit/Assembler.h | 2 +- js/src/nanojit/NativeARM.cpp | 41 ++- js/src/nanojit/NativeARM.h | 2 +- js/src/nanojit/NativeMIPS.cpp | 18 +- js/src/nanojit/NativeMIPS.h | 2 +- js/src/nanojit/NativePPC.cpp | 6 +- js/src/nanojit/NativePPC.h | 2 +- js/src/nanojit/NativeSparc.h | 2 +- js/src/nanojit/Nativei386.cpp | 520 ++++++++++++++++++---------------- js/src/nanojit/Nativei386.h | 2 +- 11 files changed, 324 insertions(+), 291 deletions(-) diff --git a/js/src/nanojit/Assembler.cpp b/js/src/nanojit/Assembler.cpp index a909caf3dbad..9921930521d5 100755 --- a/js/src/nanojit/Assembler.cpp +++ b/js/src/nanojit/Assembler.cpp @@ -417,23 +417,23 @@ namespace nanojit // optimize the LIR_alloc case by indexing off FP, thus saving the use of // a GpReg. // - Register Assembler::getBaseReg(LIns *i, int &d, RegisterMask allow) + Register Assembler::getBaseReg(LInsp base, int &d, RegisterMask allow) { #if !PEDANTIC - if (i->isop(LIR_alloc)) { + if (base->isop(LIR_alloc)) { // The value of a LIR_alloc is a pointer to its stack memory, // which is always relative to FP. So we can just return FP if we // also adjust 'd' (and can do so in a valid manner). Or, in the // PEDANTIC case, we can just assign a register as normal; // findRegFor() will allocate the stack memory for LIR_alloc if // necessary. - d += findMemFor(i); + d += findMemFor(base); return FP; } #else (void) d; #endif - return findRegFor(i, allow); + return findRegFor(base, allow); } // Like findRegFor2(), but used for stores where the base value has the @@ -2086,13 +2086,13 @@ namespace nanojit } /** - * move regs around so the SavedRegs contains the highest priority regs. + * Move regs around so the SavedRegs contains the highest priority regs. */ void Assembler::evictScratchRegsExcept(RegisterMask ignore) { - // find the top GpRegs that are candidates to put in SavedRegs + // Find the top GpRegs that are candidates to put in SavedRegs. - // tosave is a binary heap stored in an array. the root is tosave[0], + // 'tosave' is a binary heap stored in an array. The root is tosave[0], // left child is at i+1, right child is at i+2. Register tosave[LastReg-FirstReg+1]; @@ -2121,8 +2121,8 @@ namespace nanojit } } - // now primap has the live exprs in priority order. - // allocate each of the top priority exprs to a SavedReg + // Now primap has the live exprs in priority order. + // Allocate each of the top priority exprs to a SavedReg. RegisterMask allow = SavedRegs; while (allow && len > 0) { diff --git a/js/src/nanojit/Assembler.h b/js/src/nanojit/Assembler.h index e1d226b6a3c5..9f0f0a310483 100644 --- a/js/src/nanojit/Assembler.h +++ b/js/src/nanojit/Assembler.h @@ -368,7 +368,7 @@ namespace nanojit verbose_only(, size_t &nBytes)); bool canRemat(LIns*); - bool isKnownReg(Register r) { + bool deprecated_isKnownReg(Register r) { return r != deprecated_UnknownReg; } diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index c1f580784a27..aac2ce43cd83 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -634,7 +634,7 @@ Assembler::asm_arg_64(LInsp arg, Register& r, int& stkd) if (_config.arm_vfp) { fp_reg = findRegFor(arg, FpRegs); - NanoAssert(isKnownReg(fp_reg)); + NanoAssert(deprecated_isKnownReg(fp_reg)); } #ifdef NJ_ARM_EABI @@ -722,7 +722,7 @@ Assembler::asm_arg_64(LInsp arg, Register& r, int& stkd) void Assembler::asm_regarg(ArgSize sz, LInsp p, Register r) { - NanoAssert(isKnownReg(r)); + NanoAssert(deprecated_isKnownReg(r)); if (sz & ARGSIZE_MASK_INT) { // arg goes in specific register @@ -765,7 +765,7 @@ Assembler::asm_stkarg(LInsp arg, int stkd) bool isF64 = arg->isF64(); Register rr; - if (arg->isUsed() && (rr = arg->deprecated_getReg(), isKnownReg(rr))) { + if (arg->isUsed() && (rr = arg->deprecated_getReg(), deprecated_isKnownReg(rr))) { // The argument resides somewhere in registers, so we simply need to // push it onto the stack. if (!_config.arm_vfp || !isF64) { @@ -872,7 +872,7 @@ Assembler::asm_call(LInsp ins) NanoAssert(ins->opcode() == LIR_fcall); - if (!isKnownReg(rr)) { + if (!deprecated_isKnownReg(rr)) { int d = deprecated_disp(ins); NanoAssert(d != 0); deprecated_freeRsrcOf(ins, false); @@ -1327,7 +1327,7 @@ Assembler::asm_load64(LInsp ins) switch (ins->opcode()) { case LIR_ldf: case LIR_ldfc: - if (_config.arm_vfp && isKnownReg(rr)) { + if (_config.arm_vfp && deprecated_isKnownReg(rr)) { // VFP is enabled and the result will go into a register. NanoAssert(IsFpReg(rr)); @@ -1341,7 +1341,7 @@ Assembler::asm_load64(LInsp ins) // Either VFP is not available or the result needs to go into memory; // in either case, VFP instructions are not required. Note that the // result will never be loaded into registers if VFP is not available. - NanoAssert(!isKnownReg(rr)); + NanoAssert(!deprecated_isKnownReg(rr)); NanoAssert(d != 0); // Check that the offset is 8-byte (64-bit) aligned. @@ -1355,7 +1355,7 @@ Assembler::asm_load64(LInsp ins) case LIR_ld32f: case LIR_ldc32f: if (_config.arm_vfp) { - if (isKnownReg(rr)) { + if (deprecated_isKnownReg(rr)) { NanoAssert(IsFpReg(rr)); FCVTDS(rr, S14); } else { @@ -1415,8 +1415,8 @@ Assembler::asm_store64(LOpcode op, LInsp value, int dr, LInsp base) Register rv = findRegFor(value, FpRegs); - NanoAssert(isKnownReg(rb)); - NanoAssert(isKnownReg(rv)); + NanoAssert(deprecated_isKnownReg(rb)); + NanoAssert(deprecated_isKnownReg(rv)); Register baseReg = rb; intptr_t baseOffset = dr; @@ -1464,8 +1464,8 @@ Assembler::asm_store64(LOpcode op, LInsp value, int dr, LInsp base) Register rv = findRegFor(value, FpRegs); - NanoAssert(isKnownReg(rb)); - NanoAssert(isKnownReg(rv)); + NanoAssert(deprecated_isKnownReg(rb)); + NanoAssert(deprecated_isKnownReg(rv)); Register baseReg = rb; intptr_t baseOffset = dr; @@ -1535,8 +1535,7 @@ Assembler::asm_quad(LInsp ins) deprecated_freeRsrcOf(ins, false); - if (_config.arm_vfp && isKnownReg(rr)) - { + if (_config.arm_vfp && deprecated_isKnownReg(rr)) { asm_spill(rr, d, false, true); underrunProtect(4*4); @@ -2086,7 +2085,7 @@ Assembler::asm_i2f(LInsp ins) Register srcr = findRegFor(ins->oprnd1(), GpRegs); // todo: support int value in memory, as per x86 - NanoAssert(isKnownReg(srcr)); + NanoAssert(deprecated_isKnownReg(srcr)); FSITOD(rr, S14); FMSR(S14, srcr); @@ -2099,7 +2098,7 @@ Assembler::asm_u2f(LInsp ins) Register sr = findRegFor(ins->oprnd1(), GpRegs); // todo: support int value in memory, as per x86 - NanoAssert(isKnownReg(sr)); + NanoAssert(deprecated_isKnownReg(sr)); FUITOD(rr, S14); FMSR(S14, sr); @@ -2358,8 +2357,8 @@ Assembler::asm_arith(LInsp ins) : lhs->deprecated_getReg() ); // Don't re-use the registers we've already allocated. - NanoAssert(isKnownReg(rr)); - NanoAssert(isKnownReg(ra)); + NanoAssert(deprecated_isKnownReg(rr)); + NanoAssert(deprecated_isKnownReg(ra)); allow &= ~rmask(rr); allow &= ~rmask(ra); @@ -2382,7 +2381,7 @@ Assembler::asm_arith(LInsp ins) Register rs = deprecated_prepResultReg(ins, allow); int d = findMemFor(lhs) + rhs->imm32(); - NanoAssert(isKnownReg(rs)); + NanoAssert(deprecated_isKnownReg(rs)); asm_add_imm(rs, FP, d); } @@ -2418,11 +2417,11 @@ Assembler::asm_arith(LInsp ins) rb = ra; } else { rb = asm_binop_rhs_reg(ins); - if (!isKnownReg(rb)) + if (!deprecated_isKnownReg(rb)) rb = findRegFor(rhs, allow); allow &= ~rmask(rb); } - NanoAssert(isKnownReg(rb)); + NanoAssert(deprecated_isKnownReg(rb)); const Register SBZ = (Register)0; switch (op) @@ -2536,7 +2535,7 @@ Assembler::asm_neg_not(LInsp ins) Register ra = ( !lhs->isInReg() ? findSpecificRegFor(lhs, rr) : lhs->deprecated_getReg() ); - NanoAssert(isKnownReg(ra)); + NanoAssert(deprecated_isKnownReg(ra)); if (op == LIR_not) MVN(rr, ra); diff --git a/js/src/nanojit/NativeARM.h b/js/src/nanojit/NativeARM.h index 24519ea8aa46..230fc16b2ed8 100644 --- a/js/src/nanojit/NativeARM.h +++ b/js/src/nanojit/NativeARM.h @@ -121,7 +121,7 @@ typedef enum { FirstReg = R0, LastReg = D6, - deprecated_UnknownReg = 32, + deprecated_UnknownReg = 32, // XXX: remove eventually, see bug 538924 S14 = 24 } Register; diff --git a/js/src/nanojit/NativeMIPS.cpp b/js/src/nanojit/NativeMIPS.cpp index 37d90bbfac34..1a3f7e8ad982 100644 --- a/js/src/nanojit/NativeMIPS.cpp +++ b/js/src/nanojit/NativeMIPS.cpp @@ -391,7 +391,7 @@ namespace nanojit void Assembler::asm_regarg(ArgSize sz, LInsp p, Register r) { - NanoAssert(isKnownReg(r)); + NanoAssert(deprecated_isKnownReg(r)); if (sz & ARGSIZE_MASK_INT) { // arg goes in specific register if (p->isconst()) @@ -427,7 +427,7 @@ namespace nanojit { bool isF64 = arg->isF64(); Register rr; - if (arg->isUsed() && (rr = arg->deprecated_getReg(), isKnownReg(rr))) { + if (arg->isUsed() && (rr = arg->deprecated_getReg(), deprecated_isKnownReg(rr))) { // The argument resides somewhere in registers, so we simply need to // push it onto the stack. if (!cpu_has_fpu || !isF64) { @@ -542,7 +542,7 @@ namespace nanojit Register ft = registerAllocTmp(FpRegs & ~(rmask(fr))); // allocate temporary register for constant // todo: support int value in memory, as per x86 - NanoAssert(isKnownReg(v)); + NanoAssert(deprecated_isKnownReg(v)); // mtc1 $v,$ft // bgez $v,1f @@ -642,7 +642,7 @@ namespace nanojit deprecated_freeRsrcOf(ins, false); - if (cpu_has_fpu && isKnownReg(rr)) { + if (cpu_has_fpu && deprecated_isKnownReg(rr)) { asm_spill(rr, d, false, true); asm_li_d(rr, ins->imm64_1(), ins->imm64_0()); } @@ -682,7 +682,7 @@ namespace nanojit NanoAssert(IsGpReg(rbase)); deprecated_freeRsrcOf(ins, false); - if (cpu_has_fpu && isKnownReg(rd)) { + if (cpu_has_fpu && deprecated_isKnownReg(rd)) { NanoAssert(IsFpReg(rd)); asm_ldst64 (false, rd, dr, rbase); } @@ -690,7 +690,7 @@ namespace nanojit // Either FPU is not available or the result needs to go into memory; // in either case, FPU instructions are not required. Note that the // result will never be loaded into registers if FPU is not available. - NanoAssert(!isKnownReg(rd)); + NanoAssert(!deprecated_isKnownReg(rd)); NanoAssert(ds != 0); NanoAssert(isS16(dr) && isS16(dr+4)); @@ -949,8 +949,8 @@ namespace nanojit Register rb; // Don't re-use the registers we've already allocated. - NanoAssert(isKnownReg(rr)); - NanoAssert(isKnownReg(ra)); + NanoAssert(deprecated_isKnownReg(rr)); + NanoAssert(deprecated_isKnownReg(ra)); allow &= ~rmask(rr); allow &= ~rmask(ra); @@ -1018,7 +1018,7 @@ namespace nanojit // general case, put rhs in register rb = (rhs == lhs) ? ra : findRegFor(rhs, allow); - NanoAssert(isKnownReg(rb)); + NanoAssert(deprecated_isKnownReg(rb)); switch (op) { case LIR_add: diff --git a/js/src/nanojit/NativeMIPS.h b/js/src/nanojit/NativeMIPS.h index 289df34112be..d31aae3137a8 100644 --- a/js/src/nanojit/NativeMIPS.h +++ b/js/src/nanojit/NativeMIPS.h @@ -88,7 +88,7 @@ namespace nanojit // Wellknown register names used by code generator FirstReg = ZERO, LastReg = F31, - deprecated_UnknownReg = 127 + deprecated_UnknownReg = 127 // XXX: remove eventually, see bug 538924 } Register; diff --git a/js/src/nanojit/NativePPC.cpp b/js/src/nanojit/NativePPC.cpp index 1c997c48a1dd..fdca2a6bf795 100644 --- a/js/src/nanojit/NativePPC.cpp +++ b/js/src/nanojit/NativePPC.cpp @@ -230,7 +230,7 @@ namespace nanojit LIns* base = ins->oprnd1(); #ifdef NANOJIT_64BIT Register rr = ins->deprecated_getReg(); - if (isKnownReg(rr) && (rmask(rr) & FpRegs)) { + if (deprecated_isKnownReg(rr) && (rmask(rr) & FpRegs)) { // FPR already assigned, fine, use it deprecated_freeRsrcOf(ins, false); } else { @@ -796,7 +796,7 @@ namespace nanojit else if (sz == ARGSIZE_F) { if (p->isUsed()) { Register rp = p->deprecated_getReg(); - if (!isKnownReg(rp) || !IsFpReg(rp)) { + if (!deprecated_isKnownReg(rp) || !IsFpReg(rp)) { // load it into the arg reg int d = findMemFor(p); LFD(r, d, FP); @@ -1039,7 +1039,7 @@ namespace nanojit void Assembler::asm_quad(LIns *ins) { #ifdef NANOJIT_64BIT Register r = ins->deprecated_getReg(); - if (isKnownReg(r) && (rmask(r) & FpRegs)) { + if (deprecated_isKnownReg(r) && (rmask(r) & FpRegs)) { // FPR already assigned, fine, use it deprecated_freeRsrcOf(ins, false); } else { diff --git a/js/src/nanojit/NativePPC.h b/js/src/nanojit/NativePPC.h index db692834c1df..6da77812af02 100644 --- a/js/src/nanojit/NativePPC.h +++ b/js/src/nanojit/NativePPC.h @@ -162,7 +162,7 @@ namespace nanojit Rlr = 8, Rctr = 9, - deprecated_UnknownReg = 127, + deprecated_UnknownReg = 127, // XXX: remove eventually, see bug 538924 FirstReg = R0, LastReg = F31 }; diff --git a/js/src/nanojit/NativeSparc.h b/js/src/nanojit/NativeSparc.h index 828bc741306b..5b0335212259 100644 --- a/js/src/nanojit/NativeSparc.h +++ b/js/src/nanojit/NativeSparc.h @@ -166,7 +166,7 @@ namespace nanojit FirstReg = 0, LastReg = 29, - deprecated_UnknownReg = 30 + deprecated_UnknownReg = 30 // XXX: remove eventually, see bug 538924 } Register; diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index 0e0e8cfebe64..032d318f6be8 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -161,13 +161,10 @@ namespace nanojit void Assembler::asm_call(LInsp ins) { - Register retReg = ( ins->isop(LIR_fcall) ? FST0 : retRegs[0] ); - deprecated_prepResultReg(ins, rmask(retReg)); + Register rr = ( ins->isop(LIR_fcall) ? FST0 : retRegs[0] ); + prepareResultReg(ins, rmask(rr)); - // Do this after we've handled the call result, so we don't - // force the call result to be spilled unnecessarily. - - evictScratchRegsExcept(0); + evictScratchRegsExcept(rmask(rr)); const CallInfo* call = ins->callInfo(); // must be signed, not unsigned @@ -224,15 +221,19 @@ namespace nanojit CALL(call); } else { - // indirect call. x86 Calling conventions don't use EAX as an + // Indirect call. x86 Calling conventions don't use EAX as an // argument, and do use EAX as a return value. We need a register // for the address to call, so we use EAX since it will always be - // available + // available. CALLr(call, EAX); } - // Make sure fpu stack is empty before call (restoreCallerSaved). + // Call this now so that the arg setup can involve 'rr'. + freeResourcesOf(ins); + + // Make sure fpu stack is empty before call. NanoAssert(_allocator.isFree(FST0)); + // Pre-assign registers to the first N 4B args based on the calling convention. uint32_t n = 0; @@ -247,7 +248,7 @@ namespace nanojit stkd = 0; } - for(uint32_t i=0; i < argc; i++) + for (uint32_t i = 0; i < argc; i++) { uint32_t j = argc-i-1; ArgSize sz = sizes[j]; @@ -487,87 +488,73 @@ namespace nanojit LIns* base = ins->oprnd1(); int db = ins->disp(); - Register rr = UnspecifiedReg; // init to shut GCC up - bool inReg = ins->isInReg(); - if (inReg) - rr = ins->getReg(); + Register rb = getBaseReg(base, db, GpRegs); - if (inReg && (rmask(rr) & XmmRegs)) - { - deprecated_freeRsrcOf(ins, false); - Register rb = getBaseReg(base, db, GpRegs); + // There are two cases: + // - 'ins' is in FpRegs: load it. + // - otherwise: there's no point loading the value into a register + // because its only use will be to immediately spill it. Instead we + // do a memory-to-memory move from the load address directly to the + // spill slot. (There must be a spill slot assigned.) This is why + // we don't use prepareResultReg() here unlike most other places -- + // because it mandates bringing the value into a register. + // + if (ins->isInReg()) { + Register rr = ins->getReg(); + asm_spilli(ins, false); // if also in memory in post-state, spill it now switch (ins->opcode()) { - case LIR_ldf: - case LIR_ldfc: + case LIR_ldf: + case LIR_ldfc: + if (rmask(rr) & XmmRegs) { SSE_LDQ(rr, db, rb); - break; - case LIR_ld32f: - case LIR_ldc32f: + } else { + NanoAssert(rmask(rr) & x87Regs); + FLDQ(db, rb); + } + break; + + case LIR_ld32f: + case LIR_ldc32f: + if (rmask(rr) & XmmRegs) { SSE_CVTSS2SD(rr, rr); SSE_LDSS(rr, db, rb); SSE_XORPDr(rr,rr); - break; - default: - NanoAssertMsg(0, "asm_load64 should never receive this LIR opcode"); - break; + } else { + NanoAssert(rmask(rr) & x87Regs); + FLD32(db, rb); + } + break; + + default: + NanoAssert(0); + break; } - } - else - { - bool inAr = ins->isInAr(); - int dr = 0; - if (inAr) - dr = arDisp(ins); - Register rb; - if (base->isop(LIR_alloc)) { - rb = FP; - db += findMemFor(base); - } else { - rb = findRegFor(base, GpRegs); - } - ins->clearReg(); + + } else { + NanoAssert(ins->isInAr()); + int dr = arDisp(ins); switch (ins->opcode()) { - case LIR_ldf: - case LIR_ldfc: - // don't use an fpu reg to simply load & store the value. - if (inAr) - asm_mmq(FP, dr, rb, db); - deprecated_freeRsrcOf(ins, false); - if (inReg) - { - NanoAssert(rmask(rr)&x87Regs); - _allocator.retire(rr); - FLDQ(db, rb); - } - break; - case LIR_ld32f: - case LIR_ldc32f: - deprecated_freeRsrcOf(ins, false); - if (inReg) - { - NanoAssert(rmask(rr)&x87Regs); - _allocator.retire(rr); - // Be sure to shadow the value onto our local area if there's space for it, - // but don't pop the FP stack, we expect the register to stay valid. - if (inAr) - FSTQ(0, dr, FP); - FLD32(db, rb); - } - else - { - // We need to use fpu to expand 32->64, can't use asm_mmq... - // just load-and-store-with-pop. - NanoAssert(inAr); - FSTPQ(dr, FP); - FLD32(db, rb); - } - break; - default: - NanoAssertMsg(0, "asm_load64 should never receive this LIR opcode"); - break; + case LIR_ldf: + case LIR_ldfc: + // Don't use an fpu reg to simply load & store the value. + asm_mmq(FP, dr, rb, db); + break; + + case LIR_ld32f: + case LIR_ldc32f: + // Need to use fpu to expand 32->64. + FSTPQ(dr, FP); + FLD32(db, rb); + break; + + default: + NanoAssert(0); + break; } } + + freeResourcesOf(ins); } void Assembler::asm_store64(LOpcode op, LInsp value, int dr, LInsp base) @@ -921,7 +908,7 @@ namespace nanojit Register rr = prepareResultReg(ins, allow); // If 'lhs' isn't in a register, it can be clobbered by 'ins'. - Register ra = !lhs->isInReg() ? rr : lhs->getReg(); + Register ra = lhs->isInReg() ? lhs->getReg() : rr; if (!isConstRhs) { if (lhs == rhs) @@ -996,7 +983,7 @@ namespace nanojit prepareResultReg(div, rmask(EAX)); Register rDivR = findRegFor(divR, (GpRegs & ~(rmask(EAX)|rmask(EDX)))); - Register rDivL = !divL->isInReg() ? EAX : divL->getReg(); + Register rDivL = divL->isInReg() ? divL->getReg() : EAX; DIV(rDivR); CDQ(); // sign-extend EAX into EDX:EAX @@ -1035,7 +1022,7 @@ namespace nanojit Register rr = prepareResultReg(ins, GpRegs); // If 'lhs' isn't in a register, it can be clobbered by 'ins'. - Register ra = !lhs->isInReg() ? rr : lhs->getReg(); + Register ra = lhs->isInReg() ? lhs->getReg() : rr; if (ins->isop(LIR_not)) { NOT(rr); @@ -1058,119 +1045,155 @@ namespace nanojit LOpcode op = ins->opcode(); LIns* base = ins->oprnd1(); int32_t d = ins->disp(); - Register rr = deprecated_prepResultReg(ins, GpRegs); + + Register rr = prepareResultReg(ins, GpRegs); if (base->isconst()) { intptr_t addr = base->imm32(); addr += d; - switch(op) { + switch (op) { case LIR_ldzb: case LIR_ldcb: LD8Zdm(rr, addr); - return; + break; case LIR_ldsb: case LIR_ldcsb: LD8Sdm(rr, addr); - return; + break; case LIR_ldzs: case LIR_ldcs: LD16Zdm(rr, addr); - return; + break; case LIR_ldss: case LIR_ldcss: LD16Sdm(rr, addr); - return; + break; case LIR_ld: case LIR_ldc: LDdm(rr, addr); - return; + break; default: NanoAssertMsg(0, "asm_load32 should never receive this LIR opcode"); - return; + break; } - } - /* Search for add(X,Y) */ - if (base->opcode() == LIR_piadd) { - int scale = 0; + freeResourcesOf(ins); + + } else if (base->opcode() == LIR_piadd) { + // Search for add(X,Y). LIns *lhs = base->oprnd1(); LIns *rhs = base->oprnd2(); - /* See if we can bypass any SHLs, by searching for - * add(X, shl(Y,Z)) -> mov r, [X+Y*Z] - */ + // If we have this: + // + // W = ld (add(X, shl(Y, Z)))[d] , where int(1) <= Z <= int(3) + // + // we assign lhs=X, rhs=Y, scale=Z, and generate this: + // + // mov rW, [rX+rY*(2^rZ)] + // + // Otherwise, we must have this: + // + // W = ld (add(X, Y))[d] + // + // which we treat like this: + // + // W = ld (add(X, shl(Y, 0)))[d] + // + int scale; if (rhs->opcode() == LIR_pilsh && rhs->oprnd2()->isconst()) { scale = rhs->oprnd2()->imm32(); if (scale >= 1 && scale <= 3) rhs = rhs->oprnd1(); else scale = 0; + } else { + scale = 0; } - /* Does LHS have a register yet? If not, re-use the result reg. - * @todo -- If LHS is const, we could eliminate a register use. - */ - Register rleft = ( !lhs->isInReg() - ? findSpecificRegForUnallocated(lhs, rr) - : lhs->getReg() ); + // If 'lhs' isn't in a register, it can be clobbered by 'ins'. + // Likewise for 'rhs', but we try it with 'lhs' first. + Register ra, rb; + // @todo -- If LHS and/or RHS is const, we could eliminate a register use. + if (!lhs->isInReg()) { + ra = rr; + rb = findRegFor(rhs, GpRegs & ~(rmask(ra))); - /* Does RHS have a register yet? If not, try to re-use the result reg. */ - Register rright = ( rr != rleft && !rhs->isInReg() - ? findSpecificRegForUnallocated(rhs, rr) - : findRegFor(rhs, GpRegs & ~(rmask(rleft))) ); + } else { + ra = lhs->getReg(); + NanoAssert(ra != rr); + rb = rhs->isInReg() ? findRegFor(rhs, GpRegs & ~(rmask(ra))) : rr; + } - switch(op) { + switch (op) { case LIR_ldzb: case LIR_ldcb: - LD8Zsib(rr, d, rleft, rright, scale); - return; + LD8Zsib(rr, d, ra, rb, scale); + break; case LIR_ldsb: case LIR_ldcsb: - LD8Ssib(rr, d, rleft, rright, scale); - return; + LD8Ssib(rr, d, ra, rb, scale); + break; case LIR_ldzs: case LIR_ldcs: - LD16Zsib(rr, d, rleft, rright, scale); - return; + LD16Zsib(rr, d, ra, rb, scale); + break; case LIR_ldss: case LIR_ldcss: - LD16Ssib(rr, d, rleft, rright, scale); - return; + LD16Ssib(rr, d, ra, rb, scale); + break; case LIR_ld: case LIR_ldc: - LDsib(rr, d, rleft, rright, scale); - return; + LDsib(rr, d, ra, rb, scale); + break; default: NanoAssertMsg(0, "asm_load32 should never receive this LIR opcode"); - return; + break; } - } - Register ra = getBaseReg(base, d, GpRegs); - switch(op) { - case LIR_ldzb: - case LIR_ldcb: - LD8Z(rr, d, ra); - return; - case LIR_ldsb: - case LIR_ldcsb: - LD8S(rr, d, ra); - return; - case LIR_ldzs: - case LIR_ldcs: - LD16Z(rr, d, ra); - return; - case LIR_ldss: - case LIR_ldcss: - LD16S(rr, d, ra); - return; - case LIR_ld: - case LIR_ldc: - LD(rr, d, ra); - return; - default: - NanoAssertMsg(0, "asm_load32 should never receive this LIR opcode"); - return; + freeResourcesOf(ins); + if (!lhs->isInReg()) { + NanoAssert(ra == rr); + findSpecificRegForUnallocated(lhs, ra); + } else if (!rhs->isInReg()) { + NanoAssert(rb == rr); + findSpecificRegForUnallocated(rhs, rb); + } + + } else { + Register ra = getBaseReg(base, d, GpRegs); + + switch (op) { + case LIR_ldzb: + case LIR_ldcb: + LD8Z(rr, d, ra); + break; + case LIR_ldsb: + case LIR_ldcsb: + LD8S(rr, d, ra); + break; + case LIR_ldzs: + case LIR_ldcs: + LD16Z(rr, d, ra); + break; + case LIR_ldss: + case LIR_ldcss: + LD16S(rr, d, ra); + break; + case LIR_ld: + case LIR_ldc: + LD(rr, d, ra); + break; + default: + NanoAssertMsg(0, "asm_load32 should never receive this LIR opcode"); + break; + } + + freeResourcesOf(ins); + if (!base->isop(LIR_alloc) && !base->isInReg()) { + NanoAssert(ra == rr); + findSpecificRegForUnallocated(base, ra); + } } } @@ -1183,50 +1206,68 @@ namespace nanojit NanoAssert(condval->isCmp()); NanoAssert(ins->isop(LIR_cmov) && iftrue->isI32() && iffalse->isI32()); - const Register rr = deprecated_prepResultReg(ins, GpRegs); + Register rr = prepareResultReg(ins, GpRegs); - // this code assumes that neither LD nor MR nor MRcc set any of the condition flags. - // (This is true on Intel, is it true on all architectures?) - const Register iffalsereg = findRegFor(iffalse, GpRegs & ~rmask(rr)); + Register rf = findRegFor(iffalse, GpRegs & ~rmask(rr)); + + // If 'iftrue' isn't in a register, it can be clobbered by 'ins'. + Register rt = iftrue->isInReg() ? iftrue->getReg() : rr; + + // WARNING: We cannot generate any code that affects the condition + // codes between the MRcc generation here and the asm_cmp() call + // below. See asm_cmp() for more details. switch (condval->opcode()) { - // note that these are all opposites... - case LIR_eq: MRNE(rr, iffalsereg); break; - case LIR_lt: MRGE(rr, iffalsereg); break; - case LIR_le: MRG( rr, iffalsereg); break; - case LIR_gt: MRLE(rr, iffalsereg); break; - case LIR_ge: MRL( rr, iffalsereg); break; - case LIR_ult: MRAE(rr, iffalsereg); break; - case LIR_ule: MRA( rr, iffalsereg); break; - case LIR_ugt: MRBE(rr, iffalsereg); break; - case LIR_uge: MRB( rr, iffalsereg); break; + // Note that these are all opposites... + case LIR_eq: MRNE(rr, rf); break; + case LIR_lt: MRGE(rr, rf); break; + case LIR_le: MRG( rr, rf); break; + case LIR_gt: MRLE(rr, rf); break; + case LIR_ge: MRL( rr, rf); break; + case LIR_ult: MRAE(rr, rf); break; + case LIR_ule: MRA( rr, rf); break; + case LIR_ugt: MRBE(rr, rf); break; + case LIR_uge: MRB( rr, rf); break; default: NanoAssert(0); break; } - /*const Register iftruereg =*/ findSpecificRegFor(iftrue, rr); + + if (rr != rt) + MR(rr, rt); + + freeResourcesOf(ins); + if (!iftrue->isInReg()) { + NanoAssert(rt == rr); + findSpecificRegForUnallocated(iftrue, rr); + } + asm_cmp(condval); } void Assembler::asm_param(LInsp ins) { - uint32_t a = ins->paramArg(); + uint32_t arg = ins->paramArg(); uint32_t kind = ins->paramKind(); if (kind == 0) { // ordinary param AbiKind abi = _thisfrag->lirbuf->abi; uint32_t abi_regcount = max_abi_regs[abi]; - if (a < abi_regcount) { + if (arg < abi_regcount) { // Incoming arg in register. - deprecated_prepResultReg(ins, rmask(argRegs[a])); + prepareResultReg(ins, rmask(argRegs[arg])); + // No code to generate. + } else { // Incoming arg is on stack, and EBP points nearby (see genPrologue()). - Register r = deprecated_prepResultReg(ins, GpRegs); - int d = (a - abi_regcount) * sizeof(intptr_t) + 8; + Register r = prepareResultReg(ins, GpRegs); + int d = (arg - abi_regcount) * sizeof(intptr_t) + 8; LD(r, d, FP); } + + } else { + // Saved param. + prepareResultReg(ins, rmask(savedRegs[arg])); + // No code to generate. } - else { - // saved param - deprecated_prepResultReg(ins, rmask(savedRegs[a])); - } + freeResourcesOf(ins); } void Assembler::asm_int(LInsp ins) @@ -1287,10 +1328,13 @@ namespace nanojit void Assembler::asm_quad(LInsp ins) { + NanoAssert(ins->isconstf()); if (ins->isInReg()) { Register rr = ins->getReg(); NanoAssert(rmask(rr) & FpRegs); asm_quad(rr, ins->imm64(), ins->imm64f(), /*canClobberCCs*/true); + } else { + // Do nothing, will be rematerialized when necessary. } freeResourcesOf(ins); @@ -1364,8 +1408,7 @@ namespace nanojit // If 'r' is known, then that's the register we have to put 'ins' // into. - if (sz == ARGSIZE_I || sz == ARGSIZE_U) - { + if (sz == ARGSIZE_I || sz == ARGSIZE_U) { if (r != UnspecifiedReg) { if (ins->isconst()) { // Rematerialize the constant. @@ -1394,9 +1437,8 @@ namespace nanojit else asm_pusharg(ins); } - } - else - { + + } else { NanoAssert(sz == ARGSIZE_F); asm_farg(ins, stkd); } @@ -1454,7 +1496,6 @@ namespace nanojit } else { FSTPQ(stkd, SP); - // // 22Jul09 rickr - Enabling the evict causes a 10% slowdown on primes // // evict() triggers a very expensive fstpq/fldq pair around the store. @@ -1462,11 +1503,12 @@ namespace nanojit // // see https://bugzilla.mozilla.org/show_bug.cgi?id=491084 - /* It's possible that the same LIns* with r=FST0 will appear in the argument list more - * than once. In this case FST0 will not have been evicted and the multiple pop - * actions will unbalance the FPU stack. A quick fix is to always evict FST0 manually. - */ - evictIfActive(FST0); + // It's possible that the same LIns* with r=FST0 will appear in the argument list more + // than once. In this case FST0 will not have been evicted and the multiple pop + // actions will unbalance the FPU stack. A quick fix is to always evict FST0 manually. + NanoAssert(r == FST0); + NanoAssert(ins == _allocator.getActive(r)); + evict(ins); } if (!_config.i386_fixed_esp) SUBi(ESP, 8); @@ -1485,93 +1527,85 @@ namespace nanojit RegisterMask allow = XmmRegs; Register rb = UnspecifiedReg; if (lhs != rhs) { - rb = findRegFor(rhs,allow); + rb = findRegFor(rhs, allow); allow &= ~rmask(rb); } - Register rr = deprecated_prepResultReg(ins, allow); - Register ra; + Register rr = prepareResultReg(ins, allow); - // if this is last use of lhs in reg, we can re-use result reg + // If 'lhs' isn't in a register, it can be clobbered by 'ins'. + Register ra; if (!lhs->isInReg()) { - ra = findSpecificRegForUnallocated(lhs, rr); - } else if ((rmask(lhs->getReg()) & XmmRegs) == 0) { - // We need this case on AMD64, because it's possible that - // an earlier instruction has done a quadword load and reserved a - // GPR. If so, ask for a new register. - ra = findRegFor(lhs, XmmRegs); + ra = rr; + + } else if (!(rmask(lhs->getReg()) & XmmRegs)) { + NanoAssert(lhs->getReg() == FST0); + + // We need to evict lhs from x87Regs, which then puts us in + // the same situation as the !isInReg() case. + evict(lhs); + ra = rr; + } else { - // lhs already has a register assigned but maybe not from the allow set - ra = findRegFor(lhs, allow); + ra = lhs->getReg(); + NanoAssert(rmask(ra) & XmmRegs); } if (lhs == rhs) rb = ra; - if (op == LIR_fadd) - SSE_ADDSD(rr, rb); - else if (op == LIR_fsub) - SSE_SUBSD(rr, rb); - else if (op == LIR_fmul) - SSE_MULSD(rr, rb); - else //if (op == LIR_fdiv) - SSE_DIVSD(rr, rb); + switch (op) { + case LIR_fadd: SSE_ADDSD(rr, rb); break; + case LIR_fsub: SSE_SUBSD(rr, rb); break; + case LIR_fmul: SSE_MULSD(rr, rb); break; + case LIR_fdiv: SSE_DIVSD(rr, rb); break; + default: NanoAssert(0); + } if (rr != ra) SSE_MOVSD(rr, ra); + + freeResourcesOf(ins); + if (!lhs->isInReg()) { + NanoAssert(ra == rr); + findSpecificRegForUnallocated(lhs, ra); + } } else { - // we swap lhs/rhs on purpose here, works out better - // if you only have one fpu reg. use divr/subr. + // We swap lhs/rhs on purpose here, it works out better with + // only one fpu reg -- we can use divr/subr. LIns* rhs = ins->oprnd1(); LIns* lhs = ins->oprnd2(); - Register rr = deprecated_prepResultReg(ins, rmask(FST0)); + debug_only( Register rr = ) prepareResultReg(ins, rmask(FST0)); + NanoAssert(FST0 == rr); + NanoAssert(!lhs->isInReg() || FST0 == lhs->getReg()); - if (rhs->isconstq()) - { + if (rhs->isconstq()) { const uint64_t* p = findQuadConstant(rhs->imm64()); - // lhs into reg, prefer same reg as result + switch (op) { + case LIR_fadd: FADDdm( (const double*)p); break; + case LIR_fsub: FSUBRdm((const double*)p); break; + case LIR_fmul: FMULdm( (const double*)p); break; + case LIR_fdiv: FDIVRdm((const double*)p); break; + default: NanoAssert(0); + } - // last use of lhs in reg, can reuse rr - // else, lhs already has a different reg assigned - if (!lhs->isInReg()) - findSpecificRegForUnallocated(lhs, rr); - - NanoAssert(lhs->getReg()==FST0); - // assume that the lhs is in ST(0) and rhs is on stack - if (op == LIR_fadd) - { FADDdm((const double*)p); } - else if (op == LIR_fsub) - { FSUBRdm((const double*)p); } - else if (op == LIR_fmul) - { FMULdm((const double*)p); } - else if (op == LIR_fdiv) - { FDIVRdm((const double*)p); } - } - else - { - // make sure rhs is in memory + } else { int db = findMemFor(rhs); - // lhs into reg, prefer same reg as result - - // last use of lhs in reg, can reuse rr - // else, lhs already has a different reg assigned - if (!lhs->isInReg()) - findSpecificRegForUnallocated(lhs, rr); - - NanoAssert(lhs->getReg()==FST0); - // assume that the lhs is in ST(0) and rhs is on stack - if (op == LIR_fadd) - { FADD(db, FP); } - else if (op == LIR_fsub) - { FSUBR(db, FP); } - else if (op == LIR_fmul) - { FMUL(db, FP); } - else if (op == LIR_fdiv) - { FDIVR(db, FP); } + switch (op) { + case LIR_fadd: FADD( db, FP); break; + case LIR_fsub: FSUBR(db, FP); break; + case LIR_fmul: FMUL( db, FP); break; + case LIR_fdiv: FDIVR(db, FP); break; + default: NanoAssert(0); + } + } + freeResourcesOf(ins); + if (!lhs->isInReg()) { + findSpecificRegForUnallocated(lhs, FST0); } } } diff --git a/js/src/nanojit/Nativei386.h b/js/src/nanojit/Nativei386.h index 923fa42ce8dc..c87277aeb277 100644 --- a/js/src/nanojit/Nativei386.h +++ b/js/src/nanojit/Nativei386.h @@ -880,7 +880,7 @@ namespace nanojit *(--_nIns) = 0x57;\ *(--_nIns) = 0x0f;\ *(--_nIns) = 0x66;\ - asm_output("xorpd %s,[0x%p]",gpn(r),(void*)(maskaddr));\ + asm_output("xorpd %s,[%p]",gpn(r),(void*)(maskaddr));\ } while(0) #define SSE_XORPDr(rd,rs) do{ \ From 78c1268189683c661f5a75f6116412ca30582bfd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 1 Mar 2010 15:02:36 +1100 Subject: [PATCH 13/52] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index d3df1fd3e5e6..d423c37e116a 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -a5291bc7b0cef4f41f4180db6388edebdbb4c208 +05949faa5b451d5452c9b5eb95296a53b555dda1 From 8167bb1a7cf022ef780a4381c214eed191c45476 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 1 Mar 2010 11:07:40 -0600 Subject: [PATCH 14/52] Bug 548276 - "Assertion failure: HAS_FUNCTION_CLASS(funobj), at ../jsdbgapi.cpp". r=jwalden. --- js/src/jsdbgapi.cpp | 4 +++- js/src/tests/js1_8_5/regress/regress-548276.js | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 js/src/tests/js1_8_5/regress/regress-548276.js diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 644127b34815..7803f7aaf731 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -773,8 +773,10 @@ IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop) { if (sprop->attrs & JSPROP_SETTER) { JSObject *funobj = sprop->setterObject(); - JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); + if (!funobj->isFunction()) + return false; + JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); return FUN_NATIVE(fun) == js_watch_set_wrapper; } return sprop->setterOp() == js_watch_set; diff --git a/js/src/tests/js1_8_5/regress/regress-548276.js b/js/src/tests/js1_8_5/regress/regress-548276.js new file mode 100644 index 000000000000..98192e2222a8 --- /dev/null +++ b/js/src/tests/js1_8_5/regress/regress-548276.js @@ -0,0 +1,9 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributors: Gary Kwong and Jason Orendorff + */ +var obj = {}; +obj.__defineSetter__("x", function() {}); +obj.watch("x", function() {}); +obj.__defineSetter__("x", /a/); From 4b7c35b234e0890dbbdc10b3448962c4cc162913 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Mon, 1 Mar 2010 13:30:23 -0800 Subject: [PATCH 15/52] Disallow embeddings reaching into our guts (part 1: jsnum.h, bug 548205, r=brendan). --- content/base/public/nsContentUtils.h | 24 +++++++++---------- .../canvas/src/nsCanvasRenderingContext2D.cpp | 16 +++++++++++-- dom/base/nsDOMClassInfo.cpp | 3 +-- dom/src/json/nsJSON.cpp | 1 - js/src/Makefile.in | 1 - js/src/jsapi.cpp | 6 +++++ js/src/jsapi.h | 3 +++ 7 files changed, 35 insertions(+), 19 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index bcfb9dca43b4..07f953c5874f 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -42,8 +42,12 @@ #ifndef nsContentUtils_h___ #define nsContentUtils_h___ +#include +#if defined(XP_WIN) || defined(XP_OS2) +#include +#endif + #include "jsprvtd.h" -#include "jsnum.h" #include "nsAString.h" #include "nsIStatefulFrame.h" #include "nsINodeInfo.h" @@ -1711,20 +1715,14 @@ private: /* * Check whether a floating point number is finite (not +/-infinity and not a - * NaN value). We wrap JSDOUBLE_IS_FINITE in a function because it expects to - * take the address of its argument, and because the argument must be of type - * jsdouble to have the right size and layout of bits. - * - * Note: we could try to exploit the fact that |infinity - infinity == NaN| - * instead of using JSDOUBLE_IS_FINITE. This would produce more compact code - * and perform better by avoiding type conversions and bit twiddling. - * Unfortunately, some architectures don't guarantee that |f == f| evaluates - * to true (where f is any *finite* floating point number). See - * https://bugzilla.mozilla.org/show_bug.cgi?id=369418#c63 . To play it safe - * for gecko 1.9, we just reuse JSDOUBLE_IS_FINITE. + * NaN value). */ inline NS_HIDDEN_(PRBool) NS_FloatIsFinite(jsdouble f) { - return JSDOUBLE_IS_FINITE(f); +#ifdef WIN32 + return _finite(f); +#else + return finite(f); +#endif } /* diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index 5bc97e02ed94..e29c95913de2 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -41,6 +41,9 @@ #define _USE_MATH_DEFINES #endif #include +#if defined(XP_WIN) || defined(XP_OS2) +#include +#endif #include "prmem.h" @@ -87,7 +90,6 @@ #include "nsIDocShellTreeNode.h" #include "nsIXPConnect.h" #include "jsapi.h" -#include "jsnum.h" #include "nsTArray.h" @@ -116,7 +118,17 @@ using namespace mozilla; /* Float validation stuff */ -#define VALIDATE(_f) if (!JSDOUBLE_IS_FINITE(_f)) return PR_FALSE +static inline bool +DoubleIsFinite(double d) +{ +#ifdef WIN32 + return _finite(d); +#else + return finite(d); +#endif +} + +#define VALIDATE(_f) if (!DoubleIsFinite(_f)) return PR_FALSE /* These must take doubles as args, because JSDOUBLE_IS_FINITE expects * to take the address of its argument; we can't cast/convert in the diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d22126de19c1..0f5889722281 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -67,7 +67,6 @@ #include "jsprvtd.h" // we are using private JS typedefs... #include "jscntxt.h" #include "jsdbgapi.h" -#include "jsnum.h" // General helper includes #include "nsGlobalWindow.h" @@ -3825,7 +3824,7 @@ nsDOMClassInfo::GetArrayIndexFromId(JSContext *cx, jsval id, PRBool *aIsNumber) jsint i = -1; - if (!JSDOUBLE_IS_INT(array_index, i)) { + if (!::JS_DoubleIsInt32(array_index, &i)) { return -1; } diff --git a/dom/src/json/nsJSON.cpp b/dom/src/json/nsJSON.cpp index 6cb362774204..b4963f88ac29 100644 --- a/dom/src/json/nsJSON.cpp +++ b/dom/src/json/nsJSON.cpp @@ -40,7 +40,6 @@ #include "jsapi.h" #include "jsdtoa.h" #include "jsprvtd.h" -#include "jsnum.h" #include "jsbool.h" #include "jsarena.h" #include "jscntxt.h" diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 50b079ec5ce9..ca475544f0b6 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -193,7 +193,6 @@ INSTALLED_HEADERS = \ jslock.h \ jslong.h \ jsmath.h \ - jsnum.h \ jsobj.h \ jsobjinlines.h \ json.h \ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 17f69069cb0e..300b4b69c177 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -443,6 +443,12 @@ JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp) return !JSVAL_IS_NULL(tvr.value()); } +JS_PUBLIC_API(JSBool) +JS_DoubleIsInt32(jsdouble d, jsint *ip) +{ + return JSDOUBLE_IS_INT(d, *ip); +} + JS_PUBLIC_API(JSBool) JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 6e0fdbd12e41..818be2610920 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -467,6 +467,9 @@ JS_ValueToSource(JSContext *cx, jsval v); extern JS_PUBLIC_API(JSBool) JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp); +extern JS_PUBLIC_API(JSBool) +JS_DoubleIsInt32(jsdouble d, jsint *ip); + /* * Convert a value to a number, then to an int32, according to the ECMA rules * for ToInt32. From 540374599476c4ec93ea4395852fe155f09f9f16 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Fri, 26 Feb 2010 17:06:23 -0800 Subject: [PATCH 16/52] Bug 542864 - Convert the right variable to an id. r=jorendorff --- js/src/shell/js.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 0c60923838fd..ca3ce67c6cd8 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2549,7 +2549,7 @@ split_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_TRUE; if (!cpx->isInner && cpx->inner) { /* Make sure to define this property on the inner object. */ - if (!JS_ValueToId(cx, *vp, &asId)) + if (!JS_ValueToId(cx, id, &asId)) return JS_FALSE; return JS_DefinePropertyById(cx, cpx->inner, asId, *vp, NULL, NULL, JSPROP_ENUMERATE); } From a9bf220597a5d5b021d4ef1b710dfb3473ca3681 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 2 Mar 2010 11:18:48 +1100 Subject: [PATCH 17/52] Bustage fix for Windows. No bug, r=me. --HG-- extra : convert_revision : 4901be8fd3260bb90b90fda989f624cda7401032 --- js/src/nanojit/LIR.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index e2452766df56..fcd0ab21e973 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -829,7 +829,7 @@ namespace nanojit if (oprnd1->isconst() && oprnd2->isconst()) { int32_t c1 = oprnd1->imm32(); int32_t c2 = oprnd2->imm32(); - double d; + double d = 0.0; switch (op) { case LIR_addxov: d = double(c1) + double(c2); break; @@ -2510,6 +2510,8 @@ namespace nanojit void ValidateWriter::typeCheckArgs(LOpcode op, int nArgs, LTy formals[], LIns* args[]) { + NanoAssert(nArgs >= 0); + // Type-check the arguments. for (int i = 0; i < nArgs; i++) { LTy formal = formals[i]; @@ -2896,7 +2898,7 @@ namespace nanojit LIns* ValidateWriter::insGuard(LOpcode op, LIns *cond, GuardRecord *gr) { - int nArgs; + int nArgs = -1; // init to shut compilers up LTy formals[1]; LIns* args[1]; @@ -2953,7 +2955,7 @@ namespace nanojit LIns* ValidateWriter::insBranch(LOpcode op, LIns* cond, LIns* to) { - int nArgs = 0; + int nArgs = -1; // init to shut compilers up LTy formals[1]; LIns* args[1]; From 2709dc1edc37cb1a6b4796ae2c70d97fa02a162a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 2 Mar 2010 12:43:20 +1100 Subject: [PATCH 18/52] Bug 545274 - nanojit: start adding alias info to loads/stores/calls. r=rreitmai. --HG-- extra : convert_revision : 4adbf1bbb16cf4751b46a49a4f9c474c0ab0a3b9 --- js/src/lirasm/lirasm.cpp | 39 ++--- js/src/lirasm/tests/fuzz-527178.in | 2 +- js/src/nanojit/Assembler.cpp | 8 - js/src/nanojit/LIR.cpp | 178 ++++++++++++++-------- js/src/nanojit/LIR.h | 233 ++++++++++++++++++++++++----- js/src/nanojit/LIRopcode.tbl | 38 ++--- js/src/nanojit/NativeARM.cpp | 7 - js/src/nanojit/NativeMIPS.cpp | 10 +- js/src/nanojit/NativePPC.cpp | 8 - js/src/nanojit/NativeSparc.cpp | 9 +- js/src/nanojit/NativeX64.cpp | 10 +- js/src/nanojit/Nativei386.cpp | 21 +-- 12 files changed, 345 insertions(+), 218 deletions(-) diff --git a/js/src/lirasm/lirasm.cpp b/js/src/lirasm/lirasm.cpp index b8aae9fc7604..ea6da1fbfee9 100644 --- a/js/src/lirasm/lirasm.cpp +++ b/js/src/lirasm/lirasm.cpp @@ -151,7 +151,7 @@ enum ReturnType { #endif #define CI(name, args) \ - {(uintptr_t) (&name), args, /*_cse*/0, /*_fold*/0, nanojit::ABI_CDECL \ + {(uintptr_t) (&name), args, nanojit::ABI_CDECL, /*isPure*/0, ACC_STORE_ANY \ DEBUG_ONLY_NAME(name)} #define FN(name, args) \ @@ -1064,23 +1064,15 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons break; #if NJ_EXPANDED_LOADSTORE_SUPPORTED - case LIR_ldzb: - case LIR_ldzs: case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: case LIR_ld32f: - case LIR_ldc32f: #endif + case LIR_ldzb: + case LIR_ldzs: case LIR_ld: - case LIR_ldc: CASE64(LIR_ldq:) - CASE64(LIR_ldqc:) case LIR_ldf: - case LIR_ldfc: - case LIR_ldcb: - case LIR_ldcs: ins = assemble_load(); break; @@ -1334,6 +1326,10 @@ const CallInfo ci_N_IQF = CI(f_N_IQF, argMask(I32, 1, 3) | // - LIR_file/LIR_line (#ifdef VTUNE only) // - LIR_fmod (not implemented in NJ backends) // +// Other limitations: +// - Loads always use accSet==ACC_LOAD_ANY +// - Stores always use accSet==ACC_STORE_ANY +// void FragmentAssembler::assembleRandomFragment(int nIns) { @@ -1459,34 +1455,23 @@ FragmentAssembler::assembleRandomFragment(int nIns) I_loads.push_back(LIR_ld); // weight LIR_ld more heavily I_loads.push_back(LIR_ld); I_loads.push_back(LIR_ld); - I_loads.push_back(LIR_ldc); - I_loads.push_back(LIR_ldcb); - I_loads.push_back(LIR_ldcs); -#if NJ_EXPANDED_LOADSTORE_SUPPORTED I_loads.push_back(LIR_ldzb); I_loads.push_back(LIR_ldzs); +#if NJ_EXPANDED_LOADSTORE_SUPPORTED I_loads.push_back(LIR_ldsb); I_loads.push_back(LIR_ldss); - I_loads.push_back(LIR_ldcsb); - I_loads.push_back(LIR_ldcss); #endif #ifdef NANOJIT_64BIT vector Q_loads; - Q_loads.push_back(LIR_ldq); // weight LIR_ld more heavily Q_loads.push_back(LIR_ldq); - Q_loads.push_back(LIR_ldqc); #endif vector F_loads; - F_loads.push_back(LIR_ldf); // weight LIR_ldf more heavily F_loads.push_back(LIR_ldf); - F_loads.push_back(LIR_ldfc); #if NJ_EXPANDED_LOADSTORE_SUPPORTED - // this loads a 32-bit float and expands to 64-bit float - F_loads.push_back(LIR_ld32f); // weight LIR_ld32f more heavily - F_loads.push_back(LIR_ld32f); - F_loads.push_back(LIR_ldc32f); + // this loads a 32-bit float and expands it to 64-bit float + F_loads.push_back(LIR_ld32f); #endif enum LInsClass { @@ -2024,13 +2009,13 @@ Lirasm::lookupFunction(const string &name, CallInfo *&ci) // The ABI, arg types and ret type will be overridden by the caller. if (func->second.mReturnType == RT_FLOAT) { CallInfo target = {(uintptr_t) func->second.rfloat, - 0, 0, 0, ABI_FASTCALL + 0, ABI_FASTCALL, /*isPure*/0, ACC_STORE_ANY verbose_only(, func->first.c_str()) }; *ci = target; } else { CallInfo target = {(uintptr_t) func->second.rint, - 0, 0, 0, ABI_FASTCALL + 0, ABI_FASTCALL, /*isPure*/0, ACC_STORE_ANY verbose_only(, func->first.c_str()) }; *ci = target; } diff --git a/js/src/lirasm/tests/fuzz-527178.in b/js/src/lirasm/tests/fuzz-527178.in index 19684bc7fcf2..9b210716fff3 100644 --- a/js/src/lirasm/tests/fuzz-527178.in +++ b/js/src/lirasm/tests/fuzz-527178.in @@ -1,5 +1,5 @@ base = alloc 512 five = int 5 sti five base 256 -x = ldcs base 256 +x = ldzs base 256 ret x diff --git a/js/src/nanojit/Assembler.cpp b/js/src/nanojit/Assembler.cpp index 9921930521d5..fa7ce8317336 100755 --- a/js/src/nanojit/Assembler.cpp +++ b/js/src/nanojit/Assembler.cpp @@ -1384,12 +1384,7 @@ namespace nanojit case LIR_ldzs: case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: case LIR_ld: - case LIR_ldc: - case LIR_ldcb: - case LIR_ldcs: { countlir_ld(); asm_load32(ins); @@ -1397,11 +1392,8 @@ namespace nanojit } case LIR_ld32f: - case LIR_ldc32f: case LIR_ldf: - case LIR_ldfc: CASE64(LIR_ldq:) - CASE64(LIR_ldqc:) { countlir_ldq(); asm_load64(ins); diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index fcd0ab21e973..52c4e95f64de 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -209,12 +209,17 @@ namespace nanojit return startOfRoom; } - LInsp LirBufWriter::insStore(LOpcode op, LInsp val, LInsp base, int32_t d) + LInsp LirBufWriter::insStore(LOpcode op, LInsp val, LInsp base, int32_t d, AccSet accSet) { - LInsSti* insSti = (LInsSti*)_buf->makeRoom(sizeof(LInsSti)); - LIns* ins = insSti->getLIns(); - ins->initLInsSti(op, val, base, d); - return ins; + if (isS16(d)) { + LInsSti* insSti = (LInsSti*)_buf->makeRoom(sizeof(LInsSti)); + LIns* ins = insSti->getLIns(); + ins->initLInsSti(op, val, base, d, accSet); + return ins; + } else { + // If the displacement is more than 16 bits, put it in a separate instruction. + return insStore(op, val, ins2(LIR_addp, base, insImmWord(d)), 0, accSet); + } } LInsp LirBufWriter::ins0(LOpcode op) @@ -249,12 +254,19 @@ namespace nanojit return ins; } - LInsp LirBufWriter::insLoad(LOpcode op, LInsp base, int32_t d) + LInsp LirBufWriter::insLoad(LOpcode op, LInsp base, int32_t d, AccSet accSet) { - LInsLd* insLd = (LInsLd*)_buf->makeRoom(sizeof(LInsLd)); - LIns* ins = insLd->getLIns(); - ins->initLInsLd(op, base, d); - return ins; + if (isS16(d)) { + LInsLd* insLd = (LInsLd*)_buf->makeRoom(sizeof(LInsLd)); + LIns* ins = insLd->getLIns(); + ins->initLInsLd(op, base, d, accSet); + return ins; + } else { + // If the displacement is more than 16 bits, put it in a separate instruction. + // Note that CseFilter::insLoad() also does this, so this will + // only occur if CseFilter has been removed from the pipeline. + return insLoad(op, ins2(LIR_addp, base, insImmWord(d)), 0, accSet); + } } LInsp LirBufWriter::insGuard(LOpcode op, LInsp c, GuardRecord *gr) @@ -895,7 +907,7 @@ namespace nanojit return out->insBranch(v, c, t); } - LIns* ExprFilter::insLoad(LOpcode op, LIns* base, int32_t off) { + LIns* ExprFilter::insLoad(LOpcode op, LIns* base, int32_t off, AccSet accSet) { if (base->isconstp() && !isS8(off)) { // if the effective address is constant, then transform: // ld const[bigconst] => ld (const+bigconst)[0] @@ -903,9 +915,9 @@ namespace nanojit // under the assumption that we're more likely to CSE-match the // constant base address if we dont const-fold small offsets. uintptr_t p = (uintptr_t)base->constvalp() + off; - return out->insLoad(op, insImmPtr((void*)p), 0); + return out->insLoad(op, insImmPtr((void*)p), 0, accSet); } - return out->insLoad(op, base, off); + return out->insLoad(op, base, off, accSet); } LIns* LirWriter::ins_eq0(LIns* oprnd1) @@ -936,7 +948,7 @@ namespace nanojit #endif } - LIns* LirWriter::insStorei(LIns* value, LIns* base, int32_t d) + LIns* LirWriter::insStorei(LIns* value, LIns* base, int32_t d, AccSet accSet) { // Determine which kind of store should be used for 'value' based on // its type. @@ -950,7 +962,7 @@ namespace nanojit case LTy_Void: NanoAssert(0); break; default: NanoAssert(0); break; } - return insStore(op, value, base, d); + return insStore(op, value, base, d, accSet); } #if NJ_SOFTFLOAT_SUPPORTED @@ -1575,21 +1587,13 @@ namespace nanojit break; case LIR_ld: - case LIR_ldc: CASE64(LIR_ldq:) - CASE64(LIR_ldqc:) case LIR_ldf: - case LIR_ldfc: case LIR_ldzb: case LIR_ldzs: - case LIR_ldcb: - case LIR_ldcs: case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: case LIR_ld32f: - case LIR_ldc32f: case LIR_ret: CASE64(LIR_qret:) case LIR_fret: @@ -1755,6 +1759,26 @@ namespace nanojit } } + char* LirNameMap::formatAccSet(LInsp ins, bool isLoad, char* buf) { + AccSet accSet = ins->accSet(); + int i = 0; + if ((isLoad && accSet == ACC_LOAD_ANY) || + (!isLoad && accSet == ACC_STORE_ANY)) + { + // boring, don't bother with a suffix + } else { + buf[i++] = '.'; + if (accSet & ACC_READONLY) { buf[i++] = 'r'; accSet &= ~ACC_READONLY; } + if (accSet & ACC_STACK) { buf[i++] = 's'; accSet &= ~ACC_STACK; } + if (accSet & ACC_OTHER) { buf[i++] = 'o'; accSet &= ~ACC_OTHER; } + // This assertion will fail if we add a new accSet value but + // forget to handle it here. + NanoAssert(accSet == 0); + } + buf[i] = 0; + return buf; + } + void LirNameMap::copyName(LInsp i, const char *s, int suffix) { char s2[200]; if (VMPI_isdigit(s[VMPI_strlen(s)-1])) { @@ -2014,37 +2038,35 @@ namespace nanojit break; case LIR_ld: - case LIR_ldc: CASE64(LIR_ldq:) - CASE64(LIR_ldqc:) case LIR_ldf: - case LIR_ldfc: case LIR_ldzb: case LIR_ldzs: - case LIR_ldcb: - case LIR_ldcs: case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: - case LIR_ld32f: - case LIR_ldc32f: - VMPI_sprintf(s, "%s = %s %s[%d]", formatRef(i), lirNames[op], + case LIR_ld32f: { + char b[32]; + VMPI_sprintf(s, "%s = %s%s %s[%d]", formatRef(i), lirNames[op], + formatAccSet(i, /*isLoad*/true, b), formatRef(i->oprnd1()), i->disp()); break; + } case LIR_sti: CASE64(LIR_stqi:) case LIR_stfi: case LIR_stb: case LIR_sts: - case LIR_st32f: - VMPI_sprintf(s, "%s %s[%d] = %s", lirNames[op], + case LIR_st32f: { + char b[32]; + VMPI_sprintf(s, "%s%s %s[%d] = %s", lirNames[op], + formatAccSet(i, /*isLoad*/false, b), formatRef(i->oprnd2()), i->disp(), formatRef(i->oprnd1())); break; + } default: NanoAssertMsgf(0, "Can't handle opcode %s\n", lirNames[op]); @@ -2163,18 +2185,27 @@ namespace nanojit return exprs->add(LIns3, ins, k); } - LIns* CseFilter::insLoad(LOpcode v, LInsp base, int32_t disp) + LIns* CseFilter::insLoad(LOpcode v, LInsp base, int32_t disp, AccSet accSet) { - if (isCseOpcode(v)) { - uint32_t k; - LInsp ins = exprs->findLoad(v, base, disp, k); - if (ins) - return ins; - ins = out->insLoad(v, base, disp); - NanoAssert(ins->opcode() == v && ins->oprnd1() == base && ins->disp() == disp); - return exprs->add(LInsLoad, ins, k); + if (isS16(disp)) { + // XXX: This condition is overly strict. Bug 517910 will make it better. + if (accSet == ACC_READONLY) { + uint32_t k; + LInsp ins = exprs->findLoad(v, base, disp, k); + if (ins) + return ins; + ins = out->insLoad(v, base, disp, accSet); + NanoAssert(ins->opcode() == v && ins->oprnd1() == base && ins->disp() == disp); + return exprs->add(LInsLoad, ins, k); + } + return out->insLoad(v, base, disp, accSet); + } else { + // If the displacement is more than 16 bits, put it in a separate + // instruction. LirBufWriter also does this, we do it here as + // well because CseFilter relies on LirBufWriter not changing + // code. + return insLoad(v, ins2(LIR_addp, base, insImmWord(disp)), 0, accSet); } - return out->insLoad(v, base, disp); } LInsp CseFilter::insGuard(LOpcode v, LInsp c, GuardRecord *gr) @@ -2225,7 +2256,8 @@ namespace nanojit LInsp CseFilter::insCall(const CallInfo *ci, LInsp args[]) { - if (ci->_cse) { + if (ci->_isPure) { + NanoAssert(ci->_storeAccSet == ACC_NONE); uint32_t k; uint32_t argc = ci->count_args(); LInsp ins = exprs->findCall(ci, argc, args, k); @@ -2238,7 +2270,7 @@ namespace nanojit return out->insCall(ci, args); } - LInsp LoadFilter::insLoad(LOpcode v, LInsp base, int32_t disp) + LInsp LoadFilter::insLoad(LOpcode v, LInsp base, int32_t disp, AccSet accSet) { if (base != sp && base != rp) { @@ -2257,7 +2289,7 @@ namespace nanojit LInsp ins = exprs->findLoad(v, base, disp, k); if (ins) return ins; - ins = out->insLoad(v, base, disp); + ins = out->insLoad(v, base, disp, accSet); return exprs->add(LInsLoad, ins, k); } default: @@ -2265,7 +2297,7 @@ namespace nanojit break; } } - return out->insLoad(v, base, disp); + return out->insLoad(v, base, disp, accSet); } void LoadFilter::clear(LInsp p) @@ -2274,15 +2306,15 @@ namespace nanojit exprs->clear(); } - LInsp LoadFilter::insStore(LOpcode op, LInsp v, LInsp b, int32_t d) + LInsp LoadFilter::insStore(LOpcode op, LInsp v, LInsp b, int32_t d, AccSet accSet) { clear(b); - return out->insStore(op, v, b, d); + return out->insStore(op, v, b, d, accSet); } LInsp LoadFilter::insCall(const CallInfo *ci, LInsp args[]) { - if (!ci->_cse) + if (!ci->_isPure) exprs->clear(); return out->insCall(ci, args); } @@ -2316,7 +2348,7 @@ namespace nanojit #define SF_CALLINFO(name, typesig) \ static const CallInfo name##_ci = \ - { (intptr_t)&name, typesig, /*cse*/1, /*fold*/1, ABI_FASTCALL verbose_only(, #name) } + { (intptr_t)&name, typesig, ABI_FASTCALL, /*isPure*/1, ACC_NONE verbose_only(, #name) } SF_CALLINFO(i2f, SIG_F_I); SF_CALLINFO(u2f, SIG_F_U); @@ -2542,6 +2574,13 @@ namespace nanojit lirNames[op], lirNames[arg->opcode()], shouldBeDesc); } + void ValidateWriter::errorAccSetShould(const char* what, AccSet accSet, const char* shouldDesc) + { + NanoAssertMsgf(0, + "LIR AccSet error (%s): '%s' AccSet is %d; it should %s", + _whereInPipeline, what, accSet, shouldDesc); + } + void ValidateWriter::checkLInsIsACondOrConst(LOpcode op, int argN, LIns* ins) { // We could introduce a LTy_B32 type in the type system but that's a @@ -2568,29 +2607,27 @@ namespace nanojit : LirWriter(out), _whereInPipeline(stageName) {} - LIns* ValidateWriter::insLoad(LOpcode op, LIns* base, int32_t d) + LIns* ValidateWriter::insLoad(LOpcode op, LIns* base, int32_t d, AccSet accSet) { + if (accSet == ACC_NONE) + errorAccSetShould(lirNames[op], accSet, "not equal ACC_NONE"); + + if (accSet & ~ACC_LOAD_ANY) + errorAccSetShould(lirNames[op], accSet, "not contain bits that aren't in ACC_LOAD_ANY"); + int nArgs = 1; LTy formals[1] = { LTy_Ptr }; LIns* args[1] = { base }; switch (op) { case LIR_ld: - case LIR_ldc: case LIR_ldf: - case LIR_ldfc: case LIR_ldzb: case LIR_ldzs: - case LIR_ldcb: - case LIR_ldcs: case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: case LIR_ld32f: - case LIR_ldc32f: CASE64(LIR_ldq:) - CASE64(LIR_ldqc:) break; default: NanoAssert(0); @@ -2598,11 +2635,17 @@ namespace nanojit typeCheckArgs(op, nArgs, formals, args); - return out->insLoad(op, base, d); + return out->insLoad(op, base, d, accSet); } - LIns* ValidateWriter::insStore(LOpcode op, LIns* value, LIns* base, int32_t d) + LIns* ValidateWriter::insStore(LOpcode op, LIns* value, LIns* base, int32_t d, AccSet accSet) { + if (accSet == ACC_NONE) + errorAccSetShould(lirNames[op], accSet, "not equal ACC_NONE"); + + if (accSet & ~ACC_STORE_ANY) + errorAccSetShould(lirNames[op], accSet, "not contain bits that aren't in ACC_STORE_ANY"); + int nArgs = 2; LTy formals[2] = { LTy_Void, LTy_Ptr }; // LTy_Void is overwritten shortly LIns* args[2] = { value, base }; @@ -2873,6 +2916,13 @@ namespace nanojit LOpcode op = getCallOpcode(ci); + if (ci->_isPure && ci->_storeAccSet != ACC_NONE) + errorAccSetShould(ci->_name, ci->_storeAccSet, "equal ACC_NONE for pure functions"); + + if (ci->_storeAccSet & ~ACC_STORE_ANY) + errorAccSetShould(lirNames[op], ci->_storeAccSet, + "not contain bits that aren't in ACC_STORE_ANY"); + // This loop iterates over the args from right-to-left (because // arg() and get_sizes() use right-to-left order), but puts the // results into formals[] and args[] in left-to-right order so diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index 60c8bab32fee..a2a19da8feaf 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -62,7 +62,6 @@ namespace nanojit // pointer op aliases LIR_ldp = PTR_SIZE(LIR_ld, LIR_ldq), - LIR_ldcp = PTR_SIZE(LIR_ldc, LIR_ldqc), LIR_stpi = PTR_SIZE(LIR_sti, LIR_stqi), LIR_piadd = PTR_SIZE(LIR_add, LIR_qiadd), LIR_piand = PTR_SIZE(LIR_and, LIR_qiand), @@ -170,13 +169,132 @@ namespace nanojit CALL_INDIRECT = 0 }; + //----------------------------------------------------------------------- + // Aliasing + // -------- + // *Aliasing* occurs when a single memory location can be accessed through + // multiple names. For example, consider this code: + // + // ld a[0] + // sti b[0] + // ld a[0] + // + // In general, it's possible that a[0] and b[0] may refer to the same + // memory location. This means, for example, that you cannot safely + // perform CSE on the two loads. However, if you know that 'a' cannot be + // an alias of 'b' (ie. the two loads do not alias with the store) then + // you can safely perform CSE. + // + // Access regions + // -------------- + // Doing alias analysis precisely is difficult. But it turns out that + // keeping track of aliasing at a very coarse level is enough to help with + // many optimisations. So we conceptually divide the memory that is + // accessible from LIR into a small number of "access regions". An access + // region may be non-contiguous. No two access regions can overlap. The + // union of all access regions covers all memory accessible from LIR. + // + // In general a (static) load or store may be executed more than once, and + // thus may access multiple regions; however, in practice almost all + // loads and stores will obviously access only a single region. A + // function called from LIR may load and/or store multiple access regions + // (even if executed only once). + // + // If two loads/stores/calls are known to not access the same region(s), + // then they do not alias. + // + // The access regions used are as follows: + // + // - READONLY: all memory that is read-only, ie. never stored to. + // A load from a READONLY region will never alias with any stores. + // + // - STACK: the stack. Stack loads/stores can usually be easily + // identified because they use SP as the stack pointer. + // + // - OTHER: all other regions of memory. + // + // It makes sense to add new access regions when doing so will help with + // one or more optimisations. + // + // One subtlety is that the meanings of the access region markings only + // apply to the LIR fragment that they are in. For example, if a memory + // location M is read-only in a particular LIR fragment, all loads + // involving M in that fragment can be safely marked READONLY, even if M + // is modified elsewhere. This is safe because the a LIR fragment is the + // unit of analysis in which the markings are used. In other words alias + // region markings are only used for intra-fragment optimisations. + // + // Access region sets and instruction markings + // ------------------------------------------- + // The LIR generator must mark each load/store with an "access region + // set", which is a set of one or more access regions. This indicates + // which parts of LIR-accessible memory the load/store may touch. + // + // The LIR generator must also mark each function called from LIR with an + // access region set for memory stored to by the function. (We could also + // have a marking for memory loads, but there's no need at the moment.) + // These markings apply to the function itself, not the call site (ie. + // they're not context-sensitive). + // + // These load/store/call markings MUST BE ACCURATE -- if they are wrong + // then invalid optimisations might occur that change the meaning of the + // code. However, they can safely be imprecise (ie. conservative), in the + // following ways: + // + // - A load that accesses a READONLY region can be safely marked instead + // as loading from OTHER. In other words, it's safe to underestimate + // the size of the READONLY region. (This would also apply to the load + // set of a function, if we recorded that.) + // + // - A load/store can safely be marked as accessing regions that it + // doesn't, so long as the regions it does access are also included (one + // exception: marking a store with READONLY is nonsense and will cause + // assertions). + // + // In other words, a load/store can be marked with an access region set + // that is a superset of its actual access region set. Taking this to + // its logical conclusion, any load can be safely marked with LOAD_ANY and + // any store can be safely marked with with STORE_ANY (and the latter is + // true for the store set of a function.) + // + // Such imprecision is safe but may reduce optimisation opportunities. + //----------------------------------------------------------------------- + + // An access region set is represented as a bitset. Nb: this restricts us + // to at most eight alias regions for the moment. + typedef uint8_t AccSet; + + // The access regions. Note that because of the bitset representation + // these constants are also valid (singleton) AccSet values. If you add + // new ones please update ACC_ALL_WRITABLE and LirNameMap::formatAccSet(). + // + static const AccSet ACC_READONLY = 1 << 0; // 0000_0001b + static const AccSet ACC_STACK = 1 << 1; // 0000_0010b + static const AccSet ACC_OTHER = 1 << 2; // 0000_0100b + + // Some common (non-singleton) access region sets. ACC_NONE does not make + // sense for loads or stores (which must access at least one region), it + // only makes sense for calls. + // + // A convention that's worth using: use ACC_LOAD_ANY/ACC_STORE_ANY for + // cases that you're unsure about or haven't considered carefully. Use + // ACC_ALL/ACC_ALL_WRITABLE for cases that you have considered carefully. + // That way it's easy to tell which ones have been considered and which + // haven't. + static const AccSet ACC_NONE = 0x0; + static const AccSet ACC_ALL_WRITABLE = ACC_STACK | ACC_OTHER; + static const AccSet ACC_ALL = ACC_READONLY | ACC_ALL_WRITABLE; + static const AccSet ACC_LOAD_ANY = ACC_ALL; // synonym + static const AccSet ACC_STORE_ANY = ACC_ALL_WRITABLE; // synonym + + struct CallInfo { uintptr_t _address; uint32_t _argtypes:27; // 9 3-bit fields indicating arg type, by ARGSIZE above (including ret type): a1 a2 a3 a4 a5 ret - uint8_t _cse:1; // true if no side effects - uint8_t _fold:1; // true if no side effects AbiKind _abi:3; + uint8_t _isPure:1; // _isPure=1 means no side-effects, result only depends on args + AccSet _storeAccSet; // access regions stored by the function verbose_only ( const char* _name; ) uint32_t _count_args(uint32_t mask) const; @@ -479,8 +597,8 @@ namespace nanojit inline void initLInsOp1(LOpcode opcode, LIns* oprnd1); inline void initLInsOp2(LOpcode opcode, LIns* oprnd1, LIns* oprnd2); inline void initLInsOp3(LOpcode opcode, LIns* oprnd1, LIns* oprnd2, LIns* oprnd3); - inline void initLInsLd(LOpcode opcode, LIns* val, int32_t d); - inline void initLInsSti(LOpcode opcode, LIns* val, LIns* base, int32_t d); + inline void initLInsLd(LOpcode opcode, LIns* val, int32_t d, AccSet accSet); + inline void initLInsSti(LOpcode opcode, LIns* val, LIns* base, int32_t d, AccSet accSet); inline void initLInsSk(LIns* prevLIns); // Nb: args[] must be allocated and initialised before being passed in; // initLInsC() just copies the pointer into the LInsC. @@ -563,8 +681,9 @@ namespace nanojit // For guards. inline GuardRecord* record() const; - // Displacement for LInsLd/LInsSti + // For loads/stores. inline int32_t disp() const; + inline int32_t accSet() const; // For LInsSk. inline LIns* prevLIns() const; @@ -771,9 +890,9 @@ namespace nanojit bool isStmt() { NanoAssert(!isop(LIR_start) && !isop(LIR_skip)); // All instructions with Void retType are statements, as are calls - // to non-CSEable functions. + // to impure functions. if (isCall()) - return !callInfo()->_cse; + return !callInfo()->_isPure; else return isVoid(); } @@ -860,7 +979,12 @@ namespace nanojit private: friend class LIns; - int32_t disp; + // Nb: the LIR writer pipeline handles things if a displacement + // exceeds 16 bits. This is rare, but does happen occasionally. We + // could go to 24 bits but then it would happen so rarely that the + // handler code would be difficult to test and thus untrustworthy. + int16_t disp; + AccSet accSet; LIns* oprnd_1; @@ -876,7 +1000,8 @@ namespace nanojit private: friend class LIns; - int32_t disp; + int16_t disp; + AccSet accSet; LIns* oprnd_2; @@ -1033,21 +1158,23 @@ namespace nanojit toLInsOp3()->oprnd_3 = oprnd3; NanoAssert(isLInsOp3()); } - void LIns::initLInsLd(LOpcode opcode, LIns* val, int32_t d) { + void LIns::initLInsLd(LOpcode opcode, LIns* val, int32_t d, AccSet accSet) { clearReg(); clearArIndex(); lastWord.opcode = opcode; toLInsLd()->oprnd_1 = val; toLInsLd()->disp = d; + toLInsLd()->accSet = accSet; NanoAssert(isLInsLd()); } - void LIns::initLInsSti(LOpcode opcode, LIns* val, LIns* base, int32_t d) { + void LIns::initLInsSti(LOpcode opcode, LIns* val, LIns* base, int32_t d, AccSet accSet) { clearReg(); clearArIndex(); lastWord.opcode = opcode; toLInsSti()->oprnd_1 = val; toLInsSti()->oprnd_2 = base; toLInsSti()->disp = d; + toLInsSti()->accSet = accSet; NanoAssert(isLInsSti()); } void LIns::initLInsSk(LIns* prevLIns) { @@ -1166,6 +1293,15 @@ namespace nanojit } } + int32_t LIns::accSet() const { + if (isLInsSti()) { + return toLInsSti()->accSet; + } else { + NanoAssert(isLInsLd()); + return toLInsLd()->accSet; + } + } + LIns* LIns::prevLIns() const { NanoAssert(isLInsSk()); return toLInsSk()->prevLIns; @@ -1278,11 +1414,11 @@ namespace nanojit virtual LInsp insImmf(double d) { return out->insImmf(d); } - virtual LInsp insLoad(LOpcode op, LIns* base, int32_t d) { - return out->insLoad(op, base, d); + virtual LInsp insLoad(LOpcode op, LIns* base, int32_t d, AccSet accSet) { + return out->insLoad(op, base, d, accSet); } - virtual LInsp insStore(LOpcode op, LIns* value, LIns* base, int32_t d) { - return out->insStore(op, value, base, d); + virtual LInsp insStore(LOpcode op, LIns* value, LIns* base, int32_t d, AccSet accSet) { + return out->insStore(op, value, base, d, accSet); } // args[] is in reverse order, ie. args[0] holds the rightmost arg. virtual LInsp insCall(const CallInfo *call, LInsp args[]) { @@ -1300,24 +1436,41 @@ namespace nanojit // Inserts a conditional to execute and branches to execute if // the condition is true and false respectively. - LIns* ins_choose(LIns* cond, LIns* iftrue, LIns* iffalse, bool use_cmov); + LIns* ins_choose(LIns* cond, LIns* iftrue, LIns* iffalse, bool use_cmov); + // Inserts an integer comparison to 0 - LIns* ins_eq0(LIns* oprnd1); + LIns* ins_eq0(LIns* oprnd1); + // Inserts a pointer comparison to 0 - LIns* ins_peq0(LIns* oprnd1); + LIns* ins_peq0(LIns* oprnd1); + // Inserts a binary operation where the second operand is an // integer immediate. - LIns* ins2i(LOpcode op, LIns *oprnd1, int32_t); + LIns* ins2i(LOpcode op, LIns *oprnd1, int32_t); + #if NJ_SOFTFLOAT_SUPPORTED - LIns* qjoin(LInsp lo, LInsp hi); + LIns* qjoin(LInsp lo, LInsp hi); #endif - LIns* insImmPtr(const void *ptr); - LIns* insImmWord(intptr_t ptr); + LIns* insImmPtr(const void *ptr); + LIns* insImmWord(intptr_t ptr); + // Sign or zero extend integers to native integers. On 32-bit this is a no-op. - LIns* ins_i2p(LIns* intIns); - LIns* ins_u2p(LIns* uintIns); - // choose LIR_sti or LIR_stqi based on size of value - LIns* insStorei(LIns* value, LIns* base, int32_t d); + LIns* ins_i2p(LIns* intIns); + LIns* ins_u2p(LIns* uintIns); + + // Chooses LIR_sti or LIR_stqi based on size of value. + LIns* insStorei(LIns* value, LIns* base, int32_t d, AccSet accSet); + + // Insert a load/store with the most pessimistic region access info, which is always safe. + LIns* insLoad(LOpcode op, LIns* base, int32_t d) { + return insLoad(op, base, d, ACC_LOAD_ANY); + } + LIns* insStore(LOpcode op, LIns* value, LIns* base, int32_t d) { + return insStore(op, value, base, d, ACC_STORE_ANY); + } + LIns* insStorei(LIns* value, LIns* base, int32_t d) { + return insStorei(value, base, d, ACC_STORE_ANY); + } }; @@ -1392,6 +1545,7 @@ namespace nanojit void addName(LInsp i, const char *s); void copyName(LInsp i, const char *s, int suffix); + char* formatAccSet(LInsp ins, bool isLoad, char* buf); const char *formatRef(LIns *ref); const char *formatIns(LInsp i); void formatGuard(LInsp i, char *buf); @@ -1479,11 +1633,11 @@ namespace nanojit LIns* insParam(int32_t i, int32_t kind) { return add(out->insParam(i, kind)); } - LIns* insLoad(LOpcode v, LInsp base, int32_t disp) { - return add(out->insLoad(v, base, disp)); + LIns* insLoad(LOpcode v, LInsp base, int32_t disp, AccSet accSet) { + return add(out->insLoad(v, base, disp, accSet)); } - LIns* insStore(LOpcode op, LInsp v, LInsp b, int32_t d) { - return add(out->insStore(op, v, b, d)); + LIns* insStore(LOpcode op, LInsp v, LInsp b, int32_t d, AccSet accSet) { + return add(out->insStore(op, v, b, d, accSet)); } LIns* insAlloc(int32_t size) { return add(out->insAlloc(size)); @@ -1513,7 +1667,7 @@ namespace nanojit LIns* insGuard(LOpcode, LIns *cond, GuardRecord *); LIns* insGuardXov(LOpcode, LIns* a, LIns* b, GuardRecord *); LIns* insBranch(LOpcode, LIns *cond, LIns *target); - LIns* insLoad(LOpcode op, LInsp base, int32_t off); + LIns* insLoad(LOpcode op, LInsp base, int32_t off, AccSet accSet); }; enum LInsHashKind { @@ -1617,7 +1771,7 @@ namespace nanojit LIns* ins1(LOpcode v, LInsp); LIns* ins2(LOpcode v, LInsp, LInsp); LIns* ins3(LOpcode v, LInsp, LInsp, LInsp); - LIns* insLoad(LOpcode op, LInsp cond, int32_t d); + LIns* insLoad(LOpcode op, LInsp cond, int32_t d, AccSet accSet); LIns* insCall(const CallInfo *call, LInsp args[]); LIns* insGuard(LOpcode op, LInsp cond, GuardRecord *gr); LIns* insGuardXov(LOpcode op, LInsp a, LInsp b, GuardRecord *gr); @@ -1675,8 +1829,8 @@ namespace nanojit } // LirWriter interface - LInsp insLoad(LOpcode op, LInsp base, int32_t disp); - LInsp insStore(LOpcode op, LInsp o1, LInsp o2, int32_t disp); + LInsp insLoad(LOpcode op, LInsp base, int32_t disp, AccSet accSet); + LInsp insStore(LOpcode op, LInsp o1, LInsp o2, int32_t disp, AccSet accSet); LInsp ins0(LOpcode op); LInsp ins1(LOpcode op, LInsp o1); LInsp ins2(LOpcode op, LInsp o1, LInsp o2); @@ -1783,8 +1937,8 @@ namespace nanojit } LInsp ins0(LOpcode); - LInsp insLoad(LOpcode, LInsp base, int32_t disp); - LInsp insStore(LOpcode op, LInsp v, LInsp b, int32_t d); + LInsp insLoad(LOpcode op, LInsp base, int32_t disp, AccSet accSet); + LInsp insStore(LOpcode op, LInsp value, LInsp base, int32_t disp, AccSet accSet); LInsp insCall(const CallInfo *call, LInsp args[]); }; @@ -1837,14 +1991,15 @@ namespace nanojit void typeCheckArgs(LOpcode op, int nArgs, LTy formals[], LIns* args[]); void errorStructureShouldBe(LOpcode op, const char* argDesc, int argN, LIns* arg, const char* shouldBeDesc); + void errorAccSetShould(const char* what, AccSet accSet, const char* shouldDesc); void checkLInsHasOpcode(LOpcode op, int argN, LIns* ins, LOpcode op2); void checkLInsIsACondOrConst(LOpcode op, int argN, LIns* ins); void checkLInsIsNull(LOpcode op, int argN, LIns* ins); public: ValidateWriter(LirWriter* out, const char* stageName); - LIns* insLoad(LOpcode op, LIns* base, int32_t d); - LIns* insStore(LOpcode op, LIns* value, LIns* base, int32_t d); + LIns* insLoad(LOpcode op, LIns* base, int32_t d, AccSet accSet); + LIns* insStore(LOpcode op, LIns* value, LIns* base, int32_t d, AccSet accSet); LIns* ins0(LOpcode v); LIns* ins1(LOpcode v, LIns* a); LIns* ins2(LOpcode v, LIns* a, LIns* b); diff --git a/js/src/nanojit/LIRopcode.tbl b/js/src/nanojit/LIRopcode.tbl index 7c18267caaff..91b715308291 100644 --- a/js/src/nanojit/LIRopcode.tbl +++ b/js/src/nanojit/LIRopcode.tbl @@ -102,14 +102,14 @@ OP___(regfence, 1, Op0, Void, 0) // register fence, no register allocation is OP___(skip, 2, Sk, Void, 0) // used to link code chunks // Impure operations. -OP___(ldsb, 3, Ld, I32, 0) // 8-bit integer load, sign-extend to 32-bit -OP___(ldss, 4, Ld, I32, 0) // 16-bit integer load, sign-extend to 32-bit -OP___(ldzb, 5, Ld, I32, 0) // 8-bit integer load, zero extend to 32-bit -OP___(ldzs, 6, Ld, I32, 0) // 16-bit integer load, zero extend to 32-bit +OP___(ldsb, 3, Ld, I32, -1) // 8-bit integer load, sign-extend to 32-bit +OP___(ldss, 4, Ld, I32, -1) // 16-bit integer load, sign-extend to 32-bit +OP___(ldzb, 5, Ld, I32, -1) // 8-bit integer load, zero-extend to 32-bit +OP___(ldzs, 6, Ld, I32, -1) // 16-bit integer load, zero-extend to 32-bit OP_32(iaddp, 7, Op2, I32, 0) // 32-bit integer addition for temporary pointer calculations OP_32(iparam, 8, P, I32, 0) // load a parameter (32-bit register or stack location) -OP___(stb, 9, Sti, Void, 0) // 8-bit integer store -OP___(ld, 10, Ld, I32, 0) // 32-bit integer load +OP___(stb, 9, Sti, Void, 0) // 8-bit integer store +OP___(ld, 10, Ld, I32, -1) // 32-bit integer load OP_32(ialloc, 11, I, I32, 0) // allocate some stack space (result is a 32-bit address) OP___(sti, 12, Sti, Void, 0) // 32-bit integer store OP___(ret, 13, Op1, Void, 0) // return a 32-bit integer @@ -147,9 +147,9 @@ OP___(fgt, 29, Op2, I32, 1) // floating-point greater-than OP___(fle, 30, Op2, I32, 1) // floating-point less-than-or-equal OP___(fge, 31, Op2, I32, 1) // floating-point greater-than-or-equal -OP___(ldcb, 32, Ld, I32, 1) // non-volatile 8-bit integer load, zero-extended to 32-bit -OP___(ldcs, 33, Ld, I32, 1) // non-volatile 16-bit integer load, zero-extended to 32-bit -OP___(ldc, 34, Ld, I32, 1) // non-volatile 32-bit integer load, zero-extended to 32-bit +OP_UN(32) +OP_UN(33) +OP_UN(34) OP___(neg, 35, Op1, I32, 1) // 32-bit integer negation OP___(add, 36, Op2, I32, 1) // 32-bit integer addition @@ -177,8 +177,8 @@ OP___(xf, 49, Op2, Void, 1) // exit if false (0x31 0011 0001) OP_SF(qlo, 50, Op1, I32, 1) // get the low 32 bits of a 64-bit value OP_SF(qhi, 51, Op1, I32, 1) // get the high 32 bits of a 64-bit value -OP___(ldcsb, 52, Ld, I32, 1) // non-volatile 8-bit integer load, sign-extended to 32-bit -OP___(ldcss, 53, Ld, I32, 1) // non-volatile 16-bit integer load, sign-extended to 32-bit +OP_UN(52) +OP_UN(53) OP___(addxov, 54, Op3, I32, 1) // 32-bit integer addition; exit if overflow occurred, result is valid on either path OP___(subxov, 55, Op3, I32, 1) // 32-bit integer subtraction; exit if overflow occurred, result is valid on either path @@ -209,15 +209,15 @@ OP_64(qlive, 70, Op1, Void, 0) // extend live range of a 64-bit integer OP_64(qaddp, 71, Op2, I64, 0) // 64-bit integer addition for temp pointer calculations OP_64(qparam, 72, P, I64, 0) // load a parameter (64bit register or stack location) -OP___(ldf, 73, Ld, F64, 0) // 64-bit float load -OP_64(ldq, 74, Ld, I64, 0) // 64-bit integer load +OP___(ldf, 73, Ld, F64, -1) // 64-bit float load +OP_64(ldq, 74, Ld, I64, -1) // 64-bit integer load OP_64(qalloc, 75, I, I64, 0) // allocate some stack space (result is a 64-bit address) OP_64(stqi, 76, Sti, Void, 0) // 64-bit integer store OP___(st32f, 77, Sti, Void, 0) // store 64-bit float as a 32-bit float (dropping precision) -OP___(ld32f, 78, Ld, F64, 0) // load 32-bit float and widen to 64-bit float +OP___(ld32f, 78, Ld, F64, -1) // load 32-bit float and widen to 64-bit float OP___(fcall, 79, C, F64, -1) // subroutine call returning 64-bit float value OP_64(qcall, 80, C, I64, -1) // subroutine call returning 64-bit integer value @@ -243,9 +243,8 @@ OP___(f2i, 94, Op1, I32, 1) // f2i conversion, no exception raised, plat OP_UN(95) OP_UN(96) - -OP___(ldfc, 97, Ld, F64, 1) // non-volatile 64-bit float load -OP_64(ldqc, 98, Ld, I64, 1) // non-volatile 64-bit integer load +OP_UN(97) +OP_UN(98) OP___(fneg, 99, Op1, F64, 1) // floating-point negation OP___(fadd, 100, Op2, F64, 1) // floating-point addition @@ -267,11 +266,14 @@ OP_64(qirsh, 110, Op2, I64, 1) // 64-bit signed right shift; 2nd operand OP_64(qursh, 111, Op2, I64, 1) // 64-bit unsigned right shift; 2nd operand is a 32-bit integer OP_64(qiadd, 112, Op2, I64, 1) // 64-bit bitwise ADD -OP___(ldc32f, 113, Ld, F64, 1) // non-volatile load 32-bit float and widen to 64-bit float +OP_UN(113) + OP_SF(qjoin, 114, Op2, F64, 1) // join two 32-bit values (1st arg is low bits, 2nd is high) OP_64(q2i, 115, Op1, I32, 1) // truncate i64 to i32 + OP_UN(116) OP_UN(117) + OP___(float, 118, N64, F64, 1) // 64-bit float constant value // 64-bit integer comparisons. Their order must be preserved so that, except diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index aac2ce43cd83..2cd25386920f 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -1326,7 +1326,6 @@ Assembler::asm_load64(LInsp ins) switch (ins->opcode()) { case LIR_ldf: - case LIR_ldfc: if (_config.arm_vfp && deprecated_isKnownReg(rr)) { // VFP is enabled and the result will go into a register. NanoAssert(IsFpReg(rr)); @@ -1353,7 +1352,6 @@ Assembler::asm_load64(LInsp ins) return; case LIR_ld32f: - case LIR_ldc32f: if (_config.arm_vfp) { if (deprecated_isKnownReg(rr)) { NanoAssert(IsFpReg(rr)); @@ -2555,7 +2553,6 @@ Assembler::asm_load32(LInsp ins) switch (op) { case LIR_ldzb: - case LIR_ldcb: if (isU12(-d) || isU12(d)) { LDRB(rr, ra, d); } else { @@ -2564,7 +2561,6 @@ Assembler::asm_load32(LInsp ins) } return; case LIR_ldzs: - case LIR_ldcs: // Some ARM machines require 2-byte alignment here. // Similar to the ldcb/ldzb case, but the max offset is smaller. if (isU8(-d) || isU8(d)) { @@ -2575,7 +2571,6 @@ Assembler::asm_load32(LInsp ins) } return; case LIR_ld: - case LIR_ldc: // Some ARM machines require 4-byte alignment here. if (isU12(-d) || isU12(d)) { LDR(rr, ra, d); @@ -2585,7 +2580,6 @@ Assembler::asm_load32(LInsp ins) } return; case LIR_ldsb: - case LIR_ldcsb: if (isU8(-d) || isU8(d)) { LDRSB(rr, ra, d); } else { @@ -2594,7 +2588,6 @@ Assembler::asm_load32(LInsp ins) } return; case LIR_ldss: - case LIR_ldcss: if (isU8(-d) || isU8(d)) { LDRSH(rr, ra, d); } else { diff --git a/js/src/nanojit/NativeMIPS.cpp b/js/src/nanojit/NativeMIPS.cpp index 1a3f7e8ad982..f0e3251b1bd0 100644 --- a/js/src/nanojit/NativeMIPS.cpp +++ b/js/src/nanojit/NativeMIPS.cpp @@ -668,8 +668,6 @@ namespace nanojit void Assembler::asm_load64(LIns *ins) { - NanoAssert(!ins->isop(LIR_ldq) && !ins->isop(LIR_ldqc)); - NanoAssert(ins->isF64()); LIns* base = ins->oprnd1(); @@ -879,23 +877,18 @@ namespace nanojit Register rbase = getBaseReg(base, d, GpRegs); switch (op) { - case LIR_ldcb: case LIR_ldzb: // 8-bit integer load, zero-extend to 32-bit asm_ldst(OP_LBU, rres, d, rbase); break; - case LIR_ldcs: case LIR_ldzs: // 16-bit integer load, zero-extend to 32-bit asm_ldst(OP_LHU, rres, d, rbase); break; - case LIR_ldcsb: case LIR_ldsb: // 8-bit integer load, sign-extend to 32-bit asm_ldst(OP_LB, rres, d, rbase); break; - case LIR_ldcss: case LIR_ldss: // 16-bit integer load, sign-extend to 32-bit asm_ldst(OP_LH, rres, d, rbase); break; - case LIR_ldc: case LIR_ld: // 32-bit integer load asm_ldst(OP_LW, rres, d, rbase); break; @@ -1112,8 +1105,7 @@ namespace nanojit if (value->isconstq()) asm_store_imm64(value, dr, rbase); - else if (!cpu_has_fpu || - value->isop(LIR_ldq) || value->isop(LIR_ldqc)) { + else if (!cpu_has_fpu || value->isop(LIR_ldq)) { int ds = findMemFor(value); diff --git a/js/src/nanojit/NativePPC.cpp b/js/src/nanojit/NativePPC.cpp index fdca2a6bf795..c695a0f16fe3 100644 --- a/js/src/nanojit/NativePPC.cpp +++ b/js/src/nanojit/NativePPC.cpp @@ -139,7 +139,6 @@ namespace nanojit switch(ins->opcode()) { case LIR_ldzb: - case LIR_ldcb: if (isS16(d)) { LBZ(rr, d, ra); } else { @@ -148,7 +147,6 @@ namespace nanojit } return; case LIR_ldzs: - case LIR_ldcs: // these are expected to be 2 or 4-byte aligned if (isS16(d)) { LHZ(rr, d, ra); @@ -158,7 +156,6 @@ namespace nanojit } return; case LIR_ld: - case LIR_ldc: // these are expected to be 4-byte aligned if (isS16(d)) { LWZ(rr, d, ra); @@ -169,8 +166,6 @@ namespace nanojit return; case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: NanoAssertMsg(0, "NJ_EXPANDED_LOADSTORE_SUPPORTED not yet supported for this architecture"); return; default: @@ -213,13 +208,10 @@ namespace nanojit switch (ins->opcode()) { case LIR_ldf: - case LIR_ldfc: CASE64(LIR_ldq:) - CASE64(LIR_ldqc:) // handled by mainline code below for now break; case LIR_ld32f: - case LIR_ldc32f: NanoAssertMsg(0, "NJ_EXPANDED_LOADSTORE_SUPPORTED not yet supported for this architecture"); return; default: diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 924445b7905c..0bcc0a59ffd2 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -330,11 +330,9 @@ namespace nanojit { switch (ins->opcode()) { case LIR_ldf: - case LIR_ldfc: // handled by mainline code below for now break; case LIR_ld32f: - case LIR_ldc32f: NanoAssertMsg(0, "NJ_EXPANDED_LOADSTORE_SUPPORTED not yet supported for this architecture"); return; default: @@ -398,7 +396,7 @@ namespace nanojit return; } - if (value->isop(LIR_ldf) || value->isop(LIR_ldfc)) + if (value->isop(LIR_ldf)) { // value is 64bit struct or int64_t, or maybe a double. // it may be live in an FPU reg. Either way, don't @@ -737,21 +735,16 @@ namespace nanojit Register ra = getBaseReg(base, d, GpRegs); switch(op) { case LIR_ldzb: - case LIR_ldcb: LDUB32(ra, d, rr); break; case LIR_ldzs: - case LIR_ldcs: LDUH32(ra, d, rr); break; case LIR_ld: - case LIR_ldc: LDSW32(ra, d, rr); break; case LIR_ldsb: case LIR_ldss: - case LIR_ldcsb: - case LIR_ldcss: NanoAssertMsg(0, "NJ_EXPANDED_LOADSTORE_SUPPORTED not yet supported for this architecture"); return; default: diff --git a/js/src/nanojit/NativeX64.cpp b/js/src/nanojit/NativeX64.cpp index 6cab6ac007de..5d5c9b9e1d3a 100644 --- a/js/src/nanojit/NativeX64.cpp +++ b/js/src/nanojit/NativeX64.cpp @@ -1474,19 +1474,16 @@ namespace nanojit int32_t dr; switch (ins->opcode()) { case LIR_ldq: - case LIR_ldqc: beginLoadRegs(ins, GpRegs, rr, dr, rb); NanoAssert(IsGpReg(rr)); MOVQRM(rr, dr, rb); // general 64bit load, 32bit const displacement break; case LIR_ldf: - case LIR_ldfc: beginLoadRegs(ins, FpRegs, rr, dr, rb); NanoAssert(IsFpReg(rr)); MOVSDRM(rr, dr, rb); // load 64bits into XMM break; case LIR_ld32f: - case LIR_ldc32f: beginLoadRegs(ins, FpRegs, rr, dr, rb); NanoAssert(IsFpReg(rr)); CVTSS2SD(rr, rr); @@ -1505,25 +1502,20 @@ namespace nanojit int32_t d; beginLoadRegs(ins, GpRegs, r, d, b); LOpcode op = ins->opcode(); - switch(op) { + switch (op) { case LIR_ldzb: - case LIR_ldcb: MOVZX8M( r, d, b); break; case LIR_ldzs: - case LIR_ldcs: MOVZX16M(r, d, b); break; case LIR_ld: - case LIR_ldc: MOVLRM( r, d, b); break; case LIR_ldsb: - case LIR_ldcsb: MOVSX8M( r, d, b); break; case LIR_ldss: - case LIR_ldcss: MOVSX16M( r, d, b); break; default: diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index 032d318f6be8..dd4e5c5c1758 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -504,7 +504,6 @@ namespace nanojit asm_spilli(ins, false); // if also in memory in post-state, spill it now switch (ins->opcode()) { case LIR_ldf: - case LIR_ldfc: if (rmask(rr) & XmmRegs) { SSE_LDQ(rr, db, rb); } else { @@ -514,7 +513,6 @@ namespace nanojit break; case LIR_ld32f: - case LIR_ldc32f: if (rmask(rr) & XmmRegs) { SSE_CVTSS2SD(rr, rr); SSE_LDSS(rr, db, rb); @@ -536,13 +534,11 @@ namespace nanojit switch (ins->opcode()) { case LIR_ldf: - case LIR_ldfc: // Don't use an fpu reg to simply load & store the value. asm_mmq(FP, dr, rb, db); break; case LIR_ld32f: - case LIR_ldc32f: // Need to use fpu to expand 32->64. FSTPQ(dr, FP); FLD32(db, rb); @@ -584,7 +580,7 @@ namespace nanojit STi(rb, dr+4, value->imm64_1()); STi(rb, dr, value->imm64_0()); - } else if (value->isop(LIR_ldf) || value->isop(LIR_ldfc)) { + } else if (value->isop(LIR_ldf)) { // value is 64bit struct or int64_t, or maybe a double. // It may be live in an FPU reg. Either way, don't put it in an // FPU reg just to load & store it. @@ -1053,23 +1049,18 @@ namespace nanojit addr += d; switch (op) { case LIR_ldzb: - case LIR_ldcb: LD8Zdm(rr, addr); break; case LIR_ldsb: - case LIR_ldcsb: LD8Sdm(rr, addr); break; case LIR_ldzs: - case LIR_ldcs: LD16Zdm(rr, addr); break; case LIR_ldss: - case LIR_ldcss: LD16Sdm(rr, addr); break; case LIR_ld: - case LIR_ldc: LDdm(rr, addr); break; default: @@ -1127,23 +1118,18 @@ namespace nanojit switch (op) { case LIR_ldzb: - case LIR_ldcb: LD8Zsib(rr, d, ra, rb, scale); break; case LIR_ldsb: - case LIR_ldcsb: LD8Ssib(rr, d, ra, rb, scale); break; case LIR_ldzs: - case LIR_ldcs: LD16Zsib(rr, d, ra, rb, scale); break; case LIR_ldss: - case LIR_ldcss: LD16Ssib(rr, d, ra, rb, scale); break; case LIR_ld: - case LIR_ldc: LDsib(rr, d, ra, rb, scale); break; default: @@ -1165,23 +1151,18 @@ namespace nanojit switch (op) { case LIR_ldzb: - case LIR_ldcb: LD8Z(rr, d, ra); break; case LIR_ldsb: - case LIR_ldcsb: LD8S(rr, d, ra); break; case LIR_ldzs: - case LIR_ldcs: LD16Z(rr, d, ra); break; case LIR_ldss: - case LIR_ldcss: LD16S(rr, d, ra); break; case LIR_ld: - case LIR_ldc: LD(rr, d, ra); break; default: From 380c80bfcbdfd8ab34a52fcbd56b269609c964b4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 2 Mar 2010 12:50:19 +1100 Subject: [PATCH 19/52] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index d423c37e116a..a1fffba92591 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -05949faa5b451d5452c9b5eb95296a53b555dda1 +4adbf1bbb16cf4751b46a49a4f9c474c0ab0a3b9 From ecf1dcc241c863121ba560420e8a944552f7d7a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 2 Mar 2010 13:47:17 +1100 Subject: [PATCH 20/52] Bug 545274 - nanojit: start adding alias info to loads/stores/calls (TM-specific part). r=jseward. --- content/canvas/src/CustomQS_WebGL.h | 22 +++--- js/src/jsarray.cpp | 28 +++++--- js/src/jsbuiltins.cpp | 44 ++++++------ js/src/jsbuiltins.h | 105 +++++++++++++++++----------- js/src/jsdate.cpp | 4 +- js/src/jsfun.cpp | 23 +++--- js/src/jsiter.cpp | 2 +- js/src/jsmath.cpp | 26 +++---- js/src/jsnum.cpp | 12 ++-- js/src/jsobj.cpp | 18 +++-- js/src/jsregexp.cpp | 14 ++-- js/src/jsstr.cpp | 32 +++++---- js/src/jstracer.cpp | 103 ++++++++++++++------------- js/src/jstracer.h | 5 +- js/src/jstypedarray.cpp | 2 +- js/src/xpconnect/src/qsgen.py | 2 +- 16 files changed, 253 insertions(+), 189 deletions(-) diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index c505abbccb08..2d479060e59d 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -936,7 +936,7 @@ nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -945,7 +945,7 @@ nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -954,7 +954,7 @@ nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -963,7 +963,7 @@ nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -972,7 +972,7 @@ nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -981,7 +981,7 @@ nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -990,7 +990,7 @@ nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) @@ -999,7 +999,7 @@ nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, uint3 } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg) @@ -1008,7 +1008,7 @@ nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv, - (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0))) + (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg) @@ -1017,7 +1017,7 @@ nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv, - (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0))) + (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY))) static jsval FASTCALL nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg) @@ -1026,6 +1026,6 @@ nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, } JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv, - (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0))) + (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY))) #endif /* JS_TRACER */ diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 026ddee28ea2..b8ff12c1e9de 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -950,7 +950,8 @@ js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v) JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); return dense_grow(cx, obj, i, v); } -JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, + nanojit::ACC_STORE_ANY) JSBool FASTCALL js_Array_dense_setelem_int(JSContext* cx, JSObject* obj, jsint i, int32 j) @@ -968,7 +969,8 @@ js_Array_dense_setelem_int(JSContext* cx, JSObject* obj, jsint i, int32 j) return dense_grow(cx, obj, i, v); } -JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_int, CONTEXT, OBJECT, INT32, INT32, 0, 0) +JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_int, CONTEXT, OBJECT, INT32, INT32, 0, + nanojit::ACC_STORE_ANY) JSBool FASTCALL js_Array_dense_setelem_double(JSContext* cx, JSObject* obj, jsint i, jsdouble d) @@ -987,7 +989,8 @@ js_Array_dense_setelem_double(JSContext* cx, JSObject* obj, jsint i, jsdouble d) return dense_grow(cx, obj, i, v); } -JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_double, CONTEXT, OBJECT, INT32, DOUBLE, 0, 0) +JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_double, CONTEXT, OBJECT, INT32, DOUBLE, + 0, nanojit::ACC_STORE_ANY) #endif static JSBool @@ -2426,7 +2429,8 @@ js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v) obj->dslots[length] = v; return JS_TRUE; } -JS_DEFINE_CALLINFO_3(extern, BOOL, js_ArrayCompPush, CONTEXT, OBJECT, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_3(extern, BOOL, js_ArrayCompPush, CONTEXT, OBJECT, JSVAL, 0, + nanojit::ACC_STORE_ANY) #ifdef JS_TRACER static jsval FASTCALL @@ -3309,13 +3313,13 @@ static JSPropertySpec array_props[] = { }; JS_DEFINE_TRCINFO_1(array_toString, - (2, (static, STRING_FAIL, Array_p_toString, CONTEXT, THIS, 0, 0))) + (2, (static, STRING_FAIL, Array_p_toString, CONTEXT, THIS, 0, nanojit::ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(array_join, - (3, (static, STRING_FAIL, Array_p_join, CONTEXT, THIS, STRING, 0, 0))) + (3, (static, STRING_FAIL, Array_p_join, CONTEXT, THIS, STRING, 0, nanojit::ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(array_push, - (3, (static, JSVAL_FAIL, Array_p_push1, CONTEXT, THIS, JSVAL, 0, 0))) + (3, (static, JSVAL_FAIL, Array_p_push1, CONTEXT, THIS, JSVAL, 0, nanojit::ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(array_pop, - (2, (static, JSVAL_FAIL, Array_p_pop, CONTEXT, THIS, 0, 0))) + (2, (static, JSVAL_FAIL, Array_p_pop, CONTEXT, THIS, 0, nanojit::ACC_STORE_ANY))) static JSFunctionSpec array_methods[] = { #if JS_HAS_TOSOURCE @@ -3416,7 +3420,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto) return obj; } #ifdef JS_TRACER -JS_DEFINE_CALLINFO_2(extern, OBJECT, js_NewEmptyArray, CONTEXT, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_2(extern, OBJECT, js_NewEmptyArray, CONTEXT, OBJECT, 0, nanojit::ACC_STORE_ANY) #endif JSObject* JS_FASTCALL @@ -3431,7 +3435,8 @@ js_NewEmptyArrayWithLength(JSContext* cx, JSObject* proto, int32 len) return obj; } #ifdef JS_TRACER -JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewEmptyArrayWithLength, CONTEXT, OBJECT, INT32, 0, 0) +JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewEmptyArrayWithLength, CONTEXT, OBJECT, INT32, 0, + nanojit::ACC_STORE_ANY) #endif JSObject* JS_FASTCALL @@ -3446,7 +3451,8 @@ js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len) return obj; } #ifdef JS_TRACER -JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewArrayWithSlots, CONTEXT, OBJECT, UINT32, 0, 0) +JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewArrayWithSlots, CONTEXT, OBJECT, UINT32, 0, + nanojit::ACC_STORE_ANY) #endif JSObject * diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 5f2e325a4281..5e6ea36d091e 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -90,7 +90,7 @@ js_dmod(jsdouble a, jsdouble b) } return js_fmod(a, b); } -JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, 1) +JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, ACC_NONE) int32 FASTCALL js_imod(int32 a, int32 b) @@ -100,7 +100,7 @@ js_imod(int32 a, int32 b) int r = a % b; return r; } -JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, 1) +JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACC_NONE) /* The following boxing/unboxing primitives we can't emit inline because they either interact with the GC and depend on Spidermonkey's 32-bit @@ -118,7 +118,7 @@ js_BoxDouble(JSContext* cx, jsdouble d) return JSVAL_ERROR_COOKIE; return v; } -JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxDouble, CONTEXT, DOUBLE, 1, 1) +JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxDouble, CONTEXT, DOUBLE, 1, ACC_NONE) jsval FASTCALL js_BoxInt32(JSContext* cx, int32 i) @@ -132,7 +132,7 @@ js_BoxInt32(JSContext* cx, int32 i) return JSVAL_ERROR_COOKIE; return v; } -JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, 1) +JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, ACC_NONE) jsdouble FASTCALL js_UnboxDouble(jsval v) @@ -141,7 +141,7 @@ js_UnboxDouble(jsval v) return (jsdouble)JSVAL_TO_INT(v); return *JSVAL_TO_DOUBLE(v); } -JS_DEFINE_CALLINFO_1(extern, DOUBLE, js_UnboxDouble, JSVAL, 1, 1) +JS_DEFINE_CALLINFO_1(extern, DOUBLE, js_UnboxDouble, JSVAL, 1, ACC_NONE) int32 FASTCALL js_UnboxInt32(jsval v) @@ -150,7 +150,7 @@ js_UnboxInt32(jsval v) return JSVAL_TO_INT(v); return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v)); } -JS_DEFINE_CALLINFO_1(extern, INT32, js_UnboxInt32, JSVAL, 1, 1) +JS_DEFINE_CALLINFO_1(extern, INT32, js_UnboxInt32, JSVAL, 1, ACC_NONE) JSBool FASTCALL js_TryUnboxInt32(jsval v, int32* i32p) @@ -168,21 +168,21 @@ js_TryUnboxInt32(jsval v, int32* i32p) *i32p = i; return JS_TRUE; } -JS_DEFINE_CALLINFO_2(extern, BOOL, js_TryUnboxInt32, JSVAL, INT32PTR, 1, 1) +JS_DEFINE_CALLINFO_2(extern, BOOL, js_TryUnboxInt32, JSVAL, INT32PTR, 1, ACC_NONE) int32 FASTCALL js_DoubleToInt32(jsdouble d) { return js_DoubleToECMAInt32(d); } -JS_DEFINE_CALLINFO_1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, 1) +JS_DEFINE_CALLINFO_1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, ACC_NONE) uint32 FASTCALL js_DoubleToUint32(jsdouble d) { return js_DoubleToECMAUint32(d); } -JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, 1) +JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, ACC_NONE) jsdouble FASTCALL js_StringToNumber(JSContext* cx, JSString* str) @@ -201,7 +201,7 @@ js_StringToNumber(JSContext* cx, JSString* str) } return d; } -JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, 1) +JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, ACC_NONE) int32 FASTCALL js_StringToInt32(JSContext* cx, JSString* str) @@ -227,7 +227,7 @@ js_StringToInt32(JSContext* cx, JSString* str) } return js_DoubleToECMAInt32(d); } -JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, 1) +JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, ACC_NONE) JSBool FASTCALL js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) @@ -282,7 +282,7 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) JS_UNLOCK_SCOPE(cx, scope); return JS_FALSE; } -JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, 0) +JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, ACC_STORE_ANY) static JSBool HasProperty(JSContext* cx, JSObject* obj, jsid id) @@ -314,7 +314,7 @@ js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr) return HasProperty(cx, obj, id); } -JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING, 0, 0) +JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING, 0, ACC_STORE_ANY) JSBool FASTCALL js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index) @@ -325,7 +325,8 @@ js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index) return HasProperty(cx, obj, id); } -JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32, 0, 0) +JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32, 0, + ACC_STORE_ANY) JSString* FASTCALL js_TypeOfObject(JSContext* cx, JSObject* obj) @@ -334,7 +335,7 @@ js_TypeOfObject(JSContext* cx, JSObject* obj) return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_OBJECT]); return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[obj->typeOf(cx)]); } -JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, 1) +JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, ACC_NONE) JSString* FASTCALL js_TypeOfBoolean(JSContext* cx, int32 unboxed) @@ -345,7 +346,7 @@ js_TypeOfBoolean(JSContext* cx, int32 unboxed) JSType type = JS_TypeOfValue(cx, boxed); return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]); } -JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfBoolean, CONTEXT, INT32, 1, 1) +JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfBoolean, CONTEXT, INT32, 1, ACC_NONE) jsdouble FASTCALL js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed) @@ -355,7 +356,7 @@ js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed) JS_ASSERT(unboxed == JS_TRUE || unboxed == JS_FALSE); return unboxed; } -JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_BooleanOrUndefinedToNumber, CONTEXT, INT32, 1, 1) +JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_BooleanOrUndefinedToNumber, CONTEXT, INT32, 1, ACC_NONE) JSString* FASTCALL js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed) @@ -363,7 +364,7 @@ js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed) JS_ASSERT(uint32(unboxed) <= 2); return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]); } -JS_DEFINE_CALLINFO_2(extern, STRING, js_BooleanOrUndefinedToString, CONTEXT, INT32, 1, 1) +JS_DEFINE_CALLINFO_2(extern, STRING, js_BooleanOrUndefinedToString, CONTEXT, INT32, 1, ACC_NONE) JSObject* FASTCALL js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent) @@ -383,7 +384,8 @@ js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* pa reinterpret_cast(fun)); return closure; } -JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT, 0, + ACC_STORE_ANY) JS_REQUIRES_STACK JSBool FASTCALL js_PopInterpFrame(JSContext* cx, InterpState* state) @@ -424,7 +426,7 @@ js_PopInterpFrame(JSContext* cx, InterpState* state) *state->inlineCallCountp = *state->inlineCallCountp - 1; return JS_TRUE; } -JS_DEFINE_CALLINFO_2(extern, BOOL, js_PopInterpFrame, CONTEXT, INTERPSTATE, 0, 0) +JS_DEFINE_CALLINFO_2(extern, BOOL, js_PopInterpFrame, CONTEXT, INTERPSTATE, 0, ACC_STORE_ANY) JSString* FASTCALL js_ConcatN(JSContext *cx, JSString **strArray, uint32 size) @@ -463,4 +465,4 @@ js_ConcatN(JSContext *cx, JSString **strArray, uint32 size) cx->free(buf); return str; } -JS_DEFINE_CALLINFO_3(extern, STRING, js_ConcatN, CONTEXT, STRINGPTR, UINT32, 0, 0) +JS_DEFINE_CALLINFO_3(extern, STRING, js_ConcatN, CONTEXT, STRINGPTR, UINT32, 0, ACC_STORE_ANY) diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index 5dc32094dc4f..80efbfe984b6 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -256,15 +256,26 @@ struct ClosureVarInfo; #define _JS_CALLINFO(name) name##_ci #if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32) -#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \ +#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \ _JS_TN_LINKAGE(linkage, crtype) name cargtypes; \ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \ - { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_CDECL _JS_CI_NAME(name) }; + { (intptr_t) &name, argtypes, nanojit::ABI_CDECL, isPure, storeAccSet _JS_CI_NAME(name) };\ + /* XXX: a temporary assertion to check all cse/fold pairs are correctly */ \ + /* converted to isPure/storeAccSet pairs for bug 545274. Will be removed */ \ + /* when bug 517910 starts doing more precise storeAccSet markings. */ \ + JS_STATIC_ASSERT_IF(!isPure, storeAccSet == nanojit::ACC_STORE_ANY); /* temporary */ \ + JS_STATIC_ASSERT_IF(isPure, storeAccSet == nanojit::ACC_NONE); + #else -#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \ +#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \ _JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \ - { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_FASTCALL _JS_CI_NAME(name) }; + { (intptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \ + /* XXX: a temporary assertion to check all cse/fold pairs are correctly */ \ + /* converted to isPure/storeAccSet pairs for bug 545274. Will be removed */ \ + /* when bug 517910 starts doing more precise storeAccSet markings. */ \ + JS_STATIC_ASSERT_IF(!isPure, storeAccSet == nanojit::ACC_STORE_ANY); /* temporary */ \ + JS_STATIC_ASSERT_IF(isPure, storeAccSet == nanojit::ACC_NONE); #endif /* @@ -289,33 +300,40 @@ struct ClosureVarInfo; * * - The parameter types. * - * - The cse flag. 1 if the builtin call can be optimized away by common - * subexpression elimination; otherwise 0. This should be 1 only if the - * function is idempotent and the return value is determined solely by the - * arguments. + * - The isPure flag. Set to 1 if: + * (a) the function's return value is determined solely by its arguments + * (ie. no hidden state, no implicit inputs used such as global + * variables or the result of an I/O operation); and + * (b) the function causes no observable side-effects (ie. no writes to + * global variables, no I/O output). + * Multiple calls to a pure function can be merged during CSE. * - * - The fold flag. Reserved. The same as cse for now. + * - The storeAccSet. This indicates which memory access regions the function + * accesses. It must be ACC_NONE if the function is pure; use + * ACC_STORE_ANY if you're not sure. Used to determine if each call site of + * the function aliases any loads. */ -#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold) \ +#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, isPure, storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), (_JS_CTYPE_TYPE(at0)), \ (_JS_CTYPE_ARGSIZE(at0) << (1*nanojit::ARGSIZE_SHIFT)) | \ - _JS_CTYPE_RETSIZE(rt), cse, fold) -#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold) \ + _JS_CTYPE_RETSIZE(rt), \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, isPure, storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1)), \ (_JS_CTYPE_ARGSIZE(at0) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at1) << (1*nanojit::ARGSIZE_SHIFT)) | \ _JS_CTYPE_RETSIZE(rt), \ - cse, fold) -#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold) \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, isPure, storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2)), \ (_JS_CTYPE_ARGSIZE(at0) << (3*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at1) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at2) << (1*nanojit::ARGSIZE_SHIFT)) | \ _JS_CTYPE_RETSIZE(rt), \ - cse, fold) -#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, isPure, storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \ _JS_CTYPE_TYPE(at3)), \ @@ -324,8 +342,8 @@ struct ClosureVarInfo; (_JS_CTYPE_ARGSIZE(at2) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at3) << (1*nanojit::ARGSIZE_SHIFT)) | \ _JS_CTYPE_RETSIZE(rt), \ - cse, fold) -#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, isPure, storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \ _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4)), \ @@ -335,8 +353,8 @@ struct ClosureVarInfo; (_JS_CTYPE_ARGSIZE(at3) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at4) << (1*nanojit::ARGSIZE_SHIFT)) | \ _JS_CTYPE_RETSIZE(rt), \ - cse, fold) -#define JS_DEFINE_CALLINFO_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, cse, fold) \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, isPure, storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \ _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4), _JS_CTYPE_TYPE(at5)), \ @@ -346,8 +364,10 @@ struct ClosureVarInfo; (_JS_CTYPE_ARGSIZE(at3) << (3*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at4) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at5) << (1*nanojit::ARGSIZE_SHIFT)) | \ - _JS_CTYPE_RETSIZE(rt), cse, fold) -#define JS_DEFINE_CALLINFO_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, cse, fold) \ + _JS_CTYPE_RETSIZE(rt), \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, isPure, \ + storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \ _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4), _JS_CTYPE_TYPE(at5), \ @@ -359,8 +379,10 @@ struct ClosureVarInfo; (_JS_CTYPE_ARGSIZE(at4) << (3*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at5) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at6) << (1*nanojit::ARGSIZE_SHIFT)) | \ - _JS_CTYPE_RETSIZE(rt), cse, fold) -#define JS_DEFINE_CALLINFO_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, cse, fold) \ + _JS_CTYPE_RETSIZE(rt), \ + isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, isPure, \ + storeAccSet) \ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \ _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4), _JS_CTYPE_TYPE(at5), \ @@ -373,37 +395,38 @@ struct ClosureVarInfo; (_JS_CTYPE_ARGSIZE(at5) << (3*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at6) << (2*nanojit::ARGSIZE_SHIFT)) | \ (_JS_CTYPE_ARGSIZE(at7) << (1*nanojit::ARGSIZE_SHIFT)) | \ - _JS_CTYPE_RETSIZE(rt), cse, fold) + _JS_CTYPE_RETSIZE(rt), \ + isPure, storeAccSet) #define JS_DECLARE_CALLINFO(name) extern const nanojit::CallInfo _JS_CALLINFO(name); #define _JS_TN_INIT_HELPER_n(n, args) _JS_TN_INIT_HELPER_##n args -#define _JS_TN_INIT_HELPER_1(linkage, rt, op, at0, cse, fold) \ +#define _JS_TN_INIT_HELPER_1(linkage, rt, op, at0, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at0), \ _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_2(linkage, rt, op, at0, at1, cse, fold) \ +#define _JS_TN_INIT_HELPER_2(linkage, rt, op, at0, at1, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \ _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_3(linkage, rt, op, at0, at1, at2, cse, fold) \ +#define _JS_TN_INIT_HELPER_3(linkage, rt, op, at0, at1, at2, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \ _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \ +#define _JS_TN_INIT_HELPER_4(linkage, rt, op, at0, at1, at2, at3, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \ _JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \ +#define _JS_TN_INIT_HELPER_5(linkage, rt, op, at0, at1, at2, at3, at4, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) \ _JS_CTYPE_PCH(at0), \ @@ -411,7 +434,7 @@ struct ClosureVarInfo; _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, cse, fold) \ +#define _JS_TN_INIT_HELPER_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at5) _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) \ _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \ @@ -419,7 +442,7 @@ struct ClosureVarInfo; _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, cse, fold) \ +#define _JS_TN_INIT_HELPER_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at6) _JS_CTYPE_PCH(at5) _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) \ _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \ @@ -427,7 +450,7 @@ struct ClosureVarInfo; _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0), \ _JS_CTYPE_FLAGS(rt) -#define _JS_TN_INIT_HELPER_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, cse, fold) \ +#define _JS_TN_INIT_HELPER_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, isPure, storeAccSet) \ &_JS_CALLINFO(op), \ _JS_CTYPE_PCH(at7) _JS_CTYPE_PCH(at6) _JS_CTYPE_PCH(at5) _JS_CTYPE_PCH(at4) \ _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \ @@ -492,14 +515,14 @@ js_dmod(jsdouble a, jsdouble b); #else -#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold) -#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold) -#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold) -#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) -#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) -#define JS_DEFINE_CALLINFO_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, cse, fold) -#define JS_DEFINE_CALLINFO_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, cse, fold) -#define JS_DEFINE_CALLINFO_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, cse, fold) +#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_6(linkage, rt, op, at0, at1, at2, at3, at4, at5, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_7(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, isPure, storeAccSet) +#define JS_DEFINE_CALLINFO_8(linkage, rt, op, at0, at1, at2, at3, at4, at5, at6, at7, isPure, storeAccSet) #define JS_DECLARE_CALLINFO(name) #define JS_DEFINE_TRCINFO_1(name, tn0) #define JS_DEFINE_TRCINFO_2(name, tn0, tn1) diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index b5347e228b3e..9aa79066183e 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -2253,7 +2253,7 @@ date_valueOf(JSContext *cx, uintN argc, jsval *vp) // Don't really need an argument here, but we don't support arg-less builtins JS_DEFINE_TRCINFO_1(date_now, - (1, (static, DOUBLE, date_now_tn, CONTEXT, 0, 0))) + (1, (static, DOUBLE, date_now_tn, CONTEXT, 0, nanojit::ACC_STORE_ANY))) static JSFunctionSpec date_static_methods[] = { JS_FN("UTC", date_UTC, MAXARGS,0), @@ -2263,7 +2263,7 @@ static JSFunctionSpec date_static_methods[] = { }; JS_DEFINE_TRCINFO_1(date_valueOf, - (3, (static, JSVAL_RETRY, date_valueOf_tn, CONTEXT, THIS, STRING, 0, 0))) + (3, (static, JSVAL_RETRY, date_valueOf_tn, CONTEXT, THIS, STRING, 0, nanojit::ACC_STORE_ANY))) static JSFunctionSpec date_methods[] = { JS_FN("getTime", date_getTime, 0,0), diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 64ba94eebbd5..aba332600644 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -297,7 +297,7 @@ js_Arguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee, #endif JS_DEFINE_CALLINFO_6(extern, OBJECT, js_Arguments, CONTEXT, OBJECT, UINT32, OBJECT, - DOUBLEPTR, APNPTR, 0, 0) + DOUBLEPTR, APNPTR, 0, nanojit::ACC_STORE_ANY) /* FIXME change the return type to void. */ JSBool JS_FASTCALL @@ -309,7 +309,8 @@ js_PutArguments(JSContext *cx, JSObject *argsobj, jsval *args) return true; } -JS_DEFINE_CALLINFO_3(extern, BOOL, js_PutArguments, CONTEXT, OBJECT, JSVALPTR, 0, 0) +JS_DEFINE_CALLINFO_3(extern, BOOL, js_PutArguments, CONTEXT, OBJECT, JSVALPTR, 0, + nanojit::ACC_STORE_ANY) static JSBool args_delProperty(JSContext *cx, JSObject *obj, jsval idval, jsval *vp) @@ -867,7 +868,8 @@ js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSO return callobj; } -JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CreateCallObjectOnTrace, CONTEXT, FUNCTION, OBJECT, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CreateCallObjectOnTrace, CONTEXT, FUNCTION, OBJECT, OBJECT, + 0, nanojit::ACC_STORE_ANY) JSFunction * js_GetCallObjectFunction(JSObject *obj) @@ -947,7 +949,8 @@ js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs, jsval return true; } -JS_DEFINE_CALLINFO_6(extern, BOOL, js_PutCallObjectOnTrace, CONTEXT, OBJECT, UINT32, JSVALPTR, UINT32, JSVALPTR, 0, 0) +JS_DEFINE_CALLINFO_6(extern, BOOL, js_PutCallObjectOnTrace, CONTEXT, OBJECT, UINT32, JSVALPTR, + UINT32, JSVALPTR, 0, nanojit::ACC_STORE_ANY) static JSBool call_enumerate(JSContext *cx, JSObject *obj) @@ -1133,8 +1136,10 @@ js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v) return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, JS_TRUE); } -JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0, 0) -JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0, + nanojit::ACC_STORE_ANY) +JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallVar, CONTEXT, OBJECT, JSID, JSVAL, 0, + nanojit::ACC_STORE_ANY) static JSBool call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, @@ -2467,8 +2472,8 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, } #ifdef JS_TRACER -JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CloneFunctionObject, - CONTEXT, FUNCTION, OBJECT, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CloneFunctionObject, CONTEXT, FUNCTION, OBJECT, OBJECT, 0, + nanojit::ACC_STORE_ANY) #endif /* @@ -2498,7 +2503,7 @@ js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain) } JS_DEFINE_CALLINFO_3(extern, OBJECT, js_AllocFlatClosure, - CONTEXT, FUNCTION, OBJECT, 0, 0) + CONTEXT, FUNCTION, OBJECT, 0, nanojit::ACC_STORE_ANY) JS_REQUIRES_STACK JSObject * js_NewFlatClosure(JSContext *cx, JSFunction *fun) diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 13cb7dca9177..a95b34904572 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -464,7 +464,7 @@ js_CloseIterator(JSContext *cx, jsval v) #endif return JS_TRUE; } -JS_DEFINE_CALLINFO_2(FRIEND, BOOL, js_CloseIterator, CONTEXT, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_2(FRIEND, BOOL, js_CloseIterator, CONTEXT, JSVAL, 0, nanojit::ACC_STORE_ANY) static JSBool CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval) diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index b26a0ae678f8..5ac7b49930a9 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -563,7 +563,7 @@ math_toSource(JSContext *cx, uintN argc, jsval *vp) #define MATH_BUILTIN_CFUN_1(name, cfun) \ static jsdouble FASTCALL math_##name##_tn(jsdouble d) { return cfun(d); } \ JS_DEFINE_TRCINFO_1(math_##name, \ - (1, (static, DOUBLE, math_##name##_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_##name##_tn, DOUBLE, 1, nanojit::ACC_NONE))) MATH_BUILTIN_CFUN_1(abs, fabs) MATH_BUILTIN_1(atan) @@ -609,7 +609,7 @@ math_exp_tn(JSContext *cx, jsdouble d) } JS_DEFINE_TRCINFO_1(math_exp, - (2, (static, DOUBLE, math_exp_tn, CONTEXT, DOUBLE, 1, 1))) + (2, (static, DOUBLE, math_exp_tn, CONTEXT, DOUBLE, 1, nanojit::ACC_NONE))) #else @@ -692,27 +692,27 @@ math_floor_tn(jsdouble x) } JS_DEFINE_TRCINFO_1(math_acos, - (1, (static, DOUBLE, math_acos_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_acos_tn, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(math_asin, - (1, (static, DOUBLE, math_asin_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_asin_tn, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(math_atan2, - (2, (static, DOUBLE, math_atan2_kernel, DOUBLE, DOUBLE, 1, 1))) + (2, (static, DOUBLE, math_atan2_kernel, DOUBLE, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(js_math_floor, - (1, (static, DOUBLE, math_floor_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_floor_tn, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(math_log, - (1, (static, DOUBLE, math_log_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_log_tn, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(js_math_max, - (2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, 1))) + (2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(js_math_min, - (2, (static, DOUBLE, math_min_tn, DOUBLE, DOUBLE, 1, 1))) + (2, (static, DOUBLE, math_min_tn, DOUBLE, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(math_pow, - (2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1))) + (2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(math_random, - (1, (static, DOUBLE, math_random_tn, CONTEXT, 0, 0))) + (1, (static, DOUBLE, math_random_tn, CONTEXT, 0, nanojit::ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(js_math_round, - (1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_round_tn, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(js_math_ceil, - (1, (static, DOUBLE, math_ceil_tn, DOUBLE, 1, 1))) + (1, (static, DOUBLE, math_ceil_tn, DOUBLE, 1, nanojit::ACC_NONE))) #endif /* JS_TRACER */ diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 6256e1016ebd..bfa18bf87571 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -254,11 +254,11 @@ const char js_parseInt_str[] = "parseInt"; #ifdef JS_TRACER JS_DEFINE_TRCINFO_2(num_parseInt, - (2, (static, DOUBLE, ParseInt, CONTEXT, STRING, 1, 1)), - (1, (static, DOUBLE, ParseIntDouble, DOUBLE, 1, 1))) + (2, (static, DOUBLE, ParseInt, CONTEXT, STRING, 1, nanojit::ACC_NONE)), + (1, (static, DOUBLE, ParseIntDouble, DOUBLE, 1, nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(num_parseFloat, - (2, (static, DOUBLE, ParseFloat, CONTEXT, STRING, 1, 1))) + (2, (static, DOUBLE, ParseFloat, CONTEXT, STRING, 1, nanojit::ACC_NONE))) #endif /* JS_TRACER */ @@ -625,8 +625,10 @@ num_toPrecision(JSContext *cx, uintN argc, jsval *vp) #ifdef JS_TRACER JS_DEFINE_TRCINFO_2(num_toString, - (2, (extern, STRING_RETRY, js_NumberToString, CONTEXT, THIS_DOUBLE, 1, 1)), - (3, (static, STRING_RETRY, js_NumberToStringWithBase, CONTEXT, THIS_DOUBLE, INT32, 1, 1))) + (2, (extern, STRING_RETRY, js_NumberToString, CONTEXT, THIS_DOUBLE, 1, + nanojit::ACC_NONE)), + (3, (static, STRING_RETRY, js_NumberToStringWithBase, CONTEXT, THIS_DOUBLE, INT32, 1, + nanojit::ACC_NONE))) #endif /* JS_TRACER */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index fa493a3cbefd..a72f94fd2391 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2782,11 +2782,14 @@ const char js_lookupSetter_str[] = "__lookupSetter__"; #endif JS_DEFINE_TRCINFO_1(obj_valueOf, - (3, (static, JSVAL, Object_p_valueOf, CONTEXT, THIS, STRING, 0, 0))) + (3, (static, JSVAL, Object_p_valueOf, CONTEXT, THIS, STRING, 0, + nanojit::ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(obj_hasOwnProperty, - (3, (static, BOOL_FAIL, Object_p_hasOwnProperty, CONTEXT, THIS, STRING, 0, 0))) + (3, (static, BOOL_FAIL, Object_p_hasOwnProperty, CONTEXT, THIS, STRING, 0, + nanojit::ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(obj_propertyIsEnumerable, - (3, (static, BOOL_FAIL, Object_p_propertyIsEnumerable, CONTEXT, THIS, STRING, 0, 0))) + (3, (static, BOOL_FAIL, Object_p_propertyIsEnumerable, CONTEXT, THIS, STRING, 0, + nanojit::ACC_STORE_ANY))) static JSFunctionSpec object_methods[] = { #if JS_HAS_TOSOURCE @@ -3028,7 +3031,8 @@ js_Object_tn(JSContext* cx, JSObject* proto) } JS_DEFINE_TRCINFO_1(js_Object, - (2, (extern, CONSTRUCTOR_RETRY, js_Object_tn, CONTEXT, CALLEE_PROTOTYPE, 0, 0))) + (2, (extern, CONSTRUCTOR_RETRY, js_Object_tn, CONTEXT, CALLEE_PROTOTYPE, 0, + nanojit::ACC_STORE_ANY))) JSObject* FASTCALL js_NonEmptyObject(JSContext* cx, JSObject* proto) @@ -3052,7 +3056,8 @@ js_NonEmptyObject(JSContext* cx, JSObject* proto) return obj; } -JS_DEFINE_CALLINFO_2(extern, CONSTRUCTOR_RETRY, js_NonEmptyObject, CONTEXT, CALLEE_PROTOTYPE, 0, 0) +JS_DEFINE_CALLINFO_2(extern, CONSTRUCTOR_RETRY, js_NonEmptyObject, CONTEXT, CALLEE_PROTOTYPE, 0, + nanojit::ACC_STORE_ANY) static inline JSObject* NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto, @@ -3111,7 +3116,8 @@ js_NewInstance(JSContext *cx, JSClass *clasp, JSObject *ctor) JSObject::defaultPrivate(clasp)); } -JS_DEFINE_CALLINFO_3(extern, CONSTRUCTOR_RETRY, js_NewInstance, CONTEXT, CLASS, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_3(extern, CONSTRUCTOR_RETRY, js_NewInstance, CONTEXT, CLASS, OBJECT, 0, + nanojit::ACC_STORE_ANY) #else /* !JS_TRACER */ diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 4ec1fd79ba36..4a48db78369e 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -2352,7 +2352,7 @@ class RegExpNativeCompiler { LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_plt, pos, cpend), 0); if (!fails.append(to_fail)) return NULL; - LIns* text_ch = lir->insLoad(LIR_ldcs, pos, 0); + LIns* text_ch = lir->insLoad(LIR_ldzs, pos, 0, ACC_READONLY); // Extra characters that need to be compared against when doing folding. struct extra { @@ -2573,7 +2573,7 @@ class RegExpNativeCompiler { LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_plt, pos, cpend), 0); if (!fails.append(to_fail)) return NULL; - LIns* text_ch = lir->insLoad(LIR_ldcs, pos, 0); + LIns* text_ch = lir->insLoad(LIR_ldzs, pos, 0, ACC_READONLY); if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_le, text_ch, lir->insImm(charSet->length)), 0))) { @@ -2581,7 +2581,8 @@ class RegExpNativeCompiler { } LIns* byteIndex = lir->ins_i2p(lir->ins2(LIR_rsh, text_ch, lir->insImm(3))); LIns* bitmap = lir->insImmPtr(bitmapData); - LIns* byte = lir->insLoad(LIR_ldcb, lir->ins2(LIR_piadd, bitmap, byteIndex), (int) 0); + LIns* byte = lir->insLoad(LIR_ldzb, lir->ins2(LIR_piadd, bitmap, byteIndex), (int) 0, + ACC_READONLY); LIns* bitMask = lir->ins2(LIR_lsh, lir->insImm(1), lir->ins2(LIR_and, text_ch, lir->insImm(0x7))); LIns* test = lir->ins2(LIR_eq, lir->ins2(LIR_and, byte, bitMask), lir->insImm(0)); @@ -2600,7 +2601,7 @@ class RegExpNativeCompiler { chr = lir->ins2(LIR_lsh, chr, sizeLog2); } LIns *addr = lir->ins2(LIR_piadd, lir->insImmPtr(tbl), lir->ins_u2p(chr)); - return lir->insLoad(LIR_ldcb, addr, 0); + return lir->insLoad(LIR_ldzb, addr, 0, ACC_READONLY); } /* Compile a builtin character class. */ @@ -2609,7 +2610,7 @@ class RegExpNativeCompiler { /* All the builtins checked below consume one character. */ if (!fails.append(lir->insBranch(LIR_jf, lir->ins2(LIR_plt, pos, cpend), 0))) return NULL; - LIns *chr = lir->insLoad(LIR_ldcs, pos, 0); + LIns *chr = lir->insLoad(LIR_ldzs, pos, 0, ACC_READONLY); switch (node->op) { case REOP_DOT: @@ -5875,7 +5876,8 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto) } #ifdef JS_TRACER -JS_DEFINE_CALLINFO_3(extern, OBJECT, js_CloneRegExpObject, CONTEXT, OBJECT, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_3(extern, OBJECT, js_CloneRegExpObject, CONTEXT, OBJECT, OBJECT, 0, + ACC_STORE_ANY) #endif bool diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 6d3a0a2b91e7..90cdc69970fd 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1029,7 +1029,8 @@ js_String_p_charCodeAt_int_int(JSString* str, jsint i) return 0; return str->chars()[i]; } -JS_DEFINE_CALLINFO_2(extern, INT32, js_String_p_charCodeAt_int_int, STRING, INT32, 1, 1) +JS_DEFINE_CALLINFO_2(extern, INT32, js_String_p_charCodeAt_int_int, STRING, INT32, 1, + nanojit::ACC_NONE) int32 FASTCALL js_String_p_charCodeAt_double_int(JSString* str, double d) @@ -1039,7 +1040,8 @@ js_String_p_charCodeAt_double_int(JSString* str, double d) return 0; return str->chars()[jsuint(d)]; } -JS_DEFINE_CALLINFO_2(extern, INT32, js_String_p_charCodeAt_double_int, STRING, DOUBLE, 1, 1) +JS_DEFINE_CALLINFO_2(extern, INT32, js_String_p_charCodeAt_double_int, STRING, DOUBLE, 1, + nanojit::ACC_NONE) jsdouble FASTCALL js_String_p_charCodeAt0(JSString* str) @@ -1060,7 +1062,7 @@ js_String_p_charCodeAt0_int(JSString* str) return 0; return str->chars()[0]; } -JS_DEFINE_CALLINFO_1(extern, INT32, js_String_p_charCodeAt0_int, STRING, 1, 1) +JS_DEFINE_CALLINFO_1(extern, INT32, js_String_p_charCodeAt0_int, STRING, 1, nanojit::ACC_NONE) #endif jsint @@ -2543,14 +2545,19 @@ js_String_getelem(JSContext* cx, JSString* str, int32 i) #endif JS_DEFINE_TRCINFO_1(js_str_toString, - (2, (extern, STRING_RETRY, String_p_toString, CONTEXT, THIS, 1, 1))) + (2, (extern, STRING_RETRY, String_p_toString, CONTEXT, THIS, 1, + nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(str_charAt, - (3, (extern, STRING_RETRY, js_String_getelem, CONTEXT, THIS_STRING, INT32, 1, 1))) + (3, (extern, STRING_RETRY, js_String_getelem, CONTEXT, THIS_STRING, INT32, 1, + nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_2(str_charCodeAt, - (1, (extern, DOUBLE, js_String_p_charCodeAt0, THIS_STRING, 1, 1)), - (2, (extern, DOUBLE, js_String_p_charCodeAt, THIS_STRING, DOUBLE, 1, 1))) + (1, (extern, DOUBLE, js_String_p_charCodeAt0, THIS_STRING, 1, + nanojit::ACC_NONE)), + (2, (extern, DOUBLE, js_String_p_charCodeAt, THIS_STRING, DOUBLE, 1, + nanojit::ACC_NONE))) JS_DEFINE_TRCINFO_1(str_concat, - (3, (extern, STRING_RETRY, js_ConcatStrings, CONTEXT, THIS_STRING, STRING, 1, 1))) + (3, (extern, STRING_RETRY, js_ConcatStrings, CONTEXT, THIS_STRING, STRING, 1, + nanojit::ACC_NONE))) #define GENERIC JSFUN_GENERIC_NATIVE #define PRIMITIVE JSFUN_THISP_PRIMITIVE @@ -2952,7 +2959,8 @@ js_String_tn(JSContext* cx, JSObject* proto, JSString* str) JS_ASSERT(JS_ON_TRACE(cx)); return js_NewObjectWithClassProto(cx, &js_StringClass, proto, STRING_TO_JSVAL(str)); } -JS_DEFINE_CALLINFO_3(extern, OBJECT, js_String_tn, CONTEXT, CALLEE_PROTOTYPE, STRING, 0, 0) +JS_DEFINE_CALLINFO_3(extern, OBJECT, js_String_tn, CONTEXT, CALLEE_PROTOTYPE, STRING, 0, + nanojit::ACC_STORE_ANY) #endif /* !JS_TRACER */ @@ -3009,7 +3017,7 @@ String_fromCharCode(JSContext* cx, int32 i) #endif JS_DEFINE_TRCINFO_1(str_fromCharCode, - (2, (static, STRING_RETRY, String_fromCharCode, CONTEXT, INT32, 1, 1))) + (2, (static, STRING_RETRY, String_fromCharCode, CONTEXT, INT32, 1, nanojit::ACC_NONE))) static JSFunctionSpec string_static_methods[] = { JS_TN("fromCharCode", str_fromCharCode, 1, 0, &str_fromCharCode_trcinfo), @@ -3430,7 +3438,7 @@ js_EqualStrings(JSString *str1, JSString *str2) return JS_TRUE; } -JS_DEFINE_CALLINFO_2(extern, BOOL, js_EqualStrings, STRING, STRING, 1, 1) +JS_DEFINE_CALLINFO_2(extern, BOOL, js_EqualStrings, STRING, STRING, 1, nanojit::ACC_NONE) int32 JS_FASTCALL js_CompareStrings(JSString *str1, JSString *str2) @@ -3456,7 +3464,7 @@ js_CompareStrings(JSString *str1, JSString *str2) } return (intN)(l1 - l2); } -JS_DEFINE_CALLINFO_2(extern, INT32, js_CompareStrings, STRING, STRING, 1, 1) +JS_DEFINE_CALLINFO_2(extern, INT32, js_CompareStrings, STRING, STRING, 1, nanojit::ACC_NONE) size_t js_strlen(const jschar *s) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 7a818080288e..3c11dd4362da 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -834,7 +834,7 @@ PrintOnTrace(char* format, uint32 argc, double *argv) return JS_TRUE; } -JS_DEFINE_CALLINFO_3(extern, BOOL, PrintOnTrace, CHARPTR, UINT32, DOUBLEPTR, 0, 0) +JS_DEFINE_CALLINFO_3(extern, BOOL, PrintOnTrace, CHARPTR, UINT32, DOUBLEPTR, 0, ACC_STORE_ANY) // This version is not intended to be called directly: usually it is easier to // use one of the other overloads. @@ -5005,7 +5005,8 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_s ci->_address = uintptr_t(inner->code()); JS_ASSERT(ci->_address); ci->_argtypes = ARGSIZE_P | ARGSIZE_P << ARGSIZE_SHIFT; - ci->_cse = ci->_fold = 0; + ci->_isPure = 0; + ci->_storeAccSet = ACC_STORE_ANY; ci->_abi = ABI_FASTCALL; #ifdef DEBUG ci->_name = "fragment"; @@ -7775,8 +7776,10 @@ TraceRecorder::frameIfInRange(JSObject* obj, unsigned* depthp) const return NULL; } -JS_DEFINE_CALLINFO_4(extern, UINT32, GetClosureVar, CONTEXT, OBJECT, CVIPTR, DOUBLEPTR, 0, 0) -JS_DEFINE_CALLINFO_4(extern, UINT32, GetClosureArg, CONTEXT, OBJECT, CVIPTR, DOUBLEPTR, 0, 0) +JS_DEFINE_CALLINFO_4(extern, UINT32, GetClosureVar, CONTEXT, OBJECT, CVIPTR, DOUBLEPTR, 0, + ACC_STORE_ANY) +JS_DEFINE_CALLINFO_4(extern, UINT32, GetClosureArg, CONTEXT, OBJECT, CVIPTR, DOUBLEPTR, 0, + ACC_STORE_ANY) /* * Search the scope chain for a property lookup operation at the current PC and @@ -9073,8 +9076,9 @@ TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins, LIns*& ops_ins, si return false; #undef OP - ops_ins = addName(lir->insLoad(LIR_ldcp, map_ins, int(offsetof(JSObjectMap, ops))), "ops"); - LIns* n = lir->insLoad(LIR_ldcp, ops_ins, op_offset); + ops_ins = addName(lir->insLoad(LIR_ldp, map_ins, int(offsetof(JSObjectMap, ops)), ACC_READONLY), + "ops"); + LIns* n = lir->insLoad(LIR_ldp, ops_ins, op_offset, ACC_READONLY); guard(true, addName(lir->ins2(LIR_peq, n, INS_CONSTPTR(ptr)), "guard(native-map)"), BRANCH_EXIT); @@ -9253,7 +9257,8 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins, if (entry->adding()) { LIns *vshape_ins = addName( lir->insLoad(LIR_ld, - addName(lir->insLoad(LIR_ldcp, cx_ins, offsetof(JSContext, runtime)), + addName(lir->insLoad(LIR_ldp, cx_ins, + offsetof(JSContext, runtime), ACC_READONLY), "runtime"), offsetof(JSRuntime, protoHazardShape)), "protoHazardShape"); @@ -9341,7 +9346,8 @@ LIns* TraceRecorder::stobj_get_const_fslot(LIns* obj_ins, unsigned slot) { JS_ASSERT(slot < JS_INITIAL_NSLOTS); - return lir->insLoad(LIR_ldcp, obj_ins, offsetof(JSObject, fslots) + slot * sizeof(jsval)); + return lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, fslots) + slot * sizeof(jsval), + ACC_READONLY); } LIns* @@ -9426,15 +9432,10 @@ TraceRecorder::unbox_jsval(jsval v, LIns* v_ins, VMSideExit* exit) INS_CONSTWORD(JSVAL_OBJECT)), exit); - /* - * LIR_ldcp is ok to use here even though Array classword can - * change, because no object's classword can ever change from - * &js_ArrayClass to &js_FunctionClass. - */ guard(HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)), lir->ins2(LIR_peq, lir->ins2(LIR_piand, - lir->insLoad(LIR_ldcp, v_ins, offsetof(JSObject, classword)), + lir->insLoad(LIR_ldp, v_ins, offsetof(JSObject, classword)), INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)), INS_CONSTPTR(&js_FunctionClass)), exit); @@ -9528,11 +9529,11 @@ TraceRecorder::getThis(LIns*& this_ins) JS_REQUIRES_STACK bool TraceRecorder::guardClass(JSObject* obj, LIns* obj_ins, JSClass* clasp, VMSideExit* exit, - LOpcode loadOp) + AccSet accSet) { bool cond = obj->getClass() == clasp; - LIns* class_ins = lir->insLoad(loadOp, obj_ins, offsetof(JSObject, classword)); + LIns* class_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, classword), accSet); class_ins = lir->ins2(LIR_piand, class_ins, INS_CONSTWORD(~JSSLOT_CLASS_MASK_BITS)); #ifdef JS_JIT_SPEW @@ -10516,7 +10517,8 @@ TraceRecorder::emitNativePropertyOp(JSScope* scope, JSScopeProperty* sprop, LIns ARGSIZE_P << (2*ARGSIZE_SHIFT) | ARGSIZE_P << (3*ARGSIZE_SHIFT) | ARGSIZE_P << (4*ARGSIZE_SHIFT); - ci->_cse = ci->_fold = 0; + ci->_isPure = 0; + ci->_storeAccSet = ACC_STORE_ANY; ci->_abi = ABI_CDECL; #ifdef DEBUG ci->_name = "JSPropertyOp"; @@ -10899,7 +10901,8 @@ TraceRecorder::callNative(uintN argc, JSOp mode) CallInfo* ci = new (traceAlloc()) CallInfo(); ci->_address = uintptr_t(fun->u.n.native); - ci->_cse = ci->_fold = 0; + ci->_isPure = 0; + ci->_storeAccSet = ACC_STORE_ANY; ci->_abi = ABI_CDECL; ci->_argtypes = types; #ifdef DEBUG @@ -11229,7 +11232,7 @@ MethodWriteBarrier(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, JSObjec return OBJ_SCOPE(obj)->methodWriteBarrier(cx, sprop, tvr.value()); } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, MethodWriteBarrier, CONTEXT, OBJECT, SCOPEPROP, OBJECT, - 0, 0) + 0, ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop, @@ -11399,8 +11402,9 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty offsetof(InterpState, callstackBase)); LIns *frameInfo_ins = lir->insLoad(LIR_ldp, callstackBase_ins, 0); LIns *typemap_ins = lir->ins2(LIR_addp, frameInfo_ins, INS_CONSTWORD(sizeof(FrameInfo))); - LIns *type_ins = lir->insLoad(LIR_ldcb, - lir->ins2(LIR_addp, typemap_ins, lir->ins_u2p(slot_ins)), 0); + LIns *type_ins = lir->insLoad(LIR_ldzb, + lir->ins2(LIR_addp, typemap_ins, lir->ins_u2p(slot_ins)), 0, + ACC_READONLY); TraceType type = getCoercedType(v); if (type == TT_INT32 && !isPromoteInt(v_ins)) type = TT_DOUBLE; @@ -11532,7 +11536,7 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval* vp) return cx->interpState->builtinStatus == 0; } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyByName, CONTEXT, OBJECT, STRINGPTR, JSVALPTR, - 0, 0) + 0, ACC_STORE_ANY) // Convert the value in a slot to a string and store the resulting string back // in the slot (typically in order to root it). @@ -11594,7 +11598,8 @@ GetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, jsval* vp) } return cx->interpState->builtinStatus == 0; } -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyByIndex, CONTEXT, OBJECT, INT32, JSVALPTR, 0, 0) +JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyByIndex, CONTEXT, OBJECT, INT32, JSVALPTR, 0, + ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::getPropertyByIndex(LIns* obj_ins, LIns* index_ins, jsval* outp) @@ -11621,8 +11626,8 @@ GetPropertyById(JSContext* cx, JSObject* obj, jsid id, jsval* vp) } return cx->interpState->builtinStatus == 0; } -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyById, - CONTEXT, OBJECT, JSVAL, JSVALPTR, 0, 0) +JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyById, CONTEXT, OBJECT, JSVAL, JSVALPTR, + 0, ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::getPropertyById(LIns* obj_ins, jsval* outp) @@ -11678,7 +11683,7 @@ GetPropertyWithNativeGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop return cx->interpState->builtinStatus == 0; } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyWithNativeGetter, - CONTEXT, OBJECT, SCOPEPROP, JSVALPTR, 0, 0) + CONTEXT, OBJECT, SCOPEPROP, JSVALPTR, 0, ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::getPropertyWithNativeGetter(LIns* obj_ins, JSScopeProperty* sprop, jsval* outp) @@ -11804,7 +11809,7 @@ TraceRecorder::record_JSOP_GETELEM() lir->ins_u2p(lir->ins2(LIR_mul, idx_ins, INS_CONST(sizeof(TraceType))))); - LIns* type_ins = lir->insLoad(LIR_ldcb, typep_ins, 0); + LIns* type_ins = lir->insLoad(LIR_ldzb, typep_ins, 0, ACC_READONLY); guard(true, addName(lir->ins2(LIR_eq, type_ins, lir->insImm(type)), "guard(type-stable upvar)"), @@ -11875,7 +11880,7 @@ SetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval* vp) return cx->interpState->builtinStatus == 0; } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, SetPropertyByName, CONTEXT, OBJECT, STRINGPTR, JSVALPTR, - 0, 0) + 0, ACC_STORE_ANY) static JSBool FASTCALL InitPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval val) @@ -11891,7 +11896,7 @@ InitPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, jsval val) return cx->interpState->builtinStatus == 0; } JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByName, CONTEXT, OBJECT, STRINGPTR, JSVAL, - 0, 0) + 0, ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::initOrSetPropertyByName(LIns* obj_ins, jsval* idvalp, jsval* rvalp, bool init) @@ -11932,7 +11937,8 @@ SetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, jsval* vp) } return cx->interpState->builtinStatus == 0; } -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, SetPropertyByIndex, CONTEXT, OBJECT, INT32, JSVALPTR, 0, 0) +JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, SetPropertyByIndex, CONTEXT, OBJECT, INT32, JSVALPTR, 0, + ACC_STORE_ANY) static JSBool FASTCALL InitPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, jsval val) @@ -11947,7 +11953,8 @@ InitPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, jsval val) } return cx->interpState->builtinStatus == 0; } -JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByIndex, CONTEXT, OBJECT, INT32, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByIndex, CONTEXT, OBJECT, INT32, JSVAL, 0, + ACC_STORE_ANY) JS_REQUIRES_STACK RecordingStatus TraceRecorder::initOrSetPropertyByIndex(LIns* obj_ins, LIns* index_ins, jsval* rvalp, bool init) @@ -12017,11 +12024,13 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) lir->insGuard(LIR_xf, lir->ins2(LIR_ult, idx_ins, - lir->insLoad(LIR_ldc, priv_ins, js::TypedArray::lengthOffset())), + lir->insLoad(LIR_ld, priv_ins, js::TypedArray::lengthOffset(), + ACC_READONLY)), createGuardRecord(snapshot(OVERFLOW_EXIT))); // We're now ready to store - LIns* data_ins = lir->insLoad(LIR_ldcp, priv_ins, js::TypedArray::dataOffset()); + LIns* data_ins = lir->insLoad(LIR_ldp, priv_ins, js::TypedArray::dataOffset(), + ACC_READONLY); LIns* pidx_ins = lir->ins_u2p(idx_ins); LIns* addr_ins = 0; @@ -12177,11 +12186,11 @@ TraceRecorder::record_JSOP_CALLNAME() } JS_DEFINE_CALLINFO_5(extern, UINT32, GetUpvarArgOnTrace, CONTEXT, UINT32, INT32, UINT32, - DOUBLEPTR, 0, 0) + DOUBLEPTR, 0, ACC_STORE_ANY) JS_DEFINE_CALLINFO_5(extern, UINT32, GetUpvarVarOnTrace, CONTEXT, UINT32, INT32, UINT32, - DOUBLEPTR, 0, 0) + DOUBLEPTR, 0, ACC_STORE_ANY) JS_DEFINE_CALLINFO_5(extern, UINT32, GetUpvarStackOnTrace, CONTEXT, UINT32, INT32, UINT32, - DOUBLEPTR, 0, 0) + DOUBLEPTR, 0, ACC_STORE_ANY) /* * Record LIR to get the given upvar. Return the LIR instruction for the upvar @@ -12310,7 +12319,7 @@ TraceRecorder::record_JSOP_GETDSLOT() unsigned index = GET_UINT16(cx->fp->regs->pc); LIns* dslots_ins = lir->insLoad(LIR_ldp, callee_ins, offsetof(JSObject, dslots)); - LIns* v_ins = lir->insLoad(LIR_ldcp, dslots_ins, index * sizeof(jsval)); + LIns* v_ins = lir->insLoad(LIR_ldp, dslots_ins, index * sizeof(jsval), ACC_READONLY); stack(0, unbox_jsval(callee->dslots[index], v_ins, snapshot(BRANCH_EXIT))); return ARECORD_CONTINUE; @@ -12613,7 +12622,7 @@ CatchStopIteration_tn(JSContext* cx, JSBool ok, jsval* vp) } JS_DEFINE_TRCINFO_1(CatchStopIteration_tn, - (3, (static, BOOL, CatchStopIteration_tn, CONTEXT, BOOL, JSVALPTR, 0, 0))) + (3, (static, BOOL, CatchStopIteration_tn, CONTEXT, BOOL, JSVALPTR, 0, ACC_STORE_ANY))) JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_NativeCallComplete() @@ -12763,7 +12772,7 @@ MethodReadBarrier(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, JSObject return JSVAL_TO_OBJECT(tvr.value()); } JS_DEFINE_CALLINFO_4(static, OBJECT_FAIL, MethodReadBarrier, CONTEXT, OBJECT, SCOPEPROP, OBJECT, - 0, 0) + 0, ACC_STORE_ANY) /* * Get a property. The current opcode has JOF_ATOM. @@ -13075,12 +13084,12 @@ TraceRecorder::typedArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_ guard(true, lir->ins2(LIR_ult, idx_ins, - lir->insLoad(LIR_ldc, priv_ins, js::TypedArray::lengthOffset())), + lir->insLoad(LIR_ld, priv_ins, js::TypedArray::lengthOffset(), ACC_READONLY)), OVERFLOW_EXIT); /* We are now ready to load. Do a different type of load * depending on what type of thing we're loading. */ - LIns* data_ins = lir->insLoad(LIR_ldcp, priv_ins, js::TypedArray::dataOffset()); + LIns* data_ins = lir->insLoad(LIR_ldp, priv_ins, js::TypedArray::dataOffset(), ACC_READONLY); switch (tarray->type) { case js::TypedArray::TYPE_INT8: @@ -13786,7 +13795,7 @@ HasInstance(JSContext* cx, JSObject* ctor, jsval val) SetBuiltinError(cx); return result; } -JS_DEFINE_CALLINFO_3(static, BOOL_FAIL, HasInstance, CONTEXT, OBJECT, JSVAL, 0, 0) +JS_DEFINE_CALLINFO_3(static, BOOL_FAIL, HasInstance, CONTEXT, OBJECT, JSVAL, 0, ACC_STORE_ANY) JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_INSTANCEOF() @@ -14882,9 +14891,9 @@ CallIteratorNext_tn(JSContext* cx, jsbytecode* pc, JSObject* iterobj) } JS_DEFINE_TRCINFO_1(ObjectToIterator, - (4, (static, OBJECT_FAIL, ObjectToIterator_tn, CONTEXT, PC, THIS, INT32, 0, 0))) + (4, (static, OBJECT_FAIL, ObjectToIterator_tn, CONTEXT, PC, THIS, INT32, 0, ACC_STORE_ANY))) JS_DEFINE_TRCINFO_1(CallIteratorNext, - (3, (static, JSVAL_FAIL, CallIteratorNext_tn, CONTEXT, PC, THIS, 0, 0))) + (3, (static, JSVAL_FAIL, CallIteratorNext_tn, CONTEXT, PC, THIS, 0, ACC_STORE_ANY))) static const struct BuiltinFunctionInfo { JSNativeTraceInfo *ti; @@ -15003,9 +15012,9 @@ TraceRecorder::record_JSOP_LENGTH() } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) { // Ensure array is a typed array and is the same type as what was written guardConstClass(obj, obj_ins, obj->getClass(), snapshot(BRANCH_EXIT)); - v_ins = lir->ins1(LIR_i2f, lir->insLoad(LIR_ldc, + v_ins = lir->ins1(LIR_i2f, lir->insLoad(LIR_ld, stobj_get_const_fslot(obj_ins, JSSLOT_PRIVATE), - js::TypedArray::lengthOffset())); + js::TypedArray::lengthOffset(), ACC_READONLY)); } else { if (!OBJ_IS_NATIVE(obj)) RETURN_STOP_A("can't trace length property access on non-array, non-native object"); @@ -15120,7 +15129,7 @@ js_Unbrand(JSContext *cx, JSObject *obj) return obj->unbrand(cx); } -JS_DEFINE_CALLINFO_2(extern, BOOL, js_Unbrand, CONTEXT, OBJECT, 0, 0) +JS_DEFINE_CALLINFO_2(extern, BOOL, js_Unbrand, CONTEXT, OBJECT, 0, ACC_STORE_ANY) JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_UNBRAND() diff --git a/js/src/jstracer.h b/js/src/jstracer.h index e7389cc9ca85..ba3e59ca2cc6 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1294,9 +1294,10 @@ class TraceRecorder JS_REQUIRES_STACK nanojit::LIns* box_jsval(jsval v, nanojit::LIns* v_ins); JS_REQUIRES_STACK nanojit::LIns* unbox_jsval(jsval v, nanojit::LIns* v_ins, VMSideExit* exit); JS_REQUIRES_STACK bool guardClass(JSObject* obj, nanojit::LIns* obj_ins, JSClass* clasp, - VMSideExit* exit, nanojit::LOpcode loadOp = nanojit::LIR_ldp); + VMSideExit* exit, + nanojit::AccSet accSet = nanojit::ACC_LOAD_ANY); bool guardConstClass(JSObject* obj, nanojit::LIns* obj_ins, JSClass* clasp, VMSideExit* exit) { - return guardClass(obj, obj_ins, clasp, exit, nanojit::LIR_ldcp); + return guardClass(obj, obj_ins, clasp, exit, nanojit::ACC_READONLY); } JS_REQUIRES_STACK bool guardDenseArray(JSObject* obj, nanojit::LIns* obj_ins, ExitType exitType = MISMATCH_EXIT); diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 7d250537070a..484feeecb75b 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -339,7 +339,7 @@ js_TypedArray_uint8_clamp_double(const double x) return y; } -JS_DEFINE_CALLINFO_1(extern, INT32, js_TypedArray_uint8_clamp_double, DOUBLE, 1, 1) +JS_DEFINE_CALLINFO_1(extern, INT32, js_TypedArray_uint8_clamp_double, DOUBLE, 1, nanojit::ACC_NONE) struct uint8_clamped { diff --git a/js/src/xpconnect/src/qsgen.py b/js/src/xpconnect/src/qsgen.py index 7b7abf666665..a3021f15b574 100644 --- a/js/src/xpconnect/src/qsgen.py +++ b/js/src/xpconnect/src/qsgen.py @@ -1303,7 +1303,7 @@ def writeTraceableQuickStub(f, customMethodCalls, member, stubName): # Write the JS_DEFINE_TRCINFO block f.write("JS_DEFINE_TRCINFO_1(%s,\n" % stubName) - f.write(" (%d, (static, %s, %s, %s, 0, 0)))\n\n" + f.write(" (%d, (static, %s, %s, %s, 0, nanojit::ACC_STORE_ANY)))\n\n" % (len(traceInfo["params"]), traceInfo["type"], stubName + "_tn", ", ".join(traceInfo["params"]))) From 0350b3b5f436e366181d295a4cf12fed36b205f8 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Tue, 2 Mar 2010 11:03:04 -0800 Subject: [PATCH 21/52] Bug 549531 - fix strict aliasing warnings about scopeChain (also clean trailing whitespace; r=dmandelin). --- js/src/jsinterp.h | 5 +++- js/src/jsrecursion.cpp | 2 +- js/src/jstracer.cpp | 53 ++++++++++++++++++++--------------------- js/src/jstypedarray.cpp | 2 +- js/src/jstypedarray.h | 2 +- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index f2d4f3d4287f..e5482db3b84a 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -119,7 +119,10 @@ struct JSStackFrame { * also used in some other cases --- entering 'with' blocks, for * example. */ - JSObject *scopeChain; + union { + JSObject *scopeChain; + jsval scopeChainVal; + }; JSObject *blockChain; uint32 flags; /* frame flags -- see below */ diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index e3f51fe28cea..90028b8b7af7 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -526,7 +526,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) &info); /* scopeChain */ slurpSlot(addName(lir->insLoad(LIR_ldp, fp_ins, offsetof(JSStackFrame, scopeChain)), "scopeChain"), - (jsval*) &fp->scopeChain, + &fp->scopeChainVal, &info); /* vars */ LIns* slots_ins = addName(lir->insLoad(LIR_ldp, fp_ins, offsetof(JSStackFrame, slots)), diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 3c11dd4362da..559dc5929087 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -853,7 +853,7 @@ TraceRecorder::tprint(const char *format, int count, nanojit::LIns *insa[]) LIns* args_ins[] = { INS_CONSTPTR(args), INS_CONST(count), INS_CONSTPTR(data) }; LIns* call_ins = lir->insCall(&PrintOnTrace_ci, args_ins); - guard(false, lir->ins_eq0(call_ins), MISMATCH_EXIT); + guard(false, lir->ins_eq0(call_ins), MISMATCH_EXIT); } // Generate a 'printf'-type call from trace for debugging. @@ -901,7 +901,7 @@ TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LI } void -TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LIns *ins4, +TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LIns *ins4, LIns *ins5, LIns *ins6) { LIns* insa[] = { ins1, ins2, ins3, ins4, ins5, ins6 }; @@ -1786,7 +1786,7 @@ VisitFrameSlots(Visitor &visitor, unsigned depth, JSStackFrame *fp, // requires type |jsval|. But the bits are the same, so we can import // it with a cast and the (identity function) unboxing will be OK. visitor.setStackSlotKind("scopeChain"); - if (!visitor.visitStackSlots((jsval*) &fp->scopeChain, 1, fp)) + if (!visitor.visitStackSlots(&fp->scopeChainVal, 1, fp)) return false; visitor.setStackSlotKind("var"); if (!visitor.visitStackSlots(fp->slots, fp->script->nfixed, fp)) @@ -2093,7 +2093,7 @@ MergeTypeMaps(TraceType** partial, unsigned* plength, TraceType* complete, unsig } /* - * Specializes a tree to any specifically missing globals, including any + * Specializes a tree to any specifically missing globals, including any * dependent trees. */ static JS_REQUIRES_STACK void @@ -3301,7 +3301,7 @@ FlushNativeStackFrame(JSContext* cx, unsigned callDepth, const TraceType* mp, do for (; n != 0; fp = fp->down) { --n; if (fp->argv) { - if (fp->argsobj && + if (fp->argsobj && js_GetArgsPrivateNative(JSVAL_TO_OBJECT(fp->argsobj))) { JSVAL_TO_OBJECT(fp->argsobj)->setPrivate(fp); } @@ -3310,7 +3310,7 @@ FlushNativeStackFrame(JSContext* cx, unsigned callDepth, const TraceType* mp, do JS_ASSERT(HAS_FUNCTION_CLASS(fp->calleeObject())); JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee()) == fp->fun); - if (FUN_INTERPRETED(fp->fun) && + if (FUN_INTERPRETED(fp->fun) && (fp->fun->flags & JSFUN_HEAVYWEIGHT)) { // Iff these fields are NULL, then |fp| was synthesized on trace exit, so // we need to update the frame fields. @@ -3543,7 +3543,7 @@ TraceRecorder::importGlobalSlot(unsigned slot) { JS_ASSERT(slot == uint16(slot)); JS_ASSERT(STOBJ_NSLOTS(globalObj) <= MAX_GLOBAL_SLOTS); - + jsval* vp = &STOBJ_GET_SLOT(globalObj, slot); JS_ASSERT(!known(vp)); @@ -4941,7 +4941,7 @@ TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) (long long int)sp_adj, (long long int)tree->nativeStackBase, (long long int)inner->nativeStackBase); - ptrdiff_t sp_offset = + ptrdiff_t sp_offset = - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ + inner->maxNativeStackSlots * sizeof(double); /* plus the inner tree's stack */ @@ -5637,7 +5637,7 @@ RecordTree(JSContext* cx, TraceMonitor* tm, TreeFragment* peer, jsbytecode* oute debug_only_printf(LC_TMTreeVis, "%c", typeChar[f->typeMap[f->nStackTypes + i]]); debug_only_print0(LC_TMTreeVis, "\"\n"); #endif - + /* Recording primary trace. */ return TraceRecorder::startRecorder(cx, NULL, f, f->nStackTypes, f->globalSlots->length(), @@ -5973,9 +5973,8 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount) Blacklist(cx->fp->script->code); AbortRecording(cx, "Inner tree is an unsupported type of recursion"); return ARECORD_ABORTED; - } else { - f->recursion = Recursion_Disallowed; } + f->recursion = Recursion_Disallowed; } adjustCallerTypes(f); @@ -5990,7 +5989,7 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount) // Refresh the import type map so the tracker can reimport values after the // call with their correct types. The inner tree must not change the type of - // any variable in a frame above the current one (i.e., upvars). + // any variable in a frame above the current one (i.e., upvars). // // Note that DetermineTypesVisitor may call determineSlotType, which may // read from the (current, stale) import type map, but this is safe here. @@ -7737,7 +7736,7 @@ JS_REQUIRES_STACK LIns* TraceRecorder::scopeChain() { return cx->fp->callee() - ? get((jsval*) &cx->fp->scopeChain) + ? get(&cx->fp->scopeChainVal) : entryScopeChain(); } @@ -9703,8 +9702,8 @@ TraceRecorder::putActivationObjects() slots_ins = INS_CONSTPTR(0); } - LIns* scopeChain_ins = get((jsval*) &cx->fp->scopeChain); - LIns* args[] = { slots_ins, INS_CONST(nslots), args_ins, + LIns* scopeChain_ins = get(&cx->fp->scopeChainVal); + LIns* args[] = { slots_ins, INS_CONST(nslots), args_ins, INS_CONST(cx->fp->fun->nargs), scopeChain_ins, cx_ins }; lir->insCall(&js_PutCallObjectOnTrace_ci, args); } @@ -9776,7 +9775,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) if (cx->fp->fun && JSFUN_HEAVYWEIGHT_TEST(cx->fp->fun->flags)) { // We need to make sure every part of the frame is known to the tracker // before taking a snapshot. - set((jsval *) &fp->scopeChain, INS_NULL(), true); + set(&fp->scopeChainVal, INS_NULL(), true); if (js_IsNamedLambda(cx->fp->fun)) RETURN_STOP_A("can't call named lambda heavyweight on trace"); @@ -9787,9 +9786,9 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) LIns* call_ins = lir->insCall(&js_CreateCallObjectOnTrace_ci, args); guard(false, lir->ins_peq0(call_ins), snapshot(OOM_EXIT)); - set((jsval *) &fp->scopeChain, call_ins); + set(&fp->scopeChainVal, call_ins); } else { - set((jsval *) &fp->scopeChain, scopeChain_ins, true); + set(&fp->scopeChainVal, scopeChain_ins, true); } /* @@ -9986,9 +9985,9 @@ TraceRecorder::newArguments(LIns* callee_ins) LIns* global_ins = INS_CONSTOBJ(globalObj); LIns* argc_ins = INS_CONST(cx->fp->argc); LIns* argv_ins = cx->fp->argc - ? lir->ins2(LIR_piadd, lirbuf->sp, - lir->insImmWord(nativespOffset(&cx->fp->argv[0]))) - : INS_CONSTPTR((void *) 2); + ? lir->ins2(LIR_piadd, lirbuf->sp, + lir->insImmWord(nativespOffset(&cx->fp->argv[0]))) + : INS_CONSTPTR((void *) 2); ArgsPrivateNative *apn = ArgsPrivateNative::create(traceAlloc(), cx->fp->argc); for (uintN i = 0; i < cx->fp->argc; ++i) { apn->typemap()[i] = determineSlotType(&cx->fp->argv[i]); @@ -10014,7 +10013,7 @@ TraceRecorder::record_JSOP_ARGUMENTS() args_ins = newArguments(callee_ins); } else { // Generate LIR to create arguments only if it has not already been created. - + LIns* mem_ins = lir->insAlloc(sizeof(jsval)); LIns* br1 = lir->insBranch(LIR_jt, lir->ins_peq0(a_ins), NULL); @@ -11398,11 +11397,11 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty LIns *offset_ins = lir->ins2(LIR_mul, slot_ins, INS_CONST(sizeof(double))); // Guard that we are not changing the type of the slot we are storing to. - LIns *callstackBase_ins = lir->insLoad(LIR_ldp, lirbuf->state, + LIns *callstackBase_ins = lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, callstackBase)); LIns *frameInfo_ins = lir->insLoad(LIR_ldp, callstackBase_ins, 0); LIns *typemap_ins = lir->ins2(LIR_addp, frameInfo_ins, INS_CONSTWORD(sizeof(FrameInfo))); - LIns *type_ins = lir->insLoad(LIR_ldzb, + LIns *type_ins = lir->insLoad(LIR_ldzb, lir->ins2(LIR_addp, typemap_ins, lir->ins_u2p(slot_ins)), 0, ACC_READONLY); TraceType type = getCoercedType(v); @@ -11414,10 +11413,10 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty BRANCH_EXIT); // Store to the native stack slot. - LIns *stackBase_ins = lir->insLoad(LIR_ldp, lirbuf->state, + LIns *stackBase_ins = lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, stackBase)); LIns *storeValue_ins = isPromoteInt(v_ins) ? demote(lir, v_ins) : v_ins; - lir->insStorei(storeValue_ins, + lir->insStorei(storeValue_ins, lir->ins2(LIR_addp, stackBase_ins, lir->ins_u2p(offset_ins)), 0); LIns *br2 = lir->insBranch(LIR_j, NULL, NULL); @@ -11435,7 +11434,7 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty LIns *label2 = lir->ins0(LIR_label); br2->setTarget(label2); - + return RECORD_CONTINUE; } diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 484feeecb75b..267f8094b144 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -1,5 +1,5 @@ /* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */ -/* vim: set ts=40 sw=4 et tw=78: */ +/* vim: set ts=40 sw=4 et tw=99: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * diff --git a/js/src/jstypedarray.h b/js/src/jstypedarray.h index 9c7f71f78949..7cecfaf333a7 100644 --- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -1,5 +1,5 @@ /* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */ -/* vim: set ts=40 sw=4 et tw=78: */ +/* vim: set ts=40 sw=4 et tw=99: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * From 5b5fa0e2d3ea35c6e0bc503c38132d9418a760cd Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 2 Mar 2010 12:56:48 -0800 Subject: [PATCH 22/52] 540706 - Small record_EnterFrame simplification (r=dvander) --- js/src/jstracer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 559dc5929087..7ea1eb6bb702 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -9758,8 +9758,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) jsval* vp = &fp->argv[fp->argc]; jsval* vpstop = vp + ptrdiff_t(fp->fun->nargs) - ptrdiff_t(fp->argc); while (vp < vpstop) { - if (vp >= fp->down->regs->sp) - nativeFrameTracker.set(vp, (LIns*)0); + nativeFrameTracker.set(vp, (LIns*)0); set(vp++, void_ins, true); } From 6c48b4560c67027d12aef8a3ee73a5f0ee0c1d98 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 2 Mar 2010 14:04:50 -0800 Subject: [PATCH 23/52] Removed initializing inparam from TraceRecorder::set. (bug 549727, r=luke) --- js/src/jstracer.cpp | 26 +++++++++++++------------- js/src/jstracer.h | 3 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 7ea1eb6bb702..92cba42423fa 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3601,7 +3601,7 @@ TraceRecorder::writeBack(LIns* i, LIns* base, ptrdiff_t offset, bool shouldDemot /* Update the tracker, then issue a write back store. */ JS_REQUIRES_STACK void -TraceRecorder::set(jsval* p, LIns* i, bool initializing, bool demote) +TraceRecorder::set(jsval* p, LIns* i, bool demote) { JS_ASSERT(i != NULL); checkForGlobalObjectReallocation(); @@ -4472,7 +4472,7 @@ class SlotMap : public SlotVisitorBase JS_ASSERT(mRecorder.get(info.vp)->isF64()); /* Never demote this final i2f. */ - mRecorder.set(info.vp, mRecorder.get(info.vp), false, false); + mRecorder.set(info.vp, mRecorder.get(info.vp), false); } } @@ -8028,7 +8028,7 @@ TraceRecorder::stack(int n) JS_REQUIRES_STACK void TraceRecorder::stack(int n, LIns* i) { - set(&stackval(n), i, n >= 0); + set(&stackval(n), i); } JS_REQUIRES_STACK LIns* @@ -9759,14 +9759,14 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) jsval* vpstop = vp + ptrdiff_t(fp->fun->nargs) - ptrdiff_t(fp->argc); while (vp < vpstop) { nativeFrameTracker.set(vp, (LIns*)0); - set(vp++, void_ins, true); + set(vp++, void_ins); } vp = &fp->slots[0]; vpstop = vp + fp->script->nfixed; while (vp < vpstop) - set(vp++, void_ins, true); - set(&fp->argsobj, INS_NULL(), true); + set(vp++, void_ins); + set(&fp->argsobj, INS_NULL()); LIns* callee_ins = get(&cx->fp->argv[-2]); LIns* scopeChain_ins = stobj_get_parent(callee_ins); @@ -9774,7 +9774,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) if (cx->fp->fun && JSFUN_HEAVYWEIGHT_TEST(cx->fp->fun->flags)) { // We need to make sure every part of the frame is known to the tracker // before taking a snapshot. - set(&fp->scopeChainVal, INS_NULL(), true); + set(&fp->scopeChainVal, INS_NULL()); if (js_IsNamedLambda(cx->fp->fun)) RETURN_STOP_A("can't call named lambda heavyweight on trace"); @@ -9787,7 +9787,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) set(&fp->scopeChainVal, call_ins); } else { - set(&fp->scopeChainVal, scopeChain_ins, true); + set(&fp->scopeChainVal, scopeChain_ins); } /* @@ -9878,7 +9878,7 @@ TraceRecorder::record_LeaveFrame() // LeaveFrame gets called after the interpreter popped the frame and // stored rval, so cx->fp not cx->fp->down, and -1 not 0. atoms = FrameAtomBase(cx, cx->fp); - set(&stackval(-1), rval_ins, true); + set(&stackval(-1), rval_ins); return ARECORD_CONTINUE; } @@ -11490,9 +11490,9 @@ TraceRecorder::finishGetProp(LIns* obj_ins, LIns* vp_ins, LIns* ok_ins, jsval* o // guard. The deep-bail case requires this. If the property get fails, // these slots will be ignored anyway. LIns* result_ins = lir->insLoad(LIR_ldp, vp_ins, 0); - set(outp, result_ins, true); + set(outp, result_ins); if (js_CodeSpec[*cx->fp->regs->pc].format & JOF_CALLOP) - set(outp + 1, obj_ins, true); + set(outp + 1, obj_ins); // We need to guard on ok_ins, but this requires a snapshot of the state // after this op. monitorRecording will do it for us. @@ -12833,7 +12833,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp, } } while (guardHasPrototype(obj, obj_ins, &obj, &obj_ins, exit)); - set(outp, INS_CONST(JSVAL_TO_SPECIAL(JSVAL_VOID)), true); + set(outp, INS_CONST(JSVAL_TO_SPECIAL(JSVAL_VOID))); return ARECORD_CONTINUE; } @@ -12932,7 +12932,7 @@ TraceRecorder::propTail(JSObject* obj, LIns* obj_ins, JSObject* obj2, jsuword pc *v_insp = v_ins; } if (outp) - set(outp, v_ins, true); + set(outp, v_ins); return ARECORD_CONTINUE; } diff --git a/js/src/jstracer.h b/js/src/jstracer.h index ba3e59ca2cc6..22bfa528dd60 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1109,8 +1109,7 @@ class TraceRecorder nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset, bool demote); - JS_REQUIRES_STACK void set(jsval* p, nanojit::LIns* l, bool initializing = false, - bool demote = true); + JS_REQUIRES_STACK void set(jsval* p, nanojit::LIns* l, bool demote = true); nanojit::LIns* getFromTracker(jsval* p); JS_REQUIRES_STACK nanojit::LIns* get(jsval* p); JS_REQUIRES_STACK nanojit::LIns* attemptImport(jsval* p); From 3b2eafa1867e602952007a17e6a153856200ced6 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 31 Dec 2009 14:05:54 -0600 Subject: [PATCH 24/52] Bug 484508 - Support imacro groups corresponding to non-contiguous opcodes. r=brendan --- js/src/imacro_asm.js.in | 32 ++++++++++++++++++++++---------- js/src/imacros.jsasm | 3 ++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/js/src/imacro_asm.js.in b/js/src/imacro_asm.js.in index b0a83b945042..ff8bdbf7a537 100644 --- a/js/src/imacro_asm.js.in +++ b/js/src/imacro_asm.js.in @@ -182,7 +182,7 @@ const line_regexp_parts = [ "^(?:(\\w+):)?", // optional label at start of line "\\s*(\\.?\\w+)", // optional spaces, (pseudo-)opcode "(?:\\s+(\\w+|\\([^)]*\\)))?", // optional first immediate operand - "(?:\\s+([\\w-]+|\\([^)]*\\)))?", // optional second immediate operand + "(?:\\s+([\\w-,]+|\\([^)]*\\)))?", // optional second immediate operand "(?:\\s*(?:#.*))?$" // optional spaces and comment ]; @@ -216,14 +216,29 @@ function assemble(filename) { throw new Error("missing .igroup name"); if (igroup) throw new Error("nested .igroup " + imm1); - let oprange = imm2.match(/^(\w+)(?:-(\w+))?$/); - if (!oprange) + if (!imm2.match(/^\w+(?:-\w+)?(?:,\w+(?:-\w+)?)*$/)) throw new Error("invalid igroup operator range " + imm2); - let firstop = jsop2opcode[oprange[1]]; + let ops = imm2.split(",").reduce(function(initial, current) { + let split = current.match(/^(\w+)(?:-(\w+))?$/); + let opcode = jsop2opcode[split[1]]; + if (opcode in initial) + throw new Error("repeated opcode " + split[1]); + initial[opcode] = true; + if (split[2] !== undefined) { + let lastopcode = jsop2opcode[split[2]]; + if (opcode >= lastopcode) + throw new Error("invalid opcode range: " + current); + while (++opcode <= lastopcode) { + if (opcode in initial) + throw new Error("repeated opcode " + split[2]); + initial[opcode] = true; + } + } + return initial; + }, {}); igroup = { name: imm1, - firstop: firstop, - lastop: oprange[2] ? jsop2opcode[oprange[2]] : firstop, + ops: ops, imacros: [] }; break; @@ -286,11 +301,8 @@ function assemble(filename) { print("};"); - let opcode = igroup.firstop; - let oplast = igroup.lastop; - do { + for (let opcode in igroup.ops) opcode2extra[opcode] = maxdepth; - } while (opcode++ != oplast); igroups.push(igroup); igroup = null; } else { diff --git a/js/src/imacros.jsasm b/js/src/imacros.jsasm index b68c9bc6219f..c775042adde4 100644 --- a/js/src/imacros.jsasm +++ b/js/src/imacros.jsasm @@ -86,7 +86,8 @@ .end equality -.igroup binary JSOP_BITOR-JSOP_MOD +# A single range, split up like so to test groups over multiple ranges of ops +.igroup binary JSOP_BITOR-JSOP_BITAND,JSOP_EQ-JSOP_DIV,JSOP_MOD .imacro any_obj # any obj dup # any obj obj From 0dea5494a330450eda51bbe07315ee4aabb50dca Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 18 Feb 2010 19:51:57 -0800 Subject: [PATCH 25/52] Bug 547087 - JS_EnumerateStandardClasses uses non-configurable, not non-configurable/non-writable, as attributes for global.undefined. r=jorendorff --- js/src/jsapi.cpp | 3 ++- .../tests/ecma_5/misc/enumerate-undefined.js | 25 +++++++++++++++++++ js/src/tests/ecma_5/misc/jstests.list | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 js/src/tests/ecma_5/misc/enumerate-undefined.js diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 300b4b69c177..d9fe319a9f55 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1480,7 +1480,8 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) atom = rt->atomState.typeAtoms[JSTYPE_VOID]; if (!AlreadyHasOwnProperty(cx, obj, atom) && !obj->defineProperty(cx, ATOM_TO_JSID(atom), JSVAL_VOID, - JS_PropertyStub, JS_PropertyStub, JSPROP_PERMANENT)) { + JS_PropertyStub, JS_PropertyStub, + JSPROP_PERMANENT | JSPROP_READONLY)) { return JS_FALSE; } diff --git a/js/src/tests/ecma_5/misc/enumerate-undefined.js b/js/src/tests/ecma_5/misc/enumerate-undefined.js new file mode 100644 index 000000000000..163c611b2025 --- /dev/null +++ b/js/src/tests/ecma_5/misc/enumerate-undefined.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'enumerate-undefined.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 547087; +var summary = 'JS_EnumerateStandardClasses uses wrong attributes for undefined'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +for (var p in this); + +assertEq(Object.getOwnPropertyDescriptor(this, "undefined").writable, false); + +/******************************************************************************/ + +reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/ecma_5/misc/jstests.list b/js/src/tests/ecma_5/misc/jstests.list index 3a1e67a12100..136f00db5816 100644 --- a/js/src/tests/ecma_5/misc/jstests.list +++ b/js/src/tests/ecma_5/misc/jstests.list @@ -1,3 +1,4 @@ url-prefix ../../jsreftest.html?test=ecma_5/misc/ script global-numeric-properties.js script redeclare-var-non-writable-property.js +script enumerate-undefined.js From 7716ededf298361cb370bdd67a12af6e6f144e3c Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Tue, 2 Mar 2010 17:30:54 -0800 Subject: [PATCH 26/52] Bug 549617 - JS_EvaluateUCInStackFrame doesn't see variables in flat closure (r=mrbkap). --- js/src/jsfun.cpp | 175 +++++++++++------- js/src/shell/js.cpp | 8 +- js/src/tests/ecma/extensions/jstests.list | 1 + .../tests/ecma/extensions/trapflatclosure.js | 24 +++ 4 files changed, 133 insertions(+), 75 deletions(-) create mode 100644 js/src/tests/ecma/extensions/trapflatclosure.js diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index aba332600644..6c381a5d8fb5 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1007,113 +1007,135 @@ call_enumerate(JSContext *cx, JSObject *obj) return ok; } -typedef enum JSCallPropertyKind { +enum JSCallPropertyKind { JSCPK_ARGUMENTS, JSCPK_ARG, - JSCPK_VAR -} JSCallPropertyKind; + JSCPK_VAR, + JSCPK_UPVAR +}; static JSBool CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp, - JSCallPropertyKind kind, JSBool setter) + JSCallPropertyKind kind, JSBool setter = false) { - JSFunction *fun; - JSStackFrame *fp; - uintN i; - jsval *array; - - if (STOBJ_GET_CLASS(obj) != &js_CallClass) - return JS_TRUE; - - fun = js_GetCallObjectFunction(obj); - fp = (JSStackFrame *) obj->getPrivate(); - - if (kind == JSCPK_ARGUMENTS) { - if (setter) { - if (fp) - fp->flags |= JSFRAME_OVERRIDE_ARGS; - STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp); - } else { - if (fp && !(fp->flags & JSFRAME_OVERRIDE_ARGS)) { - JSObject *argsobj; - - argsobj = js_GetArgsObject(cx, fp); - if (!argsobj) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(argsobj); - } else { - *vp = STOBJ_GET_SLOT(obj, JSSLOT_CALL_ARGUMENTS); - } - } - return JS_TRUE; - } - + JS_ASSERT(obj->getClass() == &js_CallClass); JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id)); - i = (uint16) JSVAL_TO_INT(id); - JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs); - JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars); - if (!fp) { - i += CALL_CLASS_FIXED_RESERVED_SLOTS; - if (kind == JSCPK_VAR) - i += fun->nargs; - else - JS_ASSERT(kind == JSCPK_ARG); - return setter - ? JS_SetReservedSlot(cx, obj, i, *vp) - : JS_GetReservedSlot(cx, obj, i, vp); - } + uintN i = (uint16) JSVAL_TO_INT(id); - if (kind == JSCPK_ARG) { - array = fp->argv; + jsval *array; + if (kind == JSCPK_UPVAR) { + JSObject *callee = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(obj, JSSLOT_CALLEE)); + +#ifdef DEBUG + JSFunction *callee_fun = (JSFunction *) callee->getPrivate(); + JS_ASSERT(FUN_FLAT_CLOSURE(callee_fun)); + JS_ASSERT(i < callee_fun->u.i.nupvars); +#endif + + array = callee->dslots; } else { - JS_ASSERT(kind == JSCPK_VAR); - array = fp->slots; + JSFunction *fun = js_GetCallObjectFunction(obj); + JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs); + JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars); + + JSStackFrame *fp = (JSStackFrame *) obj->getPrivate(); + + if (kind == JSCPK_ARGUMENTS) { + if (setter) { + if (fp) + fp->flags |= JSFRAME_OVERRIDE_ARGS; + STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp); + } else { + if (fp && !(fp->flags & JSFRAME_OVERRIDE_ARGS)) { + JSObject *argsobj; + + argsobj = js_GetArgsObject(cx, fp); + if (!argsobj) + return false; + *vp = OBJECT_TO_JSVAL(argsobj); + } else { + *vp = STOBJ_GET_SLOT(obj, JSSLOT_CALL_ARGUMENTS); + } + } + return true; + } + + if (!fp) { + i += CALL_CLASS_FIXED_RESERVED_SLOTS; + if (kind == JSCPK_VAR) + i += fun->nargs; + else + JS_ASSERT(kind == JSCPK_ARG); + return setter + ? JS_SetReservedSlot(cx, obj, i, *vp) + : JS_GetReservedSlot(cx, obj, i, vp); + } + + if (kind == JSCPK_ARG) { + array = fp->argv; + } else { + JS_ASSERT(kind == JSCPK_VAR); + array = fp->slots; + } } + if (setter) { GC_POKE(cx, array[i]); array[i] = *vp; } else { *vp = array[i]; } - return JS_TRUE; + return true; } static JSBool GetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_FALSE); + return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS); } static JSBool SetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_TRUE); + return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, true); } JSBool js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE); + return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG); } JSBool SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE); + return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, true); +} + +JSBool +GetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + return CallPropertyOp(cx, obj, id, vp, JSCPK_UPVAR); +} + +JSBool +SetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + return CallPropertyOp(cx, obj, id, vp, JSCPK_UPVAR, true); } JSBool js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE); + return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR); } JSBool js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE)) - return JS_FALSE; + if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR)) + return false; return CheckForEscapingClosure(cx, obj, vp); } @@ -1121,19 +1143,19 @@ js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp) JSBool SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE); + return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, true); } JSBool JS_FASTCALL js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v) { - return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, JS_TRUE); + return CallPropertyOp(cx, obj, id, &v, JSCPK_ARG, true); } JSBool JS_FASTCALL js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v) { - return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, JS_TRUE); + return CallPropertyOp(cx, obj, id, &v, JSCPK_VAR, true); } JS_DEFINE_CALLINFO_4(extern, BOOL, js_SetCallArg, CONTEXT, OBJECT, JSID, JSVAL, 0, @@ -1178,7 +1200,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, * comments in js_PurgeScopeChainHelper from jsobj.cpp. */ localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot); - if (localKind != JSLOCAL_NONE && localKind != JSLOCAL_UPVAR) { + if (localKind != JSLOCAL_NONE) { JS_ASSERT((uint16) slot == slot); /* @@ -1191,12 +1213,22 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, getter = js_GetCallArg; setter = SetCallArg; } else { - JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST); - JS_ASSERT(slot < fun->u.i.nvars); - getter = js_GetCallVar; - setter = SetCallVar; - if (localKind == JSLOCAL_CONST) - attrs |= JSPROP_READONLY; + JSCallPropertyKind cpkind; + if (localKind == JSLOCAL_UPVAR) { + if (!FUN_FLAT_CLOSURE(fun)) + return JS_TRUE; + getter = GetFlatUpvar; + setter = SetFlatUpvar; + cpkind = JSCPK_UPVAR; + } else { + JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST); + JS_ASSERT(slot < fun->u.i.nvars); + getter = js_GetCallVar; + setter = SetCallVar; + cpkind = JSCPK_VAR; + if (localKind == JSLOCAL_CONST) + attrs |= JSPROP_READONLY; + } /* * Use js_GetCallVarChecked if the local's value is a null closure. @@ -1204,7 +1236,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, * null closure, not on every use. */ jsval v; - if (!CallPropertyOp(cx, obj, INT_TO_JSID((int16)slot), &v, JSCPK_VAR, JS_FALSE)) + if (!CallPropertyOp(cx, obj, INT_TO_JSID((int16)slot), &v, cpkind)) return JS_FALSE; if (VALUE_IS_FUNCTION(cx, v) && GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))->needsWrapper()) { @@ -2535,6 +2567,7 @@ js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun) { JS_ASSERT(cx->fp->fun->flags & JSFUN_HEAVYWEIGHT); JS_ASSERT(!cx->fp->fun->optimizedClosure()); + JS_ASSERT(FUN_FLAT_CLOSURE(fun)); return WrapEscapingClosure(cx, cx->fp, FUN_OBJECT(fun), fun); } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index ca3ce67c6cd8..9296e09a0106 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1457,10 +1457,10 @@ TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, str = (JSString *) closure; caller = JS_GetScriptedCaller(cx, NULL); - if (!JS_EvaluateScript(cx, caller->scopeChain, - JS_GetStringBytes(str), JS_GetStringLength(str), - caller->script->filename, caller->script->lineno, - rval)) { + if (!JS_EvaluateUCInStackFrame(cx, caller, + JS_GetStringChars(str), JS_GetStringLength(str), + caller->script->filename, caller->script->lineno, + rval)) { return JSTRAP_ERROR; } if (!JSVAL_IS_VOID(*rval)) diff --git a/js/src/tests/ecma/extensions/jstests.list b/js/src/tests/ecma/extensions/jstests.list index 12d4973695bb..f50d09d859c9 100644 --- a/js/src/tests/ecma/extensions/jstests.list +++ b/js/src/tests/ecma/extensions/jstests.list @@ -32,3 +32,4 @@ script 15.8-1.js script 15.9.5.js script 8.6.2.1-1.js script 9.9-1.js +script testflatclosure.js diff --git a/js/src/tests/ecma/extensions/trapflatclosure.js b/js/src/tests/ecma/extensions/trapflatclosure.js new file mode 100644 index 000000000000..3f4bb343de76 --- /dev/null +++ b/js/src/tests/ecma/extensions/trapflatclosure.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'trapflatclosure.js'; +var BUGNUMBER = 549617; +var summary = 'flat closure debugged via trap while still active'; + +var expect = "abc"; +var actual = expect; + +function a(x, y) { + return function () { return x; }; +} + +var f = a("abc", 123); +if (this.trap) + trap(f, "try {actual = x} catch (e) {actual = e}"); +f(); + +reportCompare(expect, actual, summary); + +printStatus("All tests passed!"); From 24efecca53de08cc713594ccc12aa4d11ee64512 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Tue, 2 Mar 2010 17:48:00 -0800 Subject: [PATCH 27/52] Typo'ed testname in jstests.list for 549617. --- js/src/tests/ecma/extensions/jstests.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/tests/ecma/extensions/jstests.list b/js/src/tests/ecma/extensions/jstests.list index f50d09d859c9..94e9b12893e9 100644 --- a/js/src/tests/ecma/extensions/jstests.list +++ b/js/src/tests/ecma/extensions/jstests.list @@ -32,4 +32,4 @@ script 15.8-1.js script 15.9.5.js script 8.6.2.1-1.js script 9.9-1.js -script testflatclosure.js +script trapflatclosure.js From fe60436390f69dace829e7797dc7c2d11cd2b6c8 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 3 Mar 2010 09:26:04 -0800 Subject: [PATCH 28/52] Bug 515812 - Fix Range assignment (r=me) --- js/src/jshashtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jshashtable.h b/js/src/jshashtable.h index 8771af4b78af..358df5333161 100644 --- a/js/src/jshashtable.h +++ b/js/src/jshashtable.h @@ -140,7 +140,7 @@ class HashTable : AllocPolicy ++cur; } - Entry *cur, * const end; + Entry *cur, *end; public: bool empty() const { From ec8581732d88fb54507d86d8058405ff674e41cf Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 3 Mar 2010 14:44:03 -0800 Subject: [PATCH 29/52] Fix CallPropertyOp to cope with non-int arguments id (549951, r=mrbkap). --- js/src/jsfun.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 6c381a5d8fb5..3a22950ca196 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1019,9 +1019,12 @@ CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp, JSCallPropertyKind kind, JSBool setter = false) { JS_ASSERT(obj->getClass() == &js_CallClass); - JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id)); - uintN i = (uint16) JSVAL_TO_INT(id); + uintN i = 0; + if (kind != JSCPK_ARGUMENTS) { + JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id)); + i = (uint16) JSVAL_TO_INT(id); + } jsval *array; if (kind == JSCPK_UPVAR) { From bf5b082e09bbab1c860f8a385194bbecd9682d1a Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 3 Mar 2010 16:43:17 -0800 Subject: [PATCH 30/52] Fix latent bug, exposed by fix for 549617, where JS_EvaluateUCInStackFrame looks like eval and confuses the compiler into writing into the empty script singleton-const (550045, r=mrbkap). --- js/src/jsparse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 0319c7ae622f..412b0af7bb5e 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -1056,7 +1056,7 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal JS_DumpArenaStats(stdout); #endif script = js_NewScriptFromCG(cx, &cg); - if (script && funbox) + if (script && funbox && script != script->emptyScript()) script->savedCallerFun = true; #ifdef JS_SCOPE_DEPTH_METER From ffafb514eda6a985fbf77b057ce295579fa8f314 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 3 Mar 2010 17:14:20 -0800 Subject: [PATCH 31/52] Fix dictionary-mode scope property node alloc to happen inside rt->gcLock (538307, r=jorendorff). --- js/src/jsscope.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index fac7a7f567ce..076bbbf90bec 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1092,7 +1092,9 @@ JSScopeProperty * JSScope::newDictionaryProperty(JSContext *cx, const JSScopeProperty &child, JSScopeProperty **childp) { + JS_LOCK_GC(cx->runtime); JSScopeProperty *dprop = NewScopeProperty(cx->runtime); + JS_UNLOCK_GC(cx->runtime); if (!dprop) { JS_ReportOutOfMemory(cx); return NULL; From 8befd2ecbb0f2a0265510dc1534c809af2716b43 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 1 Mar 2010 17:40:01 -0800 Subject: [PATCH 32/52] Bug 549503: more SunSpider verification tests, r=dvander --HG-- extra : rebase_source : 15ebc76e6de2c982ca77bb6a271f691ddc8559a8 --- .../tests/sunspider/check-3d-cube.js | 345 ++++ .../tests/sunspider/check-crypto-aes.js | 424 ++++ .../tests/sunspider/check-crypto-md5.js | 287 +++ .../tests/sunspider/check-crypto-sha1.js | 225 +++ .../tests/sunspider/check-math-cordic.js | 100 + .../sunspider/check-math-partial-sums.js | 36 + .../sunspider/check-math-spectral-norm.js | 53 + .../tests/sunspider/check-regexp-dna.js | 1714 +++++++++++++++++ .../tests/sunspider/check-string-fasta.js | 90 + .../tests/sunspider/check-string-tagcloud.js | 266 +++ .../sunspider/check-string-unpack-code.js | 73 + 11 files changed, 3613 insertions(+) create mode 100644 js/src/trace-test/tests/sunspider/check-3d-cube.js create mode 100644 js/src/trace-test/tests/sunspider/check-crypto-aes.js create mode 100644 js/src/trace-test/tests/sunspider/check-crypto-md5.js create mode 100644 js/src/trace-test/tests/sunspider/check-crypto-sha1.js create mode 100644 js/src/trace-test/tests/sunspider/check-math-cordic.js create mode 100644 js/src/trace-test/tests/sunspider/check-math-partial-sums.js create mode 100644 js/src/trace-test/tests/sunspider/check-math-spectral-norm.js create mode 100644 js/src/trace-test/tests/sunspider/check-regexp-dna.js create mode 100644 js/src/trace-test/tests/sunspider/check-string-fasta.js create mode 100644 js/src/trace-test/tests/sunspider/check-string-tagcloud.js create mode 100644 js/src/trace-test/tests/sunspider/check-string-unpack-code.js diff --git a/js/src/trace-test/tests/sunspider/check-3d-cube.js b/js/src/trace-test/tests/sunspider/check-3d-cube.js new file mode 100644 index 000000000000..036a4f6f7107 --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-3d-cube.js @@ -0,0 +1,345 @@ +// 3D Cube Rotation +// http://www.speich.net/computer/moztesting/3d.htm +// Created by Simon Speich + +var Q = new Array(); +var MTrans = new Array(); // transformation matrix +var MQube = new Array(); // position information of qube +var I = new Array(); // entity matrix +var Origin = new Object(); +var Testing = new Object(); +var LoopTimer; + +var DisplArea = new Object(); +DisplArea.Width = 300; +DisplArea.Height = 300; + +function DrawLine(From, To) { + var x1 = From.V[0]; + var x2 = To.V[0]; + var y1 = From.V[1]; + var y2 = To.V[1]; + var dx = Math.abs(x2 - x1); + var dy = Math.abs(y2 - y1); + var x = x1; + var y = y1; + var IncX1, IncY1; + var IncX2, IncY2; + var Den; + var Num; + var NumAdd; + var NumPix; + + if (x2 >= x1) { IncX1 = 1; IncX2 = 1; } + else { IncX1 = -1; IncX2 = -1; } + if (y2 >= y1) { IncY1 = 1; IncY2 = 1; } + else { IncY1 = -1; IncY2 = -1; } + if (dx >= dy) { + IncX1 = 0; + IncY2 = 0; + Den = dx; + Num = dx / 2; + NumAdd = dy; + NumPix = dx; + } + else { + IncX2 = 0; + IncY1 = 0; + Den = dy; + Num = dy / 2; + NumAdd = dx; + NumPix = dy; + } + + NumPix = Math.round(Q.LastPx + NumPix); + + var i = Q.LastPx; + for (; i < NumPix; i++) { + Num += NumAdd; + if (Num >= Den) { + Num -= Den; + x += IncX1; + y += IncY1; + } + x += IncX2; + y += IncY2; + } + Q.LastPx = NumPix; +} + +function CalcCross(V0, V1) { + var Cross = new Array(); + Cross[0] = V0[1]*V1[2] - V0[2]*V1[1]; + Cross[1] = V0[2]*V1[0] - V0[0]*V1[2]; + Cross[2] = V0[0]*V1[1] - V0[1]*V1[0]; + return Cross; +} + +function CalcNormal(V0, V1, V2) { + var A = new Array(); var B = new Array(); + for (var i = 0; i < 3; i++) { + A[i] = V0[i] - V1[i]; + B[i] = V2[i] - V1[i]; + } + A = CalcCross(A, B); + var Length = Math.sqrt(A[0]*A[0] + A[1]*A[1] + A[2]*A[2]); + for (var i = 0; i < 3; i++) A[i] = A[i] / Length; + A[3] = 1; + return A; +} + +function CreateP(X,Y,Z) { + this.V = [X,Y,Z,1]; +} + +// multiplies two matrices +function MMulti(M1, M2) { + var M = [[],[],[],[]]; + var i = 0; + var j = 0; + for (; i < 4; i++) { + j = 0; + for (; j < 4; j++) M[i][j] = M1[i][0] * M2[0][j] + M1[i][1] * M2[1][j] + M1[i][2] * M2[2][j] + M1[i][3] * M2[3][j]; + } + return M; +} + +//multiplies matrix with vector +function VMulti(M, V) { + var Vect = new Array(); + var i = 0; + for (;i < 4; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2] + M[i][3] * V[3]; + return Vect; +} + +function VMulti2(M, V) { + var Vect = new Array(); + var i = 0; + for (;i < 3; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2]; + return Vect; +} + +// add to matrices +function MAdd(M1, M2) { + var M = [[],[],[],[]]; + var i = 0; + var j = 0; + for (; i < 4; i++) { + j = 0; + for (; j < 4; j++) M[i][j] = M1[i][j] + M2[i][j]; + } + return M; +} + +function Translate(M, Dx, Dy, Dz) { + var T = [ + [1,0,0,Dx], + [0,1,0,Dy], + [0,0,1,Dz], + [0,0,0,1] + ]; + return MMulti(T, M); +} + +function RotateX(M, Phi) { + var a = Phi; + a *= Math.PI / 180; + var Cos = Math.cos(a); + var Sin = Math.sin(a); + var R = [ + [1,0,0,0], + [0,Cos,-Sin,0], + [0,Sin,Cos,0], + [0,0,0,1] + ]; + return MMulti(R, M); +} + +function RotateY(M, Phi) { + var a = Phi; + a *= Math.PI / 180; + var Cos = Math.cos(a); + var Sin = Math.sin(a); + var R = [ + [Cos,0,Sin,0], + [0,1,0,0], + [-Sin,0,Cos,0], + [0,0,0,1] + ]; + return MMulti(R, M); +} + +function RotateZ(M, Phi) { + var a = Phi; + a *= Math.PI / 180; + var Cos = Math.cos(a); + var Sin = Math.sin(a); + var R = [ + [Cos,-Sin,0,0], + [Sin,Cos,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + return MMulti(R, M); +} + +function DrawQube() { + // calc current normals + var CurN = new Array(); + var i = 5; + Q.LastPx = 0; + for (; i > -1; i--) CurN[i] = VMulti2(MQube, Q.Normal[i]); + if (CurN[0][2] < 0) { + if (!Q.Line[0]) { DrawLine(Q[0], Q[1]); Q.Line[0] = true; }; + if (!Q.Line[1]) { DrawLine(Q[1], Q[2]); Q.Line[1] = true; }; + if (!Q.Line[2]) { DrawLine(Q[2], Q[3]); Q.Line[2] = true; }; + if (!Q.Line[3]) { DrawLine(Q[3], Q[0]); Q.Line[3] = true; }; + } + if (CurN[1][2] < 0) { + if (!Q.Line[2]) { DrawLine(Q[3], Q[2]); Q.Line[2] = true; }; + if (!Q.Line[9]) { DrawLine(Q[2], Q[6]); Q.Line[9] = true; }; + if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; }; + if (!Q.Line[10]) { DrawLine(Q[7], Q[3]); Q.Line[10] = true; }; + } + if (CurN[2][2] < 0) { + if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; }; + if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; }; + if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; }; + if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; }; + } + if (CurN[3][2] < 0) { + if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; }; + if (!Q.Line[8]) { DrawLine(Q[5], Q[1]); Q.Line[8] = true; }; + if (!Q.Line[0]) { DrawLine(Q[1], Q[0]); Q.Line[0] = true; }; + if (!Q.Line[11]) { DrawLine(Q[0], Q[4]); Q.Line[11] = true; }; + } + if (CurN[4][2] < 0) { + if (!Q.Line[11]) { DrawLine(Q[4], Q[0]); Q.Line[11] = true; }; + if (!Q.Line[3]) { DrawLine(Q[0], Q[3]); Q.Line[3] = true; }; + if (!Q.Line[10]) { DrawLine(Q[3], Q[7]); Q.Line[10] = true; }; + if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; }; + } + if (CurN[5][2] < 0) { + if (!Q.Line[8]) { DrawLine(Q[1], Q[5]); Q.Line[8] = true; }; + if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; }; + if (!Q.Line[9]) { DrawLine(Q[6], Q[2]); Q.Line[9] = true; }; + if (!Q.Line[1]) { DrawLine(Q[2], Q[1]); Q.Line[1] = true; }; + } + Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false]; + Q.LastPx = 0; +} + +function Loop() { + if (Testing.LoopCount > Testing.LoopMax) return; + var TestingStr = String(Testing.LoopCount); + while (TestingStr.length < 3) TestingStr = "0" + TestingStr; + MTrans = Translate(I, -Q[8].V[0], -Q[8].V[1], -Q[8].V[2]); + MTrans = RotateX(MTrans, 1); + MTrans = RotateY(MTrans, 3); + MTrans = RotateZ(MTrans, 5); + MTrans = Translate(MTrans, Q[8].V[0], Q[8].V[1], Q[8].V[2]); + MQube = MMulti(MTrans, MQube); + var i = 8; + for (; i > -1; i--) { + Q[i].V = VMulti(MTrans, Q[i].V); + } + DrawQube(); + Testing.LoopCount++; + Loop(); +} + +function Init(CubeSize) { + // init/reset vars + Origin.V = [150,150,20,1]; + Testing.LoopCount = 0; + Testing.LoopMax = 50; + Testing.TimeMax = 0; + Testing.TimeAvg = 0; + Testing.TimeMin = 0; + Testing.TimeTemp = 0; + Testing.TimeTotal = 0; + Testing.Init = false; + + // transformation matrix + MTrans = [ + [1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + + // position information of qube + MQube = [ + [1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + + // entity matrix + I = [ + [1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + + // create qube + Q[0] = new CreateP(-CubeSize,-CubeSize, CubeSize); + Q[1] = new CreateP(-CubeSize, CubeSize, CubeSize); + Q[2] = new CreateP( CubeSize, CubeSize, CubeSize); + Q[3] = new CreateP( CubeSize,-CubeSize, CubeSize); + Q[4] = new CreateP(-CubeSize,-CubeSize,-CubeSize); + Q[5] = new CreateP(-CubeSize, CubeSize,-CubeSize); + Q[6] = new CreateP( CubeSize, CubeSize,-CubeSize); + Q[7] = new CreateP( CubeSize,-CubeSize,-CubeSize); + + // center of gravity + Q[8] = new CreateP(0, 0, 0); + + // anti-clockwise edge check + Q.Edge = [[0,1,2],[3,2,6],[7,6,5],[4,5,1],[4,0,3],[1,5,6]]; + + // calculate squad normals + Q.Normal = new Array(); + for (var i = 0; i < Q.Edge.length; i++) Q.Normal[i] = CalcNormal(Q[Q.Edge[i][0]].V, Q[Q.Edge[i][1]].V, Q[Q.Edge[i][2]].V); + + // line drawn ? + Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false]; + + // create line pixels + Q.NumPx = 9 * 2 * CubeSize; + for (var i = 0; i < Q.NumPx; i++) CreateP(0,0,0); + + MTrans = Translate(MTrans, Origin.V[0], Origin.V[1], Origin.V[2]); + MQube = MMulti(MTrans, MQube); + + var i = 0; + for (; i < 9; i++) { + Q[i].V = VMulti(MTrans, Q[i].V); + } + DrawQube(); + Testing.Init = true; + Loop(); +} + +for ( var i = 20; i <= 160; i *= 2 ) { + Init(i); +} + +var actual = ''; +for (var i = 0; i < Q.length; ++i) { + actual += Q[i].V + ';'; +} +var expected = "-116.618229186398,212.51135212951073,62.5094191967962,1;127.83701023614447,417.11611179082263,90.41153816299942,1;293.9570894432935,196.58093046570656,252.17789153139591,1;49.501850020750915,-8.02382919560505,224.275772565193,1;6.042910556709444,103.41906953429206,-212.1778915313964,1;250.49814997925202,308.02382919560387,-184.27577256519325,1;416.61822918640064,87.48864787048812,-22.509419196796493,1;172.1629897638581,-117.1161117908236,-50.41153816299975,1;150.0000000000007,149.99999999999952,20,1;"; +assertEq(actual, expected); + +Q = null; +MTrans = null; +MQube = null; +I = null; +Origin = null; +Testing = null; +LoopTime = null; +DisplArea = null; + diff --git a/js/src/trace-test/tests/sunspider/check-crypto-aes.js b/js/src/trace-test/tests/sunspider/check-crypto-aes.js new file mode 100644 index 000000000000..6bcdb5496405 --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-crypto-aes.js @@ -0,0 +1,424 @@ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* + * AES Cipher function: encrypt 'input' with Rijndael algorithm + * + * takes byte-array 'input' (16 bytes) + * 2D byte-array key schedule 'w' (Nr+1 x Nb bytes) + * + * applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage + * + * returns byte-array encrypted value (16 bytes) + */ +function Cipher(input, w) { // main Cipher function [§5.1] + var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) + var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys + + var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4] + for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i]; + + state = AddRoundKey(state, w, 0, Nb); + + for (var round=1; round 6 && i%Nk == 4) { + temp = SubWord(temp); + } + for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t]; + } + + return w; +} + +function SubWord(w) { // apply SBox to 4-byte word w + for (var i=0; i<4; i++) w[i] = Sbox[w[i]]; + return w; +} + +function RotWord(w) { // rotate 4-byte word w left by one byte + w[4] = w[0]; + for (var i=0; i<4; i++) w[i] = w[i+1]; + return w; +} + + +// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1] +var Sbox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]; + +// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] +var Rcon = [ [0x00, 0x00, 0x00, 0x00], + [0x01, 0x00, 0x00, 0x00], + [0x02, 0x00, 0x00, 0x00], + [0x04, 0x00, 0x00, 0x00], + [0x08, 0x00, 0x00, 0x00], + [0x10, 0x00, 0x00, 0x00], + [0x20, 0x00, 0x00, 0x00], + [0x40, 0x00, 0x00, 0x00], + [0x80, 0x00, 0x00, 0x00], + [0x1b, 0x00, 0x00, 0x00], + [0x36, 0x00, 0x00, 0x00] ]; + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* + * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation + * - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + * for each block + * - outputblock = cipher(counter, key) + * - cipherblock = plaintext xor outputblock + */ +function AESEncryptCtr(plaintext, password, nBits) { + if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys + + // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; + // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1 + var nBytes = nBits/8; // no bytes in key + var pwBytes = new Array(nBytes); + for (var i=0; i>> i*8) & 0xff; + for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; + + // generate key schedule - an expansion of the key into distinct Key Rounds for each round + var keySchedule = KeyExpansion(key); + + var blockCount = Math.ceil(plaintext.length/blockSize); + var ciphertext = new Array(blockCount); // ciphertext as array of strings + + for (var b=0; b>> c*8) & 0xff; + for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8) + + var cipherCntr = Cipher(counterBlock, keySchedule); // -- encrypt counter block -- + + // calculate length of final block: + var blockLength = b>> c*8) & 0xff; + for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff; + + var cipherCntr = Cipher(counterBlock, keySchedule); // encrypt counter block + + ciphertext[b] = unescCtrlChars(ciphertext[b]); + + var pt = ''; + for (var i=0; i>18 & 0x3f; + h2 = bits>>12 & 0x3f; + h3 = bits>>6 & 0x3f; + h4 = bits & 0x3f; + + // end of string? index to '=' in b64 + if (isNaN(o3)) h4 = 64; + if (isNaN(o2)) h3 = 64; + + // use hexets to index into b64, and append result to encoded string + enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < str.length); + + return enc; +} + +function decodeBase64(str) { + var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc=''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(str.charAt(i++)); + h2 = b64.indexOf(str.charAt(i++)); + h3 = b64.indexOf(str.charAt(i++)); + h4 = b64.indexOf(str.charAt(i++)); + + bits = h1<<18 | h2<<12 | h3<<6 | h4; + + o1 = bits>>16 & 0xff; + o2 = bits>>8 & 0xff; + o3 = bits & 0xff; + + if (h3 == 64) enc += String.fromCharCode(o1); + else if (h4 == 64) enc += String.fromCharCode(o1, o2); + else enc += String.fromCharCode(o1, o2, o3); + } while (i < str.length); + + return decodeUTF8(enc); // decode UTF-8 byte-array back to Unicode +} + +function encodeUTF8(str) { // encode multi-byte string into utf-8 multiple single-byte characters + str = str.replace( + /[\u0080-\u07ff]/g, // U+0080 - U+07FF = 2-byte chars + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } + ); + str = str.replace( + /[\u0800-\uffff]/g, // U+0800 - U+FFFF = 3-byte chars + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } + ); + return str; +} + +function decodeUTF8(str) { // decode utf-8 encoded string back into multi-byte characters + str = str.replace( + /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars + function(c) { + var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; + return String.fromCharCode(cc); } + ); + str = str.replace( + /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars + function(c) { + var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f; + return String.fromCharCode(cc); } + ); + return str; +} + + +function byteArrayToHexStr(b) { // convert byte array to hex string for displaying test vectors + var s = ''; + for (var i=0; i> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) +{ + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); +} +function md5_ff(a, b, c, d, x, s, t) +{ + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) +{ + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) +{ + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) +{ + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Calculate the HMAC-MD5, of a key and some data + */ +function core_hmac_md5(key, data) +{ + var bkey = str2binl(key); + if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); + return core_md5(opad.concat(hash), 512 + 128); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert a string to an array of little-endian words + * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. + */ +function str2binl(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); + return bin; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); + return str; +} + +/* + * Convert an array of little-endian words to a hex string. + */ +function binl2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of little-endian words to a base-64 string + */ +function binl2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} + +var plainText = "Rebellious subjects, enemies to peace,\n\ +Profaners of this neighbour-stained steel,--\n\ +Will they not hear? What, ho! you men, you beasts,\n\ +That quench the fire of your pernicious rage\n\ +With purple fountains issuing from your veins,\n\ +On pain of torture, from those bloody hands\n\ +Throw your mistemper'd weapons to the ground,\n\ +And hear the sentence of your moved prince.\n\ +Three civil brawls, bred of an airy word,\n\ +By thee, old Capulet, and Montague,\n\ +Have thrice disturb'd the quiet of our streets,\n\ +And made Verona's ancient citizens\n\ +Cast by their grave beseeming ornaments,\n\ +To wield old partisans, in hands as old,\n\ +Canker'd with peace, to part your canker'd hate:\n\ +If ever you disturb our streets again,\n\ +Your lives shall pay the forfeit of the peace.\n\ +For this time, all the rest depart away:\n\ +You Capulet; shall go along with me:\n\ +And, Montague, come you this afternoon,\n\ +To know our further pleasure in this case,\n\ +To old Free-town, our common judgment-place.\n\ +Once more, on pain of death, all men depart." + +for (var i = 0; i <4; i++) { + plainText += plainText; +} + +var md5Output = hex_md5(plainText); +assertEq(md5Output, "a831e91e0f70eddcb70dc61c6f82f6cd") diff --git a/js/src/trace-test/tests/sunspider/check-crypto-sha1.js b/js/src/trace-test/tests/sunspider/check-crypto-sha1.js new file mode 100644 index 000000000000..d25d5adb1dbe --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-crypto-sha1.js @@ -0,0 +1,225 @@ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ +var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} +function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} +function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} +function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} +function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} +function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha1_vm_test() +{ + return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; +} + +/* + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ +function core_sha1(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for(var j = 0; j < 80; j++) + { + if(j < 16) w[j] = x[i + j]; + else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); + var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + +} + +/* + * Perform the appropriate triplet combination function for the current + * iteration + */ +function sha1_ft(t, b, c, d) +{ + if(t < 20) return (b & c) | ((~b) & d); + if(t < 40) return b ^ c ^ d; + if(t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; +} + +/* + * Determine the appropriate additive constant for the current iteration + */ +function sha1_kt(t) +{ + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; +} + +/* + * Calculate the HMAC-SHA1 of a key and some data + */ +function core_hmac_sha1(key, data) +{ + var bkey = str2binb(key); + if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); + return core_sha1(opad.concat(hash), 512 + 160); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert an 8-bit or 16-bit string to an array of big-endian words + * In 8-bit function, characters >255 have their hi-byte silently ignored. + */ +function str2binb(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); + return bin; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); + return str; +} + +/* + * Convert an array of big-endian words to a hex string. + */ +function binb2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of big-endian words to a base-64 string + */ +function binb2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} + + +var plainText = "Two households, both alike in dignity,\n\ +In fair Verona, where we lay our scene,\n\ +From ancient grudge break to new mutiny,\n\ +Where civil blood makes civil hands unclean.\n\ +From forth the fatal loins of these two foes\n\ +A pair of star-cross'd lovers take their life;\n\ +Whole misadventured piteous overthrows\n\ +Do with their death bury their parents' strife.\n\ +The fearful passage of their death-mark'd love,\n\ +And the continuance of their parents' rage,\n\ +Which, but their children's end, nought could remove,\n\ +Is now the two hours' traffic of our stage;\n\ +The which if you with patient ears attend,\n\ +What here shall miss, our toil shall strive to mend."; + +for (var i = 0; i <4; i++) { + plainText += plainText; +} + +var sha1Output = hex_sha1(plainText); +assertEq(sha1Output, "2524d264def74cce2498bf112bedf00e6c0b796d") diff --git a/js/src/trace-test/tests/sunspider/check-math-cordic.js b/js/src/trace-test/tests/sunspider/check-math-cordic.js new file mode 100644 index 000000000000..f1ade3a3b2e8 --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-math-cordic.js @@ -0,0 +1,100 @@ +/* + * Copyright (C) Rich Moore. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/////. Start CORDIC + +var AG_CONST = 0.6072529350; + +function FIXED(X) +{ + return X * 65536.0; +} + +function FLOAT(X) +{ + return X / 65536.0; +} + +function DEG2RAD(X) +{ + return 0.017453 * (X); +} + +var Angles = [ + FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502), + FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614), + FIXED(0.223811), FIXED(0.111906), FIXED(0.055953), + FIXED(0.027977) + ]; + + +function cordicsincos() { + var X; + var Y; + var TargetAngle; + var CurrAngle; + var Step; + + X = FIXED(AG_CONST); /* AG_CONST * cos(0) */ + Y = 0; /* AG_CONST * sin(0) */ + + TargetAngle = FIXED(28.027); + CurrAngle = 0; + for (Step = 0; Step < 12; Step++) { + var NewX; + if (TargetAngle > CurrAngle) { + NewX = X - (Y >> Step); + Y = (X >> Step) + Y; + X = NewX; + CurrAngle += Angles[Step]; + } else { + NewX = X + (Y >> Step); + Y = -(X >> Step) + Y; + X = NewX; + CurrAngle -= Angles[Step]; + } + } + return CurrAngle; +} + +///// End CORDIC + +function cordic( runs ) { + var actual; + + var start = new Date(); + + for ( var i = 0 ; i < runs ; i++ ) { + actual = cordicsincos(); + } + + var end = new Date(); + + assertEq(actual, 1834995.3515519998) + + return end.getTime() - start.getTime(); +} + +cordic(25000); diff --git a/js/src/trace-test/tests/sunspider/check-math-partial-sums.js b/js/src/trace-test/tests/sunspider/check-math-partial-sums.js new file mode 100644 index 000000000000..21a896a70a3c --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-math-partial-sums.js @@ -0,0 +1,36 @@ +// The Computer Language Shootout +// http://shootout.alioth.debian.org/ +// contributed by Isaac Gouy + +function partial(n){ + var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0; + var twothirds = 2.0/3.0; + var alt = -1.0; + var k2 = k3 = sk = ck = 0.0; + + for (var k = 1; k <= n; k++){ + k2 = k*k; + k3 = k2*k; + sk = Math.sin(k); + ck = Math.cos(k); + alt = -alt; + + a1 += Math.pow(twothirds,k-1); + a2 += Math.pow(k,-0.5); + a3 += 1.0/(k*(k+1.0)); + a4 += 1.0/(k3 * sk*sk); + a5 += 1.0/(k3 * ck*ck); + a6 += 1.0/k; + a7 += 1.0/k2; + a8 += alt/k; + a9 += alt/(2*k -1); + } + + return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ].join(','); +} + +var actual = ''; +for (var i = 1024; i <= 16384; i *= 2) { + actual += partial(i) + ';'; +} +assertEq(actual, "2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656;2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243;2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086;2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433;2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998;") diff --git a/js/src/trace-test/tests/sunspider/check-math-spectral-norm.js b/js/src/trace-test/tests/sunspider/check-math-spectral-norm.js new file mode 100644 index 000000000000..824863c6a5b4 --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-math-spectral-norm.js @@ -0,0 +1,53 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by Ian Osgood + +function A(i,j) { + return 1/((i+j)*(i+j+1)/2+i+1); +} + +function Au(u,v) { + for (var i=0; i.*\n|\n/g,"") +clen = dnaInput.length + +var dnaOutputString = ''; + +for(i in seqs) + dnaOutputString += seqs[i].source + " " + (dnaInput.match(seqs[i]) || []).length + "\n"; + // match returns null if no matches, so replace with empty + +for(k in subs) + dnaInput = dnaInput.replace(k, subs[k], "g") + // search string, replacement string, flags + +assertEq(dnaOutputString, "agggtaaa|tttaccct 0\n[cgt]gggtaaa|tttaccc[acg] 9\na[act]ggtaaa|tttacc[agt]t 27\nag[act]gtaaa|tttac[agt]ct 24\nagg[act]taaa|ttta[agt]cct 30\naggg[acg]aaa|ttt[cgt]ccct 9\nagggt[cgt]aa|tt[acg]accct 12\nagggta[cgt]a|t[acg]taccct 9\nagggtaa[cgt]|[acg]ttaccct 15\n") diff --git a/js/src/trace-test/tests/sunspider/check-string-fasta.js b/js/src/trace-test/tests/sunspider/check-string-fasta.js new file mode 100644 index 000000000000..ed5ecef9c18e --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-string-fasta.js @@ -0,0 +1,90 @@ +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org +// +// Contributed by Ian Osgood + +var last = 42, A = 3877, C = 29573, M = 139968; + +function rand(max) { + last = (last * A + C) % M; + return max * last / M; +} + +var ALU = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +var IUB = { + a:0.27, c:0.12, g:0.12, t:0.27, + B:0.02, D:0.02, H:0.02, K:0.02, + M:0.02, N:0.02, R:0.02, S:0.02, + V:0.02, W:0.02, Y:0.02 +} + +var HomoSap = { + a: 0.3029549426680, + c: 0.1979883004921, + g: 0.1975473066391, + t: 0.3015094502008 +} + +function makeCumulative(table) { + var last = null; + for (var c in table) { + if (last) table[c] += table[last]; + last = c; + } +} + +function fastaRepeat(n, seq) { + var seqi = 0, lenOut = 60; + while (n>0) { + if (n0) { + if (n= 0x7f) { + validates = false; + break; + } + } + + if (!validates) + continue; + + var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase(); + var popularity = tagInfo[i].popularity; + var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)'; + output += ' ' + tag + ' \n'; + } + + output += ''; + output.replace(" ", " "); + + return output; +} + +var tagcloud = makeTagCloud(tagInfo); +tagInfo = null; +assertEq(tagcloud.length, 315260) diff --git a/js/src/trace-test/tests/sunspider/check-string-unpack-code.js b/js/src/trace-test/tests/sunspider/check-string-unpack-code.js new file mode 100644 index 000000000000..a7013ec76dd8 --- /dev/null +++ b/js/src/trace-test/tests/sunspider/check-string-unpack-code.js @@ -0,0 +1,73 @@ +// This test case unpacks the compressed code for the MochiKit, +// jQuery, Dojo and Prototype JavaScript libraries. + +/*** + MochiKit.MochiKit 1.3.1 : PACKED VERSION + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + See for documentation, downloads, license, etc. + + (c) 2005 Bob Ippolito. All rights Reserved. +***/ + +for (var i = 0; i < 2; i++) { + +var decompressedMochiKit = function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(H(1q)!="L"){1q.2X("B.J")}if(H(B)=="L"){B={}}if(H(B.J)=="L"){B.J={}}B.J.1Y="1.3.1";B.J.1r="B.J";B.J.2l=G(7V,vR){if(7V===O){7V={}}R(u i=1;i=0;i--){aw.e9(o[i])}}N{X.1c(o)}}F X},1R:G(7U,1i,av){if(!av){av=0}if(1i){u l=1i.K;if(H(l)!="2y"){if(H(B.15)!="L"){1i=B.15.2G(1i);l=1i.K}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(!7U){7U=[]}R(u i=av;i>b},vG:G(a,b){F a>>>b},eq:G(a,b){F a==b},ne:G(a,b){F a!=b},gt:G(a,b){F a>b},ge:G(a,b){F a>=b},lt:G(a,b){F al){7T=l}}69=[];R(i=0;i<7T;i++){u fa=[];R(u j=1;j0){ap=m.2o(me.am,ap)}u 4o=me.f7;if(!4o){4o=D}F me.f5.1w(4o,ap)};7Q.f7=f6;7Q.f5=ao;7Q.am=5f;F 7Q},lF:G(7P){u mp=B.J.1O;R(u k in 7P){u f4=7P[k];if(H(f4)=="G"){7P[k]=mp(f4,7P)}}},5u:G(mo,mn,ml,mk){B.J.ae.5M(mo,mn,ml,mk)},mj:{"5L":1h,"1n":1h,"2y":1h},2f:G(a,b){if(a==b){F 0}u f3=(H(a)=="L"||a===O);u f2=(H(b)=="L"||b===O);if(f3&&f2){F 0}N{if(f3){F-1}N{if(f2){F 1}}}u m=B.J;u f1=m.mj;if(!(H(a)in f1&&H(b)in f1)){1f{F m.ae.3C(a,b)}1e(e){if(e!=m.4d){14 e}}}if(ab){F 1}}u f0=m.U;14 Y 3p(f0(a)+" 3W "+f0(b)+" 9v 2E be vv")},eM:G(a,b){F B.J.2f(a.9P(),b.9P())},eL:G(a,b){u mi=B.J.2f;u 7O=a.K;u al=0;if(7O>b.K){al=1;7O=b.K}N{if(7O0))){u kv=B.S.d5(3s);3s=kv[0];68=kv[1]}N{if(M.K==1){u o=3s;3s=[];68=[];R(u k in o){u v=o[k];if(H(v)!="G"){3s.1c(k);68.1c(v)}}}}u W=[];u lT=28.2a(3s.K,68.K);u eT=B.J.af;R(u i=0;i=2J){14 I.25}5c+=3a;F W}}},4c:G(aa,p,q){u m=B.J;u I=B.15;u lb=m.2r(I.1Q,m.1R(O,M,1));u 2r=m.2r;u 1a=I.1a;F{U:G(){F"4c(...)"},1l:m.24("U"),1a:G(){F aa.1w(D,2r(1a,lb))}}},ep:G(aa,1V,I){1V=B.15.1Q(1V);u m=B.J;F{U:G(){F"ep(...)"},1l:m.24("U"),1a:G(){F aa.1w(I,1V.1a())}}},55:G(p,q){u I=B.15;u m=B.J;if(M.K==1){F I.1Q(M[0])}u 64=m.2r(I.1Q,M);F{U:G(){F"55(...)"},1l:m.24("U"),1a:G(){1M(64.K>1){1f{F 64[0].1a()}1e(e){if(e!=I.25){14 e}64.2P()}}if(64.K==1){u a9=64.2P();D.1a=m.1O("1a",a9);F D.1a()}14 I.25}}},9Z:G(3b,1V){u I=B.15;1V=I.1Q(1V);F{U:G(){F"9Z(...)"},1l:B.J.24("U"),1a:G(){u W=1V.1a();if(!3b(W)){D.1a=G(){14 I.25};D.1a()}F W}}},eo:G(3b,1V){1V=B.15.1Q(1V);u m=B.J;u 1O=m.1O;F{"U":G(){F"eo(...)"},"1l":m.24("U"),"1a":G(){1M(1h){u W=1V.1a();if(!3b(W)){2K}}D.1a=1O("1a",1V);F W}}},a7:G(63,2u,la){2u.62[63]=-1;u m=B.J;u l9=m.eI;F{U:G(){F"en("+63+", ...)"},1l:m.24("U"),1a:G(){u W;u i=2u.62[63];if(i==2u.29){W=la.1a();2u.a8.1c(W);2u.29+=1;2u.62[63]+=1}N{W=2u.a8[i-2u.2a];2u.62[63]+=1;if(i==2u.2a&&l9(2u.62)!=2u.2a){2u.2a+=1;2u.a8.2P()}}F W}}},en:G(a6,n){u W=[];u 2u={"62":[],"a8":[],"29":-1,"2a":-1};if(M.K==1){n=2}u I=B.15;a6=I.1Q(a6);u a7=I.a7;R(u i=0;i0&&4k>=2J)||(3a<0&&4k<=2J)){14 B.15.25}u W=4k;4k+=3a;F W},U:G(){F"7I("+[4k,2J,3a].2b(", ")+")"},1l:B.J.24("U")}},l0:G(a5,l7){u x=l7||0;u I=B.15;a5=I.1Q(a5);1f{1M(1h){x+=a5.1a()}}1e(e){if(e!=I.25){14 e}}F x},em:G(a4){u I=B.15;a4=I.1Q(a4);1f{1M(1h){a4.1a()}}1e(e){if(e!=I.25){14 e}}},9a:G(7J,1A,I){u m=B.J;if(M.K>2){1A=m.1O(1A,I)}if(m.3A(7J)){1f{R(u i=0;i<7J.K;i++){1A(7J[i])}}1e(e){if(e!=B.15.25){14 e}}}N{I=B.15;I.em(I.4c(1A,7J))}},kZ:G(l6,1A){u I=B.15;1f{I.a0(1A,l6).1a();F 1m}1e(e){if(e!=I.25){14 e}F 1h}},kY:G(l5,4j){u W=B.15.2G(l5);if(M.K==1){4j=B.J.2f}W.iz(4j);F W},kX:G(l4){u W=B.15.2G(l4);W.vg();F W},kW:G(l3,1A){u I=B.15;1f{I.a1(1A,l3).1a();F 1h}1e(e){if(e!=I.25){14 e}F 1m}},kV:G(1g,5b){if(B.J.3A(5b)){R(u i=0;i<5b.K;i++){1g.1c(5b[i])}}N{u I=B.15;5b=I.1Q(5b);1f{1M(1h){1g.1c(5b.1a())}}1e(e){if(e!=I.25){14 e}}}F 1g},ek:G(a3,eH){u m=B.J;u I=B.15;if(M.K<2){eH=m.4i.eE}a3=I.1Q(a3);u pk=L;u k=L;u v;G eF(){v=a3.1a();k=eH(v)}G l2(){u 7j=v;v=L;F 7j}u eG=1h;F{U:G(){F"ek(...)"},1a:G(){1M(k==pk){eF();if(eG){eG=1m;2K}}pk=k;F[k,{1a:G(){if(v==L){eF()}if(k!=pk){14 I.25}F l2()}}]}}},kU:G(a2,eD){u m=B.J;u I=B.15;if(M.K<2){eD=m.4i.eE}a2=I.1Q(a2);u ey=[];u eA=1h;u ez;1M(1h){1f{u eB=a2.1a();u 2h=eD(eB)}1e(e){if(e==I.25){2K}14 e}if(eA||2h!=ez){u eC=[];ey.1c([2h,eC])}eC.1c(eB);eA=1m;ez=2h}F ey},9X:G(ex){u i=0;F{U:G(){F"9X(...)"},1l:B.J.24("U"),1a:G(){if(i>=ex.K){14 B.15.25}F ex[i++]}}},eh:G(ew){F(ew&&H(ew.ei)=="G")},9V:G(l1){F{U:G(){F"9V(...)"},1l:B.J.24("U"),1a:G(){u W=l1.ei();if(W===O||W===L){14 B.15.25}F W}}}});B.15.1W=["9Y","9X","eh","9V",];B.15.1z=["25","9W","1Q","eu","et","7b","1a","es","a1","a0","er","4c","ep","55","9Z","eo","en","2G","7H","7I","l0","em","9a","kZ","kY","kX","kW","kV","ek","kU"];B.15.2d=G(){u m=B.J;D.25=Y m.5a("25");D.9Y=Y m.4a();D.9W("ej",m.3A,D.9X);D.9W("ei",D.eh,D.9V);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.15.2d();if(!B.3d){7H=B.15.7H}B.J.2Y(D,B.15);if(H(1q)!="L"){1q.2X("B.1H");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1H 3F on B.J!"}if(H(B.1H)=="L"){B.1H={}}B.1H.1r="B.1H";B.1H.1Y="1.3.1";B.1H.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1H.1l=G(){F D.1K()};B.1H.1z=["5C","49","7A","kR","2L","5Z","kG","ch","kE","kC"];B.1H.1W=["ef","e8","e7"];B.1H.49=G(1P,kT,3z){D.1P=1P;D.3N=kT;D.3z=3z;D.vf=Y 3Q()};B.1H.49.1U={U:G(){u m=B.J;F"49("+m.2r(m.U,[D.1P,D.3N,D.3z]).2b(", ")+")"},1l:B.J.24("U")};B.J.2l(B.1H,{ef:G(7F){u I=B.1H;if(H(7F)=="1n"){7F=I.5C[7F]}F G(1t){u 7G=1t.3N;if(H(7G)=="1n"){7G=I.5C[7G]}F 7G>=7F}},e8:G(){u kS=B.1H.49;R(u i=0;i=0&&D.4h.K>D.ec){D.4h.2P()}},c8:G(9U){u ea=0;if(!(H(9U)=="L"||9U===O)){ea=28.29(0,D.4h.K-9U)}F D.4h.9T(ea)},kJ:G(7B){if(H(7B)=="L"||7B===O){7B=30}u 9S=D.c8(7B);if(9S.K){u 1g=2r(G(m){F"\\n ["+m.1P+"] "+m.3N+": "+m.3z.2b(" ")},9S);1g.e9("va "+9S.K+" v9:");F 1g.2b("")}F""},v8:G(kI){if(H(B.1I)=="L"){cq(D.kJ())}N{B.1I.bY(kI||1m)}}};B.1H.2d=G(){D.5C={8M:40,8L:50,8K:30,8J:20,8I:10};u m=B.J;m.5u("49",D.e8,D.e7);u 61=m.2z;u e6=D.7A;u 60=e6.1U.kH;m.2l(D.7A.1U,{kF:61(60,"8I"),5Z:61(60,"8J"),dE:61(60,"8M"),kD:61(60,"8L"),kB:61(60,"8K")});u I=D;u 5Y=G(1b){F G(){I.2L[1b].1w(I.2L,M)}};D.5Z=5Y("5Z");D.kG=5Y("dE");D.ch=5Y("kF");D.kE=5Y("kD");D.kC=5Y("kB");D.2L=Y e6();D.2L.e5=1h;D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};if(H(5X)=="L"&&H(2v)!="L"&&2v.kA&&H(kz)!="L"){5X=G(){5X.3G=M;u ev=2v.kA("v7");ev.v6("5X",1m,1h);kz(ev)}}B.1H.2d();B.J.2Y(D,B.1H);if(H(1q)!="L"){1q.2X("B.1D")}if(H(B)=="L"){B={}}if(H(B.1D)=="L"){B.1D={}}B.1D.1r="B.1D";B.1D.1Y="1.3.1";B.1D.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1D.1l=G(){F D.1K()};B.1D.ks=G(1y){1y=1y+"";if(H(1y)!="1n"||1y.K===0){F O}u 7z=1y.2R("-");if(7z.K===0){F O}F Y 3Q(7z[0],7z[1]-1,7z[2])};B.1D.ky=/(\\d{4,})(?:-(\\d{1,2})(?:-(\\d{1,2})(?:[T ](\\d{1,2}):(\\d{1,2})(?::(\\d{1,2})(?:\\.(\\d+))?)?(?:(Z)|([+-])(\\d{1,2})(?::(\\d{1,2}))?)?)?)?)?/;B.1D.kr=G(1y){1y=1y+"";if(H(1y)!="1n"||1y.K===0){F O}u X=1y.3C(B.1D.ky);if(H(X)=="L"||X===O){F O}u 5W,7y,7x,9R,2a,9Q,7w;5W=3w(X[1],10);if(H(X[2])=="L"||X[2]===""){F Y 3Q(5W)}7y=3w(X[2],10)-1;7x=3w(X[3],10);if(H(X[4])=="L"||X[4]===""){F Y 3Q(5W,7y,7x)}9R=3w(X[4],10);2a=3w(X[5],10);9Q=(H(X[6])!="L"&&X[6]!=="")?3w(X[6],10):0;if(H(X[7])!="L"&&X[7]!==""){7w=28.ha(c5*4M("0."+X[7]))}N{7w=0}if((H(X[8])=="L"||X[8]==="")&&(H(X[9])=="L"||X[9]==="")){F Y 3Q(5W,7y,7x,9R,2a,9Q,7w)}u 58;if(H(X[9])!="L"&&X[9]!==""){58=3w(X[10],10)*v5;if(H(X[11])!="L"&&X[11]!==""){58+=3w(X[11],10)*kw}if(X[9]=="-"){58=-58}}N{58=0}F Y 3Q(3Q.v4(5W,7y,7x,9R,2a,9Q,7w)-58)};B.1D.dY=G(2g,kx){if(H(2g)=="L"||2g===O){F O}u hh=2g.v3();u mm=2g.v2();u ss=2g.v1();u 1g=[((kx&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];F 1g.2b(":")};B.1D.kq=G(2g,7v){if(H(2g)=="L"||2g===O){F O}u ku=7v?"T":" ";u kt=7v?"Z":"";if(7v){2g=Y 3Q(2g.9P()+(2g.v0()*kw))}F B.1D.dX(2g)+ku+B.1D.dY(2g,7v)+kt};B.1D.dX=G(2g){if(H(2g)=="L"||2g===O){F O}u e4=B.1D.e3;F[2g.dZ(),e4(2g.e1()+1),e4(2g.e0())].2b("-")};B.1D.kp=G(d){d=d+"";if(H(d)!="1n"||d.K===0){F O}u a=d.2R("/");F Y 3Q(a[2],a[0]-1,a[1])};B.1D.e3=G(n){F(n>9)?n:"0"+n};B.1D.ko=G(d){if(H(d)=="L"||d===O){F O}u e2=B.1D.e3;F[e2(d.e1()+1),e2(d.e0()),d.dZ()].2b("/")};B.1D.kn=G(d){if(H(d)=="L"||d===O){F O}F[d.e1()+1,d.e0(),d.dZ()].2b("/")};B.1D.1z=["ks","kr","dY","kq","dX","kp","ko","kn"];B.1D.1W=[];B.1D.2k={":3e":B.1D.1z,":1p":B.1D.1z};B.1D.2d=G(){u 2w=D.1r+".";R(u k in D){u o=D[k];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+k}1e(e){}}}};B.1D.2d();if(H(B.J)!="L"){B.J.2Y(D,B.1D)}N{(G(km,dW){if((H(1x)=="L"&&H(1q)=="L")||(H(B.3d)=="5L"&&B.3d)){u 1p=dW.2k[":1p"];R(u i=0;i<1p.K;i++){km[1p[i]]=dW[1p[i]]}}})(D,B.1D)}if(H(1q)!="L"){1q.2X("B.1s")}if(H(B)=="L"){B={}}if(H(B.1s)=="L"){B.1s={}}B.1s.1r="B.1s";B.1s.1Y="1.3.1";B.1s.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1s.1l=G(){F D.1K()};B.1s.ke=G(kl,kk,kj,ki,kh,dV,kg,9N,kf){F G(1P){1P=4M(1P);if(H(1P)=="L"||1P===O||k8(1P)){F kl}u 9L=kk;u 9K=kj;if(1P<0){1P=-1P}N{9L=9L.23(/-/,"")}u me=M.2U;u 9M=B.1s.dJ(ki);if(kh){1P=1P*3k;9K=9M.9y+9K}1P=B.1s.dK(1P,dV);u 9O=1P.2R(/\\./);u 3r=9O[0];u 3P=(9O.K==1)?"":9O[1];u X="";1M(3r.K9N){u i=3r.K-9N;X=9M.9A+3r.2W(i,3r.K)+X;3r=3r.2W(0,i)}}X=3r+X;if(dV>0){1M(3P.K=0)){D.9u()}},jR:G(X){D.9x(X);D.jX()},9x:G(X){D.2H=((X 2C 2x)?1:0);D.53[D.2H]=X;D.9u()},dD:G(){if(D.2H!=-1){if(!D.7l){14 Y B.1k.dj(D)}D.7l=1m;F}},3o:G(X){D.dD();if(X 2C B.1k.2t){14 Y 2x("2t jW 9v aB be 7r if jV jU jT jS of a 3o")}D.9x(X)},52:G(X){D.dD();u I=B.1k;if(X 2C I.2t){14 Y 2x("2t jW 9v aB be 7r if jV jU jT jS of a 3o")}if(!(X 2C 2x)){X=Y I.9p(X)}D.9x(X)},jP:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(fn,fn)},5Q:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(fn,O)},jA:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(O,fn)},9w:G(cb,eb){if(D.7r){14 Y 2x("uQ uP 9v 2E be re-uO")}D.55.1c([cb,eb]);if(D.2H>=0){D.9u()}F D},9u:G(){u dC=D.55;u 56=D.2H;u X=D.53[56];u I=D;u cb=O;1M(dC.K>0&&D.54===0){u 2n=dC.2P();u f=2n[56];if(f===O){2V}1f{X=f(X);56=((X 2C 2x)?1:0);if(X 2C B.1k.2t){cb=G(X){I.jR(X)};D.jQ()}}1e(3O){56=1;if(!(3O 2C 2x)){3O=Y B.1k.9p(3O)}X=3O}}D.2H=56;D.53[56]=X;if(cb&&D.54){X.jP(cb);X.7r=1h}}};B.J.2l(B.1k,{dk:G(){F dB("("+M[0].jN+")")},dp:G(uN){u d=Y B.1k.2t();d.3o.1w(d,M);F d},9q:G(uM){u d=Y B.1k.2t();d.52.1w(d,M);F d},do:G(){u I=M.2U;if(!I.7q){u dy=[G(){F Y 7q()},G(){F Y dA("jO.dz")},G(){F Y dA("uL.dz")},G(){F Y dA("jO.dz.4.0")},G(){14 Y B.1k.dh("uK uJ 2E uI 7q")}];R(u i=0;i1){u m=B.J;u qs=m.dw.1w(O,m.1R(O,M,1));if(qs){5F+="?"+qs}}2s.cp("uB",5F,1h);F I.dl(2s)},jv:G(5F){u I=B.1k;u d=I.dn.1w(I,M);d=d.5Q(I.dk);F d},dm:G(jJ,dv){u d=Y B.1k.2t();u m=B.J;if(H(dv)!="L"){d.5Q(G(){F dv})}u jI=uA(m.1O("3o",d),28.8B(jJ*c5));d.7m=G(){1f{uz(jI)}1e(e){}};F d},ju:G(jH,1A){u m=B.J;u jG=m.2z.1w(m,m.1R(O,M,1));F B.1k.dm(jH).5Q(G(X){F jG()})}});B.1k.5O=G(){D.5S=[];D.4e=1m;D.id=D.7n()};B.1k.5O.1U={bX:B.1k.5O,uy:G(){d=Y B.1k.2t();if(D.4e){D.5S.1c(d)}N{D.4e=1h;d.3o(D)}F d},jF:G(){if(!D.4e){14 3p("ux to jF an jE 5O")}D.4e=1m;if(D.5S.K>0){D.4e=1h;D.5S.2P().3o(D)}},7n:B.J.4f(),U:G(){u 9t;if(D.4e){9t="4e, "+D.5S.K+" 5S"}N{9t="jE"}F"5O("+D.id+", "+9t+")"},1l:B.J.24("U")};B.1k.7i=G(2G,du,jC,jB,jD){D.2G=2G;D.9r=Y 7o(D.2G.K);D.55=[];D.id=D.7n();D.2H=-1;D.54=0;D.53=[O,O];D.7m=jD;D.7l=1m;if(D.2G.K===0&&!du){D.3o(D.9r)}D.dr=0;D.jz=du;D.jy=jC;D.jx=jB;u 9s=0;B.J.2r(B.J.1O(G(d){d.5Q(B.J.1O(D.dt,D),9s,1h);d.jA(B.J.1O(D.dt,D),9s,1m);9s+=1},D),D.2G)};B.J.2l(B.1k.7i.1U,B.1k.2t.1U);B.J.2l(B.1k.7i.1U,{dt:G(ds,7k,5R){D.9r[ds]=[7k,5R];D.dr+=1;if(D.2H!==0){if(7k&&D.jz){D.3o([ds,5R])}N{if(!7k&&D.jy){D.52(5R)}N{if(D.dr==D.2G.K){D.3o(D.9r)}}}}if(!7k&&D.jx){5R=O}F 5R}});B.1k.jt=G(jw){u d=Y B.1k.7i(jw,1m,1h,1m);d.5Q(G(dq){u 7j=[];R(u i=0;i=0){u 9m=Q.1S[Q.j4];7d.1c(1b);7c.1c((9m.3m)?9m.3m:9m.7X);F O}7d.1c(1b);7c.1c("");F O}if(4Y=="cu"||4Y=="P"||4Y=="8d"||4Y=="6m"){F Q.5h}7d.1c(1b);7c.1c(Q.3m||"");F O}F Q.5h});F[7d,7c]},94:G(1N,1A){u I=B.S;u d3=I.1Z;u W;1f{I.1Z=1N;W=1A()}1e(e){I.1Z=d3;14 e}I.1Z=d3;F W},j3:G(1b,j2,3y,j1){B.S.9b.5M(1b,j2,3y,j1)},9k:G(1j,7a){u im=B.15;u I=B.S;u 1Q=im.1Q;u iY=im.7b;u 4c=im.4c;u iX=I.9b;u iZ=I.9k;u iW=B.J.4d;1M(1h){if(H(1j)=="L"||1j===O){F O}if(H(1j.3T)!="L"&&1j.3T>0){F 1j}if(H(1j)=="2y"||H(1j)=="5L"){1j=1j.1l()}if(H(1j)=="1n"){F I.1Z.4S(1j)}if(H(1j.j0)=="G"){1j=1j.j0(7a);2V}if(H(1j)=="G"){1j=1j(7a);2V}u 9l=O;1f{9l=1Q(1j)}1e(e){}if(9l){F 4c(iZ,9l,iY(7a))}1f{1j=iX.3C(1j,7a);2V}1e(e){if(e!=iW){14 e}}F I.1Z.4S(1j.1l())}F L},iV:G(1j,79,iU){u o={};o[79]=iU;1f{F B.S.4X(1j,o)}1e(e){}F O},iT:G(1j,79){u I=B.S;u d2=I.4U.99[79];1j=I.1E(1j);1f{if(d2){F 1j[d2]}F 1j.fm(79)}1e(e){}F O},4X:G(1j,5K){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j)}if(5K){u d0=B.J.8Z;if(I.4U.6X){R(u k in 5K){u v=5K[k];if(H(v)=="3n"&&H(Q[k])=="3n"){d0(Q[k],v)}N{if(k.2W(0,2)=="on"){if(H(v)=="1n"){v=Y cZ(v)}Q[k]=v}N{Q.4p(k,v)}}}}N{u iS=I.4U.99;R(k in 5K){v=5K[k];u d1=iS[k];if(k=="1T"&&H(v)=="1n"){Q.1T.3x=v}N{if(H(d1)=="1n"){Q[d1]=v}N{if(H(Q[k])=="3n"&&H(v)=="3n"){d0(Q[k],v)}N{if(k.2W(0,2)=="on"){if(H(v)=="1n"){v=Y cZ(v)}Q[k]=v}N{Q.4p(k,v)}}}}}}}F Q},9j:G(1j){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j)}u 78=[I.9k(B.J.1R(O,M,1),Q)];u iR=B.J.2o;1M(78.K){u n=78.2P();if(H(n)=="L"||n===O){}N{if(H(n.3T)=="2y"){Q.2c(n)}N{78=iR(n,78)}}}F Q},iQ:G(1j){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j);M[0]=Q}u cY;1M((cY=Q.6n)){Q.6S(cY)}if(M.K<2){F Q}N{F I.9j.1w(D,M)}},cX:G(1b,4b){u Q;u I=B.S;u m=B.J;if(H(4b)=="1n"||H(4b)=="2y"){u 3G=m.1R([1b,O],M,1);F M.2U.1w(D,3G)}if(H(1b)=="1n"){if(4b&&"1b"in 4b&&!I.4U.6X){1b=("<"+1b+" 1b=\\""+I.9c(4b.1b)+"\\">")}Q=I.1Z.2S(1b)}N{Q=1b}if(4b){I.4X(Q,4b)}if(M.K<=2){F Q}N{u 3G=m.1R([Q],M,2);F I.9j.1w(D,3G)}},cw:G(){u m=B.J;F m.2z.1w(D,m.1R([B.S.cX],M))},cs:G(5J,1d){u I=B.S;5J=I.1E(5J);u cW=5J.3t;if(1d){1d=I.1E(1d);cW.uj(1d,5J)}N{cW.6S(5J)}F 1d},1E:G(id){u I=B.S;if(M.K==1){F((H(id)=="1n")?I.1Z.hN(id):id)}N{F B.J.2r(I.1E,M)}},4q:G(iP,cV,cU){if(M.K==2){cU=cV}u I=B.S;u el=I.1E(iP);u 77=I.1Z;if(!el||el==77){F L}if(el.iO){F el.iO[cV]}if(H(77.5k)=="L"){F L}if(77.5k===O){F L}u 9i=77.5k.g4(el,O);if(H(9i)=="L"||9i===O){F L}F 9i.6q(cU)},aH:G(76,9g,4W){u I=B.S;if(H(76)=="L"||76===O){76="*"}if(H(4W)=="L"||4W===O){4W=I.1Z}4W=I.1E(4W);u 9h=(4W.fr(76)||I.1Z.1p);if(H(9g)=="L"||9g===O){F B.J.1R(O,9h)}u cR=[];R(u i=0;i<9h.K;i++){u cS=9h[i];u cT=cS.3M.2R(" ");R(u j=0;j/g,">")},iB:G(2q){F B.S.cG(2q).2b("")},cG:G(2q,1g){if(H(1g)=="L"||1g===O){1g=[]}u 70=[2q];u I=B.S;u cB=I.9c;u iA=I.4U;1M(70.K){2q=70.hP();if(H(2q)=="1n"){1g.1c(2q)}N{if(2q.3T==1){1g.1c("<"+2q.cD.8G());u 71=[];u cF=iA(2q);R(u i=0;i");70.1c("");u cC=2q.5h;R(i=cC.K-1;i>=0;i--){70.1c(cC[i])}}N{1g.1c("/>")}}N{if(2q.3T==3){1g.1c(cB(2q.iv))}}}}F 1g},97:G(ix,cA){u m=B.J;u iy=m.1R(O,M,1);B.15.9a(m.47(O,m.2r(B.S.1E,iy)),G(cA){cA.1T.3u=ix})},iw:G(1j,iu){u W=[];(G(1j){u cn=1j.5h;if(cn){R(u i=0;i0){u it=m.47;2T=G(1j){F it(2T.ir,1j.6Y)};2T.cx={};B.15.9a(6Z.6Y,G(a){2T.cx[a.1b]=a.3m});2T.ir=G(a){F(2T.cx[a.1b]!=a.3m)};2T.6X=1m;2T.99={"iq":"3M","ip":"ud","uc":"ub","R":"u9"}}N{2T=G(1j){F 1j.6Y};2T.6X=1h;2T.99={}}D.4U=2T;u 1C=D.cw;D.io=1C("ul");D.il=1C("ol");D.ik=1C("li");D.ij=1C("td");D.cm=1C("tr");D.ii=1C("u8");D.ih=1C("u7");D.ig=1C("u6");D.ie=1C("u5");D.ic=1C("th");D.cv=1C("ck");D.8d=1C("cj");D.A=1C("a");D.6m=1C("4u");D.ib=1C("u4");D.ia=1C("2e");D.i9=1C("tt");D.i8=1C("4O");D.i7=1C("h1");D.i6=1C("h2");D.i5=1C("h3");D.i4=1C("br");D.i3=1C("hr");D.i2=1C("u3");D.i1=1C("u2");D.cu=1C("u1");D.P=1C("p");D.ct=1C("u0");D.i0=1C("hJ");D.hZ=1C("tZ");D.hY=1C("tY");D.hX=1C("tX");D.hW=1C("tW");D.hV=1C("tV");D.hU=m.2z(D.97,"98");D.hT=m.2z(D.97,"8c");D.hS=D.cs;D.$=D.1E;D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)}});B.S.2d(((H(2O)=="L")?D:2O));if(!B.3d){95=B.S.95;94=B.S.94}B.J.2Y(D,B.S);if(H(1q)!="L"){1q.2X("B.1I");1q.2M("B.1H");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.1H",[]);1x.26("B.J",[])}1f{if(H(B.J)=="L"||H(B.1H)=="L"){14""}}1e(e){14"B.1I 3F on B.J 3W B.1H!"}if(H(B.1I)=="L"){B.1I={}}B.1I.1r="B.1I";B.1I.1Y="1.3.1";B.1I.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1I.1l=G(){F D.1K()};B.1I.bY=G(6W){u m=B.1I;6W=!(!6W);if(m.3l&&m.3l.8Q!=6W){m.3l.hA();m.3l=O}if(!m.3l||m.3l.8P){m.3l=Y m.1I(6W,B.1H.2L)}F m.3l};B.1I.1I=G(4R,6V){if(H(6V)=="L"||6V===O){6V=B.1H.2L}D.2L=6V;u tU=B.J.2l;u c3=B.J.8Z;u 1O=B.J.1O;u hM=B.J.4L;u 2m=2O;u 6U="tT";if(H(B.S)!="L"){2m=B.S.cr()}if(!4R){u 5F=2m.tS.tR.2R("?")[0].23(/[:\\/.><&]/g,"hR");u 1b=6U+"hR"+5F;u 5D=2m.cp("",1b,"tQ,tP,3V=hQ");if(!5D){cq("tO tN to cp tM 2O tL to hP-up tK.");F L}5D.2v.fl(""+"<5E><8Y>[B.1I]"+"<5s>");5D.2v.hG();5D.2v.8Y+=" "+2m.2v.8Y;2m=5D}u 1N=2m.2v;D.1N=1N;u 21=1N.hN(6U);u c4=!!21;if(21&&H(21.5B)!="L"){21.5B.2L=D.2L;21.5B.6K();F 21.5B}if(c4){u cl;1M((cl=21.6n)){21.6S(cl)}}N{21=1N.2S("4u");21.id=6U}21.5B=D;u 8T=1N.2S("ck");u 8S=1N.2S("ck");u 6O=1N.2S("2e");u 6N=1N.2S("2e");u 6M=1N.2S("2e");u 6L=1N.2S("2e");u 3L=1N.2S("4u");u 42=1N.2S("4u");u 8U=6U+"tz";D.8N=hM(D.8N);u 4T=[];u 6R=O;u cf=G(1t){u 6T=1t.3N;if(H(6T)=="2y"){6T=B.1H.5C[6T]}F 6T};u cd=G(1t){F 1t.3z.2b(" ")};u ca=1O(G(1t){u 8W=cf(1t);u 7X=cd(1t);u c=D.8N[8W];u p=1N.2S("cj");p.3M="B-49 B-5C-"+8W;p.1T.3x="ty: 2N; 4F-8X: -hL-4O-3y; 4F-8X: -o-4O-3y; 4F-8X: 4O-3y; 4F-8X: 4O-tx; hK-3y: 2K-hK; 3y-hJ: tw; 3U: "+c;p.2c(1N.4S(8W+": "+7X));42.2c(p);42.2c(1N.2S("br"));if(3L.ci>3L.hI){3L.4C=0}N{3L.4C=3L.hI}},D);u hD=G(1t){4T[4T.K]=1t;ca(1t)};u hF=G(){u cg,ce;1f{cg=Y 8V(8T.3m);ce=Y 8V(8S.3m)}1e(e){ch("2x in 47 tv: "+e.43);F O}F G(1t){F(cg.hH(cf(1t))&&ce.hH(cd(1t)))}};u cc=G(){1M(42.6n){42.6S(42.6n)}};u hB=G(){4T=[];cc()};u bZ=1O(G(){if(D.8P){F}D.8P=1h;if(B.1I.3l==D){B.1I.3l=O}D.2L.c9(8U);21.5B=O;if(4R){21.3t.6S(21)}N{D.2m.hG()}},D);u c7=G(){cc();R(u i=0;i<4T.K;i++){u 1t=4T[i];if(6R===O||6R(1t)){ca(1t)}}};D.6K=G(){6R=hF();c7();D.2L.c9(8U);D.2L.hE(8U,6R,hD)};u c0=1O(G(){4T=D.2L.c8();c7()},D);u c2=1O(G(6Q){6Q=6Q||2O.6D;2h=6Q.6w||6Q.8t;if(2h==13){D.6K()}},D);u 31="3u: 8c; z-c6: c5; 2I: 2N; 6f: 2N; 6P: tu; 5A: 3k%; he-3U: 4F; c1: "+D.8O;if(4R){31+="; 3V: ts; 3E-3D: fO 8a 8y"}N{31+="; 3V: 3k%;"}21.1T.3x=31;if(!c4){1N.5s.2c(21)}31={"3x":"5A: 33%; 3u: 8Q; c1: "+D.8O};c3(8T,{"3m":"8L|8M|8K|8J|8I","hC":c2,"1T":31});21.2c(8T);c3(8S,{"3m":".*","hC":c2,"1T":31});21.2c(8S);31="5A: 8%; 3u:8Q; c1: "+D.8O;6O.2c(1N.4S("tq"));6O.8R=1O("6K",D);6O.1T.3x=31;21.2c(6O);6N.2c(1N.4S("tp"));6N.8R=c0;6N.1T.3x=31;21.2c(6N);6M.2c(1N.4S("tn"));6M.8R=hB;6M.1T.3x=31;21.2c(6M);6L.2c(1N.4S("tm"));6L.8R=bZ;6L.1T.3x=31;21.2c(6L);3L.1T.3x="fS: tk; 5A: 3k%";42.1T.3x="5A: 3k%; 3V: "+(4R?"tj":"3k%");3L.2c(42);21.2c(3L);D.6K();c0();if(4R){D.2m=L}N{D.2m=2m}D.8Q=4R;D.hA=bZ;D.8P=1m;F D};B.1I.1I.1U={"8O":"ti tg,tf-te","8N":{"8M":"1v","8L":"gU","8K":"1F","8J":"8y","8I":"bx"}};B.1I.1W=["1I"];B.1I.1z=["bY"];B.1I.2d=G(){D.2k={":3e":D.1z,":1p":B.J.2o(D.1z,D.1W)};B.J.3f(D);B.1I.3l=O};B.1I.2d();B.J.2Y(D,B.1I);if(H(1q)!="L"){1q.2X("B.V");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.V 3F on B.J"}if(H(B.V)=="L"){B.V={}}B.V.1r="B.V";B.V.1Y="1.3.1";B.V.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.V.1l=G(){F D.1K()};B.V.V=G(1v,hz,1F,6J){if(H(6J)=="L"||6J===O){6J=1}D.1B={r:1v,g:hz,b:1F,a:6J}};B.V.V.1U={bX:B.V.V,tc:G(hy){u 1B=D.1B;u m=B.V;F m.V.3Y(1B.r,1B.g,1B.b,hy)},tb:G(1o){u 1G=D.41();1G.h=1o;u m=B.V;F m.V.4H(1G)},ta:G(hx){u 1G=D.41();1G.s=hx;u m=B.V;F m.V.4H(1G)},t9:G(hw){u 1G=D.41();1G.l=hw;u m=B.V;F m.V.4H(1G)},t8:G(hv){u 1G=D.41();1G.l=28.29(1G.l-hv,0);u m=B.V;F m.V.4H(1G)},t7:G(hu){u 1G=D.41();1G.l=28.2a(1G.l+hu,1);u m=B.V;F m.V.4H(1G)},fJ:G(ht,5z){if(H(5z)=="L"||5z===O){5z=0.5}u sf=1-5z;u s=D.1B;u d=ht.1B;u df=5z;F B.V.V.3Y((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df))},h4:G(hs){u a=D.6r();u b=hs.6r();F B.J.2f([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a])},hq:G(){F D.41().b>0.5},t6:G(){F(!D.hq())},t5:G(){u c=D.41();u 2Z=B.V.6F;u W=D.ho;if(!W){u 5y=(2Z(c.h,bF).6I(0)+","+2Z(c.s,3k).hp(4)+"%"+","+2Z(c.l,3k).hp(4)+"%");u a=c.a;if(a>=1){a=1;W="1G("+5y+")"}N{if(a<=0){a=0}W="t4("+5y+","+a+")"}D.ho=W}F W},hl:G(){u c=D.1B;u 2Z=B.V.6F;u W=D.hn;if(!W){u 5y=(2Z(c.r,3h).6I(0)+","+2Z(c.g,3h).6I(0)+","+2Z(c.b,3h).6I(0));if(c.a!=1){W="t3("+5y+","+c.a+")"}N{W="1B("+5y+")"}D.hn=W}F W},6r:G(){F B.J.4L(D.1B)},t2:G(){u m=B.V;u c=D.1B;u 2Z=B.V.6F;u W=D.hm;if(!W){W=("#"+m.6E(2Z(c.r,3h))+m.6E(2Z(c.g,3h))+m.6E(2Z(c.b,3h)));D.hm=W}F W},t1:G(){u 2Q=D.2Q;u c=D.1B;if(H(2Q)=="L"||2Q===O){2Q=B.V.bA(D.1B);D.2Q=2Q}F B.J.4L(2Q)},41:G(){u 1G=D.1G;u c=D.1B;if(H(1G)=="L"||1G===O){1G=B.V.bC(D.1B);D.1G=1G}F B.J.4L(1G)},1l:G(){F D.hl()},U:G(){u c=D.1B;u hk=[c.r,c.g,c.b,c.a];F D.bX.1r+"("+hk.2b(", ")+")"}};B.J.2l(B.V.V,{3Y:G(1v,bW,1F,8H){u hj=B.V.V;if(M.K==1){u 1B=1v;1v=1B.r;bW=1B.g;1F=1B.b;if(H(1B.a)=="L"){8H=L}N{8H=1B.a}}F Y hj(1v,bW,1F,8H)},4H:G(1o,t0,sZ,sY){u m=B.V;F m.V.3Y(m.bB.1w(m,M))},sX:G(1o,sW,sV,sU){u m=B.V;F m.V.3Y(m.bz.1w(m,M))},hi:G(1b){u 8F=B.V.V;if(1b.3Z(0)=="\\""){1b=1b.3H(1,1b.K-2)}u bV=8F.by[1b.8G()];if(H(bV)=="1n"){F 8F.bT(bV)}N{if(1b=="aP"){F 8F.sT()}}F O},8f:G(4Q){u I=B.V.V;u bU=4Q.3H(0,3);if(bU=="1B"){F I.h9(4Q)}N{if(bU=="1G"){F I.h8(4Q)}N{if(4Q.3Z(0)=="#"){F I.bT(4Q)}}}F I.hi(4Q)},bT:G(4P){if(4P.3Z(0)=="#"){4P=4P.2W(1)}u 8E=[];u i,5x;if(4P.K==3){R(i=0;i<3;i++){5x=4P.3H(i,1);8E.1c(3w(5x+5x,16)/3h)}}N{R(i=0;i<6;i+=2){5x=4P.3H(i,2);8E.1c(3w(5x,16)/3h)}}u bS=B.V.V;F bS.3Y.1w(bS,8E)},bG:G(4O,hf,hg,4N){if(4N.2A(4O)===0){4N=4N.2W(4N.2A("(",3)+1,4N.K-1)}u bR=4N.2R(/\\s*,\\s*/);u bP=[];R(u i=0;i0){F 8D}}F O},ba:G(Q){u 2F=B.V.V;F 2F.bN(Q,"aZ","he-3U")||2F.sN()},sM:G(Q){u 2F=B.V.V;F 2F.bN(Q,"3U","3U")||2F.sL()},sK:G(){F B.J.4L(B.V.V.by)}});B.J.2l(B.V,{6F:G(v,8C){v*=8C;if(v<0){F 0}N{if(v>8C){F 8C}N{F v}}},hc:G(n1,n2,1o){if(1o>6){1o-=6}N{if(1o<0){1o+=6}}u 2i;if(1o<1){2i=n1+(n2-n1)*1o}N{if(1o<3){2i=n2}N{if(1o<4){2i=n1+(n2-n1)*(4-1o)}N{2i=n1}}}F 2i},bz:G(1o,5w,3i,bM){if(M.K==1){u 2Q=1o;1o=2Q.h;5w=2Q.s;3i=2Q.v;bM=2Q.a}u 1v;u 3K;u 1F;if(5w===0){1v=0;3K=0;1F=0}N{u i=28.8B(1o*6);u f=(1o*6)-i;u p=3i*(1-5w);u q=3i*(1-(5w*f));u t=3i*(1-(5w*(1-f)));hd(i){3j 1:1v=q;3K=3i;1F=p;2K;3j 2:1v=p;3K=3i;1F=t;2K;3j 3:1v=p;3K=q;1F=3i;2K;3j 4:1v=t;3K=p;1F=3i;2K;3j 5:1v=3i;3K=p;1F=q;2K;3j 6:3j 0:1v=3i;3K=t;1F=p;2K}}F{r:1v,g:3K,b:1F,a:bM}},bB:G(1o,5v,3v,bL){if(M.K==1){u 1G=1o;1o=1G.h;5v=1G.s;3v=1G.l;bL=1G.a}u 1v;u 8A;u 1F;if(5v===0){1v=3v;8A=3v;1F=3v}N{u m2;if(3v<=0.5){m2=3v*(1+5v)}N{m2=3v+5v-(3v*5v)}u m1=(2*3v)-m2;u f=B.V.hc;u h6=1o*6;1v=f(m1,m2,h6+2);8A=f(m1,m2,h6);1F=f(m1,m2,h6-2)}F{r:1v,g:8A,b:1F,a:bL}},bA:G(1v,4K,1F,bK){if(M.K==1){u 1B=1v;1v=1B.r;4K=1B.g;1F=1B.b;bK=1B.a}u 29=28.29(28.29(1v,4K),1F);u 2a=28.2a(28.2a(1v,4K),1F);u 1o;u 8z;u hb=29;if(2a==29){1o=0;8z=0}N{u 6H=(29-2a);8z=6H/29;if(1v==29){1o=(4K-1F)/6H}N{if(4K==29){1o=2+((1F-1v)/6H)}N{1o=4+((1v-4K)/6H)}}1o/=6;if(1o<0){1o+=1}if(1o>1){1o-=1}}F{h:1o,s:8z,v:hb,a:bK}},bC:G(1v,4J,1F,bI){if(M.K==1){u 1B=1v;1v=1B.r;4J=1B.g;1F=1B.b;bI=1B.a}u 29=28.29(1v,28.29(4J,1F));u 2a=28.2a(1v,28.2a(4J,1F));u 1o;u 6G;u bJ=(29+2a)/2;u 4I=29-2a;if(4I===0){1o=0;6G=0}N{if(bJ<=0.5){6G=4I/(29+2a)}N{6G=4I/(2-29-2a)}if(1v==29){1o=(4J-1F)/4I}N{if(4J==29){1o=2+((1F-1v)/4I)}N{1o=4+((1v-4J)/4I)}}1o/=6;if(1o<0){1o+=1}if(1o>1){1o-=1}}F{h:1o,s:6G,l:bJ,a:bI}},6E:G(1P){1P=28.ha(1P);u bH=1P.1l(16);if(1P<16){F"0"+bH}F bH},2d:G(){u m=B.J;D.V.h9=m.1O(D.V.bG,D.V,"1B","3Y",[1/3h,1/3h,1/3h,1]);D.V.h8=m.1O(D.V.bG,D.V,"1G","4H",[1/bF,0.bE,0.bE,1]);u 4G=1/3;u bD={8y:[0,0,0],1F:[0,0,1],gY:[0.6,0.4,0.2],gX:[0,1,1],sJ:[4G,4G,4G],gR:[0.5,0.5,0.5],bx:[0,1,0],sI:[2*4G,2*4G,2*4G],gN:[1,0,1],gL:[1,0.5,0],gK:[0.5,0,0.5],1v:[1,0,0],aP:[0,0,0,0],4F:[1,1,1],gI:[1,1,0]};u h7=G(1b,r,g,b,a){u W=D.3Y(r,g,b,a);D[1b]=G(){F W};F W};R(u k in bD){u 1b=k+"V";u h5=m.2o([h7,D.V,1b],bD[k]);D.V[1b]=m.1O.1w(O,h5)}u h0=G(){R(u i=0;i1){u 1d=B.S.1E(M[0]);u 2D=M[1];u 1i=M[2];u 1A=M[3];R(u i=5o.K-1;i>=0;i--){u o=5o[i];if(o[0]===1d&&o[1]===2D&&o[4]===1i&&o[5]===1A){I.6t(o);5o.4y(i,1);F 1h}}}N{u 5n=m.bi(5o,bh);if(5n>=0){I.6t(bh);5o.4y(5n,1);F 1h}}F 1m},8i:G(1d,2D){1d=B.S.1E(1d);u m=B.J;u 8l=m.bg(m.1R(O,M,1));u I=B.1u;u bd=I.6t;u 4z=I.4x;if(8l.K===0){R(u i=4z.K-1;i>=0;i--){u 4A=4z[i];if(4A[0]===1d){bd(4A);4z.4y(i,1)}}}N{u bf={};R(u i=0;i<8l.K;i++){bf[8l[i]]=1h}R(u i=4z.K-1;i>=0;i--){u 4A=4z[i];if(4A[0]===1d&&4A[1]in bf){bd(4A);4z.4y(i,1)}}}},8h:G(1d,2D){u bc=B.1u.4x;1d=B.S.1E(1d);u 3G=B.J.1R(O,M,2);u 5m=[];R(u i=0;i1){u e=Y 2x("mZ bb mY in mX \'2D\', mW bb mV");e.bb=5m;14 e}}}});B.1u.1W=[];B.1u.1z=["6s","8j","8h","8i"];B.1u.2d=G(2m){u m=B.J;D.1Z=2v;D.3X=2m;1f{D.6s(2O,"g8",D.g7)}1e(e){}D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.1u.2d(D);if(!B.3d){6s=B.1u.6s;8j=B.1u.8j;8i=B.1u.8i;8h=B.1u.8h}B.J.2Y(D,B.1u);if(H(1q)!="L"){1q.2X("B.1X");1q.2M("B.J");1q.2M("B.S");1q.2M("B.V")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.S",[]);1x.26("B.V",[])}1f{if(H(B.J)=="L"||H(B.S)=="L"||H(B.V)=="L"){14""}}1e(e){14"B.1X 3F on B.J, B.S 3W B.V!"}if(H(B.1X)=="L"){B.1X={}}B.1X.1r="B.1X";B.1X.1Y="1.3.1";B.1X.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1X.1l=G(){F D.1K()};B.1X.aI=G(e,g6){e=B.S.1E(e);D.fN(g6);if(D.1S.fL){e=D.g5(e)}u 4w=D.1S.3U;u C=B.V.V;if(D.1S.3U=="aW"){4w=C.ba(e)}N{if(!(4w 2C C)){4w=C.8f(4w)}}D.82=(4w.6r().a<=0);u 5l=D.1S.aV;if(D.1S.aV=="fM"){5l=C.ba(e.8g)}N{if(!(5l 2C C)){5l=C.8f(5l)}}D.g3(e,4w,5l)};B.1X.aI.1U={g5:G(e){u mU=e.3t;u 1N=B.S.b9();if(H(1N.5k)=="L"||1N.5k===O){F e}u 4v=1N.5k.g4(e,O);if(H(4v)=="L"||4v===O){F e}u b8=B.S.6m({"1T":{3u:"8c",mT:4v.6q("6p-3D"),85:4v.6q("6p-3g"),mS:4v.6q("6p-6f"),86:4v.6q("6p-2I"),6p:"2N"}});b8.6o=e.6o;e.6o="";e.2c(b8);F e},g3:G(e,b7,8e){if(D.1S.3E){D.g2(e,8e)}if(D.fy()){D.fX(e,b7,8e)}if(D.fx()){D.fV(e,b7,8e)}},g2:G(el,g1){u b6="6l 8a "+D.aQ(g1);u g0="3E-2I: "+b6;u fZ="3E-3g: "+b6;u fY="1T=\'"+g0+";"+fZ+"\'";el.6o="<4u "+fY+">"+el.6o+""},fX:G(el,fW,b5){u b4=D.b1(b5);R(u i=0;i=0;i--){b2.2c(D.b0(fU,b3,i,"6f"))}el.1T.mP=0;el.2c(b2)},b1:G(fT){u 2q=B.S;F 2q.6m({1T:{aZ:fT.1l()}})},b0:G(aY,fQ,n,aX){u 6k=B.S.8d();u 2p=6k.1T;2p.aZ=aY.1l();2p.3u="8c";2p.3V="6l";2p.fS="fR";2p.mO="6l";u 8b=D.aQ(aY,fQ);if(D.1S.3E&&n===0){2p.mN="8a";2p.mM="6l";2p.84="2N";2p.83="2N";2p.mL="2N";2p.3V="2N";2p.fP=8b.1l()}N{if(8b){2p.fP=8b.1l();2p.mK="8a";2p.mJ="2N 6l"}}if(!D.1S.4r&&(n==(D.1S.89-1))){2p.3V="fO"}D.fI(6k,n,aX);D.fG(6k,n,aX);F 6k},fN:G(fK){D.1S={6g:"1p",3U:"aW",aV:"fM",5j:1h,3E:1m,4r:1m,fL:1m};B.J.2l(D.1S,fK);D.1S.89=(D.1S.4r?2:4)},aL:G(){u 88=D.1S.6g;if(D.6h(88,"1p","3D")){F""}u aU=(88.2A("tl")!=-1);u aT=(88.2A("tr")!=-1);if(aU&&aT){F""}if(aU){F"2I"}if(aT){F"3g"}F""},aK:G(){u 87=D.1S.6g;if(D.6h(87,"1p","6f")){F""}u aS=(87.2A("bl")!=-1);u aR=(87.2A("br")!=-1);if(aS&&aR){F""}if(aS){F"2I"}if(aR){F"3g"}F""},aQ:G(aN,aO){if(aN=="aP"){F aO}N{if(D.1S.3E){F D.1S.3E}N{if(D.1S.5j){F aO.fJ(aN)}}}F""},fI:G(el,n,fH){u 6j=D.fE(n)+"px";u aM=(fH=="3D"?D.aL():D.aK());u 4t=el.1T;if(aM=="2I"){4t.86=6j;4t.85="2N"}N{if(aM=="3g"){4t.85=6j;4t.86="2N"}N{4t.86=6j;4t.85=6j}}},fG:G(el,n,fF){u 6i=D.fz(n)+"px";u aJ=(fF=="3D"?D.aL():D.aK());u 4s=el.1T;if(aJ=="2I"){4s.84=6i;4s.83="2N"}N{if(aJ=="3g"){4s.83=6i;4s.84="2N"}N{4s.84=6i;4s.83=6i}}},fE:G(n){if(D.82){F 0}u o=D.1S;if(o.4r&&o.5j){u fD=[1,0];F fD[n]}N{if(o.4r){u fC=[2,1];F fC[n]}N{if(o.5j){u fB=[3,2,1,0];F fB[n]}N{u fA=[5,3,2,1];F fA[n]}}}},fz:G(n){u o=D.1S;u 5i;if(o.4r&&(o.5j||D.82)){F 1}N{if(o.4r){5i=[1,0]}N{if(o.5j){5i=[2,1,1,1]}N{if(o.3E){5i=[0,2,0,0]}N{if(D.82){5i=[5,3,2,1]}N{F 0}}}}}F 5i[n]},6h:G(1y){R(u i=1;i")}}})()}',62,1976,'||||||||||||||||||||||||||||||var|||||||MochiKit||this||return|function|typeof|self|Base|length|undefined|arguments|else|null||elem|for|DOM||repr|Color|rval|res|new||||||throw|Iter|||||next|name|push|src|catch|try|lst|true|obj|node|Async|toString|false|string|hue|all|dojo|NAME|Format|msg|Signal|red|apply|JSAN|str|EXPORT|func|rgb|_425|DateTime|getElement|blue|hsl|Logging|LoggingPane|type|__repr__|_event|while|doc|bind|num|iter|extend|options|style|prototype|seq|EXPORT_OK|Visual|VERSION|_document||_434||replace|forwardCall|StopIteration|use||Math|max|min|join|appendChild|__new__|button|compare|date|key|val|_329|EXPORT_TAGS|update|win|pair|concat|_596|dom|map|req|Deferred|sync|document|base|Error|number|partial|indexOf||instanceof|sig|not|cls|list|fired|left|stop|break|logger|require|0px|window|shift|hsv|split|createElement|_423|callee|continue|substring|provide|_exportSymbols|ccc||_464|||||||||step|pred|_51|__compat__|common|nameFunctions|right|255|_517|case|100|_loggingPane|value|object|callback|TypeError|_251|_246|_113|parentNode|display|_522|parseInt|cssText|wrap|info|isArrayLike|end|match|top|border|depends|args|substr|mouse|code|_519|_443|className|level|err|frac|Date|_135|_85|nodeType|color|height|and|_window|fromRGB|charAt||asHSL|_444|message||||filter||LogMessage|AdapterRegistry|_366|imap|NotFound|locked|counter|_262|_messages|operator|cmp|_165|_161|pairs|arr|_52|setAttribute|computedStyle|compact|_614|_610|div|_576|_572|_observers|splice|_565|_566|_555|scrollTop|page|modifier|white|_541|fromHSL|_539|_535|_528|clone|parseFloat|_505|pre|_499|_497|_427|createTextNode|_446|attributeArray|_388|_379|updateNodeAttributes|_341|_326||box|errback|results|paused|chain|_285||ofs||NamedError|_175|_147|_122|_83|_54|_17|childNodes|_619|blend|defaultView|_574|_569|idx|_562|must|_554|_specialKeys|body|Coordinates|registerComparator|_521|_516|hex|mid|_478|width|loggingPane|LogLevel|nwin|head|url|setElementClass|callStack|path|dest|_359|boolean|register|Dimensions|DeferredLock|_313|addCallback|_310|waiting|onreadystatechange|_290|LOCALE|year|printfire|_214|log|_213|_211|pos|_155|_153||typeMatcher|listMinMax|_114|_40|itr|typ|_19|_634|_625|bottom|corners|_hasString|_612|_608|_595|1px|DIV|firstChild|innerHTML|padding|getPropertyValue|asRGB|connect|_disconnect|_559|middle|which|clientY|scrollLeft|clientX|client|charCode|relatedTarget|event|toColorPart|clampColorComponent|_537|_534|toFixed|_468|buildAndApplyFilter|_442|_441|_440|_439|position|_463|_447|removeChild|_449|uid|_428|_426|compliant|attributes|_422|_409|_412|_400|_395|_390|_389|_377|_375|_363|attr|ctx|repeat|_340|_339|isNotEmpty|_335|_333|opera|DeferredList|ret|_309|silentlyCancelled|canceller|_nextId|Array|_293|XMLHttpRequest|chained|_281|tail|_252|_225|msec|day|month|iso|Logger|_208|listeners|_200|_198|_194|_196|reduce|range|_169|_162|truth|registerRepr|_121|_70|_58|_56|_47|_45|_41|_13|_1|script|text|uri|documentElement|_630|_629|isTransparent|borderRightWidth|borderLeftWidth|marginRight|marginLeft|_602|_599|numSlices|solid|_597|block|SPAN|_579|fromString|offsetParent|signal|disconnectAll|disconnect|_570|_563|_557|preventDefault|stopPropagation|clientTop|clientLeft|pageY|pageX|keyCode|meta|ctrl|alt|target|black|_532|_524|floor|_513|_512|_500|_495|toLowerCase|_487|DEBUG|INFO|WARNING|FATAL|ERROR|colorTable|logFont|closed|inline|onclick|_438|_437|_445|RegExp|_452|space|title|updatetree|||||withDocument|withWindow||setDisplayForElement|none|renames|forEach|domConverters|escapeHTML|addElementClass|removeElementClass|once|_378|_380|_376|appendChildNodes|coerceToDOM|_355|opt|clientWidth|opacity|GenericError|fail|resultList|_307|_301|_fire|can|addCallbacks|_resback|percent|decimal|separator|twoDigitFloat|_274|_273|_264|_257|_250|_249|_254|_248|_243|_242|fmt|_240|_245|getTime|sec|hour|_209|slice|_206|iterateNextIter|registerIteratorFactory|arrayLikeIter|iteratorRegistry|takewhile|ifilterfalse|ifilter|_181|_176|_168|_166|_159|_tee|deque|arg|fun|jsonRegistry|reprString|reprRegistry|comparatorRegistry|urlEncode|_110|_108|cur|_95|_87|_71|im_preargs||_53|_57|_46|present|like|array|Argument|_15|_12|_632|_631|_633|SUBMODULES|only|_628|_627|_626|roundElement|_624|getElementsByTagAndClassName|_RoundCorners|_613|_whichSideBottom|_whichSideTop|_609|_605|_606|transparent|_borderColor|_604|_603|_601|_600|bgColor|fromElement|_594|_592|backgroundColor|_createCornerSlice|_createCorner|_590|_589|_587|_586|_581|_578|_577|currentDocument|fromBackground|errors|_568|_564||sigs|flattenArguments|_561|findIdentical|_560|_558||_556|attachEvent|addEventListener|funcOrStr|Event||_548|fromCharCode|String|_specialMacKeys|any|green|_namedColors|hsvToRGB|rgbToHSV|hslToRGB|rgbToHSL|_542|01|360|_fromColorString|_540|_536|_538|_529|_523|_518|fromComputedStyle|_511|_507|_508|_506|_501|fromHexString|_498|_496|_486|__class__|createLoggingPane|_459|_461|font|_462|_430|_435|1000|index|_460|getMessages|removeListener|_451||_457|_450|infore|_448|_456|logDebug|offsetHeight|span|input|_436|TR||HTML|open|alert|currentWindow|swapDOM|SELECT|FORM|INPUT|createDOMFunc|ignoreAttr|_421|call|_417|_410|_415|nodeName|_414|_413|emitHTML|good|_406|_399|_397|_393|_392|addLoadEvent|addToCallStack|_387|_386|_381|_382|_383|_373|_372|_369|createDOM|_365|Function|_360|_362|_358|_344|nodeWalk|formContents|_337|_338|_334|_332|offsetTop|offsetLeft|visibility|parentElement|||XMLHttpRequestError|BrowserComplianceError|CancelledError|AlreadyCalledError|evalJSONRequest|sendXMLHttpRequest|wait|doSimpleXMLHttpRequest|getXMLHttpRequest|succeed|_312|finishedCount|_308|_cbDeferred|_303|_297|queryString|_nothing|_289|XMLHTTP|ActiveXObject|eval|_284|_check|error|_279|default|rstrip|lstrip|formatLocale|roundToFixed|truncToFixed|_276|pow|_272|_271|_270|sign|_265|_263|tmp|_238|_232|toISODate|toISOTime|getFullYear|getDate|getMonth|_230|_padTwo|_228|useNativeConsole|_212|compareLogMessage|isLogMessage|unshift|_207||maxSize|_202|_199|logLevelAtLeast|console|hasIterateNext|iterateNext|arrayLike|groupby||exhaust|tee|dropwhile|applymap||islice|izip|cycle|count||_189|_188|_183|_185|_184|_186|_187|_182|identity|fetch|_180|_177|listMin|reprNumber|reprArrayLike|compareArrayLike|compareDateLike|isDateLike|findValue|_128|__export__|keyComparator|_124|_118|_93|_94|_90|_88|_84|_77|_68|_67|_66|_65|_60|im_func|_55|im_self|_48|_44|_42|_39|_36|_33|_27|_26|_25|_22|_24|_20|javascript|write|getAttribute||org|www|http|getElementsByTagName|roundClass|_623|_622|_621|_620|_isBottomRounded|_isTopRounded|_borderSize|_618|_617|_616|_615|_marginSize|_611|_setBorder|_607|_setMargin|blendedColor|_598|__unstable__wrapElement|fromParent|_setOptions|2px|borderColor|_593|hidden|overflow|_591|_588|_roundBottomCorners|_585|_roundTopCorners|_584|_583|_582|_580|_renderBorder|_roundCornersImpl|getComputedStyle|_doWrap|_571|_unloadCache|onunload|detachEvent|removeEventListener|_listener|objOrFunc|_552||_551|_549|onload|delete|112|KEY_F|KEY_|MINUS|KEY_SEMICOLON|KEY_DELETE|KEY_INSERT|KEY_ARROW_DOWN|KEY_ARROW_RIGHT|KEY_ARROW_UP||KEY_ARROW_LEFT|KEY_HOME|KEY_END|KEY_PAGE_DOWN|KEY_PAGE_UP|KEY_ENTER|KEY_NUM_PAD_CLEAR|63236|mousemove|contextmenu|click|mouseout|mouseover|_src|yellow|708090|purple|orange|ff00ff|magenta|778899|d3d3d3|808080|gray|696969|2f4f4f|darkred|a9a9a9|00ffff|cyan|brown|_547|_546||||compareRGB|_545||_543|fromHSLString|fromRGBString|round|_533|_hslValue|switch|background|_503|_504||fromName|_488|col|toRGBString|_hexString|_rgbString|_hslString|toPrecision|isLight||_481|_477|_476|_475|_474|_473|_469|_466|closePane|_458|onkeypress|_454|addListener|_455|close|test|scrollHeight|option|word|moz|_431|getElementById|html|pop|200|_|removeElement|showElement|hideElement|CANVAS|STRONG|FIELDSET|LEGEND|OPTGROUP|OPTION|TEXTAREA|LABEL|HR|BR|H3|H2|H1|PRE|TT|BUTTON|IMG|TH||TABLE||TFOOT|THEAD|TBODY|TD|LI|OL|||UL|checked|class|ignoreAttrFilter||_424|_419|nodeValue|scrapeText|_416|_418|sort|_411|toHTML|_404|hasElementClass|_403|_402|_401|swapElementClass|_398|_394|toggleElementClass|_391|focusOnLoad|_newCallStack|currentStyle|_371|replaceChildNodes|_364|_361|getNodeAttribute|_357|setNodeAttribute|_354|_352|_350|_353|toDOM|_346|_345|registerDOMConverter|selectedIndex|setElementPosition|setElementDimensions|tagName|absolute|getBoxObjectFor|getBoundingClientRect|elementPosition|_325|_324|_322|_323|offsetWidth|elementDimensions|clientHeight|innerWidth|getViewportDimensions|setOpacity|status|_317|deferred|_316|_newNamedError|maybeDeferred||gatherResults|callLater|loadJSONDoc|_311|consumeErrors|fireOnOneErrback|fireOnOneCallback|addErrback|_305|_304|_306|unlocked|release|_300|_299|_298|_296|_xhr_onreadystatechange|_xhr_canceller|304|responseText|Msxml2|addBoth|_pause|_continue|result|the|are|they|instances|_unpause|cancel|_280|_278|en_US|strip|percentFormat|twoDigitAverage|numberFormatter|_277|_275|isNaN|_259|_258|_260|_255|_253|_numberFormatter|_241|_239|_237|_236|_235|_234|_233|_231|toAmericanDate|toPaddedAmericanDate|americanDate|toISOTimestamp|isoTimestamp|isoDate|foot|sep||60000|_221|_isoRegexp|dispatchEvent|createEvent|warning|logWarning|fatal|logFatal|debug|logError|baseLog|_210|getMessageText|logToConsole|dispatchListeners|_204|_203|ident|_201|postError|alertListener|_197|_192|groupby_as_array|iextend|some|reversed|sorted|every|sum|_190|eat|_174|_173|_172|_171|_167|_163|_158|_157|_151|_144|_141||_139|_136|_134||_133|_132|zip|merge|isUndefined|isCallable|listMax|_131|_130|encodeURIComponent||_127|method|parseQueryString|evalJSON|registerJSON|serializeJSON|objMin|objMax|reverseKeyComparator|arrayEqual|objEqual|bindMethods|xfilter|xmap|isEmpty|isNull|isUndefinedOrNull|itemgetter|items|keys|setdefault|_126|_120|decodeURIComponent|_119|len|_109|_107|_104|_105|_101|_102|_98|||_100|_97|_96|_91|json|__json__|_82|_81|_80|_79|_76||_75|_74|_73|_69|_primitives|_64|_63||_62|_61|_59|_wrapDumbFunction|_49|_50|_31|_30|_21|_7|application|MochiKit_|createElementNS|namespaceURI|lastIndexOf|xul|there|gatekeeper|keymaster|mozilla|getElementsComputedStyle|_hasSingleTextChild|borderWidth|borderStyle|borderBottomWidth|borderTopWidth|borderTopStyle|fontSize|paddingBottom|insertBefore|paddingTop|marginBottom|marginTop|_575|property|see|handling|thrown|Multiple|element|||given|123|KEY_NUM_PAD_|105|KEY_APOSTROPHE|222|KEY_RIGHT_SQUARE_BRACKET|221|KEY_REVERSE_SOLIDUS|220|KEY_LEFT_SQUARE_BRACKET||219|KEY_GRAVE_ACCENT|192|KEY_SOLIDUS|191|KEY_FULL_STOP|190|KEY_HYPHEN|189||KEY_COMMA|188|KEY_EQUALS_SIGN|187|186|KEY_SCROLL_LOCK|145|KEY_NUM_LOCK|144|KEY_NUM_PAD_SOLIDUS|111|KEY_NUM_PAD_FULL_STOP|110|KEY_NUM_PAD_HYPHEN|109|KEY_NUM_PAD_PLUS_SIGN|107|KEY_NUM_PAD_ASTERISK|106|KEY_SELECT|KEY_WINDOWS_RIGHT|KEY_WINDOWS_LEFT|KEY_PRINT_SCREEN|KEY_SPACEBAR|KEY_ESCAPE|KEY_CAPS_LOCK|KEY_PAUSE|KEY_ALT|KEY_CTRL|KEY_SHIFT|KEY_TAB|KEY_BACKSPACE|63242|63272|63302|63233|63235|63232|63234|63273|63275|63277|63276|63289|returnValue|cancelBubble|keypress|KEY_UNKNOWN|keyup|keydown|shiftKey|metaKey||ctrlKey|altKey|toElement|srcElement|9acd32||yellowgreen||ffff00|f5f5f5|whitesmoke||ffffff|f5deb3|wheat|ee82ee|violet|40e0d0|turquoise|ff6347|tomato|d8bfd8|thistle|008080|teal|d2b48c|tan|4682b4|steelblue|00ff7f|springgreen|fffafa|snow|slategrey|slategray|6a5acd|slateblue|87ceeb|skyblue|c0c0c0|silver|a0522d|sienna|fff5ee|seashell|2e8b57|seagreen|f4a460|sandybrown|fa8072|salmon|8b4513|saddlebrown|4169e1|royalblue|bc8f8f|rosybrown|ff0000|800080|b0e0e6|powderblue|dda0dd|plum|ffc0cb|pink|cd853f||peru|ffdab9|peachpuff|ffefd5|papayawhip|db7093|palevioletred|afeeee|paleturquoise|98fb98|palegreen|eee8aa||palegoldenrod|da70d6|orchid|ff4500|orangered|ffa500|6b8e23|olivedrab|808000|olive|fdf5e6|oldlace|000080|navy|ffdead|navajowhite|ffe4b5|moccasin|ffe4e1|mistyrose|f5fffa|mintcream|191970|midnightblue|c71585|mediumvioletred|48d1cc|mediumturquoise|00fa9a|mediumspringgreen|7b68ee|mediumslateblue|3cb371|mediumseagreen|9370db|mediumpurple|ba55d3|mediumorchid|0000cd|mediumblue|66cdaa|mediumaquamarine|800000|maroon|faf0e6|linen|32cd32|limegreen|00ff00|lime|ffffe0|lightyellow|b0c4de|lightsteelblue|lightslategrey|lightslategray||87cefa|lightskyblue|20b2aa|lightseagreen|ffa07a|lightsalmon|ffb6c1|lightpink|lightgrey|90ee90|lightgreen|lightgray|fafad2|lightgoldenrodyellow|e0ffff|lightcyan|f08080|lightcoral|add8e6|lightblue|fffacd|lemonchiffon|7cfc00|lawngreen|fff0f5|lavenderblush|e6e6fa|lavender|f0e68c|khaki|fffff0|ivory|4b0082|indigo|cd5c5c|indianred|ff69b4|hotpink|f0fff0|honeydew|grey|adff2f|greenyellow|008000|daa520|goldenrod|ffd700||gold|f8f8ff|ghostwhite|dcdcdc|gainsboro|fuchsia|228b22|forestgreen|fffaf0|floralwhite|b22222|firebrick|1e90ff|dodgerblue|dimgrey|dimgray|00bfff|deepskyblue|ff1493|deeppink|9400d3|darkviolet|00ced1|darkturquoise|darkslategrey|darkslategray|483d8b|darkslateblue|8fbc8f|darkseagreen|e9967a|darksalmon|8b0000|9932cc|darkorchid|ff8c00|darkorange|556b2f|darkolivegreen|8b008b|darkmagenta|bdb76b|darkkhaki|darkgrey|006400|darkgreen|darkgray|b8860b|darkgoldenrod|008b8b|darkcyan|00008b|darkblue|dc143c|crimson|fff8dc|cornsilk|6495ed|cornflowerblue|ff7f50|coral|d2691e||chocolate|7fff00|chartreuse|5f9ea0|cadetblue|deb887|burlywood|a52a2a|8a2be2|blueviolet|0000ff|ffebcd||blanchedalmond|000000|ffe4c4|bisque|f5f5dc|beige|f0ffff|azure|7fffd4|aquamarine|aqua|faebd7|antiquewhite|f0f8ff|aliceblue|lightGray|darkGray|namedColors|blackColor|fromText|whiteColor|_510|_509|PI|rad|deg|transparentColor|_494|_493|_492|fromHSV|_491|_490|_489|asHSV|toHexString|rgba|hsla|toHSLString|isDark|lighterColorWithLevel|darkerColorWithLevel|colorWithLightness|colorWithSaturation|colorWithHue|colorWithAlpha||serif|sans|Verdana||8pt|8em|auto||Close|Clear||Load|Filter||10em||fixed|regex|emergency|line|margin|_Listener|dtd|loose|html4|w3|EN|Transitional|DTD|W3C|PUBLIC|DOCTYPE|blocking|due|debugging|able|Not|resizable|dependent|href|location|_MochiKit_LoggingPane|_429|canvas|strong|fieldset|legend|optgroup|select|form|textarea|label|img|table|tfoot|thead|tbody|htmlFor||useMap|usemap|defaultChecked|hasChildNodes|quot|amp|_405|focus|replaceChild|checkbox||radio|_win|BODY||safari|version|userAgent|navigator|innerHeight|alpha|khtml|Tried|acquire|clearTimeout|setTimeout|GET|ignore|send|abort|failed|Request|readyState|support|does|Browser|Microsoft|_288|_287|used|Deferreds|Chained|success|unfired|fr_FR|de_DE|00|abs|search|pattern|Invalid|getTimezoneOffset|getSeconds|getMinutes|getHours|UTC|3600000|initEvent|Events|debuggingBookmarklet|MESSAGES|LAST|_205|clear|ninfo|nlevel|timestamp|reverse|takes|initial|with|sequence|empty|iterable|numbers|dateLike|escape|find|forward|unregister|unescape|Object|compared|item|contains|logor|logand|cle|clt|cge|cgt|cne|ceq|zrshift|rshift|lshift|xor|mul|mod|sub|add|neg|lognot|_9|_2'.split('|'),0,{}) + + +/* + * jQuery 1.2.1 - New Wave Javascript + * + * Copyright (c) 2007 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $ + * $Rev: 3353 $ + */ + +var decompressedJQuery = function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(G(){9(1m E!="W")H w=E;H E=18.15=G(a,b){I 6 7u E?6.5N(a,b):1u E(a,b)};9(1m $!="W")H D=$;18.$=E;H u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;E.1b=E.3A={5N:G(c,a){c=c||U;9(1m c=="1M"){H m=u.2S(c);9(m&&(m[1]||!a)){9(m[1])c=E.4D([m[1]],a);J{H b=U.3S(m[3]);9(b)9(b.22!=m[3])I E().1Y(c);J{6[0]=b;6.K=1;I 6}J c=[]}}J I 1u E(a).1Y(c)}J 9(E.1n(c))I 1u E(U)[E.1b.2d?"2d":"39"](c);I 6.6v(c.1c==1B&&c||(c.4c||c.K&&c!=18&&!c.1y&&c[0]!=W&&c[0].1y)&&E.2h(c)||[c])},4c:"1.2.1",7Y:G(){I 6.K},K:0,21:G(a){I a==W?E.2h(6):6[a]},2o:G(a){H b=E(a);b.4Y=6;I b},6v:G(a){6.K=0;1B.3A.1a.16(6,a);I 6},N:G(a,b){I E.N(6,a,b)},4I:G(a){H b=-1;6.N(G(i){9(6==a)b=i});I b},1x:G(f,d,e){H c=f;9(f.1c==3X)9(d==W)I 6.K&&E[e||"1x"](6[0],f)||W;J{c={};c[f]=d}I 6.N(G(a){L(H b 1i c)E.1x(e?6.R:6,b,E.1e(6,c[b],e,a,b))})},17:G(b,a){I 6.1x(b,a,"3C")},2g:G(e){9(1m e!="5i"&&e!=S)I 6.4n().3g(U.6F(e));H t="";E.N(e||6,G(){E.N(6.3j,G(){9(6.1y!=8)t+=6.1y!=1?6.6x:E.1b.2g([6])})});I t},5m:G(b){9(6[0])E(b,6[0].3H).6u().3d(6[0]).1X(G(){H a=6;1W(a.1w)a=a.1w;I a}).3g(6);I 6},8m:G(a){I 6.N(G(){E(6).6q().5m(a)})},8d:G(a){I 6.N(G(){E(6).5m(a)})},3g:G(){I 6.3z(1q,Q,1,G(a){6.58(a)})},6j:G(){I 6.3z(1q,Q,-1,G(a){6.3d(a,6.1w)})},6g:G(){I 6.3z(1q,P,1,G(a){6.12.3d(a,6)})},50:G(){I 6.3z(1q,P,-1,G(a){6.12.3d(a,6.2q)})},2D:G(){I 6.4Y||E([])},1Y:G(t){H b=E.1X(6,G(a){I E.1Y(t,a)});I 6.2o(/[^+>] [^+>]/.14(t)||t.1g("..")>-1?E.4V(b):b)},6u:G(e){H f=6.1X(G(){I 6.67?E(6.67)[0]:6.4R(Q)});H d=f.1Y("*").4O().N(G(){9(6[F]!=W)6[F]=S});9(e===Q)6.1Y("*").4O().N(G(i){H c=E.M(6,"2P");L(H a 1i c)L(H b 1i c[a])E.1j.1f(d[i],a,c[a][b],c[a][b].M)});I f},1E:G(t){I 6.2o(E.1n(t)&&E.2W(6,G(b,a){I t.16(b,[a])})||E.3m(t,6))},5V:G(t){I 6.2o(t.1c==3X&&E.3m(t,6,Q)||E.2W(6,G(a){I(t.1c==1B||t.4c)?E.2A(a,t)<0:a!=t}))},1f:G(t){I 6.2o(E.1R(6.21(),t.1c==3X?E(t).21():t.K!=W&&(!t.11||E.11(t,"2Y"))?t:[t]))},3t:G(a){I a?E.3m(a,6).K>0:P},7c:G(a){I 6.3t("."+a)},3i:G(b){9(b==W){9(6.K){H c=6[0];9(E.11(c,"24")){H e=c.4Z,a=[],Y=c.Y,2G=c.O=="24-2G";9(e<0)I S;L(H i=2G?e:0,33=2G?e+1:Y.K;i<33;i++){H d=Y[i];9(d.26){H b=E.V.1h&&!d.9V["1Q"].9L?d.2g:d.1Q;9(2G)I b;a.1a(b)}}I a}J I 6[0].1Q.1p(/\\r/g,"")}}J I 6.N(G(){9(b.1c==1B&&/4k|5j/.14(6.O))6.2Q=(E.2A(6.1Q,b)>=0||E.2A(6.2H,b)>=0);J 9(E.11(6,"24")){H a=b.1c==1B?b:[b];E("9h",6).N(G(){6.26=(E.2A(6.1Q,a)>=0||E.2A(6.2g,a)>=0)});9(!a.K)6.4Z=-1}J 6.1Q=b})},4o:G(a){I a==W?(6.K?6[0].3O:S):6.4n().3g(a)},6H:G(a){I 6.50(a).28()},6E:G(i){I 6.2J(i,i+1)},2J:G(){I 6.2o(1B.3A.2J.16(6,1q))},1X:G(b){I 6.2o(E.1X(6,G(a,i){I b.2O(a,i,a)}))},4O:G(){I 6.1f(6.4Y)},3z:G(f,d,g,e){H c=6.K>1,a;I 6.N(G(){9(!a){a=E.4D(f,6.3H);9(g<0)a.8U()}H b=6;9(d&&E.11(6,"1I")&&E.11(a[0],"4m"))b=6.4l("1K")[0]||6.58(U.5B("1K"));E.N(a,G(){H a=c?6.4R(Q):6;9(!5A(0,a))e.2O(b,a)})})}};G 5A(i,b){H a=E.11(b,"1J");9(a){9(b.3k)E.3G({1d:b.3k,3e:P,1V:"1J"});J E.5f(b.2g||b.6s||b.3O||"");9(b.12)b.12.3b(b)}J 9(b.1y==1)E("1J",b).N(5A);I a}E.1k=E.1b.1k=G(){H c=1q[0]||{},a=1,2c=1q.K,5e=P;9(c.1c==8o){5e=c;c=1q[1]||{}}9(2c==1){c=6;a=0}H b;L(;a<2c;a++)9((b=1q[a])!=S)L(H i 1i b){9(c==b[i])6r;9(5e&&1m b[i]==\'5i\'&&c[i])E.1k(c[i],b[i]);J 9(b[i]!=W)c[i]=b[i]}I c};H F="15"+(1u 3D()).3B(),6p=0,5c={};E.1k({8a:G(a){18.$=D;9(a)18.15=w;I E},1n:G(a){I!!a&&1m a!="1M"&&!a.11&&a.1c!=1B&&/G/i.14(a+"")},4a:G(a){I a.2V&&!a.1G||a.37&&a.3H&&!a.3H.1G},5f:G(a){a=E.36(a);9(a){9(18.6l)18.6l(a);J 9(E.V.1N)18.56(a,0);J 3w.2O(18,a)}},11:G(b,a){I b.11&&b.11.27()==a.27()},1L:{},M:G(c,d,b){c=c==18?5c:c;H a=c[F];9(!a)a=c[F]=++6p;9(d&&!E.1L[a])E.1L[a]={};9(b!=W)E.1L[a][d]=b;I d?E.1L[a][d]:a},30:G(c,b){c=c==18?5c:c;H a=c[F];9(b){9(E.1L[a]){2E E.1L[a][b];b="";L(b 1i E.1L[a])1T;9(!b)E.30(c)}}J{2a{2E c[F]}29(e){9(c.53)c.53(F)}2E E.1L[a]}},N:G(a,b,c){9(c){9(a.K==W)L(H i 1i a)b.16(a[i],c);J L(H i=0,48=a.K;i<48;i++)9(b.16(a[i],c)===P)1T}J{9(a.K==W)L(H i 1i a)b.2O(a[i],i,a[i]);J L(H i=0,48=a.K,3i=a[0];i<48&&b.2O(3i,i,3i)!==P;3i=a[++i]){}}I a},1e:G(c,b,d,e,a){9(E.1n(b))b=b.2O(c,[e]);H f=/z-?4I|7T-?7Q|1r|69|7P-?1H/i;I b&&b.1c==4W&&d=="3C"&&!f.14(a)?b+"2T":b},1o:{1f:G(b,c){E.N((c||"").2l(/\\s+/),G(i,a){9(!E.1o.3K(b.1o,a))b.1o+=(b.1o?" ":"")+a})},28:G(b,c){b.1o=c!=W?E.2W(b.1o.2l(/\\s+/),G(a){I!E.1o.3K(c,a)}).66(" "):""},3K:G(t,c){I E.2A(c,(t.1o||t).3s().2l(/\\s+/))>-1}},2k:G(e,o,f){L(H i 1i o){e.R["3r"+i]=e.R[i];e.R[i]=o[i]}f.16(e,[]);L(H i 1i o)e.R[i]=e.R["3r"+i]},17:G(e,p){9(p=="1H"||p=="2N"){H b={},42,41,d=["7J","7I","7G","7F"];E.N(d,G(){b["7C"+6]=0;b["7B"+6+"5Z"]=0});E.2k(e,b,G(){9(E(e).3t(\':3R\')){42=e.7A;41=e.7w}J{e=E(e.4R(Q)).1Y(":4k").5W("2Q").2D().17({4C:"1P",2X:"4F",19:"2Z",7o:"0",1S:"0"}).5R(e.12)[0];H a=E.17(e.12,"2X")||"3V";9(a=="3V")e.12.R.2X="7g";42=e.7e;41=e.7b;9(a=="3V")e.12.R.2X="3V";e.12.3b(e)}});I p=="1H"?42:41}I E.3C(e,p)},3C:G(h,j,i){H g,2w=[],2k=[];G 3n(a){9(!E.V.1N)I P;H b=U.3o.3Z(a,S);I!b||b.4y("3n")==""}9(j=="1r"&&E.V.1h){g=E.1x(h.R,"1r");I g==""?"1":g}9(j.1t(/4u/i))j=y;9(!i&&h.R[j])g=h.R[j];J 9(U.3o&&U.3o.3Z){9(j.1t(/4u/i))j="4u";j=j.1p(/([A-Z])/g,"-$1").2p();H d=U.3o.3Z(h,S);9(d&&!3n(h))g=d.4y(j);J{L(H a=h;a&&3n(a);a=a.12)2w.4w(a);L(a=0;a<2w.K;a++)9(3n(2w[a])){2k[a]=2w[a].R.19;2w[a].R.19="2Z"}g=j=="19"&&2k[2w.K-1]!=S?"2s":U.3o.3Z(h,S).4y(j)||"";L(a=0;a<2k.K;a++)9(2k[a]!=S)2w[a].R.19=2k[a]}9(j=="1r"&&g=="")g="1"}J 9(h.3Q){H f=j.1p(/\\-(\\w)/g,G(m,c){I c.27()});g=h.3Q[j]||h.3Q[f];9(!/^\\d+(2T)?$/i.14(g)&&/^\\d/.14(g)){H k=h.R.1S;H e=h.4v.1S;h.4v.1S=h.3Q.1S;h.R.1S=g||0;g=h.R.71+"2T";h.R.1S=k;h.4v.1S=e}}I g},4D:G(a,e){H r=[];e=e||U;E.N(a,G(i,d){9(!d)I;9(d.1c==4W)d=d.3s();9(1m d=="1M"){d=d.1p(/(<(\\w+)[^>]*?)\\/>/g,G(m,a,b){I b.1t(/^(70|6Z|6Y|9Q|4t|9N|9K|3a|9G|9E)$/i)?m:a+">"});H s=E.36(d).2p(),1s=e.5B("1s"),2x=[];H c=!s.1g("<9y")&&[1,"<24>",""]||!s.1g("<9w")&&[1,"<6T>",""]||s.1t(/^<(9u|1K|9t|9r|9p)/)&&[1,"<1I>",""]||!s.1g("<4m")&&[2,"<1I><1K>",""]||(!s.1g("<9m")||!s.1g("<9k"))&&[3,"<1I><1K><4m>",""]||!s.1g("<6Y")&&[2,"<1I><1K><6L>",""]||E.V.1h&&[1,"1s<1s>",""]||[0,"",""];1s.3O=c[1]+d+c[2];1W(c[0]--)1s=1s.5p;9(E.V.1h){9(!s.1g("<1I")&&s.1g("<1K")<0)2x=1s.1w&&1s.1w.3j;J 9(c[1]=="<1I>"&&s.1g("<1K")<0)2x=1s.3j;L(H n=2x.K-1;n>=0;--n)9(E.11(2x[n],"1K")&&!2x[n].3j.K)2x[n].12.3b(2x[n]);9(/^\\s/.14(d))1s.3d(e.6F(d.1t(/^\\s*/)[0]),1s.1w)}d=E.2h(1s.3j)}9(0===d.K&&(!E.11(d,"2Y")&&!E.11(d,"24")))I;9(d[0]==W||E.11(d,"2Y")||d.Y)r.1a(d);J r=E.1R(r,d)});I r},1x:G(c,d,a){H e=E.4a(c)?{}:E.5o;9(d=="26"&&E.V.1N)c.12.4Z;9(e[d]){9(a!=W)c[e[d]]=a;I c[e[d]]}J 9(E.V.1h&&d=="R")I E.1x(c.R,"9e",a);J 9(a==W&&E.V.1h&&E.11(c,"2Y")&&(d=="9d"||d=="9a"))I c.97(d).6x;J 9(c.37){9(a!=W){9(d=="O"&&E.11(c,"4t")&&c.12)6G"O 94 93\'t 92 91";c.90(d,a)}9(E.V.1h&&/6C|3k/.14(d)&&!E.4a(c))I c.4p(d,2);I c.4p(d)}J{9(d=="1r"&&E.V.1h){9(a!=W){c.69=1;c.1E=(c.1E||"").1p(/6O\\([^)]*\\)/,"")+(3I(a).3s()=="8S"?"":"6O(1r="+a*6A+")")}I c.1E?(3I(c.1E.1t(/1r=([^)]*)/)[1])/6A).3s():""}d=d.1p(/-([a-z])/8Q,G(z,b){I b.27()});9(a!=W)c[d]=a;I c[d]}},36:G(t){I(t||"").1p(/^\\s+|\\s+$/g,"")},2h:G(a){H r=[];9(1m a!="8P")L(H i=0,2c=a.K;i<2c;i++)r.1a(a[i]);J r=a.2J(0);I r},2A:G(b,a){L(H i=0,2c=a.K;i<2c;i++)9(a[i]==b)I i;I-1},1R:G(a,b){9(E.V.1h){L(H i=0;b[i];i++)9(b[i].1y!=8)a.1a(b[i])}J L(H i=0;b[i];i++)a.1a(b[i]);I a},4V:G(b){H r=[],2f={};2a{L(H i=0,6y=b.K;i<6y;i++){H a=E.M(b[i]);9(!2f[a]){2f[a]=Q;r.1a(b[i])}}}29(e){r=b}I r},2W:G(b,a,c){9(1m a=="1M")a=3w("P||G(a,i){I "+a+"}");H d=[];L(H i=0,4g=b.K;i<4g;i++)9(!c&&a(b[i],i)||c&&!a(b[i],i))d.1a(b[i]);I d},1X:G(c,b){9(1m b=="1M")b=3w("P||G(a){I "+b+"}");H d=[];L(H i=0,4g=c.K;i<4g;i++){H a=b(c[i],i);9(a!==S&&a!=W){9(a.1c!=1B)a=[a];d=d.8M(a)}}I d}});H v=8K.8I.2p();E.V={4s:(v.1t(/.+(?:8F|8E|8C|8B)[\\/: ]([\\d.]+)/)||[])[1],1N:/6w/.14(v),34:/34/.14(v),1h:/1h/.14(v)&&!/34/.14(v),35:/35/.14(v)&&!/(8z|6w)/.14(v)};H y=E.V.1h?"4h":"5h";E.1k({5g:!E.V.1h||U.8y=="8x",4h:E.V.1h?"4h":"5h",5o:{"L":"8w","8v":"1o","4u":y,5h:y,4h:y,3O:"3O",1o:"1o",1Q:"1Q",3c:"3c",2Q:"2Q",8u:"8t",26:"26",8s:"8r"}});E.N({1D:"a.12",8q:"15.4e(a,\'12\')",8p:"15.2I(a,2,\'2q\')",8n:"15.2I(a,2,\'4d\')",8l:"15.4e(a,\'2q\')",8k:"15.4e(a,\'4d\')",8j:"15.5d(a.12.1w,a)",8i:"15.5d(a.1w)",6q:"15.11(a,\'8h\')?a.8f||a.8e.U:15.2h(a.3j)"},G(i,n){E.1b[i]=G(a){H b=E.1X(6,n);9(a&&1m a=="1M")b=E.3m(a,b);I 6.2o(E.4V(b))}});E.N({5R:"3g",8c:"6j",3d:"6g",8b:"50",89:"6H"},G(i,n){E.1b[i]=G(){H a=1q;I 6.N(G(){L(H j=0,2c=a.K;j<2c;j++)E(a[j])[n](6)})}});E.N({5W:G(a){E.1x(6,a,"");6.53(a)},88:G(c){E.1o.1f(6,c)},87:G(c){E.1o.28(6,c)},86:G(c){E.1o[E.1o.3K(6,c)?"28":"1f"](6,c)},28:G(a){9(!a||E.1E(a,[6]).r.K){E.30(6);6.12.3b(6)}},4n:G(){E("*",6).N(G(){E.30(6)});1W(6.1w)6.3b(6.1w)}},G(i,n){E.1b[i]=G(){I 6.N(n,1q)}});E.N(["85","5Z"],G(i,a){H n=a.2p();E.1b[n]=G(h){I 6[0]==18?E.V.1N&&3y["84"+a]||E.5g&&38.33(U.2V["5a"+a],U.1G["5a"+a])||U.1G["5a"+a]:6[0]==U?38.33(U.1G["6n"+a],U.1G["6m"+a]):h==W?(6.K?E.17(6[0],n):S):6.17(n,h.1c==3X?h:h+"2T")}});H C=E.V.1N&&3x(E.V.4s)<83?"(?:[\\\\w*57-]|\\\\\\\\.)":"(?:[\\\\w\\82-\\81*57-]|\\\\\\\\.)",6k=1u 47("^>\\\\s*("+C+"+)"),6i=1u 47("^("+C+"+)(#)("+C+"+)"),6h=1u 47("^([#.]?)("+C+"*)");E.1k({55:{"":"m[2]==\'*\'||15.11(a,m[2])","#":"a.4p(\'22\')==m[2]",":":{80:"im[3]-0",2I:"m[3]-0==i",6E:"m[3]-0==i",3v:"i==0",3u:"i==r.K-1",6f:"i%2==0",6e:"i%2","3v-46":"a.12.4l(\'*\')[0]==a","3u-46":"15.2I(a.12.5p,1,\'4d\')==a","7X-46":"!15.2I(a.12.5p,2,\'4d\')",1D:"a.1w",4n:"!a.1w",7W:"(a.6s||a.7V||15(a).2g()||\'\').1g(m[3])>=0",3R:\'"1P"!=a.O&&15.17(a,"19")!="2s"&&15.17(a,"4C")!="1P"\',1P:\'"1P"==a.O||15.17(a,"19")=="2s"||15.17(a,"4C")=="1P"\',7U:"!a.3c",3c:"a.3c",2Q:"a.2Q",26:"a.26||15.1x(a,\'26\')",2g:"\'2g\'==a.O",4k:"\'4k\'==a.O",5j:"\'5j\'==a.O",54:"\'54\'==a.O",52:"\'52\'==a.O",51:"\'51\'==a.O",6d:"\'6d\'==a.O",6c:"\'6c\'==a.O",2r:\'"2r"==a.O||15.11(a,"2r")\',4t:"/4t|24|6b|2r/i.14(a.11)",3K:"15.1Y(m[3],a).K",7S:"/h\\\\d/i.14(a.11)",7R:"15.2W(15.32,G(1b){I a==1b.T;}).K"}},6a:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1u 47("^([:.#]*)("+C+"+)")],3m:G(a,c,b){H d,2b=[];1W(a&&a!=d){d=a;H f=E.1E(a,c,b);a=f.t.1p(/^\\s*,\\s*/,"");2b=b?c=f.r:E.1R(2b,f.r)}I 2b},1Y:G(t,o){9(1m t!="1M")I[t];9(o&&!o.1y)o=S;o=o||U;H d=[o],2f=[],3u;1W(t&&3u!=t){H r=[];3u=t;t=E.36(t);H l=P;H g=6k;H m=g.2S(t);9(m){H p=m[1].27();L(H i=0;d[i];i++)L(H c=d[i].1w;c;c=c.2q)9(c.1y==1&&(p=="*"||c.11.27()==p.27()))r.1a(c);d=r;t=t.1p(g,"");9(t.1g(" ")==0)6r;l=Q}J{g=/^([>+~])\\s*(\\w*)/i;9((m=g.2S(t))!=S){r=[];H p=m[2],1R={};m=m[1];L(H j=0,31=d.K;j<31;j++){H n=m=="~"||m=="+"?d[j].2q:d[j].1w;L(;n;n=n.2q)9(n.1y==1){H h=E.M(n);9(m=="~"&&1R[h])1T;9(!p||n.11.27()==p.27()){9(m=="~")1R[h]=Q;r.1a(n)}9(m=="+")1T}}d=r;t=E.36(t.1p(g,""));l=Q}}9(t&&!l){9(!t.1g(",")){9(o==d[0])d.44();2f=E.1R(2f,d);r=d=[o];t=" "+t.68(1,t.K)}J{H k=6i;H m=k.2S(t);9(m){m=[0,m[2],m[3],m[1]]}J{k=6h;m=k.2S(t)}m[2]=m[2].1p(/\\\\/g,"");H f=d[d.K-1];9(m[1]=="#"&&f&&f.3S&&!E.4a(f)){H q=f.3S(m[2]);9((E.V.1h||E.V.34)&&q&&1m q.22=="1M"&&q.22!=m[2])q=E(\'[@22="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.11(q,m[3]))?[q]:[]}J{L(H i=0;d[i];i++){H a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];9(a=="*"&&d[i].11.2p()=="5i")a="3a";r=E.1R(r,d[i].4l(a))}9(m[1]==".")r=E.4X(r,m[2]);9(m[1]=="#"){H e=[];L(H i=0;r[i];i++)9(r[i].4p("22")==m[2]){e=[r[i]];1T}r=e}d=r}t=t.1p(k,"")}}9(t){H b=E.1E(t,r);d=r=b.r;t=E.36(b.t)}}9(t)d=[];9(d&&o==d[0])d.44();2f=E.1R(2f,d);I 2f},4X:G(r,m,a){m=" "+m+" ";H c=[];L(H i=0;r[i];i++){H b=(" "+r[i].1o+" ").1g(m)>=0;9(!a&&b||a&&!b)c.1a(r[i])}I c},1E:G(t,r,h){H d;1W(t&&t!=d){d=t;H p=E.6a,m;L(H i=0;p[i];i++){m=p[i].2S(t);9(m){t=t.7O(m[0].K);m[2]=m[2].1p(/\\\\/g,"");1T}}9(!m)1T;9(m[1]==":"&&m[2]=="5V")r=E.1E(m[3],r,Q).r;J 9(m[1]==".")r=E.4X(r,m[2],h);J 9(m[1]=="["){H g=[],O=m[3];L(H i=0,31=r.K;i<31;i++){H a=r[i],z=a[E.5o[m[2]]||m[2]];9(z==S||/6C|3k|26/.14(m[2]))z=E.1x(a,m[2])||\'\';9((O==""&&!!z||O=="="&&z==m[5]||O=="!="&&z!=m[5]||O=="^="&&z&&!z.1g(m[5])||O=="$="&&z.68(z.K-m[5].K)==m[5]||(O=="*="||O=="~=")&&z.1g(m[5])>=0)^h)g.1a(a)}r=g}J 9(m[1]==":"&&m[2]=="2I-46"){H e={},g=[],14=/(\\d*)n\\+?(\\d*)/.2S(m[3]=="6f"&&"2n"||m[3]=="6e"&&"2n+1"||!/\\D/.14(m[3])&&"n+"+m[3]||m[3]),3v=(14[1]||1)-0,d=14[2]-0;L(H i=0,31=r.K;i<31;i++){H j=r[i],12=j.12,22=E.M(12);9(!e[22]){H c=1;L(H n=12.1w;n;n=n.2q)9(n.1y==1)n.4U=c++;e[22]=Q}H b=P;9(3v==1){9(d==0||j.4U==d)b=Q}J 9((j.4U+d)%3v==0)b=Q;9(b^h)g.1a(j)}r=g}J{H f=E.55[m[1]];9(1m f!="1M")f=E.55[m[1]][m[2]];f=3w("P||G(a,i){I "+f+"}");r=E.2W(r,f,h)}}I{r:r,t:t}},4e:G(b,c){H d=[];H a=b[c];1W(a&&a!=U){9(a.1y==1)d.1a(a);a=a[c]}I d},2I:G(a,e,c,b){e=e||1;H d=0;L(;a;a=a[c])9(a.1y==1&&++d==e)1T;I a},5d:G(n,a){H r=[];L(;n;n=n.2q){9(n.1y==1&&(!a||n!=a))r.1a(n)}I r}});E.1j={1f:G(g,e,c,h){9(E.V.1h&&g.4j!=W)g=18;9(!c.2u)c.2u=6.2u++;9(h!=W){H d=c;c=G(){I d.16(6,1q)};c.M=h;c.2u=d.2u}H i=e.2l(".");e=i[0];c.O=i[1];H b=E.M(g,"2P")||E.M(g,"2P",{});H f=E.M(g,"2t",G(){H a;9(1m E=="W"||E.1j.4T)I a;a=E.1j.2t.16(g,1q);I a});H j=b[e];9(!j){j=b[e]={};9(g.4S)g.4S(e,f,P);J g.7N("43"+e,f)}j[c.2u]=c;6.1Z[e]=Q},2u:1,1Z:{},28:G(d,c,b){H e=E.M(d,"2P"),2L,4I;9(1m c=="1M"){H a=c.2l(".");c=a[0]}9(e){9(c&&c.O){b=c.4Q;c=c.O}9(!c){L(c 1i e)6.28(d,c)}J 9(e[c]){9(b)2E e[c][b.2u];J L(b 1i e[c])9(!a[1]||e[c][b].O==a[1])2E e[c][b];L(2L 1i e[c])1T;9(!2L){9(d.4P)d.4P(c,E.M(d,"2t"),P);J d.7M("43"+c,E.M(d,"2t"));2L=S;2E e[c]}}L(2L 1i e)1T;9(!2L){E.30(d,"2P");E.30(d,"2t")}}},1F:G(d,b,e,c,f){b=E.2h(b||[]);9(!e){9(6.1Z[d])E("*").1f([18,U]).1F(d,b)}J{H a,2L,1b=E.1n(e[d]||S),4N=!b[0]||!b[0].2M;9(4N)b.4w(6.4M({O:d,2m:e}));b[0].O=d;9(E.1n(E.M(e,"2t")))a=E.M(e,"2t").16(e,b);9(!1b&&e["43"+d]&&e["43"+d].16(e,b)===P)a=P;9(4N)b.44();9(f&&f.16(e,b)===P)a=P;9(1b&&c!==P&&a!==P&&!(E.11(e,\'a\')&&d=="4L")){6.4T=Q;e[d]()}6.4T=P}I a},2t:G(d){H a;d=E.1j.4M(d||18.1j||{});H b=d.O.2l(".");d.O=b[0];H c=E.M(6,"2P")&&E.M(6,"2P")[d.O],3q=1B.3A.2J.2O(1q,1);3q.4w(d);L(H j 1i c){3q[0].4Q=c[j];3q[0].M=c[j].M;9(!b[1]||c[j].O==b[1]){H e=c[j].16(6,3q);9(a!==P)a=e;9(e===P){d.2M();d.3p()}}}9(E.V.1h)d.2m=d.2M=d.3p=d.4Q=d.M=S;I a},4M:G(c){H a=c;c=E.1k({},a);c.2M=G(){9(a.2M)a.2M();a.7L=P};c.3p=G(){9(a.3p)a.3p();a.7K=Q};9(!c.2m&&c.65)c.2m=c.65;9(E.V.1N&&c.2m.1y==3)c.2m=a.2m.12;9(!c.4K&&c.4J)c.4K=c.4J==c.2m?c.7H:c.4J;9(c.64==S&&c.63!=S){H e=U.2V,b=U.1G;c.64=c.63+(e&&e.2R||b.2R||0);c.7E=c.7D+(e&&e.2B||b.2B||0)}9(!c.3Y&&(c.61||c.60))c.3Y=c.61||c.60;9(!c.5F&&c.5D)c.5F=c.5D;9(!c.3Y&&c.2r)c.3Y=(c.2r&1?1:(c.2r&2?3:(c.2r&4?2:0)));I c}};E.1b.1k({3W:G(c,a,b){I c=="5Y"?6.2G(c,a,b):6.N(G(){E.1j.1f(6,c,b||a,b&&a)})},2G:G(d,b,c){I 6.N(G(){E.1j.1f(6,d,G(a){E(6).5X(a);I(c||b).16(6,1q)},c&&b)})},5X:G(a,b){I 6.N(G(){E.1j.28(6,a,b)})},1F:G(c,a,b){I 6.N(G(){E.1j.1F(c,a,6,Q,b)})},7x:G(c,a,b){9(6[0])I E.1j.1F(c,a,6[0],P,b)},25:G(){H a=1q;I 6.4L(G(e){6.4H=0==6.4H?1:0;e.2M();I a[6.4H].16(6,[e])||P})},7v:G(f,g){G 4G(e){H p=e.4K;1W(p&&p!=6)2a{p=p.12}29(e){p=6};9(p==6)I P;I(e.O=="4x"?f:g).16(6,[e])}I 6.4x(4G).5U(4G)},2d:G(f){5T();9(E.3T)f.16(U,[E]);J E.3l.1a(G(){I f.16(6,[E])});I 6}});E.1k({3T:P,3l:[],2d:G(){9(!E.3T){E.3T=Q;9(E.3l){E.N(E.3l,G(){6.16(U)});E.3l=S}9(E.V.35||E.V.34)U.4P("5S",E.2d,P);9(!18.7t.K)E(18).39(G(){E("#4E").28()})}}});E.N(("7s,7r,39,7q,6n,5Y,4L,7p,"+"7n,7m,7l,4x,5U,7k,24,"+"51,7j,7i,7h,3U").2l(","),G(i,o){E.1b[o]=G(f){I f?6.3W(o,f):6.1F(o)}});H x=P;G 5T(){9(x)I;x=Q;9(E.V.35||E.V.34)U.4S("5S",E.2d,P);J 9(E.V.1h){U.7f("<7d"+"7y 22=4E 7z=Q "+"3k=//:><\\/1J>");H a=U.3S("4E");9(a)a.62=G(){9(6.2C!="1l")I;E.2d()};a=S}J 9(E.V.1N)E.4B=4j(G(){9(U.2C=="5Q"||U.2C=="1l"){4A(E.4B);E.4B=S;E.2d()}},10);E.1j.1f(18,"39",E.2d)}E.1b.1k({39:G(g,d,c){9(E.1n(g))I 6.3W("39",g);H e=g.1g(" ");9(e>=0){H i=g.2J(e,g.K);g=g.2J(0,e)}c=c||G(){};H f="4z";9(d)9(E.1n(d)){c=d;d=S}J{d=E.3a(d);f="5P"}H h=6;E.3G({1d:g,O:f,M:d,1l:G(a,b){9(b=="1C"||b=="5O")h.4o(i?E("<1s/>").3g(a.40.1p(/<1J(.|\\s)*?\\/1J>/g,"")).1Y(i):a.40);56(G(){h.N(c,[a.40,b,a])},13)}});I 6},7a:G(){I E.3a(6.5M())},5M:G(){I 6.1X(G(){I E.11(6,"2Y")?E.2h(6.79):6}).1E(G(){I 6.2H&&!6.3c&&(6.2Q||/24|6b/i.14(6.11)||/2g|1P|52/i.14(6.O))}).1X(G(i,c){H b=E(6).3i();I b==S?S:b.1c==1B?E.1X(b,G(a,i){I{2H:c.2H,1Q:a}}):{2H:c.2H,1Q:b}}).21()}});E.N("5L,5K,6t,5J,5I,5H".2l(","),G(i,o){E.1b[o]=G(f){I 6.3W(o,f)}});H B=(1u 3D).3B();E.1k({21:G(d,b,a,c){9(E.1n(b)){a=b;b=S}I E.3G({O:"4z",1d:d,M:b,1C:a,1V:c})},78:G(b,a){I E.21(b,S,a,"1J")},77:G(c,b,a){I E.21(c,b,a,"45")},76:G(d,b,a,c){9(E.1n(b)){a=b;b={}}I E.3G({O:"5P",1d:d,M:b,1C:a,1V:c})},75:G(a){E.1k(E.59,a)},59:{1Z:Q,O:"4z",2z:0,5G:"74/x-73-2Y-72",6o:Q,3e:Q,M:S},49:{},3G:G(s){H f,2y=/=(\\?|%3F)/g,1v,M;s=E.1k(Q,s,E.1k(Q,{},E.59,s));9(s.M&&s.6o&&1m s.M!="1M")s.M=E.3a(s.M);9(s.1V=="4b"){9(s.O.2p()=="21"){9(!s.1d.1t(2y))s.1d+=(s.1d.1t(/\\?/)?"&":"?")+(s.4b||"5E")+"=?"}J 9(!s.M||!s.M.1t(2y))s.M=(s.M?s.M+"&":"")+(s.4b||"5E")+"=?";s.1V="45"}9(s.1V=="45"&&(s.M&&s.M.1t(2y)||s.1d.1t(2y))){f="4b"+B++;9(s.M)s.M=s.M.1p(2y,"="+f);s.1d=s.1d.1p(2y,"="+f);s.1V="1J";18[f]=G(a){M=a;1C();1l();18[f]=W;2a{2E 18[f]}29(e){}}}9(s.1V=="1J"&&s.1L==S)s.1L=P;9(s.1L===P&&s.O.2p()=="21")s.1d+=(s.1d.1t(/\\?/)?"&":"?")+"57="+(1u 3D()).3B();9(s.M&&s.O.2p()=="21"){s.1d+=(s.1d.1t(/\\?/)?"&":"?")+s.M;s.M=S}9(s.1Z&&!E.5b++)E.1j.1F("5L");9(!s.1d.1g("8g")&&s.1V=="1J"){H h=U.4l("9U")[0];H g=U.5B("1J");g.3k=s.1d;9(!f&&(s.1C||s.1l)){H j=P;g.9R=g.62=G(){9(!j&&(!6.2C||6.2C=="5Q"||6.2C=="1l")){j=Q;1C();1l();h.3b(g)}}}h.58(g);I}H k=P;H i=18.6X?1u 6X("9P.9O"):1u 6W();i.9M(s.O,s.1d,s.3e);9(s.M)i.5C("9J-9I",s.5G);9(s.5y)i.5C("9H-5x-9F",E.49[s.1d]||"9D, 9C 9B 9A 5v:5v:5v 9z");i.5C("X-9x-9v","6W");9(s.6U)s.6U(i);9(s.1Z)E.1j.1F("5H",[i,s]);H c=G(a){9(!k&&i&&(i.2C==4||a=="2z")){k=Q;9(d){4A(d);d=S}1v=a=="2z"&&"2z"||!E.6S(i)&&"3U"||s.5y&&E.6R(i,s.1d)&&"5O"||"1C";9(1v=="1C"){2a{M=E.6Q(i,s.1V)}29(e){1v="5k"}}9(1v=="1C"){H b;2a{b=i.5s("6P-5x")}29(e){}9(s.5y&&b)E.49[s.1d]=b;9(!f)1C()}J E.5r(s,i,1v);1l();9(s.3e)i=S}};9(s.3e){H d=4j(c,13);9(s.2z>0)56(G(){9(i){i.9q();9(!k)c("2z")}},s.2z)}2a{i.9o(s.M)}29(e){E.5r(s,i,S,e)}9(!s.3e)c();I i;G 1C(){9(s.1C)s.1C(M,1v);9(s.1Z)E.1j.1F("5I",[i,s])}G 1l(){9(s.1l)s.1l(i,1v);9(s.1Z)E.1j.1F("6t",[i,s]);9(s.1Z&&!--E.5b)E.1j.1F("5K")}},5r:G(s,a,b,e){9(s.3U)s.3U(a,b,e);9(s.1Z)E.1j.1F("5J",[a,s,e])},5b:0,6S:G(r){2a{I!r.1v&&9n.9l=="54:"||(r.1v>=6N&&r.1v<9j)||r.1v==6M||E.V.1N&&r.1v==W}29(e){}I P},6R:G(a,c){2a{H b=a.5s("6P-5x");I a.1v==6M||b==E.49[c]||E.V.1N&&a.1v==W}29(e){}I P},6Q:G(r,b){H c=r.5s("9i-O");H d=b=="6K"||!b&&c&&c.1g("6K")>=0;H a=d?r.9g:r.40;9(d&&a.2V.37=="5k")6G"5k";9(b=="1J")E.5f(a);9(b=="45")a=3w("("+a+")");I a},3a:G(a){H s=[];9(a.1c==1B||a.4c)E.N(a,G(){s.1a(3f(6.2H)+"="+3f(6.1Q))});J L(H j 1i a)9(a[j]&&a[j].1c==1B)E.N(a[j],G(){s.1a(3f(j)+"="+3f(6))});J s.1a(3f(j)+"="+3f(a[j]));I s.66("&").1p(/%20/g,"+")}});E.1b.1k({1A:G(b,a){I b?6.1U({1H:"1A",2N:"1A",1r:"1A"},b,a):6.1E(":1P").N(G(){6.R.19=6.3h?6.3h:"";9(E.17(6,"19")=="2s")6.R.19="2Z"}).2D()},1z:G(b,a){I b?6.1U({1H:"1z",2N:"1z",1r:"1z"},b,a):6.1E(":3R").N(G(){6.3h=6.3h||E.17(6,"19");9(6.3h=="2s")6.3h="2Z";6.R.19="2s"}).2D()},6J:E.1b.25,25:G(a,b){I E.1n(a)&&E.1n(b)?6.6J(a,b):a?6.1U({1H:"25",2N:"25",1r:"25"},a,b):6.N(G(){E(6)[E(6).3t(":1P")?"1A":"1z"]()})},9c:G(b,a){I 6.1U({1H:"1A"},b,a)},9b:G(b,a){I 6.1U({1H:"1z"},b,a)},99:G(b,a){I 6.1U({1H:"25"},b,a)},98:G(b,a){I 6.1U({1r:"1A"},b,a)},96:G(b,a){I 6.1U({1r:"1z"},b,a)},95:G(c,a,b){I 6.1U({1r:a},c,b)},1U:G(k,i,h,g){H j=E.6D(i,h,g);I 6[j.3L===P?"N":"3L"](G(){j=E.1k({},j);H f=E(6).3t(":1P"),3y=6;L(H p 1i k){9(k[p]=="1z"&&f||k[p]=="1A"&&!f)I E.1n(j.1l)&&j.1l.16(6);9(p=="1H"||p=="2N"){j.19=E.17(6,"19");j.2U=6.R.2U}}9(j.2U!=S)6.R.2U="1P";j.3M=E.1k({},k);E.N(k,G(c,a){H e=1u E.2j(3y,j,c);9(/25|1A|1z/.14(a))e[a=="25"?f?"1A":"1z":a](k);J{H b=a.3s().1t(/^([+-]=)?([\\d+-.]+)(.*)$/),1O=e.2b(Q)||0;9(b){H d=3I(b[2]),2i=b[3]||"2T";9(2i!="2T"){3y.R[c]=(d||1)+2i;1O=((d||1)/e.2b(Q))*1O;3y.R[c]=1O+2i}9(b[1])d=((b[1]=="-="?-1:1)*d)+1O;e.3N(1O,d,2i)}J e.3N(1O,a,"")}});I Q})},3L:G(a,b){9(E.1n(a)){b=a;a="2j"}9(!a||(1m a=="1M"&&!b))I A(6[0],a);I 6.N(G(){9(b.1c==1B)A(6,a,b);J{A(6,a).1a(b);9(A(6,a).K==1)b.16(6)}})},9f:G(){H a=E.32;I 6.N(G(){L(H i=0;i-8O?r:3I(E.17(6.T,6.1e))||0},3N:G(c,b,e){6.5u=(1u 3D()).3B();6.1O=c;6.2D=b;6.2i=e||6.2i||"2T";6.2v=6.1O;6.4q=6.4i=0;6.4r();H f=6;G t(){I f.2F()}t.T=6.T;E.32.1a(t);9(E.32.K==1){H d=4j(G(){H a=E.32;L(H i=0;i6.Y.2e+6.5u){6.2v=6.2D;6.4q=6.4i=1;6.4r();6.Y.3M[6.1e]=Q;H a=Q;L(H i 1i 6.Y.3M)9(6.Y.3M[i]!==Q)a=P;9(a){9(6.Y.19!=S){6.T.R.2U=6.Y.2U;6.T.R.19=6.Y.19;9(E.17(6.T,"19")=="2s")6.T.R.19="2Z"}9(6.Y.1z)6.T.R.19="2s";9(6.Y.1z||6.Y.1A)L(H p 1i 6.Y.3M)E.1x(6.T.R,p,6.Y.3P[p])}9(a&&E.1n(6.Y.1l))6.Y.1l.16(6.T);I P}J{H n=t-6.5u;6.4i=n/6.Y.2e;6.4q=E.3J[6.Y.3J||(E.3J.5q?"5q":"6B")](6.4i,n,0,1,6.Y.2e);6.2v=6.1O+((6.2D-6.1O)*6.4q);6.4r()}I Q}};E.2j.2F={2R:G(a){a.T.2R=a.2v},2B:G(a){a.T.2B=a.2v},1r:G(a){E.1x(a.T.R,"1r",a.2v)},6z:G(a){a.T.R[a.1e]=a.2v+a.2i}};E.1b.6m=G(){H c=0,3E=0,T=6[0],5t;9(T)8L(E.V){H b=E.17(T,"2X")=="4F",1D=T.12,23=T.23,2K=T.3H,4f=1N&&3x(4s)<8J;9(T.6V){5w=T.6V();1f(5w.1S+38.33(2K.2V.2R,2K.1G.2R),5w.3E+38.33(2K.2V.2B,2K.1G.2B));9(1h){H d=E("4o").17("8H");d=(d=="8G"||E.5g&&3x(4s)>=7)&&2||d;1f(-d,-d)}}J{1f(T.5l,T.5z);1W(23){1f(23.5l,23.5z);9(35&&/^t[d|h]$/i.14(1D.37)||!4f)d(23);9(4f&&!b&&E.17(23,"2X")=="4F")b=Q;23=23.23}1W(1D.37&&!/^1G|4o$/i.14(1D.37)){9(!/^8D|1I-9S.*$/i.14(E.17(1D,"19")))1f(-1D.2R,-1D.2B);9(35&&E.17(1D,"2U")!="3R")d(1D);1D=1D.12}9(4f&&b)1f(-2K.1G.5l,-2K.1G.5z)}5t={3E:3E,1S:c}}I 5t;G d(a){1f(E.17(a,"9T"),E.17(a,"8A"))}G 1f(l,t){c+=3x(l)||0;3E+=3x(t)||0}}})();',62,616,'||||||this|||if|||||||||||||||||||||||||||||||||function|var|return|else|length|for|data|each|type|false|true|style|null|elem|document|browser|undefined||options|||nodeName|parentNode||test|jQuery|apply|css|window|display|push|fn|constructor|url|prop|add|indexOf|msie|in|event|extend|complete|typeof|isFunction|className|replace|arguments|opacity|div|match|new|status|firstChild|attr|nodeType|hide|show|Array|success|parent|filter|trigger|body|height|table|script|tbody|cache|string|safari|start|hidden|value|merge|left|break|animate|dataType|while|map|find|global||get|id|offsetParent|select|toggle|selected|toUpperCase|remove|catch|try|cur|al|ready|duration|done|text|makeArray|unit|fx|swap|split|target||pushStack|toLowerCase|nextSibling|button|none|handle|guid|now|stack|tb|jsre|timeout|inArray|scrollTop|readyState|end|delete|step|one|name|nth|slice|doc|ret|preventDefault|width|call|events|checked|scrollLeft|exec|px|overflow|documentElement|grep|position|form|block|removeData|rl|timers|max|opera|mozilla|trim|tagName|Math|load|param|removeChild|disabled|insertBefore|async|encodeURIComponent|append|oldblock|val|childNodes|src|readyList|multiFilter|color|defaultView|stopPropagation|args|old|toString|is|last|first|eval|parseInt|self|domManip|prototype|getTime|curCSS|Date|top||ajax|ownerDocument|parseFloat|easing|has|queue|curAnim|custom|innerHTML|orig|currentStyle|visible|getElementById|isReady|error|static|bind|String|which|getComputedStyle|responseText|oWidth|oHeight|on|shift|json|child|RegExp|ol|lastModified|isXMLDoc|jsonp|jquery|previousSibling|dir|safari2|el|styleFloat|state|setInterval|radio|getElementsByTagName|tr|empty|html|getAttribute|pos|update|version|input|float|runtimeStyle|unshift|mouseover|getPropertyValue|GET|clearInterval|safariTimer|visibility|clean|__ie_init|absolute|handleHover|lastToggle|index|fromElement|relatedTarget|click|fix|evt|andSelf|removeEventListener|handler|cloneNode|addEventListener|triggered|nodeIndex|unique|Number|classFilter|prevObject|selectedIndex|after|submit|password|removeAttribute|file|expr|setTimeout|_|appendChild|ajaxSettings|client|active|win|sibling|deep|globalEval|boxModel|cssFloat|object|checkbox|parsererror|offsetLeft|wrapAll|dequeue|props|lastChild|swing|handleError|getResponseHeader|results|startTime|00|box|Modified|ifModified|offsetTop|evalScript|createElement|setRequestHeader|ctrlKey|callback|metaKey|contentType|ajaxSend|ajaxSuccess|ajaxError|ajaxStop|ajaxStart|serializeArray|init|notmodified|POST|loaded|appendTo|DOMContentLoaded|bindReady|mouseout|not|removeAttr|unbind|unload|Width|keyCode|charCode|onreadystatechange|clientX|pageX|srcElement|join|outerHTML|substr|zoom|parse|textarea|reset|image|odd|even|before|quickClass|quickID|prepend|quickChild|execScript|offset|scroll|processData|uuid|contents|continue|textContent|ajaxComplete|clone|setArray|webkit|nodeValue|fl|_default|100|linear|href|speed|eq|createTextNode|throw|replaceWith|splice|_toggle|xml|colgroup|304|200|alpha|Last|httpData|httpNotModified|httpSuccess|fieldset|beforeSend|getBoundingClientRect|XMLHttpRequest|ActiveXObject|col|br|abbr|pixelLeft|urlencoded|www|application|ajaxSetup|post|getJSON|getScript|elements|serialize|clientWidth|hasClass|scr|clientHeight|write|relative|keyup|keypress|keydown|change|mousemove|mouseup|mousedown|right|dblclick|resize|focus|blur|frames|instanceof|hover|offsetWidth|triggerHandler|ipt|defer|offsetHeight|border|padding|clientY|pageY|Left|Right|toElement|Bottom|Top|cancelBubble|returnValue|detachEvent|attachEvent|substring|line|weight|animated|header|font|enabled|innerText|contains|only|size|gt|lt|uFFFF|u0128|417|inner|Height|toggleClass|removeClass|addClass|replaceAll|noConflict|insertAfter|prependTo|wrap|contentWindow|contentDocument|http|iframe|children|siblings|prevAll|nextAll|wrapInner|prev|Boolean|next|parents|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|compatible|borderTopWidth|ie|ra|inline|it|rv|medium|borderWidth|userAgent|522|navigator|with|concat|1px|10000|array|ig|PI|NaN|400|reverse|fast|600|slow|Function|Object|setAttribute|changed|be|can|property|fadeTo|fadeOut|getAttributeNode|fadeIn|slideToggle|method|slideUp|slideDown|action|cssText|stop|responseXML|option|content|300|th|protocol|td|location|send|cap|abort|colg|cos|tfoot|thead|With|leg|Requested|opt|GMT|1970|Jan|01|Thu|area|Since|hr|If|Type|Content|meta|specified|open|link|XMLHTTP|Microsoft|img|onload|row|borderLeftWidth|head|attributes'.split('|'),0,{}); + +/* + Copyright (c) 2004-2007, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +/* + This is a compiled version of Dojo, built for deployment and not for + development. To get an editable version, please visit: + + http://dojotoolkit.org + + for documentation and information on getting the source. +*/ + +var decompressedDojo = function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(V z=="1k"){(B(){if(V D["1o"]=="1k"){D.1o={}}if((!D["1z"])||(!1z["ca"])){D.1z={}}A cn=["rA","rz","1K","ry","rx","9f","rw","rv","ru","rt","rs","rr","rq","ro","rn","rm"];A i=0,24;1s(24=cn[i++]){if(!1z[24]){1z[24]=B(){}}}if(V D["z"]=="1k"){D.z={}}z.1W=D;A d3={im:U,rl:U,rk:"",rj:"",ri:"",rh:K,rg:U};R(A 8z in d3){if(V 1o[8z]=="1k"){1o[8z]=d3[8z]}}A jK=["rf","rd","rc","rb"];A t;1s(t=jK.3a()){z["is"+t]=U}})();z.8h=1o.8h;z.cY={jJ:0,jI:9,jH:0,jG:"",jF:2V("$ra: r9 $".1f(/[0-9]+/)[0]),2i:B(){4G(z.cY){C jJ+"."+jI+"."+jH+jG+" ("+jF+")"}}};z.d1=B(jE,jD,1V){A 2h=1V||z.1W;R(A i=0,p;2h&&(p=jE[i]);i++){2h=(p in 2h?2h[p]:(jD?2h[p]={}:1k))}C 2h};z.88=B(jC,jA,jB){A d2=jC.1A("."),p=d2.8q(),M=z.d1(d2,K,jB);C(M&&p?(M[p]=jA):1k)};z.6q=B(jz,jy,jx){C z.d1(jz.1A("."),jy,jx)};z.r8=B(jw,M){C!!z.6q(jw,U,M)};z["3u"]=B(d0){C z.1W.3u?z.1W.3u(d0):3u(d0)};z.ia=B(jv,cZ,cX){A 8y="r7: "+jv;if(cZ){8y+=" "+cZ}if(cX){8y+=" -- r6 be r5 in cY: "+cX}1z.1K(8y)};z.r4=B(ju,cW){A cV="r3: "+ju+" -- r2 r1 4F r0 qZ qY.";if(cW){cV+=" "+cW}1z.1K(cV)};(B(){A cR={53:{},6p:0,1h:{},8k:{z:{1p:"z",1Z:"."},cU:{1p:"cU",1Z:"../qX/cU"},cT:{1p:"cT",1Z:"cT"}},cN:B(cS){A mp=D.8k;C jp(mp[cS]&&mp[cS].1Z)},jk:B(8x){A mp=D.8k;if(D.cN(8x)){C mp[8x].1Z}C 8x},8v:[],6t:U,56:[],8t:[],8u:U};R(A cQ in cR){z[cQ]=cR[cQ]}})();z.jg=B(8w,cP,cb){A 1g=(((8w.2s(0)=="/"||8w.1f(/^\\w+:/)))?"":D.51)+8w;if(1o.jt&&z.c8){1g+="?"+67(1o.jt).2f(/\\W+/g,"")}1u{C!cP?D.cO(1g,cb):D.jq(1g,cP,cb)}1y(e){1z.1K(e);C U}};z.cO=B(1g,cb){if(D.8v[1g]){C K}A 6u=D.iR(1g,K);if(!6u){C U}D.8v[1g]=K;D.8v.Y(1g);if(cb){6u="("+6u+")"}A jr=z["3u"](6u+"\\r\\n//@ qW="+1g);if(cb){cb(jr)}C K};z.jq=B(1g,jo,cb){A ok=U;1u{ok=D.cO(1g,cb)}1y(e){1z.1K("qV je ",1g," 4G 9f: ",e)}C jp(ok&&D.53[jo])};z.6m=B(){D.8u=K;D.6t=K;A 57=D.56;D.56=[];R(A x=0;x<57.G;x++){57[x]()}D.8u=U;if(z.6t&&z.6p==0&&D.56.G>0){z.8s()}};z.ck=B(){A 57=D.8t;1s(57.G){(57.8q())()}};z.qU=B(M,jn){A d=z;if(P.G==1){d.56.Y(M)}I{if(P.G>1){d.56.Y(B(){M[jn]()})}}if(d.6t&&d.6p==0&&!d.8u){d.8s()}};z.dW=B(M,jm){A d=z;if(P.G==1){d.8t.Y(M)}I{if(P.G>1){d.8t.Y(B(){M[jm]()})}}};z.iM=B(){if(D.6t){C}if(D.6p>0){1z.1K("qT qS in qR!");C}z.8s()};z.8s=B(){if(V 5c=="8b"||(1o["qQ"]&&z.2M)){5c("z.6m();",0)}I{z.6m()}};z.cF=B(jl){A 4v=jl.1A(".");R(A i=4v.G;i>0;i--){A 8r=4v.2w(0,i).22(".");if((i==1)&&!D.cN(8r)){4v[0]="../"+4v[0]}I{A cM=D.jk(8r);if(cM!=8r){4v.3S(0,i,cM);3f}}}C 4v};z.jj=U;z.8m=B(2T,qP,55){55=D.jj||55;A 54=D.53[2T];if(54){C 54}A cL=2T.1A(".");A 3L=D.cF(2T);A jh=((3L[0].2s(0)!="/")&&!3L[0].1f(/^\\w+:/));A ji=3L[3L.G-1];A 3m;if(ji=="*"){2T=cL.2w(0,-1).22(".");3L.8q();3m=3L.22("/")+"/"+(1o["qO"]||"qN")+".js";if(jh&&3m.2s(0)=="/"){3m=3m.2w(1)}}I{3m=3L.22("/")+".js";2T=cL.22(".")}A jf=(!55)?2T:L;A ok=D.jg(3m,jf);if((!ok)&&(!55)){2m S 1O("qM 3O 4E \'"+2T+"\'; 72 qL \'"+3m+"\'")}if((!55)&&(!D["qK"])){54=D.53[2T];if(!54){2m S 1O("qJ \'"+2T+"\' is 3O qI a8 je \'"+3m+"\'")}}C 54};z.8c=z.8m;z.1Q=B(cK){A cJ=cK+"";A 8p=cJ;A 6s=cK.1A(/\\./);if(6s[6s.G-1]=="*"){6s.8q();8p=6s.22(".")}A 8o=z.6q(8p,K);D.53[cJ]=8o;D.53[8p]=8o;C 8o};z.qH=B(8n){A jd=8n["qG"]||[];A cI=jd.3U(8n[z.j4]||8n["aY"]||[]);R(A x=0;x0&&!(j==1&&1X[0]=="")&&1X[j]==".."&&1X[j-1]!=".."){if(j==(1X.G-1)){1X.3S(j,1);1X[j-1]=""}I{1X.3S(j-1,2);j-=2}}}}1t.28=1X.22("/")}}}}1g="";if(1t.4t){1g+=1t.4t+":"}if(1t.3l){1g+="//"+1t.3l}1g+=1t.28;if(1t.1r){1g+="?"+1t.1r}if(1t.52){1g+="#"+1t.52}}D.1g=1g.2i();A r=D.1g.1f(j7);D.4t=r[2]||(r[1]?"":n);D.3l=r[4]||(r[3]?"":n);D.28=r[5];D.1r=r[7]||(r[6]?"":n);D.52=r[9]||(r[8]?"":n);if(D.3l!=n){r=D.3l.1f(j6);D.8X=r[3]||n;D.8W=r[4]||n;D.qw=r[5];D.qv=r[7]||n}};z.4r.1C.2i=B(){C D.1g}})();z.qu=B(j5,2E){A 2B=z.cF(j5).22("/");if(!2B){C L}if(2B.31("/")!=2B.G-1){2B+="/"}A cE=2B.T(":");if(2B.2s(0)!="/"&&(cE==-1||cE>2B.T("/"))){2B=z.51+2B}C S z.4r(2B,2E)};if(V 26!="1k"){z.c8=K;z.j4="qt";(B(){A d=z;if(1q&&1q.4I){A 8j=1q.4I("ak");A j3=/z(\\.qs)?\\.js([\\?\\.]|$)/i;R(A i=0;i<8j.G;i++){A 4X=8j[i].5t("4X");if(!4X){6c}A m=4X.1f(j3);if(m){if(!1o["51"]){1o["51"]=4X.21(0,m.hK)}A cD=8j[i].5t("1o");if(cD){A cC=3u("({ "+cD+" })");R(A x in cC){1o[x]=cC[x]}}3f}}}d.51=1o["51"];A n=cq;A 8i=n.iL;A 4Z=n.qr;A 6r=2k(4Z);d.2M=(8i.T("qq")>=0)?6r:0;d.6B=(4Z.T("qo")>=0)||(4Z.T("j2")>=0)?6r:0;d.3o=(4Z.T("j2")>=0)?6r:0;A j1=8i.T("qn");d.gu=d.7B=((j1>=0)&&(!d.6B))?6r:0;d.j0=0;d.1l=0;d.iV=0;1u{if(d.7B){d.j0=2k(8i.1A("qm/")[1].1A(" ")[0])}if((1q.gx)&&(!d.2M)){d.1l=2k(4Z.1A("qk ")[1].1A(";")[0])}}1y(e){}if(z.1l&&(26.8f.cu==="9q:")){1o.iT=K}d.iX=B(){A 2A;A qj;A cB=d.6q("cz.cy");if(cB){C cB}if(V iZ!="1k"){2A=S iZ()}I{if(d.1l){1u{2A=S 9j("qi.qh")}1y(e){}}I{if(cq.qg["8Z/x-iY"]){2A=1q.a9("8b");2A.cA("Z","8Z/x-iY");2A.cA("3n",0);2A.cA("58",0);2A.1c.gq="7C";1q.5K.4c(2A)}}}if(!2A){C L}z.88("cz.cy.qf",2A);C z.6q("cz.cy")};A iW=d.iX();if(iW){d.iV=K}A cm=1q["aX"];d.qe=(cm=="aW")||(cm=="gr")||(d.1l<6);d.8h=1o.8h||(d.1l?n.qd:n.qc).1M();d.qb=1z.1K;d.cx=["iU.8g","em.8g","iU.8g.4.0"];d.9b=B(){A 4s=L;A cv=L;if(!z.1l||!1o.iT){1u{4s=S qa()}1y(e){}}if(!4s){R(A i=0;i<3;++i){A cw=z.cx[i];1u{4s=S 9j(cw)}1y(e){cv=e}if(4s){z.cx=[cw];3f}}}if(!4s){2m S 1O("8g 3O q9: "+cv)}C 4s};d.8Y=B(iS){A 4Y=iS.3N||0;C((4Y>=q8)&&(4Y0);d.iR=B(1g,iP){A 3K=D.9b();if(!iQ&&z.4r){1g=(S z.4r(26.8f,1g)).2i()}3K.dL("dD",1g,U);1u{3K.dI(L);if(!d.8Y(3K)){A 1G=1O("q2 4F 4E "+1g+" 3N:"+3K.3N);1G.3N=3K.3N;1G.2G=3K.2G;2m 1G}}1y(e){if(iP){C L}2m e}C 3K.2G}})();z.iO=U;z.6o=B(e){z.iO=K;A cr=(e&&e.Z)?e.Z.1M():"4E";if(P.2O.iN||(cr!="q1"&&cr!="4E")){C}P.2O.iN=K;if(V z["8e"]!="1k"){dX(z.8e);63 z.8e}if(z.6p==0){z.iM()}};if(1q.66){if(z.2M||(z.7B&&(1o["q0"]===K))){1q.66("pZ",z.6o,L)}26.66("4E",z.6o,L)}if(/(pY|pX)/i.6Z(cq.iL)){z.8e=dN(B(){if(/6m|iJ/.6Z(1q.6F)){z.6o()}},10)}(B(){A 3g=26;A 8d=B(cp,fp){A iK=3g[cp]||B(){};3g[cp]=B(){fp.14(3g,P);iK.14(3g,P)}};if(z.1l){1q.fJ(""+"");A co=K;8d("iG",B(){3g.5c(B(){co=U},0)});8d("pU",B(){if(co){z.ck()}});1u{1q.pT.2P("v","pS:pR-pQ-pP:pO");1q.pN().pM("v\\\\:*","pL:2E(#aY#pK)")}1y(e){}}I{8d("iG",B(){z.ck()})}})();z.pJ=B(){};z.1e=26["1q"]||L;z.3E=B(){C z.1e.3E||z.1e.4I("3E")[0]};z.ch=B(iF,iE){z.1W=iF;z.1e=iE};z.cf=B(4q,6n,iD){if((6n)&&((V 4q=="3c")||(4q 1N 67))){4q=6n[4q]}C(6n?4q.14(6n,iD||[]):4q())};z.pI=B(cj,iC,iB,iA){A cg;A iz=z.1W;A iy=z.1e;1u{z.ch(cj,cj.1q);cg=z.cf(iC,iB,iA)}ir{z.ch(iz,iy)}C cg};z.pH=B(ix,iw,iv,iu){A ce;A ip=z.1e;1u{z.1e=ix;ce=z.cf(iw,iv,iu)}ir{z.1e=ip}C ce};if(1o["cd"]){R(A cc in 1o["cd"]){z.io(cc,1o["cd"][cc])}}}if(1o.im){if(!1z.ca){z.8c("z.pG.ca")}}}if(!z.1h["z.X.c9"]){z.1h["z.X.c9"]=K;z.1Q("z.X.c9");z.1R=B(it){C(V it=="3c"||it 1N 67)};z.2l=B(it){C(it&&it 1N 4e||V it=="6a"||((V z["1H"]!="1k")&&(it 1N z.1H)))};if(z.c8&&z.3o){z.1Y=B(it){if((V(it)=="B")&&(it=="[8b 1H]")){C U}C(V it=="B"||it 1N bI)}}I{z.1Y=B(it){C(V it=="B"||it 1N bI)}}z.ib=B(it){if(V it=="1k"){C U}C(it===L||V it=="8b"||z.2l(it)||z.1Y(it))};z.pF=B(it){A d=z;if((!it)||(V it=="1k")){C U}if(d.1R(it)){C U}if(d.1Y(it)){C U}if(d.2l(it)){C K}if((it.5w)&&(it.5w.1M()=="3R")){C U}if(pE(it.G)){C K}C U};z.pD=B(it){if(!it){C U}C!z.1Y(it)&&/\\{\\s*\\[il 5h\\]\\s*\\}/.6Z(67(it))};z.c7=B(M,4W){A 8a={};R(A x in 4W){if((V 8a[x]=="1k")||(8a[x]!=4W[x])){M[x]=4W[x]}}if(z.1l){A p=4W.2i;if((V(p)=="B")&&(p!=M.2i)&&(p!=8a.2i)&&(p!="\\pC 2i() {\\n [il 5h]\\n}\\n")){M.2i=4W.2i}}C M};z.1x=B(M,pB){R(A i=1,l=P.G;i2){C z.ig.14(z,P)}if(!3k){3k=2z;2z=L}if(z.1R(3k)){2z=2z||z.1W;if(!2z[3k]){2m(["z.2p: ie[\\"",3k,"\\"] is L (ie=\\"",2z,"\\")"].22(""))}C B(){C 2z[3k].14(2z,P||[])}}I{C(!2z?3k:B(){C 3k.14(2z,P||[])})}};z.6j=B(M,c3){B c4(){};c4.1C=M;A c2=S c4();if(c3){z.1x(c2,c3)}C c2};z.7X=B(pz){A Q=[L];C z.2p.14(z,Q.3U(z.4d(P)))};z.4d=B(M,ic){A Q=[];R(A x=ic||0;x3)){z.ia("z.2r: R 9P \'"+6l+"\' py pw B as \'1P\' pv pu of as a pt i3.","","1.0");A c=3j;3j=P[3]||{};3j.1P=c}A dd=P.2O,4V=L;if(z.2l(4p)){4V=4p;4p=4V.3a()}if(4V){R(A i=0,m;i<4V.G;i++){m=4V[i];if(!m){2m("ps #"+i+" 4F pr of "+6l+" is L. pq\'s pp a po pl is 3O 6m.")}4p=dd.6j(4p,m)}}A i9=(3j||0).1P,6k=dd.6j(4p),fn;R(A i in 3j){if(z.1Y(fn=3j[i])&&(!0[i])){fn.i4=i}}z.4M(6k,{4o:6l,bY:i9,bZ:L},3j||0);6k.1C.1P=6k;C z.88(6l,6k)};z.1x(z.2r,{6j:B(c0,i8){A bp=(c0||0).1C,mp=(i8||0).1C;A 2S=z.2r.i7();z.1x(2S,{84:bp,1x:mp});if(c0){2S.1C=z.6j(bp)}z.4M(2S,z.2r.i6,mp||0,{bY:L});2S.1C.1P=2S;2S.1C.4o=(bp||0).4o+"pk"+(mp||0).4o;z.88(2S.1C.4o,2S);C 2S},i7:B(){C B(){D.i5(P)}},i6:{i5:B(86){A c=86.2O,s=c.84,ct=s&&s.1P,m=c.1x,87=m&&m.1P,a=86,ii,fn;if(a[0]){if((fn=a[0]["bZ"])){a=fn.14(D,a)||a}}if(fn=c.1C.bZ){a=fn.14(D,a)||a}if(ct&&ct.14){ct.14(D,a)}if(87&&87.14){87.14(D,a)}if(ii=c.1C.bY){ii.14(D,86)}},bX:B(85){A c=D.1P,p,m;1s(c){p=c.84;m=c.1x;if(m==85||(m 1N 85.1P)){C p}if(m&&(m=m.bX(85))){C m}c=p&&p.1P}},6h:B(83,82,bW,6i){A p=bW,c,m,f;do{c=p.1P;m=c.1x;if(m&&(m=D.6h(83,82,m,6i))){C m}if((f=p[83])&&(6i==(f==82))){C p}p=c.84}1s(p);C!6i&&(p=D.bX(bW))&&D.6h(83,82,p,6i)},bU:B(2R,4U,bV){A a=P;if(!z.1R(a[0])){bV=4U;4U=2R;2R=4U.2O.i4}A c=4U.2O,p=D.1P.1C,a=bV||4U,fn,mp;if(D[2R]!=c||p[2R]==c){mp=D.6h(2R,c,p,K);if(!mp){2m(D.4o+": 1p i3 (\\""+2R+"\\") 4F bU pj 1f 2O (2r.js)")}p=D.6h(2R,c,mp,U)}fn=p&&p[2R];if(!fn){1z.1K(mp.4o+": no bU \\""+2R+"\\" ph pg (2r.js)");C}C fn.14(D,a)}}})}if(!z.1h["z.X.2c"]){z.1h["z.X.2c"]=K;z.1Q("z.X.2c");z.3i={i2:B(){C B(){A ap=4e.1C,c=P.2O,ls=c.2b,t=c.5V;A r=t&&t.14(D,P);R(A i in ls){if(!(i in ap)){ls[i].14(D,P)}}C r}},2P:B(6g,bT,i1){6g=6g||z.1W;A f=6g[bT];if(!f||!f.2b){A d=z.3i.i2();d.5V=f;d.2b=[];f=6g[bT]=d}C f.2b.Y(i1)},3J:B(i0,hZ,bS){A f=(i0||z.1W)[hZ];if(f&&f.2b&&bS--){63 f.2b[bS]}}};z.2c=B(M,pd,pc,pa,p9){A a=P,F=[],i=0;F.Y(z.1R(a[0])?L:a[i++],a[i++]);A a1=a[i+1];F.Y(z.1R(a1)||z.1Y(a1)?a[i++]:L,a[i++]);R(A l=a.G;i2){6e=z.7X(6e,P,2)}C D.5k(6e,6e)},ef:B(cb,4T){A 7Y=z.2p(cb,4T);if(P.G>2){7Y=z.7X(7Y,P,2)}C D.5k(7Y,L)},ed:B(cb,4T){A 7W=z.2p(cb,4T);if(P.G>2){7W=z.7X(7W,P,2)}C D.5k(L,7W)},5k:B(cb,eb){D.bM.Y([cb,eb]);if(D.2y>=0){D.7U()}C D},7U:B(){A bL=D.bM;A 4n=D.2y;A 1v=D.4R[4n];A 4S=D;A cb=L;1s((bL.G>0)&&(D.3M==0)){A f=bL.3a()[4n];if(!f){6c}1u{1v=f(1v);4n=((1v 1N 1O)?1:0);if(1v 1N z.30){cb=B(1v){4S.7V(1v);4S.3M--;if((4S.3M==0)&&(4S.2y>=0)){4S.7U()}};D.3M++}}1y(1G){1z.1K(1G);4n=1;1v=1G}}D.2y=4n;D.4R[4n]=1v;if((cb)&&(D.3M)){1v.9e(cb)}}})}if(!z.1h["z.X.2e"]){z.1h["z.X.2e"]=K;z.1Q("z.X.2e");z.5m=B(2e){1u{C 3u("("+2e+")")}1y(e){1z.1K(e);C 2e}};z.bK=B(2H){C("\\""+2H.2f(/(["\\\\])/g,"\\\\$1")+"\\"").2f(/[\\f]/g,"\\\\f").2f(/[\\b]/g,"\\\\b").2f(/[\\n]/g,"\\\\n").2f(/[\\t]/g,"\\\\t").2f(/[\\r]/g,"\\\\r")};z.hM="\\t";z.eq=B(it,4l,4P){4P=4P||"";A 4k=(4l?4P+z.hM:"");A 6b=(4l?"\\n":"");A 4Q=V(it);if(4Q=="1k"){C"1k"}I{if((4Q=="4J")||(4Q=="p1")){C it+""}I{if(it===L){C"L"}}}if(4Q=="3c"){C z.bK(it)}A 6d=P.2O;A 4m;if(V it.hL=="B"){4m=it.hL();if(it!==4m){C 6d(4m,4l,4k)}}if(V it.2e=="B"){4m=it.2e();if(it!==4m){C 6d(4m,4l,4k)}}if(z.2l(it)){A 1v=[];R(A i=0;i>=7R;t[x]=7R==4?17*c:c});t.a=1;C t};z.7P=B(a,M){A t=M||S z.1J();t.bz(2V(a[0]),2V(a[1]),2V(a[2]),2V(a[3]));if(2L(t.a)){t.a=1}C t.7Q()};z.hq=B(2H,M){A a=z.1J.hp[2H];C a&&z.7P(a,M)||z.ho(2H,M)||z.hn(2H,M)}}if(!z.1h["z.X"]){z.1h["z.X"]=K;z.1Q("z.X")}if(!z.1h["z.X.5Z"]){z.1h["z.X.5Z"]=K;z.1Q("z.X.5Z");(B(){A 1j=z.b2={2P:B(E,68,fp){if(!E){C}68=1j.4O(68);fp=1j.7G(68,fp);E.66(68,fp,U);C fp},3J:B(E,hm,hl){(E)&&(E.oF(1j.4O(hm),hl,U))},4O:B(1p){C(1p.2w(0,2)=="on"?1p.2w(2):1p)},7G:B(1p,fp){C(1p!="4b"?fp:B(e){C fp.2d(D,1j.4i(e,D))})},4i:B(H,oE){4w(H.Z){2X"4b":1j.7K(H);3f}C H},7K:B(H){H.oD=(H.3h?67.oC(H.3h):"")}};z.oB=B(H,hk){C 1j.4i(H,hk)};z.gY=B(H){H.7J();H.7I()};A 7O=z.3i;z.by=B(M,bx,hh,hg,hi){A hj=M&&(M.2t||M.oA||M.66);A bw=!hj?0:(!hi?1:2),l=[z.3i,1j,7O][bw];A h=l.2P(M,bx,z.2p(hh,hg));C[M,bx,h,bw]};z.bv=B(M,he,hd,hf){([z.3i,1j,7O][hf]).3J(M,he,hd)};z.5W={oz:8,gV:9,oy:12,ox:13,ow:16,ov:17,ou:18,gG:19,ot:20,os:27,or:32,b5:33,b4:34,gE:35,gF:36,b7:37,b9:38,b6:39,b8:40,gD:45,8S:46,oq:47,oo:91,om:92,ol:93,oj:96,oi:97,oh:98,og:99,oe:6D,od:oc,ob:oa,o9:o8,o7:o6,o5:o4,o3:bi,o2:o1,o0:nZ,nY:nX,nW:nV,nU:bk,gS:nT,gR:nS,gQ:nR,gP:nQ,gO:nP,gN:nO,gM:nN,gL:nM,gK:nL,gJ:nK,gI:nJ,gH:nI,nH:nG,nF:nE,nD:nC,gB:nB,gC:nA};if(z.1l){bf=B(e,5h){1u{C(e.3I=5h)}1y(e){C 0}};A 61=z.3i;if(!1o.nz){7O=61=z.gy={b3:[],2P:B(64,bu,hc){64=64||z.1W;A f=64[bu];if(!f||!f.2b){A d=z.gz();d.5V=f&&(7M.Y(f)-1);d.2b=[];f=64[bu]=d}C f.2b.Y(7M.Y(hc)-1)},3J:B(hb,ha,7N){A f=(hb||z.1W)[ha],l=f&&f.2b;if(f&&l&&7N--){63 7M[l[7N]];63 l[7N]}}};A 7M=61.b3}z.1x(1j,{2P:B(E,62,fp){if(!E){C}62=1j.4O(62);if(62=="h3"){A kd=E.bs;if(!kd||!kd.2b||!kd.h9){1j.2P(E,"bs",1j.h4);E.bs.h9=K}}C 61.2P(E,62,1j.7G(fp))},3J:B(E,h8,h7){61.3J(E,1j.4O(h8),h7)},4O:B(7L){C(7L.2w(0,2)!="on"?"on"+7L:7L)},ny:B(){},4i:B(H,4N){if(!H){A w=(4N)&&((4N.aD||4N.1q||4N).nx)||26;H=w.5Z}if(!H){C(H)}H.5V=H.br;H.bh=(4N||H.br);H.nw=H.nv;H.nu=H.nr;A bq=H.br,1e=(bq&&bq.aD)||1q;A bn=((z.1l<6)||(1e["aX"]=="aW"))?1e.3E:1e.5K;A bm=z.aB();H.nq=H.np+z.aH(bn.5I||0)-bm.x;H.nn=H.nm+(bn.5G||0)-bm.y;if(H.Z=="fk"){H.h6=H.nl}if(H.Z=="fj"){H.h6=H.nk}H.7I=1j.bc;H.7J=1j.ba;C 1j.h5(H)},h5:B(H){4w(H.Z){2X"4b":A c=("3h"in H?H.3h:H.3I);if(c==10){c=0;H.3I=13}I{if(c==13||c==27){c=0}I{if(c==3){c=99}}}H.3h=c;1j.7K(H);3f}C H},gZ:{bi:42,bk:47,h2:59,nj:43,ni:44,nh:45,ng:46,nf:47,60:96,h1:91,nb:92,na:93,h0:39},h4:B(H){A kp=H.bh.h3;if(!kp||!kp.2b){C}A k=H.3I;A bj=(k!=13)&&(k!=32)&&(k!=27)&&(k<48||k>90)&&(k<96||k>bk)&&(k60)&&(kh0);if(bj||H.5Y){A c=(bj?0:k);if(H.5Y){if(k==3||k==13){C}I{if(c>95&&c=65&&c<=90)){c+=32}I{c=1j.gZ[c]||c}}}}A 2x=1j.7H(H,{Z:"4b",2x:K,3h:c});kp.2d(H.bh,2x);H.bg=2x.bg;H.bd=2x.bd;bf(H,2x.3I)}},bc:B(){D.bg=K},ba:B(){D.n9=D.3I;if(D.5Y){bf(D,0)}D.bd=U}});z.gY=B(H){H=H||26.5Z;1j.bc.2d(H);1j.ba.2d(H)}}1j.7H=B(H,gX){A 2x=z.1x({},H,gX);1j.7K(2x);2x.7J=B(){H.7J()};2x.7I=B(){H.7I()};C 2x};if(z.2M){z.1x(1j,{4i:B(H,n8){4w(H.Z){2X"4b":A c=H.n7;if(c==3){c=99}c=((c<41)&&(!H.5X)?0:c);if((H.5Y)&&(!H.5X)&&(c>=65)&&(c<=90)){c+=32}C 1j.7H(H,{3h:c})}C H}})}if(z.3o){z.1x(1j,{4i:B(H,n6){4w(H.Z){2X"4b":A c=H.3h,s=H.5X,k=H.3I;k=k||gA[H.gW]||0;if(H.gW=="n5"){c=0}I{if((H.5Y)&&(c>0)&&(c<27)){c+=96}I{if(c==z.5W.gU){c=z.5W.gV;s=K}I{c=(c>=32&&c gh",E).1n(B(i){i.1c.7E=i.1c.7E.2f(/gk:[^;]*;/i,"")})}}I{A o="mh(mg="+(7D*6D)+")";E.1c.3T=o}if(E.gj.1M()=="gi"){z.1r("> gh",E).1n(B(i){i.1c.3T=o})}C 7D}:B(E,gg){C E.1c.2W=gg});A 5Q={3n:K,58:K,2g:K,5J:K};A gd=B(E,Z,5P){Z=Z.1M();if(5Q[Z]===K){C z.4g(E,5P)}I{if(5Q[Z]===U){C 5P}I{if((Z.T("mf")>=0)||(Z.T("md")>=0)||(Z.T("3n")>=0)||(Z.T("58")>=0)||(Z.T("5q")>=0)||(Z.T("mc")>=0)||(Z.T("ma")>=0)){5Q[Z]=K;C z.4g(E,5P)}I{5Q[Z]=U;C 5P}}}};z.1c=B(E,5O,aT){A n=z.1D(E),F=P.G,op=(5O=="2W");if(F==3){C op?z.gf(n,aT):n.1c[5O]=aT}if(F==2&&op){C z.ge(n)}A s=z.3F(n);C(F==1)?s:gd(n,5O,s[5O])};z.7A=B(n,gc){A s=gc||1E(n),px=z.4g,l=px(n,s.m9),t=px(n,s.m8);C{l:l,t:t,w:l+px(n,s.m7),h:t+px(n,s.m6)}};z.5N=B(n,gb){A ne="7C",px=z.4g,s=gb||1E(n),bl=(s.m5!=ne?px(n,s.m4):0),bt=(s.m3!=ne?px(n,s.m2):0);C{l:bl,t:bt,w:bl+(s.m1!=ne?px(n,s.m0):0),h:bt+(s.lZ!=ne?px(n,s.lY):0)}};z.aN=B(n,ga){A s=ga||1E(n),p=z.7A(n,s),b=z.5N(n,s);C{l:p.l+b.l,t:p.t+b.t,w:p.w+b.w,h:p.h+b.h}};z.aM=B(n,g9){A s=g9||1E(n),px=z.4g,l=px(n,s.lX),t=px(n,s.lW),r=px(n,s.lV),b=px(n,s.lU);if(z.3o&&(s.ax!="fU")){r=l}C{l:l,t:t,w:l+r,h:t+b}};z.au=B(E,g8){A s=g8||1E(E),me=z.aM(E,s);A l=E.fT-me.l,t=E.fS-me.t;if(z.7B){A aS=2k(s.2g),aR=2k(s.5J);if(!2L(aS)&&!2L(aR)){l=aS,t=aR}I{A p=E.1L;if(p&&p.1c){A aQ=1E(p);if(aQ.lT!="lS"){A be=z.5N(p,aQ);l+=be.l,t+=be.t}}}}I{if(z.2M){A p=E.1L;if(p){A be=z.5N(p);l-=be.l,t-=be.t}}}C{l:l,t:t,w:E.6v+me.w,h:E.8D+me.h}};z.aK=B(E,g7){A s=g7||1E(E),pe=z.7A(E,s),be=z.5N(E,s),w=E.aF,h;if(!w){w=E.6v,h=E.8D}I{h=E.lR,be.w=be.h=0}if(z.2M){pe.l+=be.l;pe.t+=be.t}C{l:pe.l,t:pe.t,w:w-pe.w-be.w,h:h-pe.h-be.h}};z.lQ=B(E,g6){A s=g6||1E(E),pe=z.7A(E,s),cb=z.aK(E,s);C{l:cb.l-pe.l,t:cb.t-pe.t,w:cb.w+pe.w,h:cb.h+pe.h}};z.aL=B(E,l,t,w,h,u){u=u||"px";4G(E.1c){if(!2L(l)){2g=l+u}if(!2L(t)){5J=t+u}if(w>=0){3n=w+u}if(h>=0){58=h+u}}};z.aO=B(E){A n=E.5w;C(z.aP=="g5-3G")||(n=="lP")||(n=="lO")};z.fX=B(E,7z,7y,g4){A bb=z.aO(E);if(bb){A pb=z.aN(E,g4);if(7z>=0){7z+=pb.w}if(7y>=0){7y+=pb.h}}z.aL(E,g3,g3,7z,7y)};z.fY=B(E,g1,g0,5M,5L,g2){A s=g2||z.3F(E);A bb=z.aO(E),pb=bb?fZ:z.aN(E,s),mb=z.aM(E,s);if(5M>=0){5M=2Y.5q(5M-pb.w-mb.w,0)}if(5L>=0){5L=2Y.5q(5L-pb.h-mb.h,0)}z.aL(E,g1,g0,5M,5L)};A fZ={l:0,t:0,w:0,h:0};z.lN=B(E,3G){A n=z.1D(E),s=1E(n),b=3G;C!b?z.au(n,s):z.fY(n,b.l,b.t,b.w,b.h,s)};z.lM=B(E,3G){A n=z.1D(E),s=1E(n),b=3G;C!b?z.aK(n,s):z.fX(n,b.w,b.h,s)};A 5H=B(E,1a){if(!(E=(E||0).1L)){C 0}A 1U,aJ=0,2h=z.3E();1s(E&&E.1c){if(1E(E).ax=="lL"){C 0}1U=E[1a];if(1U){aJ+=1U-0;if(E==2h){3f}}E=E.1L}C aJ};z.fQ=B(){A 2h=z.3E();A 3g=z.1W;A de=z.1e.5K;C{y:(3g.lK||de.5G||2h.5G||0),x:(3g.lJ||z.aH(de.5I)||2h.5I||0)}};z.aG=B(){C V z.aI=="1k"?(z.aI=z.3F(z.3E()).lI=="lH"):z.aI};z.aB=B(){A de=z.1e.5K;if(z.1l>=7){C{x:de.aC().2g,y:de.aC().5J}}I{C{x:z.aG()||26.am==26?de.fW:de.6v-de.aF-de.fW,y:de.lG}}};z.aH=B(aE){if(z.1l&&!z.aG()){A de=z.1e.5K;C aE+de.aF-de.lF}C aE};z.fP=B(E,aw){A ay=E.aD;A J={x:0,y:0};A 7w=U;A db=z.3E();if(z.1l){A aA=E.aC();A az=z.aB();J.x=aA.2g-az.x;J.y=aA.5J-az.y}I{if(ay["fV"]){A bo=ay.fV(E);J.x=bo.x-5H(E,"5I");J.y=bo.y-5H(E,"5G")}I{if(E["fR"]){7w=K;A 7x;if(z.3o&&(1E(E).ax=="fU")&&(E.1L==db)){7x=db}I{7x=db.1L}if(E.1L!=db){A nd=E;if(z.2M){nd=db}J.x-=5H(nd,"5I");J.y-=5H(nd,"5G")}A 4f=E;do{A n=4f["fT"];if(!z.2M||n>0){J.x+=2L(n)?0:n}A m=4f["fS"];J.y+=2L(m)?0:m;4f=4f.fR}1s((4f!=7x)&&4f)}I{if(E["x"]&&E["y"]){J.x+=2L(E.x)?0:E.x;J.y+=2L(E.y)?0:E.y}}}}if(7w||aw){A av=z.fQ();A m=7w?(!aw?-1:0):1;J.y+=m*av.y;J.x+=m*av.x}C J};z.af=B(E,fO){A n=z.1D(E),s=1E(n),mb=z.au(n,s);A at=z.fP(n,fO);mb.x=at.x;mb.y=at.y;C mb}})();z.fL=B(E,fN){C((" "+E.3A+" ").T(" "+fN+" ")>=0)};z.7s=B(E,ar){A 7v=E.3A;if((" "+7v+" ").T(" "+ar+" ")<0){E.3A=7v+(7v?" ":"")+ar}};z.7r=B(E,fM){A t=z.7g((" "+E.3A+" ").2f(" "+fM+" "," "));if(E.3A!=t){E.3A=t}};z.lE=B(E,aq,7u){if(V 7u=="1k"){7u=!z.fL(E,aq)}z[7u?"7s":"7r"](E,aq)}}if(!z.1h["z.X.1H"]){z.1h["z.X.1H"]=K;z.1Q("z.X.1H");(B(){A d=z;z.1H=B(){A F=P;if((F.G==1)&&(V F[0]=="4J")){D.G=eK(F[0])}I{if(F.G){d.1n(F,B(i){D.Y(i)},D)}}};z.1H.1C=S 4e;if(d.1l){A fK=B(al){C("A a2 = am."+al+"; "+"A ap = 4e.1C; "+"A ao = a2.1C; "+"R(A x in ao){ ap[x] = ao[x]; } "+"am."+al+" = 4e; ")};A fI=fK("z.1H");A aj=26.lD();aj.1q.fJ(""+fI+"");aj.lC(1,1,1,1)}z.4M(z.1H,{T:B(fH,fG){C d.T(D,fH,fG)},31:B(lB,lA){A aa=d.4d(P);aa.ae(D);C d.31.14(d,aa)},ah:B(fF,fE){C d.ah(D,fF,fE)},ag:B(fD,fC){C d.ag(D,fD,fC)},1n:B(fB,fA){d.1n(D,fB,fA);C D},23:B(7t,M){C d.23(D,7t,M,d.1H)},af:B(){C d.23(D,d.af)},1c:B(lz,ly){A aa=d.4d(P);aa.ae(D[0]);A s=d.1c.14(d,aa);C(P.G>1)?D:s},lx:B(lw,lv){A aa=d.4d(P);aa.ae(L);A s=D.23(B(i){aa[0]=i;C d.1c.14(d,aa)});C(P.G>1)?D:s},7s:B(fz){C D.1n(B(i){z.7s(i,fz)})},7r:B(fy){C D.1n(B(i){z.7r(i,fy)})},5E:B(fw,7q){A 1m=d.1r(fw)[0];7q=7q||"72";R(A x=0;x=0){if(i[x]<1d){1d=i[x]}}}C(1d<0)?ql:1d};A 6X=B(7l){A i=2I(7l);if(i[0]!=-1){C 7l.21(i[0]+1,a0(7l,1))}I{C""}};A 5r=B(7k){A 5D;A i=2I(7k);if((i[0]==0)||(i[1]==0)){5D=0}I{5D=a0(7k,0)}C((5D>0)?7k.3b(0,5D).1M():"*")};A fg=B(Q){A J=-1;R(A x=0;x=0){if((1S>J)||(J==-1)){J=1S}}}C J};A 9H=B(7i){A i=2I(7i);if(-1==i[1]){C""}A di=i[1]+1;A 7j=fg(i.2w(2));if(di<7j){C 7i.21(di,7j)}I{if(-1==7j){C 7i.3b(di)}I{C""}}};A f3=[{1i:"|=",1f:B(15,fe){C"[5z(3U(\' \',@"+15+",\' \'), \' "+fe+"-\')]"}},{1i:"~=",1f:B(15,fd){C"[5z(3U(\' \',@"+15+",\' \'), \' "+fd+" \')]"}},{1i:"^=",1f:B(15,fb){C"[li-4G(@"+15+", \'"+fb+"\')]"}},{1i:"*=",1f:B(15,fa){C"[5z(@"+15+", \'"+fa+"\')]"}},{1i:"$=",1f:B(15,9Z){C"[21(@"+15+", 3c-G(@"+15+")-"+(9Z.G-1)+")=\'"+9Z+"\']"}},{1i:"!=",1f:B(15,f9){C"[3O(@"+15+"=\'"+f9+"\')]"}},{1i:"=",1f:B(15,f8){C"[@"+15+"=\'"+f8+"\']"}}];A 9C=B(9Y,3Z,f7,f6){A 49;A i=2I(3Z);if(i[2]>=0){A 4L=3Z.T("]",i[2]);A 29=3Z.21(i[2]+1,4L);1s(29&&29.G){if(29.2s(0)=="@"){29=29.2w(1)}49=L;R(A x=0;x<9Y.G;x++){A 1S=9Y[x];A 7h=29.T(1S.1i);if(7h>=0){A 15=29.21(0,7h);A 4a=29.21(7h+1S.1i.G);if((4a.2s(0)=="\\"")||(4a.2s(0)=="\'")){4a=4a.21(1,4a.G-1)}49=1S.1f(d.7g(15),d.7g(4a));3f}}if((!49)&&(29.G)){49=f7(29)}if(49){f6(49)}29=L;A 7f=3Z.T("[",4L);if(0<=7f){4L=3Z.T("]",7f);if(0<=4L){29=3Z.21(7f+1,4L)}}}}};A f0=B(f5){A 4K=".";A 7e=f5.1A(" ");1s(7e.G){A 2K=7e.3a();A 7d;if(2K==">"){7d="/";2K=7e.3a()}I{7d="//"}A f4=5r(2K);4K+=7d+f4;A id=6X(2K);if(id.G){4K+="[@id=\'"+id+"\'][1]"}A cn=9H(2K);if(cn.G){A 9X=" ";if(cn.2s(cn.G-1)=="*"){9X="";cn=cn.3b(0,cn.G-1)}4K+="[5z(3U(\' \',@9P,\' \'), \' "+cn+9X+"\')]"}9C(f3,2K,B(f2){C"[@"+f2+"]"},B(f1){4K+=f1})}C 4K};A 7a={};A eC=B(28){if(7a[28]){C 7a[28]}A 1e=d.1e;A 9W=f0(28);A 4H=B(9V){A J=[];A 7b;1u{7b=1e.9x(9W,9V,L,lh.lg,L)}1y(e){1z.1K("lf in le:",9W,"lc:",9V);1z.1K(e)}A 7c=7b.eZ();1s(7c){J.Y(7c);7c=7b.eZ()}C J};C 7a[28]=4H};A 5x={};A 9B={};A 3y=B(79,78){if(!79){C 78}if(!78){C 79}C B(){C 79.14(26,P)&&78.14(26,P)}};A 75=B(9U,3Y,5B,2J){A 2v=2J+1;A 76=(3Y.G==2v);A 2K=3Y[2J];if(2K==">"){A 77=9U.3W;if(!77.G){C}2v++;76=(3Y.G==2v);A 4H=6O(3Y[2J+1]);R(A x=0,11;x<77.G,11=77[x];x++){if(4H(11)){if(76){5B.Y(11)}I{75(11,3Y,5B,2v)}}}}A 5C=6U(2K)(9U);if(76){1s(5C.G){5B.Y(5C.3a())}}I{1s(5C.G){75(5C.3a(),3Y,5B,2v)}}};A eE=B(9T,eY){A J=[];A x=9T.G-1,11;1s(11=9T[x--]){75(11,eY,J,0)}C J};A 6O=B(3D){if(5x[3D]){C 5x[3D]}A ff=L;A 9S=5r(3D);if(9S!="*"){ff=3y(ff,B(N){C((N.2t==1)&&(9S==N.5w.1M()))})}A 9R=6X(3D);if(9R.G){ff=3y(ff,B(N){C((N.2t==1)&&(N.id==9R))})}if(2Y.5q.14(D,2I(3D).2w(1))>=0){ff=3y(ff,9z(3D))}C 5x[3D]=ff};A 5y=B(E){A pn=E.1L;A 9Q=pn.3W;A 2v=-1;A 3C=pn.5A;if(!3C){C 2v}A ci=E["eW"];A cl=pn["eX"];if(((V cl=="4J")&&(cl!=9Q.G))||(V ci!="4J")){pn["eX"]=9Q.G;A 2J=1;do{if(3C===E){2v=2J}if(3C.2t==1){3C["eW"]=2J;2J++}3C=3C.71}1s(3C)}I{2v=ci}C 2v};A lb=0;A 3X=B(N,15){A 74="";if(15=="9P"){C N.3A||74}if(15=="R"){C N.la||74}C N.5t(15,2)||74};A eH=[{1i:"|=",1f:B(15,9O){A eV=" "+9O+"-";C B(N){A ea=" "+(N.5t(15,2)||"");C((ea==9O)||(ea.T(eV)==0))}}},{1i:"^=",1f:B(15,eU){C B(N){C(3X(N,15).T(eU)==0)}}},{1i:"*=",1f:B(15,eT){C B(N){C(3X(N,15).T(eT)>=0)}}},{1i:"~=",1f:B(15,eS){A 9N=" "+eS+" ";C B(N){A ea=" "+3X(N,15)+" ";C(ea.T(9N)>=0)}}},{1i:"$=",1f:B(15,73){A 9N=" "+73;C B(N){A ea=" "+3X(N,15);C(ea.31(73)==(ea.G-73.G))}}},{1i:"!=",1f:B(15,eR){C B(N){C(3X(N,15)!=eR)}}},{1i:"=",1f:B(15,eQ){C B(N){C(3X(N,15)==eQ)}}}];A 9E=[{1i:"9M-9K",1f:B(1p,l9){C B(N){if(N.2t!=1){C U}A fc=N.eP;1s(fc&&(fc.2t!=1)){fc=fc.eP}C(!fc)}}},{1i:"72-9K",1f:B(1p,l8){C B(N){if(N.2t!=1){C U}A nc=N.71;1s(nc&&(nc.2t!=1)){nc=nc.71}C(!nc)}}},{1i:"l7",1f:B(1p,l6){C B(N){A cn=N.3W;A eO=N.3W.G;R(A x=eO-1;x>=0;x--){A nt=cn[x].2t;if((nt==1)||(nt==3)){C U}}C K}}},{1i:"5z",1f:B(1p,eN){C B(N){C(N.9L.T(eN)>=0)}}},{1i:"3O",1f:B(1p,eM){A eL=6O(eM);C B(N){C(!eL(N))}}},{1i:"l5-9K",1f:B(1p,2u){A pi=eK;if(2u=="l4"){C B(N){C(((5y(N))%2)==1)}}I{if((2u=="2n")||(2u=="l3")){C B(N){C((5y(N)%2)==0)}}I{if(2u.T("l2+")==0){A 70=pi(2u.3b(3));C B(N){C(N.1L.3W[70-1]===N)}}I{if((2u.T("n+")>0)&&(2u.G>3)){A 9J=2u.1A("n+",2);A eJ=pi(9J[0]);A 2J=pi(9J[1]);C B(N){C((5y(N)%eJ)==2J)}}I{if(2u.T("n")==-1){A 70=pi(2u);C B(N){C(5y(N)==70)}}}}}}}}];A 9z=B(3e){A 9I=(9B[3e]||5x[3e]);if(9I){C 9I}A ff=L;A i=2I(3e);if(i[0]>=0){A 24=5r(3e);if(24!="*"){ff=3y(ff,B(N){C(N.5w.1M()==24)})}}A 5u;A 3B=9H(3e);if(3B.G){A 9F=3B.2s(3B.G-1)=="*";if(9F){3B=3B.3b(0,3B.G-1)}A re=S 9G("(?:^|\\\\s)"+3B+(9F?".*":"")+"(?:\\\\s|$)");ff=3y(ff,B(N){C re.6Z(N.3A)})}if(i[3]>=0){A 3z=3e.3b(i[3]+1);A 9D="";A 5v=3z.T("(");A 6Y=3z.31(")");if((0<=5v)&&(0<=6Y)&&(6Y>5v)){9D=3z.21(5v+1,6Y);3z=3z.3b(0,5v)}5u=L;R(A x=0;x<9E.G;x++){A 1S=9E[x];if(1S.1i==3z){5u=1S.1f(3z,9D);3f}}if(5u){ff=3y(ff,5u)}}A eG=(d.1l)?B(5s){A eI=5s.1M();C B(N){C N[5s]||N[eI]}}:B(5s){C B(N){C(N&&N.5t&&N.l1(5s))}};9C(eH,3e,eG,B(eF){ff=3y(ff,eF)});if(!ff){ff=B(){C K}}C 9B[3e]=ff};A 6W={};A 6U=B(3d,1B){A 9A=6W[3d];if(9A){C 9A}A i=2I(3d);A id=6X(3d);if(i[0]==0){C 6W[3d]=B(1B){C[d.1D(id)]}}A 9y=9z(3d);A 5p;if(i[0]>=0){5p=B(1B){A 11=d.1D(id);if(9y(11)){C[11]}}}I{A 3V;A 24=5r(3d);if(2Y.5q.14(D,2I(3d))==-1){5p=B(1B){A J=[];A 11,x=0,3V=1B.4I(24);1s(11=3V[x++]){J.Y(11)}C J}}I{5p=B(1B){A J=[];A 11,x=0,3V=1B.4I(24);1s(11=3V[x++]){if(9y(11)){J.Y(11)}}C J}}}C 6W[3d]=5p};A l0={};A 5o={">":B(1B){A J=[];A 11,x=0,3V=1B.3W;1s(11=3V[x++]){if(11.2t==1){J.Y(11)}}C J}};A 9w=B(6V){if(0>6V.T(" ")){C 6U(6V)}A eD=B(1B){A 6S=6V.1A(" ");A 6T;if(6S[0]==">"){6T=[1B]}I{6T=6U(6S.3a())(1B)}C eE(6T,6S)};C eD};A 9v=((1q["9x"]&&!d.3o)?B(3x){A 6R=3x.1A(" ");if((1q["9x"])&&(3x.T(":")==-1)&&((K))){if(((6R.G>2)&&(3x.T(">")==-1))||(6R.G>3)||(3x.T("[")>=0)||((1==6R.G)&&(0<=3x.T(".")))){C eC(3x)}}C 9w(3x)}:9w);A ey=B(3w){if(5o[3w]){C 5o[3w]}if(0>3w.T(",")){C 5o[3w]=9v(3w)}I{A eB=3w.1A(/\\s*,\\s*/);A 4H=B(1B){A eA=0;A J=[];A 6Q;1s(6Q=eB[eA++]){J=J.3U(9v(6Q,6Q.T(" "))(1B))}C J};C 5o[3w]=4H}};A 5n=0;A ez=B(Q){A J=S d.1H();if(!Q){C J}if(Q[0]){J.Y(Q[0])}if(Q.G<2){C J}5n++;Q[0]["9u"]=5n;R(A x=1,11;11=Q[x];x++){if(Q[x]["9u"]!=5n){J.Y(11)}11["9u"]=5n}C J};d.1r=B(6P,1B){if(V 6P!="3c"){C S d.1H(6P)}if(V 1B=="3c"){1B=d.1D(1B)}C ez(ey(6P)(1B||d.1e))};d.9t=B(ex,9s){A 9r=S d.1H();A ff=(9s)?6O(9s):B(){C K};R(A x=0,11;11=ex[x];x++){if(ff(11)){9r.Y(11)}}C 9r}})()}if(!z.1h["z.X.1b"]){z.1h["z.X.1b"]=K;z.1Q("z.X.1b");z.6K=B(ew){A J={};A iq="kZ[Z!=9q][Z!=kY][Z!=et][Z!=kX][Z!=kW], kV, kU";z.1r(iq,ew).3T(B(E){C(!E.kT)}).1n(B(1m){A 3v=1m.1p;A Z=(1m.Z||"").1M();if((Z=="kS")||(Z=="kR")){if(1m.kQ){J[3v]=1m.1Z}}I{if(1m.kP){A ev=J[3v]=[];z.1r("kO[kN]",1m).1n(B(eu){ev.Y(eu.1Z)})}I{J[3v]=1m.1Z;if(Z=="et"){J[3v+".x"]=J[3v+".y"]=J[3v].x=J[3v].y=0}}}});C J};z.9h=B(23){A ec=kM;A J="";A es={};R(A x in 23){if(23[x]!=es[x]){if(z.2l(23[x])){R(A y=0;y<23[x].G;y++){J+=ec(x)+"="+ec(23[x][y])+"&"}}I{J+=ec(x)+"="+ec(23[x])+"&"}}}if((J.G)&&(J.2s(J.G-1)=="&")){J=J.3b(0,J.G-1)}C J};z.kL=B(er){C z.9h(z.6K(er))};z.kK=B(ep){C z.eq(z.6K(ep))};z.kJ=B(2H){A J={};A qp=2H.1A("&");A dc=kI;z.1n(qp,B(1m){if(1m.G){A 9p=1m.1A("=");A 1p=dc(9p.3a());A 1U=dc(9p.22("="));if(z.1R(J[1p])){J[1p]=[J[1p]]}if(z.2l(J[1p])){J[1p].Y(1U)}I{J[1p]=1U}}});C J};z.e1=U;z.e6={"9g":B(1b){C 1b.2G},"2e":B(1b){if(!1o.eo){1z.1K("kH kG kF a kE of 9g/2e-6M-9m"+" 4F kD kC kB kA 4G en kz"+" (ky 1o.eo=K 4F kx kw D kv)")}C z.5m(1b.2G)},"2e-6M-ku":B(1b){A 6N=1b.2G;A 9o=6N.T("/*");A 9n=6N.31("*/");if((9o==-1)||(9n==-1)){C z.5m(1b.2G)}C z.5m(6N.21(9o+2,9n))},"2e-6M-9m":B(1b){A 6L=1b.2G;A 9l=6L.T("/*");A 9k=6L.31("*/");if((9l==-1)||(9k==-1)){1z.1K("kt en ks\'t 6M 9m!");C""}C z.5m(6L.21(9l+2,9k))},"kr":B(1b){C z.3u(1b.2G)},"kq":B(1b){if(z.1l&&!1b.el){z.1n(["ko","em","kn","km"],B(i){1u{A 1e=S 9j(kl[i]+".kk");1e.kj=U;1e.ki(1b.2G);C 1e}1y(e){}})}I{C 1b.el}}};(B(){z.e5=B(F,ej,ei,eh){A 2F={};2F.F=F;A 6J=L;if(F.3R){A 3R=z.1D(F.3R);A 9i=3R.kh("kg");2F.2E=F.2E||(9i?9i.1Z:L);6J=z.6K(3R)}I{2F.2E=F.2E}A 5l=[{}];if(6J){5l.Y(6J)}if(F.5g){5l.Y(F.5g)}if(F.ek){5l.Y({"z.ek":S 5d().8O()})}2F.1r=z.9h(z.1x.14(L,5l));2F.9d=F.9d||"9g";A d=S z.30(ej);d.5k(ei,B(eg){C eh(eg,d)});A ld=F.4E;if(ld&&z.1Y(ld)){d.ef(B(ee){C ld.2d(F,ee,2F)})}A 1G=F.9f;if(1G&&z.1Y(1G)){d.ed(B(e9){C 1G.2d(F,e9,2F)})}A 6I=F.kf;if(6I&&z.1Y(6I)){d.9e(B(e8){C 6I.2d(F,e8,2F)})}d.1F=2F;C d};A e4=B(O){O.e0=K;A 1b=O.1F.1b;if(V 1b.e7=="B"){1b.e7()}};A e3=B(O){C z.e6[O.1F.9d](O.1F.1b)};A e2=B(9c,O){1z.1K(9c);C 9c};A 3Q=B(F){A O=z.e5(F,e4,e3,e2);O.1F.1b=z.9b(O.1F.F);C O};A 5j=L;A 3t=[];A 94=B(){A dZ=(S 5d()).dU();if(!z.e1){z.1n(3t,B(4D,6H){if(!4D){C}A O=4D.O;1u{if(!O||O.e0||!4D.dT(O)){3t.3S(6H,1);C}if(4D.dR(O)){3t.3S(6H,1);4D.dP(O)}I{if(O.9a){if(O.9a+(O.1F.F.6G||0)0){5c(z.2p(D,B(){D.5b(L,8R)}),d);C D}D.4A=S 5d().8O();if(D.2Z){D.4A-=D.8Q*D.2o}D.8N=D.4A+D.8Q;D.2D=K;D.2Z=U;A 8P=D.2C.4x(D.2o);if(!D.2o){if(!D.4y){D.4y=D.4z}D.3q("dt",[8P])}D.3q("ds",[8P]);D.8M();C D},jS:B(){5e(D.3r);if(!D.2D){C D}D.2Z=K;D.3q("dr",[D.2C.4x(D.2o)]);C D},jR:B(dq,dp){5e(D.3r);D.2D=D.2Z=K;D.2o=dq*6D;if(dp){D.5b()}C D},jQ:B(dn){if(!D.3r){C}5e(D.3r);if(dn){D.2o=1}D.3q("dm",[D.2C.4x(D.2o)]);D.2D=D.2Z=U;C D},3N:B(){if(D.2D){C D.2Z?"3M":"jP"}C"jO"},8M:B(){5e(D.3r);if(D.2D){A dl=S 5d().8O();A 2q=(dl-D.4A)/(D.8N-D.4A);if(2q>=1){2q=1}D.2o=2q;if(D.5a){2q=D.5a(2q)}D.3q("8B",[D.2C.4x(2q)]);if(2q<1){D.3r=5c(z.2p(D,"8M"),D.dj)}I{D.2D=U;if(D.4z>0){D.4z--;D.5b(L,K)}I{if(D.4z==-1){D.5b(L,K)}I{if(D.4y){D.4z=D.4y;D.4y=0}}}D.2o=0;D.3q("dh")}}C D}});(B(){A df=B(E){if(z.1l){A ns=E.1c;if(!ns.8L.G&&z.1c(E,"8L")=="dg"){ns.8L="1"}if(!ns.3n.G&&z.1c(E,"3n")=="8K"){ns.3n="8K"}}};z.6C=B(F){if(V F.1d=="1k"){2m S 1O("z.6C jN an 1d 1Z")}F.E=z.1D(F.E);A 3p=z.1x({6w:{}},F);A 8J=(3p.6w.2W={});8J.1w=(V 3p.1w=="1k")?B(){C 2V(z.1c(3p.E,"2W"))}:3p.1w;8J.1d=3p.1d;A 2U=z.6y(3p);z.2c(2U,"6x",L,B(){df(3p.E)});C 2U};z.8I=B(F){C z.6C(z.1x({1d:1},F))};z.8H=B(F){C z.6C(z.1x({1d:0},F))};if(z.6B&&!z.3o){z.8E=B(n){C 2k("0.5")+((2Y.da((n+2k("1.5"))*2Y.d9))/2)}}I{z.8E=B(n){C 0.5+((2Y.da((n+1.5)*2Y.d9))/2)}}A d4=B(6A){D.8G=6A;R(A p in 6A){A 1a=6A[p];if(1a.1w 1N z.1J){1a.d7=S z.1J()}}D.4x=B(r){A J={};R(A p in D.8G){A 1a=D.8G[p];A 6z=L;if(1a.1w 1N z.1J){6z=z.d8(1a.1w,1a.1d,r,1a.d7).8F()}I{if(!z.2l(1a.1w)){6z=((1a.1d-1a.1w)*r)+1a.1w+(p!="2W"?1a.jM||"px":"")}}J[p]=6z}C J}};z.6y=B(F){F.E=z.1D(F.E);if(!F.5a){F.5a=z.8E}A 2U=S z.d6(F);z.2c(2U,"6x",2U,B(){A pm={};R(A p in D.6w){A 1a=pm[p]=z.1x({},D.6w[p]);if(z.1Y(1a.1w)){1a.1w=1a.1w()}if(z.1Y(1a.1d)){1a.1d=1a.1d()}A d5=(p.1M().T("jL")>=0);B 8C(E,p){4w(p){2X"58":C E.8D;2X"3n":C E.6v}A v=z.1c(E,p);C(p=="2W")?2V(v):2k(v)};if(V 1a.1d=="1k"){1a.1d=8C(D.E,p)}I{if(V 1a.1w=="1k"){1a.1w=8C(D.E,p)}}if(d5){1a.1w=S z.1J(1a.1w);1a.1d=S z.1J(1a.1d)}I{1a.1w=(p=="2W")?2V(1a.1w):2k(1a.1w)}}D.2C=S d4(pm)});z.2c(2U,"8B",2U,B(8A){R(A s in 8A){z.1c(D.E,s,8A[s])}});C 2U}})()}',62,1711,'|||||||||||||||||||||||||||||||||||dojo|var|function|return|this|node|args|length|evt|else|ret|true|null|obj|elem|dfd|arguments|arr|for|new|indexOf|false|typeof||_base|push|type||te|||apply|attr|||||prop|xhr|style|end|doc|match|uri|_hasResource|key|del|undefined|isIE|item|forEach|djConfig|name|document|query|while|_66|try|res|start|mixin|catch|console|split|root|prototype|byId|gcs|ioArgs|err|NodeList|_p|Color|debug|parentNode|toLowerCase|instanceof|Error|constructor|provide|isString|ta|255|val|_a|global|_69|isFunction|value||substring|join|map|tn||window||path|_343|_220|_listeners|connect|call|json|replace|left|_b|toString|128|parseFloat|isArray|throw||_percent|hitch|step|declare|charAt|nodeType|_3c3|nidx|slice|faux|fired|_c4|_7e|loc|curve|_active|url|_44c|responseText|str|_312|idx|tqp|isNaN|isOpera|_22d|callee|add|_18b|_f8|_e2|_41|anim|Number|opacity|case|Math|_paused|Deferred|lastIndexOf|||||||||shift|substr|string|_3e7|_3ce|break|_w|charCode|_listener|_d5|_c5|authority|_49|width|isSafari|_49e|fire|_timer|_47b|_465|eval|_in|_40c|_409|_362|_3d9|className|_3d5|_386|_37a|body|getComputedStyle|box|_221|keyCode|remove|_8d|_46|paused|status|not|_478|_461|form|splice|filter|concat|tret|childNodes|_38b|_367|_33d||||||||||_340|_348|keypress|appendChild|_toArray|Array|_2b0|_toPixelValue|ref|_fixEvent|_19f|_14c|_14a|_150|_141|declaredClass|_d4|_99|_Url|_83|scheme|_67|_3d|switch|getValue|_startRepeatCount|repeat|_startTime|_47e|cancel|tif|load|to|with|tf|getElementsByTagName|number|_34c|_342|extend|_1e3|_normalizeEventName|_14b|_14e|results|self|cbfn|_f9|_d8|_b2|src|_88|dav||baseUrl|fragment|_loadedModules|_44|_43|_loaders|mll|height||easing|play|setTimeout|Date|clearTimeout|hdr|content|code|errback|_464|addCallbacks|_450|fromJson|_413|_3fc|_3ee|max|_31e|cond|getAttribute|_3d4|obi|tagName|_360|_381|contains|firstChild|_368|_372|_320|place|_2fa|scrollTop|_299|scrollLeft|top|documentElement|_288|_287|_getBorderExtents|_23f|_23d|_239|_218|_216|_211|eles|target|keys|shiftKey|ctrlKey|event|192|iel|_1db|delete|_1cf||addEventListener|String|_1af|_157|array|_14d|continue|_14f|_137|_11f|_106|_findMethod|has|_delegate|_dc|_d3|loaded|_9a|_loadInit|_inFlightCount|getObject|tv|_4f|_postLoad|_2d|offsetWidth|properties|beforeBegin|animateProperty|_4ad|_4a6|isKhtml|_fade|100|headers|readyState|timeout|_469|_457|_44d|formToObject|_441|comment|_43d|_36f|_419|tp|_40a|_406|_407|_373|_403|_3e6|_31b|cbi|test|_3c7|nextSibling|last|_3a1|_38e|_365|_36b|ecn|_364|_363|_356|_35e|_35f|_34f|_34d|_349|trim|tci|_328|_32b|_31f|_31c|_anim|_300|_2ff|_2f5|_2e7|removeClass|addClass|func|_2c4|cls|_2a9|_2ae|_280|_27f|_getPadExtents|isMoz|none|_233|cssText|_214|_fixCallback|_synthesizeEvent|stopPropagation|preventDefault|_setKeyChar|_1e1|ieh|_1d7|_1be|colorFromArray|sanitize|bits|rgb|_156|_fire|_resback|_13d|partial|_13a|silentlyCancelled|_topics|_127|_f1|_f0|superclass|_ec|_e3|mct|setObject|_bf|_b3|object|require|_92|_khtmlTimer|location|XMLHTTP|locale|dua|_71|_modulePrefixes|_55|_loadModule|_51|_50|_4e|pop|_3f|_callLoaded|_unloaders|_loadNotifying|_loadedUrls|_27|_24|_1d|_5|_4b7|onAnimate|getStyle|offsetHeight|_defaultEasing|toCss|_properties|fadeOut|fadeIn|_49f|auto|zoom|_cycle|_endTime|valueOf|_494|duration|_492|DELETE|_ioAddQueryToUrl|putData|contentType|password|user|_isDocumentOk|application|||||_466||||||startTime|_xhrObj|_45f|handleAs|addBoth|error|text|objectToQuery|_44f|ActiveXObject|_443|_442|filtered|_43f|_43e|_437|file|tnl|_41c|_filterQueryResult|_zipIdx|_408|_402|evaluate|_3ed|_380|fHit|_361|_33b|_3da|_3ab|_3d6|RegExp|_327|_3cf|_3c9|child|innerHTML|first|tval|_391|class|pnc|_37e|_37c|_375|_366|_35c|_35a|_353|_33c|_336|_314|||_315|_oe|_307|_309|cloneNode|after|createElement||_2f8|_2ef|_2ee|unshift|coords|some|every||_2cb|script|_2c9|parent||a2p||_2c3|_2bd||abs|_getMarginBox|_2b3|_2a6|position|_2a7|_2ac|_2ab|_getIeDocumentElementOffset|getBoundingClientRect|ownerDocument|_2a3|clientWidth|_isBodyLtr|_fixIeBiDiScrollLeft|_bodyLtr|_29d|_getContentBox|_setBox|_getMarginExtents|_getPadBorderExtents|_usesBorderBox|boxModel|pcs|st|sl|_240|runtimeStyle|_dcm|BackCompat|compatMode|default|_21b|_d|html|_event_listener|handlers|PAGE_DOWN|PAGE_UP|RIGHT_ARROW|LEFT_ARROW|DOWN_ARROW|UP_ARROW|_preventDefault||_stopPropagation|returnValue||_trySetKeyCode|cancelBubble|currentTarget|106|_1ee|111||_1e8|_1e7|||se|srcElement|onkeydown||_1d0|_disconnect|lid|_1c0|_connect|_set|_195|_185|_183|_17d|_everyOrSome|_16b|_172|_15b|Function|_154|_escapeString|_140|chain|_check|canceller|_12d|_124|_11a|_10d|_107|inherited|_fa|_f2|_findMixin|_constructor|preamble|_de|clone|tmp|_c7|TMP|_be|_ba|_mixin|isBrowser|lang|firebug||param|modulePaths|_a7|_fireCallback|_a0|setContext||_9c|unloaded||||_96|_93|navigator|_90|_89||protocol|_84|_86|_XMLHTTP_PROGIDS|gears|google|setAttribute|_80|_77|cfg|_6f|_getModuleSymbols|_5a|_58|_53|_4d|_4c|_45|_40|_moduleHasPrefix|_loadUri|_28|_26|_21|_22|tests|doh|_20|_1f|_1c|version|_1b|_19|_getProp|_11|_4|_4a5|_4b3|_Animation|tempColor|blendColors|PI|sin|||||_49a|normal|onEnd||rate||curr|onStop|_497||_496|pct|onPause|onPlay|onBegin|delay||_491|_Line|_48b|wrapForm|PUT|_487|POST|GET|_476|_474|_472|_ioWatch|send|_471|setRequestHeader|open|callback|setInterval|_470|resHandle|_46f|ioCheck|_46e|validCheck|getTime|_ioCancelAll|addOnUnload|clearInterval|dojoType|now|canceled|_blockAsync|_45e|_45c|_459|_ioSetArgs|_contentHandlers|abort|_458|_456||||addErrback|_454|addCallback|_452|_44b|_44a|_449|preventCache|responseXML|Microsoft|JSON|usePlainJson|_431|toJson|_430|_42d|image|opt|ria|_421|_41b|_40b|_zip|_410|_40d|_357|sqf|_374|_3e5|_3df|_38f|clc|pred|parseInt|ntf|_3bf|_3bc|cnl|previousSibling|_3a9|_3a6|_39c|_399|_396|_392|__cachedIndex|__cachedLength|_376|iterateNext|_34a|_355|_354|_32c|_350|_34b|_33f|_33e|_33a|_338|_334|_332||_330|_32e||_322|_316|mousemove|mouseout|mouseover|_305|lastChild||_2f9||_2f2|_2f1|removeChild|_2ec|_2eb|_2ea|_2e6||_2e4|_2e2|_2d6|_2d5|_2d4|_2d3|_2d2|_2d1|_2cd|_2cc|scs|write|_2c8|hasClass|_2c0|_2bb|_2b5|_abs|_docScroll|offsetParent|offsetTop|offsetLeft|absolute|getBoxObjectFor|clientLeft|_setContentSize|_setMarginBox|_28d|_286|_285|_289|NaN|_281|border|_272|_26b|_260|_258|_253|_24c|_246|_23a|_getOpacity|_setOpacity|_238|td|tr|nodeName|FILTER|_22f|_22e|currentStyle|_22c|_22b|display|QuirksMode|unselectable|_217|isMozilla|getElementById|attributes|all|_ie_listener|_getIeDispatcher|_1fd|NUM_LOCK|SCROLL_LOCK|INSERT|END|HOME|PAUSE|F12|F11|F10|F9|F8|F7|F6|F5|F4|F3|F2|F1|63232|SHIFT_TAB|TAB|keyIdentifier|_1f3|stopEvent|_punctMap|222|219|186|onkeypress|_stealthKeyDown|_fixKeys|relatedTarget|_1e0|_1df|_stealthKeydown|_1d6|_1d5|_1d1|_1ca|_1c9|_1cb|_1c2|_1c1|_1c3|_1c4|_1bc|_1b3|_1b2|colorFromHex|colorFromRgb|named|colorFromString|mask|rgba|_19c|_197|_192|setColor|_180|_178|_177|_175|_174|_16d|_166|_164|_163|_162|_15c|_15d|_15e|index|__json__|toJsonIndentStr|_nextId|_12f|_12b|publish|_128|_126|_125|_122|_121|_123|_11c|_11b|_10c|_10b|_108|getDispatcher|argument|nom|_construct|_core|_makeCtor|_df|_db|deprecated|isObject|_cc||scope||_hitchArgs|_c2||pre|_c1|native|isDebug||registerModulePath|_a8||finally|||_a6|_a5|_a4|_a3|_a2|_a1|_9f|_9e|_9d|_9b|_98|_97|onbeforeunload|ipt|scr|complete|_95|userAgent|_modulesLoaded|initialized|_initFired|_8c|_8a|_getText|_87|ieForceActiveXXhr|Msxml2|isGears|_81|_gearsObject|googlegears|GearsFactory|isFF|_7d|Safari|_72|_name|_6c|ire|ore|_68|i18n|_5b|requireIf|_56|_52|loading|_4a|_loadPath|_47|_48|_global_omit_module_check|_getModulePrefix|_3c|_3a|_37|_30|Boolean|_loadUriAndCheck|_2e||cacheBust|_1e|_1a|_17|_16|_15|_14|_f|_10|_e|_9|_8|revision|flag|patch|minor|major|_6|color|units|needs|stopped|playing|stop|gotoPercent|pause|1000|implemented|yet|_48a|xhrDelete|rawXhrPut|xhrPut|postData|rawXhrPost|xhrPost|xhrGet|Type|Content|sync|response|http|bad|urlencoded|www|_watchInFlightError||exceeded|handle|action|getAttributeNode|loadXML|async|XMLDOM|prefixes|MSXML3|MSXML|MSXML2||xml|javascript|wasn|your|optional|message|off|turn|use|endpoints|issues|security|potential|avoid|mimetype|using|consider|please|decodeURIComponent|queryToObject|formToJson|formToQuery|encodeURIComponent|selected|option|multiple|checked|checkbox|radio|disabled|textarea|select|button|reset|submit|input|_3fb|hasAttribute|0n|even|odd|nth|_3b5|empty|_3b1|_3ad|htmlFor|_38a|under||exprssion|failure|ANY_TYPE|XPathResult|starts|keyup|keydown|mouseup|mousedown|blur|click|combine|span|addContent||adopt|orphan|_2de|_2dd|styles|_2da|_2d9|_2cf|_2ce|show|createPopup|toggleClass|scrollWidth|clientTop|ltr|direction|pageXOffset|pageYOffset|fixed|contentBox|marginBox|BUTTON|TABLE|_getBorderBox|clientHeight|visible|overflow|marginBottom|marginRight|marginTop|marginLeft|borderBottomWidth|borderBottomStyle|borderRightWidth|borderRightStyle|borderTopWidth|borderTopStyle|borderLeftWidth|borderLeftStyle|paddingBottom|paddingRight|paddingTop|paddingLeft|offset||min|padding||margin|Opacity|Alpha|alpha|filters|pixelLeft|medium|_22a|defaultView|before||insertBefore|KhtmlUserSelect|MozUserSelect|setSelectable|isDescendant|div|_destroyElement|BackgroundImageCache|execCommand|PageDown|PageUp|Right|Left|Down|Up|63289|63249|63248|PRINT_SCREEN|63302|63277|63276|63275|63273|63272|63250|63247|63246|63245|63244|63243|63242|63241|63240|63239|63238|63237|63236|63235|63234|63233|Enter|_1f9|which|_1f6|bubbledKeyCode|221|220||||191|190|189|188|187|toElement|fromElement|clientY|pageY||clientX|pageX|offsetY|||layerY|offsetX|layerX|parentWindow|_nop|_allow_leaks|145|144|126|F15|125|F14|124|F13|123|122|121|120|119|118|117|116|115|114|113|112|NUMPAD_DIVIDE|110|NUMPAD_PERIOD|109|NUMPAD_MINUS|108|NUMPAD_ENTER|107|NUMPAD_PLUS|NUMPAD_MULTIPLY|105|NUMPAD_9|104|NUMPAD_8|103|NUMPAD_7|102|NUMPAD_6|101|NUMPAD_5|NUMPAD_4||NUMPAD_3|NUMPAD_2|NUMPAD_1|NUMPAD_0||SELECT|RIGHT_WINDOW||LEFT_WINDOW||HELP|SPACE|ESCAPE|CAPS_LOCK|ALT|CTRL|SHIFT|ENTER|CLEAR|BACKSPACE|attachEvent|fixEvent|fromCharCode|keyChar|_1b9|removeEventListener|0x|round|toHex|toRgba|toRgb|aqua|teal|blue|navy|yellow|olive|lime|green|fuchsia|purple|red|maroon|white|gray|silver|black|boolean|called|already|Cancelled|connectPublisher|unsubscribe|subscribe|disconnect|_113|_112||_111|_110|||found|was||must|_|module|||required|likely|It|declaration|Mixin|separate|instead|property|initializer||pass|_c9|_bb|_b7|nfunction|isAlien|isFinite|isArrayLike|_firebug|withDoc|withGlobal|_writeIncludes|VML|behavior|addRule|createStyleSheet|vml|com|microsoft|schemas|urn|namespaces|onunload|onreadystatechange|defer|khtml|WebKit|DOMContentLoaded|enableMozDomContentLoaded|domcontentloaded|Unable|base|chrome|1223|304|300|200|available|XMLHttpRequest|_println|language|userLanguage|isQuirks|factory|mimeTypes|Factory|Gears|_7f|MSIE||Firefox|Gecko|Konqueror||Opera|appVersion|xd|browser|moduleUrl|port|host|hostenv|_requireLocalization|_5f|_5e|_5d|_5c|requireLocalization|requireAfterIf|_57|common|platformRequire|defined|symbol|_isXDomain|tried|Could|__package__|packageFileName|_42|useXDomain|flight|still|files|addOnLoad|failed|sourceURL|util|notice|without|change|subject|APIs|EXPERIMENTAL|experimental|removed|will|DEPRECATED|exists|10315|Rev|Mobile|Spidermonkey|Rhino||Browser|delayMozLoadingFix|preventBackButtonFix|libraryScriptUri|baseRelativePath|baseScriptUri|allowQueryConfig|warn|trace|timeEnd||time|profileEnd|profile|log|info|groupEnd|group|dirxml|dir|count|assert'.split('|'),0,{}); + + +/* + +Prototype 1.5 rc0 + - Adapted from Ruby on Rails - http://dev.rubyonrails.org/browser/spinoffs/prototype/src + - By Lunarmedia, 06 August, 2006 + - Available at (and packed with) JavascriptCompressor.com + +Please note this version is missing the selector.js component of the full Prototype library. +You can get the compressed version of selector at JavascriptCompressor.com + +*/ + +var decompressedPrototype = function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[(function(e){return d[e]})];e=(function(){return'\\w+'});c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('d T={4l:\'1.5.8P\',3E:\'(?:<3G.*?>)((\\n|\\r|.)*?)(?:<\\/3G>)\',2v:7(){},K:7(x){c x}};d 1b={17:7(){c 7(){6.1I.2n(6,N)}}};d 1e=z q();q.u=7(5d,O){G(d 1G 2M O){5d[1G]=O[1G]}c 5d};q.1U=7(U){1j{f(U==1v)c\'1v\';f(U==1L)c\'1L\';c U.1U?U.1U():U.2C()}1s(e){f(e 8R 9l)c\'...\';25 e}};7j.v.1d=7(){d 43=6,23=$A(N),U=23.8S();c 7(){c 43.2n(U,23.3s($A(N)))}};7j.v.8U=7(U){d 43=6;c 7(C){c 43.8V(U,C||1W.C)}};q.u(8Q.v,{8W:7(){d 4Z=6.2C(16);f(6<16)c\'0\'+4Z;c 4Z},5j:7(){c 6+1},8Y:7(o){$R(0,6,11).V(o);c 6}});d 6s={6j:7(){d 48;G(d i=0;i0){f(I=O.I(1A)){L+=O.47(0,I.w);L+=(1z(I)||\'\').2C();O=O.47(I.w+I[0].t)}1D{L+=O,O=\'\'}}c L},92:7(1A,1z,3i){1z=6.2T.52(1z);3i=3i===1v?1:3i;c 6.2T(1A,7(I){f(--3i<0)c I[0];c 1z(I)})},93:7(1A,o){6.2T(1A,o);c 6},94:7(t,2S){t=t||30;2S=2S===1v?\'...\':2S;c 6.t>t?6.47(0,t-2S.t)+2S:6},9F:7(){c 6.2y(/^\\s+/,\'\').2y(/\\s+$/,\'\')},71:7(){c 6.2y(/<\\/?[^>]+>/7Y,\'\')},2Q:7(){c 6.2y(z 3O(T.3E,\'5P\'),\'\')},70:7(){d 6Y=z 3O(T.3E,\'5P\');d 5p=z 3O(T.3E,\'98\');c(6.I(6Y)||[]).1C(7(5o){c(5o.I(5p)||[\'\',\'\'])[1]})},3q:7(){c 6.70().1C(7(3G){c 4q(3G)})},9E:7(){d 1q=J.4Y(\'1q\');d 1Y=J.9D(6);1q.75(1Y);c 1q.3h},9c:7(){d 1q=J.4Y(\'1q\');1q.3h=6.71();c 1q.2z[0]?1q.2z[0].6q:\'\'},78:7(){d 7i=6.I(/^\\??(.*)$/)[1].3j(\'&\');c 7i.36({},7(5b,72){d 1i=72.3j(\'=\');5b[1i[0]]=1i[1];c 5b})},1Z:7(){c 6.3j(\'\')},3P:7(){d 2l=6.3j(\'-\');f(2l.t==1)c 2l[0];d 54=6.5g(\'-\')==0?2l[0].7e(0).3Y()+2l[0].7g(1):2l[0];G(d i=1,73=2l.t;i<73;i++){d s=2l[i];54+=s.7e(0).3Y()+s.7g(1)}c 54},1U:7(){c"\'"+6.2y(/\\\\/g,\'\\\\\\\\\').2y(/\'/g,\'\\\\\\\'\')+"\'"}});4b.v.2T.52=7(1z){f(2i 1z==\'7\')c 1z;d 2U=z 3n(1z);c 7(I){c 2U.7a(I)}};4b.v.9h=4b.v.78;d 3n=1b.17();3n.79=/(^|.|\\r|\\n)(#\\{(.*?)\\})/;3n.v={1I:7(2U,1A){6.2U=2U.2C();6.1A=1A||3n.79},7a:7(U){c 6.2U.2T(6.1A,7(I){d 53=I[1];f(53==\'\\\\\')c I[2];c 53+(U[I[3]]||\'\').2C()})}};d $1y=z q();d $49=z q();d 1p={V:7(o){d w=0;1j{6.2m(7(h){1j{o(h,w++)}1s(e){f(e!=$49)25 e}})}1s(e){f(e!=$1y)25 e}},9n:7(o){d L=11;6.V(7(h,w){L=L&&!!(o||T.K)(h,w);f(!L)25 $1y});c L},9o:7(o){d L=11;6.V(7(h,w){f(L=!!(o||T.K)(h,w))25 $1y});c L},3e:7(o){d P=[];6.V(7(h,w){P.W(o(h,w))});c P},7n:7(o){d L;6.V(7(h,w){f(o(h,w)){L=h;25 $1y}});c L},7o:7(o){d P=[];6.V(7(h,w){f(o(h,w))P.W(h)});c P},9p:7(1A,o){d P=[];6.V(7(h,w){d 7c=h.2C();f(7c.I(1A))P.W((o||T.K)(h,w))});c P},1M:7(U){d 51=Y;6.V(7(h){f(h==U){51=11;25 $1y}});c 51},36:7(45,o){6.V(7(h,w){45=o(45,h,w)});c 45},9q:7(1F){d 23=$A(N).47(1);c 6.3e(7(h){c h[1F].2n(h,23)})},9s:7(o){d L;6.V(7(h,w){h=(o||T.K)(h,w);f(L==1v||h>=L)L=h});c L},9u:7(o){d L;6.V(7(h,w){h=(o||T.K)(h,w);f(L==1v||hb?1:0}).3r(\'h\')},1Z:7(){c 6.3e(T.K)},9B:7(){d o=T.K,23=$A(N);f(2i 23.5e()==\'7\')o=23.9C();d 7l=[6].3s(23).1C($A);c 6.1C(7(h,w){c o(7l.3r(w))})},1U:7(){c\'#<1p:\'+6.1Z().1U()+\'>\'}};q.u(1p,{1C:1p.3e,5v:1p.7n,1k:1p.7o,8M:1p.1M,7p:1p.1Z});d $A=1E.7q=7(2R){f(!2R)c[];f(2R.1Z){c 2R.1Z()}1D{d P=[];G(d i=0;i<2R.t;i++)P.W(2R[i]);c P}};q.u(1E.v,1p);f(!1E.v.4d)1E.v.4d=1E.v.4m;q.u(1E.v,{2m:7(o){G(d i=0;i<6.t;i++)o(6[i])},5i:7(){6.t=0;c 6},7r:7(){c 6[0]},5e:7(){c 6[6.t-1]},7s:7(){c 6.1k(7(h){c h!=1v||h!=1L})},6J:7(){c 6.36([],7(6H,h){c 6H.3s(h&&h.5D==1E?h.6J():[h])})},5s:7(){d 4N=$A(N);c 6.1k(7(h){c!4N.1M(h)})},5g:7(U){G(d i=0;i<6.t;i++)f(6[i]==U)c i;c-1},4m:7(5h){c(5h!==Y?6:6.1Z()).4d()},1U:7(){c\'[\'+6.1C(q.1U).1N(\', \')+\']\'}});d 4h={2m:7(o){G(d 1O 2M 6){d h=6[1O];f(2i h==\'7\')49;d 1i=[1O,h];1i.1O=1O;1i.h=h;o(1i)}},7t:7(){c 6.3r(\'1O\')},4N:7(){c 6.3r(\'h\')},7u:7(2N){c $H(2N).36($H(6),7(4Q,1i){4Q[1i.1O]=1i.h;c 4Q})},7w:7(){c 6.1C(7(1i){c 1i.1C(4n).1N(\'=\')}).1N(\'&\')},1U:7(){c\'#<4h:{\'+6.1C(7(1i){c 1i.1C(q.1U).1N(\': \')}).1N(\', \')+\'}>\'}};7 $H(U){d 2N=q.u({},U||{});q.u(2N,1p);q.u(2N,4h);c 2N};3L=1b.17();q.u(3L.v,1p);q.u(3L.v,{1I:7(22,2x,2H){6.22=22;6.2x=2x;6.2H=2H},2m:7(o){d h=6.22;2q{o(h);h=h.5j()}1H(6.1M(h))},1M:7(h){f(h<6.22)c Y;f(6.2H)c h<6.2x;c h<=6.2x}});d $R=7(22,2x,2H){c z 3L(22,2x,2H)};d M={4w:7(){c 6s.6j(7(){c z 5C()},7(){c z 5n(\'7y.6d\')},7(){c z 5n(\'7z.6d\')})||Y},4s:0};M.2W={3b:[],2m:7(o){6.3b.2m(o)},69:7(4F){f(!6.1M(4F))6.3b.W(4F)},7A:7(5t){6.3b=6.3b.5s(5t)},3y:7(1a,26,E,2Z){6.V(7(3o){f(3o[1a]&&2i 3o[1a]==\'7\'){1j{3o[1a].2n(3o,[26,E,2Z])}1s(e){}}})}};q.u(M.2W,1p);M.2W.69({5G:7(){M.4s++},1B:7(){M.4s--}});M.44=7(){};M.44.v={4a:7(m){6.m={1F:\'4j\',4p:11,5H:\'5E/x-86-Q-7C\',28:\'\'};q.u(6.m,m||{})},3l:7(){c 6.E.32==1v||6.E.32==0||(6.E.32>=84&&6.E.32<7E)},7G:7(){c!6.3l()}};M.3t=1b.17();M.3t.5L=[\'7H\',\'80\',\'7I\',\'7J\',\'4t\'];M.3t.v=q.u(z M.44(),{1I:7(1l,m){6.E=M.4w();6.4a(m);6.26(1l)},26:7(1l){d 28=6.m.28||\'\';f(28.t>0)28+=\'&7K=\';1j{6.1l=1l;f(6.m.1F==\'7L\'&&28.t>0)6.1l+=(6.1l.I(/\\?/)?\'&\':\'?\')+28;M.2W.3y(\'5G\',6,6.E);6.E.7N(6.m.1F,6.1l,6.m.4p);f(6.m.4p){6.E.5T=6.5J.1d(6);2Y((7(){6.4r(1)}).1d(6),10)}6.5A();d 1c=6.m.5V?6.m.5V:28;6.E.7O(6.m.1F==\'4j\'?1c:1L)}1s(e){6.3p(e)}},5A:7(){d 1P=[\'X-7P-7Q\',\'5C\',\'X-T-4l\',T.4l,\'7R\',\'1Y/7m, 1Y/2e, 5E/5F, 1Y/5F, */*\'];f(6.m.1F==\'4j\'){1P.W(\'5Q-2g\',6.m.5H);f(6.E.7S)1P.W(\'7T\',\'7U\')}f(6.m.1P)1P.W.2n(1P,6.m.1P);G(d i=0;i<1P.t;i+=2)6.E.7V(1P[i],1P[i+1])},5J:7(){d 2F=6.E.2F;f(2F!=1)6.4r(6.E.2F)},4A:7(B){1j{c 6.E.7W(B)}1s(e){}},5M:7(){1j{c 4q(\'(\'+6.4A(\'X-7X\')+\')\')}1s(e){}},5R:7(){1j{c 4q(6.E.3F)}1s(e){6.3p(e)}},4r:7(2F){d C=M.3t.5L[2F];d E=6.E,2Z=6.5M();f(C==\'4t\'){1j{(6.m[\'2I\'+6.E.32]||6.m[\'2I\'+(6.3l()?\'81\':\'82\')]||T.2v)(E,2Z)}1s(e){6.3p(e)}f((6.4A(\'5Q-2g\')||\'\').I(/^1Y\\/7m/i))6.5R()}1j{(6.m[\'2I\'+C]||T.2v)(E,2Z);M.2W.3y(\'2I\'+C,6,E,2Z)}1s(e){6.3p(e)}f(C==\'4t\')6.E.5T=T.2v},3p:7(57){(6.m.5W||T.2v)(6,57);M.2W.3y(\'5W\',6,57)}});M.4C=1b.17();q.u(q.u(M.4C.v,M.3t.v),{1I:7(1w,1l,m){6.4x={3m:1w.3m?$(1w.3m):$(1w),3z:1w.3z?$(1w.3z):(1w.3m?1L:$(1w))};6.E=M.4w();6.4a(m);d 1B=6.m.1B||T.2v;6.m.1B=(7(E,U){6.5Y();1B(E,U)}).1d(6);6.26(1l)},5Y:7(){d 3A=6.3l()?6.4x.3m:6.4x.3z;d 3k=6.E.3F;f(!6.m.3q)3k=3k.2Q();f(3A){f(6.m.60){z 6.m.60(3A,3k)}1D{k.6h(3A,3k)}}f(6.3l()){f(6.1B)2Y(6.1B.1d(6),10)}}});M.61=1b.17();M.61.v=q.u(z M.44(),{1I:7(1w,1l,m){6.4a(m);6.1B=6.m.1B;6.1J=(6.m.1J||2);6.2s=(6.m.2s||1);6.4B={};6.1w=1w;6.1l=1l;6.22()},22:7(){6.m.1B=6.63.1d(6);6.2D()},7b:7(){6.4B.1B=1v;89(6.65);(6.1B||T.2v).2n(6,N)},63:7(26){f(6.m.2s){6.2s=(26.3F==6.64?6.2s*6.m.2s:1);6.64=26.3F}6.65=2Y(6.2D.1d(6),6.2s*6.1J*4z)},2D:7(){6.4B=z M.4C(6.1w,6.1l,6.m)}});7 $(){d P=[],4;G(d i=0;i<4V>\'+6.2t+\'\';c $A(1q.2z[0].2z[0].2z)}};d 1g=z q();1g.6W=1b.17();1g.6W.v=q.u(z 1e.1g(\'96\'),{2V:7(){6.1K.97(6.4)},2X:7(2h){2h.V((7(2j){6.4.1X.55(2j,6.4)}).1d(6))}});1g.5m=1b.17();1g.5m.v=q.u(z 1e.1g(\'99\'),{2V:7(){6.1K.56(6.4);6.1K.74(11)},2X:7(2h){2h.4m(Y).V((7(2j){6.4.55(2j,6.4.9a)}).1d(6))}});1g.7h=1b.17();1g.7h.v=q.u(z 1e.1g(\'9d\'),{2V:7(){6.1K.56(6.4);6.1K.74(6.4)},2X:7(2h){2h.V((7(2j){6.4.75(2j)}).1d(6))}});1g.76=1b.17();1g.76.v=q.u(z 1e.1g(\'9i\'),{2V:7(){6.1K.9m(6.4)},2X:7(2h){2h.V((7(2j){6.4.1X.55(2j,6.4.9t)}).1d(6))}});k.3S=1b.17();k.3S.v={1I:7(4){6.4=$(4)},2m:7(o){6.4.1f.3j(/\\s+/).1k(7(B){c B.t>0}).2m(o)},5c:7(1f){6.4.1f=1f},7k:7(5a){f(6.1M(5a))c;6.5c(6.1Z().3s(5a).1N(\' \'))},42:7(4c){f(!6.1M(4c))c;6.5c(6.1k(7(1f){c 1f!=4c}).1N(\' \'))},2C:7(){c 6.1Z().1N(\' \')}};q.u(k.3S.v,1p);d 5I={5i:7(){G(d i=0;i=0){2b=4.m[w];h=2b.h||2b.1Y}c[4.B,h]},5X:7(4){d h=[];G(d i=0;i<4.t;i++){d 2b=4.m[i];f(2b.87)h.W(2b.h||2b.1Y)}c[4.B,h]}};d $F=D.k.1x;1e.3D=7(){};1e.3D.v={1I:7(4,1J,1a){6.1J=1J;6.4=$(4);6.1a=1a;6.2K=6.1x();6.2A()},2A:7(){5Z(6.2D.1d(6),6.1J*4z)},2D:7(){d h=6.1x();f(6.2K!=h){6.1a(6.4,h);6.2K=h}}};D.k.3C=1b.17();D.k.3C.v=q.u(z 1e.3D(),{1x:7(){c D.k.1x(6.4)}});D.3C=1b.17();D.3C.v=q.u(z 1e.3D(),{1x:7(){c D.3a(6.4)}});1e.2c=7(){};1e.2c.v={1I:7(4,1a){6.4=$(4);6.1a=1a;6.2K=6.1x();f(6.4.1h.2w()==\'Q\')6.67();1D 6.2A(6.4)},4K:7(){d h=6.1x();f(6.2K!=h){6.1a(6.4,h);6.2K=h}},67:7(){d 12=D.2L(6.4);G(d i=0;i<12.t;i++)6.2A(12[i])},2A:7(4){f(4.2g){6c(4.2g.2w()){1r\'6g\':1r\'6i\':1o.3B(4,\'8j\',6.4K.1d(6));1y;1r\'6l\':1r\'1Y\':1r\'3J\':1r\'1k-6n\':1r\'1k-8t\':1o.3B(4,\'8u\',6.4K.1d(6));1y}}}};D.k.2c=1b.17();D.k.2c.v=q.u(z 1e.2c(),{1x:7(){c D.k.1x(6.4)}});D.2c=1b.17();D.2c.v=q.u(z 1e.2c(),{1x:7(){c D.3a(6.4)}});f(!1W.1o){d 1o=z q()}q.u(1o,{8C:8,8F:9,8H:13,8I:27,8J:37,8L:38,8O:39,8T:40,8X:46,4:7(C){c C.Z||C.91},95:7(C){c(((C.6X)&&(C.6X==1))||((C.6Z)&&(C.6Z==1)))},9b:7(C){c C.9e||(C.9f+(J.3R.2G||J.1c.2G))},9g:7(C){c C.9j||(C.9k+(J.3R.2O||J.1c.2O))},7b:7(C){f(C.7d){C.7d();C.9r()}1D{C.48=Y;C.9w=11}},9A:7(C,1h){d 4=1o.4(C);1H(4.1X&&(!4.1h||(4.1h.3Y()!=1h.3Y())))4=4.1X;c 4},1T:Y,5u:7(4,B,1V,1u){f(!6.1T)6.1T=[];f(4.5f){6.1T.W([4,B,1V,1u]);4.5f(B,1V,1u)}1D f(4.4i){6.1T.W([4,B,1V,1u]);4.4i(\'2I\'+B,1V)}},66:7(){f(!1o.1T)c;G(d i=0;i<1o.1T.t;i++){1o.5N.2n(6,1o.1T[i]);1o.1T[i][0]=1L}1o.1T=Y},3B:7(4,B,1V,1u){d 4=$(4);1u=1u||Y;f(B==\'5U\'&&(33.4u.I(/3x|3w|3u/)||4.4i))B=\'5K\';6.5u(4,B,1V,1u)},5N:7(4,B,1V,1u){d 4=$(4);1u=1u||Y;f(B==\'5U\'&&(33.4u.I(/3x|3w|3u/)||4.4k))B=\'5K\';f(4.5x){4.5x(B,1V,1u)}1D f(4.4k){1j{4.4k(\'2I\'+B,1V)}1s(e){}}}});f(33.4u.I(/\\88\\b/))1o.3B(1W,\'8a\',1o.66,Y);d 2d={6o:Y,4P:7(){6.6z=1W.8e||J.3R.2G||J.1c.2G||0;6.6F=1W.8g||J.3R.2O||J.1c.2O||0},6u:7(4){d 19=0,15=0;2q{19+=4.2O||0;15+=4.2G||0;4=4.1X}1H(4);c[15,19]},35:7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;4=4.1Q}1H(4);c[15,19]},68:7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;4=4.1Q;f(4){p=k.1R(4,\'14\');f(p==\'3T\'||p==\'2o\')1y}}1H(4);c[15,19]},1Q:7(4){f(4.1Q)c 4.1Q;f(4==J.1c)c 4;1H((4=4.1X)&&4!=J.1c)f(k.1R(4,\'14\')!=\'4G\')c 4;c J.1c},8o:7(4,x,y){f(6.6o)c 6.6r(4,x,y);6.3g=x;6.34=y;6.1t=6.35(4);c(y>=6.1t[1]&&y<6.1t[1]+4.2k&&x>=6.1t[0]&&x<6.1t[0]+4.2p)},6r:7(4,x,y){d 4S=6.6u(4);6.3g=x+4S[0]-6.6z;6.34=y+4S[1]-6.6F;6.1t=6.35(4);c(6.34>=6.1t[1]&&6.34<6.1t[1]+4.2k&&6.3g>=6.1t[0]&&6.3g<6.1t[0]+4.2p)},8E:7(3Z,4){f(!3Z)c 0;f(3Z==\'8G\')c((6.1t[1]+4.2k)-6.34)/4.2k;f(3Z==\'8K\')c((6.1t[0]+4.2p)-6.3g)/4.2p},77:7(O,Z){O=$(O);Z=$(Z);Z.l.14=\'2o\';d 2P=6.35(O);Z.l.1n=2P[1]+\'1m\';Z.l.18=2P[0]+\'1m\';Z.l.21=O.2p+\'1m\';Z.l.24=O.2k+\'1m\'},4e:7(4M){d 19=0,15=0;d 4=4M;2q{19+=4.29||0;15+=4.2f||0;f(4.1Q==J.1c)f(k.1R(4,\'14\')==\'2o\')1y}1H(4=4.1Q);4=4M;2q{19-=4.2O||0;15-=4.2G||0}1H(4=4.1X);c[15,19]},77:7(O,Z){d m=q.u({5l:11,5r:11,5B:11,5q:11,29:0,2f:0},N[2]||{});O=$(O);d p=2d.4e(O);Z=$(Z);d 2J=[0,0];d 3v=1L;f(k.1R(Z,\'14\')==\'2o\'){3v=2d.1Q(Z);2J=2d.4e(3v)}f(3v==J.1c){2J[0]-=J.1c.2f;2J[1]-=J.1c.29}f(m.5l)Z.l.18=(p[0]-2J[0]+m.2f)+\'1m\';f(m.5r)Z.l.1n=(p[1]-2J[1]+m.29)+\'1m\';f(m.5B)Z.l.21=O.2p+\'1m\';f(m.5q)Z.l.24=O.2k+\'1m\'},8b:7(4){4=$(4);f(4.l.14==\'2o\')c;2d.4P();d 2P=2d.68(4);d 1n=2P[1];d 18=2P[0];d 21=4.6m;d 24=4.6p;4.6P=18-3X(4.l.18||0);4.6I=1n-3X(4.l.1n||0);4.5k=4.l.21;4.7f=4.l.24;4.l.14=\'2o\';4.l.1n=1n+\'1m\';4.l.18=18+\'1m\';4.l.21=21+\'1m\';4.l.24=24+\'1m\'},8w:7(4){4=$(4);f(4.l.14==\'3T\')c;2d.4P();4.l.14=\'3T\';d 1n=3X(4.l.1n||0)-(4.6I||0);d 18=3X(4.l.18||0)-(4.6P||0);4.l.1n=1n+\'1m\';4.l.18=18+\'1m\';4.l.24=4.7f;4.l.21=4.5k}};f(/3x|3w|3u/.4v(33.62)){2d.35=7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;f(4.1Q==J.1c)f(k.1R(4,\'14\')==\'2o\')1y;4=4.1Q}1H(4);c[15,19]}};',62,600,'||||element||this|function|||||return|var||if||value|||Element|style|options||iterator||Object|||length|extend|prototype|index|||new||name|event|Form|transport||for||match|document||result|Ajax|arguments|source|results|form|||Prototype|object|each|push||false|target||true|elements||position|valueL||create|left|valueT|callback|Class|body|bind|Abstract|className|Insertion|tagName|pair|try|select|url|px|top|Event|Enumerable|div|case|catch|offset|useCapture|undefined|container|getValue|break|replacement|pattern|onComplete|map|else|Array|method|property|while|initialize|frequency|range|null|include|join|key|requestHeaders|offsetParent|getStyle|parameter|observers|inspect|observer|window|parentNode|text|toArray|els|width|start|args|height|throw|request||parameters|offsetTop|methods|opt|EventObserver|Position|html|offsetLeft|type|fragments|typeof|fragment|offsetHeight|oStringList|_each|apply|absolute|offsetWidth|do|cache|decay|content|input|emptyFunction|toLowerCase|end|replace|childNodes|registerCallback|display|toString|onTimerEvent|Serializers|readyState|scrollLeft|exclusive|on|delta|lastValue|getElements|in|hash|scrollTop|offsets|stripScripts|iterable|truncation|gsub|template|initializeRange|Responders|insertContent|setTimeout|json||hidden|status|navigator|ycomp|cumulativeOffset|inject||||serialize|responders|_overflow|Methods|collect|adjacency|xcomp|innerHTML|count|split|response|responseIsSuccess|success|Template|responder|dispatchException|evalScripts|pluck|concat|Request|KHTML|parent|Safari|Konqueror|dispatch|failure|receiver|observe|Observer|TimedObserver|ScriptFragment|responseText|script|inputs|ancestor|textarea|classNames|ObjectRange|node|typeName|RegExp|camelize|none|documentElement|ClassNames|relative|right|overflow|HTMLElement|parseFloat|toUpperCase|mode||currentlyExecuting|remove|__method|Base|memo||slice|returnValue|continue|setOptions|String|classNameToRemove|_reverse|page|focus|queryComponent|Hash|attachEvent|post|detachEvent|Version|reverse|encodeURIComponent|disabled|asynchronous|eval|respondToReadyState|activeRequestCount|Complete|appVersion|test|getTransport|containers|matchingInputs|1000|header|updater|Updater|getElementsByTagName|child|responderToAdd|static|tagElements|queryComponents|defaultView|onElementEvent|css|forElement|values|visibility|prepare|mergedHash|pos|offsetcache|_madePositioned|visible|tbody|findOrStore|_nativeExtensions|createElement|digits|trues|found|prepareReplacement|before|camelizedString|insertBefore|selectNodeContents|exception|falses|criteria|classNameToAdd|params|set|destination|last|addEventListener|indexOf|inline|clear|succ|_originalWidth|setLeft|Top|ActiveXObject|scriptTag|matchOne|setHeight|setTop|without|responderToRemove|_observeAndCache|find|reset|removeEventListener|activate|findFirstElement|setRequestHeaders|setWidth|XMLHttpRequest|constructor|application|xml|onCreate|contentType|Field|onStateChange|keydown|Events|evalJSON|stopObserving|inputSelector|img|Content|evalResponse|selectOne|onreadystatechange|keypress|postBody|onException|selectMany|updateContent|setInterval|insertion|PeriodicalUpdater|userAgent|updateComplete|lastText|timer|unloadCache|registerFormCallbacks|positionedOffset|register|parentElement|children|switch|XMLHTTP|_extended|hide|checkbox|update|radio|these|outerHTML|password|clientWidth|one|includeScrollOffsets|clientHeight|nodeValue|withinIncludingScrolloffsets|Try|scrollTo|realOffset|getComputedStyle|show|currentStyle|auto|deltaX|originalPosition|originalVisibility|originalWidth|originalHeight|opera|deltaY|bottom|array|_originalTop|flatten|addMethods|lambda|Toggle|toggle|insertAdjacentHTML|_originalLeft|PeriodicalExecuter|ownerDocument|createRange|createContextualFragment|contentFromAnonymousTable|table|Before|which|matchAll|button|extractScripts|stripTags|pairString|len|collapse|appendChild|After|clone|toQueryParams|Pattern|evaluate|stop|stringValue|preventDefault|charAt|_originalHeight|substring|Bottom|pairs|Function|add|collections|javascript|detect|findAll|entries|from|first|compact|keys|merge|present|toQueryString|getInputs|Msxml2|Microsoft|unregister|disable|urlencoded|blur|300|enable|responseIsFailure|Uninitialized|Loaded|Interactive|_|get|focusFirstElement|open|send|Requested|With|Accept|overrideMimeType|Connection|close|setRequestHeader|getResponseHeader|JSON|gi|submit|Loading|Success|Failure|checked|200|selectedIndex|www|selected|bMSIE|clearTimeout|unload|absolutize|string|getElementById|pageXOffset|getElementsByClassName|pageYOffset|removeChild|replaceChild|click|getHeight|hasClassName|addClassName|removeClassName|within|cleanWhitespace|nodeType|empty|childOf|multiple|change|getPropertyValue|relativize|setStyle|getDimensions|makePositioned|undoPositioned|makeClipping|KEY_BACKSPACE|undoClipping|overlap|KEY_TAB|vertical|KEY_RETURN|KEY_ESC|KEY_LEFT|horizontal|KEY_UP|member|tr|KEY_RIGHT|0_RC_0|Number|instanceof|shift|KEY_DOWN|bindAsEventListener|call|toColorPart|KEY_DELETE|times|finally|callee|srcElement|sub|scan|truncate|isLeftClick|beforeBegin|setStartBefore|im|afterBegin|firstChild|pointerX|unescapeHTML|beforeEnd|pageX|clientX|pointerY|parseQuery|afterEnd|pageY|clientY|RangeError|setStartAfter|all|any|grep|invoke|stopPropagation|max|nextSibling|min|partition|cancelBubble|reject|sortBy|sort|findElement|zip|pop|createTextNode|escapeHTML|strip'.split('|'),0,{}) + +} + +assertEq(decompressedMochiKit.length, 106415) +assertEq(decompressedMochiKit[2000], '5') +assertEq(decompressedMochiKit[12000], '_') +assertEq(decompressedMochiKit[82556], '>') From f31ff58b3a121052c121e134ed58b1b9fabdc809 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Thu, 4 Mar 2010 15:22:07 -0800 Subject: [PATCH 33/52] No bug: refresh JS_OPMETER feature, no_r=me --- js/src/jsinterp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index b87c735243b9..a9cf1b656d73 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2782,7 +2782,7 @@ js_Interpret(JSContext *cx) JS_EXTENSION_(goto *jumpTable[op]); \ JS_END_MACRO # define DO_NEXT_OP(n) JS_BEGIN_MACRO \ - METER_OP_PAIR(op, regs.pc[n]); \ + METER_OP_PAIR(op, JSOp(regs.pc[n])); \ op = (JSOp) *(regs.pc += (n)); \ DO_OP(); \ JS_END_MACRO From e4d01dd682e07d82116df011df22452432395cd7 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Thu, 4 Mar 2010 16:17:05 -0800 Subject: [PATCH 34/52] Don't include JS-engine internal header files in header files outside the JS engine (bug 549440, r=jst). --- content/base/public/nsContentUtils.h | 3 ++- dom/base/nsDOMClassInfo.cpp | 8 ++++++++ dom/base/nsDOMClassInfo.h | 8 +------- dom/src/json/nsJSON.h | 1 - 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 07f953c5874f..6144e6759c28 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -47,7 +47,6 @@ #include #endif -#include "jsprvtd.h" #include "nsAString.h" #include "nsIStatefulFrame.h" #include "nsINodeInfo.h" @@ -65,6 +64,8 @@ #include "nsReadableUtils.h" #include "nsIPrefBranch2.h" +#include "jsapi.h" + struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error! class nsIDOMScriptObjectFactory; diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 0f5889722281..8814e07dea21 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -66,6 +66,7 @@ #include "jsapi.h" #include "jsprvtd.h" // we are using private JS typedefs... #include "jscntxt.h" +#include "jsobj.h" #include "jsdbgapi.h" // General helper includes @@ -1564,6 +1565,13 @@ GetInternedJSVal(JSContext *cx, const char *str) } // static + +nsISupports * +nsDOMClassInfo::GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj) +{ + return wrapper ? wrapper->Native() : static_cast(obj->getPrivate()); +} + nsresult nsDOMClassInfo::DefineStaticJSVals(JSContext *cx) { diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index 0f8ea3e597af..c2c7b439487e 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -43,7 +43,6 @@ #include "nsIDOMClassInfo.h" #include "nsIXPCScriptable.h" #include "jsapi.h" -#include "jsobj.h" #include "nsIScriptSecurityManager.h" #include "nsIScriptContext.h" #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext @@ -206,12 +205,7 @@ public: static void PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper); - static inline nsISupports *GetNative(nsIXPConnectWrappedNative *wrapper, - JSObject *obj) - { - return wrapper ? wrapper->Native() : - static_cast(obj->getPrivate()); - } + static nsISupports *GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj); static nsIXPConnect *XPConnect() { diff --git a/dom/src/json/nsJSON.h b/dom/src/json/nsJSON.h index 0de0746f2684..a6bf9f760e1f 100644 --- a/dom/src/json/nsJSON.h +++ b/dom/src/json/nsJSON.h @@ -39,7 +39,6 @@ #ifndef nsJSON_h__ #define nsJSON_h__ -#include "jsprvtd.h" #include "jsapi.h" #include "nsIJSON.h" #include "nsString.h" From 6ee558a163fa899997350aa649c1cad8cf7c3929 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 4 Mar 2010 16:32:06 -0800 Subject: [PATCH 35/52] Loosen check-math-partial-sums for floating error (r=dmandelin) --- .../tests/sunspider/check-math-partial-sums.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/js/src/trace-test/tests/sunspider/check-math-partial-sums.js b/js/src/trace-test/tests/sunspider/check-math-partial-sums.js index 21a896a70a3c..a9082702ccf2 100644 --- a/js/src/trace-test/tests/sunspider/check-math-partial-sums.js +++ b/js/src/trace-test/tests/sunspider/check-math-partial-sums.js @@ -26,11 +26,16 @@ function partial(n){ a9 += alt/(2*k -1); } - return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ].join(','); + return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ]; } -var actual = ''; -for (var i = 1024; i <= 16384; i *= 2) { - actual += partial(i) + ';'; -} -assertEq(actual, "2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656;2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243;2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086;2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433;2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998;") +var actual = []; +for (var i = 1024; i <= 16384; i *= 2) + Array.prototype.push.apply(actual, partial(i)); + +var eps = 1e-12; +var expect = [2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656,2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243,2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086,2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433,2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998]; + +assertEq(actual.length, expect.length); +for (var i = 0; i < expect.length; ++i) + assertEq(Math.abs(actual[i] - expect[i]) < eps, true); From 6f2d7df0a07402759fe25d0a70076509a2d74da4 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 4 Mar 2010 00:33:57 -0800 Subject: [PATCH 36/52] Bug 543057 - Drop the Script object (r=brendan) --- js/src/Makefile.ref | 9 - js/src/editline/editline.c | 30 +- js/src/editline/editline.h | 10 +- js/src/jsapi.cpp | 6 - js/src/jsproto.tbl | 69 ++--- js/src/jsscript.cpp | 605 +------------------------------------ js/src/jsversion.h | 10 - js/src/jsxdrapi.h | 2 +- 8 files changed, 51 insertions(+), 690 deletions(-) diff --git a/js/src/Makefile.ref b/js/src/Makefile.ref index edf7f5472b52..50308a2dc5c2 100644 --- a/js/src/Makefile.ref +++ b/js/src/Makefile.ref @@ -95,10 +95,6 @@ ifdef JS_NO_THIN_LOCKS DEFINES += -DJS_USE_ONLY_NSPR_LOCKS endif -ifdef JS_HAS_FILE_OBJECT -DEFINES += -DJS_HAS_FILE_OBJECT -endif - ifdef JS_GC_ZEAL DEFINES += -DJS_GC_ZEAL endif @@ -318,11 +314,6 @@ ifndef BUILD_OPT # $(NULL) endif -ifdef JS_HAS_FILE_OBJECT -JS_CPPFILES += jsfile.cpp -JS_HFILES += jsfile.h -endif - LIB_CPPFILES = $(JS_CPPFILES) LIB_ASFILES := $(wildcard *_$(OS_ARCH).s) PROG_CPPFILES = js.cpp diff --git a/js/src/editline/editline.c b/js/src/editline/editline.c index 6feeaefdbc47..879dd67ea6fe 100644 --- a/js/src/editline/editline.c +++ b/js/src/editline/editline.c @@ -117,11 +117,11 @@ typedef struct _HISTORY { /* ** Globals. */ -int rl_eof; -int rl_erase; -int rl_intr; -int rl_kill; -int rl_quit; +unsigned rl_eof; +unsigned rl_erase; +unsigned rl_intr; +unsigned rl_kill; +unsigned rl_quit; STATIC CHAR NIL[] = ""; STATIC CONST CHAR *Input = NIL; @@ -841,7 +841,7 @@ meta() unsigned int c; KEYMAP *kp; - if ((c = TTYget()) == EOF) + if ((int)(c = TTYget()) == EOF) return CSeof; #if defined(ANSI_ARROWS) /* Also include VT-100 arrows. */ @@ -857,7 +857,7 @@ meta() #endif /* defined(ANSI_ARROWS) */ if (isdigit(c)) { - for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); ) + for (Repeat = c - '0'; (int)(c = TTYget()) != EOF && isdigit(c); ) Repeat = Repeat * 10 + c - '0'; Pushed = 1; PushBack = c; @@ -902,7 +902,7 @@ TTYspecial(c) if (ISMETA(c)) return CSdispatch; - if (c == rl_erase || c == DEL) + if (c == rl_erase || (int)c == DEL) return bk_del_char(); if (c == rl_kill) { if (Point != 0) { @@ -936,7 +936,7 @@ editinput() Line[0] = '\0'; Signal = -1; - while ((c = TTYget()) != EOF) + while ((int)(c = TTYget()) != EOF) switch (TTYspecial(c)) { case CSdone: return Line; @@ -966,7 +966,7 @@ editinput() case CSstay: break; } - if (strlen(Line)) + if (strlen((char *)Line)) return Line; free(Line); return NULL; @@ -1050,7 +1050,7 @@ add_history(p) return; #if defined(UNIQUE_HISTORY) - if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0) + if (H.Size && strcmp(p, (char *)H.Lines[H.Size - 1]) == 0) return; #endif /* defined(UNIQUE_HISTORY) */ hist_add((CHAR *)p); @@ -1113,7 +1113,7 @@ quote() { unsigned int c; - return (c = TTYget()) == EOF ? CSeof : insert_char((int)c); + return (int)(c = TTYget()) == EOF ? CSeof : insert_char((int)c); } STATIC STATUS @@ -1147,9 +1147,9 @@ exchange() unsigned int c; if ((c = TTYget()) != CTL('X')) - return c == EOF ? CSeof : ring_bell(); + return (int)c == EOF ? CSeof : ring_bell(); - if ((c = Mark) <= End) { + if ((int)(c = Mark) <= End) { Mark = Point; Point = c; return CSmove; @@ -1186,7 +1186,7 @@ move_to_char() int i; CHAR *p; - if ((c = TTYget()) == EOF) + if ((int)(c = TTYget()) == EOF) return CSeof; for (i = Point + 1, p = &Line[i]; i < End; i++, p++) if (*p == c) { diff --git a/js/src/editline/editline.h b/js/src/editline/editline.h index e820049bd8ab..41f8f3d3337e 100644 --- a/js/src/editline/editline.h +++ b/js/src/editline/editline.h @@ -108,11 +108,11 @@ typedef unsigned char CHAR; /* ** Variables and routines internal to this package. */ -extern int rl_eof; -extern int rl_erase; -extern int rl_intr; -extern int rl_kill; -extern int rl_quit; +extern unsigned rl_eof; +extern unsigned rl_erase; +extern unsigned rl_intr; +extern unsigned rl_kill; +extern unsigned rl_quit; extern char *rl_complete(); extern int rl_list_possib(); extern void rl_ttyset(); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index d9fe319a9f55..9a9e24e1f425 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1194,9 +1194,6 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj) js_InitStringClass(cx, obj) && js_InitEval(cx, obj) && js_InitTypedArrayClasses(cx, obj) && -#if JS_HAS_SCRIPT_OBJECT - js_InitScriptClass(cx, obj) && -#endif #if JS_HAS_XML_SUPPORT js_InitXMLClasses(cx, obj) && #endif @@ -1255,9 +1252,6 @@ static JSStdName standard_class_atoms[] = { {js_InitStringClass, EAGER_ATOM_AND_CLASP(String)}, {js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)}, {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)}, -#if JS_HAS_SCRIPT_OBJECT - {js_InitScriptClass, EAGER_ATOM_AND_CLASP(Script)}, -#endif #if JS_HAS_XML_SUPPORT {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)}, {js_InitNamespaceClass, EAGER_ATOM_AND_XCLASP(Namespace)}, diff --git a/js/src/jsproto.tbl b/js/src/jsproto.tbl index e433aea5115d..714ac2d8e478 100644 --- a/js/src/jsproto.tbl +++ b/js/src/jsproto.tbl @@ -38,12 +38,6 @@ #include "jsversion.h" -#if JS_HAS_SCRIPT_OBJECT -# define SCRIPT_INIT js_InitScriptClass -#else -# define SCRIPT_INIT js_InitNullClass -#endif - #if JS_HAS_XML_SUPPORT # define XML_INIT js_InitXMLClass # define NAMESPACE_INIT js_InitNamespaceClass @@ -66,12 +60,6 @@ # define GENERATOR_INIT js_InitNullClass #endif -#if JS_HAS_FILE_OBJECT -# define FILE_INIT js_InitFileClass -#else -# define FILE_INIT js_InitNullClass -#endif - /* * Enumerator codes in the second column must not change -- they are part of * the JS XDR API. Client modules including jsproto.tbl should consider @@ -88,41 +76,36 @@ JS_PROTO(Math, 7, js_InitMathClass) JS_PROTO(Number, 8, js_InitNumberClass) JS_PROTO(String, 9, js_InitStringClass) JS_PROTO(RegExp, 10, js_InitRegExpClass) -JS_PROTO(Script, 11, SCRIPT_INIT) -JS_PROTO(XML, 12, XML_INIT) -JS_PROTO(Namespace, 13, NAMESPACE_INIT) -JS_PROTO(QName, 14, QNAME_INIT) -JS_PROTO(AnyName, 15, ANYNAME_INIT) -JS_PROTO(AttributeName, 16, ATTRIBUTE_INIT) -JS_PROTO(Error, 17, js_InitExceptionClasses) -JS_PROTO(InternalError, 18, js_InitExceptionClasses) -JS_PROTO(EvalError, 19, js_InitExceptionClasses) -JS_PROTO(RangeError, 20, js_InitExceptionClasses) -JS_PROTO(ReferenceError, 21, js_InitExceptionClasses) -JS_PROTO(SyntaxError, 22, js_InitExceptionClasses) -JS_PROTO(TypeError, 23, js_InitExceptionClasses) -JS_PROTO(URIError, 24, js_InitExceptionClasses) -JS_PROTO(Generator, 25, GENERATOR_INIT) -JS_PROTO(Iterator, 26, js_InitIteratorClasses) -JS_PROTO(StopIteration, 27, js_InitIteratorClasses) -JS_PROTO(File, 28, FILE_INIT) +JS_PROTO(XML, 11, XML_INIT) +JS_PROTO(Namespace, 12, NAMESPACE_INIT) +JS_PROTO(QName, 13, QNAME_INIT) +JS_PROTO(AnyName, 14, ANYNAME_INIT) +JS_PROTO(AttributeName, 15, ATTRIBUTE_INIT) +JS_PROTO(Error, 16, js_InitExceptionClasses) +JS_PROTO(InternalError, 17, js_InitExceptionClasses) +JS_PROTO(EvalError, 18, js_InitExceptionClasses) +JS_PROTO(RangeError, 19, js_InitExceptionClasses) +JS_PROTO(ReferenceError, 20, js_InitExceptionClasses) +JS_PROTO(SyntaxError, 21, js_InitExceptionClasses) +JS_PROTO(TypeError, 22, js_InitExceptionClasses) +JS_PROTO(URIError, 23, js_InitExceptionClasses) +JS_PROTO(Generator, 24, GENERATOR_INIT) +JS_PROTO(Iterator, 25, js_InitIteratorClasses) +JS_PROTO(StopIteration, 26, js_InitIteratorClasses) +JS_PROTO(ArrayBuffer, 27, js_InitTypedArrayClasses) +JS_PROTO(Int8Array, 28, js_InitTypedArrayClasses) +JS_PROTO(Uint8Array, 29, js_InitTypedArrayClasses) +JS_PROTO(Int16Array, 30, js_InitTypedArrayClasses) +JS_PROTO(Uint16Array, 31, js_InitTypedArrayClasses) +JS_PROTO(Int32Array, 32, js_InitTypedArrayClasses) +JS_PROTO(Uint32Array, 33, js_InitTypedArrayClasses) +JS_PROTO(Float32Array, 34, js_InitTypedArrayClasses) +JS_PROTO(Float64Array, 35, js_InitTypedArrayClasses) +JS_PROTO(Uint8ClampedArray, 36, js_InitTypedArrayClasses) -JS_PROTO(ArrayBuffer, 29, js_InitTypedArrayClasses) -JS_PROTO(Int8Array, 30, js_InitTypedArrayClasses) -JS_PROTO(Uint8Array, 31, js_InitTypedArrayClasses) -JS_PROTO(Int16Array, 32, js_InitTypedArrayClasses) -JS_PROTO(Uint16Array, 33, js_InitTypedArrayClasses) -JS_PROTO(Int32Array, 34, js_InitTypedArrayClasses) -JS_PROTO(Uint32Array, 35, js_InitTypedArrayClasses) -JS_PROTO(Float32Array, 36, js_InitTypedArrayClasses) -JS_PROTO(Float64Array, 37, js_InitTypedArrayClasses) -JS_PROTO(Uint8ClampedArray, 38, js_InitTypedArrayClasses) - -#undef SCRIPT_INIT #undef XML_INIT #undef NAMESPACE_INIT #undef QNAME_INIT #undef ANYNAME_INIT #undef ATTRIBUTE_INIT #undef GENERATOR_INIT -#undef FILE_INIT diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 902a9132361e..da7e1a94fe08 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -72,337 +72,6 @@ using namespace js; const uint32 JSSLOT_EXEC_DEPTH = JSSLOT_PRIVATE + 1; const uint32 JSSCRIPT_RESERVED_SLOTS = 1; -#if JS_HAS_SCRIPT_OBJECT - -static const char js_script_exec_str[] = "Script.prototype.exec"; -static const char js_script_compile_str[] = "Script.prototype.compile"; - -static jsint -GetScriptExecDepth(JSObject *obj) -{ - jsval v = obj->fslots[JSSLOT_EXEC_DEPTH]; - return JSVAL_IS_VOID(v) ? 0 : JSVAL_TO_INT(v); -} - -static void -AdjustScriptExecDepth(JSObject *obj, jsint delta) -{ - jsint execDepth = GetScriptExecDepth(obj); - obj->fslots[JSSLOT_EXEC_DEPTH] = INT_TO_JSVAL(execDepth + delta); -} - -#if JS_HAS_TOSOURCE -static JSBool -script_toSource(JSContext *cx, uintN argc, jsval *vp) -{ - JSObject *obj; - uint32 indent; - JSScript *script; - size_t i, j, k, n; - char buf[16]; - jschar *s, *t; - JSString *str; - - obj = JS_THIS_OBJECT(cx, vp); - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2)) - return JS_FALSE; - - indent = 0; - if (argc != 0) { - indent = js_ValueToECMAUint32(cx, &vp[2]); - if (JSVAL_IS_NULL(vp[2])) - return JS_FALSE; - } - - script = (JSScript *) obj->getPrivate(); - - /* Let n count the source string length, j the "front porch" length. */ - j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name); - n = j + 2; - if (!script) { - /* Let k count the constructor argument string length. */ - k = 0; - s = NULL; /* quell GCC overwarning */ - } else { - str = JS_DecompileScript(cx, script, "Script.prototype.toSource", - (uintN)indent); - if (!str) - return JS_FALSE; - str = js_QuoteString(cx, str, '\''); - if (!str) - return JS_FALSE; - const jschar *cs; - str->getCharsAndLength(cs, k); - s = const_cast(cs); - n += k; - } - - /* Allocate the source string and copy into it. */ - t = (jschar *) cx->malloc((n + 1) * sizeof(jschar)); - if (!t) - return JS_FALSE; - for (i = 0; i < j; i++) - t[i] = buf[i]; - for (j = 0; j < k; i++, j++) - t[i] = s[j]; - t[i++] = ')'; - t[i++] = ')'; - t[i] = 0; - - /* Create and return a JS string for t. */ - str = JS_NewUCString(cx, t, n); - if (!str) { - cx->free(t); - return JS_FALSE; - } - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif /* JS_HAS_TOSOURCE */ - -static JSBool -script_toString(JSContext *cx, uintN argc, jsval *vp) -{ - uint32 indent; - JSObject *obj; - JSScript *script; - JSString *str; - - indent = 0; - if (argc != 0) { - indent = js_ValueToECMAUint32(cx, &vp[2]); - if (JSVAL_IS_NULL(vp[2])) - return JS_FALSE; - } - - obj = JS_THIS_OBJECT(cx, vp); - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2)) - return JS_FALSE; - script = (JSScript *) obj->getPrivate(); - if (!script) { - *vp = STRING_TO_JSVAL(cx->runtime->emptyString); - return JS_TRUE; - } - - str = JS_DecompileScript(cx, script, "Script.prototype.toString", - (uintN)indent); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -script_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - JSObject *scopeobj; - JSScript *script, *oldscript; - JSStackFrame *caller; - const char *file; - uintN line; - JSPrincipals *principals; - jsint execDepth; - - /* Make sure obj is a Script object. */ - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - - /* If no args, leave private undefined and return early. */ - if (argc == 0) - goto out; - - /* Otherwise, the first arg is the script source to compile. */ - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - - scopeobj = NULL; - if (argc >= 2) { - if (!js_ValueToObject(cx, argv[1], &scopeobj)) - return JS_FALSE; - argv[1] = OBJECT_TO_JSVAL(scopeobj); - } - - /* Compile using the caller's scope chain, which js_Invoke passes to fp. */ - caller = js_GetScriptedCaller(cx, NULL); - JS_ASSERT(!caller || cx->fp->scopeChain == caller->scopeChain); - - if (caller) { - if (!scopeobj) { - scopeobj = js_GetScopeChain(cx, caller); - if (!scopeobj) - return JS_FALSE; - } - - principals = JS_EvalFramePrincipals(cx, cx->fp, caller); - file = js_ComputeFilename(cx, caller, principals, &line); - } else { - file = NULL; - line = 0; - principals = NULL; - } - - /* Ensure we compile this script with the right (inner) principals. */ - scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile_str); - if (!scopeobj) - return JS_FALSE; - - /* - * Compile the new script using the caller's scope chain, a la eval(). - * Unlike jsobj.c:obj_eval, however, we do not pass TCF_COMPILE_N_GO in - * tcflags and use NULL for the callerFrame argument, because compilation - * is here separated from execution, and the run-time scope chain may not - * match the compile-time. TCF_COMPILE_N_GO is tested in jsemit.c and - * jsparse.c to optimize based on identity of run- and compile-time scope. - */ - script = JSCompiler::compileScript(cx, scopeobj, NULL, principals, - TCF_NEED_MUTABLE_SCRIPT, - str->chars(), str->length(), - NULL, file, line); - if (!script) - return JS_FALSE; - - JS_LOCK_OBJ(cx, obj); - execDepth = GetScriptExecDepth(obj); - - /* - * execDepth must be 0 to allow compilation here, otherwise the JSScript - * struct can be released while running. - */ - if (execDepth > 0) { - JS_UNLOCK_OBJ(cx, obj); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_COMPILE_EXECED_SCRIPT); - return JS_FALSE; - } - - /* Swap script for obj's old script, if any. */ - oldscript = (JSScript*) obj->getPrivate(); - obj->setPrivate(script); - JS_UNLOCK_OBJ(cx, obj); - - if (oldscript) - js_DestroyScript(cx, oldscript); - - script->u.object = obj; - js_CallNewScriptHook(cx, script, NULL); - -out: - /* Return the object. */ - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -script_compile(JSContext *cx, uintN argc, jsval *vp) -{ - return script_compile_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp); -} - -static JSBool -script_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSObject *scopeobj; - JSStackFrame *caller; - JSPrincipals *principals; - JSScript *script; - JSBool ok; - - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - - scopeobj = NULL; - if (argc != 0) { - if (!js_ValueToObject(cx, argv[0], &scopeobj)) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(scopeobj); - } - - /* - * Emulate eval() by using caller's this, var object, sharp array, etc., - * all propagated by js_Execute via a non-null fourth (down) argument to - * js_Execute. If there is no scripted caller, js_Execute uses its second - * (chain) argument to set the exec frame's varobj, thisv, and scopeChain. - * - * Unlike eval, which the compiler detects, Script.prototype.exec may be - * called from a lightweight function, or even from native code (in which - * fp->scopeChain is null). If exec is called from a lightweight function, - * we will need to get a Call object representing its frame, to act as the - * var object and scope chain head. - */ - caller = js_GetScriptedCaller(cx, NULL); - if (caller && !caller->varobj(cx)) { - /* Called from a lightweight function. */ - JS_ASSERT(caller->fun && !JSFUN_HEAVYWEIGHT_TEST(caller->fun->flags)); - - /* Scope chain links from Call object to caller's scope chain. */ - if (!js_GetCallObject(cx, caller)) - return JS_FALSE; - } - - if (!scopeobj) { - /* No scope object passed in: try to use the caller's scope chain. */ - if (caller) { - /* - * Load caller->scopeChain after the conditional js_GetCallObject - * call above, which resets scopeChain as well as the callobj. - */ - scopeobj = js_GetScopeChain(cx, caller); - if (!scopeobj) - return JS_FALSE; - } else { - /* - * Called from native code, so we don't know what scope object to - * use. We could use the caller's scope chain (see above), but Script.prototype.exec - * might be a shared/sealed "superglobal" method. A more general - * approach would use cx->globalObject, which will be the same as - * exec.__parent__ in the non-superglobal case. In the superglobal - * case it's the right object: the global, not the superglobal. - */ - scopeobj = cx->globalObject; - } - } - - scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec_str); - if (!scopeobj) - return JS_FALSE; - - /* Keep track of nesting depth for the script. */ - AdjustScriptExecDepth(obj, 1); - - /* Must get to out label after this */ - script = (JSScript *) obj->getPrivate(); - if (!script) { - ok = JS_FALSE; - goto out; - } - - /* Belt-and-braces: check that this script object has access to scopeobj. */ - principals = script->principals; - ok = js_CheckPrincipalsAccess(cx, scopeobj, principals, - CLASS_ATOM(cx, Script)); - if (!ok) - goto out; - - ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval); - -out: - AdjustScriptExecDepth(obj, -1); - return ok; -} - -static JSBool -script_exec(JSContext *cx, uintN argc, jsval *vp) -{ - return script_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp); -} - -#endif /* JS_HAS_SCRIPT_OBJECT */ - static const jsbytecode emptyScriptCode[] = {JSOP_STOP, SRC_NULL}; /* static */ const JSScript JSScript::emptyScriptConst = { @@ -717,199 +386,8 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, return JS_FALSE; } -#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW -/* - * These cannot be exposed to web content, and chrome does not need them, so - * we take them out of the Mozilla client altogether. Fortunately, there is - * no way to serialize a native function (see fun_xdrObject in jsfun.c). - */ - -static JSBool -script_freeze(JSContext *cx, uintN argc, jsval *vp) -{ - JSObject *obj; - JSXDRState *xdr; - JSScript *script; - JSBool ok, hasMagic; - uint32 len; - void *buf; - JSString *str; - - obj = JS_THIS_OBJECT(cx, vp); - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2)) - return JS_FALSE; - script = (JSScript *) obj->getPrivate(); - if (!script) - return JS_TRUE; - - /* create new XDR */ - xdr = JS_XDRNewMem(cx, JSXDR_ENCODE); - if (!xdr) - return JS_FALSE; - - /* write */ - ok = js_XDRScript(xdr, &script, false, &hasMagic); - if (!ok) - goto out; - if (!hasMagic) { - *vp = JSVAL_VOID; - goto out; - } - - buf = JS_XDRMemGetData(xdr, &len); - if (!buf) { - ok = JS_FALSE; - goto out; - } - - JS_ASSERT((jsword)buf % sizeof(jschar) == 0); - len /= sizeof(jschar); -#if IS_BIG_ENDIAN - { - jschar *chars; - uint32 i; - - /* Swap bytes in Unichars to keep frozen strings machine-independent. */ - chars = (jschar *)buf; - for (i = 0; i < len; i++) - chars[i] = JSXDR_SWAB16(chars[i]); - } -#endif - str = JS_NewUCStringCopyN(cx, (jschar *)buf, len); - if (!str) { - ok = JS_FALSE; - goto out; - } - - *vp = STRING_TO_JSVAL(str); - -out: - JS_XDRDestroy(xdr); - return ok; -} - -static JSBool -script_thaw(JSContext *cx, uintN argc, jsval *vp) -{ - JSObject *obj; - JSXDRState *xdr; - JSString *str; - void *buf; - size_t len; - JSScript *script, *oldscript; - JSBool ok, hasMagic; - jsint execDepth; - - obj = JS_THIS_OBJECT(cx, vp); - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2)) - return JS_FALSE; - - if (argc == 0) - return JS_TRUE; - str = js_ValueToString(cx, vp[2]); - if (!str) - return JS_FALSE; - vp[2] = STRING_TO_JSVAL(str); - - /* create new XDR */ - xdr = JS_XDRNewMem(cx, JSXDR_DECODE); - if (!xdr) - return JS_FALSE; - - const jschar *cs; - str->getCharsAndLength(cs, len); - buf = const_cast(cs); -#if IS_BIG_ENDIAN - { - jschar *from, *to; - uint32 i; - - /* Swap bytes in Unichars to keep frozen strings machine-independent. */ - from = (jschar *)buf; - to = (jschar *) cx->malloc(len * sizeof(jschar)); - if (!to) { - JS_XDRDestroy(xdr); - return JS_FALSE; - } - for (i = 0; i < len; i++) - to[i] = JSXDR_SWAB16(from[i]); - buf = (char *)to; - } -#endif - len *= sizeof(jschar); - JS_XDRMemSetData(xdr, buf, len); - - /* XXXbe should magic mismatch be error, or false return value? */ - ok = js_XDRScript(xdr, &script, true, &hasMagic); - if (!ok) - goto out; - if (!hasMagic) { - *vp = JSVAL_FALSE; - goto out; - } - - JS_LOCK_OBJ(cx, obj); - execDepth = GetScriptExecDepth(obj); - - /* - * execDepth must be 0 to allow compilation here, otherwise the JSScript - * struct can be released while running. - */ - if (execDepth > 0) { - JS_UNLOCK_OBJ(cx, obj); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_COMPILE_EXECED_SCRIPT); - goto out; - } - - /* Swap script for obj's old script, if any. */ - oldscript = (JSScript *) obj->getPrivate(); - obj->setPrivate(script); - JS_UNLOCK_OBJ(cx, obj); - - if (oldscript) - js_DestroyScript(cx, oldscript); - - script->u.object = obj; - js_CallNewScriptHook(cx, script, NULL); - -out: - /* - * We reset the buffer to be NULL so that it doesn't free the chars - * memory owned by str (vp[2]). - */ - JS_XDRMemSetData(xdr, NULL, 0); - JS_XDRDestroy(xdr); -#if IS_BIG_ENDIAN - cx->free(buf); -#endif - *vp = JSVAL_TRUE; - return ok; -} - -static const char js_thaw_str[] = "thaw"; - -#endif /* JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW */ #endif /* JS_HAS_XDR */ -#if JS_HAS_SCRIPT_OBJECT - -static JSFunctionSpec script_methods[] = { -#if JS_HAS_TOSOURCE - JS_FN(js_toSource_str, script_toSource, 0,0), -#endif - JS_FN(js_toString_str, script_toString, 0,0), - JS_FN("compile", script_compile, 2,0), - JS_FN("exec", script_exec, 1,0), -#if JS_HAS_XDR_FREEZE_THAW - JS_FN("freeze", script_freeze, 0,0), - JS_FN(js_thaw_str, script_thaw, 1,0), -#endif /* JS_HAS_XDR_FREEZE_THAW */ - JS_FS_END -}; - -#endif /* JS_HAS_SCRIPT_OBJECT */ - static void script_finalize(JSContext *cx, JSObject *obj) { @@ -918,16 +396,6 @@ script_finalize(JSContext *cx, JSObject *obj) js_DestroyScript(cx, script); } -static JSBool -script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ -#if JS_HAS_SCRIPT_OBJECT - return script_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval); -#else - return JS_FALSE; -#endif -} - static void script_trace(JSTracer *trc, JSObject *obj) { @@ -936,81 +404,16 @@ script_trace(JSTracer *trc, JSObject *obj) js_TraceScript(trc, script); } -#if !JS_HAS_SCRIPT_OBJECT -#define JSProto_Script JSProto_Object -#endif - -JS_FRIEND_DATA(JSClass) js_ScriptClass = { - js_Script_str, +JSClass js_ScriptClass = { + "Script", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSCRIPT_RESERVED_SLOTS) | - JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Script), + JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize, - NULL, NULL, script_call, NULL,/*XXXbe xdr*/ + NULL, NULL, NULL, NULL,/*XXXbe xdr*/ NULL, NULL, JS_CLASS_TRACE(script_trace), NULL }; -#if JS_HAS_SCRIPT_OBJECT - -static JSBool -Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - /* If not constructing, replace obj with a new Script object. */ - if (!JS_IsConstructing(cx)) { - obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL); - if (!obj) - return JS_FALSE; - - /* - * script_compile_sub does not use rval to root its temporaries so we - * can use it to root obj. - */ - *rval = OBJECT_TO_JSVAL(obj); - } - - if (!JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(0))) - return JS_FALSE; - - return script_compile_sub(cx, obj, argc, argv, rval); -} - -#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW - -static JSBool -script_static_thaw(JSContext *cx, uintN argc, jsval *vp) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL); - if (!obj) - return JS_FALSE; - vp[1] = OBJECT_TO_JSVAL(obj); - if (!script_thaw(cx, argc, vp)) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSFunctionSpec script_static_methods[] = { - JS_FN(js_thaw_str, script_static_thaw, 1,0), - JS_FS_END -}; - -#else /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */ - -#define script_static_methods NULL - -#endif /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */ - -JSObject * -js_InitScriptClass(JSContext *cx, JSObject *obj) -{ - return JS_InitClass(cx, obj, NULL, &js_ScriptClass, Script, 1, - NULL, script_methods, NULL, script_static_methods); -} - -#endif /* JS_HAS_SCRIPT_OBJECT */ - /* * Shared script filename management. */ diff --git a/js/src/jsversion.h b/js/src/jsversion.h index 56c0aa73584a..b5a8328a3d76 100644 --- a/js/src/jsversion.h +++ b/js/src/jsversion.h @@ -88,9 +88,7 @@ #define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */ #define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */ #define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ #define JS_HAS_XDR 0 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ #define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */ #define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ #define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ @@ -120,9 +118,7 @@ #define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ #define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ #define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */ #define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ #define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ #define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ #define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ @@ -148,9 +144,7 @@ #define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ #define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ #define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */ #define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ #define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ #define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ #define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ @@ -176,9 +170,7 @@ #define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ #define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ #define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ #define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ #define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ #define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ #define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ @@ -204,9 +196,7 @@ #define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ #define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ #define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ #define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ #define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ #define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ #define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 4824637ef272..ba9355cd140e 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -205,7 +205,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 61) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 62) /* * Library-private functions. From 73aa8d23f64dd9920284084d61e3c9e8ccd5ae48 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Thu, 4 Mar 2010 17:03:53 -0800 Subject: [PATCH 37/52] Bug 550352: make check-string-tagcloud more robust, r=lw --- js/src/trace-test/tests/sunspider/check-string-tagcloud.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/trace-test/tests/sunspider/check-string-tagcloud.js b/js/src/trace-test/tests/sunspider/check-string-tagcloud.js index d5ece194ae91..f446e46ed5c3 100644 --- a/js/src/trace-test/tests/sunspider/check-string-tagcloud.js +++ b/js/src/trace-test/tests/sunspider/check-string-tagcloud.js @@ -263,4 +263,8 @@ function makeTagCloud(tagInfo) var tagcloud = makeTagCloud(tagInfo); tagInfo = null; -assertEq(tagcloud.length, 315260) + +// The result string embeds floating-point numbers, which can vary a bit on different platforms, +// so we truncate them a bit before comparing. +var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' }) +assertEq(tagcloud_norm.length, 295906) From 9cab0c75a616917a0180df8614985a07cd897120 Mon Sep 17 00:00:00 2001 From: Mike Moening Date: Thu, 4 Mar 2010 20:44:09 -0800 Subject: [PATCH 38/52] bug 549010 - fixing and silencing MSVC warnings. r=brendan,igor --- dom/base/nsDOMClassInfo.cpp | 14 ++-- js/src/jsapi.cpp | 19 +++-- js/src/jsarray.cpp | 84 +++++++++---------- js/src/jsarray.h | 7 +- js/src/jsbuiltins.cpp | 2 +- js/src/jscntxt.cpp | 2 +- js/src/jscntxt.h | 24 +++++- js/src/jsdbgapi.cpp | 2 +- js/src/jsfun.cpp | 8 +- js/src/jsgc.cpp | 8 +- js/src/jsinterp.cpp | 12 +-- js/src/jsinterp.h | 7 +- js/src/jsiter.cpp | 6 +- js/src/jsnum.cpp | 4 +- js/src/jsobj.cpp | 50 +++++------ js/src/jsobj.h | 15 ++-- js/src/json.cpp | 6 +- js/src/jsopcode.h | 10 +++ js/src/jsops.cpp | 18 ++-- js/src/jsparse.cpp | 4 +- js/src/jsprvtd.h | 2 +- js/src/jsrecursion.cpp | 2 +- js/src/jsregexp.cpp | 38 ++++----- js/src/jsscan.cpp | 9 +- js/src/jsscope.h | 9 +- js/src/jsscopeinlines.h | 2 +- js/src/jsscript.cpp | 2 +- js/src/jstracer.cpp | 46 +++++----- js/src/jstypedarray.cpp | 24 +++--- js/src/jsxml.cpp | 8 +- .../xpconnect/src/XPCChromeObjectWrapper.cpp | 2 +- .../xpconnect/src/XPCCrossOriginWrapper.cpp | 6 +- js/src/xpconnect/src/XPCNativeWrapper.cpp | 10 +-- .../xpconnect/src/XPCSafeJSObjectWrapper.cpp | 2 +- js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp | 4 +- js/src/xpconnect/src/XPCWrapper.cpp | 2 +- js/src/xpconnect/src/xpcdebug.cpp | 2 +- js/src/xpconnect/src/xpcwrappednative.cpp | 8 +- js/src/xpconnect/src/xpcwrappednativeinfo.cpp | 2 +- 39 files changed, 260 insertions(+), 222 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 8814e07dea21..00634b47c2a3 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1481,10 +1481,10 @@ FindObjectClass(JSObject* aGlobalObject) JSObject *obj, *proto = aGlobalObject; do { obj = proto; - proto = STOBJ_GET_PROTO(obj); + proto = obj->getProto(); } while (proto); - sObjectClass = STOBJ_GET_CLASS(obj); + sObjectClass = obj->getClass(); } static void @@ -6413,7 +6413,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, #ifdef DEBUG if (!win->IsChromeWindow()) { NS_ASSERTION(JSVAL_IS_OBJECT(v) && - !strcmp(STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name, + !strcmp(JSVAL_TO_OBJECT(v)->getClass()->name, "XPCCrossOriginWrapper"), "Didn't wrap a window!"); } @@ -6526,7 +6526,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, #ifdef DEBUG if (!win->IsChromeWindow()) { NS_ASSERTION(JSVAL_IS_OBJECT(v) && - !strcmp(STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name, + !strcmp(JSVAL_TO_OBJECT(v)->getClass()->name, "XPCCrossOriginWrapper"), "Didn't wrap a location object!"); } @@ -6732,7 +6732,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, wrapper->GetJSObject(&realObj); if (obj == realObj) { - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (proto) { jsid interned_id; JSObject *pobj = NULL; @@ -8474,8 +8474,8 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj, return JS_TRUE; } - while (STOBJ_GET_CLASS(obj) != &sHTMLDocumentAllClass) { - obj = STOBJ_GET_PROTO(obj); + while (obj->getClass() != &sHTMLDocumentAllClass) { + obj = obj->getProto(); if (!obj) { NS_ERROR("The JS engine lies!"); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 9a9e24e1f425..1f430e0ed779 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1145,9 +1145,9 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj) } /* Function.prototype and the global object delegate to Object.prototype. */ - OBJ_SET_PROTO(cx, fun_proto, obj_proto); - if (!OBJ_GET_PROTO(cx, obj)) - OBJ_SET_PROTO(cx, obj, obj_proto); + fun_proto->setProto(obj_proto); + if (!obj->getProto()) + obj->setProto(obj_proto); out: /* If resolving, remove the other entry (Object or Function) from table. */ @@ -1409,7 +1409,7 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, } } - if (!stdnm && !OBJ_GET_PROTO(cx, obj)) { + if (!stdnm && !obj->getProto()) { /* * Try even less frequently used names delegated from the global * object to Object.prototype, but only if the Object class hasn't @@ -2659,7 +2659,7 @@ JS_GetPrototype(JSContext *cx, JSObject *obj) JSObject *proto; CHECK_REQUEST(cx); - proto = OBJ_GET_PROTO(cx, obj); + proto = obj->getProto(); /* Beware ref to dead object (we may be called from obj's finalizer). */ return proto && proto->map ? proto : NULL; @@ -2745,7 +2745,7 @@ JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep) uint32 nslots, i; jsval v; - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj)) + if (obj->isDenseArray() && !js_MakeArraySlow(cx, obj)) return JS_FALSE; if (!OBJ_IS_NATIVE(obj)) { @@ -3064,7 +3064,7 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop, *vp = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2)) ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot) : JSVAL_TRUE; - } else if (OBJ_IS_DENSE_ARRAY(cx, obj2)) { + } else if (obj2->isDenseArray()) { ok = js_GetDenseArrayElementValue(cx, obj2, prop, vp); } else { /* XXX bad API: no way to return "defined but value unknown" */ @@ -3644,7 +3644,7 @@ JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector) JS_PUBLIC_API(JSBool) JS_IsArrayObject(JSContext *cx, JSObject *obj) { - return OBJ_IS_ARRAY(cx, js_GetWrappedObject(cx, obj)); + return js_GetWrappedObject(cx, obj)->isArray(); } JS_PUBLIC_API(JSBool) @@ -5583,7 +5583,8 @@ JS_ClearPendingException(JSContext *cx) JS_PUBLIC_API(JSBool) JS_ReportPendingException(JSContext *cx) { - JSBool save, ok; + JSBool ok; + JSPackedBool save; CHECK_REQUEST(cx); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index b8ff12c1e9de..edf0b43348c3 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -226,7 +226,7 @@ ValueIsLength(JSContext *cx, jsval* vp) JSBool js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) { - if (OBJ_IS_ARRAY(cx, obj)) { + if (obj->isArray()) { *lengthp = obj->fslots[JSSLOT_ARRAY_LENGTH]; return JS_TRUE; } @@ -444,7 +444,7 @@ GetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, JSBool *hole, jsval *vp) { JS_ASSERT(index >= 0); - if (OBJ_IS_DENSE_ARRAY(cx, obj) && index < js_DenseArrayCapacity(obj) && + if (obj->isDenseArray() && index < js_DenseArrayCapacity(obj) && (*vp = obj->dslots[jsuint(index)]) != JSVAL_HOLE) { *hole = JS_FALSE; return JS_TRUE; @@ -484,7 +484,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, jsval v) { JS_ASSERT(index >= 0); - if (OBJ_IS_DENSE_ARRAY(cx, obj)) { + if (obj->isDenseArray()) { /* Predicted/prefetched code should favor the remains-dense case. */ if (index <= jsuint(-1)) { jsuint idx = jsuint(index); @@ -518,7 +518,7 @@ static JSBool DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index) { JS_ASSERT(index >= 0); - if (OBJ_IS_DENSE_ARRAY(cx, obj)) { + if (obj->isDenseArray()) { if (index <= jsuint(-1)) { jsuint idx = jsuint(index); if (!INDEX_TOO_SPARSE(obj, idx) && idx < js_DenseArrayCapacity(obj)) { @@ -615,9 +615,9 @@ static JSBool array_length_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { do { - if (OBJ_IS_ARRAY(cx, obj)) + if (obj->isArray()) return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp); - } while ((obj = OBJ_GET_PROTO(cx, obj)) != NULL); + } while ((obj = obj->getProto()) != NULL); return JS_TRUE; } @@ -630,7 +630,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) JSTempValueRooter tvr; JSBool ok; - if (!OBJ_IS_ARRAY(cx, obj)) { + if (!obj->isArray()) { jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); return obj->defineProperty(cx, lengthId, *vp, NULL, NULL, JSPROP_ENUMERATE); @@ -652,7 +652,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_TRUE; } - if (OBJ_IS_DENSE_ARRAY(cx, obj)) { + if (obj->isDenseArray()) { /* Don't reallocate if we're not actually shrinking our slots. */ jsuint capacity = js_DenseArrayCapacity(obj); if (capacity > newlen && !ResizeSlots(cx, obj, capacity, newlen)) @@ -709,7 +709,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) static inline bool IsDenseArrayId(JSContext *cx, JSObject *obj, jsid id) { - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT(obj->isDenseArray()); uint32 i; return id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom) || @@ -723,7 +723,7 @@ static JSBool array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp) { - if (!OBJ_IS_DENSE_ARRAY(cx, obj)) + if (!obj->isDenseArray()) return js_LookupProperty(cx, obj, id, objp, propp); if (IsDenseArrayId(cx, obj, id)) { @@ -732,7 +732,7 @@ array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, return JS_TRUE; } - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (!proto) { *objp = NULL; *propp = NULL; @@ -776,7 +776,7 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) return JS_TRUE; } - if (!OBJ_IS_DENSE_ARRAY(cx, obj)) + if (!obj->isDenseArray()) return js_GetProperty(cx, obj, id, vp); if (!js_IdIsIndex(ID_TO_VALUE(id), &i) || i >= js_DenseArrayCapacity(obj) || @@ -785,7 +785,7 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) JSProperty *prop; JSScopeProperty *sprop; - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (!proto) { *vp = JSVAL_VOID; return JS_TRUE; @@ -862,7 +862,7 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) return array_length_setter(cx, obj, id, vp); - if (!OBJ_IS_DENSE_ARRAY(cx, obj)) + if (!obj->isDenseArray()) return js_SetProperty(cx, obj, id, vp); if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) { @@ -947,7 +947,7 @@ dense_grow(JSContext* cx, JSObject* obj, jsint i, jsval v) JSBool FASTCALL js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v) { - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT(obj->isDenseArray()); return dense_grow(cx, obj, i, v); } JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, @@ -956,7 +956,7 @@ JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT3 JSBool FASTCALL js_Array_dense_setelem_int(JSContext* cx, JSObject* obj, jsint i, int32 j) { - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT(obj->isDenseArray()); jsval v; if (JS_LIKELY(INT_FITS_IN_JSVAL(j))) { @@ -975,7 +975,7 @@ JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_int, CONTEXT, OBJECT, JSBool FASTCALL js_Array_dense_setelem_double(JSContext* cx, JSObject* obj, jsint i, jsdouble d) { - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT(obj->isDenseArray()); jsval v; jsint j; @@ -1004,7 +1004,7 @@ array_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, return JS_TRUE; isIndex = js_IdIsIndex(ID_TO_VALUE(id), &i); - if (!isIndex || attrs != JSPROP_ENUMERATE || !OBJ_IS_DENSE_ARRAY(cx, obj) || INDEX_TOO_SPARSE(obj, i)) { + if (!isIndex || attrs != JSPROP_ENUMERATE || !obj->isDenseArray() || INDEX_TOO_SPARSE(obj, i)) { if (!ENSURE_SLOW_ARRAY(cx, obj)) return JS_FALSE; return js_DefineProperty(cx, obj, id, value, getter, setter, attrs); @@ -1036,7 +1036,7 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval) { uint32 i; - if (!OBJ_IS_DENSE_ARRAY(cx, obj)) + if (!obj->isDenseArray()) return js_DeleteProperty(cx, obj, id, rval); if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) { @@ -1124,7 +1124,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, switch (enum_op) { case JSENUMERATE_INIT: - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT(obj->isDenseArray()); capacity = js_DenseArrayCapacity(obj); if (idp) *idp = INT_TO_JSVAL(obj->fslots[JSSLOT_ARRAY_COUNT]); @@ -1646,7 +1646,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, jsva * Optimize for dense arrays so long as adding the given set of elements * wouldn't otherwise make the array slow. */ - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj) && + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && start <= MAXINDEX - count && !INDEX_TOO_BIG(start + count)) { #ifdef DEBUG_jwalden @@ -1713,7 +1713,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, jsva return JS_TRUE; /* Finish out any remaining elements past the max array index. */ - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !ENSURE_SLOW_ARRAY(cx, obj)) + if (obj->isDenseArray() && !ENSURE_SLOW_ARRAY(cx, obj)) return JS_FALSE; JS_ASSERT(start == MAXINDEX); @@ -1740,7 +1740,7 @@ static JSBool InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector, JSBool holey = JS_FALSE) { - JS_ASSERT(OBJ_IS_ARRAY(cx, obj)); + JS_ASSERT(obj->isArray()); obj->fslots[JSSLOT_ARRAY_LENGTH] = length; @@ -1819,7 +1819,7 @@ array_reverse(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; *vp = OBJECT_TO_JSVAL(obj); - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj)) { + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj)) { /* An empty array or an array with no elements is already reversed. */ if (len == 0 || !obj->dslots) return JS_TRUE; @@ -2410,7 +2410,7 @@ array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval) JSBool JS_FASTCALL js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v) { - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT(obj->isDenseArray()); uint32_t length = (uint32_t) obj->fslots[JSSLOT_ARRAY_LENGTH]; JS_ASSERT(length <= js_DenseArrayCapacity(obj)); @@ -2437,7 +2437,7 @@ static jsval FASTCALL Array_p_push1(JSContext* cx, JSObject* obj, jsval v) { JSAutoTempValueRooter tvr(cx, v); - if (OBJ_IS_DENSE_ARRAY(cx, obj) + if (obj->isDenseArray() ? array_push1_dense(cx, obj, v, tvr.addr()) : array_push_slowly(cx, obj, 1, tvr.addr(), tvr.addr())) { return tvr.value(); @@ -2456,7 +2456,7 @@ array_push(JSContext *cx, uintN argc, jsval *vp) obj = JS_THIS_OBJECT(cx, vp); if (!obj) return JS_FALSE; - if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj)) + if (argc != 1 || !obj->isDenseArray()) return array_push_slowly(cx, obj, argc, vp + 2, vp); return array_push1_dense(cx, obj, vp[2], vp); @@ -2509,7 +2509,7 @@ static jsval FASTCALL Array_p_pop(JSContext* cx, JSObject* obj) { JSAutoTempValueRooter tvr(cx); - if (OBJ_IS_DENSE_ARRAY(cx, obj) + if (obj->isDenseArray() ? array_pop_dense(cx, obj, tvr.addr()) : array_pop_slowly(cx, obj, tvr.addr())) { return tvr.value(); @@ -2527,7 +2527,7 @@ array_pop(JSContext *cx, uintN argc, jsval *vp) obj = JS_THIS_OBJECT(cx, vp); if (!obj) return JS_FALSE; - if (OBJ_IS_DENSE_ARRAY(cx, obj)) + if (obj->isDenseArray()) return array_pop_dense(cx, obj, vp); return array_pop_slowly(cx, obj, vp); } @@ -2547,7 +2547,7 @@ array_shift(JSContext *cx, uintN argc, jsval *vp) } else { length--; - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj) && + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && length < js_DenseArrayCapacity(obj)) { if (JS_LIKELY(obj->dslots != NULL)) { *vp = obj->dslots[0]; @@ -2606,7 +2606,7 @@ array_unshift(JSContext *cx, uintN argc, jsval *vp) /* Slide up the array to make room for argc at the bottom. */ argv = JS_ARGV(cx, vp); if (length > 0) { - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj) && + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && !INDEX_TOO_SPARSE(obj, unsigned(newlen + argc))) { JS_ASSERT(newlen + argc == length + argc); if (!EnsureCapacity(cx, obj, length + argc)) @@ -2711,7 +2711,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp) /* If there are elements to remove, put them into the return value. */ if (count > 0) { - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj) && + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj2) && end <= js_DenseArrayCapacity(obj)) { if (!InitArrayObject(cx, obj2, count, obj->dslots + begin, @@ -2740,7 +2740,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp) if (argc > count) { delta = (jsuint)argc - count; last = length; - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj) && + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && length <= js_DenseArrayCapacity(obj) && (length == 0 || obj->dslots[length - 1] != JSVAL_HOLE)) { if (!EnsureCapacity(cx, obj, length + delta)) @@ -2767,7 +2767,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp) length += delta; } else if (argc < count) { delta = count - (jsuint)argc; - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_PrototypeHasIndexedProperties(cx, obj) && + if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && length <= js_DenseArrayCapacity(obj)) { /* (uint) end could be 0, so we can't use a vanilla >= test. */ for (last = end; last < length; last++) { @@ -2816,7 +2816,7 @@ array_concat(JSContext *cx, uintN argc, jsval *vp) /* Create a new Array object and root it using *vp. */ aobj = JS_THIS_OBJECT(cx, vp); - if (OBJ_IS_DENSE_ARRAY(cx, aobj)) { + if (aobj->isDenseArray()) { /* * Clone aobj but pass the minimum of its length and capacity, to * handle a = [1,2,3]; a.length = 10000 "dense" cases efficiently. In @@ -2858,7 +2858,7 @@ array_concat(JSContext *cx, uintN argc, jsval *vp) aobj = JSVAL_TO_OBJECT(v); wobj = js_GetWrappedObject(cx, aobj); - if (OBJ_IS_ARRAY(cx, wobj)) { + if (wobj->isArray()) { jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); if (!aobj->getProperty(cx, id, tvr.addr())) return false; @@ -2943,7 +2943,7 @@ array_slice(JSContext *cx, uintN argc, jsval *vp) if (begin > end) begin = end; - if (OBJ_IS_DENSE_ARRAY(cx, obj) && end <= js_DenseArrayCapacity(obj) && + if (obj->isDenseArray() && end <= js_DenseArrayCapacity(obj) && !js_PrototypeHasIndexedProperties(cx, obj)) { nobj = js_NewArrayObject(cx, end - begin, obj->dslots + begin, obj->fslots[JSSLOT_ARRAY_COUNT] != @@ -3302,7 +3302,7 @@ array_isArray(JSContext *cx, uintN argc, jsval *vp) { *vp = BOOLEAN_TO_JSVAL(argc > 0 && !JSVAL_IS_PRIMITIVE(vp[2]) && - OBJ_IS_ARRAY(cx, js_GetWrappedObject(cx, JSVAL_TO_OBJECT(vp[2])))); + js_GetWrappedObject(cx, JSVAL_TO_OBJECT(vp[2]))->isArray()); return JS_TRUE; } @@ -3400,7 +3400,7 @@ JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT); JSObject* JS_FASTCALL js_NewEmptyArray(JSContext* cx, JSObject* proto) { - JS_ASSERT(OBJ_IS_ARRAY(cx, proto)); + JS_ASSERT(proto->isArray()); JSObject* obj = js_NewGCObject(cx); if (!obj) @@ -3517,15 +3517,15 @@ js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) if (!bytes) return JS_FALSE; if (JSVAL_IS_PRIMITIVE(argv[i]) || - !OBJ_IS_ARRAY(cx, (array = JSVAL_TO_OBJECT(argv[i])))) { + !(array = JSVAL_TO_OBJECT(argv[i]))->isArray()) { fprintf(stderr, "%s: not array\n", bytes); cx->free(bytes); continue; } fprintf(stderr, "%s: %s (len %lu", bytes, - OBJ_IS_DENSE_ARRAY(cx, array) ? "dense" : "sparse", + array->isDenseArray()) ? "dense" : "sparse", array->fslots[JSSLOT_ARRAY_LENGTH]); - if (OBJ_IS_DENSE_ARRAY(cx, array)) { + if (array->isDenseArray()) { fprintf(stderr, ", count %lu, capacity %lu", array->fslots[JSSLOT_ARRAY_COUNT], js_DenseArrayCapacity(array)); diff --git a/js/src/jsarray.h b/js/src/jsarray.h index c3a00b874ed9..7305b74760a9 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -67,9 +67,6 @@ JSObject::isArray() const return isDenseArray() || getClass() == &js_SlowArrayClass; } -#define OBJ_IS_DENSE_ARRAY(cx,obj) (obj)->isDenseArray() -#define OBJ_IS_ARRAY(cx,obj) (obj)->isArray() - /* * Dense arrays are not native (OBJ_IS_NATIVE(cx, aobj) for a dense array aobj * results in false, meaning aobj->map does not point to a JSScope). @@ -90,9 +87,9 @@ JSObject::isArray() const * (obj) for the |this| value of a getter, setter, or method call (bug 476447). */ static JS_INLINE JSObject * -js_GetProtoIfDenseArray(JSContext *cx, JSObject *obj) +js_GetProtoIfDenseArray(JSObject *obj) { - return OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj; + return obj->isDenseArray() ? obj->getProto() : obj; } extern JSObject * diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 5e6ea36d091e..6cb207a0aeef 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -288,7 +288,7 @@ 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 = OBJ_GET_PROTO(cx, pobj)) { + for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) { if (pobj->map->ops->lookupProperty != js_LookupProperty) return JSVAL_TO_SPECIAL(JSVAL_VOID); JSClass* clasp = OBJ_GET_CLASS(cx, pobj); diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 1aeace017db2..ba235a5f608c 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1653,7 +1653,7 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback, PopulateReportBlame(cx, &report); if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber, - &message, &report, charArgs, ap)) { + &message, &report, !!charArgs, ap)) { return JS_FALSE; } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index af28604c171e..f96e701acd6b 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -63,6 +63,13 @@ #include "jsvector.h" #include "jshashtable.h" +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */ +#pragma warning(push) +#pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */ +#endif + /* * js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a * given pc in a script. We use the script->code pointer to tag the cache, @@ -125,7 +132,7 @@ struct TreeFragment; struct InterpState; template class Queue; typedef Queue SlotList; -struct TypeMap; +class TypeMap; struct REFragment; typedef nanojit::HashMap REHashMap; @@ -283,7 +290,7 @@ class CallStack return suspendedFrame; } - bool isSuspended() const { return suspendedFrame; } + bool isSuspended() const { return !!suspendedFrame; } void setPrevious(CallStack *cs) { previous = cs; } CallStack *getPrevious() const { return previous; } @@ -417,9 +424,9 @@ struct TraceMonitor { */ REHashMap* reFragments; - // Cached temporary typemap to avoid realloc'ing every time we create one. + // Cached temporary typemap to avoid realloc'ing every time we create one. // This must be used in only one place at a given time. It must be cleared - // before use. + // before use. TypeMap* cachedTempTypeMap; #ifdef DEBUG @@ -1801,6 +1808,10 @@ class JSAutoIdArray { JSIdArray * const idArray; JSTempValueRooter tvr; JS_DECL_USE_GUARD_OBJECT_NOTIFIER + + /* No copy or assignment semantics. */ + JSAutoIdArray(JSAutoIdArray &); + void operator=(JSAutoIdArray &); }; /* The auto-root for enumeration object and its state. */ @@ -2280,4 +2291,9 @@ ContextAllocPolicy::reportAllocOverflow() const } +#ifdef _MSC_VER +#pragma warning(pop) +#pragma warning(pop) +#endif + #endif /* jscntxt_h___ */ diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 7803f7aaf731..f044a1c2e597 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -1465,7 +1465,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, { pd->id = ID_TO_VALUE(sprop->id); - bool wasThrowing = cx->throwing; + JSBool wasThrowing = cx->throwing; JSAutoTempValueRooter lastException(cx, cx->exception); cx->throwing = JS_FALSE; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 3a22950ca196..78800ada07e2 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1178,7 +1178,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, uintN slot, attrs; JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_CallClass); - JS_ASSERT(!STOBJ_GET_PROTO(obj)); + JS_ASSERT(!obj->getProto()); if (!JSVAL_IS_STRING(idval)) return JS_TRUE; @@ -1357,7 +1357,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) { if (slot != FUN_LENGTH) return JS_TRUE; - obj = OBJ_GET_PROTO(cx, obj); + obj = obj->getProto(); if (!obj) return JS_TRUE; } @@ -1614,7 +1614,7 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp) if (!fun) return JS_FALSE; STOBJ_CLEAR_PARENT(FUN_OBJECT(fun)); - STOBJ_CLEAR_PROTO(FUN_OBJECT(fun)); + FUN_OBJECT(fun)->clearProto(); #ifdef __GNUC__ nvars = nargs = nupvars = 0; /* quell GCC uninitialized warning */ #endif @@ -2448,7 +2448,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, fun = (JSFunction *) funobj; /* Initialize all function members. */ - fun->nargs = nargs; + fun->nargs = uint16(nargs); fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO); if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) { JS_ASSERT(!native); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index f5af74f8a0e4..422260b931fe 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -346,7 +346,7 @@ struct JSGCArena { return reinterpret_cast(pageStart); } - bool hasPrevUnmarked() const { return info.prevUnmarkedPage; } + bool hasPrevUnmarked() const { return !!info.prevUnmarkedPage; } JSGCArena *getPrevUnmarked() const { JS_ASSERT(hasPrevUnmarked()); @@ -520,7 +520,7 @@ IsMarkedGCThing(JSGCArena *a, void *thing) { JS_ASSERT(a == JSGCArena::fromGCThing(thing)); jsuword index = ThingToGCCellIndex(thing); - return JS_TEST_BIT(a->markBitmap, index); + return !!JS_TEST_BIT(a->markBitmap, index); } inline bool @@ -529,7 +529,7 @@ IsMarkedGCThing(JSGCArena *a, jsuword thingOffset) JS_ASSERT(thingOffset < GC_ARENA_CELLS_SIZE); JS_ASSERT(!(thingOffset & GC_CELL_MASK)); jsuword index = thingOffset >> GC_CELL_SHIFT; - return JS_TEST_BIT(a->markBitmap, index); + return !!JS_TEST_BIT(a->markBitmap, index); } inline bool @@ -1060,7 +1060,7 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp) sumThings += st->nthings; sumMaxThings += st->maxthings; sumThingSize += thingSize * st->nthings; - sumTotalThingSize += thingSize * st->totalthings; + sumTotalThingSize += size_t(thingSize * st->totalthings); sumArenaCapacity += thingSize * thingsPerArena * st->narenas; sumTotalArenaCapacity += thingSize * thingsPerArena * st->totalarenas; sumAlloc += st->alloc; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index a9cf1b656d73..6a699cb7f6a0 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -155,7 +155,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, protoIndex = 1; for (;;) { - tmp = OBJ_GET_PROTO(cx, tmp); + tmp = tmp->getProto(); /* * We cannot cache properties coming from native objects behind @@ -295,7 +295,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, * matching empty scope. In unusual cases involving * __proto__ assignment we may not find one. */ - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (!proto || !OBJ_IS_NATIVE(proto)) return JS_NO_PROP_CACHE_FILL; JSScope *protoscope = OBJ_SCOPE(proto); @@ -335,7 +335,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, #ifdef DEBUG if (scopeIndex == 0) { JS_ASSERT(protoIndex != 0); - JS_ASSERT((protoIndex == 1) == (OBJ_GET_PROTO(cx, obj) == pobj)); + JS_ASSERT((protoIndex == 1) == (obj->getProto() == pobj)); } #endif @@ -454,7 +454,7 @@ js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, } while (vcap & PCVCAP_PROTOMASK) { - tmp = OBJ_GET_PROTO(cx, pobj); + tmp = pobj->getProto(); if (!tmp || !OBJ_IS_NATIVE(tmp)) break; pobj = tmp; @@ -783,7 +783,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) * be a block either. So we can just grab limitClone's prototype here * regardless of its type or which frame it belongs to. */ - limitBlock = OBJ_GET_PROTO(cx, limitClone); + limitBlock = limitClone->getProto(); /* If the innermost block has already been cloned, we are done. */ if (limitBlock == sharedBlock) @@ -808,7 +808,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) */ JSObject *newChild = innermostNewChild; for (;;) { - JS_ASSERT(OBJ_GET_PROTO(cx, newChild) == sharedBlock); + JS_ASSERT(newChild->getProto() == sharedBlock); sharedBlock = OBJ_GET_PARENT(cx, sharedBlock); /* Sometimes limitBlock will be NULL, so check that first. */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index e5482db3b84a..b6ae9aeee5a7 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -190,12 +190,17 @@ StackBase(JSStackFrame *fp) return fp->slots + fp->script->nfixed; } +#ifdef DEBUG void JSStackFrame::assertValidStackDepth(uintN depth) { JS_ASSERT(0 <= regs->sp - StackBase(this)); JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(this))); } +#else +void +JSStackFrame::assertValidStackDepth(uintN /*depth*/){} +#endif static JS_INLINE uintN GlobalVarCount(JSStackFrame *fp) @@ -416,7 +421,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, pobj = obj; \ JS_ASSERT(PCVCAP_TAG(entry->vcap) <= 1); \ if (PCVCAP_TAG(entry->vcap) == 1 && \ - (tmp_ = OBJ_GET_PROTO(cx, pobj)) != NULL) { \ + (tmp_ = pobj->getProto()) != NULL) { \ pobj = tmp_; \ } \ \ diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index a95b34904572..c1bd9c623c73 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -180,7 +180,7 @@ InitNativeIterator(JSContext *cx, JSObject *iterobj, JSObject *obj, uintN flags) * store the original object. */ JS_ASSERT(obj != iterobj); - STOBJ_SET_PROTO(iterobj, obj); + iterobj->setProto(obj); } return JS_TRUE; } @@ -484,7 +484,7 @@ CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval) JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass); obj = STOBJ_GET_PARENT(iterobj); - origobj = STOBJ_GET_PROTO(iterobj); + origobj = iterobj->getProto(); state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE); if (JSVAL_IS_NULL(state)) goto stop; @@ -530,7 +530,7 @@ CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval) } else #endif { - obj = OBJ_GET_PROTO(cx, obj); + obj = obj->getProto(); if (obj) { STOBJ_SET_PARENT(iterobj, obj); if (!obj->enumerate(cx, JSENUMERATE_INIT, &state, NULL)) diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index bfa18bf87571..d6f9fea43a39 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -421,7 +421,7 @@ num_toString(JSContext *cx, uintN argc, jsval *vp) static JSBool num_toLocaleString(JSContext *cx, uintN argc, jsval *vp) { - char thousandsLength, decimalLength; + size_t thousandsLength, decimalLength; const char *numGrouping, *tmpGroup; JSRuntime *rt; JSString *numStr, *str; @@ -885,7 +885,7 @@ js_NumberToStringWithBase(JSContext *cx, jsdouble d, jsint base) if (jsuint(i) < jsuint(base)) { if (i < 10) return JSString::intString(i); - return JSString::unitString('a' + i - 10); + return JSString::unitString(jschar('a' + i - 10)); } } numStr = NumberToCString(cx, d, base, buf, sizeof buf); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a72f94fd2391..daafecb89cbc 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -305,7 +305,7 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj, JS_LOCK_OBJ(cx, oldproto); JSScope *scope = OBJ_SCOPE(oldproto); scope->protoShapeChange(cx); - JSObject *tmp = STOBJ_GET_PROTO(oldproto); + JSObject *tmp = oldproto->getProto(); JS_UNLOCK_OBJ(cx, oldproto); oldproto = tmp; } @@ -1595,7 +1595,7 @@ obj_watch(JSContext *cx, uintN argc, jsval *vp) return JS_TRUE; *vp = JSVAL_VOID; - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj)) + if (obj->isDenseArray() && !js_MakeArraySlow(cx, obj)) return JS_FALSE; return JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, callable); } @@ -2571,7 +2571,7 @@ DefinePropertyArray(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc * attributes). Such definitions are probably unlikely, so we don't bother * for now. */ - if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj)) + if (obj->isDenseArray() && !js_MakeArraySlow(cx, obj)) return JS_FALSE; jsuint oldLen = obj->fslots[JSSLOT_ARRAY_LENGTH]; @@ -2616,7 +2616,7 @@ static JSBool DefineProperty(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc, bool throwError, bool *rval) { - if (OBJ_IS_ARRAY(cx, obj)) + if (obj->isArray()) return DefinePropertyArray(cx, obj, desc, throwError, rval); if (!OBJ_IS_NATIVE(obj)) @@ -2831,7 +2831,7 @@ static inline bool InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* ops) { JS_ASSERT(ops->isNative()); - JS_ASSERT(proto == OBJ_GET_PROTO(cx, obj)); + JS_ASSERT(proto == obj->getProto()); /* Share proto's emptyScope only if obj is similar to proto. */ JSClass *clasp = OBJ_GET_CLASS(cx, obj); @@ -3243,7 +3243,7 @@ with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, flags = js_InferFlags(cx, flags); flags |= JSRESOLVE_WITH; JSAutoResolveFlags rf(cx, flags); - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_LookupProperty(cx, obj, id, objp, propp); return proto->lookupProperty(cx, id, objp, propp); @@ -3252,7 +3252,7 @@ with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, static JSBool with_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_GetProperty(cx, obj, id, vp); return proto->getProperty(cx, id, vp); @@ -3261,7 +3261,7 @@ with_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) static JSBool with_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_SetProperty(cx, obj, id, vp); return proto->setProperty(cx, id, vp); @@ -3271,7 +3271,7 @@ static JSBool with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, uintN *attrsp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_GetAttributes(cx, obj, id, prop, attrsp); return proto->getAttributes(cx, id, prop, attrsp); @@ -3281,7 +3281,7 @@ static JSBool with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, uintN *attrsp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_SetAttributes(cx, obj, id, prop, attrsp); return proto->setAttributes(cx, id, prop, attrsp); @@ -3290,7 +3290,7 @@ with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, static JSBool with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_DeleteProperty(cx, obj, id, rval); return proto->deleteProperty(cx, id, rval); @@ -3299,7 +3299,7 @@ with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval) static JSBool with_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_DefaultValue(cx, obj, hint, vp); return proto->defaultValue(cx, hint, vp); @@ -3309,7 +3309,7 @@ static JSBool with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, jsval *statep, jsid *idp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_Enumerate(cx, obj, enum_op, statep, idp); return proto->enumerate(cx, enum_op, statep, idp); @@ -3319,7 +3319,7 @@ static JSBool with_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, jsval *vp, uintN *attrsp) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return js_CheckAccess(cx, obj, id, mode, vp, attrsp); return proto->checkAccess(cx, id, mode, vp, attrsp); @@ -3334,7 +3334,7 @@ with_TypeOf(JSContext *cx, JSObject *obj) static JSObject * with_ThisObject(JSContext *cx, JSObject *obj) { - JSObject *proto = OBJ_GET_PROTO(cx, obj); + JSObject *proto = obj->getProto(); if (!proto) return obj; return proto->thisObject(cx); @@ -3804,7 +3804,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ if (OBJ_GET_CLASS(cx, ctor) == clasp) - OBJ_SET_PROTO(cx, ctor, proto); + ctor->setProto(proto); } /* Add properties and methods to the prototype and the constructor. */ @@ -4308,7 +4308,7 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id) while (obj) { if (!OBJ_IS_NATIVE(obj)) { - obj = OBJ_GET_PROTO(cx, obj); + obj = obj->getProto(); continue; } JS_LOCK_OBJ(cx, obj); @@ -4675,7 +4675,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags, } protoIndex = 0; for (proto = start; proto && proto != obj2; - proto = OBJ_GET_PROTO(cx, proto)) { + proto = proto->getProto()) { protoIndex++; } if (!OBJ_IS_NATIVE(obj2)) { @@ -4815,7 +4815,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, JS_ASSERT(protoIndex == 1); } else { /* Call and DeclEnvClass objects have no prototypes. */ - JS_ASSERT(!OBJ_GET_PROTO(cx, obj)); + JS_ASSERT(!obj->getProto()); JS_ASSERT(protoIndex == 0); } } @@ -5072,7 +5072,7 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow, /* Convert string indices to integers if appropriate. */ id = js_CheckForStringIndex(id); - aobj = js_GetProtoIfDenseArray(cx, obj); + aobj = js_GetProtoIfDenseArray(obj); protoIndex = js_LookupPropertyWithFlags(cx, aobj, id, cx->resolveFlags, &obj2, &prop); if (protoIndex < 0) @@ -5172,7 +5172,7 @@ js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, jsval *vp) obj->map->ops->getProperty == js_GetProperty) { return js_GetPropertyHelper(cx, obj, id, getHow, vp); } - JS_ASSERT_IF(getHow & JSGET_CACHE_RESULT, OBJ_IS_DENSE_ARRAY(cx, obj)); + JS_ASSERT_IF(getHow & JSGET_CACHE_RESULT, obj->isDenseArray()); #if JS_HAS_XML_SUPPORT if (OBJECT_IS_XML(cx, obj)) return js_GetXMLMethod(cx, obj, id, vp); @@ -5962,7 +5962,7 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, case JSACC_PROTO: pobj = obj; if (!writing) - *vp = OBJECT_TO_JSVAL(OBJ_GET_PROTO(cx, obj)); + *vp = OBJECT_TO_JSVAL(obj->getProto()); *attrsp = JSPROP_PERMANENT; break; @@ -6208,7 +6208,7 @@ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) if (JSVAL_IS_PRIMITIVE(v)) return JS_TRUE; obj2 = js_GetWrappedObject(cx, JSVAL_TO_OBJECT(v)); - while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL) { + while ((obj2 = obj2->getProto()) != NULL) { if (obj2 == obj) { *bp = JS_TRUE; break; @@ -6814,7 +6814,7 @@ JSObject::isCallable() if (isNative()) return isFunction() || getClass()->call; - return map->ops->call; + return !!map->ops->call; } JSBool @@ -7018,7 +7018,7 @@ js_DumpObject(JSObject *obj) } fprintf(stderr, "proto "); - dumpValue(OBJECT_TO_JSVAL(STOBJ_GET_PROTO(obj))); + dumpValue(OBJECT_TO_JSVAL(obj->getProto())); fputc('\n', stderr); fprintf(stderr, "parent "); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 518b8f74f897..3f8f9ea680e6 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -188,6 +188,11 @@ struct JSObjectMap { explicit JSObjectMap(const JSObjectOps *ops, uint32 shape) : ops(ops), shape(shape) {} enum { SHAPELESS = 0xffffffff }; + +private: + /* No copy or assignment semantics. */ + JSObjectMap(JSObjectMap &); + void operator=(JSObjectMap &); }; const uint32 JS_INITIAL_NSLOTS = 5; @@ -362,7 +367,7 @@ struct JSObject { inline void initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent, jsval privateSlotValue); - inline bool hasSlotsArray() const { return dslots; } + inline bool hasSlotsArray() const { return !!dslots; } /* This method can only be called when hasSlotsArray() returns true. */ inline void freeSlotsArray(JSContext *cx); @@ -441,18 +446,10 @@ struct JSObject { /* Compatibility macros. */ #define OBJ_IS_NATIVE(obj) ((obj)->isNative()) -#define STOBJ_GET_PROTO(obj) ((obj)->getProto()) -#define STOBJ_SET_PROTO(obj,proto) ((obj)->setProto(proto)) -#define STOBJ_CLEAR_PROTO(obj) ((obj)->clearProto()) - #define STOBJ_GET_PARENT(obj) ((obj)->getParent()) #define STOBJ_SET_PARENT(obj,parent) ((obj)->setParent(parent)) #define STOBJ_CLEAR_PARENT(obj) ((obj)->clearParent()) -#define OBJ_GET_PROTO(cx,obj) STOBJ_GET_PROTO(obj) -#define OBJ_SET_PROTO(cx,obj,proto) STOBJ_SET_PROTO(obj, proto) -#define OBJ_CLEAR_PROTO(cx,obj) STOBJ_CLEAR_PROTO(obj) - #define OBJ_GET_PARENT(cx,obj) STOBJ_GET_PARENT(obj) #define OBJ_SET_PARENT(cx,obj,parent) STOBJ_SET_PARENT(obj, parent) #define OBJ_CLEAR_PARENT(cx,obj) STOBJ_CLEAR_PARENT(obj) diff --git a/js/src/json.cpp b/js/src/json.cpp index df76b5676027..af0c1bfd9dfc 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -369,7 +369,7 @@ JO(JSContext *cx, jsval *vp, StringifyContext *scx) if (iterObj) { // Always close the iterator, but make sure not to stomp on OK JS_ASSERT(OBJECT_TO_JSVAL(iterObj) == *keySource); - ok &= js_CloseIterator(cx, *keySource); + ok &= !!js_CloseIterator(cx, *keySource); } if (!ok) @@ -590,7 +590,7 @@ Walk(JSContext *cx, jsid id, JSObject *holder, jsval reviver, jsval *vp) jsval propValue = JSVAL_NULL; JSAutoTempValueRooter tvr(cx, 1, &propValue); - if(OBJ_IS_ARRAY(cx, obj)) { + if(obj->isArray()) { jsuint length = 0; if (!js_GetLengthProperty(cx, obj, &length)) return JS_FALSE; @@ -778,7 +778,7 @@ static JSBool PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value) { JSBool ok; - if (OBJ_IS_ARRAY(cx, parent)) { + if (parent->isArray()) { jsuint len; ok = js_GetLengthProperty(cx, parent, &len); if (ok) { diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 106a4f5a0151..c28a6f84ba4d 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -261,6 +261,12 @@ extern uintN js_NumCodeSpecs; extern const char *js_CodeName[]; extern const char js_EscapeMap[]; +/* Silence unreferenced formal parameter warnings */ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4100) +#endif + /* * Return a GC'ed string containing the chars in str, with any non-printing * chars or quotes (' or " as specified by the quote argument) escaped, and @@ -464,6 +470,10 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v, extern uintN js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + JS_END_EXTERN_C #endif /* jsopcode_h___ */ diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index d1136f00e24b..02ab8fb2ad3b 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -1490,7 +1490,7 @@ BEGIN_CASE(JSOP_GETXPROP) * assuming any property gets it does (e.g., for 'toString' * from JSOP_NEW) will not be leaked to the calling script. */ - aobj = js_GetProtoIfDenseArray(cx, obj); + aobj = js_GetProtoIfDenseArray(obj); if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) { PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom); if (!atom) { @@ -1540,7 +1540,7 @@ BEGIN_CASE(JSOP_LENGTH) str = JSVAL_TO_STRING(lval); regs.sp[-1] = INT_TO_JSVAL(str->length()); } else if (!JSVAL_IS_PRIMITIVE(lval) && - (obj = JSVAL_TO_OBJECT(lval), OBJ_IS_ARRAY(cx, obj))) { + (obj = JSVAL_TO_OBJECT(lval), obj->isArray())) { jsuint length; /* @@ -1586,7 +1586,7 @@ BEGIN_CASE(JSOP_CALLPROP) goto error; } - aobj = js_GetProtoIfDenseArray(cx, obj); + aobj = js_GetProtoIfDenseArray(obj); if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) { PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom); if (!atom) { @@ -1731,7 +1731,7 @@ BEGIN_CASE(JSOP_SETMETHOD) bool checkForAdd; if (sprop->attrs & JSPROP_SHARED) { if (PCVCAP_TAG(entry->vcap) == 0 || - ((obj2 = OBJ_GET_PROTO(cx, obj)) && + ((obj2 = obj->getProto()) && OBJ_IS_NATIVE(obj2) && OBJ_SHAPE(obj2) == PCVCAP_SHAPE(entry->vcap))) { goto fast_set_propcache_hit; @@ -1897,7 +1897,7 @@ BEGIN_CASE(JSOP_GETELEM) VALUE_TO_OBJECT(cx, -2, lval, obj); if (JSVAL_IS_INT(rval)) { - if (OBJ_IS_DENSE_ARRAY(cx, obj)) { + if (obj->isDenseArray()) { jsuint length; length = js_DenseArrayCapacity(obj); @@ -1946,7 +1946,7 @@ BEGIN_CASE(JSOP_SETELEM) FETCH_OBJECT(cx, -3, lval, obj); FETCH_ELEMENT_ID(obj, -2, id); do { - if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) { + if (obj->isDenseArray() && JSID_IS_INT(id)) { jsuint length; length = js_DenseArrayCapacity(obj); @@ -3528,7 +3528,7 @@ BEGIN_CASE(JSOP_INITELEM) * initialiser, set the array length to one greater than id. */ if (rval == JSVAL_HOLE) { - JS_ASSERT(OBJ_IS_ARRAY(cx, obj)); + JS_ASSERT(obj->isArray()); JS_ASSERT(JSID_IS_INT(id)); JS_ASSERT(jsuint(JSID_TO_INT(id)) < JS_ARGS_LENGTH_MAX); if (js_GetOpcode(cx, script, regs.pc + JSOP_INITELEM_LENGTH) == JSOP_ENDINIT && @@ -4026,7 +4026,7 @@ BEGIN_CASE(JSOP_ENTERBLOCK) obj2 = OBJ_GET_PARENT(cx, obj2); if (clasp == &js_BlockClass && obj2->getPrivate() == fp) { - JSObject *youngestProto = OBJ_GET_PROTO(cx, obj2); + JSObject *youngestProto = obj2->getProto(); JS_ASSERT(!OBJ_IS_CLONED_BLOCK(youngestProto)); parent = obj; while ((parent = OBJ_GET_PARENT(cx, parent)) != youngestProto) @@ -4052,7 +4052,7 @@ BEGIN_CASE(JSOP_LEAVEBLOCK) * the stack into the clone, and pop it off the chain. */ obj = fp->scopeChain; - if (OBJ_GET_PROTO(cx, obj) == fp->blockChain) { + if (obj->getProto() == fp->blockChain) { JS_ASSERT (OBJ_GET_CLASS(cx, obj) == &js_BlockClass); if (!js_PutBlockObject(cx, JS_TRUE)) goto error; diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 412b0af7bb5e..da943d3b33ba 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -1826,7 +1826,7 @@ JSCompiler::newFunction(JSTreeContext *tc, JSAtom *atom, uintN lambda) if (fun && !(tc->flags & TCF_COMPILE_N_GO)) { STOBJ_CLEAR_PARENT(FUN_OBJECT(fun)); - STOBJ_CLEAR_PROTO(FUN_OBJECT(fun)); + FUN_OBJECT(fun)->clearProto(); } return fun; } @@ -8605,7 +8605,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, return NULL; if (!(tc->flags & TCF_COMPILE_N_GO)) { STOBJ_CLEAR_PARENT(obj); - STOBJ_CLEAR_PROTO(obj); + obj->clearProto(); } pn->pn_objbox = tc->compiler->newObjectBox(obj); diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index c83cd6ac6f0a..cd78b67bb7a1 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -147,7 +147,7 @@ extern "C++" { namespace js { class TraceRecorder; -class TraceMonitor; +struct TraceMonitor; class CallStack; class ContextAllocPolicy; diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 90028b8b7af7..057fe1d97a92 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -236,7 +236,7 @@ TraceRecorder::upRecursion() */ fi->spdist = cx->fp->down->regs->sp - cx->fp->down->slots; JS_ASSERT(cx->fp->argc == cx->fp->down->argc); - fi->set_argc(cx->fp->argc, false); + fi->set_argc(uint16(cx->fp->argc), false); fi->callerHeight = downPostSlots; fi->callerArgc = cx->fp->down->argc; diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 4a48db78369e..d3586d757292 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -502,7 +502,7 @@ ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, (state->flags & JSREG_FOLD) == 0) { result->op = REOP_ALTPREREQ2; result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr; - result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index; + result->u.altprereq.ch2 = jschar(((RENode *) result->kid)->u.ucclass.index); /* ALTPREREQ2, , uch1, uch2, , ..., JUMP, ... ENDALT */ state->progLength += 13; @@ -515,7 +515,7 @@ ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, result->op = REOP_ALTPREREQ2; result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; result->u.altprereq.ch2 = - ((RENode *) result->u.kid2)->u.ucclass.index; + jschar(((RENode *) result->u.kid2)->u.ucclass.index); /* ALTPREREQ2, , uch1, uch2, , ..., JUMP, ... ENDALT */ state->progLength += 13; @@ -934,7 +934,7 @@ CalculateBitmapSize(CompilerState *state, RENode *target, const jschar *src, while (src != end) { JSBool canStartRange = JS_TRUE; - uintN localMax = 0; + jschar localMax = 0; switch (*src) { case '\\': @@ -987,7 +987,7 @@ lexHex: } n = (n << 4) | digit; } - localMax = n; + localMax = jschar(n); break; case 'd': canStartRange = JS_FALSE; @@ -1048,7 +1048,7 @@ lexHex: src--; } } - localMax = n; + localMax = jschar(n); break; default: @@ -1089,8 +1089,8 @@ lexHex: for (i = rangeStart; i <= localMax; i++) { jschar uch, dch; - uch = upcase(i); - dch = inverse_upcase(i); + uch = jschar(upcase(i)); + dch = inverse_upcase(jschar(i)); maxch = JS_MAX(maxch, uch); maxch = JS_MAX(maxch, dch); } @@ -1098,9 +1098,9 @@ lexHex: } if (localMax > max) - max = localMax; + max = uintN(localMax); } - target->u.ucclass.bmsize = max; + target->u.ucclass.bmsize = uint16(max); return JS_TRUE; } @@ -1973,7 +1973,7 @@ CompileRegExpToAST(JSContext* cx, JSTokenStream* ts, return JS_FALSE; state.cpbegin = state.cp; state.cpend = state.cp + len; - state.flags = flags; + state.flags = uint16(flags); state.parenCount = 0; state.classCount = 0; state.progLength = 0; @@ -3405,7 +3405,7 @@ js_NewRegExp(JSContext *cx, JSTokenStream *ts, re = tmp; } - re->flags = flags; + re->flags = uint16(flags); re->parenCount = state.parenCount; re->source = str; @@ -3888,9 +3888,9 @@ ProcessCharSet(JSContext *cx, JSRegExp *re, RECharSet *charSet) for (i = rangeStart; i <= thisCh; i++) { jschar uch, dch; - AddCharacterToCharSet(charSet, i); - uch = upcase(i); - dch = inverse_upcase(i); + AddCharacterToCharSet(charSet, jschar(i)); + uch = jschar(upcase(i)); + dch = inverse_upcase(jschar(i)); if (i != uch) AddCharacterToCharSet(charSet, uch); if (i != dch) @@ -3902,7 +3902,7 @@ ProcessCharSet(JSContext *cx, JSRegExp *re, RECharSet *charSet) inRange = JS_FALSE; } else { if (re->flags & JSREG_FOLD) { - AddCharacterToCharSet(charSet, upcase(thisCh)); + AddCharacterToCharSet(charSet, jschar(upcase(thisCh))); AddCharacterToCharSet(charSet, inverse_upcase(thisCh)); } else { AddCharacterToCharSet(charSet, thisCh); @@ -4977,7 +4977,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, res = &cx->regExpStatics; res->input = str; - res->parenCount = re->parenCount; + res->parenCount = uint16(re->parenCount); if (re->parenCount == 0) { res->lastParen = js_EmptySubString; } else { @@ -5115,7 +5115,7 @@ regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (!JSVAL_IS_INT(id)) return JS_TRUE; while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) { - obj = OBJ_GET_PROTO(cx, obj); + obj = obj->getProto(); if (!obj) return JS_TRUE; } @@ -5161,7 +5161,7 @@ regexp_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (!JSVAL_IS_INT(id)) return ok; while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) { - obj = OBJ_GET_PROTO(cx, obj); + obj = obj->getProto(); if (!obj) return JS_TRUE; } @@ -5438,7 +5438,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp) if (!obj) return JS_FALSE; STOBJ_CLEAR_PARENT(obj); - STOBJ_CLEAR_PROTO(obj); + obj->clearProto(); re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE); if (!re) return JS_FALSE; diff --git a/js/src/jsscan.cpp b/js/src/jsscan.cpp index dcf0bfd7f2d0..403682b1559d 100644 --- a/js/src/jsscan.cpp +++ b/js/src/jsscan.cpp @@ -494,7 +494,8 @@ ReportCompileErrorNumberVA(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, size_t linelength; jschar *linechars; char *linebytes; - JSBool warning, ok; + bool warning; + JSBool ok; JSTokenPos *tp; uintN index, i; JSErrorReporter onError; @@ -522,7 +523,7 @@ ReportCompileErrorNumberVA(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, errorNumber, &message, &report, !(flags & JSREPORT_UC), ap); if (!ok) { - warning = JS_FALSE; + warning = false; goto out; } @@ -541,14 +542,14 @@ ReportCompileErrorNumberVA(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, linelength = ts->linebuf.limit - ts->linebuf.base; linechars = (jschar *)cx->malloc((linelength + 1) * sizeof(jschar)); if (!linechars) { - warning = JS_FALSE; + warning = false; goto out; } memcpy(linechars, ts->linebuf.base, linelength * sizeof(jschar)); linechars[linelength] = 0; linebytes = js_DeflateString(cx, linechars, linelength); if (!linebytes) { - warning = JS_FALSE; + warning = false; goto out; } report.linebuf = linebytes; diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 3e39a95a8d48..24efc0e5f3bb 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -56,6 +56,8 @@ #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4800) +#pragma warning(push) +#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */ #endif JS_BEGIN_EXTERN_C @@ -553,7 +555,7 @@ js_CastAsObjectJSVal(JSPropertyOp op) } struct JSScopeProperty { - friend class JSScope; + friend struct JSScope; friend void js_SweepScopeProperties(JSContext *cx); friend JSScopeProperty * js_GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent, const JSScopeProperty &child); @@ -600,8 +602,8 @@ private: JSScopeProperty(jsid id, JSPropertyOp getter, JSPropertyOp setter, uint32 slot, uintN attrs, uintN flags, intN shortid) - : id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(attrs), - flags(flags), shortid(shortid) + : id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(uint8(attrs)), + flags(uint8(flags)), shortid(int16(shortid)) { JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER), JSVAL_TO_OBJECT(getterValue())->isCallable()); @@ -964,6 +966,7 @@ JS_END_EXTERN_C #ifdef _MSC_VER #pragma warning(pop) +#pragma warning(pop) #endif #endif /* jsscope_h___ */ diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 43065e2400d9..317606b91694 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -130,7 +130,7 @@ JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp) if (!funobj) return false; *vp = OBJECT_TO_JSVAL(funobj); - return js_SetPropertyHelper(cx, object, sprop->id, 0, vp); + return !!js_SetPropertyHelper(cx, object, sprop->id, 0, vp); } inline bool diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index da7e1a94fe08..01aa5877adf9 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -1019,7 +1019,7 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg) goto bad; } script->nslots = script->nfixed + cg->maxStackDepth; - script->staticLevel = cg->staticLevel; + script->staticLevel = uint16(cg->staticLevel); script->principals = cg->compiler->principals; if (script->principals) JSPRINCIPALS_HOLD(cx, script->principals); diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 92cba42423fa..e74d356bfbc0 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2753,7 +2753,7 @@ TraceMonitor::mark(JSTracer* trc) bool NativeToValue(JSContext* cx, jsval& v, TraceType type, double* slot) { - bool ok; + JSBool ok; jsint i; jsdouble d; switch (type) { @@ -3549,13 +3549,13 @@ TraceRecorder::importGlobalSlot(unsigned slot) /* Add the slot to the list of interned global slots. */ TraceType type; - int index = tree->globalSlots->offsetOf(slot); + int index = tree->globalSlots->offsetOf(uint16(slot)); if (index == -1) { type = getCoercedType(*vp); if (type == TT_INT32 && oracle.isGlobalSlotUndemotable(cx, slot)) type = TT_DOUBLE; index = (int)tree->globalSlots->length(); - tree->globalSlots->add(slot); + tree->globalSlots->add(uint16(slot)); tree->typeMap.add(type); SpecializeTreesToMissingGlobals(cx, globalObj, tree); JS_ASSERT(tree->nGlobalTypes() == tree->globalSlots->length()); @@ -3677,7 +3677,7 @@ TraceRecorder::get(jsval* p) return x; if (isGlobal(p)) { unsigned slot = nativeGlobalSlot(p); - JS_ASSERT(tree->globalSlots->offsetOf(slot) != -1); + JS_ASSERT(tree->globalSlots->offsetOf(uint16(slot)) != -1); importGlobalSlot(slot); } else { unsigned slot = nativeStackSlot(p); @@ -3864,7 +3864,7 @@ TraceRecorder::determineSlotType(jsval* vp) if (i) { m = isPromoteInt(i) ? TT_INT32 : TT_DOUBLE; } else if (isGlobal(vp)) { - int offset = tree->globalSlots->offsetOf(nativeGlobalSlot(vp)); + int offset = tree->globalSlots->offsetOf(uint16(nativeGlobalSlot(vp))); JS_ASSERT(offset != -1); m = importTypeMap[importStackSlots + offset]; } else { @@ -4353,6 +4353,10 @@ class SlotMap : public SlotVisitorBase { } + virtual ~SlotMap() + { + } + JS_REQUIRES_STACK JS_ALWAYS_INLINE void visitGlobalSlot(jsval *vp, unsigned n, unsigned slot) { @@ -4415,7 +4419,7 @@ class SlotMap : public SlotVisitorBase if (LIns* i = mRecorder.getFromTracker(vp)) { promoteInt = isPromoteInt(i); } else if (mRecorder.isGlobal(vp)) { - int offset = mRecorder.tree->globalSlots->offsetOf(mRecorder.nativeGlobalSlot(vp)); + int offset = mRecorder.tree->globalSlots->offsetOf(uint16(mRecorder.nativeGlobalSlot(vp))); JS_ASSERT(offset != -1); promoteInt = mRecorder.importTypeMap[mRecorder.importStackSlots + offset] == TT_INT32; @@ -4520,6 +4524,10 @@ class DefaultSlotMap : public SlotMap DefaultSlotMap(TraceRecorder& tr) : SlotMap(tr) { } + + virtual ~DefaultSlotMap() + { + } JS_REQUIRES_STACK JS_ALWAYS_INLINE bool visitStackSlots(jsval *vp, size_t count, JSStackFrame* fp) @@ -7801,7 +7809,7 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, jsval*& vp, LIns*& ins, NameR JSObject* obj2; JSProperty* prop; JSObject *obj = chainHead; - bool ok = js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &obj2, &prop); + JSBool ok = js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &obj2, &prop); /* js_FindProperty can reenter the interpreter and kill |this|. */ if (!localtm.recorder) @@ -9131,9 +9139,9 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 // hop along the proto chain when accessing a named (not indexed) property, // typically to find Array.prototype methods. JSObject* aobj = obj; - if (OBJ_IS_DENSE_ARRAY(cx, obj)) { + if (obj->isDenseArray()) { guardDenseArray(obj, obj_ins, BRANCH_EXIT); - aobj = OBJ_GET_PROTO(cx, obj); + aobj = obj->getProto(); obj_ins = stobj_get_proto(obj_ins); } @@ -11267,7 +11275,7 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop for (jsuword i = PCVCAP_TAG(entry->vcap) >> PCVCAP_PROTOBITS; i; i--) obj2 = OBJ_GET_PARENT(cx, obj2); for (jsuword j = PCVCAP_TAG(entry->vcap) & PCVCAP_PROTOMASK; j; j--) - obj2 = OBJ_GET_PROTO(cx, obj2); + obj2 = obj2->getProto(); scope = OBJ_SCOPE(obj2); JS_ASSERT_IF(entry->adding(), obj2 == obj); @@ -12106,7 +12114,7 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) } else { RETURN_STOP_A("can't trace setting typed array element to non-number value"); } - } else if (JSVAL_TO_INT(idx) < 0 || !OBJ_IS_DENSE_ARRAY(cx, obj)) { + } else if (JSVAL_TO_INT(idx) < 0 || !obj->isDenseArray()) { CHECK_STATUS_A(initOrSetPropertyByIndex(obj_ins, idx_ins, &v, *cx->fp->regs->pc == JSOP_INITELEM)); } else { @@ -12464,7 +12472,7 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, fi->pc = fp->regs->pc; fi->imacpc = fp->imacpc; fi->spdist = fp->regs->sp - fp->slots; - fi->set_argc(argc, constructing); + fi->set_argc(uint16(argc), constructing); fi->callerHeight = stackSlots - (2 + argc); fi->callerArgc = fp->argc; @@ -12577,7 +12585,7 @@ TraceRecorder::record_JSOP_APPLY() * We trace dense arrays and arguments objects. The code we generate * for apply uses imacros to handle a specific number of arguments. */ - if (OBJ_IS_DENSE_ARRAY(cx, aobj)) { + if (aobj->isDenseArray()) { guardDenseArray(aobj, aobj_ins); length = jsuint(aobj->fslots[JSSLOT_ARRAY_LENGTH]); guard(true, @@ -13754,7 +13762,7 @@ TraceRecorder::record_JSOP_IN() JSObject* obj2; JSProperty* prop; - bool ok = obj->lookupProperty(cx, id, &obj2, &prop); + JSBool ok = obj->lookupProperty(cx, id, &obj2, &prop); /* lookupProperty can reenter the interpreter and kill |this|. */ if (!localtm.recorder) { @@ -14733,7 +14741,7 @@ TraceRecorder::record_JSOP_ARRAYPUSH() JS_ASSERT(cx->fp->slots + slot < cx->fp->regs->sp - 1); jsval &arrayval = cx->fp->slots[slot]; JS_ASSERT(JSVAL_IS_OBJECT(arrayval)); - JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, JSVAL_TO_OBJECT(arrayval))); + JS_ASSERT(JSVAL_TO_OBJECT(arrayval)->isDenseArray()); LIns *array_ins = get(&arrayval); jsval &elt = stackval(-1); LIns *elt_ins = box_jsval(elt, get(&elt)); @@ -14920,7 +14928,7 @@ GetBuiltinFunction(JSContext *cx, uintN index) NULL); if (fun) { funobj = FUN_OBJECT(fun); - STOBJ_CLEAR_PROTO(funobj); + funobj->clearProto(); STOBJ_CLEAR_PARENT(funobj); JS_LOCK_GC(rt); @@ -14996,10 +15004,10 @@ TraceRecorder::record_JSOP_LENGTH() } LIns* v_ins; - if (OBJ_IS_ARRAY(cx, obj)) { - if (OBJ_IS_DENSE_ARRAY(cx, obj)) { + if (obj->isArray()) { + if (obj->isDenseArray()) { if (!guardDenseArray(obj, obj_ins, BRANCH_EXIT)) { - JS_NOT_REACHED("OBJ_IS_DENSE_ARRAY but not?!?"); + JS_NOT_REACHED("obj->isDenseArray() but not?!?"); return ARECORD_STOP; } } else { diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 267f8094b144..0f5a8930e3e9 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -255,7 +255,7 @@ TypedArray::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id, return true; } - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (!proto) { *objp = NULL; *propp = NULL; @@ -401,7 +401,7 @@ struct uint8_clamped { } inline uint8_clamped& operator= (const jsdouble x) { - val = js_TypedArray_uint8_clamp_double(x); + val = uint8(js_TypedArray_uint8_clamp_double(x)); return *this; } @@ -483,7 +483,7 @@ class TypedArrayTemplate JSProperty *prop; JSScopeProperty *sprop; - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (!proto) { *vp = JSVAL_VOID; return true; @@ -1337,31 +1337,31 @@ TypedArrayConstruct(JSContext *cx, jsint atype, uintN argc, jsval *argv, jsval * { switch (atype) { case TypedArray::TYPE_INT8: - return Int8Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Int8Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_UINT8: - return Uint8Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Uint8Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_INT16: - return Int16Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Int16Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_UINT16: - return Uint16Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Uint16Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_INT32: - return Int32Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Int32Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_UINT32: - return Uint32Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Uint32Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_FLOAT32: - return Float32Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Float32Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_FLOAT64: - return Float64Array::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Float64Array::class_constructor(cx, cx->globalObject, argc, argv, rv); case TypedArray::TYPE_UINT8_CLAMPED: - return Uint8ClampedArray::class_constructor(cx, cx->globalObject, argc, argv, rv); + return !!Uint8ClampedArray::class_constructor(cx, cx->globalObject, argc, argv, rv); default: JS_NOT_REACHED("shouldn't have gotten here"); diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 8acd9c1171df..fbca963c2bf7 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -7492,7 +7492,7 @@ js_GetFunctionNamespace(JSContext *cx, jsval *vp) * refer to this instance in scripts. When used to qualify method * names, its prefix and uri references are copied to the QName. */ - OBJ_CLEAR_PROTO(cx, obj); + obj->clearProto(); OBJ_CLEAR_PARENT(cx, obj); JS_LOCK_GC(rt); @@ -7711,7 +7711,7 @@ js_GetAnyName(JSContext *cx, jsval *vp) ok = JS_FALSE; break; } - JS_ASSERT(!OBJ_GET_PROTO(cx, obj)); + JS_ASSERT(!obj->getProto()); JS_ASSERT(!OBJ_GET_PARENT(cx, obj)); } while (0); @@ -7766,7 +7766,7 @@ js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp) /* Skip any With object that can wrap XML. */ target = obj; while (OBJ_GET_CLASS(cx, target) == &js_WithClass) { - proto = OBJ_GET_PROTO(cx, target); + proto = target->getProto(); if (!proto) break; target = proto; @@ -7832,7 +7832,7 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp) ok = JS_TRUE; goto out; } - target = OBJ_GET_PROTO(cx, target); + target = target->getProto(); if (target == NULL) break; tvr.u.object = target; diff --git a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp index c4a51c4b3e0b..70724cadeb6e 100644 --- a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp +++ b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp @@ -342,7 +342,7 @@ JSObject * GetWrapper(JSObject *obj) { while (STOBJ_GET_CLASS(obj) != &COWClass.base) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { break; } diff --git a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp index b396da6f1611..16af17e5cce2 100644 --- a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp +++ b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp @@ -126,7 +126,7 @@ JSObject * GetWrapper(JSObject *obj) { while (STOBJ_GET_CLASS(obj) != &XPCCrossOriginWrapper::XOWClass.base) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { break; } @@ -698,7 +698,7 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp, JSBool checkProto = (isSet && id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PROTO)); if (checkProto) { - proto = STOBJ_GET_PROTO(wrappedObj); + proto = wrappedObj->getProto(); } // Same origin, pass this request along as though nothing interesting @@ -717,7 +717,7 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp, } if (checkProto) { - JSObject *newProto = STOBJ_GET_PROTO(wrappedObj); + JSObject *newProto = wrappedObj->getProto(); // If code is trying to set obj.__proto__ and we're on obj's // prototype chain, then the JS_GetPropertyById above will do the diff --git a/js/src/xpconnect/src/XPCNativeWrapper.cpp b/js/src/xpconnect/src/XPCNativeWrapper.cpp index 1ff00428ee88..843ebd38e465 100644 --- a/js/src/xpconnect/src/XPCNativeWrapper.cpp +++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp @@ -525,7 +525,7 @@ XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, } while (obj && !XPCNativeWrapper::IsNativeWrapper(obj)) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); } if (!obj) { @@ -600,7 +600,7 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp, } while (!XPCNativeWrapper::IsNativeWrapper(obj)) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { return ThrowException(NS_ERROR_UNEXPECTED, cx); } @@ -752,7 +752,7 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, } while (!XPCNativeWrapper::IsNativeWrapper(obj)) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { return ThrowException(NS_ERROR_UNEXPECTED, cx); } @@ -935,7 +935,7 @@ XPCNativeWrapperCtor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, if (JS_FrameIterator(cx, &fp) && JS_IsConstructorFrame(cx, fp)) { constructing = JS_TRUE; - JSObject *proto = STOBJ_GET_PROTO(obj); + JSObject *proto = obj->getProto(); if (proto && !XPCNativeWrapper::IsNativeWrapper(proto)) { // Deal with our prototype object specially. @@ -1137,7 +1137,7 @@ XPC_NW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { while (!XPCNativeWrapper::IsNativeWrapper(obj)) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { return ThrowException(NS_ERROR_UNEXPECTED, cx); } diff --git a/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp b/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp index ddb29d64b9bc..a0ec10566de1 100644 --- a/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp +++ b/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp @@ -214,7 +214,7 @@ static inline JSObject * FindSafeObject(JSObject *obj) { while (STOBJ_GET_CLASS(obj) != &SJOWClass.base) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { break; diff --git a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp index 39811e8f3510..375b57c8efe0 100644 --- a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp +++ b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp @@ -242,7 +242,7 @@ JSObject * GetWrapper(JSObject *obj) { while (STOBJ_GET_CLASS(obj) != &SOWClass.base) { - obj = STOBJ_GET_PROTO(obj); + obj = obj->getProto(); if (!obj) { break; } @@ -346,7 +346,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp) if (native == XPC_SOW_FunctionWrapper) { // If this is a system function wrapper, make sure its ours, otherwise, // its prototype could come from the wrong scope. - if (STOBJ_GET_PROTO(wrapperObj) == STOBJ_GET_PARENT(obj)) { + if (wrapperObj->getProto() == STOBJ_GET_PARENT(obj)) { return JS_TRUE; } diff --git a/js/src/xpconnect/src/XPCWrapper.cpp b/js/src/xpconnect/src/XPCWrapper.cpp index 8278622b9a63..270fa2c00d5e 100644 --- a/js/src/xpconnect/src/XPCWrapper.cpp +++ b/js/src/xpconnect/src/XPCWrapper.cpp @@ -226,7 +226,7 @@ CreateIteratorObj(JSContext *cx, JSObject *tempWrapper, if (!XPCWrapper::Enumerate(cx, iterObj, innerObj)) { return nsnull; } - } while ((innerObj = STOBJ_GET_PROTO(innerObj)) != nsnull); + } while ((innerObj = innerObj->getProto()) != nsnull); JSIdArray *ida = JS_Enumerate(cx, iterObj); if (!ida) { diff --git a/js/src/xpconnect/src/xpcdebug.cpp b/js/src/xpconnect/src/xpcdebug.cpp index c39a080f6315..d69202633fa9 100644 --- a/js/src/xpconnect/src/xpcdebug.cpp +++ b/js/src/xpconnect/src/xpcdebug.cpp @@ -454,7 +454,7 @@ static void PrintObject(JSObject* obj, int depth, ObjectPile* pile) return; JSObject* parent = STOBJ_GET_PARENT(obj); - JSObject* proto = STOBJ_GET_PROTO(obj); + JSObject* proto = obj->getProto(); printf("%*sparent: ", INDENT(depth+1)); if(parent) diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 96f2dd8cf2b5..0f8e9d3f4c4c 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -1570,7 +1570,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx, // is directly using that of its XPCWrappedNativeProto. if(wrapper->HasProto() && - STOBJ_GET_PROTO(flat) == oldProto->GetJSProtoObject()) + flat->getProto() == oldProto->GetJSProtoObject()) { if(!JS_SetPrototype(ccx, flat, newProto->GetJSProtoObject())) { @@ -1665,7 +1665,7 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx, } } - for(cur = obj; cur; cur = STOBJ_GET_PROTO(cur)) + for(cur = obj; cur; cur = cur->getProto()) { // this is on two lines to make the compiler happy given the goto. JSClass* clazz; @@ -1980,14 +1980,14 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx, JSObject* proto = nsnull; JSObject* our_proto = GetProto()->GetJSProtoObject(); - proto = STOBJ_GET_PROTO(jso); + proto = jso->getProto(); NS_ASSERTION(proto && proto != our_proto, "!!! xpconnect/xbl check - wrapper has no special proto"); PRBool found_our_proto = PR_FALSE; while(proto && !found_our_proto) { - proto = STOBJ_GET_PROTO(proto); + proto = proto->getProto(); found_our_proto = proto == our_proto; } diff --git a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp index 180880bd4353..6662cb675757 100644 --- a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp +++ b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp @@ -228,7 +228,7 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface) AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(funobj)); STOBJ_CLEAR_PARENT(funobj); - STOBJ_CLEAR_PROTO(funobj); + funobj->clearProto(); if(!JS_SetReservedSlot(ccx, funobj, 0, PRIVATE_TO_JSVAL(iface))|| !JS_SetReservedSlot(ccx, funobj, 1, PRIVATE_TO_JSVAL(this))) From c1e0163b6ceee4491d3f2cbaf9f8363835d1d6e2 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 4 Mar 2010 23:30:28 -0800 Subject: [PATCH 39/52] Silence MSVC warning about no default assignment operator (r=me) --- js/src/jstl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/src/jstl.h b/js/src/jstl.h index ac71b92200a0..b0bcc3a3bfff 100644 --- a/js/src/jstl.h +++ b/js/src/jstl.h @@ -171,6 +171,10 @@ template inline T *ArrayEnd(T (&arr)[N]) { return arr + N; } /* Useful for implementing containers that assert non-reentrancy */ class ReentrancyGuard { + /* ReentrancyGuard is not copyable. */ + ReentrancyGuard(const ReentrancyGuard &); + void operator=(const ReentrancyGuard &); + #ifdef DEBUG bool &entered; #endif From 382035ba6611be69feee8d25175dde7d9756acb3 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Thu, 4 Mar 2010 23:52:52 -0800 Subject: [PATCH 40/52] bug 549010 - folowup to replace PROTO access macros with the inlne function --- caps/src/nsScriptSecurityManager.cpp | 8 +-- js/src/jsapi.cpp | 14 ++--- js/src/jsdbgapi.cpp | 4 +- js/src/jsemit.cpp | 6 +-- js/src/jsfun.cpp | 14 ++--- js/src/jsinterp.cpp | 38 ++++++-------- js/src/jsiter.cpp | 12 ++--- js/src/jsobj.cpp | 52 +++++++++---------- js/src/jsobj.h | 12 +---- js/src/jsops.cpp | 24 ++++----- js/src/jsparse.cpp | 8 +-- js/src/jsregexp.cpp | 2 +- js/src/jsscopeinlines.h | 2 +- js/src/jsstr.cpp | 2 +- js/src/jstracer.cpp | 28 +++++----- js/src/jsxml.cpp | 8 +-- .../xpconnect/src/XPCCrossOriginWrapper.cpp | 17 +++--- js/src/xpconnect/src/XPCNativeWrapper.cpp | 8 +-- js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp | 6 +-- js/src/xpconnect/src/XPCWrapper.cpp | 2 +- js/src/xpconnect/src/nsXPConnect.cpp | 2 +- js/src/xpconnect/src/xpcconvert.cpp | 2 +- js/src/xpconnect/src/xpcdebug.cpp | 2 +- js/src/xpconnect/src/xpcquickstubs.cpp | 2 +- js/src/xpconnect/src/xpcwrappednative.cpp | 12 ++--- js/src/xpconnect/src/xpcwrappednativeinfo.cpp | 2 +- 26 files changed, 135 insertions(+), 154 deletions(-) diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 39b991653d04..0a5e09983cf8 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -540,7 +540,7 @@ nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj, // Do the same-origin check -- this sets a JS exception if the check fails. // Pass the parent object's class name, as we have no class-info for it. nsresult rv = - ssm->CheckPropertyAccess(cx, target, STOBJ_GET_CLASS(obj)->name, id, + ssm->CheckPropertyAccess(cx, target, obj->getClass()->name, id, (mode & JSACC_WRITE) ? (PRInt32)nsIXPCSecurityManager::ACCESS_SET_PROPERTY : (PRInt32)nsIXPCSecurityManager::ACCESS_GET_PROPERTY); @@ -2315,7 +2315,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj JSObject* origObj = aObj; #endif - const JSClass *jsClass = STOBJ_GET_CLASS(aObj); + const JSClass *jsClass = aObj->getClass(); // A common case seen in this code is that we enter this function // with aObj being a Function object, whose parent is a Call @@ -2392,12 +2392,12 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj } } - aObj = STOBJ_GET_PARENT(aObj); + aObj = aObj->getParent(); if (!aObj) break; - jsClass = STOBJ_GET_CLASS(aObj); + jsClass = aObj->getClass(); } while (1); NS_ASSERTION(!aAllowShortCircuit || diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 1f430e0ed779..5fc0f561ed81 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1657,9 +1657,7 @@ JS_GetScopeChain(JSContext *cx) JS_PUBLIC_API(JSObject *) JS_GetGlobalForObject(JSContext *cx, JSObject *obj) { - JSObject *parent; - - while ((parent = OBJ_GET_PARENT(cx, obj)) != NULL) + while (JSObject *parent = obj->getParent()) obj = parent; return obj; } @@ -2675,9 +2673,7 @@ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto) JS_PUBLIC_API(JSObject *) JS_GetParent(JSContext *cx, JSObject *obj) { - JSObject *parent; - - parent = OBJ_GET_PARENT(cx, obj); + JSObject *parent = obj->getParent(); /* Beware ref to dead object (we may be called from obj's finalizer). */ return parent && parent->map ? parent : NULL; @@ -3967,7 +3963,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp) i = JSVAL_TO_INT(iterobj->fslots[JSSLOT_ITER_INDEX]); if (i < 0) { /* Native case: private data is a property tree node pointer. */ - obj = OBJ_GET_PARENT(cx, iterobj); + obj = iterobj->getParent(); JS_ASSERT(OBJ_IS_NATIVE(obj)); scope = OBJ_SCOPE(obj); sprop = (JSScopeProperty *) iterobj->getPrivate(); @@ -4155,7 +4151,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) JSMSG_BAD_CLONE_FUNOBJ_SCOPE); goto break2; } - obj = OBJ_GET_PARENT(cx, obj); + obj = obj->getParent(); } JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]); @@ -4736,7 +4732,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, JSObject *pobj = obj; uintN depth = 1; - while ((pobj = OBJ_GET_PARENT(cx, pobj)) != NULL) + while ((pobj = pobj->getParent()) != NULL) ++depth; JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth); } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index f044a1c2e597..a964851f3649 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -705,7 +705,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp) frame.fun = fun; frame.argv = argv + 2; frame.down = js_GetTopStackFrame(cx); - frame.scopeChain = OBJ_GET_PARENT(cx, closure); + frame.scopeChain = closure->getParent(); if (script && script->nslots) frame.slots = argv + slotsStart; if (script) { @@ -801,7 +801,7 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) atom = NULL; } wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0, - OBJ_GET_PARENT(cx, js_CastAsObject(setter)), + js_CastAsObject(setter)->getParent(), atom); if (!wrapper) return NULL; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index d281c62ef554..378c20a05721 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -1319,7 +1319,7 @@ js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj, { js_PushStatement(tc, stmt, STMT_BLOCK, top); stmt->flags |= SIF_SCOPE; - STOBJ_SET_PARENT(blockObj, tc->blockChain); + blockObj->setParent(tc->blockChain); stmt->downScope = tc->topScopeStmt; tc->topScopeStmt = stmt; tc->blockChain = blockObj; @@ -1512,7 +1512,7 @@ js_PopStatement(JSTreeContext *tc) if (STMT_LINKS_SCOPE(stmt)) { tc->topScopeStmt = stmt->downScope; if (stmt->flags & SIF_SCOPE) { - tc->blockChain = STOBJ_GET_PARENT(stmt->blockObj); + tc->blockChain = stmt->blockObj->getParent(); JS_SCOPE_DEPTH_METERING(--tc->scopeDepth); } } @@ -2099,7 +2099,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * as their parent by JSCompiler::newFunction. */ JSObject *scopeobj = (cg->flags & TCF_IN_FUNCTION) - ? STOBJ_GET_PARENT(FUN_OBJECT(cg->fun)) + ? FUN_OBJECT(cg->fun)->getParent() : cg->scopeChain; if (scopeobj != caller->varobj(cx)) return JS_TRUE; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 78800ada07e2..d4c0cefc077c 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -253,8 +253,8 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp) * js_GetClassPrototype not being able to find a global object containing * the standard prototype by starting from arguments and following parent. */ - JSObject *parent, *global = fp->scopeChain; - while ((parent = OBJ_GET_PARENT(cx, global)) != NULL) + JSObject *global = fp->scopeChain; + while (JSObject *parent = global->getParent()) global = parent; JS_ASSERT(fp->argv); @@ -924,7 +924,7 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp) /* Clear private pointers to fp, which is about to go away (js_Invoke). */ if (js_IsNamedLambda(fun)) { - JSObject *env = STOBJ_GET_PARENT(callobj); + JSObject *env = callobj->getParent(); JS_ASSERT(STOBJ_GET_CLASS(env) == &js_DeclEnvClass); JS_ASSERT(env->getPrivate() == fp); @@ -1518,7 +1518,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, * object itself. */ JSObject *proto = - js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj)); + js_NewObject(cx, &js_ObjectClass, NULL, obj->getParent()); if (!proto) return JS_FALSE; @@ -1613,7 +1613,7 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp) fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL); if (!fun) return JS_FALSE; - STOBJ_CLEAR_PARENT(FUN_OBJECT(fun)); + FUN_OBJECT(fun)->clearParent(); FUN_OBJECT(fun)->clearProto(); #ifdef __GNUC__ nvars = nargs = nupvars = 0; /* quell GCC uninitialized warning */ @@ -2225,7 +2225,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * its running context's globalObject, which might be different from the * top-level reachable from scopeChain (in HTML frames, e.g.). */ - parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2])); + parent = JSVAL_TO_OBJECT(argv[-2])->getParent(); fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED, parent, cx->runtime->atomState.anonymousAtom); @@ -2438,7 +2438,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, if (funobj) { JS_ASSERT(HAS_FUNCTION_CLASS(funobj)); - OBJ_SET_PARENT(cx, funobj, parent); + funobj->setParent(parent); } else { funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent); if (!funobj) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 6a699cb7f6a0..70a9df1b867c 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -150,7 +150,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, JSObject *tmp = obj; for (uintN i = 0; i != scopeIndex; i++) - tmp = OBJ_GET_PARENT(cx, tmp); + tmp = tmp->getParent(); JS_ASSERT(tmp != pobj); protoIndex = 1; @@ -443,7 +443,7 @@ js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, if (JOF_MODE(cs->format) == JOF_NAME) { while (vcap & (PCVCAP_SCOPEMASK << PCVCAP_PROTOBITS)) { - tmp = OBJ_GET_PARENT(cx, pobj); + tmp = pobj->getParent(); if (!tmp || !OBJ_IS_NATIVE(tmp)) break; pobj = tmp; @@ -762,7 +762,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) */ limitClone = fp->scopeChain; while (OBJ_GET_CLASS(cx, limitClone) == &js_WithClass) - limitClone = OBJ_GET_PARENT(cx, limitClone); + limitClone = limitClone->getParent(); JS_ASSERT(limitClone); /* @@ -809,7 +809,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) JSObject *newChild = innermostNewChild; for (;;) { JS_ASSERT(newChild->getProto() == sharedBlock); - sharedBlock = OBJ_GET_PARENT(cx, sharedBlock); + sharedBlock = sharedBlock->getParent(); /* Sometimes limitBlock will be NULL, so check that first. */ if (sharedBlock == limitBlock || !sharedBlock) @@ -821,14 +821,10 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) if (!clone) return NULL; - /* - * Avoid OBJ_SET_PARENT overhead as newChild cannot escape to - * other threads. - */ - STOBJ_SET_PARENT(newChild, clone); + newChild->setParent(clone); newChild = clone; } - STOBJ_SET_PARENT(newChild, fp->scopeChain); + newChild->setParent(fp->scopeChain); /* @@ -894,7 +890,7 @@ js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv) JSObject *thisp; if (JSVAL_IS_PRIMITIVE(argv[-2]) || - !OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]))) { + !JSVAL_TO_OBJECT(argv[-2])->getParent()) { thisp = cx->globalObject; } else { jsid id; @@ -937,10 +933,8 @@ js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv) return NULL; if (v != JSVAL_NULL) { - thisp = JSVAL_IS_VOID(v) - ? OBJ_GET_PARENT(cx, thisp) - : JSVAL_TO_OBJECT(v); - while ((parent = OBJ_GET_PARENT(cx, thisp)) != NULL) + thisp = JSVAL_IS_VOID(v) ? thisp->getParent() : JSVAL_TO_OBJECT(v); + while ((parent = thisp->getParent()) != NULL) thisp = parent; } } @@ -1135,8 +1129,8 @@ js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags) goto bad; funobj = JSVAL_TO_OBJECT(v); - parent = OBJ_GET_PARENT(cx, funobj); - clasp = OBJ_GET_CLASS(cx, funobj); + parent = funobj->getParent(); + clasp = funobj->getClass(); if (clasp != &js_FunctionClass) { #if JS_HAS_NO_SUCH_METHOD if (clasp == &js_NoSuchMethodClass) { @@ -1561,7 +1555,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, frame.argsobj = NULL; JSObject *obj = chain; if (cx->options & JSOPTION_VAROBJFIX) { - while (JSObject *tmp = OBJ_GET_PARENT(cx, obj)) + while (JSObject *tmp = obj->getParent()) obj = tmp; } frame.fun = NULL; @@ -1899,9 +1893,9 @@ js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp) } rval = vp[1]; proto = JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL; - parent = OBJ_GET_PARENT(cx, obj2); + parent = obj2->getParent(); - if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) { + if (obj2->getClass() == &js_FunctionClass) { fun2 = GET_FUNCTION_PRIVATE(cx, obj2); if (!FUN_INTERPRETED(fun2) && fun2->u.n.clasp) clasp = fun2->u.n.clasp; @@ -2005,7 +1999,7 @@ js_LeaveWith(JSContext *cx) JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass); JS_ASSERT(withobj->getPrivate() == cx->fp); JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0); - cx->fp->scopeChain = OBJ_GET_PARENT(cx, withobj); + cx->fp->scopeChain = withobj->getParent(); withobj->setPrivate(NULL); } @@ -2037,7 +2031,7 @@ js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth, JS_ASSERT(stackDepth >= 0); JS_ASSERT(StackBase(fp) + stackDepth <= fp->regs->sp); - for (obj = fp->blockChain; obj; obj = OBJ_GET_PARENT(cx, obj)) { + for (obj = fp->blockChain; obj; obj = obj->getParent()) { JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass); if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth) break; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index c1bd9c623c73..eaa3c872cd6e 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -153,7 +153,7 @@ InitNativeIterator(JSContext *cx, JSObject *iterobj, JSObject *obj, uintN flags) JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass); /* Initialize iterobj in case of enumerate hook failure. */ - STOBJ_SET_PARENT(iterobj, obj); + iterobj->setParent(obj); STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, JSVAL_NULL); STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_FLAGS, INT_TO_JSVAL(flags)); if (!js_RegisterCloseableIterator(cx, iterobj)) @@ -239,9 +239,9 @@ IteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval) JSBool foreach, ok; jsid id; - JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_IteratorClass); + JS_ASSERT(obj->getClass() == &js_IteratorClass); - iterable = OBJ_GET_PARENT(cx, obj); + iterable = obj->getParent(); JS_ASSERT(iterable); state = STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE); if (JSVAL_IS_NULL(state)) @@ -481,9 +481,9 @@ CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval) JSString *str; JS_ASSERT(flags & JSITER_ENUMERATE); - JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass); + JS_ASSERT(iterobj->getClass() == &js_IteratorClass); - obj = STOBJ_GET_PARENT(iterobj); + obj = iterobj->getParent(); origobj = iterobj->getProto(); state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE); if (JSVAL_IS_NULL(state)) @@ -532,7 +532,7 @@ CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval) { obj = obj->getProto(); if (obj) { - STOBJ_SET_PARENT(iterobj, obj); + iterobj->setParent(obj); if (!obj->enumerate(cx, JSENUMERATE_INIT, &state, NULL)) return JS_FALSE; STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index daafecb89cbc..e63105d74d24 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1174,7 +1174,7 @@ js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller } } - scopeobj = OBJ_GET_PARENT(cx, scopeobj); + scopeobj = scopeobj->getParent(); } return inner; @@ -1272,7 +1272,7 @@ obj_eval(JSContext *cx, uintN argc, jsval *vp) * the former indirect case. */ { - JSObject *parent = OBJ_GET_PARENT(cx, obj); + JSObject *parent = obj->getParent(); if (indirectCall || parent) { uintN flags = parent ? JSREPORT_ERROR @@ -1346,7 +1346,7 @@ obj_eval(JSContext *cx, uintN argc, jsval *vp) } /* NB: We know obj is a global object here. */ - JS_ASSERT(!OBJ_GET_PARENT(cx, obj)); + JS_ASSERT(!obj->getParent()); scopeobj = obj; } else { /* @@ -1458,7 +1458,7 @@ obj_eval(JSContext *cx, uintN argc, jsval *vp) } } if (i < 0 || - STOBJ_GET_PARENT(objarray->vector[i]) == scopeobj) { + objarray->vector[i]->getParent() == scopeobj) { JS_ASSERT(staticLevel == script->staticLevel); EVAL_CACHE_METER(hit); *scriptp = script->u.nextToGC; @@ -3099,7 +3099,7 @@ js_NewInstance(JSContext *cx, JSClass *clasp, JSObject *ctor) proto = JSVAL_TO_OBJECT(pval); } else if (pval == JSVAL_HOLE) { /* No ctor.prototype yet, inline and optimize fun_resolve's prototype code. */ - proto = js_NewObject(cx, clasp, NULL, OBJ_GET_PARENT(cx, ctor)); + proto = js_NewObject(cx, clasp, NULL, ctor->getParent()); if (!proto) return NULL; if (!js_SetClassPrototype(cx, ctor, proto, JSPROP_ENUMERATE | JSPROP_PERMANENT)) @@ -3464,7 +3464,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind) /* We must clear the private slot even with errors. */ obj->setPrivate(NULL); - fp->scopeChain = OBJ_GET_PARENT(cx, obj); + fp->scopeChain = obj->getParent(); return normalUnwind; } @@ -3578,7 +3578,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp) if (xdr->mode == JSXDR_ENCODE) { obj = *objp; - parent = OBJ_GET_PARENT(cx, obj); + parent = obj->getParent(); parentId = (xdr->script->objectsOffset == 0) ? NO_PARENT_INDEX : FindObjectIndex(xdr->script->objects(), parent); @@ -3609,7 +3609,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp) parent = NULL; else parent = xdr->script->getObject(parentId); - STOBJ_SET_PARENT(obj, parent); + obj->setParent(parent); } JSAutoTempValueRooter tvr(cx, obj); @@ -4003,7 +4003,7 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObjectOp init; jsval v; - while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL) + while ((tmp = obj->getParent()) != NULL) obj = tmp; if (!(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) { *objp = NULL; @@ -4049,7 +4049,7 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSBool js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj) { - JS_ASSERT(!OBJ_GET_PARENT(cx, obj)); + JS_ASSERT(!obj->getParent()); if (!(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) return JS_TRUE; @@ -4080,7 +4080,7 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey, /* Find the topmost object in the scope chain. */ do { obj = start; - start = OBJ_GET_PARENT(cx, obj); + start = obj->getParent(); } while (start); } else { obj = cx->globalObject; @@ -4159,7 +4159,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, */ ctor = JSVAL_TO_OBJECT(cval); if (!parent) - parent = OBJ_GET_PARENT(cx, ctor); + parent = ctor->getParent(); if (!proto) { if (!ctor->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &rval)) { @@ -4319,7 +4319,7 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id) scope->shadowingShapeChange(cx, sprop); JS_UNLOCK_SCOPE(cx, scope); - if (!STOBJ_GET_PARENT(obj)) { + if (!obj->getParent()) { /* * All scope chains end in a global object, so this will change * the global shape. jstracer.cpp assumes that the global shape @@ -4348,7 +4348,7 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id) * may gain such properties via eval introducing new vars; see bug 490364. */ if (STOBJ_GET_CLASS(obj) == &js_CallClass) { - while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL) { + while ((obj = obj->getParent()) != NULL) { if (PurgeProtoChain(cx, obj, id)) break; } @@ -4788,7 +4788,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, /* Scan entries on the scope chain that we can cache across. */ entry = JS_NO_PROP_CACHE_FILL; obj = scopeChain; - parent = OBJ_GET_PARENT(cx, obj); + parent = obj->getParent(); for (scopeIndex = 0; parent ? js_IsCacheableNonGlobalScope(obj) @@ -4834,7 +4834,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, goto out; } obj = parent; - parent = OBJ_GET_PARENT(cx, obj); + parent = obj->getParent(); } for (;;) { @@ -4849,7 +4849,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, * We conservatively assume that a resolve hook could mutate the scope * chain during JSObject::lookupProperty. So we read parent here again. */ - parent = OBJ_GET_PARENT(cx, obj); + parent = obj->getParent(); if (!parent) { pobj = NULL; break; @@ -4879,7 +4879,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id) * This function should not be called for a global object or from the * trace and should have a valid cache entry for native scopeChain. */ - JS_ASSERT(OBJ_GET_PARENT(cx, scopeChain)); + JS_ASSERT(scopeChain->getParent()); JS_ASSERT(!JS_ON_TRACE(cx)); JSObject *obj = scopeChain; @@ -4913,8 +4913,8 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id) } /* Call and other cacheable objects always have a parent. */ - obj = OBJ_GET_PARENT(cx, obj); - if (!OBJ_GET_PARENT(cx, obj)) + obj = obj->getParent(); + if (!obj->getParent()) return obj; } @@ -4934,11 +4934,11 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id) * chain during JSObject::lookupProperty. So we must check if parent is * not null here even if it wasn't before the lookup. */ - JSObject *parent = OBJ_GET_PARENT(cx, obj); + JSObject *parent = obj->getParent(); if (!parent) break; obj = parent; - } while (OBJ_GET_PARENT(cx, obj)); + } while (obj->getParent()); return obj; } @@ -5260,7 +5260,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, /* We should never add properties to lexical blocks. */ JS_ASSERT(OBJ_GET_CLASS(cx, obj) != &js_BlockClass); - if (!OBJ_GET_PARENT(cx, obj) && !js_CheckUndeclaredVarAssignment(cx)) + if (!obj->getParent() && !js_CheckUndeclaredVarAssignment(cx)) return JS_FALSE; } sprop = (JSScopeProperty *) prop; @@ -5969,7 +5969,7 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, case JSACC_PARENT: JS_ASSERT(!writing); pobj = obj; - *vp = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, obj)); + *vp = OBJECT_TO_JSVAL(obj->getParent()); *attrsp = JSPROP_READONLY | JSPROP_PERMANENT; break; @@ -6078,7 +6078,7 @@ GetCurrentExecutionContext(JSContext *cx, JSObject *obj, jsval *rval) JSObject *tmp; jsval xcval; - while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL) + while ((tmp = obj->getParent()) != NULL) obj = tmp; if (!obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.ExecutionContextAtom), &xcval)) return JS_FALSE; @@ -7022,7 +7022,7 @@ js_DumpObject(JSObject *obj) fputc('\n', stderr); fprintf(stderr, "parent "); - dumpValue(OBJECT_TO_JSVAL(STOBJ_GET_PARENT(obj))); + dumpValue(OBJECT_TO_JSVAL(obj->getParent())); fputc('\n', stderr); i = JSSLOT_PRIVATE; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 3f8f9ea680e6..512cbaef7e56 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -443,17 +443,9 @@ struct JSObject { inline bool unbrand(JSContext *cx); }; -/* Compatibility macros. */ +/* Compatibility macro. */ #define OBJ_IS_NATIVE(obj) ((obj)->isNative()) -#define STOBJ_GET_PARENT(obj) ((obj)->getParent()) -#define STOBJ_SET_PARENT(obj,parent) ((obj)->setParent(parent)) -#define STOBJ_CLEAR_PARENT(obj) ((obj)->clearParent()) - -#define OBJ_GET_PARENT(cx,obj) STOBJ_GET_PARENT(obj) -#define OBJ_SET_PARENT(cx,obj,parent) STOBJ_SET_PARENT(obj, parent) -#define OBJ_CLEAR_PARENT(cx,obj) STOBJ_CLEAR_PARENT(obj) - #define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \ ? JSSLOT_PRIVATE + 1 \ : JSSLOT_PRIVATE) @@ -889,7 +881,7 @@ js_IsCacheableNonGlobalScope(JSObject *obj) { extern JS_FRIEND_DATA(JSClass) js_CallClass; extern JS_FRIEND_DATA(JSClass) js_DeclEnvClass; - JS_ASSERT(STOBJ_GET_PARENT(obj)); + JS_ASSERT(obj->getParent()); JSClass *clasp = STOBJ_GET_CLASS(obj); bool cacheable = (clasp == &js_CallClass || diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index 02ab8fb2ad3b..15b540a8d49d 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -144,7 +144,7 @@ BEGIN_CASE(JSOP_POPN) JS_ASSERT_IF(obj, OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj) <= (size_t) (regs.sp - StackBase(fp))); - for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) { + for (obj = fp->scopeChain; obj; obj = obj->getParent()) { clasp = OBJ_GET_CLASS(cx, obj); if (clasp != &js_BlockClass && clasp != &js_WithClass) continue; @@ -714,7 +714,7 @@ BEGIN_CASE(JSOP_BINDNAME) * forms. */ obj = fp->scopeChain; - if (!OBJ_GET_PARENT(cx, obj)) + if (!obj->getParent()) break; if (JS_LIKELY(OBJ_IS_NATIVE(obj))) { PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom); @@ -2003,7 +2003,7 @@ BEGIN_CASE(JSOP_NEW) rval = vp[1]; obj2 = js_NewObject(cx, &js_ObjectClass, JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL, - OBJ_GET_PARENT(cx, obj)); + obj->getParent()); if (!obj2) goto error; @@ -2133,7 +2133,7 @@ BEGIN_CASE(JSOP_APPLY) newifp->frame.rval = JSVAL_VOID; newifp->frame.down = fp; newifp->frame.annotation = NULL; - newifp->frame.scopeChain = parent = OBJ_GET_PARENT(cx, obj); + newifp->frame.scopeChain = parent = obj->getParent(); newifp->frame.flags = flags; newifp->frame.blockChain = NULL; if (script->staticLevel < JS_DISPLAY_SIZE) { @@ -2919,7 +2919,7 @@ BEGIN_CASE(JSOP_DEFFUN) * windows, and user-defined JS functions precompiled and then shared among * requests in server-side JS. */ - if (OBJ_GET_PARENT(cx, obj) != obj2) { + if (obj->getParent() != obj2) { obj = CloneFunctionObject(cx, fun, obj2); if (!obj) goto error; @@ -3091,7 +3091,7 @@ BEGIN_CASE(JSOP_DEFLOCALFUN) if (!parent) goto error; - if (OBJ_GET_PARENT(cx, obj) != parent) { + if (obj->getParent() != parent) { #ifdef JS_TRACER if (TRACE_RECORDER(cx)) AbortRecording(cx, "DEFLOCALFUN for closure"); @@ -3142,7 +3142,7 @@ BEGIN_CASE(JSOP_LAMBDA) if (FUN_NULL_CLOSURE(fun)) { parent = fp->scopeChain; - if (OBJ_GET_PARENT(cx, obj) == parent) { + if (obj->getParent() == parent) { op = JSOp(regs.pc[JSOP_LAMBDA_LENGTH]); /* @@ -4012,7 +4012,7 @@ BEGIN_CASE(JSOP_ENTERBLOCK) } #ifdef DEBUG - JS_ASSERT(fp->blockChain == OBJ_GET_PARENT(cx, obj)); + JS_ASSERT(fp->blockChain == obj->getParent()); /* * The young end of fp->scopeChain may omit blocks if we haven't closed @@ -4022,14 +4022,14 @@ BEGIN_CASE(JSOP_ENTERBLOCK) * static scope. */ obj2 = fp->scopeChain; - while ((clasp = OBJ_GET_CLASS(cx, obj2)) == &js_WithClass) - obj2 = OBJ_GET_PARENT(cx, obj2); + while ((clasp = obj2->getClass()) == &js_WithClass) + obj2 = obj2->getParent(); if (clasp == &js_BlockClass && obj2->getPrivate() == fp) { JSObject *youngestProto = obj2->getProto(); JS_ASSERT(!OBJ_IS_CLONED_BLOCK(youngestProto)); parent = obj; - while ((parent = OBJ_GET_PARENT(cx, parent)) != youngestProto) + while ((parent = parent->getParent()) != youngestProto) JS_ASSERT(parent); } #endif @@ -4059,7 +4059,7 @@ BEGIN_CASE(JSOP_LEAVEBLOCK) } /* Pop the block chain, too. */ - fp->blockChain = OBJ_GET_PARENT(cx, fp->blockChain); + fp->blockChain = fp->blockChain->getParent(); /* Move the result of the expression to the new topmost stack slot. */ if (op == JSOP_LEAVEBLOCKEXPR) diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index da943d3b33ba..391d4b67ae41 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -1063,7 +1063,7 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal if (script) { JSObject *obj = scopeChain; uintN depth = 1; - while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL) + while ((obj = obj->getParent()) != NULL) ++depth; JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth); } @@ -1825,7 +1825,7 @@ JSCompiler::newFunction(JSTreeContext *tc, JSAtom *atom, uintN lambda) parent, atom); if (fun && !(tc->flags & TCF_COMPILE_N_GO)) { - STOBJ_CLEAR_PARENT(FUN_OBJECT(fun)); + FUN_OBJECT(fun)->clearParent(); FUN_OBJECT(fun)->clearProto(); } return fun; @@ -5600,7 +5600,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) JS_SCOPE_DEPTH_METERING(++tc->scopeDepth > tc->maxScopeDepth && (tc->maxScopeDepth = tc->scopeDepth)); - STOBJ_SET_PARENT(obj, tc->blockChain); + obj->setParent(tc->blockChain); tc->blockChain = obj; stmt->blockObj = obj; @@ -8604,7 +8604,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, if (!obj) return NULL; if (!(tc->flags & TCF_COMPILE_N_GO)) { - STOBJ_CLEAR_PARENT(obj); + obj->clearParent(); obj->clearProto(); } diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index d3586d757292..6642ae5a558a 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -5437,7 +5437,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp) obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL); if (!obj) return JS_FALSE; - STOBJ_CLEAR_PARENT(obj); + obj->clearParent(); obj->clearProto(); re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE); if (!re) diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 317606b91694..ba0fbc71935d 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -126,7 +126,7 @@ JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp) JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); JS_ASSERT(FUN_OBJECT(fun) == funobj && FUN_NULL_CLOSURE(fun)); - funobj = CloneFunctionObject(cx, fun, OBJ_GET_PARENT(cx, funobj)); + funobj = CloneFunctionObject(cx, fun, funobj->getParent()); if (!funobj) return false; *vp = OBJECT_TO_JSVAL(funobj); diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 90cdc69970fd..ca9893f3960a 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1787,7 +1787,7 @@ FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep) /* Push lambda and its 'this' parameter. */ jsval *sp = invokevp; *sp++ = OBJECT_TO_JSVAL(lambda); - *sp++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, lambda)); + *sp++ = OBJECT_TO_JSVAL(lambda->getParent()); /* Push $&, $1, $2, ... */ if (!PushRegExpSubstr(cx, cx->regExpStatics.lastMatch, sp)) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index e74d356bfbc0..bdec0d749c2c 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -5487,7 +5487,7 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee) #ifdef DEBUG if (fi.block != fp->blockChain) { - for (JSObject* obj = fi.block; obj != fp->blockChain; obj = STOBJ_GET_PARENT(obj)) + for (JSObject* obj = fi.block; obj != fp->blockChain; obj = obj->getParent()) JS_ASSERT(obj); } #endif @@ -6414,7 +6414,7 @@ ScopeChainCheck(JSContext* cx, TreeFragment* f) * either check causes an early return from execution. */ JSObject* child = cx->fp->scopeChain; - while (JSObject* parent = OBJ_GET_PARENT(cx, child)) { + while (JSObject* parent = child->getParent()) { if (!js_IsCacheableNonGlobalScope(child)) { debug_only_print0(LC_TMTracer,"Blacklist: non-cacheable object on scope chain.\n"); Blacklist((jsbytecode*) f->root->ip); @@ -7931,7 +7931,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp, } LIns* obj_ins; - JSObject* parent = STOBJ_GET_PARENT(cx->fp->calleeObject()); + JSObject* parent = cx->fp->calleeObject()->getParent(); LIns* parent_ins = stobj_get_parent(get(&cx->fp->argv[-2])); CHECK_STATUS(traverseScopeChain(parent, parent_ins, obj, obj_ins)); @@ -10819,7 +10819,7 @@ TraceRecorder::callNative(uintN argc, JSOp mode) this_ins = newobj_ins; /* boxing an object is a no-op */ } else if (JSFUN_BOUND_METHOD_TEST(fun->flags)) { /* |funobj| was rooted above already. */ - this_ins = INS_CONSTWORD(OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, funobj))); + this_ins = INS_CONSTWORD(OBJECT_TO_JSVAL(funobj->getParent())); } else { this_ins = get(&vp[1]); @@ -11273,7 +11273,7 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop // Find obj2. If entry->adding(), the TAG bits are all 0. JSObject* obj2 = obj; for (jsuword i = PCVCAP_TAG(entry->vcap) >> PCVCAP_PROTOBITS; i; i--) - obj2 = OBJ_GET_PARENT(cx, obj2); + obj2 = obj2->getParent(); for (jsuword j = PCVCAP_TAG(entry->vcap) & PCVCAP_PROTOMASK; j; j--) obj2 = obj2->getProto(); scope = OBJ_SCOPE(obj2); @@ -13586,7 +13586,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target if (searchObj == targetObj) break; - searchObj = STOBJ_GET_PARENT(searchObj); + searchObj = searchObj->getParent(); if (!searchObj) RETURN_STOP("cannot traverse this scope chain on trace"); } @@ -13627,7 +13627,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target if (obj == targetObj) break; - obj = STOBJ_GET_PARENT(obj); + obj = obj->getParent(); obj_ins = stobj_get_parent(obj_ins); } @@ -13646,10 +13646,10 @@ TraceRecorder::record_JSOP_BINDNAME() // In global code, fp->scopeChain can only contain blocks whose values // are still on the stack. We never use BINDNAME to refer to these. - while (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) { + while (obj->getClass() == &js_BlockClass) { // The block's values are still on the stack. JS_ASSERT(obj->getPrivate() == fp); - obj = OBJ_GET_PARENT(cx, obj); + obj = obj->getParent(); // Blocks always have parents. JS_ASSERT(obj); } @@ -13678,7 +13678,7 @@ TraceRecorder::record_JSOP_BINDNAME() // that is on the scope chain and doesn't skip the target object (the one // that contains the property). jsval *callee = &cx->fp->argv[-2]; - obj = STOBJ_GET_PARENT(JSVAL_TO_OBJECT(*callee)); + obj = JSVAL_TO_OBJECT(*callee)->getParent(); if (obj == globalObj) { stack(0, INS_CONSTOBJ(obj)); return ARECORD_CONTINUE; @@ -13953,7 +13953,7 @@ TraceRecorder::record_JSOP_LAMBDA() * must agree with the corresponding break-from-do-while(0) logic there. */ if (FUN_NULL_CLOSURE(fun)) { - if (OBJ_GET_PARENT(cx, FUN_OBJECT(fun)) != globalObj) + if (FUN_OBJECT(fun)->getParent() != globalObj) RETURN_STOP_A("Null closure function object parent must be global object"); JSOp op2 = JSOp(cx->fp->regs->pc[JSOP_LAMBDA_LENGTH]); @@ -13999,7 +13999,7 @@ TraceRecorder::record_JSOP_LAMBDA_FC() JSFunction* fun; fun = cx->fp->script->getFunction(getFullIndex()); - if (OBJ_GET_PARENT(cx, FUN_OBJECT(fun)) != globalObj) + if (FUN_OBJECT(fun)->getParent() != globalObj) return ARECORD_STOP; LIns* args[] = { @@ -14133,7 +14133,7 @@ TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj) { JSFunction* fun = GET_FUNCTION_PRIVATE(cx, obj); - if (FUN_NULL_CLOSURE(fun) && OBJ_GET_PARENT(cx, FUN_OBJECT(fun)) == globalObj) { + if (FUN_NULL_CLOSURE(fun) && FUN_OBJECT(fun)->getParent() == globalObj) { LIns *proto_ins; CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); @@ -14929,7 +14929,7 @@ GetBuiltinFunction(JSContext *cx, uintN index) if (fun) { funobj = FUN_OBJECT(fun); funobj->clearProto(); - STOBJ_CLEAR_PARENT(funobj); + funobj->clearParent(); JS_LOCK_GC(rt); if (!rt->builtinFunctions[index]) /* retest now that the lock is held */ diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index fbca963c2bf7..673b2d3abf9c 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -7493,7 +7493,7 @@ js_GetFunctionNamespace(JSContext *cx, jsval *vp) * names, its prefix and uri references are copied to the QName. */ obj->clearProto(); - OBJ_CLEAR_PARENT(cx, obj); + obj->clearParent(); JS_LOCK_GC(rt); if (!rt->functionNamespaceObject) @@ -7532,7 +7532,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp) fp = js_GetTopStackFrame(cx); obj = NULL; - for (tmp = fp->scopeChain; tmp; tmp = OBJ_GET_PARENT(cx, tmp)) { + for (tmp = fp->scopeChain; tmp; tmp = tmp->getParent()) { JSClass *clasp = OBJ_GET_CLASS(cx, tmp); if (clasp == &js_BlockClass || clasp == &js_WithClass) continue; @@ -7712,7 +7712,7 @@ js_GetAnyName(JSContext *cx, jsval *vp) break; } JS_ASSERT(!obj->getProto()); - JS_ASSERT(!OBJ_GET_PARENT(cx, obj)); + JS_ASSERT(!obj->getParent()); } while (0); js_LeaveLocalRootScopeWithResult(cx, OBJECT_TO_JSVAL(obj)); @@ -7795,7 +7795,7 @@ js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp) return JS_TRUE; } } - } while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL); + } while ((obj = obj->getParent()) != NULL); printable = js_ValueToPrintableString(cx, OBJECT_TO_JSVAL(nameobj)); if (printable) { diff --git a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp index 16af17e5cce2..9a9631482783 100644 --- a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp +++ b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp @@ -333,8 +333,8 @@ RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp) } XPCWrappedNative *wn = nsnull; - if (STOBJ_GET_CLASS(obj) == &XOWClass.base && - STOBJ_GET_PARENT(outerObj) != STOBJ_GET_PARENT(obj)) { + if (obj->getClass() == &XOWClass.base && + outerObj->getParent() != obj->getParent()) { *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj)); } else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) { return JS_TRUE; @@ -538,9 +538,9 @@ WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp) // Check if wrappedObj is an XOW. If so, verify that it's from the // right scope. if (clasp == &XOWClass.base && - STOBJ_GET_PARENT(wrappedObj) != STOBJ_GET_PARENT(outerObj)) { + wrappedObj->getParent() != outerObj->getParent()) { *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, wrappedObj)); - return WrapObject(cx, STOBJ_GET_PARENT(outerObj), vp); + return WrapObject(cx, outerObj->getParent(), vp); } return JS_TRUE; @@ -560,10 +560,10 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (!JSVAL_IS_PRIMITIVE(*vp)) { JSObject *addedObj = JSVAL_TO_OBJECT(*vp); - if (STOBJ_GET_CLASS(addedObj) == &XOWClass.base && - STOBJ_GET_PARENT(addedObj) != STOBJ_GET_PARENT(obj)) { + if (addedObj->getClass() == &XOWClass.base && + addedObj->getParent() != obj->getParent()) { *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, addedObj)); - if (!WrapObject(cx, STOBJ_GET_PARENT(obj), vp, nsnull)) { + if (!WrapObject(cx, obj->getParent(), vp, nsnull)) { return JS_FALSE; } } @@ -825,8 +825,7 @@ GetUXPCObject(JSContext *cx, JSObject *obj) } JSObject *uxpco = - JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull, - STOBJ_GET_PARENT(obj)); + JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull, obj->getParent()); if (!uxpco) { return nsnull; } diff --git a/js/src/xpconnect/src/XPCNativeWrapper.cpp b/js/src/xpconnect/src/XPCNativeWrapper.cpp index 843ebd38e465..72daa9079c5a 100644 --- a/js/src/xpconnect/src/XPCNativeWrapper.cpp +++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp @@ -534,7 +534,7 @@ XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, // The real method we're going to call is the parent of this // function's JSObject. - JSObject *methodToCallObj = STOBJ_GET_PARENT(funObj); + JSObject *methodToCallObj = funObj->getParent(); XPCWrappedNative* wrappedNative = nsnull; jsval isAllAccess; @@ -704,7 +704,7 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, } JSObject *funobj = JS_GetFunctionObject(fun); - STOBJ_SET_PARENT(funobj, obj); + funobj->setParent(obj); return JS_DefineProperty(cx, obj, "toString", OBJECT_TO_JSVAL(funobj), nsnull, nsnull, 0); @@ -904,7 +904,7 @@ static JSBool MirrorWrappedNativeParent(JSContext *cx, XPCWrappedNative *wrapper, JSObject **result NS_OUTPARAM) { - JSObject *wn_parent = STOBJ_GET_PARENT(wrapper->GetFlatJSObject()); + JSObject *wn_parent = wrapper->GetFlatJSObject()->getParent(); if (!wn_parent) { *result = nsnull; } else { @@ -1113,7 +1113,7 @@ XPC_NW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly) JSObject *wrapperIter = JS_NewObjectWithGivenProto(cx, XPCNativeWrapper::GetJSClass(), nsnull, - STOBJ_GET_PARENT(obj)); + obj->getParent()); if (!wrapperIter) { return nsnull; } diff --git a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp index 375b57c8efe0..406adb39c320 100644 --- a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp +++ b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp @@ -346,7 +346,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp) if (native == XPC_SOW_FunctionWrapper) { // If this is a system function wrapper, make sure its ours, otherwise, // its prototype could come from the wrong scope. - if (wrapperObj->getProto() == STOBJ_GET_PARENT(obj)) { + if (wrapperObj->getProto() == obj->getParent()) { return JS_TRUE; } @@ -365,7 +365,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp) // if it's possible to reach them through objects that we wrap, but figuring // that out is more expensive (and harder) than simply checking and // rewrapping here. - if (STOBJ_GET_PARENT(wrapperObj) == STOBJ_GET_PARENT(obj)) { + if (wrapperObj->getParent() == obj->getParent()) { // Already wrapped. return JS_TRUE; } @@ -379,7 +379,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp) v = *vp = OBJECT_TO_JSVAL(obj); } - return WrapObject(cx, STOBJ_GET_PARENT(wrapperObj), v, vp); + return WrapObject(cx, wrapperObj->getParent(), v, vp); } static JSBool diff --git a/js/src/xpconnect/src/XPCWrapper.cpp b/js/src/xpconnect/src/XPCWrapper.cpp index 270fa2c00d5e..b6fc00c21d7d 100644 --- a/js/src/xpconnect/src/XPCWrapper.cpp +++ b/js/src/xpconnect/src/XPCWrapper.cpp @@ -141,7 +141,7 @@ IteratorNext(JSContext *cx, uintN argc, jsval *vp) *vp = STRING_TO_JSVAL(str); } else { // We need to return an [id, value] pair. - if (!JS_GetPropertyById(cx, STOBJ_GET_PARENT(obj), id, &v)) { + if (!JS_GetPropertyById(cx, obj->getParent(), id, &v)) { return JS_FALSE; } diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 2a485db42d97..516ab25159e6 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -732,7 +732,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) if(clazz == &XPC_WN_Tearoff_JSClass) { XPCWrappedNative *wrapper = - (XPCWrappedNative*)xpc_GetJSPrivate(STOBJ_GET_PARENT(obj)); + (XPCWrappedNative*)xpc_GetJSPrivate(obj->getParent()); dontTraverse = WrapperIsNotMainThreadOnly(wrapper); } else if(IS_WRAPPER_CLASS(clazz) && IS_WN_WRAPPER_OBJECT(obj)) diff --git a/js/src/xpconnect/src/xpcconvert.cpp b/js/src/xpconnect/src/xpcconvert.cpp index a46138bfb241..544990da4c67 100644 --- a/js/src/xpconnect/src/xpcconvert.cpp +++ b/js/src/xpconnect/src/xpcconvert.cpp @@ -473,7 +473,7 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s, #ifdef DEBUG JSObject* jsobj = JSVAL_TO_OBJECT(*d); - if(jsobj && !STOBJ_GET_PARENT(jsobj)) + if(jsobj && !jsobj->getParent()) NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL, "Why did we recreate this wrapper?"); #endif diff --git a/js/src/xpconnect/src/xpcdebug.cpp b/js/src/xpconnect/src/xpcdebug.cpp index d69202633fa9..fc40f8e41516 100644 --- a/js/src/xpconnect/src/xpcdebug.cpp +++ b/js/src/xpconnect/src/xpcdebug.cpp @@ -453,7 +453,7 @@ static void PrintObject(JSObject* obj, int depth, ObjectPile* pile) if(!OBJ_IS_NATIVE(obj)) return; - JSObject* parent = STOBJ_GET_PARENT(obj); + JSObject* parent = obj->getParent(); JSObject* proto = obj->getProto(); printf("%*sparent: ", INDENT(depth+1)); diff --git a/js/src/xpconnect/src/xpcquickstubs.cpp b/js/src/xpconnect/src/xpcquickstubs.cpp index d098b3c49331..cc26a2220217 100644 --- a/js/src/xpconnect/src/xpcquickstubs.cpp +++ b/js/src/xpconnect/src/xpcquickstubs.cpp @@ -1091,7 +1091,7 @@ xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, nsISupports *p, #ifdef DEBUG JSObject* jsobj = JSVAL_TO_OBJECT(*rval); - if(jsobj && !STOBJ_GET_PARENT(jsobj)) + if(jsobj && !jsobj->getParent()) NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL, "Why did we recreate this wrapper?"); #endif diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 0f8e9d3f4c4c..a8714a949a4c 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -745,8 +745,8 @@ XPCWrappedNative::Morph(XPCCallContext& ccx, NS_ADDREF(wrapper); - NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(STOBJ_GET_PARENT( - existingJSObject)), + NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(existingJSObject + ->getParent()), "XPCNativeWrapper being used to parent XPCWrappedNative?"); if(!wrapper->Init(ccx, existingJSObject)) @@ -1635,14 +1635,14 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx, if(funobj) { - JSObject* funObjParent = STOBJ_GET_PARENT(funobj); + JSObject* funObjParent = funobj->getParent(); NS_ASSERTION(funObjParent, "funobj has no parent"); JSClass* funObjParentClass = STOBJ_GET_CLASS(funObjParent); if(IS_PROTO_CLASS(funObjParentClass)) { - NS_ASSERTION(STOBJ_GET_PARENT(funObjParent), "funobj's parent (proto) is global"); + NS_ASSERTION(funObjParent->getParent(), "funobj's parent (proto) is global"); proto = (XPCWrappedNativeProto*) xpc_GetJSPrivate(funObjParent); if(proto) protoClassInfo = proto->GetClassInfo(); @@ -1654,7 +1654,7 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx, } else if(IS_TEAROFF_CLASS(funObjParentClass)) { - NS_ASSERTION(STOBJ_GET_PARENT(funObjParent), "funobj's parent (tearoff) is global"); + NS_ASSERTION(funObjParent->getParent(), "funobj's parent (tearoff) is global"); cur = funObjParent; goto return_tearoff; } @@ -1699,7 +1699,7 @@ return_wrapper: { return_tearoff: XPCWrappedNative* wrapper = - (XPCWrappedNative*) xpc_GetJSPrivate(STOBJ_GET_PARENT(cur)); + (XPCWrappedNative*) xpc_GetJSPrivate(cur->getParent()); if(proto && proto != wrapper->GetProto() && (proto->GetScope() != wrapper->GetScope() || !protoClassInfo || !wrapper->GetProto() || diff --git a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp index 6662cb675757..8e6e3df0b668 100644 --- a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp +++ b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp @@ -227,7 +227,7 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface) AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(funobj)); - STOBJ_CLEAR_PARENT(funobj); + funobj->clearParent(); funobj->clearProto(); if(!JS_SetReservedSlot(ccx, funobj, 0, PRIVATE_TO_JSVAL(iface))|| From 42c786e2983768f078e5b2f9df874546d854460f Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 5 Mar 2010 09:05:12 -0600 Subject: [PATCH 41/52] New test for long-fixed bug 500528. We were about to re-introduce it in bug 497789! r=test coverage is good. See bug 497789 comments 78-79. --- .../tests/js1_8_5/regress/regress-500528.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 js/src/tests/js1_8_5/regress/regress-500528.js diff --git a/js/src/tests/js1_8_5/regress/regress-500528.js b/js/src/tests/js1_8_5/regress/regress-500528.js new file mode 100644 index 000000000000..a3e1c5b6b30a --- /dev/null +++ b/js/src/tests/js1_8_5/regress/regress-500528.js @@ -0,0 +1,22 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Jason Orendorff + */ + +// This test appeared in bug 497789 comment 78. + +var a = {x: 'a'}, + b1 = Object.create(a), + c1 = Object.create(b1), + b2 = Object.create(a), + c2 = Object.create(b2); + +b2.x = 'b'; // foreshadowing a.x + +var s = ''; +for each (var obj in [c1, c2]) + s += obj.x; +assertEq(s, 'ab'); + +print(" PASSED! Property cache soundness: objects with the same shape but different prototypes."); From 00b3fd34096a75533db03bd1e20a4e5c4f96a98c Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 5 Mar 2010 11:45:28 -0800 Subject: [PATCH 42/52] Bug 549509: jsval representation profiling, r=lw --HG-- extra : rebase_source : e0e6c19db20d2e469066b5f9433c96c05bbff1c1 --- js/src/jsapi.cpp | 11 ++- js/src/jsinterp.cpp | 169 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 178 insertions(+), 2 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 5fc0f561ed81..d47ccec6bcee 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -731,6 +731,12 @@ JS_DestroyRuntime(JSRuntime *rt) js_free(rt); } +#ifdef JS_REPRMETER +namespace reprmeter { + extern void js_DumpReprMeter(); +} +#endif + JS_PUBLIC_API(void) JS_ShutDown(void) { @@ -740,10 +746,13 @@ JS_ShutDown(void) #ifdef JS_OPMETER extern void js_DumpOpMeters(); - js_DumpOpMeters(); #endif +#ifdef JS_REPRMETER + reprmeter::js_DumpReprMeter(); +#endif + js_FinishDtoa(); #ifdef JS_THREADSAFE js_CleanupLocks(); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 70a9df1b867c..19115c6b2a09 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2347,6 +2347,166 @@ js_DumpOpMeters() #ifndef jsinvoke_cpp___ +#ifdef JS_REPRMETER +// jsval representation metering: this measures the kinds of jsvals that +// are used as inputs to each JSOp. +namespace reprmeter { + enum Repr { + NONE, + INT, + DOUBLE, + BOOLEAN_PROPER, + BOOLEAN_OTHER, + STRING, + OBJECT_NULL, + OBJECT_PLAIN, + FUNCTION_INTERPRETED, + FUNCTION_FASTNATIVE, + FUNCTION_SLOWNATIVE, + ARRAY_SLOW, + ARRAY_DENSE + }; + + // Return the |repr| value giving the representation of the given jsval. + static Repr + GetRepr(jsval v) + { + if (JSVAL_IS_INT(v)) + return INT; + if (JSVAL_IS_DOUBLE(v)) + return DOUBLE; + if (JSVAL_IS_SPECIAL(v)) { + return (v == JSVAL_TRUE || v == JSVAL_FALSE) + ? BOOLEAN_PROPER + : BOOLEAN_OTHER; + } + if (JSVAL_IS_STRING(v)) + return STRING; + + JS_ASSERT(JSVAL_IS_OBJECT(v)); + + JSObject *obj = JSVAL_TO_OBJECT(v); + if (VALUE_IS_FUNCTION(cx, v)) { + JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj); + if (FUN_INTERPRETED(fun)) + return FUNCTION_INTERPRETED; + if (fun->flags & JSFUN_FAST_NATIVE) + return FUNCTION_FASTNATIVE; + return FUNCTION_SLOWNATIVE; + } + // This must come before the general array test, because that + // one subsumes this one. + if (!obj) + return OBJECT_NULL; + if (obj->isDenseArray()) + return ARRAY_DENSE; + if (obj->isArray()) + return ARRAY_SLOW; + return OBJECT_PLAIN; + } + + static const char *reprName[] = { "invalid", "int", "double", "bool", "special", + "string", "null", "object", + "fun:interp", "fun:fast", "fun:slow", + "array:slow", "array:dense" }; + + // Logically, a tuple of (JSOp, repr_1, ..., repr_n) where repr_i is + // the |repr| of the ith input to the JSOp. + struct OpInput { + enum { max_uses = 16 }; + + JSOp op; + Repr uses[max_uses]; + + OpInput() : op(JSOp(255)) { + for (int i = 0; i < max_uses; ++i) + uses[i] = NONE; + } + + OpInput(JSOp op) : op(op) { + for (int i = 0; i < max_uses; ++i) + uses[i] = NONE; + } + + // Hash function + operator uint32() const { + uint32 h = op; + for (int i = 0; i < max_uses; ++i) + h = h * 7 + uses[i] * 13; + return h; + } + + bool operator==(const OpInput &opinput) const { + if (op != opinput.op) + return false; + for (int i = 0; i < max_uses; ++i) { + if (uses[i] != opinput.uses[i]) + return false; + } + return true; + } + + OpInput &operator=(const OpInput &opinput) { + op = opinput.op; + for (int i = 0; i < max_uses; ++i) + uses[i] = opinput.uses[i]; + return *this; + } + }; + + typedef HashMap, SystemAllocPolicy> OpInputHistogram; + + OpInputHistogram opinputs; + bool opinputsInitialized = false; + + // Record an OpInput for the current op. This should be called just + // before executing the op. + static void + MeterRepr(JSStackFrame *fp) + { + // Note that we simply ignore the possibility of errors (OOMs) + // using the hash map, since this is only metering code. + + if (!opinputsInitialized) { + opinputs.init(); + opinputsInitialized = true; + } + + JSOp op = JSOp(*fp->regs->pc); + unsigned nuses = js_GetStackUses(&js_CodeSpec[op], op, fp->regs->pc); + + // Build the OpInput. + OpInput opinput(op); + for (unsigned i = 0; i < nuses; ++i) { + jsval v = fp->regs->sp[-nuses+i]; + opinput.uses[i] = GetRepr(v); + } + + OpInputHistogram::AddPtr p = opinputs.lookupForAdd(opinput); + if (p) + ++p->value; + else + opinputs.add(p, opinput, 1); + } + + void + js_DumpReprMeter() + { + FILE *f = fopen("/tmp/reprmeter.txt", "w"); + JS_ASSERT(f); + for (OpInputHistogram::Range r = opinputs.all(); !r.empty(); r.popFront()) { + const OpInput &o = r.front().key; + uint64 c = r.front().value; + fprintf(f, "%3d,%s", o.op, js_CodeName[o.op]); + for (int i = 0; i < OpInput::max_uses && o.uses[i] != NONE; ++i) + fprintf(f, ",%s", reprName[o.uses[i]]); + fprintf(f, ",%llu\n", c); + } + fclose(f); + } +} +#endif /* JS_REPRMETER */ + #define PUSH(v) (*regs.sp++ = (v)) #define PUSH_OPND(v) PUSH(v) #define STORE_OPND(n,v) (regs.sp[n] = (v)) @@ -2534,6 +2694,12 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL_CONSTEXPR(JSVAL_INT_MAX))); #endif +#ifdef JS_REPRMETER +# define METER_REPR(fp) (reprmeter::MeterRepr(fp)) +#else +# define METER_REPR(fp) +#endif /* JS_REPRMETER */ + /* * Threaded interpretation via computed goto appears to be well-supported by * GCC 3 and higher. IBM's C compiler when run with the right options (e.g., @@ -2776,8 +2942,9 @@ js_Interpret(JSContext *cx) JS_EXTENSION_(goto *jumpTable[op]); \ JS_END_MACRO # define DO_NEXT_OP(n) JS_BEGIN_MACRO \ - METER_OP_PAIR(op, JSOp(regs.pc[n])); \ + METER_OP_PAIR(op, JSOp(regs.pc[n])); \ op = (JSOp) *(regs.pc += (n)); \ + METER_REPR(fp); \ DO_OP(); \ JS_END_MACRO From 43bec37956938b046371bb9e894af2d77b8bdc31 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 5 Mar 2010 16:29:44 -0600 Subject: [PATCH 43/52] In case of OOM in DEBUG build, don't crash. No bug, rs=jwalden via IRC. --HG-- extra : rebase_source : c08508a93d1c1a98606dc1c7c8d9c08c57e17cad --- js/src/jsobj.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index e63105d74d24..498c6357e26a 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2902,8 +2902,10 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto, if (clasp == &js_FunctionClass && !objectSize) { obj = (JSObject*) js_NewGCFunction(cx); #ifdef DEBUG - memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN, - sizeof(JSFunction) - sizeof(JSObject)); + if (obj) { + memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN, + sizeof(JSFunction) - sizeof(JSObject)); + } #endif } else { JS_ASSERT(!objectSize || objectSize == sizeof(JSObject)); From ec28434682862cbffae975ed4b17bf1b8a919e7e Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Fri, 5 Mar 2010 16:42:06 -0600 Subject: [PATCH 44/52] Bug 549971 - Add compile() function to JS shell. r=jorendorff. --- js/src/shell/js.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 9296e09a0106..a15dbc8f2d8c 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3635,6 +3635,32 @@ MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf) #endif // XP_UNIX +static JSBool +Compile(JSContext *cx, uintN argc, jsval *vp) +{ + if (argc < 1) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED, + "compile", "0", "s"); + return JS_FALSE; + } + jsval arg0 = JS_ARGV(cx, vp)[0]; + if (!JSVAL_IS_STRING(arg0)) { + const char *typeName = JS_GetTypeName(cx, JS_TypeOfValue(cx, arg0)); + JS_ReportError(cx, "expected string to compile, got %s", typeName); + return JS_FALSE; + } + + JSString *scriptContents = JSVAL_TO_STRING(arg0); + JSScript *result = JS_CompileUCScript(cx, NULL, JS_GetStringCharsZ(cx, scriptContents), + JS_GetStringLength(scriptContents), "", 0); + if (!result) + return JS_FALSE; + + JS_DestroyScript(cx, result); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + static JSBool Snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { @@ -3786,6 +3812,7 @@ static JSFunctionSpec shell_functions[] = { JS_FN("scatter", Scatter, 1,0), #endif JS_FS("snarf", Snarf, 0,0,0), + JS_FN("compile", Compile, 1,0), JS_FN("timeout", Timeout, 1,0), JS_FN("elapsed", Elapsed, 0,0), JS_FS_END @@ -3888,6 +3915,7 @@ static const char *const shell_help_messages[] = { "scatter(fns) Call functions concurrently (ignoring errors)", #endif "snarf(filename) Read filename into returned string", +"compile(code) Parses a string, potentially throwing", "timeout([seconds])\n" " Get/Set the limit in seconds for the execution time for the current context.\n" " A negative value (default) means that the execution time is unlimited.", From 13458bfacbbfbc3e6a51d0a7febf748eb5cca227 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Fri, 5 Mar 2010 16:47:24 -0600 Subject: [PATCH 45/52] Bug 548621 - Create suite of tests for JS parsing speed. r=jorendorff. --- js/src/tests/parsemark.py | 178 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 js/src/tests/parsemark.py diff --git a/js/src/tests/parsemark.py b/js/src/tests/parsemark.py new file mode 100644 index 000000000000..ab980091c35c --- /dev/null +++ b/js/src/tests/parsemark.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python + +"""%prog [options] dirpath + +Pulls performance data on parsing via the js shell. +Displays the average number of milliseconds it took to parse each file. + +Arguments: + dirpath directory filled with parsilicious js files +""" + +import math +import optparse +import os +import subprocess as subp +import sys +from string import Template +from operator import itemgetter + + +_DIR = os.path.dirname(__file__) +JS_CODE_TEMPLATE = Template(""" +var contents = snarf("$filepath"); +for (let i = 0; i < $warmup_run_count; i++) + compile(contents); +var results = []; +for (let i = 0; i < $real_run_count; i++) { + var start = new Date(); + compile(contents); + var end = new Date(); + results.push(end - start); +} +print(results); +""") + + +def find_shell(filename='js'): + """Look around for the js shell. Prefer more obvious places to look. + + :return: Path if found, else None. + """ + relpaths = ['', 'obj', os.pardir, [os.pardir, 'obj']] + for relpath in relpaths: + path_parts = [_DIR] + if isinstance(relpath, list): + path_parts += relpath + else: + path_parts.append(relpath) + path_parts.append(filename) + path = os.path.join(*path_parts) + if os.path.isfile(path): + return path + + +def gen_filepaths(dirpath, target_ext='.js'): + for filename in os.listdir(dirpath): + if filename.endswith(target_ext): + yield os.path.join(dirpath, filename) + + +def avg(seq): + return sum(seq) / len(seq) + + +def stddev(seq, mean): + diffs = ((float(item) - mean) ** 2 for item in seq) + return math.sqrt(sum(diffs) / len(seq)) + + +def bench(shellpath, filepath, warmup_runs, counted_runs, stfu=False): + """Return a list of milliseconds for the counted runs.""" + assert '"' not in filepath + code = JS_CODE_TEMPLATE.substitute(filepath=filepath, + warmup_run_count=warmup_runs, real_run_count=counted_runs) + proc = subp.Popen([shellpath, '-e', code], stdout=subp.PIPE) + stdout, _ = proc.communicate() + milliseconds = [int(val) for val in stdout.split(',')] + mean = avg(milliseconds) + sigma = stddev(milliseconds, mean) + if not stfu: + print 'Runs:', milliseconds + print 'Mean:', mean + print 'Stddev: %.2f (%.2f%% of mean)' % (sigma, sigma / mean * 100) + return mean, sigma + + +def parsemark(filepaths, fbench, stfu=False): + """:param fbench: fbench(filename) -> float""" + bench_map = {} + for filepath in filepaths: + filename = os.path.split(filepath)[-1] + if not stfu: + print 'Parsemarking %s...' % filename + bench_map[filename] = fbench(filepath) + print '{' + for i, (filename, (avg, stddev)) in enumerate(bench_map.iteritems()): + assert '"' not in filename + fmt = ' %30s: {"average_ms": %4d, "stddev_ms": %6.2f}' + if i != len(bench_map) - 1: + fmt += ',' + filename_str = '"%s"' % filename + print fmt % (filename_str, avg, stddev) + print '}' + return bench_map + + +def compare(current, baseline): + for key, (avg, stddev) in current.iteritems(): + try: + base_avg, base_stddev = itemgetter('average_ms', + 'stddev_ms')(baseline.get(key, None)) + except TypeError: + print key, 'missing from baseline' + continue + t_best, t_worst = avg - stddev, avg + stddev + base_t_best, base_t_worst = base_avg - base_stddev, base_avg + base_stddev + fmt = '%30s: %s' + if t_worst < base_t_best: # Worst takes less time (better) than baseline's best. + result = 'FASTER: worst time %.2f < baseline best time %.2f' % (t_worst, base_t_best) + elif t_best > base_t_worst: # Best takes more time (worse) than baseline's worst. + result = 'SLOWER: best time %.2f > baseline worst time %.2f' % (t_best, base_t_worst) + else: + result = 'Meh.' + print '%30s: %s' % (key, result) + + +def try_import_json(): + try: + import json + return json + except ImportError: + try: + import simplejson as json + return json + except ImportError: + pass + + +def main(): + parser = optparse.OptionParser(usage=__doc__.strip()) + parser.add_option('-w', '--warmup-runs', metavar='COUNT', type=int, + default=5, help='used to minimize test instability') + parser.add_option('-c', '--counted-runs', metavar='COUNT', type=int, + default=20, help='timed data runs that count towards the average') + parser.add_option('-s', '--shell', metavar='PATH', help='explicit shell ' + 'location; when omitted, will look in likely places') + parser.add_option('-b', '--baseline', metavar='JSON_PATH', + dest='baseline_path', help='json file with baseline values to ' + 'compare against') + parser.add_option('-q', '--quiet', dest='stfu', action='store_true', + default=False, help='only print JSON to stdout') + options, args = parser.parse_args() + try: + dirpath = args.pop(0) + except IndexError: + parser.error('dirpath required') + shellpath = options.shell or find_shell() + if not shellpath: + print >> sys.stderr, 'Could not find shell' + return -1 + if options.baseline_path: + json = try_import_json() + if not json: + print >> sys.stderr, 'You need a json lib for baseline comparison' + return -1 + benchfile = lambda filepath: bench(shellpath, filepath, + options.warmup_runs, options.counted_runs, stfu=options.stfu) + bench_map = parsemark(gen_filepaths(dirpath), benchfile, options.stfu) + if options.baseline_path: + fh = open(options.baseline_path, 'r') # 2.4 compat, no 'with'. + baseline_map = json.load(fh) + fh.close() + compare(current=bench_map, baseline=baseline_map) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) From f5f31d7ca0f06e9827b86458b435ba36375eb506 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 5 Mar 2010 11:55:42 -0800 Subject: [PATCH 46/52] Comparison operator for HashTable Ptr (no bug) --HG-- extra : rebase_source : 2d64c307f6a524066d0a4cb66c66a5b4cd48d83d --- js/src/jshashtable.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/js/src/jshashtable.h b/js/src/jshashtable.h index 358df5333161..f260b08b4b6f 100644 --- a/js/src/jshashtable.h +++ b/js/src/jshashtable.h @@ -109,11 +109,13 @@ class HashTable : AllocPolicy Ptr(Entry &entry) : entry(&entry) {} public: - bool found() const { return entry->isLive(); } - operator ConvertibleToBool() { return found() ? &Ptr::nonNull : 0; } + bool found() const { return entry->isLive(); } + operator ConvertibleToBool() const { return found() ? &Ptr::nonNull : 0; } + bool operator==(const Ptr &rhs) const { JS_ASSERT(found() && rhs.found()); return entry == rhs.entry; } + bool operator!=(const Ptr &rhs) const { return !(*this == rhs); } - T &operator*() const { return entry->t; } - T *operator->() const { return &entry->t; } + T &operator*() const { return entry->t; } + T *operator->() const { return &entry->t; } }; /* A Ptr that can be used to add a key after a failed lookup. */ From 49255320b6d0abb247c8aaccc4ed5454935ced92 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Mar 2010 08:09:35 +1100 Subject: [PATCH 47/52] Bug 550654 - TM: removed dead 'inner_sp_ins' variable. r=dvander. --- js/src/jstracer.cpp | 12 +++++------- js/src/jstracer.h | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index bdec0d749c2c..28eee7d758fc 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -4917,9 +4917,8 @@ TraceRecorder::endLoop(VMSideExit* exit) /* Emit code to adjust the stack to match the inner tree's stack expectations. */ JS_REQUIRES_STACK void -TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) +TraceRecorder::prepareTreeCall(TreeFragment* inner) { - inner_sp_ins = lirbuf->sp; VMSideExit* exit = snapshot(OOM_EXIT); /* @@ -4966,7 +4965,7 @@ TraceRecorder::prepareTreeCall(TreeFragment* inner, LIns*& inner_sp_ins) + sp_adj /* adjust for stack in outer frame inner tree can't see */ + inner->nativeStackBase; /* plus the inner tree's stack base */ /* We have enough space, so adjust sp and rp to their new level. */ - lir->insStorei(inner_sp_ins = lir->ins2(LIR_piadd, lirbuf->sp, INS_CONSTWORD(sp_offset)), + lir->insStorei(lir->ins2(LIR_piadd, lirbuf->sp, INS_CONSTWORD(sp_offset)), lirbuf->state, offsetof(InterpState, sp)); lir->insStorei(lir->ins2(LIR_piadd, lirbuf->rp, INS_CONSTWORD(rp_adj)), lirbuf->state, offsetof(InterpState, rp)); @@ -5004,7 +5003,7 @@ BuildGlobalTypeMapFromInnerTree(Queue& typeMap, VMSideExit* inner) /* Record a call to an inner tree. */ JS_REQUIRES_STACK void -TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_sp_ins) +TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit) { /* Invoke the inner tree. */ LIns* args[] = { lirbuf->state }; /* reverse order */ @@ -5986,8 +5985,7 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount) } adjustCallerTypes(f); - LIns* inner_sp_ins; - prepareTreeCall(f, inner_sp_ins); + prepareTreeCall(f); #ifdef DEBUG unsigned oldInlineCallCount = inlineCallCount; @@ -6036,7 +6034,7 @@ TraceRecorder::attemptTreeCall(TreeFragment* f, uintN& inlineCallCount) JS_ASSERT(oldInlineCallCount == inlineCallCount); /* Emit a call to the inner tree and continue recording the outer tree trace. */ - emitTreeCall(f, lr, inner_sp_ins); + emitTreeCall(f, lr); return ARECORD_CONTINUE; case UNSTABLE_LOOP_EXIT: diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 22bfa528dd60..638cdbc6acf4 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1363,8 +1363,8 @@ class TraceRecorder JS_REQUIRES_STACK AbortableRecordingStatus endLoop(VMSideExit* exit); JS_REQUIRES_STACK void joinEdgesToEntry(TreeFragment* peer_root); JS_REQUIRES_STACK void adjustCallerTypes(TreeFragment* f); - JS_REQUIRES_STACK void prepareTreeCall(TreeFragment* inner, nanojit::LIns*& inner_sp_ins); - JS_REQUIRES_STACK void emitTreeCall(TreeFragment* inner, VMSideExit* exit, nanojit::LIns* inner_sp_ins); + JS_REQUIRES_STACK void prepareTreeCall(TreeFragment* inner); + JS_REQUIRES_STACK void emitTreeCall(TreeFragment* inner, VMSideExit* exit); JS_REQUIRES_STACK void determineGlobalTypes(TraceType* typeMap); JS_REQUIRES_STACK VMSideExit* downSnapshot(FrameInfo* downFrame); JS_REQUIRES_STACK TreeFragment* findNestedCompatiblePeer(TreeFragment* f); From 7c0b1daf1bd7c02ead4629376b7e3acb9b523d55 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Mar 2010 16:11:59 +1100 Subject: [PATCH 48/52] Bug 550796 - TM: remove dead ImportGlobalSlotVisitor class. r=lw. --- js/src/jstracer.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 28eee7d758fc..525a4133f191 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3403,28 +3403,6 @@ TraceRecorder::import(LIns* base, ptrdiff_t offset, jsval* p, TraceType t, #endif } -class ImportGlobalSlotVisitor : public SlotVisitorBase -{ - TraceRecorder &mRecorder; - LIns *mBase; - TraceType *mTypemap; -public: - ImportGlobalSlotVisitor(TraceRecorder &recorder, - LIns *base, - TraceType *typemap) : - mRecorder(recorder), - mBase(base), - mTypemap(typemap) - {} - - JS_REQUIRES_STACK JS_ALWAYS_INLINE void - visitGlobalSlot(jsval *vp, unsigned n, unsigned slot) { - JS_ASSERT(*mTypemap != TT_JSVAL); - mRecorder.import(mBase, mRecorder.nativeGlobalOffset(vp), - vp, *mTypemap++, "global", n, NULL); - } -}; - class ImportBoxedStackSlotVisitor : public SlotVisitorBase { TraceRecorder &mRecorder; From 5a9c372534f57c458027cc17200f97f3b16cc373 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 8 Mar 2010 10:28:08 -0800 Subject: [PATCH 49/52] Trace recursion when the return keyword is omitted (bug 530900, r=gal). --- js/src/jsrecursion.cpp | 119 ++++++++++++++++++++++++++--------------- js/src/jstracer.cpp | 8 ++- 2 files changed, 83 insertions(+), 44 deletions(-) diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 057fe1d97a92..9b01ddce9568 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -156,9 +156,20 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame) unsigned exitTypeMapLen = downPostSlots + 1 + ngslots; TraceType* exitTypeMap = (TraceType*)alloca(sizeof(TraceType) * exitTypeMapLen); TraceType* typeMap = downFrame->get_typemap(); + + + /* Add stack slots. */ for (unsigned i = 0; i < downPostSlots; i++) exitTypeMap[i] = typeMap[i]; - exitTypeMap[downPostSlots] = determineSlotType(&stackval(-1)); + + /* Add the return type. */ + JS_ASSERT_IF(*cx->fp->regs->pc != JSOP_RETURN, *cx->fp->regs->pc == JSOP_STOP); + if (*cx->fp->regs->pc == JSOP_RETURN) + exitTypeMap[downPostSlots] = determineSlotType(&stackval(-1)); + else + exitTypeMap[downPostSlots] = TT_PSEUDOBOOLEAN; + + /* Add global types. */ determineGlobalTypes(&exitTypeMap[downPostSlots + 1]); VMSideExit* exit = (VMSideExit*) @@ -246,9 +257,9 @@ TraceRecorder::upRecursion() * This is always safe because this point is only reached on simple "call myself" * recursive functions. */ - #if defined DEBUG +#if defined DEBUG AssertDownFrameIsConsistent(cx, anchor, fi); - #endif +#endif fi = anchor->recursive_down; } else if (recursive_pc != fragment->root->ip) { /* @@ -296,12 +307,19 @@ TraceRecorder::upRecursion() */ exit = downSnapshot(fi); - LIns* rval_ins = (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) ? - get(&stackval(-1)) : - NULL; - JS_ASSERT(rval_ins != NULL); + LIns* rval_ins; + if (*cx->fp->regs->pc == JSOP_RETURN) { + rval_ins = (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) ? + get(&stackval(-1)) : + NULL; + JS_ASSERT(rval_ins); + } else { + rval_ins = INS_CONST(JSVAL_TO_SPECIAL(JSVAL_VOID)); + } + TraceType returnType = exit->stackTypeMap()[downPostSlots]; if (returnType == TT_INT32) { + JS_ASSERT(*cx->fp->regs->pc == JSOP_RETURN); JS_ASSERT(determineSlotType(&stackval(-1)) == TT_INT32); JS_ASSERT(isPromoteInt(rval_ins)); rval_ins = demote(lir, rval_ins); @@ -310,7 +328,10 @@ TraceRecorder::upRecursion() UpRecursiveSlotMap slotMap(*this, downPostSlots, rval_ins); for (unsigned i = 0; i < downPostSlots; i++) slotMap.addSlot(exit->stackType(i)); - slotMap.addSlot(&stackval(-1)); + if (*cx->fp->regs->pc == JSOP_RETURN) + slotMap.addSlot(&stackval(-1)); + else + slotMap.addSlot(TT_PSEUDOBOOLEAN); VisitGlobalSlots(slotMap, cx, *tree->globalSlots); if (recursive_pc == (jsbytecode*)fragment->root->ip) { debug_only_print0(LC_TMTracer, "Compiling up-recursive loop...\n"); @@ -447,10 +468,15 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) cx->fp->regs->pc = exit->pc; CaptureStackTypes(cx, frameDepth, typeMap); cx->fp->regs->pc = oldpc; - if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) - typeMap[downPostSlots] = determineSlotType(&stackval(-1)); - else + if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) { + JS_ASSERT_IF(*cx->fp->regs->pc != JSOP_RETURN, *cx->fp->regs->pc == JSOP_STOP); + if (*cx->fp->regs->pc == JSOP_RETURN) + typeMap[downPostSlots] = determineSlotType(&stackval(-1)); + else + typeMap[downPostSlots] = TT_PSEUDOBOOLEAN; + } else { typeMap[downPostSlots] = anchor->stackTypeMap()[anchor->numStackSlots - 1]; + } determineGlobalTypes(&typeMap[exit->numStackSlots]); #if defined JS_JIT_SPEW TreevisLogExit(cx, exit); @@ -466,39 +492,43 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) * grabbed safely. */ LIns* rval_ins; - TraceType returnType = exit->stackTypeMap()[downPostSlots]; - if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) { - rval_ins = get(&stackval(-1)); - if (returnType == TT_INT32) { - JS_ASSERT(determineSlotType(&stackval(-1)) == TT_INT32); - JS_ASSERT(isPromoteInt(rval_ins)); - rval_ins = demote(lir, rval_ins); + if (*cx->fp->regs->pc == JSOP_RETURN) { + TraceType returnType = exit->stackTypeMap()[downPostSlots]; + if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) { + rval_ins = get(&stackval(-1)); + if (returnType == TT_INT32) { + JS_ASSERT(determineSlotType(&stackval(-1)) == TT_INT32); + JS_ASSERT(isPromoteInt(rval_ins)); + rval_ins = demote(lir, rval_ins); + } + /* + * The return value must be written out early, before slurping can fail, + * otherwise it will not be available when there's a type mismatch. + */ + lir->insStorei(rval_ins, lirbuf->sp, exit->sp_adj - sizeof(double)); + } else { + switch (returnType) + { + case TT_PSEUDOBOOLEAN: + case TT_INT32: + rval_ins = lir->insLoad(LIR_ld, lirbuf->sp, exit->sp_adj - sizeof(double)); + break; + case TT_DOUBLE: + rval_ins = lir->insLoad(LIR_ldf, lirbuf->sp, exit->sp_adj - sizeof(double)); + break; + case TT_FUNCTION: + case TT_OBJECT: + case TT_STRING: + case TT_NULL: + rval_ins = lir->insLoad(LIR_ldp, lirbuf->sp, exit->sp_adj - sizeof(double)); + break; + default: + JS_NOT_REACHED("unknown type"); + RETURN_STOP_A("unknown type"); + } } - /* - * The return value must be written out early, before slurping can fail, - * otherwise it will not be available when there's a type mismatch. - */ - lir->insStorei(rval_ins, lirbuf->sp, exit->sp_adj - sizeof(double)); } else { - switch (returnType) - { - case TT_PSEUDOBOOLEAN: - case TT_INT32: - rval_ins = lir->insLoad(LIR_ld, lirbuf->sp, exit->sp_adj - sizeof(double)); - break; - case TT_DOUBLE: - rval_ins = lir->insLoad(LIR_ldf, lirbuf->sp, exit->sp_adj - sizeof(double)); - break; - case TT_FUNCTION: - case TT_OBJECT: - case TT_STRING: - case TT_NULL: - rval_ins = lir->insLoad(LIR_ldp, lirbuf->sp, exit->sp_adj - sizeof(double)); - break; - default: - JS_NOT_REACHED("unknown type"); - RETURN_STOP_A("unknown type"); - } + rval_ins = INS_CONST(JSVAL_TO_SPECIAL(JSVAL_VOID)); } /* Slurp */ @@ -560,7 +590,10 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc) RecursiveSlotMap slotMap(*this, downPostSlots, rval_ins); for (unsigned i = 0; i < downPostSlots; i++) slotMap.addSlot(typeMap[i]); - slotMap.addSlot(&stackval(-1), typeMap[downPostSlots]); + if (*cx->fp->regs->pc == JSOP_RETURN) + slotMap.addSlot(&stackval(-1), typeMap[downPostSlots]); + else + slotMap.addSlot(TT_PSEUDOBOOLEAN); VisitGlobalSlots(slotMap, cx, *tree->globalSlots); debug_only_print0(LC_TMTracer, "Compiling up-recursive slurp...\n"); exit = copy(exit); diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 525a4133f191..6c137c4966d7 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -4594,7 +4594,8 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) * case this loop was blacklisted in the meantime, JSOP_NOP. */ JS_ASSERT((*cx->fp->regs->pc == JSOP_TRACE || *cx->fp->regs->pc == JSOP_NOP || - *cx->fp->regs->pc == JSOP_RETURN) && !cx->fp->imacpc); + *cx->fp->regs->pc == JSOP_RETURN || *cx->fp->regs->pc == JSOP_STOP) && + !cx->fp->imacpc); if (callDepth != 0) { debug_only_print0(LC_TMTracer, @@ -14617,6 +14618,11 @@ TraceRecorder::record_JSOP_CALLELEM() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_STOP() { + if (callDepth == 0 && IsTraceableRecursion(cx) && + tree->recursion != Recursion_Disallowed && + tree->script == cx->fp->script) { + return InjectStatus(upRecursion()); + } JSStackFrame *fp = cx->fp; if (fp->imacpc) { From bdc294e14d67a31e0c3dc6ff23e7681db4f005f0 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Mon, 8 Mar 2010 18:22:44 -0600 Subject: [PATCH 50/52] Bug 550643 - Minor improvements to parsemark.py. r=jorendorff. --- js/src/tests/parsemark.py | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/js/src/tests/parsemark.py b/js/src/tests/parsemark.py index ab980091c35c..ff856646b577 100644 --- a/js/src/tests/parsemark.py +++ b/js/src/tests/parsemark.py @@ -5,6 +5,17 @@ Pulls performance data on parsing via the js shell. Displays the average number of milliseconds it took to parse each file. +For comparison, something apparently approximating a t-test is performed: +"Faster" means that: + + t_baseline_goodrun = (t_baseline_avg - t_baseline_stddev) + t_current_badrun = (t_current_avg + t_current_stddev) + t_current_badrun < t_baseline_goodrun + +Effectively, a bad run from the current data is better than a good run from the +baseline data, we're probably faster. A similar computation is used for +determining the "slower" designation. + Arguments: dirpath directory filled with parsilicious js files """ @@ -74,7 +85,7 @@ def bench(shellpath, filepath, warmup_runs, counted_runs, stfu=False): warmup_run_count=warmup_runs, real_run_count=counted_runs) proc = subp.Popen([shellpath, '-e', code], stdout=subp.PIPE) stdout, _ = proc.communicate() - milliseconds = [int(val) for val in stdout.split(',')] + milliseconds = [float(val) for val in stdout.split(',')] mean = avg(milliseconds) sigma = stddev(milliseconds, mean) if not stfu: @@ -95,7 +106,7 @@ def parsemark(filepaths, fbench, stfu=False): print '{' for i, (filename, (avg, stddev)) in enumerate(bench_map.iteritems()): assert '"' not in filename - fmt = ' %30s: {"average_ms": %4d, "stddev_ms": %6.2f}' + fmt = ' %30s: {"average_ms": %6.2f, "stddev_ms": %6.2f}' if i != len(bench_map) - 1: fmt += ',' filename_str = '"%s"' % filename @@ -107,8 +118,7 @@ def parsemark(filepaths, fbench, stfu=False): def compare(current, baseline): for key, (avg, stddev) in current.iteritems(): try: - base_avg, base_stddev = itemgetter('average_ms', - 'stddev_ms')(baseline.get(key, None)) + base_avg, base_stddev = itemgetter('average_ms', 'stddev_ms')(baseline.get(key, None)) except TypeError: print key, 'missing from baseline' continue @@ -116,9 +126,13 @@ def compare(current, baseline): base_t_best, base_t_worst = base_avg - base_stddev, base_avg + base_stddev fmt = '%30s: %s' if t_worst < base_t_best: # Worst takes less time (better) than baseline's best. - result = 'FASTER: worst time %.2f < baseline best time %.2f' % (t_worst, base_t_best) + speedup = -((t_worst - base_t_best) / base_t_best) * 100 + result = 'faster: %6.2fms < baseline %6.2fms (%+6.2f%%)' % \ + (t_worst, base_t_best, speedup) elif t_best > base_t_worst: # Best takes more time (worse) than baseline's worst. - result = 'SLOWER: best time %.2f > baseline worst time %.2f' % (t_best, base_t_worst) + slowdown = -((t_best - base_t_worst) / base_t_worst) * 100 + result = 'SLOWER: %6.2fms > baseline %6.2fms (%+6.2f%%) ' % \ + (t_best, base_t_worst, slowdown) else: result = 'Meh.' print '%30s: %s' % (key, result) @@ -153,12 +167,18 @@ def main(): try: dirpath = args.pop(0) except IndexError: - parser.error('dirpath required') + parser.print_help() + print + print >> sys.stderr, 'error: dirpath required' + return -1 shellpath = options.shell or find_shell() if not shellpath: print >> sys.stderr, 'Could not find shell' return -1 if options.baseline_path: + if not os.path.isfile(options.baseline_path): + print >> sys.stderr, 'Baseline file does not exist' + return -1 json = try_import_json() if not json: print >> sys.stderr, 'You need a json lib for baseline comparison' From bead9e13c59abd42f7e18f0141eaf79926bfebff Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 9 Mar 2010 17:21:32 -0500 Subject: [PATCH 51/52] Bug 551118. Reuse string-to-number code and fix bug with negative hex in strings being treated as a negative integer. r=brendan --- js/src/jsbuiltins.cpp | 35 +---------- js/src/jsnum.cpp | 24 +------- js/src/jsnum.h | 60 +++++++++++++++++++ .../tests/basic/testStringToNumber.js | 47 +++++++++++++++ 4 files changed, 112 insertions(+), 54 deletions(-) create mode 100644 js/src/trace-test/tests/basic/testStringToNumber.js diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 6cb207a0aeef..67180bee1fb6 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -187,45 +187,14 @@ JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, ACC_NONE) jsdouble FASTCALL js_StringToNumber(JSContext* cx, JSString* str) { - const jschar* bp; - const jschar* end; - const jschar* ep; - jsdouble d; - - str->getCharsAndEnd(bp, end); - if ((!js_strtod(cx, bp, end, &ep, &d) || - js_SkipWhiteSpace(ep, end) != end) && - (!js_strtointeger(cx, bp, end, &ep, 0, &d) || - js_SkipWhiteSpace(ep, end) != end)) { - return js_NaN; - } - return d; + return StringToNumberType(cx, str); } JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, ACC_NONE) int32 FASTCALL js_StringToInt32(JSContext* cx, JSString* str) { - const jschar* bp; - const jschar* end; - const jschar* ep; - jsdouble d; - - if (str->length() == 1) { - jschar c = str->chars()[0]; - if ('0' <= c && c <= '9') - return c - '0'; - return 0; - } - - str->getCharsAndEnd(bp, end); - if ((!js_strtod(cx, bp, end, &ep, &d) || - js_SkipWhiteSpace(ep, end) != end) && - (!js_strtointeger(cx, bp, end, &ep, 0, &d) || - js_SkipWhiteSpace(ep, end) != end)) { - return 0; - } - return js_DoubleToECMAInt32(d); + return StringToNumberType(cx, str); } JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, ACC_NONE) diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index d6f9fea43a39..b166bb0a8e37 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -73,6 +73,7 @@ #include "jsstrinlines.h" #include "jsvector.h" +using namespace js; #ifndef JS_HAVE_STDINT_H /* Native support is innocent until proven guilty. */ @@ -943,7 +944,6 @@ js_ValueToNumber(JSContext *cx, jsval *vp) { jsval v; JSString *str; - const jschar *bp, *end, *ep; jsdouble d; JSObject *obj; @@ -956,26 +956,8 @@ js_ValueToNumber(JSContext *cx, jsval *vp) if (JSVAL_IS_STRING(v)) { str = JSVAL_TO_STRING(v); - /* - * Note that ECMA doesn't treat a string beginning with a '0' as - * an octal number here. This works because all such numbers will - * be interpreted as decimal by js_strtod and will never get - * passed to js_strtointeger (which would interpret them as - * octal). - */ - str->getCharsAndEnd(bp, end); - - /* ECMA doesn't allow signed hex numbers (bug 273467). */ - bp = js_SkipWhiteSpace(bp, end); - if (bp + 2 < end && (*bp == '-' || *bp == '+') && - bp[1] == '0' && (bp[2] == 'X' || bp[2] == 'x')) { - break; - } - - if ((!js_strtod(cx, bp, end, &ep, &d) || - js_SkipWhiteSpace(ep, end) != end) && - (!js_strtointeger(cx, bp, end, &ep, 0, &d) || - js_SkipWhiteSpace(ep, end) != end)) { + d = StringToNumberType(cx, str); + if (JSDOUBLE_IS_NaN(d)) { break; } diff --git a/js/src/jsnum.h b/js/src/jsnum.h index f3e7a253dfe6..3075e0b66218 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -48,6 +48,8 @@ #include #endif +#include "jsstr.h" + /* * JS number (IEEE double) interface. * @@ -426,4 +428,62 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send, JS_END_EXTERN_C +namespace js { +template struct NumberTraits { }; +template<> struct NumberTraits { + static JS_ALWAYS_INLINE int32 NaN() { return 0; } + static JS_ALWAYS_INLINE int32 toSelfType(int32 i) { return i; } + static JS_ALWAYS_INLINE int32 toSelfType(jsdouble d) { return js_DoubleToECMAUint32(d); } +}; +template<> struct NumberTraits { + static JS_ALWAYS_INLINE jsdouble NaN() { return js_NaN; } + static JS_ALWAYS_INLINE jsdouble toSelfType(int32 i) { return i; } + static JS_ALWAYS_INLINE jsdouble toSelfType(jsdouble d) { return d; } +}; + +template +static JS_ALWAYS_INLINE T +StringToNumberType(JSContext *cx, JSString *str) +{ + if (str->length() == 1) { + jschar c = str->chars()[0]; + if ('0' <= c && c <= '9') + return NumberTraits::toSelfType(int32(c - '0')); + return NumberTraits::NaN(); + } + + const jschar* bp; + const jschar* end; + const jschar* ep; + jsdouble d; + + str->getCharsAndEnd(bp, end); + bp = js_SkipWhiteSpace(bp, end); + + /* ECMA doesn't allow signed hex numbers (bug 273467). */ + if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) { + /* Looks like a hex number. */ + if (!js_strtointeger(cx, bp, end, &ep, 16, &d) || + js_SkipWhiteSpace(ep, end) != end) { + return NumberTraits::NaN(); + } + return NumberTraits::toSelfType(d); + } + + /* + * Note that ECMA doesn't treat a string beginning with a '0' as + * an octal number here. This works because all such numbers will + * be interpreted as decimal by js_strtod. Also, any hex numbers + * that have made it here (which can only be negative ones) will + * be treated as 0 without consuming the 'x' by js_strtod. + */ + if (!js_strtod(cx, bp, end, &ep, &d) || + js_SkipWhiteSpace(ep, end) != end) { + return NumberTraits::NaN(); + } + + return NumberTraits::toSelfType(d); +} +} + #endif /* jsnum_h___ */ diff --git a/js/src/trace-test/tests/basic/testStringToNumber.js b/js/src/trace-test/tests/basic/testStringToNumber.js new file mode 100644 index 000000000000..e3e2fe7ddc5a --- /dev/null +++ b/js/src/trace-test/tests/basic/testStringToNumber.js @@ -0,0 +1,47 @@ +function convertToInt(str) { + return str | 0; +} + +function convertToIntOnTrace(str) { + var z; + for (var i = 0; i < RUNLOOP; ++i) { + z = str | 0; + } + return z; +} + +function convertToDouble(str) { + return str * 1.5; +} + +function convertToDoubleOnTrace(str) { + var z; + for (var i = 0; i < RUNLOOP; ++i) { + z = str * 1.5; + } + return z; +} + +assertEq(convertToInt("0x10"), 16); +assertEq(convertToInt("-0x10"), 0); + +assertEq(convertToIntOnTrace("0x10"), 16); +checkStats({ + traceTriggered: 1 +}); +assertEq(convertToIntOnTrace("-0x10"), 0); +checkStats({ + traceTriggered: 2 +}); + +assertEq(convertToDouble("0x10"), 24); +assertEq(convertToDouble("-0x10"), NaN); + +assertEq(convertToDoubleOnTrace("0x10"), 24); +checkStats({ + traceTriggered: 3 +}); +assertEq(convertToDoubleOnTrace("-0x10"), NaN); +checkStats({ + traceTriggered: 4 +}); From e59a6087bf10b2a09c103658791087761443c3ca Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Tue, 9 Mar 2010 14:29:50 -0800 Subject: [PATCH 52/52] Remove excessive braces; nuke else after return. --- js/src/jsnum.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index b166bb0a8e37..91e69fd3cfe4 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -957,9 +957,8 @@ js_ValueToNumber(JSContext *cx, jsval *vp) str = JSVAL_TO_STRING(v); d = StringToNumberType(cx, str); - if (JSDOUBLE_IS_NaN(d)) { + if (JSDOUBLE_IS_NaN(d)) break; - } /* * JSVAL_TRUE indicates that double jsval was never constructed @@ -972,10 +971,9 @@ js_ValueToNumber(JSContext *cx, jsval *vp) if (JSVAL_TO_BOOLEAN(v)) { *vp = JSVAL_ONE; return 1.0; - } else { - *vp = JSVAL_ZERO; - return 0.0; } + *vp = JSVAL_ZERO; + return 0.0; } if (JSVAL_IS_NULL(v)) { *vp = JSVAL_ZERO;