Bug 962555 part 6 - IonMonkey: Simplify encoding & decoding of RValueAllocations. r=h4writer

This commit is contained in:
Nicolas B. Pierron 2014-03-18 08:31:24 -07:00
Родитель 50033bf490
Коммит 14278fe362
6 изменённых файлов: 554 добавлений и 651 удалений

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

@ -259,12 +259,25 @@ class SnapshotIterator : public SnapshotReader
private:
// Read a spilled register from the machine state.
bool hasRegister(const Location &loc);
uintptr_t fromRegister(const Location &loc);
bool hasRegister(Register reg) const {
return machine_.has(reg);
}
uintptr_t fromRegister(Register reg) const {
return machine_.read(reg);
}
bool hasRegister(FloatRegister reg) const {
return machine_.has(reg);
}
double fromRegister(FloatRegister reg) const {
return machine_.read(reg);
}
// Read an uintptr_t from the stack.
bool hasStack(const Location &loc);
uintptr_t fromStack(const Location &loc);
bool hasStack(int32_t offset) const {
return true;
}
uintptr_t fromStack(int32_t offset) const;
Value allocationValue(const RValueAllocation &a);
bool allocationReadable(const RValueAllocation &a);

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

@ -1322,29 +1322,10 @@ SnapshotIterator::SnapshotIterator()
{
}
bool
SnapshotIterator::hasRegister(const Location &loc)
{
return machine_.has(loc.reg());
}
uintptr_t
SnapshotIterator::fromRegister(const Location &loc)
SnapshotIterator::fromStack(int32_t offset) const
{
return machine_.read(loc.reg());
}
bool
SnapshotIterator::hasStack(const Location &loc)
{
JS_ASSERT(loc.isStackOffset());
return true;
}
uintptr_t
SnapshotIterator::fromStack(const Location &loc)
{
return ReadFrameSlot(fp_, loc.stackOffset());
return ReadFrameSlot(fp_, offset);
}
static Value
@ -1381,25 +1362,25 @@ SnapshotIterator::allocationReadable(const RValueAllocation &alloc)
{
switch (alloc.mode()) {
case RValueAllocation::DOUBLE_REG:
return machine_.has(alloc.floatReg());
return hasRegister(alloc.fpuReg());
case RValueAllocation::TYPED_REG:
return machine_.has(alloc.reg());
return hasRegister(alloc.reg());
#if defined(JS_NUNBOX32)
case RValueAllocation::UNTYPED_REG_REG:
return hasRegister(alloc.type()) && hasRegister(alloc.payload());
return hasRegister(alloc.reg()) && hasRegister(alloc.reg2());
case RValueAllocation::UNTYPED_REG_STACK:
return hasRegister(alloc.type()) && hasStack(alloc.payload());
return hasRegister(alloc.reg()) && hasStack(alloc.stackOffset2());
case RValueAllocation::UNTYPED_STACK_REG:
return hasStack(alloc.type()) && hasRegister(alloc.payload());
return hasStack(alloc.stackOffset()) && hasRegister(alloc.reg2());
case RValueAllocation::UNTYPED_STACK_STACK:
return hasStack(alloc.type()) && hasStack(alloc.payload());
return hasStack(alloc.stackOffset()) && hasStack(alloc.stackOffset2());
#elif defined(JS_PUNBOX64)
case RValueAllocation::UNTYPED_REG:
return hasRegister(alloc.value());
return hasRegister(alloc.reg());
case RValueAllocation::UNTYPED_STACK:
return hasStack(alloc.value());
return hasStack(alloc.stackOffset());
#endif
default:
@ -1411,8 +1392,17 @@ Value
SnapshotIterator::allocationValue(const RValueAllocation &alloc)
{
switch (alloc.mode()) {
case RValueAllocation::CONSTANT:
return ionScript_->getConstant(alloc.index());
case RValueAllocation::CST_UNDEFINED:
return UndefinedValue();
case RValueAllocation::CST_NULL:
return NullValue();
case RValueAllocation::DOUBLE_REG:
return DoubleValue(machine_.read(alloc.floatReg()));
return DoubleValue(fromRegister(alloc.fpuReg()));
case RValueAllocation::FLOAT32_REG:
{
@ -1420,7 +1410,7 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc)
double d;
float f;
} pun;
pun.d = machine_.read(alloc.floatReg());
pun.d = fromRegister(alloc.fpuReg());
// The register contains the encoding of a float32. We just read
// the bits without making any conversion.
return Float32Value(pun.f);
@ -1430,21 +1420,21 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc)
return Float32Value(ReadFrameFloat32Slot(fp_, alloc.stackOffset()));
case RValueAllocation::TYPED_REG:
return FromTypedPayload(alloc.knownType(), machine_.read(alloc.reg()));
return FromTypedPayload(alloc.knownType(), fromRegister(alloc.reg2()));
case RValueAllocation::TYPED_STACK:
{
switch (alloc.knownType()) {
case JSVAL_TYPE_DOUBLE:
return DoubleValue(ReadFrameDoubleSlot(fp_, alloc.stackOffset()));
return DoubleValue(ReadFrameDoubleSlot(fp_, alloc.stackOffset2()));
case JSVAL_TYPE_INT32:
return Int32Value(ReadFrameInt32Slot(fp_, alloc.stackOffset()));
return Int32Value(ReadFrameInt32Slot(fp_, alloc.stackOffset2()));
case JSVAL_TYPE_BOOLEAN:
return BooleanValue(ReadFrameBooleanSlot(fp_, alloc.stackOffset()));
return BooleanValue(ReadFrameBooleanSlot(fp_, alloc.stackOffset2()));
case JSVAL_TYPE_STRING:
return FromStringPayload(ReadFrameSlot(fp_, alloc.stackOffset()));
return FromStringPayload(fromStack(alloc.stackOffset2()));
case JSVAL_TYPE_OBJECT:
return FromObjectPayload(ReadFrameSlot(fp_, alloc.stackOffset()));
return FromObjectPayload(fromStack(alloc.stackOffset2()));
default:
MOZ_ASSUME_UNREACHABLE("Unexpected type");
}
@ -1454,62 +1444,50 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc)
case RValueAllocation::UNTYPED_REG_REG:
{
jsval_layout layout;
layout.s.tag = (JSValueTag) fromRegister(alloc.type());
layout.s.payload.word = fromRegister(alloc.payload());
layout.s.tag = (JSValueTag) fromRegister(alloc.reg());
layout.s.payload.word = fromRegister(alloc.reg2());
return IMPL_TO_JSVAL(layout);
}
case RValueAllocation::UNTYPED_REG_STACK:
{
jsval_layout layout;
layout.s.tag = (JSValueTag) fromRegister(alloc.type());
layout.s.payload.word = fromStack(alloc.payload());
layout.s.tag = (JSValueTag) fromRegister(alloc.reg());
layout.s.payload.word = fromStack(alloc.stackOffset2());
return IMPL_TO_JSVAL(layout);
}
case RValueAllocation::UNTYPED_STACK_REG:
{
jsval_layout layout;
layout.s.tag = (JSValueTag) fromStack(alloc.type());
layout.s.payload.word = fromRegister(alloc.payload());
layout.s.tag = (JSValueTag) fromStack(alloc.stackOffset());
layout.s.payload.word = fromRegister(alloc.reg2());
return IMPL_TO_JSVAL(layout);
}
case RValueAllocation::UNTYPED_STACK_STACK:
{
jsval_layout layout;
layout.s.tag = (JSValueTag) fromStack(alloc.type());
layout.s.payload.word = fromStack(alloc.payload());
layout.s.tag = (JSValueTag) fromStack(alloc.stackOffset());
layout.s.payload.word = fromStack(alloc.stackOffset2());
return IMPL_TO_JSVAL(layout);
}
#elif defined(JS_PUNBOX64)
case RValueAllocation::UNTYPED_REG:
{
jsval_layout layout;
layout.asBits = fromRegister(alloc.value());
layout.asBits = fromRegister(alloc.reg());
return IMPL_TO_JSVAL(layout);
}
case RValueAllocation::UNTYPED_STACK:
{
jsval_layout layout;
layout.asBits = fromStack(alloc.value());
layout.asBits = fromStack(alloc.stackOffset());
return IMPL_TO_JSVAL(layout);
}
#endif
case RValueAllocation::JS_UNDEFINED:
return UndefinedValue();
case RValueAllocation::JS_NULL:
return NullValue();
case RValueAllocation::JS_INT32:
return Int32Value(alloc.int32Value());
case RValueAllocation::CONSTANT:
return ionScript_->getConstant(alloc.constantIndex());
default:
MOZ_ASSUME_UNREACHABLE("huh?");
}

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

@ -28,290 +28,325 @@ using namespace js::jit;
//
// [ptr] Debug only: JSScript *
// [vwu] pc offset
// [vwu] # of slots, including nargs
// [rva*] N recover value allocations entries,
// where N = nargs + nfixed + stackDepth
// [vwu] # of RVA's indexes, including nargs
// [vwu*] List of indexes to R(ecover)ValueAllocation table. Contains
// nargs + nfixed + stackDepth items.
//
// Recover value allocations are encoded at the end of the Snapshot buffer, and
// they are padded on ALLOCATION_TABLE_ALIGNMENT. The encoding of each
// allocation is determined by the RValueAllocation::Layout, which can be
// obtained from the RValueAllocation::Mode with layoutFromMode function. The
// layout structure list the type of payload which are used to serialized /
// deserialized / dumped the content of the allocations.
//
// R(ecover)ValueAllocation items:
// [u8'] Mode, which defines the type of the payload as well as the
// interpretation.
// [pld] first payload (packed tag, index, stack offset, register, ...)
// [pld] second payload (register, stack offset, none)
//
// Modes:
// CONSTANT [INDEX]
// Index into the constant pool.
//
// CST_UNDEFINED []
// Constant value which correspond to the "undefined" JS value.
//
// CST_NULL []
// Constant value which correspond to the "null" JS value.
//
// DOUBLE_REG [FPU_REG]
// Double value stored in a FPU register.
//
// FLOAT32_REG [FPU_REG]
// Float 32bit value stored in a FPU register.
//
// FLOAT32_STACK [STACK_OFFSET]
// Float 32bit value stored on the stack.
//
// UNTYPED_REG [GPR_REG]
// UNTYPED_STACK [STACK_OFFSET]
// UNTYPED_REG_REG [GPR_REG, GPR_REG]
// UNTYPED_REG_STACK [GPR_REG, STACK_OFFSET]
// UNTYPED_STACK_REG [STACK_OFFSET, GPR_REG]
// UNTYPED_STACK_STACK [STACK_OFFSET, STACK_OFFSET]
// Value with dynamically known type. On 32 bits architecture, the
// first register/stack-offset correspond to the holder of the type,
// and the second correspond to the payload of the JS Value.
//
// TYPED_REG [PACKED_TAG, GPR_REG]:
// Value with statically known type, which payload is stored in a
// register.
//
// TYPED_STACK [PACKED_TAG, STACK_OFFSET]:
// Value with statically known type, which payload is stored at an
// offset on the stack.
//
// Encodings:
// [ptr] A fixed-size pointer.
// [vwu] A variable-width unsigned integer.
// [vws] A variable-width signed integer.
// [u8] An 8-bit unsigned integer.
// [rva*] list of RValueAllocation which are indicating how to find a js::Value
// on a call/bailout. The first byte is split as thus:
// Bits 0-2: JSValueType
// Bits 3-7: 5-bit register code ("reg").
// [u8'] An 8-bit unsigned integer which is potentially extended with packed
// data.
// [u8"] Packed data which is stored and packed in the previous [u8'].
// [vwu*] A list of variable-width unsigned integers.
// [pld] Payload of Recover Value Allocation:
// PAYLOAD_NONE:
// There is no payload.
//
// JSVAL_TYPE_DOUBLE:
// If "reg" is InvalidFloatReg, this byte is followed by a
// [vws] stack offset. Otherwise, "reg" encodes an XMM register.
// PAYLOAD_INDEX:
// [vwu] Index, such as the constant pool index.
//
// JSVAL_TYPE_INT32:
// JSVAL_TYPE_OBJECT:
// JSVAL_TYPE_BOOLEAN:
// JSVAL_TYPE_STRING:
// If "reg" is ESC_REG_FIELD_INDEX, this byte is followed by a
// [vws] stack offset. Otherwise, "reg" encodes a GPR register.
// PAYLOAD_STACK_OFFSET:
// [vws] Stack offset based on the base of the Ion frame.
//
// JSVAL_TYPE_NULL:
// Reg value:
// 0-27: Constant integer; Int32Value(n)
// 28: Variable float32; Float register code
// 29: Variable float32; Stack index
// 30: NullValue()
// 31: Constant integer; Int32Value([vws])
// PAYLOAD_GPR:
// [u8] Code of the general register.
//
// JSVAL_TYPE_UNDEFINED:
// Reg value:
// 0-27: Constant value, index n into ionScript->constants()
// 28-29: unused
// 30: UndefinedValue()
// 31: Constant value, index [vwu] into
// ionScript->constants()
// PAYLOAD_FPU:
// [u8] Code of the FPU register.
//
// JSVAL_TYPE_MAGIC: (reg value is 30)
// The value is a lazy argument object. Followed by extra fields
// indicating the location of the payload.
// [vwu] reg2 (0-29)
// [vwu] reg2 (31) [vws] stack index
//
// JSVAL_TYPE_MAGIC:
// The type is not statically known. The meaning of this depends
// on the boxing style.
//
// NUNBOX32:
// Followed by a type and payload indicator that are one of
// the following:
// code=0 [vws] stack slot, [vws] stack slot
// code=1 [vws] stack slot, reg
// code=2 reg, [vws] stack slot
// code=3 reg, reg
//
// PUNBOX64:
// "reg" is ESC_REG_FIELD_INDEX: byte is followed by a [vws]
// stack offset containing a Value.
//
// Otherwise, "reg" is a register containing a Value.
// PAYLOAD_PACKED_TAG:
// [u8"] Bits 5-7: JSValueType is encoded on the low bits of the Mode
// of the RValueAllocation.
//
#ifdef JS_NUNBOX32
static const uint32_t NUNBOX32_STACK_STACK = 0;
static const uint32_t NUNBOX32_STACK_REG = 1;
static const uint32_t NUNBOX32_REG_STACK = 2;
static const uint32_t NUNBOX32_REG_REG = 3;
const RValueAllocation::Layout &
RValueAllocation::layoutFromMode(Mode mode)
{
switch (mode) {
case CONSTANT: {
static const RValueAllocation::Layout layout = {
PAYLOAD_INDEX,
PAYLOAD_NONE,
"constant"
};
return layout;
}
case CST_UNDEFINED: {
static const RValueAllocation::Layout layout = {
PAYLOAD_NONE,
PAYLOAD_NONE,
"undefined"
};
return layout;
}
case CST_NULL: {
static const RValueAllocation::Layout layout = {
PAYLOAD_NONE,
PAYLOAD_NONE,
"null"
};
return layout;
}
case DOUBLE_REG: {
static const RValueAllocation::Layout layout = {
PAYLOAD_FPU,
PAYLOAD_NONE,
"double"
};
return layout;
}
case FLOAT32_REG: {
static const RValueAllocation::Layout layout = {
PAYLOAD_FPU,
PAYLOAD_NONE,
"float32"
};
return layout;
}
case FLOAT32_STACK: {
static const RValueAllocation::Layout layout = {
PAYLOAD_STACK_OFFSET,
PAYLOAD_NONE,
"float32"
};
return layout;
}
#if defined(JS_NUNBOX32)
case UNTYPED_REG_REG: {
static const RValueAllocation::Layout layout = {
PAYLOAD_GPR,
PAYLOAD_GPR,
"value"
};
return layout;
}
case UNTYPED_REG_STACK: {
static const RValueAllocation::Layout layout = {
PAYLOAD_GPR,
PAYLOAD_STACK_OFFSET,
"value"
};
return layout;
}
case UNTYPED_STACK_REG: {
static const RValueAllocation::Layout layout = {
PAYLOAD_STACK_OFFSET,
PAYLOAD_GPR
};
return layout;
}
case UNTYPED_STACK_STACK: {
static const RValueAllocation::Layout layout = {
PAYLOAD_STACK_OFFSET,
PAYLOAD_STACK_OFFSET,
"value"
};
return layout;
}
#elif defined(JS_PUNBOX64)
case UNTYPED_REG: {
static const RValueAllocation::Layout layout = {
PAYLOAD_GPR,
PAYLOAD_NONE,
"value"
};
return layout;
}
case UNTYPED_STACK: {
static const RValueAllocation::Layout layout = {
PAYLOAD_STACK_OFFSET,
PAYLOAD_NONE,
"value"
};
return layout;
}
#endif
default: {
static const RValueAllocation::Layout regLayout = {
PAYLOAD_PACKED_TAG,
PAYLOAD_GPR,
"typed value"
};
static const uint32_t MAX_TYPE_FIELD_VALUE = 7;
static const RValueAllocation::Layout stackLayout = {
PAYLOAD_PACKED_TAG,
PAYLOAD_STACK_OFFSET,
"typed value"
};
static const uint32_t MAX_REG_FIELD_VALUE = 31;
static const uint32_t ESC_REG_FIELD_INDEX = 31;
static const uint32_t ESC_REG_FIELD_CONST = 30;
static const uint32_t ESC_REG_FIELD_FLOAT32_STACK = 29;
static const uint32_t ESC_REG_FIELD_FLOAT32_REG = 28;
static const uint32_t MIN_REG_FIELD_ESC = 28;
if (mode >= TYPED_REG_MIN && mode <= TYPED_REG_MAX)
return regLayout;
if (mode >= TYPED_STACK_MIN && mode <= TYPED_STACK_MAX)
return stackLayout;
}
}
MOZ_ASSUME_UNREACHABLE("Wrong mode type?");
}
// Pad serialized RValueAllocations by a multiple of X bytes in the allocation
// buffer. By padding serialized value allocations, we are building an
// indexable table of elements of X bytes, and thus we can safely divide any
// offset within the buffer by X to obtain an index.
//
// By padding, we are loosing space within the allocation buffer, but we
// multiple by X the number of indexes that we can store on one byte in each
// snapshots.
//
// Some value allocations are taking more than X bytes to be encoded, in which
// case we will pad to a multiple of X, and we are wasting indexes. The choice
// of X should be balanced between the wasted padding of serialized value
// allocation, and the saving made in snapshot indexes.
static const size_t ALLOCATION_TABLE_ALIGNMENT = 2; /* bytes */
void
RValueAllocation::readPayload(CompactBufferReader &reader, PayloadType type,
uint8_t *mode, Payload *p)
{
switch (type) {
case PAYLOAD_NONE:
break;
case PAYLOAD_INDEX:
p->index = reader.readUnsigned();
break;
case PAYLOAD_STACK_OFFSET:
p->stackOffset = reader.readSigned();
break;
case PAYLOAD_GPR:
p->gpr = Register::FromCode(reader.readByte());
break;
case PAYLOAD_FPU:
p->fpu = FloatRegister::FromCode(reader.readByte());
break;
case PAYLOAD_PACKED_TAG:
p->type = JSValueType(*mode & 0x07);
*mode = *mode & ~0x07;
break;
}
}
RValueAllocation
RValueAllocation::read(CompactBufferReader &reader)
{
uint8_t b = reader.readByte();
uint8_t mode = reader.readByte();
const Layout &layout = layoutFromMode(Mode(mode));
Payload arg1, arg2;
JSValueType type = JSValueType(b & 0x7);
uint32_t code = b >> 3;
switch (type) {
case JSVAL_TYPE_DOUBLE:
if (code < MIN_REG_FIELD_ESC)
return Double(FloatRegister::FromCode(code));
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
return Typed(type, reader.readSigned());
case JSVAL_TYPE_INT32:
case JSVAL_TYPE_STRING:
case JSVAL_TYPE_OBJECT:
case JSVAL_TYPE_BOOLEAN:
if (code < MIN_REG_FIELD_ESC)
return Typed(type, Register::FromCode(code));
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
return Typed(type, reader.readSigned());
case JSVAL_TYPE_NULL:
if (code == ESC_REG_FIELD_CONST)
return Null();
if (code == ESC_REG_FIELD_INDEX)
return Int32(reader.readSigned());
if (code == ESC_REG_FIELD_FLOAT32_REG)
return Float32(FloatRegister::FromCode(reader.readUnsigned()));
if (code == ESC_REG_FIELD_FLOAT32_STACK)
return Float32(reader.readSigned());
return Int32(code);
case JSVAL_TYPE_UNDEFINED:
if (code == ESC_REG_FIELD_CONST)
return Undefined();
if (code == ESC_REG_FIELD_INDEX)
return ConstantPool(reader.readUnsigned());
return ConstantPool(code);
case JSVAL_TYPE_MAGIC:
{
if (code == ESC_REG_FIELD_CONST) {
uint8_t reg2 = reader.readUnsigned();
if (reg2 != ESC_REG_FIELD_INDEX)
return Typed(type, Register::FromCode(reg2));
return Typed(type, reader.readSigned());
}
#ifdef JS_NUNBOX32
int32_t type, payload;
switch (code) {
case NUNBOX32_STACK_STACK:
type = reader.readSigned();
payload = reader.readSigned();
return Untyped(type, payload);
case NUNBOX32_STACK_REG:
type = reader.readSigned();
payload = reader.readByte();
return Untyped(type, Register::FromCode(payload));
case NUNBOX32_REG_STACK:
type = reader.readByte();
payload = reader.readSigned();
return Untyped(Register::FromCode(type), payload);
case NUNBOX32_REG_REG:
type = reader.readByte();
payload = reader.readByte();
return Untyped(Register::FromCode(type),
Register::FromCode(payload));
default:
MOZ_ASSUME_UNREACHABLE("bad code");
break;
}
#elif JS_PUNBOX64
if (code < MIN_REG_FIELD_ESC)
return Untyped(Register::FromCode(code));
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
return Untyped(reader.readSigned());
#endif
}
default:
MOZ_ASSUME_UNREACHABLE("bad type");
break;
}
MOZ_ASSUME_UNREACHABLE("huh?");
readPayload(reader, layout.type1, &mode, &arg1);
readPayload(reader, layout.type2, &mode, &arg2);
return RValueAllocation(Mode(mode), arg1, arg2);
}
void
RValueAllocation::writeHeader(CompactBufferWriter &writer,
JSValueType type,
uint32_t regCode) const
RValueAllocation::writePayload(CompactBufferWriter &writer, PayloadType type,
Payload p)
{
JS_ASSERT(uint32_t(type) <= MAX_TYPE_FIELD_VALUE);
JS_ASSERT(uint32_t(regCode) <= MAX_REG_FIELD_VALUE);
JS_STATIC_ASSERT(Registers::Total < MIN_REG_FIELD_ESC);
switch (type) {
case PAYLOAD_NONE:
break;
case PAYLOAD_INDEX:
writer.writeUnsigned(p.index);
break;
case PAYLOAD_STACK_OFFSET:
writer.writeSigned(p.stackOffset);
break;
case PAYLOAD_GPR:
static_assert(Registers::Total <= 0x100,
"Not enough bytes to encode all registers.");
writer.writeByte(p.gpr.code());
break;
case PAYLOAD_FPU:
static_assert(FloatRegisters::Total <= 0x100,
"Not enough bytes to encode all float registers.");
writer.writeByte(p.fpu.code());
break;
case PAYLOAD_PACKED_TAG: {
// This code assumes that the PACKED_TAG payload is following the
// writeByte of the mode.
MOZ_ASSERT(writer.length());
uint8_t *mode = writer.buffer() + (writer.length() - 1);
MOZ_ASSERT((*mode & 0x07) == 0 && (p.type & ~0x07) == 0);
*mode = *mode | p.type;
break;
}
}
}
uint8_t byte = uint32_t(type) | (regCode << 3);
writer.writeByte(byte);
void
RValueAllocation::writePadding(CompactBufferWriter &writer)
{
// Write 0x7f in all padding bytes.
while (writer.length() % ALLOCATION_TABLE_ALIGNMENT)
writer.writeByte(0x7f);
}
void
RValueAllocation::write(CompactBufferWriter &writer) const
{
switch (mode()) {
case CONSTANT: {
if (constantIndex() < MIN_REG_FIELD_ESC) {
writeHeader(writer, JSVAL_TYPE_UNDEFINED, constantIndex());
} else {
writeHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_INDEX);
writer.writeUnsigned(constantIndex());
}
break;
}
const Layout &layout = layoutFromMode(mode());
MOZ_ASSERT(layout.type2 != PAYLOAD_PACKED_TAG);
MOZ_ASSERT(writer.length() % ALLOCATION_TABLE_ALIGNMENT == 0);
case DOUBLE_REG: {
writeHeader(writer, JSVAL_TYPE_DOUBLE, floatReg().code());
break;
}
case FLOAT32_REG: {
writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_REG);
writer.writeUnsigned(floatReg().code());
break;
}
case FLOAT32_STACK: {
writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_STACK);
writer.writeSigned(stackOffset());
break;
}
case TYPED_REG: {
writeHeader(writer, knownType(), reg().code());
break;
}
case TYPED_STACK: {
writeHeader(writer, knownType(), ESC_REG_FIELD_INDEX);
writer.writeSigned(stackOffset());
break;
}
#if defined(JS_NUNBOX32)
case UNTYPED_REG_REG: {
writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_REG_REG);
writer.writeByte(type().reg().code());
writer.writeByte(payload().reg().code());
break;
}
case UNTYPED_REG_STACK: {
writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_REG_STACK);
writer.writeByte(type().reg().code());
writer.writeSigned(payload().stackOffset());
break;
}
case UNTYPED_STACK_REG: {
writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_STACK_REG);
writer.writeSigned(type().stackOffset());
writer.writeByte(payload().reg().code());
break;
}
case UNTYPED_STACK_STACK: {
writeHeader(writer, JSVAL_TYPE_MAGIC, NUNBOX32_STACK_STACK);
writer.writeSigned(type().stackOffset());
writer.writeSigned(payload().stackOffset());
break;
}
#elif defined(JS_PUNBOX64)
case UNTYPED_REG: {
writeHeader(writer, JSVAL_TYPE_MAGIC, value().reg().code());
break;
}
case UNTYPED_STACK: {
writeHeader(writer, JSVAL_TYPE_MAGIC, ESC_REG_FIELD_INDEX);
writer.writeSigned(value().stackOffset());
break;
}
#endif
case JS_UNDEFINED: {
writeHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_CONST);
break;
}
case JS_NULL: {
writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_CONST);
break;
}
case JS_INT32: {
if (int32Value() >= 0 && uint32_t(int32Value()) < MIN_REG_FIELD_ESC) {
writeHeader(writer, JSVAL_TYPE_NULL, int32Value());
} else {
writeHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_INDEX);
writer.writeSigned(int32Value());
}
break;
}
case INVALID: {
MOZ_ASSUME_UNREACHABLE("not initialized");
break;
}
}
writer.writeByte(mode_);
writePayload(writer, layout.type1, arg1_);
writePayload(writer, layout.type2, arg2_);
writePadding(writer);
}
HashNumber
@ -320,10 +355,10 @@ RValueAllocation::hash() const {
write(writer);
// We should never oom because the compact buffer writer has 32 inlined
// bytes, and in the worse case scenario, only encode 11 bytes (= header
// + signed + signed).
// bytes, and in the worse case scenario, only encode 12 bytes
// (12 == mode + signed + signed + pad).
MOZ_ASSERT(!writer.oom());
MOZ_ASSERT(writer.length() <= 11);
MOZ_ASSERT(writer.length() <= 12);
HashNumber res = 0;
for (size_t i = 0; i < writer.length(); i++) {
@ -333,15 +368,6 @@ RValueAllocation::hash() const {
return res;
}
void
Location::dump(FILE *fp) const
{
if (isStackOffset())
fprintf(fp, "stack %d", stackOffset());
else
fprintf(fp, "reg %s", reg().name());
}
static const char *
ValTypeToString(JSValueType type)
{
@ -364,72 +390,66 @@ ValTypeToString(JSValueType type)
}
void
RValueAllocation::dump(FILE *fp) const
RValueAllocation::dumpPayload(FILE *fp, PayloadType type, Payload p)
{
switch (mode()) {
case CONSTANT:
fprintf(fp, "constant (pool index %u)", constantIndex());
switch (type) {
case PAYLOAD_NONE:
break;
case DOUBLE_REG:
fprintf(fp, "double (reg %s)", floatReg().name());
case PAYLOAD_INDEX:
fprintf(fp, "index %u", p.index);
break;
case FLOAT32_REG:
fprintf(fp, "float32 (reg %s)", floatReg().name());
case PAYLOAD_STACK_OFFSET:
fprintf(fp, "stack %d", p.stackOffset);
break;
case FLOAT32_STACK:
fprintf(fp, "float32 (");
known_type_.payload.dump(fp);
fprintf(fp, ")");
case PAYLOAD_GPR:
fprintf(fp, "reg %s", p.gpr.name());
break;
case TYPED_REG:
case TYPED_STACK:
fprintf(fp, "%s (", ValTypeToString(knownType()));
known_type_.payload.dump(fp);
fprintf(fp, ")");
case PAYLOAD_FPU:
fprintf(fp, "reg %s", p.fpu.name());
break;
#if defined(JS_NUNBOX32)
case UNTYPED_REG_REG:
case UNTYPED_REG_STACK:
case UNTYPED_STACK_REG:
case UNTYPED_STACK_STACK:
fprintf(fp, "value (type = ");
type().dump(fp);
fprintf(fp, ", payload = ");
payload().dump(fp);
fprintf(fp, ")");
break;
#elif defined(JS_PUNBOX64)
case UNTYPED_REG:
case UNTYPED_STACK:
fprintf(fp, "value (");
value().dump(fp);
fprintf(fp, ")");
break;
#endif
case JS_UNDEFINED:
fprintf(fp, "undefined");
break;
case JS_NULL:
fprintf(fp, "null");
break;
case JS_INT32:
fprintf(fp, "int32_t %d", int32Value());
break;
case INVALID:
fprintf(fp, "invalid");
case PAYLOAD_PACKED_TAG:
fprintf(fp, ValTypeToString(p.type));
break;
}
}
void
RValueAllocation::dump(FILE *fp) const
{
const Layout &layout = layoutFromMode(mode());
fprintf(fp, "%s", layout.name);
if (layout.type1 != PAYLOAD_NONE)
fprintf(fp, " (");
dumpPayload(fp, layout.type1, arg1_);
if (layout.type2 != PAYLOAD_NONE)
fprintf(fp, ", ");
dumpPayload(fp, layout.type2, arg2_);
if (layout.type1 != PAYLOAD_NONE)
fprintf(fp, ")");
}
bool
RValueAllocation::equalPayloads(PayloadType type, Payload lhs, Payload rhs)
{
switch (type) {
case PAYLOAD_NONE:
return true;
case PAYLOAD_INDEX:
return lhs.index == rhs.index;
case PAYLOAD_STACK_OFFSET:
return lhs.stackOffset == rhs.stackOffset;
case PAYLOAD_GPR:
return lhs.gpr == rhs.gpr;
case PAYLOAD_FPU:
return lhs.fpu == rhs.fpu;
case PAYLOAD_PACKED_TAG:
return lhs.type == rhs.type;
}
return false;
}
SnapshotReader::SnapshotReader(const uint8_t *snapshots, uint32_t offset,
uint32_t RVATableSize, uint32_t listSize)
: reader_(snapshots + offset, snapshots + listSize),
@ -503,21 +523,6 @@ SnapshotReader::spewBailingFrom() const
}
#endif
// Pad serialized RValueAllocations by a multiple of X bytes in the allocation
// buffer. By padding serialized value allocations, we are building an
// indexable table of elements of X bytes, and thus we can safely divide any
// offset within the buffer by X to obtain an index.
//
// By padding, we are loosing space within the allocation buffer, but we
// multiple by X the number of indexes that we can store on one byte in each
// snapshots.
//
// Some value allocations are taking more than X bytes to be encoded, in which
// case we will pad to a multiple of X, and we are wasting indexes. The choice
// of X should be balanced between the wasted padding of serialized value
// allocation, and the saving made in snapshot indexes.
static const size_t ALLOCATION_TABLE_ALIGNMENT = 2; /* bytes */
RValueAllocation
SnapshotReader::readAllocation()
{
@ -606,12 +611,7 @@ SnapshotWriter::add(const RValueAllocation &alloc)
uint32_t offset;
RValueAllocMap::AddPtr p = allocMap_.lookupForAdd(alloc);
if (!p) {
// Write 0x7f in all padding bytes.
while (allocWriter_.length() % ALLOCATION_TABLE_ALIGNMENT)
allocWriter_.writeByte(0x7f);
offset = allocWriter_.length();
JS_ASSERT(offset % ALLOCATION_TABLE_ALIGNMENT == 0);
alloc.write(allocWriter_);
if (!allocMap_.add(p, alloc, offset))
return false;

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

@ -21,51 +21,6 @@ namespace jit {
class RValueAllocation;
class Location
{
friend class RValueAllocation;
// An offset that is illegal for a local variable's stack allocation.
static const int32_t InvalidStackOffset = -1;
Register::Code reg_;
int32_t stackOffset_;
static Location From(const Register &reg) {
Location loc;
loc.reg_ = reg.code();
loc.stackOffset_ = InvalidStackOffset;
return loc;
}
static Location From(int32_t stackOffset) {
JS_ASSERT(stackOffset != InvalidStackOffset);
Location loc;
loc.reg_ = Register::Code(0); // Quell compiler warnings.
loc.stackOffset_ = stackOffset;
return loc;
}
public:
Register reg() const {
JS_ASSERT(!isStackOffset());
return Register::FromCode(reg_);
}
int32_t stackOffset() const {
JS_ASSERT(isStackOffset());
return stackOffset_;
}
bool isStackOffset() const {
return stackOffset_ != InvalidStackOffset;
}
void dump(FILE *fp) const;
public:
bool operator==(const Location &l) const {
return reg_ == l.reg_ && stackOffset_ == l.stackOffset_;
}
};
// A Recover Value Allocation mirror what is known at compiled time as being the
// MIRType and the LAllocation. This is read out of the snapshot to recover the
// value which would be there if this frame was an interpreter frame instead of
@ -73,104 +28,126 @@ class Location
//
// It is used with the SnapshotIterator to recover a Value from the stack,
// spilled registers or the list of constant of the compiled script.
//
// Unit tests are located in jsapi-tests/testJitRValueAlloc.cpp.
class RValueAllocation
{
public:
// See RValueAllocation encoding in Snapshots.cpp
enum Mode
{
CONSTANT, // An index into the constant pool.
DOUBLE_REG, // Type is double, payload is in a register.
FLOAT32_REG, // Type is float32, payload is in a register.
FLOAT32_STACK, // Type is float32, payload is on the stack.
TYPED_REG, // Type is constant, payload is in a register.
TYPED_STACK, // Type is constant, payload is on the stack.
CONSTANT = 0x00,
CST_UNDEFINED = 0x01,
CST_NULL = 0x02,
DOUBLE_REG = 0x03,
FLOAT32_REG = 0x04,
FLOAT32_STACK = 0x05,
#if defined(JS_NUNBOX32)
UNTYPED_REG_REG, // Type is not known, type & payload are is in
// registers.
UNTYPED_REG_STACK, // Type is not known, type is in a register and the
// payload is on the stack.
UNTYPED_STACK_REG, // Type is not known, type is on the stack and the
// payload is in a register.
UNTYPED_STACK_STACK, // Type is not known, type & payload are on the
// stack.
UNTYPED_REG_REG = 0x06,
UNTYPED_REG_STACK = 0x07,
UNTYPED_STACK_REG = 0x08,
UNTYPED_STACK_STACK = 0x09,
#elif defined(JS_PUNBOX64)
UNTYPED_REG, // Type is not known, value is in a register.
UNTYPED_STACK, // Type is not known, value is on the stack.
UNTYPED_REG = 0x06,
UNTYPED_STACK = 0x07,
#endif
JS_UNDEFINED, // UndefinedValue()
JS_NULL, // NullValue()
JS_INT32, // Int32Value(n)
INVALID,
// The JSValueType is packed in the Mode.
TYPED_REG_MIN = 0x10,
TYPED_REG_MAX = 0x17,
TYPED_REG = TYPED_REG_MIN,
// Assert that the mode is UNTYPED by checking the range.
#if defined(JS_NUNBOX32)
UNTYPED_MIN = UNTYPED_REG_REG,
UNTYPED_MAX = UNTYPED_STACK_STACK
#elif defined(JS_PUNBOX64)
UNTYPED_MIN = UNTYPED_REG,
UNTYPED_MAX = UNTYPED_STACK
#endif
// The JSValueType is packed in the Mode.
TYPED_STACK_MIN = 0x18,
TYPED_STACK_MAX = 0x1f,
TYPED_STACK = TYPED_STACK_MIN,
INVALID = 0x100,
};
// See Payload encoding in Snapshots.cpp
enum PayloadType {
PAYLOAD_NONE,
PAYLOAD_INDEX,
PAYLOAD_STACK_OFFSET,
PAYLOAD_GPR,
PAYLOAD_FPU,
PAYLOAD_PACKED_TAG
};
struct Layout {
PayloadType type1;
PayloadType type2;
const char *name;
};
private:
Mode mode_;
union {
// DOUBLE_REG or FLOAT32_REG
FloatRegister::Code fpu_;
// TYPED_REG or TYPED_STACK or FLOAT32_STACK
struct {
JSValueType type;
Location payload;
} known_type_;
// UNTYPED
#if defined(JS_NUNBOX32)
struct {
Location type;
Location payload;
} unknown_type_;
#elif defined(JS_PUNBOX64)
struct {
Location value;
} unknown_type_;
#endif
// CONSTANT's index or JS_INT32
int32_t value_;
// Additional information to recover the content of the allocation.
union Payload {
uint32_t index;
int32_t stackOffset;
Register gpr;
FloatRegister fpu;
JSValueType type;
};
RValueAllocation(Mode mode, JSValueType type, const Location &loc)
: mode_(mode)
{
JS_ASSERT(mode == TYPED_REG || mode == TYPED_STACK);
known_type_.type = type;
known_type_.payload = loc;
Payload arg1_;
Payload arg2_;
static Payload payloadOfIndex(uint32_t index) {
Payload p;
p.index = index;
return p;
}
RValueAllocation(Mode mode, const FloatRegister &reg)
: mode_(mode)
{
JS_ASSERT(mode == FLOAT32_REG || mode == DOUBLE_REG);
fpu_ = reg.code();
static Payload payloadOfStackOffset(int32_t offset) {
Payload p;
p.stackOffset = offset;
return p;
}
RValueAllocation(Mode mode, const Location &loc)
: mode_(mode)
{
JS_ASSERT(mode == FLOAT32_STACK);
known_type_.payload = loc;
static Payload payloadOfRegister(Register reg) {
Payload p;
p.gpr = reg;
return p;
}
RValueAllocation(Mode mode, int32_t index)
: mode_(mode)
{
JS_ASSERT(mode == CONSTANT || mode == JS_INT32);
value_ = index;
static Payload payloadOfFloatRegister(FloatRegister reg) {
Payload p;
p.fpu = reg;
return p;
}
static Payload payloadOfValueType(JSValueType type) {
Payload p;
p.type = type;
return p;
}
static const Layout &layoutFromMode(Mode mode);
static void readPayload(CompactBufferReader &reader, PayloadType t,
uint8_t *mode, Payload *p);
static void writePayload(CompactBufferWriter &writer, PayloadType t,
Payload p);
static void writePadding(CompactBufferWriter &writer);
static void dumpPayload(FILE *fp, PayloadType t, Payload p);
static bool equalPayloads(PayloadType t, Payload lhs, Payload rhs);
RValueAllocation(Mode mode, Payload a1, Payload a2)
: mode_(mode),
arg1_(a1),
arg2_(a2)
{
}
RValueAllocation(Mode mode, Payload a1)
: mode_(mode),
arg1_(a1)
{
}
RValueAllocation(Mode mode)
: mode_(mode)
{
JS_ASSERT(mode == JS_UNDEFINED || mode == JS_NULL ||
(UNTYPED_MIN <= mode && mode <= UNTYPED_MAX));
}
public:
@ -180,15 +157,15 @@ class RValueAllocation
// DOUBLE_REG
static RValueAllocation Double(const FloatRegister &reg) {
return RValueAllocation(DOUBLE_REG, reg);
return RValueAllocation(DOUBLE_REG, payloadOfFloatRegister(reg));
}
// FLOAT32_REG or FLOAT32_STACK
static RValueAllocation Float32(const FloatRegister &reg) {
return RValueAllocation(FLOAT32_REG, reg);
return RValueAllocation(FLOAT32_REG, payloadOfFloatRegister(reg));
}
static RValueAllocation Float32(int32_t stackIndex) {
return RValueAllocation(FLOAT32_STACK, Location::From(stackIndex));
static RValueAllocation Float32(int32_t offset) {
return RValueAllocation(FLOAT32_STACK, payloadOfStackOffset(offset));
}
// TYPED_REG or TYPED_STACK
@ -197,75 +174,64 @@ class RValueAllocation
type != JSVAL_TYPE_MAGIC &&
type != JSVAL_TYPE_NULL &&
type != JSVAL_TYPE_UNDEFINED);
return RValueAllocation(TYPED_REG, type, Location::From(reg));
return RValueAllocation(TYPED_REG, payloadOfValueType(type),
payloadOfRegister(reg));
}
static RValueAllocation Typed(JSValueType type, int32_t stackIndex) {
static RValueAllocation Typed(JSValueType type, int32_t offset) {
JS_ASSERT(type != JSVAL_TYPE_MAGIC &&
type != JSVAL_TYPE_NULL &&
type != JSVAL_TYPE_UNDEFINED);
return RValueAllocation(TYPED_STACK, type, Location::From(stackIndex));
return RValueAllocation(TYPED_STACK, payloadOfValueType(type),
payloadOfStackOffset(offset));
}
// UNTYPED
#if defined(JS_NUNBOX32)
static RValueAllocation Untyped(const Register &type, const Register &payload) {
RValueAllocation slot(UNTYPED_REG_REG);
slot.unknown_type_.type = Location::From(type);
slot.unknown_type_.payload = Location::From(payload);
return slot;
return RValueAllocation(UNTYPED_REG_REG,
payloadOfRegister(type),
payloadOfRegister(payload));
}
static RValueAllocation Untyped(const Register &type, int32_t payloadStackIndex) {
RValueAllocation slot(UNTYPED_REG_STACK);
slot.unknown_type_.type = Location::From(type);
slot.unknown_type_.payload = Location::From(payloadStackIndex);
return slot;
static RValueAllocation Untyped(const Register &type, int32_t payloadStackOffset) {
return RValueAllocation(UNTYPED_REG_STACK,
payloadOfRegister(type),
payloadOfStackOffset(payloadStackOffset));
}
static RValueAllocation Untyped(int32_t typeStackIndex, const Register &payload) {
RValueAllocation slot(UNTYPED_STACK_REG);
slot.unknown_type_.type = Location::From(typeStackIndex);
slot.unknown_type_.payload = Location::From(payload);
return slot;
static RValueAllocation Untyped(int32_t typeStackOffset, const Register &payload) {
return RValueAllocation(UNTYPED_STACK_REG,
payloadOfStackOffset(typeStackOffset),
payloadOfRegister(payload));
}
static RValueAllocation Untyped(int32_t typeStackIndex, int32_t payloadStackIndex) {
RValueAllocation slot(UNTYPED_STACK_STACK);
slot.unknown_type_.type = Location::From(typeStackIndex);
slot.unknown_type_.payload = Location::From(payloadStackIndex);
return slot;
static RValueAllocation Untyped(int32_t typeStackOffset, int32_t payloadStackOffset) {
return RValueAllocation(UNTYPED_STACK_STACK,
payloadOfStackOffset(typeStackOffset),
payloadOfStackOffset(payloadStackOffset));
}
#elif defined(JS_PUNBOX64)
static RValueAllocation Untyped(const Register &value) {
RValueAllocation slot(UNTYPED_REG);
slot.unknown_type_.value = Location::From(value);
return slot;
static RValueAllocation Untyped(const Register &reg) {
return RValueAllocation(UNTYPED_REG, payloadOfRegister(reg));
}
static RValueAllocation Untyped(int32_t stackOffset) {
RValueAllocation slot(UNTYPED_STACK);
slot.unknown_type_.value = Location::From(stackOffset);
return slot;
return RValueAllocation(UNTYPED_STACK, payloadOfStackOffset(stackOffset));
}
#endif
// common constants.
static RValueAllocation Undefined() {
return RValueAllocation(JS_UNDEFINED);
return RValueAllocation(CST_UNDEFINED);
}
static RValueAllocation Null() {
return RValueAllocation(JS_NULL);
}
// JS_INT32
static RValueAllocation Int32(int32_t value) {
return RValueAllocation(JS_INT32, value);
return RValueAllocation(CST_NULL);
}
// CONSTANT's index
static RValueAllocation ConstantPool(uint32_t index) {
return RValueAllocation(CONSTANT, int32_t(index));
return RValueAllocation(CONSTANT, payloadOfIndex(index));
}
void writeHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const;
@ -277,83 +243,48 @@ class RValueAllocation
Mode mode() const {
return mode_;
}
uint32_t constantIndex() const {
JS_ASSERT(mode() == CONSTANT);
return value_;
}
int32_t int32Value() const {
JS_ASSERT(mode() == JS_INT32);
return value_;
}
JSValueType knownType() const {
JS_ASSERT(mode() == TYPED_REG || mode() == TYPED_STACK);
return known_type_.type;
}
Register reg() const {
JS_ASSERT(mode() == TYPED_REG && knownType() != JSVAL_TYPE_DOUBLE);
return known_type_.payload.reg();
}
FloatRegister floatReg() const {
JS_ASSERT(mode() == DOUBLE_REG || mode() == FLOAT32_REG);
return FloatRegister::FromCode(fpu_);
uint32_t index() const {
JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_INDEX);
return arg1_.index;
}
int32_t stackOffset() const {
JS_ASSERT(mode() == TYPED_STACK || mode() == FLOAT32_STACK);
return known_type_.payload.stackOffset();
JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_STACK_OFFSET);
return arg1_.stackOffset;
}
#if defined(JS_NUNBOX32)
Location payload() const {
JS_ASSERT((UNTYPED_MIN <= mode() && mode() <= UNTYPED_MAX));
return unknown_type_.payload;
Register reg() const {
JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_GPR);
return arg1_.gpr;
}
Location type() const {
JS_ASSERT((UNTYPED_MIN <= mode() && mode() <= UNTYPED_MAX));
return unknown_type_.type;
FloatRegister fpuReg() const {
JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_FPU);
return arg1_.fpu;
}
#elif defined(JS_PUNBOX64)
Location value() const {
JS_ASSERT((UNTYPED_MIN <= mode() && mode() <= UNTYPED_MAX));
return unknown_type_.value;
JSValueType knownType() const {
JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_PACKED_TAG);
return arg1_.type;
}
int32_t stackOffset2() const {
JS_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_STACK_OFFSET);
return arg2_.stackOffset;
}
Register reg2() const {
JS_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_GPR);
return arg2_.gpr;
}
#endif
public:
const char *modeToString() const;
void dump(FILE *fp) const;
void dump() const;
public:
bool operator==(const RValueAllocation &s) const {
if (mode_ != s.mode_)
bool operator==(const RValueAllocation &rhs) const {
if (mode_ != rhs.mode_)
return false;
switch (mode_) {
case DOUBLE_REG:
case FLOAT32_REG:
return fpu_ == s.fpu_;
case TYPED_REG:
case TYPED_STACK:
case FLOAT32_STACK:
return known_type_.type == s.known_type_.type &&
known_type_.payload == s.known_type_.payload;
#if defined(JS_NUNBOX32)
case UNTYPED_REG_REG:
case UNTYPED_REG_STACK:
case UNTYPED_STACK_REG:
case UNTYPED_STACK_STACK:
return unknown_type_.type == s.unknown_type_.type &&
unknown_type_.payload == s.unknown_type_.payload;
#else
case UNTYPED_REG:
case UNTYPED_STACK:
return unknown_type_.value == s.unknown_type_.value;
#endif
case CONSTANT:
case JS_INT32:
return value_ == s.value_;
default:
return true;
}
const Layout &layout = layoutFromMode(mode());
return equalPayloads(layout.type1, arg1_, rhs.arg1_) &&
equalPayloads(layout.type2, arg2_, rhs.arg2_);
}
HashNumber hash() const;

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

@ -180,17 +180,10 @@ CodeGeneratorShared::encodeAllocations(LSnapshot *snapshot, MResumePoint *resume
alloc = RValueAllocation::Double(reg);
} else {
MConstant *constant = mir->toConstant();
const Value &v = constant->value();
// Don't bother with the constant pool for smallish integers.
if (v.isInt32() && v.toInt32() >= -32 && v.toInt32() <= 32) {
alloc = RValueAllocation::Int32(v.toInt32());
} else {
uint32_t index;
if (!graph.addConstantToPool(constant->value(), &index))
return false;
alloc = RValueAllocation::ConstantPool(index);
}
uint32_t index;
if (!graph.addConstantToPool(constant->value(), &index))
return false;
alloc = RValueAllocation::ConstantPool(index);
}
break;
}

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

@ -214,18 +214,6 @@ BEGIN_TEST(testJitRValueAlloc_UndefinedAndNull)
}
END_TEST(testJitRValueAlloc_UndefinedAndNull)
BEGIN_TEST(testJitRValueAlloc_Int32)
{
RValueAllocation s;
int32_t i, last = 0, tmp;
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
s = RValueAllocation::Int32(i);
CHECK(s == Read(s));
}
return true;
}
END_TEST(testJitRValueAlloc_Int32)
BEGIN_TEST(testJitRValueAlloc_ConstantPool)
{
RValueAllocation s;