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:
Jeff Walden 2018-03-27 20:20:43 -07:00
Родитель e5512cfdf4
Коммит ca78e29895
5 изменённых файлов: 189 добавлений и 197 удалений

Просмотреть файл

@ -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))