--- 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. */