Bug 728095 - Eliminate all primitive-this machinery from JSObject and relegate it to subclasses. r=bhackett

This commit is contained in:
Jeff Walden 2012-02-16 19:10:45 -08:00
parent ed8c5375af
commit 850206480a
12 changed files with 47 additions and 60 deletions

View File

@ -157,7 +157,7 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass); JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass);
if (!booleanProto) if (!booleanProto)
return NULL; return NULL;
booleanProto->setPrimitiveThis(BooleanValue(false)); booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
JSFunction *ctor = global->createConstructor(cx, Boolean, &BooleanClass, JSFunction *ctor = global->createConstructor(cx, Boolean, &BooleanClass,
CLASS_ATOM(cx, Boolean), 1); CLASS_ATOM(cx, Boolean), 1);

View File

@ -42,13 +42,15 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/BooleanObject-inl.h"
namespace js { namespace js {
inline bool inline bool
BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp) BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp)
{ {
if (obj.isBoolean()) { if (obj.isBoolean()) {
*vp = obj.getPrimitiveThis(); *vp = BooleanValue(obj.asBoolean().unbox());
return true; return true;
} }

View File

@ -42,7 +42,10 @@
#include "jstypedarrayinlines.h" #include "jstypedarrayinlines.h"
#include "vm/BooleanObject-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/RegExpObject-inl.h" #include "vm/RegExpObject-inl.h"
#include "vm/StringObject-inl.h"
using namespace js; using namespace js;
@ -536,12 +539,12 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
} else if (js_IsArrayBuffer(obj)) { } else if (js_IsArrayBuffer(obj)) {
return writeArrayBuffer(obj); return writeArrayBuffer(obj);
} else if (obj->isBoolean()) { } else if (obj->isBoolean()) {
return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->getPrimitiveThis().toBoolean()); return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->asBoolean().unbox());
} else if (obj->isNumber()) { } else if (obj->isNumber()) {
return out.writePair(SCTAG_NUMBER_OBJECT, 0) && return out.writePair(SCTAG_NUMBER_OBJECT, 0) &&
out.writeDouble(obj->getPrimitiveThis().toNumber()); out.writeDouble(obj->asNumber().unbox());
} else if (obj->isString()) { } else if (obj->isString()) {
return writeString(SCTAG_STRING_OBJECT, obj->getPrimitiveThis().toString()); return writeString(SCTAG_STRING_OBJECT, obj->asString().unbox());
} }
if (callbacks && callbacks->write) if (callbacks && callbacks->write)

View File

@ -490,10 +490,9 @@ Number(JSContext *cx, uintN argc, Value *vp)
if (!isConstructing) if (!isConstructing)
return true; return true;
JSObject *obj = NewBuiltinClassInstance(cx, &NumberClass); JSObject *obj = NumberObject::create(cx, vp[0].toNumber());
if (!obj) if (!obj)
return false; return false;
obj->setPrimitiveThis(vp[0]);
vp->setObject(*obj); vp->setObject(*obj);
return true; return true;
} }

View File

@ -5862,7 +5862,7 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
&StringClass, &StringClass,
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom), ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
js_str_toString)) { js_str_toString)) {
*vp = obj->getPrimitiveThis(); *vp = StringValue(obj->asString().unbox());
return true; return true;
} }
@ -5885,7 +5885,9 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
ClassMethodIsNative(cx, obj, &NumberClass, ClassMethodIsNative(cx, obj, &NumberClass,
ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom), ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom),
js_num_valueOf))) { js_num_valueOf))) {
*vp = obj->getPrimitiveThis(); *vp = obj->isString()
? StringValue(obj->asString().unbox())
: NumberValue(obj->asNumber().unbox());
return true; return true;
} }

View File

