зеркало из https://github.com/mozilla/gecko-dev.git
Bug 962555 part 1 - Extract SnapshotReader::Slot. r=h4writer
This commit is contained in:
Родитель
8faecae69b
Коммит
019612019c
|
@ -237,8 +237,8 @@ class SnapshotIterator : public SnapshotReader
|
|||
IonScript *ionScript_;
|
||||
|
||||
private:
|
||||
bool hasLocation(const SnapshotReader::Location &loc);
|
||||
uintptr_t fromLocation(const SnapshotReader::Location &loc);
|
||||
bool hasLocation(const Location &loc);
|
||||
uintptr_t fromLocation(const Location &loc);
|
||||
|
||||
Value slotValue(const Slot &slot);
|
||||
bool slotReadable(const Slot &slot);
|
||||
|
|
|
@ -1319,13 +1319,13 @@ SnapshotIterator::SnapshotIterator()
|
|||
}
|
||||
|
||||
bool
|
||||
SnapshotIterator::hasLocation(const SnapshotReader::Location &loc)
|
||||
SnapshotIterator::hasLocation(const Location &loc)
|
||||
{
|
||||
return loc.isStackSlot() || machine_.has(loc.reg());
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
SnapshotIterator::fromLocation(const SnapshotReader::Location &loc)
|
||||
SnapshotIterator::fromLocation(const Location &loc)
|
||||
{
|
||||
if (loc.isStackSlot())
|
||||
return ReadFrameSlot(fp_, loc.stackSlot());
|
||||
|
@ -1365,13 +1365,13 @@ bool
|
|||
SnapshotIterator::slotReadable(const Slot &slot)
|
||||
{
|
||||
switch (slot.mode()) {
|
||||
case SnapshotReader::DOUBLE_REG:
|
||||
case Slot::DOUBLE_REG:
|
||||
return machine_.has(slot.floatReg());
|
||||
|
||||
case SnapshotReader::TYPED_REG:
|
||||
case Slot::TYPED_REG:
|
||||
return machine_.has(slot.reg());
|
||||
|
||||
case SnapshotReader::UNTYPED:
|
||||
case Slot::UNTYPED:
|
||||
#if defined(JS_NUNBOX32)
|
||||
return hasLocation(slot.type()) && hasLocation(slot.payload());
|
||||
#elif defined(JS_PUNBOX64)
|
||||
|
@ -1387,10 +1387,10 @@ Value
|
|||
SnapshotIterator::slotValue(const Slot &slot)
|
||||
{
|
||||
switch (slot.mode()) {
|
||||
case SnapshotReader::DOUBLE_REG:
|
||||
case Slot::DOUBLE_REG:
|
||||
return DoubleValue(machine_.read(slot.floatReg()));
|
||||
|
||||
case SnapshotReader::FLOAT32_REG:
|
||||
case Slot::FLOAT32_REG:
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
|
@ -1402,13 +1402,13 @@ SnapshotIterator::slotValue(const Slot &slot)
|
|||
return Float32Value(pun.f);
|
||||
}
|
||||
|
||||
case SnapshotReader::FLOAT32_STACK:
|
||||
case Slot::FLOAT32_STACK:
|
||||
return Float32Value(ReadFrameFloat32Slot(fp_, slot.stackSlot()));
|
||||
|
||||
case SnapshotReader::TYPED_REG:
|
||||
case Slot::TYPED_REG:
|
||||
return FromTypedPayload(slot.knownType(), machine_.read(slot.reg()));
|
||||
|
||||
case SnapshotReader::TYPED_STACK:
|
||||
case Slot::TYPED_STACK:
|
||||
{
|
||||
switch (slot.knownType()) {
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
|
@ -1426,7 +1426,7 @@ SnapshotIterator::slotValue(const Slot &slot)
|
|||
}
|
||||
}
|
||||
|
||||
case SnapshotReader::UNTYPED:
|
||||
case Slot::UNTYPED:
|
||||
{
|
||||
jsval_layout layout;
|
||||
#if defined(JS_NUNBOX32)
|
||||
|
@ -1438,16 +1438,16 @@ SnapshotIterator::slotValue(const Slot &slot)
|
|||
return IMPL_TO_JSVAL(layout);
|
||||
}
|
||||
|
||||
case SnapshotReader::JS_UNDEFINED:
|
||||
case Slot::JS_UNDEFINED:
|
||||
return UndefinedValue();
|
||||
|
||||
case SnapshotReader::JS_NULL:
|
||||
case Slot::JS_NULL:
|
||||
return NullValue();
|
||||
|
||||
case SnapshotReader::JS_INT32:
|
||||
case Slot::JS_INT32:
|
||||
return Int32Value(slot.int32Value());
|
||||
|
||||
case SnapshotReader::CONSTANT:
|
||||
case Slot::CONSTANT:
|
||||
return ionScript_->getConstant(slot.constantIndex());
|
||||
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "jit/Slot.h"
|
||||
|
||||
#include "jit/CompactBuffer.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
// [slot] Information on how to reify a js::Value from an Ion frame. The
|
||||
// first byte is split as thus:
|
||||
// Bits 0-2: JSValueType
|
||||
// Bits 3-7: 5-bit register code ("reg").
|
||||
//
|
||||
// JSVAL_TYPE_DOUBLE:
|
||||
// If "reg" is InvalidFloatReg, this byte is followed by a
|
||||
// [vws] stack offset. Otherwise, "reg" encodes an XMM register.
|
||||
//
|
||||
// JSVAL_TYPE_INT32:
|
||||
// JSVAL_TYPE_OBJECT:
|
||||
// JSVAL_TYPE_BOOLEAN:
|
||||
// JSVAL_TYPE_STRING:
|
||||
// If "reg" is InvalidReg1, this byte is followed by a [vws]
|
||||
// stack offset. Otherwise, "reg" encodes a GPR register.
|
||||
//
|
||||
// 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])
|
||||
//
|
||||
// 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()
|
||||
//
|
||||
// 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 InvalidReg1: byte is followed by a [vws] stack
|
||||
// offset containing a Value.
|
||||
//
|
||||
// Otherwise, "reg" is a register containing a Value.
|
||||
//
|
||||
|
||||
#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;
|
||||
#endif
|
||||
|
||||
static const uint32_t MAX_TYPE_FIELD_VALUE = 7;
|
||||
|
||||
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;
|
||||
|
||||
Slot
|
||||
Slot::read(CompactBufferReader &reader)
|
||||
{
|
||||
uint8_t b = reader.readByte();
|
||||
|
||||
JSValueType type = JSValueType(b & 0x7);
|
||||
uint32_t code = b >> 3;
|
||||
|
||||
switch (type) {
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
if (code < MIN_REG_FIELD_ESC)
|
||||
return DoubleSlot(FloatRegister::FromCode(code));
|
||||
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
|
||||
return TypedSlot(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 TypedSlot(type, Register::FromCode(code));
|
||||
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
|
||||
return TypedSlot(type, reader.readSigned());
|
||||
|
||||
case JSVAL_TYPE_NULL:
|
||||
if (code == ESC_REG_FIELD_CONST)
|
||||
return NullSlot();
|
||||
if (code == ESC_REG_FIELD_INDEX)
|
||||
return Int32Slot(reader.readSigned());
|
||||
if (code == ESC_REG_FIELD_FLOAT32_REG)
|
||||
return Float32Slot(FloatRegister::FromCode(reader.readUnsigned()));
|
||||
if (code == ESC_REG_FIELD_FLOAT32_STACK)
|
||||
return Float32Slot(reader.readSigned());
|
||||
return Int32Slot(code);
|
||||
|
||||
case JSVAL_TYPE_UNDEFINED:
|
||||
if (code == ESC_REG_FIELD_CONST)
|
||||
return UndefinedSlot();
|
||||
if (code == ESC_REG_FIELD_INDEX)
|
||||
return ConstantPoolSlot(reader.readUnsigned());
|
||||
return ConstantPoolSlot(code);
|
||||
|
||||
case JSVAL_TYPE_MAGIC:
|
||||
{
|
||||
if (code == ESC_REG_FIELD_CONST) {
|
||||
uint8_t reg2 = reader.readUnsigned();
|
||||
if (reg2 != ESC_REG_FIELD_INDEX)
|
||||
return TypedSlot(type, Register::FromCode(reg2));
|
||||
return TypedSlot(type, reader.readSigned());
|
||||
}
|
||||
|
||||
#ifdef JS_NUNBOX32
|
||||
int32_t type, payload;
|
||||
switch (code) {
|
||||
case NUNBOX32_STACK_STACK:
|
||||
type = reader.readSigned();
|
||||
payload = reader.readSigned();
|
||||
return UntypedSlot(type, payload);
|
||||
case NUNBOX32_STACK_REG:
|
||||
type = reader.readSigned();
|
||||
payload = reader.readByte();
|
||||
return UntypedSlot(type, Register::FromCode(payload));
|
||||
case NUNBOX32_REG_STACK:
|
||||
type = reader.readByte();
|
||||
payload = reader.readSigned();
|
||||
return UntypedSlot(Register::FromCode(type), payload);
|
||||
case NUNBOX32_REG_REG:
|
||||
type = reader.readByte();
|
||||
payload = reader.readByte();
|
||||
return UntypedSlot(Register::FromCode(type),
|
||||
Register::FromCode(payload));
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("bad code");
|
||||
break;
|
||||
}
|
||||
#elif JS_PUNBOX64
|
||||
if (code < MIN_REG_FIELD_ESC)
|
||||
return UntypedSlot(Register::FromCode(code));
|
||||
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
|
||||
return UntypedSlot(reader.readSigned());
|
||||
#endif
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("bad type");
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("huh?");
|
||||
}
|
||||
|
||||
void
|
||||
Slot::writeSlotHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const
|
||||
{
|
||||
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);
|
||||
|
||||
uint8_t byte = uint32_t(type) | (regCode << 3);
|
||||
writer.writeByte(byte);
|
||||
}
|
||||
|
||||
void
|
||||
Slot::write(CompactBufferWriter &writer) const
|
||||
{
|
||||
switch (mode()) {
|
||||
case CONSTANT: {
|
||||
if (constantIndex() < MIN_REG_FIELD_ESC) {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_UNDEFINED, constantIndex());
|
||||
} else {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_INDEX);
|
||||
writer.writeUnsigned(constantIndex());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DOUBLE_REG: {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_DOUBLE, floatReg().code());
|
||||
break;
|
||||
}
|
||||
|
||||
case FLOAT32_REG: {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_REG);
|
||||
writer.writeUnsigned(floatReg().code());
|
||||
break;
|
||||
}
|
||||
|
||||
case FLOAT32_STACK: {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_STACK);
|
||||
writer.writeSigned(stackSlot());
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPED_REG: {
|
||||
writeSlotHeader(writer, knownType(), reg().code());
|
||||
break;
|
||||
}
|
||||
case TYPED_STACK: {
|
||||
writeSlotHeader(writer, knownType(), ESC_REG_FIELD_INDEX);
|
||||
writer.writeSigned(stackSlot());
|
||||
break;
|
||||
}
|
||||
case UNTYPED: {
|
||||
#if defined(JS_NUNBOX32)
|
||||
uint32_t code = 0;
|
||||
if (type().isStackSlot()) {
|
||||
if (payload().isStackSlot())
|
||||
code = NUNBOX32_STACK_STACK;
|
||||
else
|
||||
code = NUNBOX32_STACK_REG;
|
||||
} else {
|
||||
if (payload().isStackSlot())
|
||||
code = NUNBOX32_REG_STACK;
|
||||
else
|
||||
code = NUNBOX32_REG_REG;
|
||||
}
|
||||
|
||||
writeSlotHeader(writer, JSVAL_TYPE_MAGIC, code);
|
||||
|
||||
if (type().isStackSlot())
|
||||
writer.writeSigned(type().stackSlot());
|
||||
else
|
||||
writer.writeByte(type().reg().code());
|
||||
|
||||
if (payload().isStackSlot())
|
||||
writer.writeSigned(payload().stackSlot());
|
||||
else
|
||||
writer.writeByte(payload().reg().code());
|
||||
|
||||
#elif defined(JS_PUNBOX64)
|
||||
if (value().isStackSlot()) {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_MAGIC, ESC_REG_FIELD_INDEX);
|
||||
writer.writeSigned(value().stackSlot());
|
||||
} else {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_MAGIC, value().reg().code());
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case JS_UNDEFINED: {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_CONST);
|
||||
break;
|
||||
}
|
||||
case JS_NULL: {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_CONST);
|
||||
break;
|
||||
}
|
||||
case JS_INT32: {
|
||||
if (int32Value() >= 0 && uint32_t(int32Value()) < MIN_REG_FIELD_ESC) {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_NULL, int32Value());
|
||||
} else {
|
||||
writeSlotHeader(writer, JSVAL_TYPE_NULL, ESC_REG_FIELD_INDEX);
|
||||
writer.writeSigned(int32Value());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INVALID: {
|
||||
MOZ_ASSUME_UNREACHABLE("not initialized");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Location::dump(FILE *fp) const
|
||||
{
|
||||
if (isStackSlot())
|
||||
fprintf(fp, "stack %d", stackSlot());
|
||||
else
|
||||
fprintf(fp, "reg %s", reg().name());
|
||||
}
|
||||
|
||||
static const char *
|
||||
ValTypeToString(JSValueType type)
|
||||
{
|
||||
switch (type) {
|
||||
case JSVAL_TYPE_INT32:
|
||||
return "int32_t";
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
return "double";
|
||||
case JSVAL_TYPE_STRING:
|
||||
return "string";
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
return "boolean";
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
return "object";
|
||||
case JSVAL_TYPE_MAGIC:
|
||||
return "magic";
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("no payload");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Slot::dump(FILE *fp) const
|
||||
{
|
||||
switch (mode()) {
|
||||
case CONSTANT:
|
||||
fprintf(fp, "constant (pool index %u)", constantIndex());
|
||||
break;
|
||||
|
||||
case DOUBLE_REG:
|
||||
fprintf(fp, "double (reg %s)", floatReg().name());
|
||||
break;
|
||||
|
||||
case FLOAT32_REG:
|
||||
fprintf(fp, "float32 (reg %s)", floatReg().name());
|
||||
break;
|
||||
|
||||
case FLOAT32_STACK:
|
||||
fprintf(fp, "float32 (");
|
||||
known_type_.payload.dump(fp);
|
||||
fprintf(fp, ")");
|
||||
break;
|
||||
|
||||
case TYPED_REG:
|
||||
case TYPED_STACK:
|
||||
fprintf(fp, "%s (", ValTypeToString(knownType()));
|
||||
known_type_.payload.dump(fp);
|
||||
fprintf(fp, ")");
|
||||
break;
|
||||
|
||||
case UNTYPED: {
|
||||
fprintf(fp, "value (");
|
||||
#if defined(JS_NUNBOX32)
|
||||
fprintf(fp, "type = ");
|
||||
type().dump(fp);
|
||||
fprintf(fp, ", payload = ");
|
||||
payload().dump(fp);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
value().dump(fp);
|
||||
#endif
|
||||
fprintf(fp, ")");
|
||||
break;
|
||||
}
|
||||
|
||||
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");
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,325 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef jit_Slot_h
|
||||
#define jit_Slot_h
|
||||
|
||||
#include "jit/Registers.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class CompactBufferReader;
|
||||
class CompactBufferWriter;
|
||||
|
||||
class Slot;
|
||||
|
||||
class Location
|
||||
{
|
||||
friend class Slot;
|
||||
|
||||
// An offset that is illegal for a local variable's stack allocation.
|
||||
static const int32_t InvalidStackSlot = -1;
|
||||
|
||||
Register::Code reg_;
|
||||
int32_t stackSlot_;
|
||||
|
||||
static Location From(const Register ®) {
|
||||
Location loc;
|
||||
loc.reg_ = reg.code();
|
||||
loc.stackSlot_ = InvalidStackSlot;
|
||||
return loc;
|
||||
}
|
||||
static Location From(int32_t stackSlot) {
|
||||
JS_ASSERT(stackSlot != InvalidStackSlot);
|
||||
Location loc;
|
||||
loc.reg_ = Register::Code(0); // Quell compiler warnings.
|
||||
loc.stackSlot_ = stackSlot;
|
||||
return loc;
|
||||
}
|
||||
|
||||
public:
|
||||
Register reg() const {
|
||||
JS_ASSERT(!isStackSlot());
|
||||
return Register::FromCode(reg_);
|
||||
}
|
||||
int32_t stackSlot() const {
|
||||
JS_ASSERT(isStackSlot());
|
||||
return stackSlot_;
|
||||
}
|
||||
bool isStackSlot() const {
|
||||
return stackSlot_ != InvalidStackSlot;
|
||||
}
|
||||
|
||||
void dump(FILE *fp) const;
|
||||
|
||||
public:
|
||||
bool operator==(const Location &l) const {
|
||||
return reg_ == l.reg_ && stackSlot_ == l.stackSlot_;
|
||||
}
|
||||
};
|
||||
|
||||
class Slot
|
||||
{
|
||||
public:
|
||||
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.
|
||||
UNTYPED, // Type is not known.
|
||||
JS_UNDEFINED, // UndefinedValue()
|
||||
JS_NULL, // NullValue()
|
||||
JS_INT32, // Int32Value(n)
|
||||
INVALID
|
||||
};
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
Slot(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;
|
||||
}
|
||||
Slot(Mode mode, const FloatRegister ®)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == FLOAT32_REG || mode == DOUBLE_REG);
|
||||
fpu_ = reg.code();
|
||||
}
|
||||
Slot(Mode mode, const Location &loc)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == FLOAT32_STACK);
|
||||
known_type_.payload = loc;
|
||||
}
|
||||
Slot(Mode mode, int32_t index)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == CONSTANT || mode == JS_INT32);
|
||||
value_ = index;
|
||||
}
|
||||
Slot(Mode mode)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == JS_UNDEFINED || mode == JS_NULL || mode == UNTYPED);
|
||||
}
|
||||
|
||||
public:
|
||||
Slot()
|
||||
: mode_(INVALID)
|
||||
{ }
|
||||
|
||||
// DOUBLE_REG
|
||||
static Slot DoubleSlot(const FloatRegister ®) {
|
||||
return Slot(DOUBLE_REG, reg);
|
||||
}
|
||||
|
||||
// FLOAT32_REG or FLOAT32_STACK
|
||||
static Slot Float32Slot(const FloatRegister ®) {
|
||||
return Slot(FLOAT32_REG, reg);
|
||||
}
|
||||
static Slot Float32Slot(int32_t stackIndex) {
|
||||
return Slot(FLOAT32_STACK, Location::From(stackIndex));
|
||||
}
|
||||
|
||||
// TYPED_REG or TYPED_STACK
|
||||
static Slot TypedSlot(JSValueType type, const Register ®) {
|
||||
JS_ASSERT(type != JSVAL_TYPE_DOUBLE &&
|
||||
type != JSVAL_TYPE_MAGIC &&
|
||||
type != JSVAL_TYPE_NULL &&
|
||||
type != JSVAL_TYPE_UNDEFINED);
|
||||
return Slot(TYPED_REG, type, Location::From(reg));
|
||||
}
|
||||
static Slot TypedSlot(JSValueType type, int32_t stackIndex) {
|
||||
JS_ASSERT(type != JSVAL_TYPE_MAGIC &&
|
||||
type != JSVAL_TYPE_NULL &&
|
||||
type != JSVAL_TYPE_UNDEFINED);
|
||||
return Slot(TYPED_STACK, type, Location::From(stackIndex));
|
||||
}
|
||||
|
||||
// UNTYPED
|
||||
#if defined(JS_NUNBOX32)
|
||||
static Slot UntypedSlot(const Register &type, const Register &payload) {
|
||||
Slot slot(UNTYPED);
|
||||
slot.unknown_type_.type = Location::From(type);
|
||||
slot.unknown_type_.payload = Location::From(payload);
|
||||
return slot;
|
||||
}
|
||||
|
||||
static Slot UntypedSlot(const Register &type, int32_t payloadStackIndex) {
|
||||
Slot slot(UNTYPED);
|
||||
slot.unknown_type_.type = Location::From(type);
|
||||
slot.unknown_type_.payload = Location::From(payloadStackIndex);
|
||||
return slot;
|
||||
}
|
||||
|
||||
static Slot UntypedSlot(int32_t typeStackIndex, const Register &payload) {
|
||||
Slot slot(UNTYPED);
|
||||
slot.unknown_type_.type = Location::From(typeStackIndex);
|
||||
slot.unknown_type_.payload = Location::From(payload);
|
||||
return slot;
|
||||
}
|
||||
|
||||
static Slot UntypedSlot(int32_t typeStackIndex, int32_t payloadStackIndex) {
|
||||
Slot slot(UNTYPED);
|
||||
slot.unknown_type_.type = Location::From(typeStackIndex);
|
||||
slot.unknown_type_.payload = Location::From(payloadStackIndex);
|
||||
return slot;
|
||||
}
|
||||
|
||||
#elif defined(JS_PUNBOX64)
|
||||
static Slot UntypedSlot(const Register &value) {
|
||||
Slot slot(UNTYPED);
|
||||
slot.unknown_type_.value = Location::From(value);
|
||||
return slot;
|
||||
}
|
||||
|
||||
static Slot UntypedSlot(int32_t valueStackSlot) {
|
||||
Slot slot(UNTYPED);
|
||||
slot.unknown_type_.value = Location::From(valueStackSlot);
|
||||
return slot;
|
||||
}
|
||||
#endif
|
||||
|
||||
// common constants.
|
||||
static Slot UndefinedSlot() {
|
||||
return Slot(JS_UNDEFINED);
|
||||
}
|
||||
static Slot NullSlot() {
|
||||
return Slot(JS_NULL);
|
||||
}
|
||||
|
||||
// JS_INT32
|
||||
static Slot Int32Slot(int32_t value) {
|
||||
return Slot(JS_INT32, value);
|
||||
}
|
||||
|
||||
// CONSTANT's index
|
||||
static Slot ConstantPoolSlot(uint32_t index) {
|
||||
return Slot(CONSTANT, int32_t(index));
|
||||
}
|
||||
|
||||
void writeSlotHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const;
|
||||
public:
|
||||
static Slot read(CompactBufferReader &reader);
|
||||
void write(CompactBufferWriter &writer) const;
|
||||
|
||||
public:
|
||||
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_);
|
||||
}
|
||||
int32_t stackSlot() const {
|
||||
JS_ASSERT(mode() == TYPED_STACK || mode() == FLOAT32_STACK);
|
||||
return known_type_.payload.stackSlot();
|
||||
}
|
||||
#if defined(JS_NUNBOX32)
|
||||
Location payload() const {
|
||||
JS_ASSERT(mode() == UNTYPED);
|
||||
return unknown_type_.payload;
|
||||
}
|
||||
Location type() const {
|
||||
JS_ASSERT(mode() == UNTYPED);
|
||||
return unknown_type_.type;
|
||||
}
|
||||
#elif defined(JS_PUNBOX64)
|
||||
Location value() const {
|
||||
JS_ASSERT(mode() == UNTYPED);
|
||||
return unknown_type_.value;
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
const char *modeToString() const;
|
||||
void dump(FILE *fp) const;
|
||||
void dump() const;
|
||||
|
||||
public:
|
||||
bool operator==(const Slot &s) const {
|
||||
if (mode_ != s.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;
|
||||
case UNTYPED:
|
||||
#if defined(JS_NUNBOX32)
|
||||
return unknown_type_.type == s.unknown_type_.type &&
|
||||
unknown_type_.payload == s.unknown_type_.payload;
|
||||
#else
|
||||
return unknown_type_.value == s.unknown_type_.value;
|
||||
#endif
|
||||
case CONSTANT:
|
||||
case JS_INT32:
|
||||
return value_ == s.value_;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // jit_Slot_h
|
|
@ -11,6 +11,7 @@
|
|||
#include "jit/IonCode.h"
|
||||
#include "jit/IonTypes.h"
|
||||
#include "jit/Registers.h"
|
||||
#include "jit/Slot.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
@ -50,162 +51,6 @@ class SnapshotReader
|
|||
void readSnapshotHeader();
|
||||
void readFrameHeader();
|
||||
|
||||
public:
|
||||
enum SlotMode
|
||||
{
|
||||
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.
|
||||
UNTYPED, // Type is not known.
|
||||
JS_UNDEFINED, // UndefinedValue()
|
||||
JS_NULL, // NullValue()
|
||||
JS_INT32 // Int32Value(n)
|
||||
};
|
||||
|
||||
class Location
|
||||
{
|
||||
friend class SnapshotReader;
|
||||
|
||||
// An offset that is illegal for a local variable's stack allocation.
|
||||
static const int32_t InvalidStackSlot = -1;
|
||||
|
||||
Register::Code reg_;
|
||||
int32_t stackSlot_;
|
||||
|
||||
static Location From(const Register ®) {
|
||||
Location loc;
|
||||
loc.reg_ = reg.code();
|
||||
loc.stackSlot_ = InvalidStackSlot;
|
||||
return loc;
|
||||
}
|
||||
static Location From(int32_t stackSlot) {
|
||||
JS_ASSERT(stackSlot != InvalidStackSlot);
|
||||
Location loc;
|
||||
loc.reg_ = Register::Code(0); // Quell compiler warnings.
|
||||
loc.stackSlot_ = stackSlot;
|
||||
return loc;
|
||||
}
|
||||
|
||||
public:
|
||||
Register reg() const {
|
||||
JS_ASSERT(!isStackSlot());
|
||||
return Register::FromCode(reg_);
|
||||
}
|
||||
int32_t stackSlot() const {
|
||||
JS_ASSERT(isStackSlot());
|
||||
return stackSlot_;
|
||||
}
|
||||
bool isStackSlot() const {
|
||||
return stackSlot_ != InvalidStackSlot;
|
||||
}
|
||||
};
|
||||
|
||||
class Slot
|
||||
{
|
||||
friend class SnapshotReader;
|
||||
|
||||
SlotMode mode_;
|
||||
|
||||
union {
|
||||
FloatRegister::Code fpu_;
|
||||
struct {
|
||||
JSValueType type;
|
||||
Location payload;
|
||||
} known_type_;
|
||||
#if defined(JS_NUNBOX32)
|
||||
struct {
|
||||
Location type;
|
||||
Location payload;
|
||||
} unknown_type_;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
struct {
|
||||
Location value;
|
||||
} unknown_type_;
|
||||
#endif
|
||||
int32_t value_;
|
||||
};
|
||||
|
||||
Slot(SlotMode mode, JSValueType type, const Location &loc)
|
||||
: mode_(mode)
|
||||
{
|
||||
known_type_.type = type;
|
||||
known_type_.payload = loc;
|
||||
}
|
||||
Slot(const FloatRegister ®)
|
||||
: mode_(DOUBLE_REG)
|
||||
{
|
||||
fpu_ = reg.code();
|
||||
}
|
||||
Slot(SlotMode mode, const FloatRegister ®)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == FLOAT32_REG);
|
||||
fpu_ = reg.code();
|
||||
}
|
||||
Slot(SlotMode mode, const Location &loc)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == FLOAT32_STACK);
|
||||
known_type_.payload = loc;
|
||||
}
|
||||
Slot(SlotMode mode)
|
||||
: mode_(mode)
|
||||
{ }
|
||||
Slot(SlotMode mode, uint32_t index)
|
||||
: mode_(mode)
|
||||
{
|
||||
JS_ASSERT(mode == CONSTANT || mode == JS_INT32);
|
||||
value_ = index;
|
||||
}
|
||||
|
||||
public:
|
||||
SlotMode 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_);
|
||||
}
|
||||
int32_t stackSlot() const {
|
||||
JS_ASSERT(mode() == TYPED_STACK || mode() == FLOAT32_STACK);
|
||||
return known_type_.payload.stackSlot();
|
||||
}
|
||||
#if defined(JS_NUNBOX32)
|
||||
Location payload() const {
|
||||
JS_ASSERT(mode() == UNTYPED);
|
||||
return unknown_type_.payload;
|
||||
}
|
||||
Location type() const {
|
||||
JS_ASSERT(mode() == UNTYPED);
|
||||
return unknown_type_.type;
|
||||
}
|
||||
#elif defined(JS_PUNBOX64)
|
||||
Location value() const {
|
||||
JS_ASSERT(mode() == UNTYPED);
|
||||
return unknown_type_.value;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
public:
|
||||
SnapshotReader(const uint8_t *buffer, const uint8_t *end);
|
||||
|
||||
|
|
|
@ -40,24 +40,8 @@ class SnapshotWriter
|
|||
#endif
|
||||
void endFrame();
|
||||
|
||||
void addSlot(const FloatRegister ®);
|
||||
void addSlot(JSValueType type, const Register ®);
|
||||
void addSlot(JSValueType type, int32_t stackIndex);
|
||||
void addUndefinedSlot();
|
||||
void addNullSlot();
|
||||
void addInt32Slot(int32_t value);
|
||||
void addFloat32Slot(const FloatRegister ®);
|
||||
void addFloat32Slot(int32_t stackIndex);
|
||||
void addConstantPoolSlot(uint32_t index);
|
||||
#if defined(JS_NUNBOX32)
|
||||
void addSlot(const Register &type, const Register &payload);
|
||||
void addSlot(const Register &type, int32_t payloadStackIndex);
|
||||
void addSlot(int32_t typeStackIndex, const Register &payload);
|
||||
void addSlot(int32_t typeStackIndex, int32_t payloadStackIndex);
|
||||
#elif defined(JS_PUNBOX64)
|
||||
void addSlot(const Register &value);
|
||||
void addSlot(int32_t valueStackSlot);
|
||||
#endif
|
||||
void addSlot(const Slot &slot);
|
||||
|
||||
void endSnapshot();
|
||||
|
||||
bool oom() const {
|
||||
|
|
|
@ -90,7 +90,7 @@ using namespace js::jit;
|
|||
// offset containing a Value.
|
||||
//
|
||||
// Otherwise, "reg" is a register containing a Value.
|
||||
//
|
||||
//
|
||||
|
||||
SnapshotReader::SnapshotReader(const uint8_t *buffer, const uint8_t *end)
|
||||
: reader_(buffer, end),
|
||||
|
@ -163,116 +163,13 @@ SnapshotReader::spewBailingFrom() const
|
|||
}
|
||||
#endif
|
||||
|
||||
#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;
|
||||
#endif
|
||||
|
||||
static const uint32_t MAX_TYPE_FIELD_VALUE = 7;
|
||||
|
||||
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;
|
||||
|
||||
SnapshotReader::Slot
|
||||
Slot
|
||||
SnapshotReader::readSlot()
|
||||
{
|
||||
JS_ASSERT(slotsRead_ < slotCount_);
|
||||
IonSpew(IonSpew_Snapshots, "Reading slot %u", slotsRead_);
|
||||
slotsRead_++;
|
||||
|
||||
uint8_t b = reader_.readByte();
|
||||
|
||||
JSValueType type = JSValueType(b & 0x7);
|
||||
uint32_t code = b >> 3;
|
||||
|
||||
switch (type) {
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
if (code < MIN_REG_FIELD_ESC)
|
||||
return Slot(FloatRegister::FromCode(code));
|
||||
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
|
||||
return Slot(TYPED_STACK, type, Location::From(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 Slot(TYPED_REG, type, Location::From(Register::FromCode(code)));
|
||||
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
|
||||
return Slot(TYPED_STACK, type, Location::From(reader_.readSigned()));
|
||||
|
||||
case JSVAL_TYPE_NULL:
|
||||
if (code == ESC_REG_FIELD_CONST)
|
||||
return Slot(JS_NULL);
|
||||
if (code == ESC_REG_FIELD_INDEX)
|
||||
return Slot(JS_INT32, reader_.readSigned());
|
||||
if (code == ESC_REG_FIELD_FLOAT32_REG)
|
||||
return Slot(FLOAT32_REG, FloatRegister::FromCode(reader_.readUnsigned()));
|
||||
if (code == ESC_REG_FIELD_FLOAT32_STACK)
|
||||
return Slot(FLOAT32_STACK, Location::From(reader_.readSigned()));
|
||||
return Slot(JS_INT32, code);
|
||||
|
||||
case JSVAL_TYPE_UNDEFINED:
|
||||
if (code == ESC_REG_FIELD_CONST)
|
||||
return Slot(JS_UNDEFINED);
|
||||
if (code == ESC_REG_FIELD_INDEX)
|
||||
return Slot(CONSTANT, reader_.readUnsigned());
|
||||
return Slot(CONSTANT, code);
|
||||
|
||||
default:
|
||||
{
|
||||
JS_ASSERT(type == JSVAL_TYPE_MAGIC);
|
||||
|
||||
if (code == ESC_REG_FIELD_CONST) {
|
||||
uint8_t reg2 = reader_.readUnsigned();
|
||||
Location loc;
|
||||
if (reg2 != ESC_REG_FIELD_INDEX)
|
||||
loc = Location::From(Register::FromCode(reg2));
|
||||
else
|
||||
loc = Location::From(reader_.readSigned());
|
||||
return Slot(TYPED_REG, type, loc);
|
||||
}
|
||||
|
||||
Slot slot(UNTYPED);
|
||||
#ifdef JS_NUNBOX32
|
||||
switch (code) {
|
||||
case NUNBOX32_STACK_STACK:
|
||||
slot.unknown_type_.type = Location::From(reader_.readSigned());
|
||||
slot.unknown_type_.payload = Location::From(reader_.readSigned());
|
||||
return slot;
|
||||
case NUNBOX32_STACK_REG:
|
||||
slot.unknown_type_.type = Location::From(reader_.readSigned());
|
||||
slot.unknown_type_.payload = Location::From(Register::FromCode(reader_.readByte()));
|
||||
return slot;
|
||||
case NUNBOX32_REG_STACK:
|
||||
slot.unknown_type_.type = Location::From(Register::FromCode(reader_.readByte()));
|
||||
slot.unknown_type_.payload = Location::From(reader_.readSigned());
|
||||
return slot;
|
||||
default:
|
||||
JS_ASSERT(code == NUNBOX32_REG_REG);
|
||||
slot.unknown_type_.type = Location::From(Register::FromCode(reader_.readByte()));
|
||||
slot.unknown_type_.payload = Location::From(Register::FromCode(reader_.readByte()));
|
||||
return slot;
|
||||
}
|
||||
#elif JS_PUNBOX64
|
||||
if (code < MIN_REG_FIELD_ESC) {
|
||||
slot.unknown_type_.value = Location::From(Register::FromCode(code));
|
||||
} else {
|
||||
JS_ASSERT(code == ESC_REG_FIELD_INDEX);
|
||||
slot.unknown_type_.value = Location::From(reader_.readSigned());
|
||||
}
|
||||
return slot;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("huh?");
|
||||
return Slot::read(reader_);
|
||||
}
|
||||
|
||||
SnapshotOffset
|
||||
|
@ -334,6 +231,21 @@ SnapshotWriter::trackFrame(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(const Slot &slot)
|
||||
{
|
||||
if (IonSpewEnabled(IonSpew_Snapshots)) {
|
||||
IonSpewHeader(IonSpew_Snapshots);
|
||||
fprintf(IonSpewFile, " slot %u: ", slotsWritten_);
|
||||
slot.dump(IonSpewFile);
|
||||
fprintf(IonSpewFile, "\n");
|
||||
}
|
||||
|
||||
slotsWritten_++;
|
||||
JS_ASSERT(slotsWritten_ <= nslots_);
|
||||
slot.write(writer_);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::endFrame()
|
||||
{
|
||||
|
@ -343,150 +255,6 @@ SnapshotWriter::endFrame()
|
|||
framesWritten_++;
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::writeSlotHeader(JSValueType type, uint32_t regCode)
|
||||
{
|
||||
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);
|
||||
|
||||
uint8_t byte = uint32_t(type) | (regCode << 3);
|
||||
writer_.writeByte(byte);
|
||||
|
||||
slotsWritten_++;
|
||||
JS_ASSERT(slotsWritten_ <= nslots_);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(const FloatRegister ®)
|
||||
{
|
||||
JS_ASSERT(uint32_t(reg.code()) < MIN_REG_FIELD_ESC);
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: double (reg %s)", slotsWritten_, reg.name());
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_DOUBLE, reg.code());
|
||||
}
|
||||
|
||||
static const char *
|
||||
ValTypeToString(JSValueType type)
|
||||
{
|
||||
switch (type) {
|
||||
case JSVAL_TYPE_INT32:
|
||||
return "int32_t";
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
return "double";
|
||||
case JSVAL_TYPE_STRING:
|
||||
return "string";
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
return "boolean";
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
return "object";
|
||||
case JSVAL_TYPE_MAGIC:
|
||||
return "magic";
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("no payload");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(JSValueType type, const Register ®)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: %s (%s)",
|
||||
slotsWritten_, ValTypeToString(type), reg.name());
|
||||
|
||||
JS_ASSERT(type != JSVAL_TYPE_DOUBLE);
|
||||
writeSlotHeader(type, reg.code());
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(JSValueType type, int32_t stackIndex)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: %s (stack %d)",
|
||||
slotsWritten_, ValTypeToString(type), stackIndex);
|
||||
|
||||
writeSlotHeader(type, ESC_REG_FIELD_INDEX);
|
||||
writer_.writeSigned(stackIndex);
|
||||
}
|
||||
|
||||
#if defined(JS_NUNBOX32)
|
||||
void
|
||||
SnapshotWriter::addSlot(const Register &type, const Register &payload)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: value (t=%s, d=%s)",
|
||||
slotsWritten_, type.name(), payload.name());
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_MAGIC, NUNBOX32_REG_REG);
|
||||
writer_.writeByte(type.code());
|
||||
writer_.writeByte(payload.code());
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(const Register &type, int32_t payloadStackIndex)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: value (t=%s, d=%d)",
|
||||
slotsWritten_, type.name(), payloadStackIndex);
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_MAGIC, NUNBOX32_REG_STACK);
|
||||
writer_.writeByte(type.code());
|
||||
writer_.writeSigned(payloadStackIndex);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(int32_t typeStackIndex, const Register &payload)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: value (t=%d, d=%s)",
|
||||
slotsWritten_, typeStackIndex, payload.name());
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_MAGIC, NUNBOX32_STACK_REG);
|
||||
writer_.writeSigned(typeStackIndex);
|
||||
writer_.writeByte(payload.code());
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(int32_t typeStackIndex, int32_t payloadStackIndex)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: value (t=%d, d=%d)",
|
||||
slotsWritten_, typeStackIndex, payloadStackIndex);
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_MAGIC, NUNBOX32_STACK_STACK);
|
||||
writer_.writeSigned(typeStackIndex);
|
||||
writer_.writeSigned(payloadStackIndex);
|
||||
}
|
||||
|
||||
#elif defined(JS_PUNBOX64)
|
||||
void
|
||||
SnapshotWriter::addSlot(const Register &value)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: value (reg %s)", slotsWritten_, value.name());
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_MAGIC, value.code());
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addSlot(int32_t valueStackSlot)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: value (stack %d)", slotsWritten_, valueStackSlot);
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_MAGIC, ESC_REG_FIELD_INDEX);
|
||||
writer_.writeSigned(valueStackSlot);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
SnapshotWriter::addUndefinedSlot()
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: undefined", slotsWritten_);
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_CONST);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addNullSlot()
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: null", slotsWritten_);
|
||||
|
||||
writeSlotHeader(JSVAL_TYPE_NULL, ESC_REG_FIELD_CONST);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::endSnapshot()
|
||||
{
|
||||
|
@ -500,47 +268,3 @@ SnapshotWriter::endSnapshot()
|
|||
IonSpew(IonSpew_Snapshots, "ending snapshot total size: %u bytes (start %u)",
|
||||
uint32_t(writer_.length() - lastStart_), lastStart_);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addInt32Slot(int32_t value)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: int32_t %d", slotsWritten_, value);
|
||||
|
||||
if (value >= 0 && uint32_t(value) < MIN_REG_FIELD_ESC) {
|
||||
writeSlotHeader(JSVAL_TYPE_NULL, value);
|
||||
} else {
|
||||
writeSlotHeader(JSVAL_TYPE_NULL, ESC_REG_FIELD_INDEX);
|
||||
writer_.writeSigned(value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addFloat32Slot(const FloatRegister ®)
|
||||
{
|
||||
JS_ASSERT(uint32_t(reg.code()) < MIN_REG_FIELD_ESC);
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: float32 (reg %s)", slotsWritten_, reg.name());
|
||||
writeSlotHeader(JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_REG);
|
||||
writer_.writeUnsigned(reg.code());
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addFloat32Slot(int32_t stackIndex)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: float32 (stack %d)", slotsWritten_, stackIndex);
|
||||
writeSlotHeader(JSVAL_TYPE_NULL, ESC_REG_FIELD_FLOAT32_STACK);
|
||||
writer_.writeSigned(stackIndex);
|
||||
}
|
||||
|
||||
void
|
||||
SnapshotWriter::addConstantPoolSlot(uint32_t index)
|
||||
{
|
||||
IonSpew(IonSpew_Snapshots, " slot %u: constant pool index %u", slotsWritten_, index);
|
||||
|
||||
if (index < MIN_REG_FIELD_ESC) {
|
||||
writeSlotHeader(JSVAL_TYPE_UNDEFINED, index);
|
||||
} else {
|
||||
writeSlotHeader(JSVAL_TYPE_UNDEFINED, ESC_REG_FIELD_INDEX);
|
||||
writer_.writeUnsigned(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -147,12 +147,14 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint,
|
|||
? MIRType_Undefined
|
||||
: mir->type();
|
||||
|
||||
Slot s;
|
||||
|
||||
switch (type) {
|
||||
case MIRType_Undefined:
|
||||
snapshots_.addUndefinedSlot();
|
||||
s = Slot::UndefinedSlot();
|
||||
break;
|
||||
case MIRType_Null:
|
||||
snapshots_.addNullSlot();
|
||||
s = Slot::NullSlot();
|
||||
break;
|
||||
case MIRType_Int32:
|
||||
case MIRType_String:
|
||||
|
@ -165,29 +167,29 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint,
|
|||
JSValueType valueType = ValueTypeFromMIRType(type);
|
||||
if (payload->isMemory()) {
|
||||
if (type == MIRType_Float32)
|
||||
snapshots_.addFloat32Slot(ToStackIndex(payload));
|
||||
s = Slot::Float32Slot(ToStackIndex(payload));
|
||||
else
|
||||
snapshots_.addSlot(valueType, ToStackIndex(payload));
|
||||
s = Slot::TypedSlot(valueType, ToStackIndex(payload));
|
||||
} else if (payload->isGeneralReg()) {
|
||||
snapshots_.addSlot(valueType, ToRegister(payload));
|
||||
s = Slot::TypedSlot(valueType, ToRegister(payload));
|
||||
} else if (payload->isFloatReg()) {
|
||||
FloatRegister reg = ToFloatRegister(payload);
|
||||
if (type == MIRType_Float32)
|
||||
snapshots_.addFloat32Slot(reg);
|
||||
s = Slot::Float32Slot(reg);
|
||||
else
|
||||
snapshots_.addSlot(reg);
|
||||
s = Slot::DoubleSlot(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) {
|
||||
snapshots_.addInt32Slot(v.toInt32());
|
||||
s = Slot::Int32Slot(v.toInt32());
|
||||
} else {
|
||||
uint32_t index;
|
||||
if (!graph.addConstantToPool(constant->value(), &index))
|
||||
return false;
|
||||
snapshots_.addConstantPoolSlot(index);
|
||||
s = Slot::ConstantPoolSlot(index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -197,7 +199,7 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint,
|
|||
uint32_t index;
|
||||
if (!graph.addConstantToPool(MagicValue(JS_OPTIMIZED_ARGUMENTS), &index))
|
||||
return false;
|
||||
snapshots_.addConstantPoolSlot(index);
|
||||
s = Slot::ConstantPoolSlot(index);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -208,24 +210,26 @@ CodeGeneratorShared::encodeSlots(LSnapshot *snapshot, MResumePoint *resumePoint,
|
|||
LAllocation *type = snapshot->typeOfSlot(i);
|
||||
if (type->isRegister()) {
|
||||
if (payload->isRegister())
|
||||
snapshots_.addSlot(ToRegister(type), ToRegister(payload));
|
||||
s = Slot::UntypedSlot(ToRegister(type), ToRegister(payload));
|
||||
else
|
||||
snapshots_.addSlot(ToRegister(type), ToStackIndex(payload));
|
||||
s = Slot::UntypedSlot(ToRegister(type), ToStackIndex(payload));
|
||||
} else {
|
||||
if (payload->isRegister())
|
||||
snapshots_.addSlot(ToStackIndex(type), ToRegister(payload));
|
||||
s = Slot::UntypedSlot(ToStackIndex(type), ToRegister(payload));
|
||||
else
|
||||
snapshots_.addSlot(ToStackIndex(type), ToStackIndex(payload));
|
||||
s = Slot::UntypedSlot(ToStackIndex(type), ToStackIndex(payload));
|
||||
}
|
||||
#elif JS_PUNBOX64
|
||||
if (payload->isRegister())
|
||||
snapshots_.addSlot(ToRegister(payload));
|
||||
s = Slot::UntypedSlot(ToRegister(payload));
|
||||
else
|
||||
snapshots_.addSlot(ToStackIndex(payload));
|
||||
s = Slot::UntypedSlot(ToStackIndex(payload));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snapshots_.addSlot(s);
|
||||
}
|
||||
|
||||
*startIndex += resumePoint->numOperands();
|
||||
|
|
|
@ -41,6 +41,7 @@ UNIFIED_SOURCES += [
|
|||
'testIntern.cpp',
|
||||
'testIntString.cpp',
|
||||
'testIntTypesABI.cpp',
|
||||
'testJitSlot.cpp',
|
||||
'testJSEvaluateScript.cpp',
|
||||
'testLookup.cpp',
|
||||
'testLooselyEqual.cpp',
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jit/CompactBuffer.h"
|
||||
#include "jit/Slot.h"
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
// These tests are checking that all slots of the current architecture can all
|
||||
// be encoded and decoded correctly. We iterate on all registers and on many
|
||||
// fake stack locations (Fibonacci).
|
||||
static Slot
|
||||
ReadSlot(const Slot &slot)
|
||||
{
|
||||
CompactBufferWriter writer;
|
||||
slot.write(writer);
|
||||
|
||||
CompactBufferReader reader(writer);
|
||||
return Slot::read(reader);
|
||||
}
|
||||
|
||||
BEGIN_TEST(testJitSlot_Double)
|
||||
{
|
||||
Slot s;
|
||||
for (uint32_t i = 0; i < FloatRegisters::Total; i++) {
|
||||
s = Slot::DoubleSlot(FloatRegister::FromCode(i));
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_Double)
|
||||
|
||||
BEGIN_TEST(testJitSlot_FloatReg)
|
||||
{
|
||||
Slot s;
|
||||
for (uint32_t i = 0; i < FloatRegisters::Total; i++) {
|
||||
s = Slot::Float32Slot(FloatRegister::FromCode(i));
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_FloatReg)
|
||||
|
||||
BEGIN_TEST(testJitSlot_FloatStack)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, last = 0, tmp;
|
||||
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
|
||||
s = Slot::Float32Slot(i);
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_FloatStack)
|
||||
|
||||
BEGIN_TEST(testJitSlot_TypedReg)
|
||||
{
|
||||
Slot s;
|
||||
for (uint32_t i = 0; i < Registers::Total; i++) {
|
||||
#define FOR_EACH_JSVAL(_) \
|
||||
/* _(JSVAL_TYPE_DOUBLE) */ \
|
||||
_(JSVAL_TYPE_INT32) \
|
||||
/* _(JSVAL_TYPE_UNDEFINED) */ \
|
||||
_(JSVAL_TYPE_BOOLEAN) \
|
||||
/* _(JSVAL_TYPE_MAGIC) */ \
|
||||
_(JSVAL_TYPE_STRING) \
|
||||
/* _(JSVAL_TYPE_NULL) */ \
|
||||
_(JSVAL_TYPE_OBJECT)
|
||||
|
||||
#define CHECK_WITH_JSVAL(jsval) \
|
||||
s = Slot::TypedSlot(jsval, Register::FromCode(i)); \
|
||||
CHECK(s == ReadSlot(s));
|
||||
|
||||
FOR_EACH_JSVAL(CHECK_WITH_JSVAL)
|
||||
#undef CHECK_WITH_JSVAL
|
||||
#undef FOR_EACH_JSVAL
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_TypedReg)
|
||||
|
||||
BEGIN_TEST(testJitSlot_TypedStack)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, last = 0, tmp;
|
||||
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
|
||||
#define FOR_EACH_JSVAL(_) \
|
||||
_(JSVAL_TYPE_DOUBLE) \
|
||||
_(JSVAL_TYPE_INT32) \
|
||||
/* _(JSVAL_TYPE_UNDEFINED) */ \
|
||||
_(JSVAL_TYPE_BOOLEAN) \
|
||||
/* _(JSVAL_TYPE_MAGIC) */ \
|
||||
_(JSVAL_TYPE_STRING) \
|
||||
/* _(JSVAL_TYPE_NULL) */ \
|
||||
_(JSVAL_TYPE_OBJECT)
|
||||
|
||||
#define CHECK_WITH_JSVAL(jsval) \
|
||||
s = Slot::TypedSlot(jsval, i); \
|
||||
CHECK(s == ReadSlot(s));
|
||||
|
||||
FOR_EACH_JSVAL(CHECK_WITH_JSVAL)
|
||||
#undef CHECK_WITH_JSVAL
|
||||
#undef FOR_EACH_JSVAL
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_TypedStack)
|
||||
|
||||
#if defined(JS_NUNBOX32)
|
||||
|
||||
BEGIN_TEST(testJitSlot_UntypedRegReg)
|
||||
{
|
||||
Slot s;
|
||||
for (uint32_t i = 0; i < Registers::Total; i++) {
|
||||
for (uint32_t j = 0; j < Registers::Total; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
s = Slot::UntypedSlot(Register::FromCode(i), Register::FromCode(j));
|
||||
MOZ_ASSERT(s == ReadSlot(s));
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UntypedRegReg)
|
||||
|
||||
BEGIN_TEST(testJitSlot_UntypedRegStack)
|
||||
{
|
||||
Slot s;
|
||||
for (uint32_t i = 0; i < Registers::Total; i++) {
|
||||
int32_t j, last = 0, tmp;
|
||||
for (j = 0; j > 0; tmp = j, j += last, last = tmp) {
|
||||
s = Slot::UntypedSlot(Register::FromCode(i), j);
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UntypedRegStack)
|
||||
|
||||
BEGIN_TEST(testJitSlot_UntypedStackReg)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, last = 0, tmp;
|
||||
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
|
||||
for (uint32_t j = 0; j < Registers::Total; j++) {
|
||||
s = Slot::UntypedSlot(i, Register::FromCode(j));
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UntypedStackReg)
|
||||
|
||||
BEGIN_TEST(testJitSlot_UntypedStackStack)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, li = 0, ti;
|
||||
for (i = 0; i > 0; ti = i, i += li, li = ti) {
|
||||
int32_t j, lj = 0, tj;
|
||||
for (j = 0; j > 0; tj = j, j += lj, lj = tj) {
|
||||
s = Slot::UntypedSlot(i, j);
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UntypedStackStack)
|
||||
|
||||
#else
|
||||
|
||||
BEGIN_TEST(testJitSlot_UntypedReg)
|
||||
{
|
||||
Slot s;
|
||||
for (uint32_t i = 0; i < Registers::Total; i++) {
|
||||
s = Slot::UntypedSlot(Register::FromCode(i));
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UntypedReg)
|
||||
|
||||
BEGIN_TEST(testJitSlot_UntypedStack)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, last = 0, tmp;
|
||||
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
|
||||
s = Slot::UntypedSlot(i);
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UntypedStack)
|
||||
|
||||
#endif
|
||||
|
||||
BEGIN_TEST(testJitSlot_UndefinedAndNull)
|
||||
{
|
||||
Slot s;
|
||||
s = Slot::UndefinedSlot();
|
||||
CHECK(s == ReadSlot(s));
|
||||
s = Slot::NullSlot();
|
||||
CHECK(s == ReadSlot(s));
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_UndefinedAndNull)
|
||||
|
||||
BEGIN_TEST(testJitSlot_Int32)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, last = 0, tmp;
|
||||
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
|
||||
s = Slot::Int32Slot(i);
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_Int32)
|
||||
|
||||
BEGIN_TEST(testJitSlot_ConstantPool)
|
||||
{
|
||||
Slot s;
|
||||
int32_t i, last = 0, tmp;
|
||||
for (i = 0; i > 0; tmp = i, i += last, last = tmp) {
|
||||
s = Slot::ConstantPoolSlot(i);
|
||||
CHECK(s == ReadSlot(s));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitSlot_ConstantPool)
|
|
@ -273,6 +273,7 @@ if CONFIG['ENABLE_ION']:
|
|||
'jit/shared/BaselineCompiler-shared.cpp',
|
||||
'jit/shared/CodeGenerator-shared.cpp',
|
||||
'jit/shared/Lowering-shared.cpp',
|
||||
'jit/Slot.cpp',
|
||||
'jit/Snapshots.cpp',
|
||||
'jit/StupidAllocator.cpp',
|
||||
'jit/TypePolicy.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче