зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1449051 - Move JS::Value::layout's members into JS::Value, make JS::Value a union, and apply correct code style to the union fields. r=sfink
--HG-- extra : rebase_source : 6a13e636b90c06419b89942b2848be92b21c4020
This commit is contained in:
Родитель
e5512cfdf4
Коммит
ca78e29895
|
@ -41,7 +41,7 @@ namespace JS {
|
|||
typedef unsigned char Latin1Char;
|
||||
|
||||
class Symbol;
|
||||
class Value;
|
||||
union Value;
|
||||
class Realm;
|
||||
struct Runtime;
|
||||
struct Zone;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "js/RootingAPI.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
namespace JS { class Value; }
|
||||
namespace JS { union Value; }
|
||||
|
||||
/* JS::Value can store a full int32_t. */
|
||||
#define JSVAL_INT_BITS 32
|
||||
|
@ -316,8 +316,81 @@ CanonicalizeNaN(double d)
|
|||
* conditional move (not speculated) to zero the payload register if the type
|
||||
* doesn't match.
|
||||
*/
|
||||
class MOZ_NON_PARAM alignas(8) Value
|
||||
union MOZ_NON_PARAM alignas(8) Value
|
||||
{
|
||||
#if !defined(_MSC_VER) && !defined(__sparc)
|
||||
// Don't expose Value's fields unless we have to: MSVC (bug 689101) and SPARC
|
||||
// (bug 737344) require Value be POD to pass it by value and not in memory.
|
||||
// More precisely, we don't want Value return values compiled as outparams.
|
||||
private:
|
||||
#endif
|
||||
|
||||
uint64_t asBits_;
|
||||
double asDouble_;
|
||||
|
||||
#if defined(JS_PUNBOX64) && !defined(_WIN64)
|
||||
// MSVC doesn't pack these correctly :-(
|
||||
struct {
|
||||
# if MOZ_LITTLE_ENDIAN
|
||||
uint64_t payload47_ : 47;
|
||||
JSValueTag tag_ : 17;
|
||||
# else
|
||||
JSValueTag tag_ : 17;
|
||||
uint64_t payload47_ : 47;
|
||||
# endif // MOZ_LITTLE_ENDIAN
|
||||
} debugView_;
|
||||
#endif // defined(JS_PUNBOX64) && !defined(_WIN64)
|
||||
|
||||
struct {
|
||||
#if defined(JS_PUNBOX64)
|
||||
# if MOZ_BIG_ENDIAN
|
||||
uint32_t : 32; // padding
|
||||
# endif // MOZ_BIG_ENDIAN
|
||||
union {
|
||||
int32_t i32_;
|
||||
uint32_t u32_;
|
||||
JSWhyMagic why_;
|
||||
} payload_;
|
||||
#elif defined(JS_NUNBOX32)
|
||||
# if MOZ_BIG_ENDIAN
|
||||
JSValueTag tag_;
|
||||
# endif // MOZ_BIG_ENDIAN
|
||||
union {
|
||||
int32_t i32_;
|
||||
uint32_t u32_;
|
||||
uint32_t boo_; // Don't use |bool| -- it must be four bytes.
|
||||
JSString* str_;
|
||||
JS::Symbol* sym_;
|
||||
JSObject* obj_;
|
||||
js::gc::Cell* cell_;
|
||||
void* ptr_;
|
||||
JSWhyMagic why_;
|
||||
} payload_;
|
||||
# if MOZ_LITTLE_ENDIAN
|
||||
JSValueTag tag_;
|
||||
# endif // MOZ_LITTLE_ENDIAN
|
||||
#endif // defined(JS_PUNBOX64)
|
||||
} s_;
|
||||
|
||||
public:
|
||||
// The default constructor leaves Value uninitialized. Adding a default
|
||||
// constructor prevents Value from being stored in a union.
|
||||
Value() = default;
|
||||
Value(const Value& v) = default;
|
||||
|
||||
private:
|
||||
explicit constexpr Value(uint64_t asBits) : asBits_(asBits) {}
|
||||
explicit constexpr Value(double d) : asDouble_(d) {}
|
||||
|
||||
static_assert(sizeof(JSValueType) == 1,
|
||||
"type bits must fit in a single byte");
|
||||
static_assert(sizeof(JSValueTag) == 4,
|
||||
"32-bit Value's tag_ must have size 4 to complement the "
|
||||
"payload union's size 4");
|
||||
static_assert(sizeof(JSWhyMagic) <= 4,
|
||||
"32-bit Value's JSWhyMagic payload field must not inflate "
|
||||
"the payload beyond 4 bytes");
|
||||
|
||||
public:
|
||||
#if defined(JS_NUNBOX32)
|
||||
using PayloadType = uint32_t;
|
||||
|
@ -325,13 +398,38 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
using PayloadType = uint64_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* N.B. the default constructor leaves Value unitialized. Adding a default
|
||||
* constructor prevents Value from being stored in a union.
|
||||
*/
|
||||
Value() = default;
|
||||
Value(const Value& v) = default;
|
||||
static constexpr uint64_t
|
||||
bitsFromTagAndPayload(JSValueTag tag, PayloadType payload)
|
||||
{
|
||||
#if defined(JS_NUNBOX32)
|
||||
return (uint64_t(uint32_t(tag)) << 32) | payload;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return (uint64_t(uint32_t(tag)) << JSVAL_TAG_SHIFT) | payload;
|
||||
#endif
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromTagAndPayload(JSValueTag tag, PayloadType payload)
|
||||
{
|
||||
return fromRawBits(bitsFromTagAndPayload(tag, payload));
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromRawBits(uint64_t asBits) {
|
||||
return Value(asBits);
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromInt32(int32_t i) {
|
||||
return fromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromDouble(double d) {
|
||||
return Value(d);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns false if creating a NumberValue containing the given type would
|
||||
* be lossy, true otherwise.
|
||||
|
@ -344,26 +442,26 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
/*** Mutators ***/
|
||||
|
||||
void setNull() {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_NULL, 0);
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_NULL, 0);
|
||||
}
|
||||
|
||||
void setUndefined() {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
|
||||
}
|
||||
|
||||
void setInt32(int32_t i) {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
|
||||
}
|
||||
|
||||
int32_t& getInt32Ref() {
|
||||
MOZ_ASSERT(isInt32());
|
||||
return data.s.payload.i32;
|
||||
return s_.payload_.i32_;
|
||||
}
|
||||
|
||||
void setDouble(double d) {
|
||||
// Don't assign to data.asDouble to fix a miscompilation with
|
||||
// GCC 5.2.1 and 5.3.1. See bug 1312488.
|
||||
data = layout(d);
|
||||
// Don't assign to asDouble_ to fix a miscompilation with GCC 5.2.1 and
|
||||
// 5.3.1. See bug 1312488.
|
||||
*this = Value(d);
|
||||
MOZ_ASSERT(isDouble());
|
||||
}
|
||||
|
||||
|
@ -373,17 +471,17 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
|
||||
double& getDoubleRef() {
|
||||
MOZ_ASSERT(isDouble());
|
||||
return data.asDouble;
|
||||
return asDouble_;
|
||||
}
|
||||
|
||||
void setString(JSString* str) {
|
||||
MOZ_ASSERT(js::gc::IsCellPointerValid(str));
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
|
||||
}
|
||||
|
||||
void setSymbol(JS::Symbol* sym) {
|
||||
MOZ_ASSERT(js::gc::IsCellPointerValid(sym));
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
|
||||
}
|
||||
|
||||
void setObject(JSObject& obj) {
|
||||
|
@ -413,22 +511,22 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
|
||||
private:
|
||||
void setObjectNoCheck(JSObject* obj) {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
|
||||
}
|
||||
|
||||
friend inline Value js::PoisonedObjectValue(uintptr_t poison);
|
||||
|
||||
public:
|
||||
void setBoolean(bool b) {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
|
||||
}
|
||||
|
||||
void setMagic(JSWhyMagic why) {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
|
||||
}
|
||||
|
||||
void setMagicUint32(uint32_t payload) {
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
|
||||
}
|
||||
|
||||
bool setNumber(uint32_t ui) {
|
||||
|
@ -460,17 +558,17 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
}
|
||||
|
||||
void swap(Value& rhs) {
|
||||
uint64_t tmp = rhs.data.asBits;
|
||||
rhs.data.asBits = data.asBits;
|
||||
data.asBits = tmp;
|
||||
uint64_t tmp = rhs.asBits_;
|
||||
rhs.asBits_ = asBits_;
|
||||
asBits_ = tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
JSValueTag toTag() const {
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.tag;
|
||||
return s_.tag_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return JSValueTag(data.asBits >> JSVAL_TAG_SHIFT);
|
||||
return JSValueTag(asBits_ >> JSVAL_TAG_SHIFT);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -478,15 +576,15 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
/*** JIT-only interfaces to interact with and create raw Values ***/
|
||||
#if defined(JS_NUNBOX32)
|
||||
PayloadType toNunboxPayload() const {
|
||||
return static_cast<PayloadType>(data.s.payload.i32);
|
||||
return static_cast<PayloadType>(s_.payload_.i32_);
|
||||
}
|
||||
|
||||
JSValueTag toNunboxTag() const {
|
||||
return data.s.tag;
|
||||
return s_.tag_;
|
||||
}
|
||||
#elif defined(JS_PUNBOX64)
|
||||
const void* bitsAsPunboxPointer() const {
|
||||
return reinterpret_cast<void*>(data.asBits);
|
||||
return reinterpret_cast<void*>(asBits_);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -503,7 +601,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
#if defined(JS_NUNBOX32)
|
||||
return toTag() == JSVAL_TAG_UNDEFINED;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return data.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
|
||||
return asBits_ == JSVAL_SHIFTED_TAG_UNDEFINED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -511,7 +609,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
#if defined(JS_NUNBOX32)
|
||||
return toTag() == JSVAL_TAG_NULL;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return data.asBits == JSVAL_SHIFTED_TAG_NULL;
|
||||
return asBits_ == JSVAL_SHIFTED_TAG_NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -524,14 +622,14 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
}
|
||||
|
||||
bool isInt32(int32_t i32) const {
|
||||
return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
|
||||
return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
|
||||
}
|
||||
|
||||
bool isDouble() const {
|
||||
#if defined(JS_NUNBOX32)
|
||||
return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return (data.asBits | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
|
||||
return (asBits_ | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -540,7 +638,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR);
|
||||
return uint32_t(toTag()) <= uint32_t(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
|
||||
return asBits_ < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -556,8 +654,8 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
#if defined(JS_NUNBOX32)
|
||||
return toTag() == JSVAL_TAG_OBJECT;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
MOZ_ASSERT((data.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
|
||||
return data.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
|
||||
MOZ_ASSERT((asBits_ >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
|
||||
return asBits_ >= JSVAL_SHIFTED_TAG_OBJECT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -565,7 +663,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
#if defined(JS_NUNBOX32)
|
||||
return uint32_t(toTag()) < uint32_t(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
|
||||
return asBits_ < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -578,7 +676,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
/* gcc sometimes generates signed < without explicit casts. */
|
||||
return uint32_t(toTag()) >= uint32_t(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
|
||||
return asBits_ >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -587,11 +685,11 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
}
|
||||
|
||||
bool isTrue() const {
|
||||
return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(true));
|
||||
return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(true));
|
||||
}
|
||||
|
||||
bool isFalse() const {
|
||||
return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(false));
|
||||
return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(false));
|
||||
}
|
||||
|
||||
bool isMagic() const {
|
||||
|
@ -599,7 +697,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
}
|
||||
|
||||
bool isMagic(JSWhyMagic why) const {
|
||||
MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
|
||||
MOZ_ASSERT_IF(isMagic(), s_.payload_.why_ == why);
|
||||
return isMagic();
|
||||
}
|
||||
|
||||
|
@ -618,22 +716,22 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
|
||||
JSWhyMagic whyMagic() const {
|
||||
MOZ_ASSERT(isMagic());
|
||||
return data.s.payload.why;
|
||||
return s_.payload_.why_;
|
||||
}
|
||||
|
||||
uint32_t magicUint32() const {
|
||||
MOZ_ASSERT(isMagic());
|
||||
return data.s.payload.u32;
|
||||
return s_.payload_.u32_;
|
||||
}
|
||||
|
||||
/*** Comparison ***/
|
||||
|
||||
bool operator==(const Value& rhs) const {
|
||||
return data.asBits == rhs.data.asBits;
|
||||
return asBits_ == rhs.asBits_;
|
||||
}
|
||||
|
||||
bool operator!=(const Value& rhs) const {
|
||||
return data.asBits != rhs.data.asBits;
|
||||
return asBits_ != rhs.asBits_;
|
||||
}
|
||||
|
||||
friend inline bool SameType(const Value& lhs, const Value& rhs);
|
||||
|
@ -643,15 +741,15 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
int32_t toInt32() const {
|
||||
MOZ_ASSERT(isInt32());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.i32;
|
||||
return s_.payload_.i32_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return int32_t(data.asBits);
|
||||
return int32_t(asBits_);
|
||||
#endif
|
||||
}
|
||||
|
||||
double toDouble() const {
|
||||
MOZ_ASSERT(isDouble());
|
||||
return data.asDouble;
|
||||
return asDouble_;
|
||||
}
|
||||
|
||||
double toNumber() const {
|
||||
|
@ -662,27 +760,27 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
JSString* toString() const {
|
||||
MOZ_ASSERT(isString());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.str;
|
||||
return s_.payload_.str_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return reinterpret_cast<JSString*>(data.asBits ^ JSVAL_SHIFTED_TAG_STRING);
|
||||
return reinterpret_cast<JSString*>(asBits_ ^ JSVAL_SHIFTED_TAG_STRING);
|
||||
#endif
|
||||
}
|
||||
|
||||
JS::Symbol* toSymbol() const {
|
||||
MOZ_ASSERT(isSymbol());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.sym;
|
||||
return s_.payload_.sym_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return reinterpret_cast<JS::Symbol*>(data.asBits ^ JSVAL_SHIFTED_TAG_SYMBOL);
|
||||
return reinterpret_cast<JS::Symbol*>(asBits_ ^ JSVAL_SHIFTED_TAG_SYMBOL);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSObject& toObject() const {
|
||||
MOZ_ASSERT(isObject());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return *data.s.payload.obj;
|
||||
return *s_.payload_.obj_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
uint64_t ptrBits = data.asBits ^ JSVAL_SHIFTED_TAG_OBJECT;
|
||||
uint64_t ptrBits = asBits_ ^ JSVAL_SHIFTED_TAG_OBJECT;
|
||||
MOZ_ASSERT(ptrBits);
|
||||
MOZ_ASSERT((ptrBits & 0x7) == 0);
|
||||
return *reinterpret_cast<JSObject*>(ptrBits);
|
||||
|
@ -692,11 +790,11 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
JSObject* toObjectOrNull() const {
|
||||
MOZ_ASSERT(isObjectOrNull());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.obj;
|
||||
return s_.payload_.obj_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
// Note: the 'Spectre mitigations' comment at the top of this class
|
||||
// explains why we use XOR here and in other to* methods.
|
||||
uint64_t ptrBits = (data.asBits ^ JSVAL_SHIFTED_TAG_OBJECT) & ~JSVAL_OBJECT_OR_NULL_BIT;
|
||||
uint64_t ptrBits = (asBits_ ^ JSVAL_SHIFTED_TAG_OBJECT) & ~JSVAL_OBJECT_OR_NULL_BIT;
|
||||
MOZ_ASSERT((ptrBits & 0x7) == 0);
|
||||
return reinterpret_cast<JSObject*>(ptrBits);
|
||||
#endif
|
||||
|
@ -705,9 +803,9 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
js::gc::Cell* toGCThing() const {
|
||||
MOZ_ASSERT(isGCThing());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.cell;
|
||||
return s_.payload_.cell_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
uint64_t ptrBits = data.asBits & JSVAL_PAYLOAD_MASK_GCTHING;
|
||||
uint64_t ptrBits = asBits_ & JSVAL_PAYLOAD_MASK_GCTHING;
|
||||
MOZ_ASSERT((ptrBits & 0x7) == 0);
|
||||
return reinterpret_cast<js::gc::Cell*>(ptrBits);
|
||||
#endif
|
||||
|
@ -720,19 +818,19 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
bool toBoolean() const {
|
||||
MOZ_ASSERT(isBoolean());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return bool(data.s.payload.boo);
|
||||
return bool(s_.payload_.boo_);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return bool(int32_t(data.asBits));
|
||||
return bool(int32_t(asBits_));
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t payloadAsRawUint32() const {
|
||||
MOZ_ASSERT(!isDouble());
|
||||
return data.s.payload.u32;
|
||||
return s_.payload_.u32_;
|
||||
}
|
||||
|
||||
uint64_t asRawBits() const {
|
||||
return data.asBits;
|
||||
return asBits_;
|
||||
}
|
||||
|
||||
JSValueType extractNonDoubleType() const {
|
||||
|
@ -753,10 +851,10 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
void setPrivate(void* ptr) {
|
||||
MOZ_ASSERT((uintptr_t(ptr) & 1) == 0);
|
||||
#if defined(JS_NUNBOX32)
|
||||
data.s.tag = JSValueTag(0);
|
||||
data.s.payload.ptr = ptr;
|
||||
s_.tag_ = JSValueTag(0);
|
||||
s_.payload_.ptr_ = ptr;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
data.asBits = uintptr_t(ptr) >> 1;
|
||||
asBits_ = uintptr_t(ptr) >> 1;
|
||||
#endif
|
||||
MOZ_ASSERT(isDouble());
|
||||
}
|
||||
|
@ -764,10 +862,10 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
void* toPrivate() const {
|
||||
MOZ_ASSERT(isDouble());
|
||||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.ptr;
|
||||
return s_.payload_.ptr_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
MOZ_ASSERT((data.asBits & 0x8000000000000000ULL) == 0);
|
||||
return reinterpret_cast<void*>(data.asBits << 1);
|
||||
MOZ_ASSERT((asBits_ & 0x8000000000000000ULL) == 0);
|
||||
return reinterpret_cast<void*>(asBits_ << 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -805,117 +903,12 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
// It throws syntax error.
|
||||
MOZ_ASSERT((((uintptr_t)cell) >> JSVAL_TAG_SHIFT) == 0);
|
||||
#endif
|
||||
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell));
|
||||
asBits_ = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell));
|
||||
}
|
||||
|
||||
bool isPrivateGCThing() const {
|
||||
return toTag() == JSVAL_TAG_PRIVATE_GCTHING;
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__sparc)
|
||||
// Value must be POD so that MSVC will pass it by value and not in memory
|
||||
// (bug 689101); the same is true for SPARC as well (bug 737344). More
|
||||
// precisely, we don't want Value return values compiled as out params.
|
||||
private:
|
||||
#endif
|
||||
|
||||
union layout {
|
||||
uint64_t asBits;
|
||||
double asDouble;
|
||||
|
||||
#if defined(JS_PUNBOX64) && !defined(_WIN64)
|
||||
/* MSVC does not pack these correctly :-( */
|
||||
struct {
|
||||
# if MOZ_LITTLE_ENDIAN
|
||||
uint64_t payload47 : 47;
|
||||
JSValueTag tag : 17;
|
||||
# else
|
||||
JSValueTag tag : 17;
|
||||
uint64_t payload47 : 47;
|
||||
# endif // MOZ_LITTLE_ENDIAN
|
||||
} debugView;
|
||||
#endif // defined(JS_PUNBOX64) && !defined(_WIN64)
|
||||
|
||||
struct {
|
||||
#if defined(JS_PUNBOX64)
|
||||
# if MOZ_BIG_ENDIAN
|
||||
uint32_t padding;
|
||||
# endif // MOZ_BIG_ENDIAN
|
||||
union {
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
JSWhyMagic why;
|
||||
} payload;
|
||||
#else
|
||||
# if MOZ_BIG_ENDIAN
|
||||
JSValueTag tag;
|
||||
# endif // MOZ_BIG_ENDIAN
|
||||
union {
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
uint32_t boo; // Don't use |bool| -- it must be four bytes.
|
||||
JSString* str;
|
||||
JS::Symbol* sym;
|
||||
JSObject* obj;
|
||||
js::gc::Cell* cell;
|
||||
void* ptr;
|
||||
JSWhyMagic why;
|
||||
} payload;
|
||||
# if MOZ_LITTLE_ENDIAN
|
||||
JSValueTag tag;
|
||||
# endif // MOZ_LITTLE_ENDIAN
|
||||
#endif // defined(JS_PUNBOX64)
|
||||
} s;
|
||||
|
||||
layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
|
||||
explicit constexpr layout(uint64_t bits) : asBits(bits) {}
|
||||
explicit constexpr layout(double d) : asDouble(d) {}
|
||||
} data;
|
||||
|
||||
private:
|
||||
explicit constexpr Value(uint64_t asBits) : data(asBits) {}
|
||||
explicit constexpr Value(double d) : data(d) {}
|
||||
|
||||
void staticAssertions() {
|
||||
JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
|
||||
JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
|
||||
JS_STATIC_ASSERT(sizeof(Value) == 8);
|
||||
}
|
||||
|
||||
friend constexpr Value JS::UndefinedValue();
|
||||
|
||||
public:
|
||||
static constexpr uint64_t
|
||||
bitsFromTagAndPayload(JSValueTag tag, PayloadType payload)
|
||||
{
|
||||
#if defined(JS_NUNBOX32)
|
||||
return (uint64_t(uint32_t(tag)) << 32) | payload;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return (uint64_t(uint32_t(tag)) << JSVAL_TAG_SHIFT) | payload;
|
||||
#endif
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromTagAndPayload(JSValueTag tag, PayloadType payload)
|
||||
{
|
||||
return fromRawBits(bitsFromTagAndPayload(tag, payload));
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromRawBits(uint64_t asBits) {
|
||||
return Value(asBits);
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromInt32(int32_t i) {
|
||||
return fromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
|
||||
}
|
||||
|
||||
static constexpr Value
|
||||
fromDouble(double d) {
|
||||
return Value(d);
|
||||
}
|
||||
} JS_HAZ_GC_POINTER;
|
||||
|
||||
/**
|
||||
|
@ -1255,7 +1248,7 @@ SameType(const Value& lhs, const Value& rhs)
|
|||
return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return (lhs.isDouble() && rhs.isDouble()) ||
|
||||
(((lhs.data.asBits ^ rhs.data.asBits) & 0xFFFF800000000000ULL) == 0);
|
||||
(((lhs.asBits_ ^ rhs.asBits_) & 0xFFFF800000000000ULL) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace JS {
|
||||
class CallArgs;
|
||||
class Value;
|
||||
union Value;
|
||||
} // namespace JS
|
||||
|
||||
namespace js {
|
||||
|
|
|
@ -10,11 +10,9 @@ mozilla.prettyprinters.clear_module_printers(__name__)
|
|||
|
||||
# Summary of the JS::Value type:
|
||||
#
|
||||
# Viewed abstractly, JS::Value is a 64-bit discriminated union, with
|
||||
# JSString *, JSObject *, IEEE 64-bit floating-point, and 32-bit integer
|
||||
# branches (and a few others). (It is not actually a C++ union;
|
||||
# 'discriminated union' just describes the overall effect.) Note that
|
||||
# JS::Value is always 64 bits long, even on 32-bit architectures.
|
||||
# JS::Value is a 64-bit discriminated union, with JSString*, JSObject*, IEEE
|
||||
# 64-bit floating-point, and 32-bit integer branches (and a few others).
|
||||
# JS::Value is 64 bits long on all architectures.
|
||||
#
|
||||
# The ECMAScript standard specifies that ECMAScript numbers are IEEE 64-bit
|
||||
# floating-point values. A JS::Value can represent any JavaScript number
|
||||
|
@ -63,11 +61,10 @@ mozilla.prettyprinters.clear_module_printers(__name__)
|
|||
# holds the address of a JSObject; if a string, the address of a
|
||||
# JSString; and so on.
|
||||
#
|
||||
# On the only 64-bit platform we support, x86_64, only the lower 48 bits of
|
||||
# an address are significant, and only those values whose top bit is zero
|
||||
# are used for user-space addresses. This means that x86_64 addresses are
|
||||
# effectively 47 bits long, and thus fit nicely in the available portion of
|
||||
# the fraction field.
|
||||
# On x86_64 only the lower 48 bits of an address are significant, and only
|
||||
# those values whose top bit is zero are used for user-space addresses. Thus
|
||||
# x86_64 addresses are effectively 47 bits long and fit nicely in the available
|
||||
# portion of the fraction field.
|
||||
#
|
||||
# See Value.h for full details.
|
||||
|
||||
|
@ -75,8 +72,8 @@ class Box(object):
|
|||
def __init__(self, asBits, jtc):
|
||||
self.asBits = asBits
|
||||
self.jtc = jtc
|
||||
# Value::layout::asBits is uint64_t, but somehow the sign bit can be
|
||||
# botched here, even though Python integers are arbitrary precision.
|
||||
# Value::asBits is uint64_t, but somehow the sign bit can be botched
|
||||
# here, even though Python integers are arbitrary precision.
|
||||
if self.asBits < 0:
|
||||
self.asBits = self.asBits + (1 << 64)
|
||||
|
||||
|
@ -167,9 +164,8 @@ class JSValue(object):
|
|||
cache.mod_JS_Value = JSValueTypeCache(cache)
|
||||
self.jtc = cache.mod_JS_Value
|
||||
|
||||
data = value['data']
|
||||
self.data = data
|
||||
self.box = self.jtc.boxer(data['asBits'], self.jtc)
|
||||
self.value = value
|
||||
self.box = self.jtc.boxer(value['asBits_'], self.jtc)
|
||||
|
||||
def to_string(self):
|
||||
tag = self.box.tag()
|
||||
|
@ -194,7 +190,7 @@ class JSValue(object):
|
|||
return '$JS::Int32Value(%s)' % value
|
||||
|
||||
if tag == self.jtc.DOUBLE:
|
||||
return '$JS::DoubleValue(%s)' % self.data['asDouble']
|
||||
return '$JS::DoubleValue(%s)' % self.value['asDouble_']
|
||||
|
||||
if tag == self.jtc.STRING:
|
||||
value = self.box.as_address().cast(self.cache.JSString_ptr_t)
|
||||
|
|
|
@ -211,7 +211,7 @@ def implemented_types(t):
|
|||
if t.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
yield t.target()
|
||||
for t2 in followers(t.target()): yield t2
|
||||
elif t.code == gdb.TYPE_CODE_STRUCT:
|
||||
elif is_struct_or_union(t):
|
||||
base_classes = []
|
||||
for f in t.fields():
|
||||
if f.is_base_class:
|
||||
|
@ -225,6 +225,9 @@ def implemented_types(t):
|
|||
|
||||
template_regexp = re.compile("([\w_:]+)<")
|
||||
|
||||
def is_struct_or_union(t):
|
||||
return t.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION)
|
||||
|
||||
# Construct and return a pretty-printer lookup function for objfile, or
|
||||
# return None if the objfile doesn't contain SpiderMonkey code
|
||||
# (specifically, definitions for SpiderMonkey types).
|
||||
|
@ -253,7 +256,7 @@ def lookup_for_objfile(objfile):
|
|||
def check_table_by_type_name(table, t):
|
||||
if t.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
return check_table(table, str(t))
|
||||
elif t.code == gdb.TYPE_CODE_STRUCT and t.tag:
|
||||
elif is_struct_or_union(t) and t.tag:
|
||||
return check_table(table, t.tag)
|
||||
else:
|
||||
return None
|
||||
|
@ -270,7 +273,7 @@ def lookup_for_objfile(objfile):
|
|||
else:
|
||||
p = check_table_by_type_name(printers_by_tag, t)
|
||||
if p: return p
|
||||
if t.code == gdb.TYPE_CODE_STRUCT and t.tag:
|
||||
if is_struct_or_union(t) and t.tag:
|
||||
m = template_regexp.match(t.tag)
|
||||
if m:
|
||||
p = check_table(template_printers_by_tag, m.group(1))
|
||||
|
|
Загрузка…
Ссылка в новой задаче