@ -998,22 +998,6 @@ struct JSObject : js::gc::Cell
bool isSealed(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, SEAL, resultp); } bool isSealed(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, SEAL, resultp); }
bool isFrozen(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, FREEZE, resultp); } bool isFrozen(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, FREEZE, resultp); }
/*
* Primitive-specific getters and setters.
*/
private:
static const uint32_t JSSLOT_PRIMITIVE_THIS = 0;
public:
inline const js::Value &getPrimitiveThis() const;
inline void setPrimitiveThis(const js::Value &pthis);
static size_t getPrimitiveThisOffset() {
/* All primitive objects have their value in a fixed slot. */
return getFixedSlotOffset(JSSLOT_PRIMITIVE_THIS);
}
/* Accessors for elements. */ /* Accessors for elements. */
js::ObjectElements *getElementsHeader() const { js::ObjectElements *getElementsHeader() const {

View File

@ -65,8 +65,12 @@
#include "gc/Barrier.h" #include "gc/Barrier.h"
#include "js/TemplateLib.h" #include "js/TemplateLib.h"
#include "vm/BooleanObject.h"
#include "vm/GlobalObject.h" #include "vm/GlobalObject.h"
#include "vm/NumberObject.h"
#include "vm/RegExpStatics.h" #include "vm/RegExpStatics.h"
#include "vm/StringObject.h"
#include "jsatominlines.h" #include "jsatominlines.h"
#include "jsfuninlines.h" #include "jsfuninlines.h"
@ -436,20 +440,6 @@ JSObject::setReservedSlot(uintN index, const js::Value &v)
setSlot(index, v); setSlot(index, v);
} }
inline const js::Value &
JSObject::getPrimitiveThis() const
{
JS_ASSERT(isPrimitive());
return getFixedSlot(JSSLOT_PRIMITIVE_THIS);
}
inline void
JSObject::setPrimitiveThis(const js::Value &pthis)
{
JS_ASSERT(isPrimitive());
setFixedSlot(JSSLOT_PRIMITIVE_THIS, pthis);
}
inline bool inline bool
JSObject::hasContiguousSlots(size_t start, size_t count) const JSObject::hasContiguousSlots(size_t start, size_t count) const
{ {
@ -1916,6 +1906,7 @@ class PrimitiveBehavior<JSString *> {
public: public:
static inline bool isType(const Value &v) { return v.isString(); } static inline bool isType(const Value &v) { return v.isString(); }
static inline JSString *extract(const Value &v) { return v.toString(); } static inline JSString *extract(const Value &v) { return v.toString(); }
static inline JSString *extract(JSObject &obj) { return obj.asString().unbox(); }
static inline Class *getClass() { return &StringClass; } static inline Class *getClass() { return &StringClass; }
}; };
@ -1924,6 +1915,7 @@ class PrimitiveBehavior<bool> {
public: public:
static inline bool isType(const Value &v) { return v.isBoolean(); } static inline bool isType(const Value &v) { return v.isBoolean(); }
static inline bool extract(const Value &v) { return v.toBoolean(); } static inline bool extract(const Value &v) { return v.toBoolean(); }
static inline bool extract(JSObject &obj) { return obj.asBoolean().unbox(); }
static inline Class *getClass() { return &BooleanClass; } static inline Class *getClass() { return &BooleanClass; }
}; };
@ -1932,6 +1924,7 @@ class PrimitiveBehavior<double> {
public: public:
static inline bool isType(const Value &v) { return v.isNumber(); } static inline bool isType(const Value &v) { return v.isNumber(); }
static inline double extract(const Value &v) { return v.toNumber(); } static inline double extract(const Value &v) { return v.toNumber(); }
static inline double extract(JSObject &obj) { return obj.asNumber().unbox(); }
static inline Class *getClass() { return &NumberClass; } static inline Class *getClass() { return &NumberClass; }
}; };
@ -1968,7 +1961,7 @@ BoxedPrimitiveMethodGuard(JSContext *cx, CallArgs args, Native native, T *v, boo
if (!NonGenericMethodGuard(cx, args, native, Behavior::getClass(), ok)) if (!NonGenericMethodGuard(cx, args, native, Behavior::getClass(), ok))
return false; return false;
*v = Behavior::extract(thisv.toObject().getPrimitiveThis()); *v = Behavior::extract(thisv.toObject());
return true; return true;
} }

View File

@ -399,7 +399,7 @@ static const uintN STRING_ELEMENT_ATTRS = JSPROP_ENUMERATE | JSPROP_READONLY | J
static JSBool static JSBool
str_enumerate(JSContext *cx, JSObject *obj) str_enumerate(JSContext *cx, JSObject *obj)
{ {
JSString *str = obj->getPrimitiveThis().toString(); JSString *str = obj->asString().unbox();
for (size_t i = 0, length = str->length(); i < length; i++) { for (size_t i = 0, length = str->length(); i < length; i++) {
JSString *str1 = js_NewDependentString(cx, str, i, 1); JSString *str1 = js_NewDependentString(cx, str, i, 1);
if (!str1) if (!str1)
@ -421,7 +421,7 @@ str_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (!JSID_IS_INT(id)) if (!JSID_IS_INT(id))
return JS_TRUE; return JS_TRUE;
JSString *str = obj->getPrimitiveThis().toString(); JSString *str = obj->asString().unbox();
jsint slot = JSID_TO_INT(id); jsint slot = JSID_TO_INT(id);
if ((size_t)slot < str->length()) { if ((size_t)slot < str->length()) {
@ -472,8 +472,9 @@ ThisToStringForStringProto(JSContext *cx, CallReceiver call)
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom), ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
js_str_toString)) js_str_toString))
{ {
call.thisv() = obj->getPrimitiveThis(); JSString *str = obj->asString().unbox();
return call.thisv().toString(); call.thisv().setString(str);
return str;
} }
} else if (call.thisv().isNullOrUndefined()) { } else if (call.thisv().isNullOrUndefined()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,

View File

@ -53,6 +53,7 @@
#include "jsautooplen.h" #include "jsautooplen.h"
#include "vm/ScopeObject-inl.h" #include "vm/ScopeObject-inl.h"
#include "vm/StringObject-inl.h"
#if defined JS_POLYIC #if defined JS_POLYIC
@ -944,7 +945,7 @@ class GetPropCompiler : public PICStubCompiler
Jump notStringObj = masm.guardShape(pic.objReg, obj); Jump notStringObj = masm.guardShape(pic.objReg, obj);
masm.loadPayload(Address(pic.objReg, JSObject::getPrimitiveThisOffset()), pic.objReg); masm.loadPayload(Address(pic.objReg, StringObject::getPrimitiveValueOffset()), pic.objReg);
masm.loadPtr(Address(pic.objReg, JSString::offsetOfLengthAndFlags()), pic.objReg); masm.loadPtr(Address(pic.objReg, JSString::offsetOfLengthAndFlags()), pic.objReg);
masm.urshift32(Imm32(JSString::LENGTH_SHIFT), pic.objReg); masm.urshift32(Imm32(JSString::LENGTH_SHIFT), pic.objReg);
masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg); masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg);
@ -1885,7 +1886,7 @@ GetPropMaybeCached(VMFrame &f, ic::PICInfo *pic, bool cached)
LookupStatus status = cc.generateStringObjLengthStub(); LookupStatus status = cc.generateStringObjLengthStub();
if (status == Lookup_Error) if (status == Lookup_Error)
THROW(); THROW();
JSString *str = obj->getPrimitiveThis().toString(); JSString *str = obj->asString().unbox();
f.regs.sp[-1].setInt32(str->length()); f.regs.sp[-1].setInt32(str->length());
} }
return; return;

