From a3f30f5a3a31d2610a2dda2b5db42d53b6f9720c Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Fri, 15 May 2009 11:09:51 +0000 Subject: [PATCH] Clean up the Result class. Reduce the size of Result from four words 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 --- src/codegen.cc | 5 +++ src/codegen.h | 26 +++++++++++++ src/compiler.h | 5 ++- src/ia32/codegen-ia32.cc | 74 ++++++++++++++++++------------------ src/ia32/register-allocator-ia32.cc | 28 +++++++------- src/ia32/virtual-frame-ia32.cc | 6 +-- src/ia32/virtual-frame-ia32.h | 2 +- src/register-allocator-inl.h | 18 +++++++-- src/register-allocator.cc | 51 +++++++++---------------- src/register-allocator.h | 75 +++++++++++++++++++++++-------------- src/virtual-frame.cc | 8 ++-- test/cctest/test-log-ia32.cc | 1 + 12 files changed, 175 insertions(+), 124 deletions(-) diff --git a/src/codegen.cc b/src/codegen.cc index 0b18503..2c56534 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -40,6 +40,10 @@ namespace v8 { namespace internal { + +CodeGenerator* CodeGeneratorScope::top_ = NULL; + + DeferredCode::DeferredCode(CodeGenerator* generator) : generator_(generator), masm_(generator->masm()), @@ -154,6 +158,7 @@ Handle 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()); diff --git a/src/codegen.h b/src/codegen.h index f593c58..fde0c46 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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 diff --git a/src/compiler.h b/src/compiler.h index 8421cda..24d77ba 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -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(); + } } }; diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index c66b672..faec20e 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -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 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* 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::FromInt(scope_->num_parameters())), this); + Result count(Handle(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* args) { Load(args->at(0)); Result key = frame_->Pop(); // Explicitly create a constant result. - Result count(Handle(Smi::FromInt(scope_->num_parameters())), this); + Result count(Handle(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. diff --git a/src/ia32/register-allocator-ia32.cc b/src/ia32/register-allocator-ia32.cc index b72d765..b493b17 100644 --- a/src/ia32/register-allocator-ia32.cc +++ b/src/ia32/register-allocator-ia32.cc @@ -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; } diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc index a63de7c..daa4558 100644 --- a/src/ia32/virtual-frame-ia32.cc +++ b/src/ia32/virtual-frame-ia32.cc @@ -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()); } } diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h index 30869f3..b3ee6c7 100644 --- a/src/ia32/virtual-frame-ia32.h +++ b/src/ia32/virtual-frame-ia32.h @@ -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 value) { - Result temp(value, cgen_); + Result temp(value); SetElementAt(index, &temp); } diff --git a/src/register-allocator-inl.h b/src/register-allocator-inl.h index f9dced3..800d530 100644 --- a/src/register-allocator-inl.h +++ b/src/register-allocator-inl.h @@ -35,13 +35,25 @@ 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()); + } } diff --git a/src/register-allocator.cc b/src/register-allocator.cc index 1da7e6b..d6f850e 100644 --- a/src/register-allocator.cc +++ b/src/register-allocator.cc @@ -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(); } diff --git a/src/register-allocator.h b/src/register-allocator.h index 19dde96..25bd026 100644 --- a/src/register-allocator.h +++ b/src/register-allocator.h @@ -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 value, CodeGenerator * cgen) - : static_type_(StaticType::TypeOf(*value)), - type_(CONSTANT), - cgen_(cgen) { - data_.handle_ = value.location(); + explicit Result(Handle 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 > 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() 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 handle() const { ASSERT(type() == CONSTANT); - return Handle(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 {}; + class TypeField: public BitField {}; + class DataField: public BitField {}; - CodeGenerator* cgen_; + inline void CopyTo(Result* destination) const; - void CopyTo(Result* destination) const; + friend class CodeGeneratorScope; }; diff --git a/src/virtual-frame.cc b/src/virtual-frame.cc index f5da5fc..9249cbf 100644 --- a/src/virtual-frame.cc +++ b/src/virtual-frame.cc @@ -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; diff --git a/test/cctest/test-log-ia32.cc b/test/cctest/test-log-ia32.cc index 43cb294..22b1600 100644 --- a/test/cctest/test-log-ia32.cc +++ b/test/cctest/test-log-ia32.cc @@ -13,6 +13,7 @@ #include "top.h" #include "cctest.h" #include "disassembler.h" +#include "register-allocator-inl.h" using v8::Function; using v8::Local; -- 2.7.4