Clean up the Result class. Reduce the size of Result from four words
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 15 May 2009 11:09:51 +0000 (11:09 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 15 May 2009 11:09:51 +0000 (11:09 +0000)
to one by keeping a stack of active code generators and by using
indirection to handles.

Mainly a cleanup.  No visible performance impact.
Review URL: http://codereview.chromium.org/113455

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1965 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/codegen.cc
src/codegen.h
src/compiler.h
src/ia32/codegen-ia32.cc
src/ia32/register-allocator-ia32.cc
src/ia32/virtual-frame-ia32.cc
src/ia32/virtual-frame-ia32.h
src/register-allocator-inl.h
src/register-allocator.cc
src/register-allocator.h
src/virtual-frame.cc
test/cctest/test-log-ia32.cc

index 0b18503..2c56534 100644 (file)
 
 namespace v8 { namespace internal {
 
+
+CodeGenerator* CodeGeneratorScope::top_ = NULL;
+
+
 DeferredCode::DeferredCode(CodeGenerator* generator)
   : generator_(generator),
     masm_(generator->masm()),
@@ -154,6 +158,7 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
   // Generate code.
   const int initial_buffer_size = 4 * KB;
   CodeGenerator cgen(initial_buffer_size, script, is_eval);
+  CodeGeneratorScope scope(&cgen);
   cgen.GenCode(flit);
   if (cgen.HasStackOverflow()) {
     ASSERT(!Top::has_pending_exception());
index f593c58..fde0c46 100644 (file)
@@ -86,9 +86,35 @@ enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
 #include "arm/codegen-arm.h"
 #endif
 
+#include "register-allocator.h"
+
 namespace v8 { namespace internal {
 
 
+// Code generation can be nested.  Code generation scopes form a stack
+// of active code generators.
+class CodeGeneratorScope BASE_EMBEDDED {
+ public:
+  explicit CodeGeneratorScope(CodeGenerator* cgen) {
+    previous_ = top_;
+    top_ = cgen;
+  }
+
+  ~CodeGeneratorScope() {
+    top_ = previous_;
+  }
+
+  static CodeGenerator* Current() {
+    ASSERT(top_ != NULL);
+    return top_;
+  }
+
+ private:
+  static CodeGenerator* top_;
+  CodeGenerator* previous_;
+};
+
+
 // Use lazy compilation; defaults to true.
 // NOTE: Do not remove non-lazy compilation until we can properly
 //       install extensions with lazy compilation enabled. At the
index 8421cda..24d77ba 100644 (file)
@@ -79,7 +79,10 @@ class CompilationZoneScope : public ZoneScope {
  public:
   explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
   virtual ~CompilationZoneScope() {
-    if (ShouldDeleteOnExit()) FrameElement::ClearConstantList();
+    if (ShouldDeleteOnExit()) {
+      FrameElement::ClearConstantList();
+      Result::ClearConstantList();
+    }
   }
 };
 
index c66b672..faec20e 100644 (file)
@@ -281,7 +281,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
         ASSERT(!function_return_is_shadowed_);
         CodeForReturnPosition(fun);
         frame_->PrepareForReturn();
-        Result undefined(Factory::undefined_value(), this);
+        Result undefined(Factory::undefined_value());
         if (function_return_.is_bound()) {
           function_return_.Jump(&undefined);
         } else {
@@ -296,7 +296,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
         // control does not flow off the end of the body so we did not
         // compile an artificial return statement just above, and (b) there
         // are return statements in the body but (c) they are all shadowed.
-        Result return_value(this);
+        Result return_value;
         // Though this is a (possibly) backward block, the frames can
         // only differ on their top element.
         function_return_.Bind(&return_value, 1);
@@ -388,7 +388,7 @@ Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot,
                                                          JumpTarget* slow) {
   ASSERT(slot->type() == Slot::CONTEXT);
   ASSERT(tmp.is_register());
-  Result context(esi, this);
+  Result context(esi);
 
   for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
     if (s->num_heap_slots() > 0) {
@@ -803,8 +803,8 @@ class DeferredInlineBinaryOperation: public DeferredCode {
 
 
 void DeferredInlineBinaryOperation::Generate() {
-  Result left(generator());
-  Result right(generator());
+  Result left;
+  Result right;
   enter()->Bind(&left, &right);
   generator()->frame()->Push(&left);
   generator()->frame()->Push(&right);
@@ -859,7 +859,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
     if (left_is_string || right_is_string) {
       frame_->Push(&left);
       frame_->Push(&right);
-      Result answer(this);
+      Result answer;
       if (left_is_string) {
         if (right_is_string) {
           // TODO(lrn): if (left.is_constant() && right.is_constant())
@@ -1045,7 +1045,7 @@ class DeferredInlineSmiOperation: public DeferredCode {
 
 
 void DeferredInlineSmiOperation::Generate() {
-  Result left(generator());
+  Result left;
   enter()->Bind(&left);
   generator()->frame()->Push(&left);
   generator()->frame()->Push(value_);
@@ -1078,7 +1078,7 @@ class DeferredInlineSmiOperationReversed: public DeferredCode {
 
 
 void DeferredInlineSmiOperationReversed::Generate() {
-  Result right(generator());
+  Result right;
   enter()->Bind(&right);
   generator()->frame()->Push(value_);
   generator()->frame()->Push(&right);
@@ -1109,7 +1109,7 @@ class DeferredInlineSmiAdd: public DeferredCode {
 
 void DeferredInlineSmiAdd::Generate() {
   // Undo the optimistic add operation and call the shared stub.
-  Result left(generator());  // Initially left + value_.
+  Result left;  // Initially left + value_.
   enter()->Bind(&left);
   left.ToRegister();
   generator()->frame()->Spill(left.reg());
@@ -1143,7 +1143,7 @@ class DeferredInlineSmiAddReversed: public DeferredCode {
 
 void DeferredInlineSmiAddReversed::Generate() {
   // Undo the optimistic add operation and call the shared stub.
-  Result right(generator());  // Initially value_ + right.
+  Result right;  // Initially value_ + right.
   enter()->Bind(&right);
   right.ToRegister();
   generator()->frame()->Spill(right.reg());
@@ -1177,7 +1177,7 @@ class DeferredInlineSmiSub: public DeferredCode {
 
 void DeferredInlineSmiSub::Generate() {
   // Undo the optimistic sub operation and call the shared stub.
-  Result left(generator());  // Initially left - value_.
+  Result left;  // Initially left - value_.
   enter()->Bind(&left);
   left.ToRegister();
   generator()->frame()->Spill(left.reg());
@@ -1211,7 +1211,7 @@ class DeferredInlineSmiSubReversed: public DeferredCode {
 
 void DeferredInlineSmiSubReversed::Generate() {
   // Call the shared stub.
-  Result right(generator());
+  Result right;
   enter()->Bind(&right);
   generator()->frame()->Push(value_);
   generator()->frame()->Push(&right);
@@ -1235,7 +1235,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
   // TODO(199): Optimize some special cases of operations involving a
   // smi literal (multiply by 2, shift by 0, etc.).
   if (IsUnsafeSmi(value)) {
-    Result unsafe_operand(value, this);
+    Result unsafe_operand(value);
     if (reversed) {
       LikelySmiBinaryOperation(op, &unsafe_operand, operand,
                                overwrite_mode);
@@ -1275,7 +1275,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
 
     case Token::SUB: {
       DeferredCode* deferred = NULL;
-      Result answer(this);  // Only allocate a new register if reversed.
+      Result answer;  // Only allocate a new register if reversed.
       if (reversed) {
         answer = allocator()->Allocate();
         ASSERT(answer.is_valid());
@@ -1304,7 +1304,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
 
     case Token::SAR: {
       if (reversed) {
-        Result constant_operand(value, this);
+        Result constant_operand(value);
         LikelySmiBinaryOperation(op, &constant_operand, operand,
                                  overwrite_mode);
       } else {
@@ -1330,7 +1330,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
 
     case Token::SHR: {
       if (reversed) {
-        Result constant_operand(value, this);
+        Result constant_operand(value);
         LikelySmiBinaryOperation(op, &constant_operand, operand,
                                  overwrite_mode);
       } else {
@@ -1365,7 +1365,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
 
     case Token::SHL: {
       if (reversed) {
-        Result constant_operand(value, this);
+        Result constant_operand(value);
         LikelySmiBinaryOperation(op, &constant_operand, operand,
                                  overwrite_mode);
       } else {
@@ -1435,7 +1435,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
     }
 
     default: {
-      Result constant_operand(value, this);
+      Result constant_operand(value);
       if (reversed) {
         LikelySmiBinaryOperation(op, &constant_operand, operand,
                                  overwrite_mode);
@@ -1484,8 +1484,8 @@ void CodeGenerator::Comparison(Condition cc,
   // Strict only makes sense for equality comparisons.
   ASSERT(!strict || cc == equal);
 
-  Result left_side(this);
-  Result right_side(this);
+  Result left_side;
+  Result right_side;
   // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
   if (cc == greater || cc == less_equal) {
     cc = ReverseCondition(cc);
@@ -1769,7 +1769,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   frame_->Push(pairs);
 
   // Duplicate the context register.
-  Result context(esi, this);
+  Result context(esi);
   frame_->Push(&context);
 
   frame_->Push(Smi::FromInt(is_eval() ? 1 : 0));
@@ -1793,7 +1793,7 @@ void CodeGenerator::VisitDeclaration(Declaration* node) {
     // during variable resolution and must have mode DYNAMIC.
     ASSERT(var->is_dynamic());
     // For now, just do a runtime call.  Duplicate the context register.
-    Result context(esi, this);
+    Result context(esi);
     frame_->Push(&context);
     frame_->Push(var->name());
     // Declaration nodes are always introduced in one of two modes.
@@ -2032,7 +2032,7 @@ void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
   Comment cmnt(masm_, "[ WithEnterStatement");
   CodeForStatementPosition(node);
   Load(node->expression());
-  Result context(this);
+  Result context;
   if (node->is_catch_block()) {
     context = frame_->CallRuntime(Runtime::kPushCatchContext, 1);
   } else {
@@ -2941,7 +2941,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
 
   // Generate unlink code for the (formerly) shadowing targets that
   // have been jumped to.  Deallocate each shadow target.
-  Result return_value(this);
+  Result return_value;
   for (int i = 0; i < shadows.length(); i++) {
     if (shadows[i]->is_linked()) {
       // Unlink from try chain; be careful not to destroy the TOS if
@@ -3073,7 +3073,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
       // on the virtual frame.  We must preserve it until it is
       // pushed.
       if (i == kReturnShadowIndex) {
-        Result return_value(this);
+        Result return_value;
         shadows[i]->Bind(&return_value);
         return_value.ToRegister(eax);
       } else {
@@ -3256,7 +3256,7 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
 
     JumpTarget slow(this);
     JumpTarget done(this);
-    Result value(this);
+    Result value;
 
     // Generate fast-case code for variables that might be shadowed by
     // eval-introduced variables.  Eval is used a lot without
@@ -3356,7 +3356,7 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
     JumpTarget* slow) {
   // Check that no extension objects have been created by calls to
   // eval from the current scope to the global scope.
-  Result context(esi, this);
+  Result context(esi);
   Result tmp = allocator_->Allocate();
   ASSERT(tmp.is_valid());  // All non-reserved registers were available.
 
@@ -3431,7 +3431,7 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
     frame_->Push(esi);
     frame_->Push(slot->var()->name());
 
-    Result value(this);
+    Result value;
     if (init_state == CONST_INIT) {
       // Same as the case for a normal store, but ignores attribute
       // (e.g. READ_ONLY) of context slot so that we can initialize const
@@ -3574,7 +3574,7 @@ class DeferredRegExpLiteral: public DeferredCode {
 
 
 void DeferredRegExpLiteral::Generate() {
-  Result literals(generator());
+  Result literals;
   enter()->Bind(&literals);
   // Since the entry is undefined we call the runtime system to
   // compute the literal.
@@ -3651,7 +3651,7 @@ class DeferredObjectLiteral: public DeferredCode {
 
 
 void DeferredObjectLiteral::Generate() {
-  Result literals(generator());
+  Result literals;
   enter()->Bind(&literals);
   // Since the entry is undefined we call the runtime system to
   // compute the literal.
@@ -3789,7 +3789,7 @@ class DeferredArrayLiteral: public DeferredCode {
 
 
 void DeferredArrayLiteral::Generate() {
-  Result literals(generator());
+  Result literals;
   enter()->Bind(&literals);
   // Since the entry is undefined we call the runtime system to
   // compute the literal.
@@ -4438,7 +4438,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 0);
   // ArgumentsAccessStub takes the parameter count as an input argument
   // in register eax.  Create a constant result for it.
-  Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this);
+  Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
   // Call the shared stub to get to the arguments.length.
   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
   Result result = frame_->CallStub(&stub, &count);
@@ -4521,7 +4521,7 @@ void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
   Load(args->at(0));
   Result key = frame_->Pop();
   // Explicitly create a constant result.
-  Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this);
+  Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
   // Call the shared stub to get to arguments[key].
   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
   Result result = frame_->CallStub(&stub, &key, &count);
@@ -4771,7 +4771,7 @@ class DeferredCountOperation: public DeferredCode {
 
 void DeferredCountOperation::Generate() {
   CodeGenerator* cgen = generator();
-  Result value(cgen);
+  Result value;
   enter()->Bind(&value);
   VirtualFrame* frame = cgen->frame();
   // Undo the optimistic smi operation.
@@ -5269,7 +5269,7 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
 
 void DeferredReferenceGetNamedValue::Generate() {
   CodeGenerator* cgen = generator();
-  Result receiver(cgen);
+  Result receiver;
   enter()->Bind(&receiver);
 
   cgen->frame()->Push(&receiver);
@@ -5311,8 +5311,8 @@ class DeferredReferenceGetKeyedValue: public DeferredCode {
 
 void DeferredReferenceGetKeyedValue::Generate() {
   CodeGenerator* cgen = generator();
-  Result receiver(cgen);
-  Result key(cgen);
+  Result receiver;
+  Result key;
   enter()->Bind(&receiver, &key);
   cgen->frame()->Push(&receiver);  // First IC argument.
   cgen->frame()->Push(&key);       // Second IC argument.
index b72d765..b493b17 100644 (file)
@@ -38,12 +38,13 @@ namespace v8 { namespace internal {
 void Result::ToRegister() {
   ASSERT(is_valid());
   if (is_constant()) {
-    Result fresh = cgen_->allocator()->Allocate();
+    Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate();
     ASSERT(fresh.is_valid());
-    if (cgen_->IsUnsafeSmi(handle())) {
-      cgen_->LoadUnsafeSmi(fresh.reg(), handle());
+    if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
+      CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle());
     } else {
-      cgen_->masm()->Set(fresh.reg(), Immediate(handle()));
+      CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
+                                                 Immediate(handle()));
     }
     // This result becomes a copy of the fresh one.
     *this = fresh;
@@ -55,23 +56,24 @@ void Result::ToRegister() {
 void Result::ToRegister(Register target) {
   ASSERT(is_valid());
   if (!is_register() || !reg().is(target)) {
-    Result fresh = cgen_->allocator()->Allocate(target);
+    Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate(target);
     ASSERT(fresh.is_valid());
     if (is_register()) {
-      cgen_->masm()->mov(fresh.reg(), reg());
+      CodeGeneratorScope::Current()->masm()->mov(fresh.reg(), reg());
     } else {
       ASSERT(is_constant());
-      if (cgen_->IsUnsafeSmi(handle())) {
-        cgen_->LoadUnsafeSmi(fresh.reg(), handle());
+      if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
+        CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle());
       } else {
-        cgen_->masm()->Set(fresh.reg(), Immediate(handle()));
+        CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
+                                                   Immediate(handle()));
       }
     }
     *this = fresh;
   } else if (is_register() && reg().is(target)) {
-    ASSERT(cgen_->has_valid_frame());
-    cgen_->frame()->Spill(target);
-    ASSERT(cgen_->allocator()->count(target) == 1);
+    ASSERT(CodeGeneratorScope::Current()->has_valid_frame());
+    CodeGeneratorScope::Current()->frame()->Spill(target);
+    ASSERT(CodeGeneratorScope::Current()->allocator()->count(target) == 1);
   }
   ASSERT(is_register());
   ASSERT(reg().is(target));
@@ -127,7 +129,7 @@ Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
   // register if valid and return an invalid result.
   if (result.is_valid() && !result.reg().is_byte_register()) {
     result.Unuse();
-    return Result(cgen_);
+    return Result();
   }
   return result;
 }
index a63de7c..daa4558 100644 (file)
@@ -1075,12 +1075,12 @@ Result VirtualFrame::Pop() {
     new_element.set_static_type(element.static_type());
     elements_[index] = new_element;
     __ mov(temp.reg(), Operand(ebp, fp_relative(index)));
-    return Result(temp.reg(), cgen_, element.static_type());
+    return Result(temp.reg(), element.static_type());
   } else if (element.is_register()) {
-    return Result(element.reg(), cgen_, element.static_type());
+    return Result(element.reg(), element.static_type());
   } else {
     ASSERT(element.is_constant());
-    return Result(element.handle(), cgen_);
+    return Result(element.handle());
   }
 }
 
index 30869f3..b3ee6c7 100644 (file)
@@ -187,7 +187,7 @@ class VirtualFrame : public ZoneObject {
 
   // Set a frame element to a constant.  The index is frame-top relative.
   void SetElementAt(int index, Handle<Object> value) {
-    Result temp(value, cgen_);
+    Result temp(value);
     SetElementAt(index, &temp);
   }
 
index f9dced3..800d530 100644 (file)
 namespace v8 { namespace internal {
 
 Result::~Result() {
-  if (is_register()) cgen_->allocator()->Unuse(reg());
+  if (is_register()) {
+    CodeGeneratorScope::Current()->allocator()->Unuse(reg());
+  }
 }
 
 
 void Result::Unuse() {
-  if (is_register()) cgen_->allocator()->Unuse(reg());
-  type_ = INVALID;
+  if (is_register()) {
+    CodeGeneratorScope::Current()->allocator()->Unuse(reg());
+  }
+  invalidate();
+}
+
+
+void Result::CopyTo(Result* destination) const {
+  destination->value_ = value_;
+  if (is_register()) {
+    CodeGeneratorScope::Current()->allocator()->Use(reg());
+  }
 }
 
 
index 1da7e6b..d6f850e 100644 (file)
@@ -35,39 +35,22 @@ namespace v8 { namespace internal {
 // -------------------------------------------------------------------------
 // Result implementation.
 
-Result::Result(Register reg, CodeGenerator* cgen)
-    : static_type_(),
-      type_(REGISTER),
-      cgen_(cgen) {
-  data_.reg_ = reg;
-  ASSERT(reg.is_valid());
-  cgen_->allocator()->Use(reg);
-}
-
 
-Result::Result(Register reg, CodeGenerator* cgen, StaticType static_type)
-    : static_type_(static_type),
-      type_(REGISTER),
-      cgen_(cgen) {
-  data_.reg_ = reg;
+Result::Result(Register reg) {
   ASSERT(reg.is_valid());
-  cgen_->allocator()->Use(reg);
+  CodeGeneratorScope::Current()->allocator()->Use(reg);
+  value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
+      | TypeField::encode(REGISTER)
+      | DataField::encode(reg.code_);
 }
 
 
-void Result::CopyTo(Result* destination) const {
-  destination->static_type_ = static_type_;
-  destination->type_ = type();
-  destination->cgen_ = cgen_;
-
-  if (is_register()) {
-    destination->data_.reg_ = reg();
-    cgen_->allocator()->Use(reg());
-  } else if (is_constant()) {
-    destination->data_.handle_ = data_.handle_;
-  } else {
-    ASSERT(!is_valid());
-  }
+Result::Result(Register reg, StaticType type) {
+  ASSERT(reg.is_valid());
+  CodeGeneratorScope::Current()->allocator()->Use(reg);
+  value_ = StaticTypeField::encode(type.static_type_)
+      | TypeField::encode(REGISTER)
+      | DataField::encode(reg.code_);
 }
 
 
@@ -80,9 +63,9 @@ Result RegisterAllocator::AllocateWithoutSpilling() {
   int free_reg = registers_.ScanForFreeRegister();
   if (free_reg < kNumRegisters) {
     Register free_result = { free_reg };
-    return Result(free_result, cgen_);
+    return Result(free_result);
   }
-  return Result(cgen_);
+  return Result();
 }
 
 
@@ -94,7 +77,7 @@ Result RegisterAllocator::Allocate() {
     Register free_reg = cgen_->frame()->SpillAnyRegister();
     if (free_reg.is_valid()) {
       ASSERT(!is_used(free_reg));
-      return Result(free_reg, cgen_);
+      return Result(free_reg);
     }
   }
   return result;
@@ -104,7 +87,7 @@ Result RegisterAllocator::Allocate() {
 Result RegisterAllocator::Allocate(Register target) {
   // If the target is not referenced, it can simply be allocated.
   if (!is_used(target)) {
-    return Result(target, cgen_);
+    return Result(target);
   }
   // If the target is only referenced in the frame, it can be spilled and
   // then allocated.
@@ -112,10 +95,10 @@ Result RegisterAllocator::Allocate(Register target) {
   if (cgen_->frame()->is_used(target) && count(target) == 1)  {
     cgen_->frame()->Spill(target);
     ASSERT(!is_used(target));
-    return Result(target, cgen_);
+    return Result(target);
   }
   // Otherwise (if it's referenced outside the frame) we cannot allocate it.
-  return Result(cgen_);
+  return Result();
 }
 
 
index 19dde96..25bd026 100644 (file)
@@ -103,6 +103,7 @@ class StaticType BASE_EMBEDDED {
   StaticTypeEnum static_type_;
 
   friend class FrameElement;
+  friend class Result;
 };
 
 
@@ -121,26 +122,20 @@ class Result BASE_EMBEDDED {
   };
 
   // Construct an invalid result.
-  explicit Result(CodeGenerator* cgen)
-      : static_type_(),
-        type_(INVALID),
-        cgen_(cgen) {}
+  Result() { invalidate(); }
 
   // Construct a register Result.
-  Result(Register reg,
-         CodeGenerator* cgen);
+  explicit Result(Register reg);
 
   // Construct a register Result with a known static type.
-  Result(Register reg,
-         CodeGenerator* cgen,
-         StaticType static_type);
+  Result(Register reg, StaticType static_type);
 
   // Construct a Result whose value is a compile-time constant.
-  Result(Handle<Object> value, CodeGenerator * cgen)
-      : static_type_(StaticType::TypeOf(*value)),
-        type_(CONSTANT),
-        cgen_(cgen) {
-    data_.handle_ = value.location();
+  explicit Result(Handle<Object> value) {
+    value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_)
+        | TypeField::encode(CONSTANT)
+        | DataField::encode(ConstantList()->length());
+    ConstantList()->Add(value);
   }
 
   // The copy constructor and assignment operators could each create a new
@@ -159,25 +154,51 @@ class Result BASE_EMBEDDED {
 
   inline ~Result();
 
+  // Static indirection table for handles to constants.  If a Result
+  // represents a constant, the data contains an index into this table
+  // of handles to the actual constants.
+  typedef ZoneList<Handle<Object> > ZoneObjectList;
+
+  static ZoneObjectList* ConstantList() {
+    static ZoneObjectList list(10);
+    return &list;
+  }
+
+  // Clear the constants indirection table.
+  static void ClearConstantList() {
+    ConstantList()->Clear();
+  }
+
   inline void Unuse();
 
-  StaticType static_type() const { return static_type_; }
-  void set_static_type(StaticType static_type) { static_type_ = static_type; }
+  StaticType static_type() const {
+    return StaticType(StaticTypeField::decode(value_));
+  }
+
+  void set_static_type(StaticType type) {
+    value_ = value_ & ~StaticTypeField::mask();
+    value_ = value_ | StaticTypeField::encode(type.static_type_);
+  }
 
-  Type type() const { return static_cast<Type>(type_); }
+  Type type() const { return TypeField::decode(value_); }
+
+  void invalidate() { value_ = TypeField::encode(INVALID); }
 
   bool is_valid() const { return type() != INVALID; }
   bool is_register() const { return type() == REGISTER; }
   bool is_constant() const { return type() == CONSTANT; }
 
   Register reg() const {
-    ASSERT(type() == REGISTER);
-    return data_.reg_;
+    ASSERT(is_register());
+    uint32_t reg = DataField::decode(value_);
+    Register result;
+    result.code_ = reg;
+    return result;
   }
 
   Handle<Object> handle() const {
     ASSERT(type() == CONSTANT);
-    return Handle<Object>(data_.handle_);
+    return ConstantList()->at(DataField::decode(value_));
   }
 
   // Move this result to an arbitrary register.  The register is not
@@ -191,17 +212,15 @@ class Result BASE_EMBEDDED {
   void ToRegister(Register reg);
 
  private:
-  StaticType static_type_;
-  byte type_;
+  uint32_t value_;
 
-  union {
-    Register reg_;
-    Object** handle_;
-  } data_;
+  class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {};
+  class TypeField: public BitField<Type, 3, 2> {};
+  class DataField: public BitField<uint32_t, 5, 32 - 6> {};
 
-  CodeGenerator* cgen_;
+  inline void CopyTo(Result* destination) const;
 
-  void CopyTo(Result* destination) const;
+  friend class CodeGeneratorScope;
 };
 
 
index f5da5fc..9249cbf 100644 (file)
@@ -324,11 +324,11 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
 
   // Early exit if the element is the same as the one being set.
   bool same_register = original.is_register()
-                    && value->is_register()
-                    && original.reg().is(value->reg());
+      && value->is_register()
+      && original.reg().is(value->reg());
   bool same_constant = original.is_constant()
-                    && value->is_constant()
-                    && original.handle().is_identical_to(value->handle());
+      && value->is_constant()
+      && original.handle().is_identical_to(value->handle());
   if (same_register || same_constant) {
     value->Unuse();
     return;
index 43cb294..22b1600 100644 (file)
@@ -13,6 +13,7 @@
 #include "top.h"
 #include "cctest.h"
 #include "disassembler.h"
+#include "register-allocator-inl.h"
 
 using v8::Function;
 using v8::Local;