View File

@ -67,14 +67,13 @@ class BooleanObject : public JSObject
*/ */
static inline BooleanObject *createWithProto(JSContext *cx, bool b, JSObject &proto); static inline BooleanObject *createWithProto(JSContext *cx, bool b, JSObject &proto);
Value unbox() const { bool unbox() const {
JS_ASSERT(getSlot(PRIMITIVE_VALUE_SLOT).isBoolean()); return getFixedSlot(PRIMITIVE_VALUE_SLOT).toBoolean();
return getSlot(PRIMITIVE_VALUE_SLOT);
} }
private: private:
inline void setPrimitiveValue(bool b) { inline void setPrimitiveValue(bool b) {
setSlot(PRIMITIVE_VALUE_SLOT, BooleanValue(b)); setFixedSlot(PRIMITIVE_VALUE_SLOT, BooleanValue(b));
} }
/* For access to init, as Boolean.prototype is special. */ /* For access to init, as Boolean.prototype is special. */

View File

@ -67,14 +67,13 @@ class NumberObject : public JSObject
*/ */
static inline NumberObject *createWithProto(JSContext *cx, jsdouble d, JSObject &proto); static inline NumberObject *createWithProto(JSContext *cx, jsdouble d, JSObject &proto);
Value unbox() const { double unbox() const {
JS_ASSERT(getSlot(PRIMITIVE_VALUE_SLOT).isNumber()); return getFixedSlot(PRIMITIVE_VALUE_SLOT).toNumber();
return getSlot(PRIMITIVE_VALUE_SLOT);
} }
private: private:
inline void setPrimitiveValue(jsdouble d) { inline void setPrimitiveValue(jsdouble d) {
setSlot(PRIMITIVE_VALUE_SLOT, NumberValue(d)); setFixedSlot(PRIMITIVE_VALUE_SLOT, NumberValue(d));
} }
/* For access to init, as Number.prototype is special. */ /* For access to init, as Number.prototype is special. */

View File

@ -50,7 +50,7 @@ namespace js {
class StringObject : public JSObject class StringObject : public JSObject
{ {
static const uintN PRIMITIVE_THIS_SLOT = 0; static const uintN PRIMITIVE_VALUE_SLOT = 0;
static const uintN LENGTH_SLOT = 1; static const uintN LENGTH_SLOT = 1;
public: public:
@ -69,20 +69,24 @@ class StringObject : public JSObject
static inline StringObject *createWithProto(JSContext *cx, JSString *str, JSObject &proto); static inline StringObject *createWithProto(JSContext *cx, JSString *str, JSObject &proto);
JSString *unbox() const { JSString *unbox() const {
return getSlot(PRIMITIVE_THIS_SLOT).toString(); return getFixedSlot(PRIMITIVE_VALUE_SLOT).toString();
} }
inline size_t length() const { inline size_t length() const {
return size_t(getSlot(LENGTH_SLOT).toInt32()); return size_t(getFixedSlot(LENGTH_SLOT).toInt32());
}
static size_t getPrimitiveValueOffset() {
return getFixedSlotOffset(PRIMITIVE_VALUE_SLOT);
} }
private: private:
inline bool init(JSContext *cx, JSString *str); inline bool init(JSContext *cx, JSString *str);
void setStringThis(JSString *str) { void setStringThis(JSString *str) {
JS_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined()); JS_ASSERT(getReservedSlot(PRIMITIVE_VALUE_SLOT).isUndefined());
setSlot(PRIMITIVE_THIS_SLOT, StringValue(str)); setFixedSlot(PRIMITIVE_VALUE_SLOT, StringValue(str));
setSlot(LENGTH_SLOT, Int32Value(int32_t(str->length()))); setFixedSlot(LENGTH_SLOT, Int32Value(int32_t(str->length())));
} }
/* For access to init, as String.prototype is special. */ /* For access to init, as String.prototype is special. */