Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(475)

Unified Diff: src/lithium.h

Issue 6378004: Move LOperand class to lithium.h and move implementations out of .h into .cc ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/lithium-gap-resolver-ia32.h ('k') | src/lithium.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/lithium.h
===================================================================
--- src/lithium.h (revision 6389)
+++ src/lithium.h (working copy)
@@ -29,12 +29,360 @@
#define V8_LITHIUM_H_
#include "hydrogen.h"
-#include "lithium-allocator.h"
#include "safepoint-table.h"
namespace v8 {
namespace internal {
+class LOperand: public ZoneObject {
+ public:
+ enum Kind {
+ INVALID,
+ UNALLOCATED,
+ CONSTANT_OPERAND,
+ STACK_SLOT,
+ DOUBLE_STACK_SLOT,
+ REGISTER,
+ DOUBLE_REGISTER,
+ ARGUMENT
+ };
+
+ LOperand() : value_(KindField::encode(INVALID)) { }
+
+ Kind kind() const { return KindField::decode(value_); }
+ int index() const { return static_cast<int>(value_) >> kKindFieldWidth; }
+ bool IsConstantOperand() const { return kind() == CONSTANT_OPERAND; }
+ bool IsStackSlot() const { return kind() == STACK_SLOT; }
+ bool IsDoubleStackSlot() const { return kind() == DOUBLE_STACK_SLOT; }
+ bool IsRegister() const { return kind() == REGISTER; }
+ bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; }
+ bool IsArgument() const { return kind() == ARGUMENT; }
+ bool IsUnallocated() const { return kind() == UNALLOCATED; }
+ bool Equals(LOperand* other) const { return value_ == other->value_; }
+ int VirtualRegister();
+
+ void PrintTo(StringStream* stream);
+ void ConvertTo(Kind kind, int index) {
+ value_ = KindField::encode(kind);
+ value_ |= index << kKindFieldWidth;
+ ASSERT(this->index() == index);
+ }
+
+ protected:
+ static const int kKindFieldWidth = 3;
+ class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
+
+ LOperand(Kind kind, int index) { ConvertTo(kind, index); }
+
+ unsigned value_;
+};
+
+
+class LUnallocated: public LOperand {
+ public:
+ enum Policy {
+ NONE,
+ ANY,
+ FIXED_REGISTER,
+ FIXED_DOUBLE_REGISTER,
+ FIXED_SLOT,
+ MUST_HAVE_REGISTER,
+ WRITABLE_REGISTER,
+ SAME_AS_FIRST_INPUT,
+ IGNORE
+ };
+
+ // Lifetime of operand inside the instruction.
+ enum Lifetime {
+ // USED_AT_START operand is guaranteed to be live only at
+ // instruction start. Register allocator is free to assign the same register
+ // to some other operand used inside instruction (i.e. temporary or
+ // output).
+ USED_AT_START,
+
+ // USED_AT_END operand is treated as live until the end of
+ // instruction. This means that register allocator will not reuse it's
+ // register for any other operand inside instruction.
+ USED_AT_END
+ };
+
+ explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) {
+ Initialize(policy, 0, USED_AT_END);
+ }
+
+ LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) {
+ Initialize(policy, fixed_index, USED_AT_END);
+ }
+
+ LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) {
+ Initialize(policy, 0, lifetime);
+ }
+
+ // The superclass has a KindField. Some policies have a signed fixed
+ // index in the upper bits.
+ static const int kPolicyWidth = 4;
+ static const int kLifetimeWidth = 1;
+ static const int kVirtualRegisterWidth = 17;
+
+ static const int kPolicyShift = kKindFieldWidth;
+ static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
+ static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth;
+ static const int kFixedIndexShift =
+ kVirtualRegisterShift + kVirtualRegisterWidth;
+
+ 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 + 1);
+ static const int kMaxFixedIndices = 128;
+
+ bool HasIgnorePolicy() const { return policy() == IGNORE; }
+ bool HasNoPolicy() const { return policy() == NONE; }
+ 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::mask();
+ value_ |= PolicyField::encode(policy);
+ }
+ int fixed_index() const {
+ return static_cast<int>(value_) >> kFixedIndexShift;
+ }
+
+ unsigned virtual_register() const {
+ return VirtualRegisterField::decode(value_);
+ }
+
+ void set_virtual_register(unsigned id) {
+ value_ &= ~VirtualRegisterField::mask();
+ value_ |= VirtualRegisterField::encode(id);
+ }
+
+ LUnallocated* CopyUnconstrained() {
+ LUnallocated* result = new LUnallocated(ANY);
+ result->set_virtual_register(virtual_register());
+ return result;
+ }
+
+ static LUnallocated* cast(LOperand* op) {
+ ASSERT(op->IsUnallocated());
+ return reinterpret_cast<LUnallocated*>(op);
+ }
+
+ bool IsUsedAtStart() {
+ return LifetimeField::decode(value_) == USED_AT_START;
+ }
+
+ 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);
+ }
+};
+
+
+class LMoveOperands BASE_EMBEDDED {
+ public:
+ LMoveOperands(LOperand* source, LOperand* destination)
+ : source_(source), destination_(destination) {
+ }
+
+ LOperand* source() const { return source_; }
+ void set_source(LOperand* operand) { source_ = operand; }
+
+ LOperand* destination() const { return destination_; }
+ void set_destination(LOperand* operand) { destination_ = operand; }
+
+ // The gap resolver marks moves as "in-progress" by clearing the
+ // destination (but not the source).
+ bool IsPending() const {
+ return destination_ == NULL && source_ != NULL;
+ }
+
+ // True if this move a move into the given destination operand.
+ bool Blocks(LOperand* operand) const {
+ return !IsEliminated() && source()->Equals(operand);
+ }
+
+ // A move is redundant if it's been eliminated, if its source and
+ // destination are the same, or if its destination is unneeded.
+ bool IsRedundant() const {
+ return IsEliminated() || source_->Equals(destination_) || IsIgnored();
+ }
+
+ bool IsIgnored() const {
+ return destination_ != NULL &&
+ destination_->IsUnallocated() &&
+ LUnallocated::cast(destination_)->HasIgnorePolicy();
+ }
+
+ // We clear both operands to indicate move that's been eliminated.
+ void Eliminate() { source_ = destination_ = NULL; }
+ bool IsEliminated() const {
+ ASSERT(source_ != NULL || destination_ == NULL);
+ return source_ == NULL;
+ }
+
+ private:
+ LOperand* source_;
+ LOperand* destination_;
+};
+
+
+class LConstantOperand: public LOperand {
+ public:
+ static LConstantOperand* Create(int index) {
+ ASSERT(index >= 0);
+ if (index < kNumCachedOperands) return &cache[index];
+ return new LConstantOperand(index);
+ }
+
+ static LConstantOperand* cast(LOperand* op) {
+ ASSERT(op->IsConstantOperand());
+ return reinterpret_cast<LConstantOperand*>(op);
+ }
+
+ static void SetupCache();
+
+ private:
+ static const int kNumCachedOperands = 128;
+ static LConstantOperand cache[];
+
+ LConstantOperand() : LOperand() { }
+ explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { }
+};
+
+
+class LArgument: public LOperand {
+ public:
+ explicit LArgument(int index) : LOperand(ARGUMENT, index) { }
+
+ static LArgument* cast(LOperand* op) {
+ ASSERT(op->IsArgument());
+ return reinterpret_cast<LArgument*>(op);
+ }
+};
+
+
+class LStackSlot: public LOperand {
+ public:
+ static LStackSlot* Create(int index) {
+ ASSERT(index >= 0);
+ if (index < kNumCachedOperands) return &cache[index];
+ return new LStackSlot(index);
+ }
+
+ static LStackSlot* cast(LOperand* op) {
+ ASSERT(op->IsStackSlot());
+ return reinterpret_cast<LStackSlot*>(op);
+ }
+
+ static void SetupCache();
+
+ private:
+ static const int kNumCachedOperands = 128;
+ static LStackSlot cache[];
+
+ LStackSlot() : LOperand() { }
+ explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { }
+};
+
+
+class LDoubleStackSlot: public LOperand {
+ public:
+ static LDoubleStackSlot* Create(int index) {
+ ASSERT(index >= 0);
+ if (index < kNumCachedOperands) return &cache[index];
+ return new LDoubleStackSlot(index);
+ }
+
+ static LDoubleStackSlot* cast(LOperand* op) {
+ ASSERT(op->IsStackSlot());
+ return reinterpret_cast<LDoubleStackSlot*>(op);
+ }
+
+ static void SetupCache();
+
+ private:
+ static const int kNumCachedOperands = 128;
+ static LDoubleStackSlot cache[];
+
+ LDoubleStackSlot() : LOperand() { }
+ explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { }
+};
+
+
+class LRegister: public LOperand {
+ public:
+ static LRegister* Create(int index) {
+ ASSERT(index >= 0);
+ if (index < kNumCachedOperands) return &cache[index];
+ return new LRegister(index);
+ }
+
+ static LRegister* cast(LOperand* op) {
+ ASSERT(op->IsRegister());
+ return reinterpret_cast<LRegister*>(op);
+ }
+
+ static void SetupCache();
+
+ private:
+ static const int kNumCachedOperands = 16;
+ static LRegister cache[];
+
+ LRegister() : LOperand() { }
+ explicit LRegister(int index) : LOperand(REGISTER, index) { }
+};
+
+
+class LDoubleRegister: public LOperand {
+ public:
+ static LDoubleRegister* Create(int index) {
+ ASSERT(index >= 0);
+ if (index < kNumCachedOperands) return &cache[index];
+ return new LDoubleRegister(index);
+ }
+
+ static LDoubleRegister* cast(LOperand* op) {
+ ASSERT(op->IsDoubleRegister());
+ return reinterpret_cast<LDoubleRegister*>(op);
+ }
+
+ static void SetupCache();
+
+ private:
+ static const int kNumCachedOperands = 16;
+ static LDoubleRegister cache[];
+
+ LDoubleRegister() : LOperand() { }
+ explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { }
+};
+
+
class LParallelMove : public ZoneObject {
public:
LParallelMove() : move_operands_(4) { }
« no previous file with comments | « src/ia32/lithium-gap-resolver-ia32.h ('k') | src/lithium.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698