Allow more virtual registers to be encoded in LUnallocated.
This is a preparation which allows us to bump the virtual register width from 15 to 18 bit without sacrificing width for other fields inside an unallocated lithium operand. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/14639008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14513 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c092da378b
commit
47608c900a
@ -2453,7 +2453,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
|
||||
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
|
||||
if (spill_index > LUnallocated::kMaxFixedIndex) {
|
||||
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
|
||||
Abort("Too many spill slots needed for OSR");
|
||||
spill_index = 0;
|
||||
}
|
||||
|
@ -299,14 +299,14 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
|
||||
//
|
||||
// The encoding is as a signed value, with parameters and receiver using
|
||||
// the negative indices and locals the non-negative ones.
|
||||
const int parameter_limit = -LUnallocated::kMinFixedIndex;
|
||||
const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
|
||||
Scope* scope = info()->scope();
|
||||
if ((scope->num_parameters() + 1) > parameter_limit) {
|
||||
info()->set_bailout_reason("too many parameters");
|
||||
return AbortOptimization();
|
||||
}
|
||||
|
||||
const int locals_limit = LUnallocated::kMaxFixedIndex;
|
||||
const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
|
||||
if (!info()->osr_ast_id().IsNone() &&
|
||||
scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
|
||||
info()->set_bailout_reason("too many parameters/locals");
|
||||
|
@ -2584,7 +2584,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
|
||||
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
|
||||
if (spill_index > LUnallocated::kMaxFixedIndex) {
|
||||
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
|
||||
Abort("Too many spill slots needed for OSR");
|
||||
spill_index = 0;
|
||||
}
|
||||
|
@ -625,13 +625,13 @@ LOperand* LAllocator::AllocateFixed(LUnallocated* operand,
|
||||
bool is_tagged) {
|
||||
TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register());
|
||||
ASSERT(operand->HasFixedPolicy());
|
||||
if (operand->policy() == LUnallocated::FIXED_SLOT) {
|
||||
operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_index());
|
||||
} else if (operand->policy() == LUnallocated::FIXED_REGISTER) {
|
||||
int reg_index = operand->fixed_index();
|
||||
if (operand->HasFixedSlotPolicy()) {
|
||||
operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_slot_index());
|
||||
} else if (operand->HasFixedRegisterPolicy()) {
|
||||
int reg_index = operand->fixed_register_index();
|
||||
operand->ConvertTo(LOperand::REGISTER, reg_index);
|
||||
} else if (operand->policy() == LUnallocated::FIXED_DOUBLE_REGISTER) {
|
||||
int reg_index = operand->fixed_index();
|
||||
} else if (operand->HasFixedDoubleRegisterPolicy()) {
|
||||
int reg_index = operand->fixed_register_index();
|
||||
operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
@ -846,7 +846,7 @@ void LAllocator::MeetConstraintsBetween(LInstruction* first,
|
||||
bool is_tagged = HasTaggedValue(cur_input->virtual_register());
|
||||
AllocateFixed(cur_input, gap_index + 1, is_tagged);
|
||||
AddConstraintsGapMove(gap_index, input_copy, cur_input);
|
||||
} else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) {
|
||||
} else if (cur_input->HasWritableRegisterPolicy()) {
|
||||
// The live range of writable input registers always goes until the end
|
||||
// of the instruction.
|
||||
ASSERT(!cur_input->IsUsedAtStart());
|
||||
|
@ -58,24 +58,27 @@ void LOperand::PrintTo(StringStream* stream) {
|
||||
case UNALLOCATED:
|
||||
unalloc = LUnallocated::cast(this);
|
||||
stream->Add("v%d", unalloc->virtual_register());
|
||||
switch (unalloc->policy()) {
|
||||
if (unalloc->basic_policy() == LUnallocated::FIXED_SLOT) {
|
||||
stream->Add("(=%dS)", unalloc->fixed_slot_index());
|
||||
break;
|
||||
}
|
||||
switch (unalloc->extended_policy()) {
|
||||
case LUnallocated::NONE:
|
||||
break;
|
||||
case LUnallocated::FIXED_REGISTER: {
|
||||
int reg_index = unalloc->fixed_register_index();
|
||||
const char* register_name =
|
||||
Register::AllocationIndexToString(unalloc->fixed_index());
|
||||
Register::AllocationIndexToString(reg_index);
|
||||
stream->Add("(=%s)", register_name);
|
||||
break;
|
||||
}
|
||||
case LUnallocated::FIXED_DOUBLE_REGISTER: {
|
||||
int reg_index = unalloc->fixed_register_index();
|
||||
const char* double_register_name =
|
||||
DoubleRegister::AllocationIndexToString(unalloc->fixed_index());
|
||||
DoubleRegister::AllocationIndexToString(reg_index);
|
||||
stream->Add("(=%s)", double_register_name);
|
||||
break;
|
||||
}
|
||||
case LUnallocated::FIXED_SLOT:
|
||||
stream->Add("(=%dS)", unalloc->fixed_index());
|
||||
break;
|
||||
case LUnallocated::MUST_HAVE_REGISTER:
|
||||
stream->Add("(R)");
|
||||
break;
|
||||
|
206
src/lithium.h
206
src/lithium.h
@ -92,12 +92,16 @@ class LOperand: public ZoneObject {
|
||||
|
||||
class LUnallocated: public LOperand {
|
||||
public:
|
||||
enum Policy {
|
||||
enum BasicPolicy {
|
||||
FIXED_SLOT,
|
||||
EXTENDED_POLICY
|
||||
};
|
||||
|
||||
enum ExtendedPolicy {
|
||||
NONE,
|
||||
ANY,
|
||||
FIXED_REGISTER,
|
||||
FIXED_DOUBLE_REGISTER,
|
||||
FIXED_SLOT,
|
||||
MUST_HAVE_REGISTER,
|
||||
WRITABLE_REGISTER,
|
||||
SAME_AS_FIRST_INPUT
|
||||
@ -117,76 +121,32 @@ class LUnallocated: public LOperand {
|
||||
USED_AT_END
|
||||
};
|
||||
|
||||
explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) {
|
||||
Initialize(policy, 0, USED_AT_END);
|
||||
explicit LUnallocated(ExtendedPolicy policy) : LOperand(UNALLOCATED, 0) {
|
||||
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
|
||||
value_ |= ExtendedPolicyField::encode(policy);
|
||||
value_ |= LifetimeField::encode(USED_AT_END);
|
||||
}
|
||||
|
||||
LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) {
|
||||
Initialize(policy, fixed_index, USED_AT_END);
|
||||
LUnallocated(BasicPolicy policy, int index) : LOperand(UNALLOCATED, 0) {
|
||||
ASSERT(policy == FIXED_SLOT);
|
||||
value_ |= BasicPolicyField::encode(policy);
|
||||
value_ |= index << FixedSlotIndexField::kShift;
|
||||
ASSERT(this->fixed_slot_index() == index);
|
||||
}
|
||||
|
||||
LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) {
|
||||
Initialize(policy, 0, lifetime);
|
||||
LUnallocated(ExtendedPolicy policy, int index) : LOperand(UNALLOCATED, 0) {
|
||||
ASSERT(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
|
||||
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
|
||||
value_ |= ExtendedPolicyField::encode(policy);
|
||||
value_ |= LifetimeField::encode(USED_AT_END);
|
||||
value_ |= FixedRegisterField::encode(index);
|
||||
}
|
||||
|
||||
// The superclass has a KindField. Some policies have a signed fixed
|
||||
// index in the upper bits.
|
||||
static const int kPolicyWidth = 3;
|
||||
static const int kLifetimeWidth = 1;
|
||||
static const int kVirtualRegisterWidth = 15;
|
||||
|
||||
static const int kPolicyShift = kKindFieldWidth;
|
||||
static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
|
||||
static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth;
|
||||
static const int kFixedIndexShift =
|
||||
kVirtualRegisterShift + kVirtualRegisterWidth;
|
||||
static const int kFixedIndexWidth = 32 - kFixedIndexShift;
|
||||
STATIC_ASSERT(kFixedIndexWidth > 5);
|
||||
|
||||
class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { };
|
||||
|
||||
class LifetimeField
|
||||
: public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> {
|
||||
};
|
||||
|
||||
class VirtualRegisterField
|
||||
: public BitField<unsigned,
|
||||
kVirtualRegisterShift,
|
||||
kVirtualRegisterWidth> {
|
||||
};
|
||||
|
||||
static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth;
|
||||
static const int kMaxFixedIndex = (1 << (kFixedIndexWidth - 1)) - 1;
|
||||
static const int kMinFixedIndex = -(1 << (kFixedIndexWidth - 1));
|
||||
|
||||
bool HasAnyPolicy() const {
|
||||
return policy() == ANY;
|
||||
}
|
||||
bool HasFixedPolicy() const {
|
||||
return policy() == FIXED_REGISTER ||
|
||||
policy() == FIXED_DOUBLE_REGISTER ||
|
||||
policy() == FIXED_SLOT;
|
||||
}
|
||||
bool HasRegisterPolicy() const {
|
||||
return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
|
||||
}
|
||||
bool HasSameAsInputPolicy() const {
|
||||
return policy() == SAME_AS_FIRST_INPUT;
|
||||
}
|
||||
Policy policy() const { return PolicyField::decode(value_); }
|
||||
void set_policy(Policy policy) {
|
||||
value_ = PolicyField::update(value_, policy);
|
||||
}
|
||||
int fixed_index() const {
|
||||
return static_cast<int>(value_) >> kFixedIndexShift;
|
||||
}
|
||||
|
||||
int virtual_register() const {
|
||||
return VirtualRegisterField::decode(value_);
|
||||
}
|
||||
|
||||
void set_virtual_register(unsigned id) {
|
||||
value_ = VirtualRegisterField::update(value_, id);
|
||||
LUnallocated(ExtendedPolicy policy, Lifetime lifetime)
|
||||
: LOperand(UNALLOCATED, 0) {
|
||||
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
|
||||
value_ |= ExtendedPolicyField::encode(policy);
|
||||
value_ |= LifetimeField::encode(lifetime);
|
||||
}
|
||||
|
||||
LUnallocated* CopyUnconstrained(Zone* zone) {
|
||||
@ -200,16 +160,114 @@ class LUnallocated: public LOperand {
|
||||
return reinterpret_cast<LUnallocated*>(op);
|
||||
}
|
||||
|
||||
bool IsUsedAtStart() {
|
||||
return LifetimeField::decode(value_) == USED_AT_START;
|
||||
// The encoding used for LUnallocated operands depends on the policy that is
|
||||
// stored within the operand. The FIXED_SLOT policy uses a compact encoding
|
||||
// because it accommodates a larger pay-load.
|
||||
//
|
||||
// For FIXED_SLOT policy:
|
||||
// +------------------------------------------+
|
||||
// | slot_index | vreg | 0 | 001 |
|
||||
// +------------------------------------------+
|
||||
//
|
||||
// For all other (extended) policies:
|
||||
// +------------------------------------------+
|
||||
// | reg_index | L | PPP | vreg | 1 | 001 | L ... Lifetime
|
||||
// +------------------------------------------+ P ... Policy
|
||||
//
|
||||
// The slot index is a signed value which requires us to decode it manually
|
||||
// instead of using the BitField utility class.
|
||||
|
||||
// The superclass has a KindField.
|
||||
STATIC_ASSERT(kKindFieldWidth == 3);
|
||||
|
||||
// BitFields for all unallocated operands.
|
||||
class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {};
|
||||
// TODO(mstarzinger): Bump this from 15 bit to 18 bit in a follow-up CL.
|
||||
class VirtualRegisterField : public BitField<unsigned, 4, 15> {};
|
||||
|
||||
// BitFields specific to BasicPolicy::FIXED_SLOT.
|
||||
class FixedSlotIndexField : public BitField<int, 22, 10> {};
|
||||
|
||||
// BitFields specific to BasicPolicy::EXTENDED_POLICY.
|
||||
class ExtendedPolicyField : public BitField<ExtendedPolicy, 22, 3> {};
|
||||
class LifetimeField : public BitField<Lifetime, 25, 1> {};
|
||||
class FixedRegisterField : public BitField<int, 26, 6> {};
|
||||
|
||||
static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1;
|
||||
static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize;
|
||||
static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
|
||||
static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
|
||||
|
||||
// Predicates for the operand policy.
|
||||
bool HasAnyPolicy() const {
|
||||
return basic_policy() == EXTENDED_POLICY &&
|
||||
extended_policy() == ANY;
|
||||
}
|
||||
bool HasFixedPolicy() const {
|
||||
return basic_policy() == FIXED_SLOT ||
|
||||
extended_policy() == FIXED_REGISTER ||
|
||||
extended_policy() == FIXED_DOUBLE_REGISTER;
|
||||
}
|
||||
bool HasRegisterPolicy() const {
|
||||
return basic_policy() == EXTENDED_POLICY && (
|
||||
extended_policy() == WRITABLE_REGISTER ||
|
||||
extended_policy() == MUST_HAVE_REGISTER);
|
||||
}
|
||||
bool HasSameAsInputPolicy() const {
|
||||
return basic_policy() == EXTENDED_POLICY &&
|
||||
extended_policy() == SAME_AS_FIRST_INPUT;
|
||||
}
|
||||
bool HasFixedSlotPolicy() const {
|
||||
return basic_policy() == FIXED_SLOT;
|
||||
}
|
||||
bool HasFixedRegisterPolicy() const {
|
||||
return basic_policy() == EXTENDED_POLICY &&
|
||||
extended_policy() == FIXED_REGISTER;
|
||||
}
|
||||
bool HasFixedDoubleRegisterPolicy() const {
|
||||
return basic_policy() == EXTENDED_POLICY &&
|
||||
extended_policy() == FIXED_DOUBLE_REGISTER;
|
||||
}
|
||||
bool HasWritableRegisterPolicy() const {
|
||||
return basic_policy() == EXTENDED_POLICY &&
|
||||
extended_policy() == WRITABLE_REGISTER;
|
||||
}
|
||||
|
||||
private:
|
||||
void Initialize(Policy policy, int fixed_index, Lifetime lifetime) {
|
||||
value_ |= PolicyField::encode(policy);
|
||||
value_ |= LifetimeField::encode(lifetime);
|
||||
value_ |= fixed_index << kFixedIndexShift;
|
||||
ASSERT(this->fixed_index() == fixed_index);
|
||||
// [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
|
||||
BasicPolicy basic_policy() const {
|
||||
return BasicPolicyField::decode(value_);
|
||||
}
|
||||
|
||||
// [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
|
||||
ExtendedPolicy extended_policy() const {
|
||||
ASSERT(basic_policy() == EXTENDED_POLICY);
|
||||
return ExtendedPolicyField::decode(value_);
|
||||
}
|
||||
|
||||
// [fixed_slot_index]: Only for FIXED_SLOT.
|
||||
int fixed_slot_index() const {
|
||||
ASSERT(HasFixedSlotPolicy());
|
||||
return static_cast<int>(value_) >> FixedSlotIndexField::kShift;
|
||||
}
|
||||
|
||||
// [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
|
||||
int fixed_register_index() const {
|
||||
ASSERT(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
|
||||
return FixedRegisterField::decode(value_);
|
||||
}
|
||||
|
||||
// [virtual_register]: The virtual register ID for this operand.
|
||||
int virtual_register() const {
|
||||
return VirtualRegisterField::decode(value_);
|
||||
}
|
||||
void set_virtual_register(unsigned id) {
|
||||
value_ = VirtualRegisterField::update(value_, id);
|
||||
}
|
||||
|
||||
// [lifetime]: Only for non-FIXED_SLOT.
|
||||
bool IsUsedAtStart() {
|
||||
ASSERT(basic_policy() == EXTENDED_POLICY);
|
||||
return LifetimeField::decode(value_) == USED_AT_START;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2328,7 +2328,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
|
||||
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
|
||||
if (spill_index > LUnallocated::kMaxFixedIndex) {
|
||||
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
|
||||
Abort("Too many spill slots needed for OSR");
|
||||
spill_index = 0;
|
||||
}
|
||||
|
@ -2384,7 +2384,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
|
||||
int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
|
||||
if (spill_index > LUnallocated::kMaxFixedIndex) {
|
||||
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
|
||||
Abort("Too many spill slots needed for OSR");
|
||||
spill_index = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user