author | Bill McCloskey <wmccloskey@mozilla.com> |
Wed, 13 Jul 2011 15:43:33 -0700 | |
changeset 73439 | ed434f4c233eee7090fb9b38229bdc1354f1555f |
parent 73438 | 0737efca777e16746dd9435bad830164d3f2f5fd |
child 73440 | dbefaf7244f1885b217e37e7f3716282b23b2ea8 |
push id | 20871 |
push user | eakhgari@mozilla.com |
push date | Thu, 28 Jul 2011 14:37:48 +0000 |
treeherder | mozilla-central@fe48bbfeff94 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cdleary |
bugs | 673451 |
milestone | 8.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jsapi-tests/testConservativeGC.cpp +++ b/js/src/jsapi-tests/testConservativeGC.cpp @@ -47,17 +47,17 @@ BEGIN_TEST(testConservativeGC) bool checkObjectFields(JSObject *savedCopy, JSObject *obj) { /* * The GC can change the shape and shrink dslots so we update them before * doing memcmp. */ savedCopy->objShape = obj->objShape; - savedCopy->slots = obj->slots; + savedCopy->setSlotsPtr(obj->getSlotsPtr()); CHECK(!memcmp(savedCopy, obj, sizeof(*obj))); return true; } END_TEST(testConservativeGC) BEGIN_TEST(testDerivedValues) {
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4000,17 +4000,17 @@ JS_NewPropertyIterator(JSContext *cx, JS if (!ida) return NULL; pdata = ida; index = ida->length; } /* iterobj cannot escape to other threads here. */ iterobj->setPrivate(const_cast<void *>(pdata)); - iterobj->getSlotRef(JSSLOT_ITER_INDEX).setInt32(index); + iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index)); return iterobj; } JS_PUBLIC_API(JSBool) JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp) { jsint i; const Shape *shape;
--- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -268,17 +268,17 @@ JSObject::willBeSparseDenseArray(uintN r uintN minimalDenseCount = requiredCapacity / 4; if (newElementsHint >= minimalDenseCount) return false; minimalDenseCount -= newElementsHint; if (minimalDenseCount > cap) return true; - Value *elems = getDenseArrayElements(); + const Value *elems = getDenseArrayElements(); for (uintN i = 0; i < cap; i++) { if (!elems[i].isMagic(JS_ARRAY_HOLE) && !--minimalDenseCount) return false; } return true; } static bool @@ -368,19 +368,20 @@ GetElementsSlow(JSContext *cx, JSObject } bool GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp) { if (aobj->isDenseArray() && length <= aobj->getDenseArrayCapacity() && !js_PrototypeHasIndexedProperties(cx, aobj)) { /* The prototype does not have indexed properties so hole = undefined */ - Value *srcbeg = aobj->getDenseArrayElements(); - Value *srcend = srcbeg + length; - for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src) + const Value *srcbeg = aobj->getDenseArrayElements(); + const Value *srcend = srcbeg + length; + const Value *src = srcbeg; + for (Value *dst = vp; src < srcend; ++dst, ++src) *dst = src->isMagic(JS_ARRAY_HOLE) ? UndefinedValue() : *src; return true; } if (aobj->isArguments()) { ArgumentsObject *argsobj = aobj->asArguments(); if (!argsobj->hasOverriddenLength()) { if (argsobj->getElements(0, length, vp)) @@ -892,17 +893,17 @@ array_deleteProperty(JSContext *cx, JSOb } // namespace js static void array_trace(JSTracer *trc, JSObject *obj) { JS_ASSERT(obj->isDenseArray()); uint32 capacity = obj->getDenseArrayCapacity(); - MarkValueRange(trc, capacity, obj->slots, "element"); + MarkValueRange(trc, capacity, obj->getSlotsPtr(), "element"); } static JSBool array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props) { JS_ASSERT(obj->isDenseArray()); /* @@ -1264,19 +1265,19 @@ array_toString_sub(JSContext *cx, JSObje jsuint length; if (!js_GetLengthProperty(cx, obj, &length)) return false; StringBuffer sb(cx); if (!locale && !seplen && obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj)) { /* Elements beyond 'capacity' are 'undefined' and thus can be ignored. */ - Value *beg = obj->getDenseArrayElements(); - Value *end = beg + Min(length, obj->getDenseArrayCapacity()); - for (Value *vp = beg; vp != end; ++vp) { + const Value *beg = obj->getDenseArrayElements(); + const Value *end = beg + Min(length, obj->getDenseArrayCapacity()); + for (const Value *vp = beg; vp != end; ++vp) { if (!JS_CHECK_OPERATION_LIMIT(cx)) return false; if (!vp->isMagic(JS_ARRAY_HOLE) && !vp->isNullOrUndefined()) { if (!ValueToStringBuffer(cx, *vp, sb)) return false; } } @@ -1391,17 +1392,17 @@ InitArrayElements(JSContext *cx, JSObjec JS_ASSERT(result == JSObject::ED_SPARSE); break; } jsuint newlen = start + count; if (newlen > obj->getArrayLength()) obj->setArrayLength(newlen); JS_ASSERT(count < uint32(-1) / sizeof(Value)); - memcpy(obj->getDenseArrayElements() + start, vector, sizeof(jsval) * count); + obj->copyDenseArrayElements(start, vector, count); JS_ASSERT_IF(count != 0, !obj->getDenseArrayElement(newlen - 1).isMagic(JS_ARRAY_HOLE)); return true; } while (false); Value* end = vector + count; while (vector != end && start < MAXINDEX) { if (!JS_CHECK_OPERATION_LIMIT(cx) || !SetArrayElement(cx, obj, start++, *vector++)) { @@ -1440,17 +1441,17 @@ InitArrayObject(JSContext *cx, JSObject JS_ASSERT(obj->isDenseArray()); obj->setArrayLength(length); if (!vector || !length) return true; /* Avoid ensureDenseArrayElements to skip sparse array checks there. */ if (!obj->ensureSlots(cx, length)) return false; - memcpy(obj->getDenseArrayElements(), vector, length * sizeof(Value)); + obj->copyDenseArrayElements(0, vector, length); return true; } /* * Perl-inspired join, reverse, and sort. */ static JSBool array_join(JSContext *cx, uintN argc, Value *vp) @@ -2188,18 +2189,17 @@ array_shift(JSContext *cx, uintN argc, V } else { length--; if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && length < obj->getDenseArrayCapacity()) { *vp = obj->getDenseArrayElement(0); if (vp->isMagic(JS_ARRAY_HOLE)) vp->setUndefined(); - Value *elems = obj->getDenseArrayElements(); - memmove(elems, elems + 1, length * sizeof(jsval)); + obj->moveDenseArrayElements(0, 1, length); obj->setDenseArrayElement(length, MagicValue(JS_ARRAY_HOLE)); obj->setArrayLength(length); if (!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(length))) return JS_FALSE; return JS_TRUE; } /* Get the to-be-deleted property's value into vp ASAP. */ @@ -2251,18 +2251,17 @@ array_unshift(JSContext *cx, uintN argc, break; JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, argc); if (result != JSObject::ED_OK) { if (result == JSObject::ED_FAILED) return false; JS_ASSERT(result == JSObject::ED_SPARSE); break; } - Value *elems = obj->getDenseArrayElements(); - memmove(elems + argc, elems, length * sizeof(jsval)); + obj->moveDenseArrayElements(argc, 0, length); for (uint32 i = 0; i < argc; i++) obj->setDenseArrayElement(i, MagicValue(JS_ARRAY_HOLE)); optimized = true; } while (false); if (!optimized) { last = length; jsdouble upperIndex = last + argc; @@ -2390,22 +2389,17 @@ array_splice(JSContext *cx, uintN argc, break; JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, delta); if (result != JSObject::ED_OK) { if (result == JSObject::ED_FAILED) return false; JS_ASSERT(result == JSObject::ED_SPARSE); break; } - Value *arraybeg = obj->getDenseArrayElements(); - Value *srcbeg = arraybeg + last - 1; - Value *srcend = arraybeg + end - 1; - Value *dstbeg = srcbeg + delta; - for (Value *src = srcbeg, *dst = dstbeg; src > srcend; --src, --dst) - *dst = *src; + obj->moveDenseArrayElements(end + delta, end, last - end); obj->setArrayLength(obj->getArrayLength() + delta); optimized = true; } while (false); if (!optimized) { /* (uint) end could be 0, so we can't use a vanilla >= test. */ while (last-- > end) { @@ -2417,22 +2411,17 @@ array_splice(JSContext *cx, uintN argc, } } length += delta; } else if (argc < count) { delta = count - (jsuint)argc; if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) && length <= obj->getDenseArrayCapacity()) { - Value *arraybeg = obj->getDenseArrayElements(); - Value *srcbeg = arraybeg + end; - Value *srcend = arraybeg + length; - Value *dstbeg = srcbeg - delta; - for (Value *src = srcbeg, *dst = dstbeg; src < srcend; ++src, ++dst) - *dst = *src; + obj->moveDenseArrayElements(end - delta, end, length - end); } else { for (last = end; last < length; last++) { if (!JS_CHECK_OPERATION_LIMIT(cx) || !GetElement(cx, obj, last, &hole, tvr.addr()) || !SetOrDeleteArrayElement(cx, obj, last - delta, hole, tvr.value())) { return JS_FALSE; } } @@ -3086,26 +3075,26 @@ NewDenseAllocatedArray(JSContext *cx, ui JSObject * JS_FASTCALL NewDenseUnallocatedArray(JSContext *cx, uint32 length, JSObject *proto) { return NewArray<false>(cx, length, proto); } JSObject * -NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto) +NewDenseCopiedArray(JSContext *cx, uintN length, const Value *vp, JSObject *proto) { JSObject* obj = NewArray<true>(cx, length, proto); if (!obj) return NULL; JS_ASSERT(obj->getDenseArrayCapacity() >= length); if (vp) - memcpy(obj->getDenseArrayElements(), vp, length * sizeof(Value)); + obj->copyDenseArrayElements(0, vp, length); return obj; } #ifdef JS_TRACER JS_DEFINE_CALLINFO_2(extern, OBJECT, NewDenseEmptyArray, CONTEXT, OBJECT, 0, nanojit::ACCSET_STORE_ANY) JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseAllocatedArray, CONTEXT, UINT32, OBJECT, 0,
--- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -174,17 +174,17 @@ NewDenseAllocatedArray(JSContext *cx, ui * Create a dense array with a set length, but without allocating space for the * contents. This is useful, e.g., when accepting length from the user. */ extern JSObject * JS_FASTCALL NewDenseUnallocatedArray(JSContext *cx, uint length, JSObject *proto=NULL); /* Create a dense array with a copy of vp. */ extern JSObject * -NewDenseCopiedArray(JSContext *cx, uint length, Value *vp, JSObject *proto=NULL); +NewDenseCopiedArray(JSContext *cx, uint length, const Value *vp, JSObject *proto=NULL); /* Create a sparse array. */ extern JSObject * NewSlowEmptyArray(JSContext *cx); } extern JSBool
--- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -369,17 +369,17 @@ CallSetter(JSContext *cx, JSObject *obj, */ JS_FORCES_STACK JS_FRIEND_API(void) DeepBail(JSContext *cx); #endif static JS_INLINE void LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj) { - if (!obj->parent) + if (!obj->getParent()) LeaveTrace(cx); } static JS_INLINE void LeaveTraceIfArgumentsObject(JSContext *cx, JSObject *obj) { if (obj->isArguments()) LeaveTrace(cx);
--- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -1236,17 +1236,17 @@ GetUTCTime(JSContext *cx, JSObject *obj, */ static JSBool SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, Value *vp = NULL) { JS_ASSERT(obj->isDate()); size_t slotCap = JS_MIN(obj->numSlots(), JSObject::DATE_CLASS_RESERVED_SLOTS); for (size_t ind = JSObject::JSSLOT_DATE_COMPONENTS_START; ind < slotCap; ind++) - obj->getSlotRef(ind).setUndefined(); + obj->setSlot(ind, UndefinedValue()); obj->setDateUTCTime(DoubleValue(t)); if (vp) vp->setDouble(t); return true; } static void
--- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -1032,17 +1032,17 @@ js_InitExceptionClasses(JSContext *cx, J JSObject *proto = DefineConstructorAndPrototype(cx, obj, protoKey, atom, (i == JSEXN_ERR) ? obj_proto : error_proto, &js_ErrorClass, Exception, 1, NULL, (i == JSEXN_ERR) ? exception_methods : NULL, NULL, NULL); if (!proto) return NULL; - JS_ASSERT(proto->privateData == NULL); + JS_ASSERT(proto->getPrivate() == NULL); if (i == JSEXN_ERR) error_proto = proto; /* Add properties to the prototype. */ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING); if (!DefineNativeProperty(cx, proto, nameId, StringValue(atom), PropertyStub, StrictPropertyStub, 0, 0, 0) ||
--- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -865,19 +865,18 @@ js_CreateCallObjectOnTrace(JSContext *cx JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CreateCallObjectOnTrace, CONTEXT, FUNCTION, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY) inline static void CopyValuesToCallObject(JSObject &callobj, uintN nargs, Value *argv, uintN nvars, Value *slots) { JS_ASSERT(callobj.numSlots() >= JSObject::CALL_RESERVED_SLOTS + nargs + nvars); - Value *base = callobj.getSlots() + JSObject::CALL_RESERVED_SLOTS; - memcpy(base, argv, nargs * sizeof(Value)); - memcpy(base + nargs, slots, nvars * sizeof(Value)); + callobj.copySlots(JSObject::CALL_RESERVED_SLOTS, argv, nargs); + callobj.copySlots(JSObject::CALL_RESERVED_SLOTS + nargs, slots, nvars); } void js_PutCallObject(StackFrame *fp) { JSObject &callobj = fp->callObj(); JS_ASSERT(callobj.getPrivate() == fp); JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame()); @@ -1009,24 +1008,21 @@ GetCallArg(JSContext *cx, JSObject *obj, } JSBool SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp) { JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); uintN i = (uint16) JSID_TO_INT(id); - Value *argp; if (StackFrame *fp = obj->maybeCallObjStackFrame()) - argp = &fp->formalArg(i); + fp->formalArg(i) = *vp; else - argp = &obj->callObjArg(i); - - GCPoke(cx, *argp); - *argp = *vp; + obj->setCallObjArg(i, *vp); + return true; } JSBool GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp) { JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); uintN i = (uint16) JSID_TO_INT(id); @@ -1036,20 +1032,17 @@ GetCallUpvar(JSContext *cx, JSObject *ob } JSBool SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp) { JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); uintN i = (uint16) JSID_TO_INT(id); - Value *up = &obj->getCallObjCallee()->getFlatClosureUpvar(i); - - GCPoke(cx, *up); - *up = *vp; + obj->getCallObjCallee()->setFlatClosureUpvar(i, *vp); return true; } JSBool GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp) { JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id)); uintN i = (uint16) JSID_TO_INT(id); @@ -1079,24 +1072,21 @@ SetCallVar(JSContext *cx, JSObject *obj, #ifdef JS_TRACER if (JS_ON_TRACE(cx)) { TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx); if (tm->recorder && tm->tracecx) AbortRecording(cx, "upvar write in nested tree"); } #endif - Value *varp; if (StackFrame *fp = obj->maybeCallObjStackFrame()) - varp = &fp->varSlot(i); + fp->varSlot(i) = *vp; else - varp = &obj->callObjVar(i); - - GCPoke(cx, *varp); - *varp = *vp; + obj->setCallObjVar(i, *vp); + return true; } } // namespace js #if JS_TRACER JSBool JS_FASTCALL js_SetCallArg(JSContext *cx, JSObject *obj, jsid slotid, ValueArgType arg) @@ -1169,17 +1159,17 @@ call_trace(JSTracer *trc, JSObject *obj) * for JS objects (including Call objects), so is unable to collect * cycles involving Call objects whose frames are active without this * hiding hack. */ uintN first = JSObject::CALL_RESERVED_SLOTS; uintN count = fp->script()->bindings.countArgsAndVars(); JS_ASSERT(obj->numSlots() >= first + count); - SetValueRangeToUndefined(obj->getSlots() + first, count); + obj->setSlotsUndefined(first, count); } MaybeMarkGenerator(trc, obj); } JS_PUBLIC_DATA(Class) js_CallClass = { "Call", JSCLASS_HAS_PRIVATE | @@ -1918,32 +1908,32 @@ CallOrConstructBoundFunction(JSContext * inline bool JSObject::initBoundFunction(JSContext *cx, const Value &thisArg, const Value *args, uintN argslen) { JS_ASSERT(isFunction()); flags |= JSObject::BOUND_FUNCTION; - getSlotRef(JSSLOT_BOUND_FUNCTION_THIS) = thisArg; - getSlotRef(JSSLOT_BOUND_FUNCTION_ARGS_COUNT).setPrivateUint32(argslen); + setSlot(JSSLOT_BOUND_FUNCTION_THIS, thisArg); + setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT, PrivateUint32Value(argslen)); if (argslen != 0) { /* FIXME? Burn memory on an empty scope whose shape covers the args slots. */ - EmptyShape *empty = EmptyShape::create(cx, clasp); + EmptyShape *empty = EmptyShape::create(cx, getClass()); if (!empty) return false; empty->slotSpan += argslen; setMap(empty); if (!ensureInstanceReservedSlots(cx, argslen)) return false; JS_ASSERT(numSlots() >= argslen + FUN_CLASS_RESERVED_SLOTS); - memcpy(getSlots() + FUN_CLASS_RESERVED_SLOTS, args, argslen * sizeof(Value)); + copySlots(FUN_CLASS_RESERVED_SLOTS, args, argslen); } return true; } inline JSObject * JSObject::getBoundFunctionTarget() const { JS_ASSERT(isFunction());
--- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -185,37 +185,30 @@ struct JSFunction : public JSObject_Slot * a compiler-created function object use the first one to hold a mutable * methodAtom() state variable, needed for correct foo.caller handling. */ enum { METHOD_ATOM_SLOT = JSSLOT_FUN_METHOD_ATOM }; public: - void setJoinable() { - JS_ASSERT(FUN_INTERPRETED(this)); - getSlotRef(METHOD_ATOM_SLOT).setNull(); - flags |= JSFUN_JOINABLE; - } + inline void setJoinable(); /* * Method name imputed from property uniquely assigned to or initialized, * where the function does not need to be cloned to carry a scope chain or * flattened upvars. */ JSAtom *methodAtom() const { return (joinable() && getSlot(METHOD_ATOM_SLOT).isString()) ? &getSlot(METHOD_ATOM_SLOT).toString()->asAtom() : NULL; } - void setMethodAtom(JSAtom *atom) { - JS_ASSERT(joinable()); - getSlotRef(METHOD_ATOM_SLOT).setString(atom); - } + inline void setMethodAtom(JSAtom *atom); JSScript *script() const { JS_ASSERT(isInterpreted()); return u.i.script; } js::Native native() const { JS_ASSERT(isNative());
--- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -44,9 +44,24 @@ #include "jsscript.h" inline bool JSFunction::inStrictMode() const { return script()->strictModeCode; } +inline void +JSFunction::setJoinable() +{ + JS_ASSERT(FUN_INTERPRETED(this)); + setSlot(METHOD_ATOM_SLOT, js::NullValue()); + flags |= JSFUN_JOINABLE; +} + +inline void +JSFunction::setMethodAtom(JSAtom *atom) +{ + JS_ASSERT(joinable()); + setSlot(METHOD_ATOM_SLOT, js::StringValue(atom)); +} + #endif /* jsfuninlines_h___ */
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3269,23 +3269,23 @@ BEGIN_CASE(JSOP_GNAMEDEC) JSObject *obj2; PropertyCacheEntry *entry; JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, atom); if (!atom) { ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry); if (obj == obj2 && entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - Value &rref = obj->nativeGetSlotRef(slot); + const Value &rref = obj->nativeGetSlot(slot); int32_t tmp; if (JS_LIKELY(rref.isInt32() && CanIncDecWithoutOverflow(tmp = rref.toInt32()))) { int32_t inc = tmp + ((js_CodeSpec[op].format & JOF_INC) ? 1 : -1); if (!(js_CodeSpec[op].format & JOF_POST)) tmp = inc; - rref.getInt32Ref() = inc; + obj->nativeSetSlot(slot, Int32Value(inc)); PUSH_INT32(tmp); len = JSOP_INCNAME_LENGTH; DO_NEXT_OP(len); } } LOAD_ATOM(0, atom); } @@ -3848,26 +3848,26 @@ BEGIN_CASE(JSOP_GETELEM) Value rval; jsid id; if (rref.isInt32()) { int32_t i = rref.toInt32(); if (obj->isDenseArray()) { jsuint idx = jsuint(i); if (idx < obj->getDenseArrayCapacity()) { - copyFrom = obj->addressOfDenseArrayElement(idx); + copyFrom = &obj->getDenseArrayElement(idx); if (!copyFrom->isMagic()) goto end_getelem; } } else if (obj->isArguments()) { uint32 arg = uint32(i); ArgumentsObject *argsobj = obj->asArguments(); if (arg < argsobj->initialLength()) { - copyFrom = argsobj->addressOfElement(arg); + copyFrom = &argsobj->element(arg); if (!copyFrom->isMagic(JS_ARGS_HOLE)) { if (StackFrame *afp = reinterpret_cast<StackFrame *>(argsobj->getPrivate())) copyFrom = &afp->canonicalActualArg(arg); goto end_getelem; } } } if (JS_LIKELY(INT_FITS_IN_JSID(i)))
--- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -225,17 +225,17 @@ EnumerateDenseArrayProperties(JSContext { if (!Enumerate(cx, obj, pobj, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), false, flags, ht, props)) { return false; } if (pobj->getArrayLength() > 0) { size_t capacity = pobj->getDenseArrayCapacity(); - Value *vp = pobj->getDenseArrayElements(); + const Value *vp = pobj->getDenseArrayElements(); for (size_t i = 0; i < capacity; ++i, ++vp) { if (!vp->isMagic(JS_ARRAY_HOLE)) { /* Dense arrays never get so large that i would not fit into an integer id. */ if (!Enumerate(cx, obj, pobj, INT_TO_JSID(i), true, flags, ht, props)) return false; } } }
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2925,17 +2925,17 @@ js_CreateThisFromTrace(JSContext *cx, JS const Shape *shape = ctor->nativeLookup(id); JS_ASSERT(shape->slot == protoSlot); JS_ASSERT(!shape->configurable()); JS_ASSERT(!shape->isMethod()); #endif JSObject *parent = ctor->getParent(); JSObject *proto; - const Value &protov = ctor->getSlotRef(protoSlot); + const Value &protov = ctor->getSlot(protoSlot); if (protov.isObject()) { proto = &protov.toObject(); } else { /* * GetInterpretedFunctionPrototype found that ctor.prototype is * primitive. Use Object.prototype for proto, per ES5 13.2.2 step 7. */ if (!js_GetClassPrototype(cx, parent, JSProto_Object, &proto)) @@ -3252,17 +3252,17 @@ js_PutBlockObject(JSContext *cx, JSBool JS_ASSERT(count <= size_t(cx->regs().sp - fp->base() - depth)); /* See comments in CheckDestructuring from jsparse.cpp. */ JS_ASSERT(count >= 1); if (normalUnwind) { uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT; depth += fp->numFixed(); - memcpy(obj->getSlots() + slot, fp->slots() + depth, count * sizeof(Value)); + obj->copySlots(slot, fp->slots() + depth, count); } /* We must clear the private slot even with errors. */ obj->setPrivate(NULL); fp->setScopeChainNoCallObj(*obj->getParent()); return normalUnwind; } @@ -3380,26 +3380,26 @@ CopySlots(JSContext *cx, JSObject *from, JS_ASSERT(!from->isNative() && !to->isNative()); size_t nslots = from->numSlots(); if (to->ensureSlots(cx, nslots)) return false; size_t n = 0; if (to->isWrapper() && (JSWrapper::wrapperHandler(to)->flags() & JSWrapper::CROSS_COMPARTMENT)) { - to->slots[0] = from->slots[0]; - to->slots[1] = from->slots[1]; + to->setSlot(0, from->getSlot(0)); + to->setSlot(1, from->getSlot(1)); n = 2; } for (; n < nslots; ++n) { - Value v = from->slots[n]; + Value v = from->getSlot(n); if (!cx->compartment->wrap(cx, &v)) return false; - to->slots[n] = v; + to->setSlot(n, v); } return true; } JSObject * JSObject::clone(JSContext *cx, JSObject *proto, JSObject *parent) { /* @@ -3466,19 +3466,19 @@ TradeGuts(JSObject *a, JSObject *b) JS_ASSERT(size <= sizeof(tmp)); memcpy(tmp, a, size); memcpy(a, b, size); memcpy(b, tmp, size); /* Fixup pointers for inline slots on the objects. */ if (aInline) - b->slots = b->fixedSlots(); + b->setSlotsPtr(b->fixedSlots()); if (bInline) - a->slots = a->fixedSlots(); + a->setSlotsPtr(a->fixedSlots()); } else { /* * If the objects are of differing sizes, then we only copy over the * JSObject portion (things like class, etc.) and leave it to * JSObject::clone to copy over the dynamic slots for us. */ if (a->isFunction()) { JSFunction tmp; @@ -3782,17 +3782,17 @@ DefineConstructorAndPrototype(JSContext /* * Create the prototype object. (GlobalObject::createBlankPrototype isn't * used because it parents the prototype object to the global and because * it uses WithProto::Given. FIXME: Undo dependencies on this parentage * [which already needs to happen for bug 638316], figure out nicer * semantics for null-protoProto, and use createBlankPrototype.) */ JSObject *proto = NewObject<WithProto::Class>(cx, clasp, protoProto, obj); - if (!proto || !proto->getEmptyShape(cx, proto->clasp, gc::FINALIZE_OBJECT0)) + if (!proto || !proto->getEmptyShape(cx, proto->getClass(), gc::FINALIZE_OBJECT0)) return NULL; proto->syncSpecialEquality(); /* After this point, control must exit via label bad or out. */ JSObject *ctor; bool named = false; if (!constructor) { @@ -4060,17 +4060,17 @@ JSObject::shrinkSlots(JSContext *cx, siz } bool JSObject::ensureInstanceReservedSlots(JSContext *cx, size_t nreserved) { JS_ASSERT_IF(isNative(), isBlock() || isCall() || (isFunction() && isBoundFunction())); - uintN nslots = JSSLOT_FREE(clasp) + nreserved; + uintN nslots = JSSLOT_FREE(getClass()) + nreserved; return nslots <= numSlots() || allocSlots(cx, nslots); } static JSObject * js_InitNullClass(JSContext *cx, JSObject *obj) { JS_ASSERT(0); return NULL; @@ -4314,36 +4314,37 @@ js_ConstructObject(JSContext *cx, Class } return obj; } bool JSObject::allocSlot(JSContext *cx, uint32 *slotp) { uint32 slot = slotSpan(); - JS_ASSERT(slot >= JSSLOT_FREE(clasp)); + JS_ASSERT(slot >= JSSLOT_FREE(getClass())); /* * If this object is in dictionary mode and it has a property table, try to * pull a free slot from the property table's slot-number freelist. */ if (inDictionaryMode() && lastProp->hasTable()) { - uint32 &last = lastProp->getTable()->freelist; + PropertyTable *table = lastProp->getTable(); + uint32 last = table->freelist; if (last != SHAPE_INVALID_SLOT) { #ifdef DEBUG JS_ASSERT(last < slot); uint32 next = getSlot(last).toPrivateUint32(); JS_ASSERT_IF(next != SHAPE_INVALID_SLOT, next < slot); #endif *slotp = last; - Value &vref = getSlotRef(last); - last = vref.toPrivateUint32(); - vref.setUndefined(); + const Value &vref = getSlot(last); + table->freelist = vref.toPrivateUint32(); + setSlot(last, UndefinedValue()); return true; } } if (slot >= numSlots() && !growSlots(cx, slot + 1)) return false; /* JSObject::growSlots or JSObject::freeSlot should set the free slots to void. */ @@ -4353,37 +4354,36 @@ JSObject::allocSlot(JSContext *cx, uint3 } bool JSObject::freeSlot(JSContext *cx, uint32 slot) { uint32 limit = slotSpan(); JS_ASSERT(slot < limit); - Value &vref = getSlotRef(slot); if (inDictionaryMode() && lastProp->hasTable()) { uint32 &last = lastProp->getTable()->freelist; /* Can't afford to check the whole freelist, but let's check the head. */ JS_ASSERT_IF(last != SHAPE_INVALID_SLOT, last < limit && last != slot); /* * Freeing a slot other than the last one mapped by this object's * shape (and not a reserved slot; see bug 595230): push the slot onto * the dictionary property table's freelist. We want to let the last * slot be freed by shrinking the dslots vector; see js_TraceObject. */ - if (JSSLOT_FREE(clasp) <= slot && slot + 1 < limit) { + if (JSSLOT_FREE(getClass()) <= slot && slot + 1 < limit) { JS_ASSERT_IF(last != SHAPE_INVALID_SLOT, last < slotSpan()); - vref.setPrivateUint32(last); + setSlot(slot, PrivateUint32Value(last)); last = slot; return true; } } - vref.setUndefined(); + setSlot(slot, UndefinedValue()); return false; } /* JSBOXEDWORD_INT_MAX as a string */ #define JSBOXEDWORD_INT_MAX_STRING "1073741823" /* * Convert string indexes that convert to int jsvals as ints to save memory.
--- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -388,18 +388,23 @@ struct JSObject : js::gc::Cell { /* If prototype, lazily filled array of empty shapes for each object size. */ js::EmptyShape **emptyShapes; JSObject *proto; /* object's prototype */ JSObject *parent; /* object's parent */ void *privateData; /* private data */ jsuword capacity; /* number of slots; for ArrayBuffer the number may be be non-integral, so this may underestimate */ + private: js::Value *slots; /* dynamically allocated slots, or pointer to fixedSlots() */ + public: + static size_t offsetOfSlots() { + return offsetof(JSObject, slots); + } /* * Return an immutable, shareable, empty shape with the same clasp as this * and the same slotSpan as this had when empty. * * If |this| is the scope of an object |proto|, the resulting scope can be * used as the scope of a new object whose prototype is |proto|. */ @@ -637,18 +642,29 @@ struct JSObject : js::gc::Cell { * their initial map. */ bool ensureInstanceReservedSlots(JSContext *cx, size_t nreserved); /* * Get a direct pointer to the object's slots. * This can be reallocated if the object is modified, watch out! */ - js::Value *getSlots() const { - return slots; + const js::Value *getSlots() const { return slots; } + + js::Value *getSlotsPtr() { return slots; } + void setSlotsPtr(js::Value *vp) { slots = vp; } + + void copySlots(uint32 dstStart, const js::Value *src, uint32 count) { + JS_ASSERT(dstStart + count <= capacity); + memcpy(slots + dstStart, src, count * sizeof(js::Value)); + } + + void setSlotsUndefined(uint32 start, uint32 count) { + JS_ASSERT(start + count <= capacity); + js::SetValueRangeToUndefined(slots + start, count); } /* * NB: ensureClassReservedSlotsForEmptyObject asserts that nativeEmpty() * Use ensureClassReservedSlots for any object, either empty or already * extended with properties. */ bool ensureClassReservedSlotsForEmptyObject(JSContext *cx); @@ -780,20 +796,21 @@ struct JSObject : js::gc::Cell { /* * Array-specific getters and setters (for both dense and slow arrays). */ inline uint32 getArrayLength() const; inline void setArrayLength(uint32 length); inline uint32 getDenseArrayCapacity(); - inline js::Value* getDenseArrayElements(); + inline const js::Value* getDenseArrayElements(); inline const js::Value &getDenseArrayElement(uintN idx); - inline js::Value* addressOfDenseArrayElement(uintN idx); inline void setDenseArrayElement(uintN idx, const js::Value &val); + inline void copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count); + inline void moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count); inline void shrinkDenseArrayElements(JSContext *cx, uintN cap); /* * ensureDenseArrayElements ensures that the dense array can hold at least * index + extra elements. It returns ED_OK on success, ED_FAILED on * failure to grow the array, ED_SPARSE when the array is too sparse to * grow (this includes the case of index + extra overflow). In the last * two cases the array is kept intact. @@ -847,21 +864,21 @@ struct JSObject : js::gc::Cell { inline JSFunction *getCallObjCalleeFunction() const; inline void setCallObjCallee(JSObject *callee); inline const js::Value &getCallObjArguments() const; inline void setCallObjArguments(const js::Value &v); /* Returns the formal argument at the given index. */ inline const js::Value &callObjArg(uintN i) const; - inline js::Value &callObjArg(uintN i); + inline void setCallObjArg(uintN i, const js::Value &v); /* Returns the variable at the given index. */ inline const js::Value &callObjVar(uintN i) const; - inline js::Value &callObjVar(uintN i); + inline void setCallObjVar(uintN i, const js::Value &v); /* * Date-specific getters and setters. */ static const uint32 JSSLOT_DATE_UTC_TIME = 0; /* @@ -912,17 +929,18 @@ struct JSObject : js::gc::Cell { public: static const uint32 FUN_CLASS_RESERVED_SLOTS = 2; inline JSFunction *getFunctionPrivate() const; inline js::Value *getFlatClosureUpvars() const; inline js::Value getFlatClosureUpvar(uint32 i) const; - inline js::Value &getFlatClosureUpvar(uint32 i); + inline const js::Value &getFlatClosureUpvar(uint32 i); + inline void setFlatClosureUpvar(uint32 i, const js::Value &v); inline void setFlatClosureUpvars(js::Value *upvars); inline bool hasMethodObj(const JSObject& obj) const; inline void setMethodObj(JSObject& obj); inline bool initBoundFunction(JSContext *cx, const js::Value &thisArg, const js::Value *args, uintN argslen);
--- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -119,17 +119,17 @@ JSObject::unbrand(JSContext *cx) } setGeneric(); return true; } inline void JSObject::syncSpecialEquality() { - if (clasp->ext.equality) + if (getClass()->ext.equality) flags |= JSObject::HAS_EQUALITY; } inline void JSObject::finalize(JSContext *cx) { /* Cope with stillborn objects that have no map. */ if (isNewborn()) @@ -355,45 +355,54 @@ JSObject::setArrayLength(uint32 length) inline uint32 JSObject::getDenseArrayCapacity() { JS_ASSERT(isDenseArray()); return numSlots(); } -inline js::Value* +inline const js::Value * JSObject::getDenseArrayElements() { JS_ASSERT(isDenseArray()); return getSlots(); } inline const js::Value & JSObject::getDenseArrayElement(uintN idx) { JS_ASSERT(isDenseArray()); return getSlot(idx); } -inline js::Value * -JSObject::addressOfDenseArrayElement(uintN idx) -{ - JS_ASSERT(isDenseArray()); - return &getSlotRef(idx); -} - inline void JSObject::setDenseArrayElement(uintN idx, const js::Value &val) { JS_ASSERT(isDenseArray()); setSlot(idx, val); } inline void +JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count) +{ + JS_ASSERT(isDenseArray()); + copySlots(dstStart, src, count); +} + +inline void +JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count) +{ + JS_ASSERT(isDenseArray()); + JS_ASSERT(dstStart + count <= capacity); + JS_ASSERT(srcStart + count <= capacity); + memmove(slots + dstStart, getSlots() + srcStart, count * sizeof(js::Value)); +} + +inline void JSObject::shrinkDenseArrayElements(JSContext *cx, uintN cap) { JS_ASSERT(isDenseArray()); shrinkSlots(cx, cap); } inline bool JSObject::callIsForEval() const @@ -412,17 +421,17 @@ JSObject::maybeCallObjStackFrame() const return reinterpret_cast<js::StackFrame *>(getPrivate()); } inline void JSObject::setCallObjCallee(JSObject *callee) { JS_ASSERT(isCall()); JS_ASSERT_IF(callee, callee->isFunction()); - return getSlotRef(JSSLOT_CALL_CALLEE).setObjectOrNull(callee); + setSlot(JSSLOT_CALL_CALLEE, js::ObjectOrNullValue(callee)); } inline JSObject * JSObject::getCallObjCallee() const { JS_ASSERT(isCall()); return getSlot(JSSLOT_CALL_CALLEE).toObjectOrNull(); } @@ -453,40 +462,40 @@ JSObject::setCallObjArguments(const js:: inline const js::Value & JSObject::callObjArg(uintN i) const { JS_ASSERT(isCall()); JS_ASSERT(i < getCallObjCalleeFunction()->nargs); return getSlot(JSObject::CALL_RESERVED_SLOTS + i); } -inline js::Value & -JSObject::callObjArg(uintN i) +inline void +JSObject::setCallObjArg(uintN i, const js::Value &v) { JS_ASSERT(isCall()); JS_ASSERT(i < getCallObjCalleeFunction()->nargs); - return getSlotRef(JSObject::CALL_RESERVED_SLOTS + i); + setSlot(JSObject::CALL_RESERVED_SLOTS + i, v); } inline const js::Value & JSObject::callObjVar(uintN i) const { JSFunction *fun = getCallObjCalleeFunction(); JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs()); JS_ASSERT(i < fun->script()->bindings.countVars()); return getSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i); } -inline js::Value & -JSObject::callObjVar(uintN i) +inline void +JSObject::setCallObjVar(uintN i, const js::Value &v) { JSFunction *fun = getCallObjCalleeFunction(); JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs()); JS_ASSERT(i < fun->script()->bindings.countVars()); - return getSlotRef(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i); + setSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i, v); } inline const js::Value & JSObject::getDateUTCTime() const { JS_ASSERT(isDate()); return getSlot(JSSLOT_DATE_UTC_TIME); } @@ -511,43 +520,50 @@ JSObject::getFlatClosureUpvars() const inline js::Value JSObject::getFlatClosureUpvar(uint32 i) const { JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); return getFlatClosureUpvars()[i]; } -inline js::Value & +inline const js::Value & JSObject::getFlatClosureUpvar(uint32 i) { JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); return getFlatClosureUpvars()[i]; } inline void +JSObject::setFlatClosureUpvar(uint32 i, const js::Value &v) +{ + JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars()); + getFlatClosureUpvars()[i] = v; +} + +inline void JSObject::setFlatClosureUpvars(js::Value *upvars) { JS_ASSERT(isFunction()); JS_ASSERT(FUN_FLAT_CLOSURE(getFunctionPrivate())); - getSlotRef(JSSLOT_FLAT_CLOSURE_UPVARS).setPrivate(upvars); + setSlot(JSSLOT_FLAT_CLOSURE_UPVARS, PrivateValue(upvars)); } inline bool JSObject::hasMethodObj(const JSObject& obj) const { return JSSLOT_FUN_METHOD_OBJ < numSlots() && getSlot(JSSLOT_FUN_METHOD_OBJ).isObject() && getSlot(JSSLOT_FUN_METHOD_OBJ).toObject() == obj; } inline void JSObject::setMethodObj(JSObject& obj) { - getSlotRef(JSSLOT_FUN_METHOD_OBJ).setObject(obj); + setSlot(JSSLOT_FUN_METHOD_OBJ, js::ObjectValue(obj)); } inline js::NativeIterator * JSObject::getNativeIterator() const { return (js::NativeIterator *) getPrivate(); } @@ -648,17 +664,17 @@ inline JSObject * JSObject::getWithThis() const { return &getSlot(JSSLOT_WITH_THIS).toObject(); } inline void JSObject::setWithThis(JSObject *thisp) { - getSlotRef(JSSLOT_WITH_THIS).setObject(*thisp); + setSlot(JSSLOT_WITH_THIS, js::ObjectValue(*thisp)); } inline void JSObject::init(JSContext *cx, js::Class *aclasp, JSObject *proto, JSObject *parent, void *priv, bool useHoles) { clasp = aclasp; flags = 0;
--- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -582,17 +582,17 @@ JSObject::checkShapeConsistency() Shape *shape = lastProp; Shape *prev = NULL; if (inDictionaryMode()) { if (shape->hasTable()) { PropertyTable *table = shape->getTable(); for (uint32 fslot = table->freelist; fslot != SHAPE_INVALID_SLOT; - fslot = getSlotRef(fslot).toPrivateUint32()) { + fslot = getSlot(fslot).toPrivateUint32()) { JS_ASSERT(fslot < shape->slotSpan); } for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) { JS_ASSERT_IF(shape != lastProp, !shape->hasTable()); Shape **spp = table->search(shape->propid, false); JS_ASSERT(SHAPE_FETCH(spp) == shape); @@ -901,17 +901,17 @@ JSObject::putProperty(JSContext *cx, jsi * has no slot. But we do not need to free oldSlot (and must not, as trying * to will botch an assertion in JSObject::freeSlot) if the new lastProp * (shape here) has a slotSpan that does not cover it. */ if (hadSlot && !shape->hasSlot()) { if (oldSlot < shape->slotSpan) freeSlot(cx, oldSlot); else - getSlotRef(oldSlot).setUndefined(); + setSlot(oldSlot, UndefinedValue()); JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals); } CHECK_SHAPE_CONSISTENCY(this); return js_UpdateWatchpointsForShape(cx, this, shape); } @@ -1097,17 +1097,17 @@ JSObject::removeProperty(JSContext *cx, if (table->freelist != SHAPE_INVALID_SLOT) { lastProp->slotSpan = shape->slotSpan; /* * Add the slot to the freelist if it wasn't added in * freeSlot and it is not a reserved slot. */ if (hadSlot && !addedToFreelist && JSSLOT_FREE(clasp) <= shape->slot) { - getSlotRef(shape->slot).setPrivateUint32(table->freelist); + setSlot(shape->slot, PrivateUint32Value(table->freelist)); table->freelist = shape->slot; } } } /* Hand off table from old to new lastProp. */ oldLastProp->setTable(NULL); lastProp->setTable(table);
--- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3043,17 +3043,17 @@ TraceMonitor::mark(JSTracer *trc) /* * Box a value from the native stack back into the Value format. */ static inline void NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot) { if (type == JSVAL_TYPE_DOUBLE) { - v.setNumber(*slot); + v = NumberValue(*slot); } else if (JS_LIKELY(type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET)) { v.boxNonDoubleFrom(type, (uint64 *)slot); } else if (type == JSVAL_TYPE_STRORNULL) { JSString *str = *(JSString **)slot; v = str ? StringValue(str) : NullValue(); } else if (type == JSVAL_TYPE_OBJORNULL) { JSObject *obj = *(JSObject **)slot; v = obj ? ObjectValue(*obj) : NullValue(); @@ -3832,17 +3832,17 @@ TraceRecorder::isValidSlot(JSObject *obj /* Lazily import a global slot if we don't already have it in the tracker. */ JS_REQUIRES_STACK void TraceRecorder::importGlobalSlot(unsigned slot) { JS_ASSERT(slot == uint16(slot)); JS_ASSERT(globalObj->numSlots() <= MAX_GLOBAL_SLOTS); - Value* vp = &globalObj->getSlotRef(slot); + const Value* vp = &globalObj->getSlot(slot); JS_ASSERT(!known(vp)); /* Add the slot to the list of interned global slots. */ JSValueType type; int index = tree->globalSlots->offsetOf(uint16(slot)); if (index == -1) { type = getCoercedType(*vp); if (type == JSVAL_TYPE_INT32 && (!oracle || oracle->isGlobalSlotUndemotable(cx, slot))) @@ -3865,17 +3865,17 @@ TraceRecorder::lazilyImportGlobalSlot(un if (slot != uint16(slot)) /* we use a table of 16-bit ints, bail out if that's not enough */ return false; /* * If the global object grows too large, alloca in ExecuteTree might fail, * so abort tracing on global objects with unreasonably many slots. */ if (globalObj->numSlots() > MAX_GLOBAL_SLOTS) return false; - Value* vp = &globalObj->getSlotRef(slot); + const Value* vp = &globalObj->getSlot(slot); if (known(vp)) return true; /* we already have it */ importGlobalSlot(slot); return true; } /* Write back a value onto the stack or global frames. */ LIns* @@ -3898,17 +3898,17 @@ TraceRecorder::writeBack(LIns* ins, LIns unsigned slot = unsigned(offset / sizeof(double)); (void)pendingGlobalSlotsToSet.append(slot); /* OOM is safe. */ } return w.st(ins, addr); } /* Update the tracker, then issue a write back store. */ JS_REQUIRES_STACK void -TraceRecorder::setImpl(void* p, LIns* i, bool shouldDemoteToInt32) +TraceRecorder::setImpl(const void* p, LIns* i, bool shouldDemoteToInt32) { JS_ASSERT(i != NULL); checkForGlobalObjectReallocation(); tracker.set(p, i); /* * If we are writing to this location for the first time, calculate the * offset into the native frame manually. Otherwise just look up the last @@ -3943,17 +3943,17 @@ TraceRecorder::setImpl(void* p, LIns* i, ? nativespOffsetImpl(p) : nativeGlobalOffset((Value *)p))); writeBack(i, base, disp, shouldDemoteToInt32); } } JS_REQUIRES_STACK inline void -TraceRecorder::set(Value* p, LIns* i, bool shouldDemoteToInt32) +TraceRecorder::set(const Value* p, LIns* i, bool shouldDemoteToInt32) { return setImpl(p, i, shouldDemoteToInt32); } JS_REQUIRES_STACK void TraceRecorder::setFrameObjPtr(void* p, LIns* i, bool shouldDemoteToInt32) { JS_ASSERT(isValidFrameObjPtr(p)); @@ -4066,18 +4066,18 @@ TraceRecorder::known(JSObject** p) * The slots of the global object are sometimes reallocated by the interpreter. * This function check for that condition and re-maps the entries of the tracker * accordingly. */ JS_REQUIRES_STACK void TraceRecorder::checkForGlobalObjectReallocationHelper() { debug_only_print0(LC_TMTracer, "globalObj->slots relocated, updating tracker\n"); - Value* src = global_slots; - Value* dst = globalObj->getSlots(); + const Value* src = global_slots; + const Value* dst = globalObj->getSlots(); jsuint length = globalObj->capacity; LIns** map = (LIns**)alloca(sizeof(LIns*) * length); for (jsuint n = 0; n < length; ++n) { map[n] = tracker.get(src); tracker.set(src++, NULL); } for (jsuint n = 0; n < length; ++n) tracker.set(dst++, map[n]); @@ -5453,17 +5453,17 @@ TraceRecorder::emitTreeCall(TreeFragment #endif /* The inner tree may modify currently-tracked upvars, so flush everything. */ ClearSlotsVisitor visitor(tracker); VisitStackSlots(visitor, cx, callDepth); SlotList& gslots = *tree->globalSlots; for (unsigned i = 0; i < gslots.length(); i++) { unsigned slot = gslots[i]; - Value* vp = &globalObj->getSlotRef(slot); + const Value* vp = &globalObj->getSlot(slot); tracker.set(vp, NULL); } /* Set stack slots from the innermost frame. */ importTypeMap.setLength(NativeStackSlots(cx, callDepth)); unsigned startOfInnerFrame = importTypeMap.length() - exit->numStackSlots; for (unsigned i = 0; i < exit->numStackSlots; i++) importTypeMap[startOfInnerFrame + i] = exit->stackTypeMap()[i]; @@ -8144,17 +8144,17 @@ JS_DEFINE_CALLINFO_4(extern, UINT32, Get * generate LIR to access the given property. Return RECORD_CONTINUE on success, * otherwise abort and return RECORD_STOP. There are 3 outparams: * * vp the address of the current property value * ins LIR instruction representing the property value on trace * NameResult describes how to look up name; see comment for NameResult in jstracer.h */ JS_REQUIRES_STACK AbortableRecordingStatus -TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameResult& nr, +TraceRecorder::scopeChainProp(JSObject* chainHead, const Value*& vp, LIns*& ins, NameResult& nr, JSObject** scopeObjp) { JS_ASSERT(chainHead == &cx->fp()->scopeChain()); JS_ASSERT(chainHead != globalObj); TraceMonitor &localtm = *traceMonitor; JSAtom* atom = atoms[GET_INDEX(cx->regs().pc)]; @@ -8194,17 +8194,17 @@ TraceRecorder::scopeChainProp(JSObject* if (obj2 != obj) RETURN_STOP_A("prototype property"); Shape* shape = (Shape*) prop; if (!isValidSlot(obj, shape)) return ARECORD_STOP; if (!lazilyImportGlobalSlot(shape->slot)) RETURN_STOP_A("lazy import of global slot failed"); - vp = &obj->getSlotRef(shape->slot); + vp = &obj->getSlot(shape->slot); ins = get(vp); nr.tracked = true; return ARECORD_CONTINUE; } if (obj == obj2 && obj->isCall()) { AbortableRecordingStatus status = InjectStatus(callProp(obj, prop, ATOM_TO_JSID(atom), vp, ins, nr)); @@ -8213,17 +8213,17 @@ TraceRecorder::scopeChainProp(JSObject* RETURN_STOP_A("fp->scopeChain is not global or active call object"); } /* * Generate LIR to access a property of a Call object. */ JS_REQUIRES_STACK RecordingStatus -TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, +TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, const Value*& vp, LIns*& ins, NameResult& nr) { Shape *shape = (Shape*) prop; JSOp op = JSOp(*cx->regs().pc); uint32 setflags = (js_CodeSpec[op].format & (JOF_SET | JOF_INCDEC | JOF_FOR)); if (setflags && !shape->writable()) RETURN_STOP("writing to a read-only property"); @@ -8921,31 +8921,31 @@ TraceRecorder::incProp(jsint incr, bool uint32 slot; LIns* v_ins; CHECK_STATUS_A(prop(obj, obj_ins, &slot, &v_ins, NULL)); if (slot == SHAPE_INVALID_SLOT) RETURN_STOP_A("incProp on invalid slot"); - Value& v = obj->getSlotRef(slot); + const Value& v = obj->getSlot(slot); Value v_after; CHECK_STATUS_A(inc(v, v_ins, v_after, incr, pre)); LIns* slots_ins = NULL; stobj_set_slot(obj, obj_ins, slot, slots_ins, v_after, v_ins); return ARECORD_CONTINUE; } JS_REQUIRES_STACK RecordingStatus TraceRecorder::incElem(jsint incr, bool pre) { Value& r = stackval(-1); Value& l = stackval(-2); - Value* vp; + const Value* vp; LIns* v_ins; LIns* addr_ins; if (!l.isPrimitive() && l.toObject().isDenseArray() && r.isInt32()) { guardDenseArray(get(&l), MISMATCH_EXIT); CHECK_STATUS(denseArrayElement(l, r, vp, v_ins, addr_ins, snapshot(BRANCH_EXIT))); if (!addr_ins) // if we read a hole, abort return RECORD_STOP; @@ -11921,17 +11921,17 @@ JS_REQUIRES_STACK AbortableRecordingStat TraceRecorder::record_JSOP_DECELEM() { return InjectStatus(incElem(-1)); } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::incName(jsint incr, bool pre) { - Value* vp; + const Value* vp; LIns* v_ins; LIns* v_ins_after; NameResult nr; CHECK_STATUS_A(name(vp, v_ins, nr)); Value v = nr.tracked ? *vp : nr.v; Value v_after; CHECK_STATUS_A(incHelper(v, v_ins, v_after, v_ins_after, incr)); @@ -13015,17 +13015,17 @@ TraceRecorder::record_JSOP_GETELEM() set(&idx, obj_ins); return ARECORD_CONTINUE; } RETURN_STOP_A("can't reach arguments object's frame"); } if (obj->isDenseArray()) { // Fast path for dense arrays accessed with a integer index. - Value* vp; + const Value* vp; LIns* addr_ins; VMSideExit* branchExit = snapshot(BRANCH_EXIT); guardDenseArray(obj_ins, branchExit); CHECK_STATUS_A(denseArrayElement(lval, idx, vp, v_ins, addr_ins, branchExit)); set(&lval, v_ins); if (call) set(&idx, obj_ins); @@ -13387,17 +13387,17 @@ JS_DEFINE_CALLINFO_2(static, BOOL, Check JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_CALLNAME() { JSObject* scopeObj = &cx->fp()->scopeChain(); LIns *funobj_ins; JSObject *funobj; if (scopeObj != globalObj) { - Value* vp; + const Value* vp; NameResult nr; CHECK_STATUS_A(scopeChainProp(scopeObj, vp, funobj_ins, nr, &scopeObj)); if (!nr.tracked) vp = &nr.v; if (!vp->isObject()) RETURN_STOP_A("callee is not an object"); funobj = &vp->toObject(); if (!funobj->isFunction()) @@ -13964,17 +13964,17 @@ TraceRecorder::record_NativeCallComplete } // We'll null pendingSpecializedNative in monitorRecording, on the next op // cycle. There must be a next op since the stack is non-empty. return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus -TraceRecorder::name(Value*& vp, LIns*& ins, NameResult& nr) +TraceRecorder::name(const Value*& vp, LIns*& ins, NameResult& nr) { JSObject* obj = &cx->fp()->scopeChain(); JSOp op = JSOp(*cx->regs().pc); if (js_CodeSpec[op].format & JOF_GNAME) obj = obj->getGlobal(); if (obj != globalObj) return scopeChainProp(obj, vp, ins, nr); @@ -14206,17 +14206,17 @@ TraceRecorder::propTail(JSObject* obj, L return RECORD_CONTINUE; } /* * When we end up with a hole, read it as undefined, and make sure to set * addr_ins to null. */ JS_REQUIRES_STACK RecordingStatus -TraceRecorder::denseArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ins, +TraceRecorder::denseArrayElement(Value& oval, Value& ival, const Value*& vp, LIns*& v_ins, LIns*& addr_ins, VMSideExit* branchExit) { JS_ASSERT(oval.isObject() && ival.isInt32()); JSObject* obj = &oval.toObject(); LIns* obj_ins = get(&oval); jsint idx = ival.toInt32(); LIns* idx_ins; @@ -14242,18 +14242,18 @@ TraceRecorder::denseArrayElement(Value& addr_ins = NULL; return RECORD_CONTINUE; } /* Guard that index is within capacity. */ guard(true, w.name(w.ltui(idx_ins, capacity_ins), "inRange"), branchExit); /* Load the value and guard on its type to unbox it. */ - vp = &obj->slots[jsuint(idx)]; - JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this. + vp = &obj->getSlot(jsuint(idx)); + JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this. addr_ins = w.name(w.getDslotAddress(obj_ins, idx_ins), "elemp"); v_ins = unbox_value(*vp, DSlotsAddress(addr_ins), branchExit); /* Don't let the hole value escape. Turn it into an undefined. */ if (vp->isMagic()) { CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT))); v_ins = w.immiUndefined(); addr_ins = NULL; @@ -14363,17 +14363,17 @@ TraceRecorder::getProp(Value& v) RETURN_STOP_A("primitive lhs"); return getProp(&v.toObject(), get(&v)); } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_NAME() { - Value* vp; + const Value* vp; LIns* v_ins; NameResult nr; CHECK_STATUS_A(name(vp, v_ins, nr)); stack(0, v_ins); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus @@ -16105,17 +16105,17 @@ TraceRecorder::record_JSOP_STOP() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_GETXPROP() { Value& l = stackval(-1); if (l.isPrimitive()) RETURN_STOP_A("primitive-this for GETXPROP?"); - Value* vp; + const Value* vp; LIns* v_ins; NameResult nr; CHECK_STATUS_A(name(vp, v_ins, nr)); stack(-1, v_ins); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus @@ -16422,17 +16422,17 @@ TraceRecorder::record_JSOP_GETGLOBAL() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_CALLGLOBAL() { uint32 slot = cx->fp()->script()->getGlobalSlot(GET_SLOTNO(cx->regs().pc)); if (!lazilyImportGlobalSlot(slot)) RETURN_STOP_A("lazy import of global slot failed"); - Value &v = globalObj->getSlotRef(slot); + const Value &v = globalObj->getSlot(slot); stack(0, get(&v)); stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_GETGNAME() {
--- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1058,17 +1058,17 @@ class TraceRecorder /* Maps interpreter stack values to the instruction generating that value. */ Tracker tracker; /* Maps interpreter stack values to the instruction writing back to the native stack. */ Tracker nativeFrameTracker; /* The start of the global object's slots we assume for the trackers. */ - Value* global_slots; + const Value* global_slots; /* The number of interpreted calls entered (and not yet left) since recording began. */ unsigned callDepth; /* The current atom table, mirroring the interpreter loop's variable of the same name. */ JSAtom** atoms; Value* consts; @@ -1216,18 +1216,18 @@ class TraceRecorder nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset, bool shouldDemoteToInt32); #ifdef DEBUG bool isValidFrameObjPtr(void *obj); #endif void assertInsideLoop(); - JS_REQUIRES_STACK void setImpl(void* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true); - JS_REQUIRES_STACK void set(Value* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true); + JS_REQUIRES_STACK void setImpl(const void* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true); + JS_REQUIRES_STACK void set(const Value* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true); JS_REQUIRES_STACK void setFrameObjPtr(void* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true); nanojit::LIns* getFromTrackerImpl(const void *p); nanojit::LIns* getFromTracker(const Value* p); JS_REQUIRES_STACK nanojit::LIns* getImpl(const void* p); JS_REQUIRES_STACK nanojit::LIns* get(const Value* p); JS_REQUIRES_STACK nanojit::LIns* getFrameObjPtr(void* p); JS_REQUIRES_STACK nanojit::LIns* attemptImport(const Value* p); @@ -1269,18 +1269,18 @@ class TraceRecorder js::Shape *shape; // shape name was resolved to }; JS_REQUIRES_STACK nanojit::LIns* scopeChain(); JS_REQUIRES_STACK nanojit::LIns* entryScopeChain() const; JS_REQUIRES_STACK nanojit::LIns* entryFrameIns() const; JS_REQUIRES_STACK StackFrame* frameIfInRange(JSObject* obj, unsigned* depthp = NULL) const; JS_REQUIRES_STACK RecordingStatus traverseScopeChain(JSObject *obj, nanojit::LIns *obj_ins, JSObject *obj2, nanojit::LIns *&obj2_ins); - JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, Value*& vp, nanojit::LIns*& ins, NameResult& nr, JSObject **scopeObjp = NULL); - JS_REQUIRES_STACK RecordingStatus callProp(JSObject* obj, JSProperty* shape, jsid id, Value*& vp, nanojit::LIns*& ins, NameResult& nr); + JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, const Value*& vp, nanojit::LIns*& ins, NameResult& nr, JSObject **scopeObjp = NULL); + JS_REQUIRES_STACK RecordingStatus callProp(JSObject* obj, JSProperty* shape, jsid id, const Value*& vp, nanojit::LIns*& ins, NameResult& nr); JS_REQUIRES_STACK nanojit::LIns* arg(unsigned n); JS_REQUIRES_STACK void arg(unsigned n, nanojit::LIns* i); JS_REQUIRES_STACK nanojit::LIns* var(unsigned n); JS_REQUIRES_STACK void var(unsigned n, nanojit::LIns* i); JS_REQUIRES_STACK nanojit::LIns* upvar(JSScript* script, JSUpvarArray* uva, uintN index, Value& v); nanojit::LIns* stackLoad(tjit::Address addr, uint8 type); JS_REQUIRES_STACK nanojit::LIns* stack(int n); @@ -1349,25 +1349,25 @@ class TraceRecorder void stobj_set_dslot(nanojit::LIns *obj_ins, unsigned slot, nanojit::LIns*& slots_ins, const Value &v, nanojit::LIns* v_ins); void stobj_set_slot(JSObject *obj, nanojit::LIns* obj_ins, unsigned slot, nanojit::LIns*& slots_ins, const Value &v, nanojit::LIns* v_ins); nanojit::LIns* unbox_slot(JSObject *obj, nanojit::LIns *obj_ins, uint32 slot, VMSideExit *exit); - JS_REQUIRES_STACK AbortableRecordingStatus name(Value*& vp, nanojit::LIns*& ins, NameResult& nr); + JS_REQUIRES_STACK AbortableRecordingStatus name(const Value*& vp, nanojit::LIns*& ins, NameResult& nr); JS_REQUIRES_STACK AbortableRecordingStatus prop(JSObject* obj, nanojit::LIns* obj_ins, uint32 *slotp, nanojit::LIns** v_insp, Value* outp); JS_REQUIRES_STACK RecordingStatus propTail(JSObject* obj, nanojit::LIns* obj_ins, JSObject* obj2, PCVal pcval, uint32 *slotp, nanojit::LIns** v_insp, Value* outp); - JS_REQUIRES_STACK RecordingStatus denseArrayElement(Value& oval, Value& idx, Value*& vp, + JS_REQUIRES_STACK RecordingStatus denseArrayElement(Value& oval, Value& idx, const Value*& vp, nanojit::LIns*& v_ins, nanojit::LIns*& addr_ins, VMSideExit* exit); JS_REQUIRES_STACK nanojit::LIns *canonicalizeNaNs(nanojit::LIns *dval_ins); JS_REQUIRES_STACK AbortableRecordingStatus typedArrayElement(Value& oval, Value& idx, Value*& vp, nanojit::LIns*& v_ins); JS_REQUIRES_STACK AbortableRecordingStatus getProp(JSObject* obj, nanojit::LIns* obj_ins); JS_REQUIRES_STACK AbortableRecordingStatus getProp(Value& v); @@ -1633,17 +1633,17 @@ class TraceRecorder bool globalSetExpected(unsigned slot) { unsigned *pi = Find(pendingGlobalSlotsToSet, slot); if (pi == pendingGlobalSlotsToSet.end()) { /* * Do slot arithmetic manually to avoid getSlotRef assertions which * do not need to be satisfied for this purpose. */ - Value *vp = globalObj->getSlots() + slot; + const Value *vp = &globalObj->getSlot(slot); /* If this global is definitely being tracked, then the write is unexpected. */ if (tracker.has(vp)) return false; /* * Otherwise, only abort if the global is not present in the * import typemap. Just deep aborting false here is not acceptable,
--- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -153,27 +153,27 @@ static inline JSBool AllocateSlots(JSContext *cx, JSObject *obj, uint32 size) { uint32 bytes = size + sizeof(Value); if (size > sizeof(Value) * ARRAYBUFFER_RESERVED_SLOTS - sizeof(Value) ) { JS_ASSERT(!obj->hasSlotsArray()); Value *tmpslots = (Value *)cx->calloc_(bytes); if (!tmpslots) return false; - obj->slots = tmpslots; + obj->setSlotsPtr(tmpslots); /* * Note that |bytes| may not be a multiple of |sizeof(Value)|, so * |capacity * sizeof(Value)| may underestimate the size by up to * |sizeof(Value) - 1| bytes. */ obj->capacity = bytes / sizeof(Value); } else { - memset(obj->slots, 0, bytes); + memset(obj->getSlotsPtr(), 0, bytes); } - *((uint32*)obj->slots) = size; + *((uint32*)obj->getSlotsPtr()) = size; return true; } static JSObject * DelegateObject(JSContext *cx, JSObject *obj) { if (!obj->getPrivate()) { JSObject *delegate = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, obj->getProto(), NULL); @@ -1317,17 +1317,17 @@ class TypedArrayTemplate JS_ASSERT(offset <= thisTypedArray->length); JS_ASSERT(len <= thisTypedArray->length - offset); NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset; if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) { JS_ASSERT(ar->getArrayLength() == len); - Value *src = ar->getDenseArrayElements(); + const Value *src = ar->getDenseArrayElements(); for (uintN i = 0; i < len; ++i) *dest++ = nativeFromValue(cx, *src++); } else { // slow path Value v; for (uintN i = 0; i < len; ++i) { @@ -1837,24 +1837,23 @@ js_IsArrayBuffer(JSObject *obj) { JS_ASSERT(obj); return obj->getClass() == &ArrayBuffer::fastClass; } JSUint32 JS_GetArrayBufferByteLength(JSObject *obj) { - return *((JSUint32*) obj->slots); + return ArrayBuffer::getByteLength(obj); } uint8 * JS_GetArrayBufferData(JSObject *obj) { - uint64 *base = ((uint64*)obj->slots) + 1; - return (uint8*) base; + return ArrayBuffer::getDataOffset(obj); } JS_FRIEND_API(JSBool) js_IsTypedArray(JSObject *obj) { JS_ASSERT(obj); Class *clasp = obj->getClass(); return clasp >= &TypedArray::fastClasses[0] &&
--- a/js/src/jstypedarrayinlines.h +++ b/js/src/jstypedarrayinlines.h @@ -43,18 +43,18 @@ #include "jsapi.h" #include "jsvalue.h" #include "jsobj.h" namespace js { inline JSUint32 ArrayBuffer::getByteLength(JSObject *obj) { - return *((JSUint32*) obj->slots); + return *((JSUint32*) obj->getSlotsPtr()); } inline uint8 * ArrayBuffer::getDataOffset(JSObject *obj) { - uint64 *base = ((uint64*)obj->slots) + 1; + uint64 *base = ((uint64*)obj->getSlotsPtr()) + 1; return (uint8*) base; } } #endif /* jstypedarrayinlines_h */
--- a/js/src/jsvalue.h +++ b/js/src/jsvalue.h @@ -847,16 +847,24 @@ ObjectOrNullValue(JSObject *obj) static JS_ALWAYS_INLINE Value PrivateValue(void *ptr) { Value v; v.setPrivate(ptr); return v; } +static JS_ALWAYS_INLINE Value +PrivateUint32Value(uint32 ui) +{ + Value v; + v.setPrivateUint32(ui); + return v; +} + static JS_ALWAYS_INLINE void ClearValueRange(Value *vec, uintN len, bool useHoles) { if (useHoles) { for (uintN i = 0; i < len; i++) vec[i].setMagic(JS_ARRAY_HOLE); } else { for (uintN i = 0; i < len; i++)
--- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -254,17 +254,17 @@ static const JSC::MacroAssembler::Regist return branchPtr(cond, Address(fun, offsetof(JSObject, clasp)), ImmPtr(&js_FunctionClass)); } /* * Finds and returns the address of a known object and slot. */ Address objSlotRef(JSObject *obj, RegisterID reg, uint32 slot) { - move(ImmPtr(&obj->slots), reg); + move(ImmPtr((char *)obj + JSObject::offsetOfSlots()), reg); loadPtr(reg, reg); return Address(reg, slot * sizeof(Value)); } /* Prepare for a call that might THROW. */ void *getFallibleCallTarget(void *fun) { #ifdef JS_CPU_ARM /* @@ -667,17 +667,17 @@ static const JSC::MacroAssembler::Regist FastArrayLoadFails fastArrayLoad(RegisterID objReg, const Int32Key &key, RegisterID typeReg, RegisterID dataReg) { JS_ASSERT(objReg != typeReg); FastArrayLoadFails fails; fails.rangeCheck = guardArrayCapacity(objReg, key); RegisterID dslotsReg = objReg; - loadPtr(Address(objReg, offsetof(JSObject, slots)), dslotsReg); + loadPtr(Address(objReg, JSObject::offsetOfSlots()), dslotsReg); // Load the slot out of the array. if (key.isConstant()) { Address slot(objReg, key.index() * sizeof(Value)); fails.holeCheck = fastArrayLoadSlot(slot, typeReg, dataReg); } else { BaseIndex slot(objReg, key.reg(), JSVAL_SCALE); fails.holeCheck = fastArrayLoadSlot(slot, typeReg, dataReg); @@ -702,17 +702,17 @@ static const JSC::MacroAssembler::Regist if (remat.inMemory()) loadPayload(remat.address(), reg); else move(remat.reg(), reg); } void loadDynamicSlot(RegisterID objReg, uint32 slot, RegisterID typeReg, RegisterID dataReg) { - loadPtr(Address(objReg, offsetof(JSObject, slots)), dataReg); + loadPtr(Address(objReg, JSObject::offsetOfSlots()), dataReg); loadValueAsComponents(Address(dataReg, slot * sizeof(Value)), typeReg, dataReg); } void loadObjProp(JSObject *obj, RegisterID objReg, const js::Shape *shape, RegisterID typeReg, RegisterID dataReg) { if (shape->isMethod())
--- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -4834,17 +4834,17 @@ mjit::Compiler::enterBlock(JSObject *obj uint32 n = js_GetEnterBlockStackDefs(cx, script, PC); INLINE_STUBCALL(stubs::EnterBlock); frame.enterBlock(n); uintN base = JSSLOT_FREE(&js_BlockClass); uintN count = OBJ_BLOCK_COUNT(cx, obj); uintN limit = base + count; for (uintN slot = base, i = 0; slot < limit; slot++, i++) { - const Value &v = obj->getSlotRef(slot); + const Value &v = obj->getSlot(slot); if (v.isBoolean() && v.toBoolean()) frame.setClosedVar(oldFrameDepth + i); } } void mjit::Compiler::leaveBlock() {
--- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -195,30 +195,30 @@ AttachSetGlobalNameStub(VMFrame &f, ic:: masm.move(ImmPtr(obj), ic->objReg); JS_ASSERT(obj->branded()); /* * Load obj->slots. If ic->objConst, then this clobbers objReg, because * ic->objReg == ic->shapeReg. */ - masm.loadPtr(Address(ic->objReg, offsetof(JSObject, slots)), ic->shapeReg); + masm.loadPtr(Address(ic->objReg, JSObject::offsetOfSlots()), ic->shapeReg); /* Test if overwriting a function-tagged slot. */ Address slot(ic->shapeReg, sizeof(Value) * shape->slot); Jump isNotObject = masm.testObject(Assembler::NotEqual, slot); /* Now, test if the object is a function object. */ masm.loadPayload(slot, ic->shapeReg); Jump isFun = masm.testFunction(Assembler::Equal, ic->shapeReg); /* Restore shapeReg to obj->slots, since we clobbered it. */ if (ic->objConst) masm.move(ImmPtr(obj), ic->objReg); - masm.loadPtr(Address(ic->objReg, offsetof(JSObject, slots)), ic->shapeReg); + masm.loadPtr(Address(ic->objReg, JSObject::offsetOfSlots()), ic->shapeReg); /* If the object test fails, shapeReg is still obj->slots. */ isNotObject.linkTo(masm.label(), &masm); DataLabel32 store = masm.storeValueWithAddressOffsetPatch(ic->vr, slot); Jump done = masm.jump(); JITScript *jit = f.jit();
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -232,17 +232,17 @@ class SetPropCompiler : public PICStubCo // // We've patched | mov dslots, [obj + DSLOTS_OFFSET] // To: | lea fslots, [obj + DSLOTS_OFFSET] // // Because the offset is wrong, it's necessary to correct it // below. // int32 diff = int32(JSObject::getFixedSlotOffset(0)) - - int32(offsetof(JSObject, slots)); + int32(JSObject::offsetOfSlots()); JS_ASSERT(diff != 0); offset = (int32(shape->slot) * sizeof(Value)) + diff; } else { offset = shape->slot * sizeof(Value); } repatcher.repatch(labels.getInlineShapeData(pic.fastPathStart, pic.shapeGuard), obj->shape()); @@ -348,17 +348,17 @@ class SetPropCompiler : public PICStubCo /* Check capacity. */ Address capacity(pic.objReg, offsetof(JSObject, capacity)); masm.load32(capacity, pic.shapeReg); Jump overCapacity = masm.branch32(Assembler::LessThanOrEqual, pic.shapeReg, Imm32(shape->slot)); if (!slowExits.append(overCapacity)) return error(); - masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.shapeReg); + masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.shapeReg); Address address(pic.shapeReg, shape->slot * sizeof(Value)); masm.storeValue(pic.u.vr, address); } uint32 newShape = obj->shape(); JS_ASSERT(newShape != initialShape); /* Write the object's new shape. */ @@ -372,17 +372,17 @@ class SetPropCompiler : public PICStubCo /* Use shapeReg to load, bitwise-or, and store flags. */ masm.load32(flags, pic.shapeReg); masm.or32(Imm32(JSObject::METHOD_BARRIER), pic.shapeReg); masm.store32(pic.shapeReg, flags); } } else if (shape->hasDefaultSetter()) { Address address(pic.objReg, JSObject::getFixedSlotOffset(shape->slot)); if (!inlineSlot) { - masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg); + masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.objReg); address = Address(pic.objReg, shape->slot * sizeof(Value)); } // If the scope is branded, or has a method barrier. It's now necessary // to guard that we're not overwriting a function-valued property. if (obj->brandedOrHasMethodBarrier()) { masm.loadTypeTag(address, pic.shapeReg); Jump skip = masm.testObject(Assembler::NotEqual, pic.shapeReg); @@ -417,17 +417,17 @@ class SetPropCompiler : public PICStubCo masm.storeValue(pic.u.vr, addr); skipOver = masm.jump(); } escapedFrame.linkTo(masm.label(), &masm); { if (shape->setterOp() == SetCallVar) slot += fun->nargs; - masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg); + masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.objReg); Address dslot(pic.objReg, (slot + JSObject::CALL_RESERVED_SLOTS) * sizeof(Value)); masm.storeValue(pic.u.vr, dslot); } pic.shapeRegHasBaseShape = false; } @@ -1413,17 +1413,17 @@ class ScopeNameCompiler : public PICStub masm.loadPayload(addr, pic.objReg); masm.loadTypeTag(addr, pic.shapeReg); skipOver = masm.jump(); } escapedFrame.linkTo(masm.label(), &masm); { - masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg); + masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.objReg); if (kind == VAR) slot += fun->nargs; Address dslot(pic.objReg, (slot + JSObject::CALL_RESERVED_SLOTS) * sizeof(Value)); /* Safe because type is loaded first. */ masm.loadValueAsComponents(dslot, pic.shapeReg, pic.objReg); } @@ -2750,17 +2750,17 @@ SetElementIC::attachHoleStub(JSContext * skipUpdate = masm.branch32(Assembler::Above, arrayLength, keyReg); masm.add32(Imm32(1), keyReg); masm.store32(keyReg, arrayLength); masm.sub32(Imm32(1), keyReg); } skipUpdate.linkTo(masm.label(), &masm); // Store the value back. - masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); + masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg); if (hasConstantKey) { Address slot(objReg, keyValue * sizeof(Value)); masm.storeValue(vr, slot); } else { BaseIndex slot(objReg, keyReg, Assembler::JSVAL_SCALE); masm.storeValue(vr, slot); }
--- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -439,26 +439,26 @@ stubs::GetElem(VMFrame &f) jsid id; if (rref.isInt32()) { int32_t i = rref.toInt32(); if (obj->isDenseArray()) { jsuint idx = jsuint(i); if (idx < obj->getArrayLength() && idx < obj->getDenseArrayCapacity()) { - copyFrom = obj->addressOfDenseArrayElement(idx); + copyFrom = &obj->getDenseArrayElement(idx); if (!copyFrom->isMagic()) goto end_getelem; } } else if (obj->isArguments()) { uint32 arg = uint32(i); ArgumentsObject *argsobj = obj->asArguments(); if (arg < argsobj->initialLength()) { - copyFrom = argsobj->addressOfElement(arg); + copyFrom = &argsobj->element(arg); if (!copyFrom->isMagic()) { if (StackFrame *afp = (StackFrame *) argsobj->getPrivate()) copyFrom = &afp->canonicalActualArg(arg); goto end_getelem; } } } if (JS_LIKELY(INT_FITS_IN_JSID(i))) @@ -1541,23 +1541,23 @@ NameIncDec(VMFrame &f, JSObject *obj, JS JSAtom *atom; JSObject *obj2; JSProperty *prop; PropertyCacheEntry *entry; JS_PROPERTY_CACHE(cx).test(cx, f.regs.pc, obj, obj2, entry, atom); if (!atom) { if (obj == obj2 && entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - Value &rref = obj->nativeGetSlotRef(slot); + const Value &rval = obj->nativeGetSlot(slot); int32_t tmp; - if (JS_LIKELY(rref.isInt32() && CanIncDecWithoutOverflow(tmp = rref.toInt32()))) { + if (JS_LIKELY(rval.isInt32() && CanIncDecWithoutOverflow(tmp = rval.toInt32()))) { int32_t inc = tmp + N; if (!POST) tmp = inc; - rref.getInt32Ref() = inc; + obj->nativeSetSlot(slot, Int32Value(inc)); f.regs.sp[0].setInt32(tmp); return true; } } atom = origAtom; } jsid id = ATOM_TO_JSID(atom);
--- a/js/src/tracejit/Writer.h +++ b/js/src/tracejit/Writer.h @@ -524,17 +524,17 @@ class Writer nj::LIns *ldiDenseArrayCapacity(nj::LIns *array) const { return name(lir->insLoad(nj::LIR_ldi, array, offsetof(JSObject, capacity), ACCSET_OBJ_CAPACITY), "capacity"); } nj::LIns *ldpObjSlots(nj::LIns *obj) const { - return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS), + return name(lir->insLoad(nj::LIR_ldp, obj, JSObject::offsetOfSlots(), ACCSET_OBJ_SLOTS), "slots"); } nj::LIns *ldiConstTypedArrayLength(nj::LIns *array) const { return name(lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY, nj::LOAD_CONST), "typedArrayLength"); }
--- a/js/src/vm/ArgumentsObject-inl.h +++ b/js/src/vm/ArgumentsObject-inl.h @@ -60,17 +60,18 @@ ArgumentsObject::initialLength() const uint32 argc = uint32(getSlot(INITIAL_LENGTH_SLOT).toInt32()) >> PACKED_BITS_COUNT; JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX); return argc; } inline void ArgumentsObject::markLengthOverridden() { - getSlotRef(INITIAL_LENGTH_SLOT).getInt32Ref() |= LENGTH_OVERRIDDEN_BIT; + uint32 v = getSlot(INITIAL_LENGTH_SLOT).toInt32() | LENGTH_OVERRIDDEN_BIT; + setSlot(INITIAL_LENGTH_SLOT, Int32Value(v)); } inline bool ArgumentsObject::hasOverriddenLength() const { const js::Value &v = getSlot(INITIAL_LENGTH_SLOT); return v.toInt32() & LENGTH_OVERRIDDEN_BIT; } @@ -91,29 +92,22 @@ ArgumentsObject::data() const inline const js::Value & ArgumentsObject::element(uint32 i) const { JS_ASSERT(i < initialLength()); return data()->slots[i]; } -inline js::Value * +inline const js::Value * ArgumentsObject::elements() const { return data()->slots; } -inline Value * -ArgumentsObject::addressOfElement(uint32 i) -{ - JS_ASSERT(i < initialLength()); - return &data()->slots[i]; -} - inline void ArgumentsObject::setElement(uint32 i, const js::Value &v) { JS_ASSERT(i < initialLength()); data()->slots[i] = v; } inline const js::Value &
--- a/js/src/vm/ArgumentsObject.h +++ b/js/src/vm/ArgumentsObject.h @@ -222,18 +222,17 @@ class ArgumentsObject : public ::JSObjec * * NB: Returning false does not indicate error! */ inline bool getElements(uint32 start, uint32 count, js::Value *vp); inline js::ArgumentsData *data() const; inline const js::Value &element(uint32 i) const; - inline js::Value *elements() const; - inline js::Value *addressOfElement(uint32 i); + inline const js::Value *elements() const; inline void setElement(uint32 i, const js::Value &v); }; /* * Non-strict arguments have a private: the function's stack frame until the * function returns, when it is replaced with null. When an arguments object * is created on-trace its private is JS_ARGUMENTS_OBJECT_ON_TRACE, and when * the trace exits its private is replaced with the stack frame or null, as
--- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -191,18 +191,18 @@ GlobalObject::isRuntimeCodeGenEnabled(JS Value &v = getSlotRef(RUNTIME_CODEGEN_ENABLED); if (v.isUndefined()) { JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx); /* * If there are callbacks, make sure that the CSP callback is installed * and that it permits runtime code generation, then cache the result. */ - v.setBoolean((!callbacks || !callbacks->contentSecurityPolicyAllows) || - callbacks->contentSecurityPolicyAllows(cx)); + v = BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) || + callbacks->contentSecurityPolicyAllows(cx)); } return !v.isFalse(); } JSFunction * GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name, uintN length) {
--- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -124,21 +124,21 @@ class GlobalObject : public ::JSObject { * prototype objects with particular internal structure (e.g. reserved * slots guaranteed to contain values of particular types) must immediately * complete the minimal initialization to make the returned object safe to * touch. */ JSObject *createBlankPrototype(JSContext *cx, js::Class *clasp); void setThrowTypeError(JSFunction *fun) { - Value &v = getSlotRef(THROWTYPEERROR); // Our bootstrapping code is currently too convoluted to correctly and // confidently assert this. // JS_ASSERT(v.isUndefined()); - v.setObject(*fun); + // JS_ASSERT(getSlot(THROWTYPEERROR).isUndefined()); + setSlot(THROWTYPEERROR, ObjectValue(*fun)); } JSObject *getThrowTypeError() const { return &getSlot(THROWTYPEERROR).toObject(); } Value getRegExpStatics() const { return getSlot(REGEXP_STATICS); @@ -152,21 +152,21 @@ class GlobalObject : public ::JSObject { bool isRuntimeCodeGenEnabled(JSContext *cx); const Value &getOriginalEval() const { return getSlot(EVAL); } void setOriginalEval(JSObject *evalobj) { - Value &v = getSlotRef(EVAL); // Our bootstrapping code is currently too convoluted to correctly and // confidently assert this. // JS_ASSERT(v.isUndefined()); - v.setObject(*evalobj); + // JS_ASSERT(getSlot(EVAL).isUndefined()); + setSlot(EVAL, ObjectValue(*evalobj)); } bool getFunctionNamespace(JSContext *cx, Value *vp); bool initStandardClasses(JSContext *cx); }; /*
--- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -595,19 +595,20 @@ ArgumentsObject::getElements(uint32 star uint32 length = initialLength(); if (start > length || start + count > length) return false; StackFrame *fp = reinterpret_cast<StackFrame *>(getPrivate()); /* If there's no stack frame for this, argument values are in elements(). */ if (!fp) { - Value *srcbeg = elements() + start; - Value *srcend = srcbeg + count; - for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src) { + const Value *srcbeg = elements() + start; + const Value *srcend = srcbeg + count; + const Value *src = srcbeg; + for (Value *dst = vp; src < srcend; ++dst, ++src) { if (src->isMagic(JS_ARGS_HOLE)) return false; *dst = *src; } return true; } /* If we're on trace, there's no canonical location for elements: fail. */