Remove instruction summaries.

Instead of constructing a temporary container for all LOperands of each
instruction, the register works directly on the LIR instructions that
 provide an abstract interface for input/output/temp operands.

This saves allocation of zone memory and speeds up LIR construction,
but makes iterating over all uses in the register allocator slightly
more expensive because environment uses are stored in a linked list of
environments. We can fix this by using a flat representation of LOperands.


Review URL: http://codereview.chromium.org/6352006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6638 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f1acd129
......@@ -25,6 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "lithium-allocator-inl.h"
#include "arm/lithium-arm.h"
#include "arm/lithium-codegen-arm.h"
......@@ -56,6 +57,31 @@ void LOsrEntry::MarkSpilledRegister(int allocation_index,
}
#ifdef DEBUG
void LInstruction::VerifyCall() {
// Call instructions can use only fixed registers as
// temporaries and outputs because all registers
// are blocked by the calling convention.
// Inputs can use either fixed register or have a short lifetime (be
// used at start of the instruction).
ASSERT(Output() == NULL ||
LUnallocated::cast(Output())->HasFixedPolicy() ||
!LUnallocated::cast(Output())->HasRegisterPolicy());
for (UseIterator it(this); it.HasNext(); it.Advance()) {
LOperand* operand = it.Next();
ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
LUnallocated::cast(operand)->IsUsedAtStart() ||
!LUnallocated::cast(operand)->HasRegisterPolicy());
}
for (TempIterator it(this); it.HasNext(); it.Advance()) {
LOperand* operand = it.Next();
ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
!LUnallocated::cast(operand)->HasRegisterPolicy());
}
}
#endif
void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
LOperand* spill_operand) {
ASSERT(spill_operand->IsDoubleStackSlot());
......@@ -66,9 +92,8 @@ void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
void LInstruction::PrintTo(StringStream* stream) {
stream->Add("%s ", this->Mnemonic());
if (HasResult()) {
PrintOutputOperandTo(stream);
}
PrintDataTo(stream);
......@@ -401,7 +426,7 @@ void LChunk::MarkEmptyBlocks() {
}
int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
LGap* gap = new LGap(block);
int index = -1;
if (instr->IsControl()) {
......@@ -417,7 +442,6 @@ int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
pointer_maps_.Add(instr->pointer_map());
instr->pointer_map()->set_lithium_position(index);
}
return index;
}
......@@ -683,7 +707,10 @@ void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
HInstruction* hinstr,
CanDeoptimize can_deoptimize) {
allocator_->MarkAsCall();
#ifdef DEBUG
instr->VerifyCall();
#endif
instr->MarkAsCall();
instr = AssignPointerMap(instr);
if (hinstr->HasSideEffects()) {
......@@ -708,7 +735,7 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
allocator_->MarkAsSaveDoubles();
instr->MarkAsSaveDoubles();
return instr;
}
......@@ -908,7 +935,6 @@ void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
void LChunkBuilder::VisitInstruction(HInstruction* current) {
HInstruction* old_current = current_instruction_;
current_instruction_ = current;
allocator_->BeginInstruction();
if (current->has_position()) position_ = current->position();
LInstruction* instr = current->CompileToLithium(this);
......@@ -931,11 +957,7 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
instr->set_hydrogen_value(current);
}
int index = chunk_->AddInstruction(instr, current_block_);
allocator_->SummarizeInstruction(index);
} else {
// This instruction should be omitted.
allocator_->OmitInstruction();
chunk_->AddInstruction(instr, current_block_);
}
current_instruction_ = old_current;
}
......
......@@ -181,7 +181,10 @@ class LCodeGen;
class LInstruction: public ZoneObject {
public:
LInstruction()
: hydrogen_value_(NULL) { }
: environment_(NULL),
hydrogen_value_(NULL),
is_call_(false),
is_save_doubles_(false) { }
virtual ~LInstruction() { }
virtual void CompileToNative(LCodeGen* generator) = 0;
......@@ -198,16 +201,14 @@ class LInstruction: public ZoneObject {
virtual bool IsControl() const { return false; }
virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
void set_environment(LEnvironment* env) { environment_.set(env); }
LEnvironment* environment() const { return environment_.get(); }
bool HasEnvironment() const { return environment_.is_set(); }
void set_environment(LEnvironment* env) { environment_ = env; }
LEnvironment* environment() const { return environment_; }
bool HasEnvironment() const { return environment_ != NULL; }
void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
virtual bool HasResult() const = 0;
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
......@@ -221,11 +222,31 @@ class LInstruction: public ZoneObject {
return deoptimization_environment_.is_set();
}
void MarkAsCall() { is_call_ = true; }
void MarkAsSaveDoubles() { is_save_doubles_ = true; }
// Interface to the register allocator and iterators.
bool IsMarkedAsCall() const { return is_call_; }
bool IsMarkedAsSaveDoubles() const { return is_save_doubles_; }
virtual bool HasResult() const = 0;
virtual LOperand* result() = 0;
virtual int InputCount() = 0;
virtual LOperand* InputAt(int i) = 0;
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
LOperand* FirstInput() { return InputAt(0); }
LOperand* Output() { return HasResult() ? result() : NULL; }
private:
SetOncePointer<LEnvironment> environment_;
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
SetOncePointer<LEnvironment> deoptimization_environment_;
bool is_call_;
bool is_save_doubles_;
};
......@@ -252,6 +273,11 @@ class OperandContainer<ElementType, 0> {
public:
int length() { return 0; }
void PrintOperandsTo(StringStream* stream) { }
ElementType& operator[](int i) {
UNREACHABLE();
static ElementType t = 0;
return t;
}
};
......@@ -1734,7 +1760,7 @@ class LChunk: public ZoneObject {
public:
explicit LChunk(HGraph* graph);
int AddInstruction(LInstruction* instruction, HBasicBlock* block);
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
LConstantOperand* DefineConstantOperand(HConstant* constant);
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
......
......@@ -29,6 +29,7 @@
#if defined(V8_TARGET_ARCH_IA32)
#include "lithium-allocator-inl.h"
#include "ia32/lithium-ia32.h"
#include "ia32/lithium-codegen-ia32.h"
......@@ -68,11 +69,35 @@ void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
}
#ifdef DEBUG
void LInstruction::VerifyCall() {
// Call instructions can use only fixed registers as
// temporaries and outputs because all registers
// are blocked by the calling convention.
// Inputs can use either fixed register or have a short lifetime (be
// used at start of the instruction).
ASSERT(Output() == NULL ||
LUnallocated::cast(Output())->HasFixedPolicy() ||
!LUnallocated::cast(Output())->HasRegisterPolicy());
for (UseIterator it(this); it.HasNext(); it.Advance()) {
LOperand* operand = it.Next();
ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
LUnallocated::cast(operand)->IsUsedAtStart() ||
!LUnallocated::cast(operand)->HasRegisterPolicy());
}
for (TempIterator it(this); it.HasNext(); it.Advance()) {
LOperand* operand = it.Next();
ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
!LUnallocated::cast(operand)->HasRegisterPolicy());
}
}
#endif
void LInstruction::PrintTo(StringStream* stream) {
stream->Add("%s ", this->Mnemonic());
if (HasResult()) {
PrintOutputOperandTo(stream);
}
PrintDataTo(stream);
......@@ -399,7 +424,7 @@ void LStoreKeyed::PrintDataTo(StringStream* stream) {
}
int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
LGap* gap = new LGap(block);
int index = -1;
if (instr->IsControl()) {
......@@ -415,7 +440,6 @@ int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
pointer_maps_.Add(instr->pointer_map());
instr->pointer_map()->set_lithium_position(index);
}
return index;
}
......@@ -683,7 +707,10 @@ void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
HInstruction* hinstr,
CanDeoptimize can_deoptimize) {
allocator_->MarkAsCall();
#ifdef DEBUG
instr->VerifyCall();
#endif
instr->MarkAsCall();
instr = AssignPointerMap(instr);
if (hinstr->HasSideEffects()) {
......@@ -708,7 +735,7 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
allocator_->MarkAsSaveDoubles();
instr->MarkAsSaveDoubles();
return instr;
}
......@@ -917,7 +944,6 @@ void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
void LChunkBuilder::VisitInstruction(HInstruction* current) {
HInstruction* old_current = current_instruction_;
current_instruction_ = current;
allocator_->BeginInstruction();
if (current->has_position()) position_ = current->position();
LInstruction* instr = current->CompileToLithium(this);
......@@ -940,11 +966,7 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
instr->set_hydrogen_value(current);
}
int index = chunk_->AddInstruction(instr, current_block_);
allocator_->SummarizeInstruction(index);
} else {
// This instruction should be omitted.
allocator_->OmitInstruction();
chunk_->AddInstruction(instr, current_block_);
}
current_instruction_ = old_current;
}
......
......@@ -182,7 +182,10 @@ class LCodeGen;
class LInstruction: public ZoneObject {
public:
LInstruction()
: hydrogen_value_(NULL) { }
: environment_(NULL),
hydrogen_value_(NULL),
is_call_(false),
is_save_doubles_(false) { }
virtual ~LInstruction() { }
virtual void CompileToNative(LCodeGen* generator) = 0;
......@@ -199,15 +202,14 @@ class LInstruction: public ZoneObject {
virtual bool IsControl() const { return false; }
virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
void set_environment(LEnvironment* env) { environment_.set(env); }
LEnvironment* environment() const { return environment_.get(); }
bool HasEnvironment() const { return environment_.is_set(); }
void set_environment(LEnvironment* env) { environment_ = env; }
LEnvironment* environment() const { return environment_; }
bool HasEnvironment() const { return environment_ != NULL; }
void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
virtual bool HasResult() const = 0;
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
......@@ -222,11 +224,35 @@ class LInstruction: public ZoneObject {
return deoptimization_environment_.is_set();
}
void MarkAsCall() { is_call_ = true; }
void MarkAsSaveDoubles() { is_save_doubles_ = true; }
// Interface to the register allocator and iterators.
bool IsMarkedAsCall() const { return is_call_; }
bool IsMarkedAsSaveDoubles() const { return is_save_doubles_; }
virtual bool HasResult() const = 0;
virtual LOperand* result() = 0;
virtual int InputCount() = 0;
virtual LOperand* InputAt(int i) = 0;
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
LOperand* FirstInput() { return InputAt(0); }
LOperand* Output() { return HasResult() ? result() : NULL; }
#ifdef DEBUG
void VerifyCall();
#endif
private:
SetOncePointer<LEnvironment> environment_;
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
SetOncePointer<LEnvironment> deoptimization_environment_;
bool is_call_;
bool is_save_doubles_;
};
......@@ -253,6 +279,11 @@ class OperandContainer<ElementType, 0> {
public:
int length() { return 0; }
void PrintOperandsTo(StringStream* stream) { }
ElementType& operator[](int i) {
UNREACHABLE();
static ElementType t = 0;
return t;
}
};
......@@ -1760,7 +1791,7 @@ class LChunk: public ZoneObject {
pointer_maps_(8),
inlined_closures_(1) { }
int AddInstruction(LInstruction* instruction, HBasicBlock* block);
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
LConstantOperand* DefineConstantOperand(HConstant* constant);
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
......
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_LITHIUM_ALLOCATOR_INL_H_
#define V8_LITHIUM_ALLOCATOR_INL_H_
#include "lithium-allocator.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/lithium-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "x64/lithium-x64.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/lithium-arm.h"
#else
#error "Unknown architecture."
#endif
namespace v8 {
namespace internal {
bool LAllocator::IsGapAt(int index) { return chunk_->IsGapAt(index); }
LInstruction* LAllocator::InstructionAt(int index) {
return chunk_->instructions()->at(index);
}
LGap* LAllocator::GapAt(int index) {
return chunk_->GetGapAt(index);
}
TempIterator::TempIterator(LInstruction* instr)
: instr_(instr),
limit_(instr->TempCount()),
current_(0) {
current_ = AdvanceToNext(0);
}
bool TempIterator::HasNext() { return current_ < limit_; }
LOperand* TempIterator::Next() {
ASSERT(HasNext());
return instr_->TempAt(current_);
}
int TempIterator::AdvanceToNext(int start) {
while (start < limit_ && instr_->TempAt(start) == NULL) start++;
return start;
}
void TempIterator::Advance() {
current_ = AdvanceToNext(current_ + 1);
}
InputIterator::InputIterator(LInstruction* instr)
: instr_(instr),
limit_(instr->InputCount()),
current_(0) {
current_ = AdvanceToNext(0);
}
bool InputIterator::HasNext() { return current_ < limit_; }
LOperand* InputIterator::Next() {
ASSERT(HasNext());
return instr_->InputAt(current_);
}
void InputIterator::Advance() {
current_ = AdvanceToNext(current_ + 1);
}
int InputIterator::AdvanceToNext(int start) {
while (start < limit_ && instr_->InputAt(start)->IsConstantOperand()) start++;
return start;
}
UseIterator::UseIterator(LInstruction* instr)
: input_iterator_(instr), env_iterator_(instr->environment()) { }
bool UseIterator::HasNext() {
return input_iterator_.HasNext() || env_iterator_.HasNext();
}
LOperand* UseIterator::Next() {
ASSERT(HasNext());
return input_iterator_.HasNext()
? input_iterator_.Next()
: env_iterator_.Next();
}
void UseIterator::Advance() {
input_iterator_.HasNext()
? input_iterator_.Advance()
: env_iterator_.Advance();
}
} } // namespace v8::internal
#endif // V8_LITHIUM_ALLOCATOR_INL_H_
This diff is collapsed.
......@@ -31,6 +31,7 @@
#include "v8.h"
#include "data-flow.h"
#include "lithium.h"
#include "zone.h"
namespace v8 {
......@@ -153,52 +154,55 @@ enum RegisterKind {
// A register-allocator view of a Lithium instruction. It contains the id of
// the output operand and a list of input operand uses.
class InstructionSummary: public ZoneObject {
class LInstruction;
class LEnvironment;
// Iterator for non-null temp operands.
class TempIterator BASE_EMBEDDED {
public:
InstructionSummary()
: output_operand_(NULL),
input_count_(0),
operands_(4),
is_call_(false),
is_save_doubles_(false) {}
// Output operands.
LOperand* Output() const { return output_operand_; }
void SetOutput(LOperand* output) {
ASSERT(output_operand_ == NULL);
output_operand_ = output;
}
inline explicit TempIterator(LInstruction* instr);
inline bool HasNext();
inline LOperand* Next();
inline void Advance();
// Input operands.
int InputCount() const { return input_count_; }
LOperand* InputAt(int i) const {
ASSERT(i < input_count_);
return operands_[i];
}
void AddInput(LOperand* input) {
operands_.InsertAt(input_count_, input);
input_count_++;
}
private:
inline int AdvanceToNext(int start);
LInstruction* instr_;
int limit_;
int current_;
};
// Temporary operands.
int TempCount() const { return operands_.length() - input_count_; }
LOperand* TempAt(int i) const { return operands_[i + input_count_]; }
void AddTemp(LOperand* temp) { operands_.Add(temp); }
void MarkAsCall() { is_call_ = true; }
bool IsCall() const { return is_call_; }
// Iterator for non-constant input operands.
class InputIterator BASE_EMBEDDED {
public:
inline explicit InputIterator(LInstruction* instr);
inline bool HasNext();
inline LOperand* Next();
inline void Advance();
private:
inline int AdvanceToNext(int start);
LInstruction* instr_;
int limit_;
int current_;
};
void MarkAsSaveDoubles() { is_save_doubles_ = true; }
bool IsSaveDoubles() const { return is_save_doubles_; }
class UseIterator BASE_EMBEDDED {
public:
inline explicit UseIterator(LInstruction* instr);
inline bool HasNext();
inline LOperand* Next();
inline void Advance();
private:
LOperand* output_operand_;
int input_count_;
ZoneList<LOperand*> operands_;
bool is_call_;
bool is_save_doubles_;
InputIterator input_iterator_;
DeepIterator env_iterator_;
};
// Representation of the non-empty interval [start,end[.
class UseInterval: public ZoneObject {
public:
......@@ -428,9 +432,6 @@ class LAllocator BASE_EMBEDDED {
public:
explicit LAllocator(int first_virtual_register, HGraph* graph)
: chunk_(NULL),
summaries_(0),
next_summary_(NULL),
summary_stack_(2),
live_in_sets_(0),
live_ranges_(16),
fixed_live_ranges_(8),
......@@ -457,27 +458,12 @@ class LAllocator BASE_EMBEDDED {
// Record a temporary operand.
void RecordTemporary(LUnallocated* operand);
// Marks the current instruction as a call.
void MarkAsCall();
// Marks the current instruction as requiring saving double registers.
void MarkAsSaveDoubles();
// Checks whether the value of a given virtual register is tagged.
bool HasTaggedValue(int virtual_register) const;
// Returns the register kind required by the given virtual register.
RegisterKind RequiredRegisterKind(int virtual_register) const;
// Begin a new instruction.
void BeginInstruction();
// Summarize the current instruction.
void SummarizeInstruction(int index);
// Summarize the current instruction.
void OmitInstruction();
// Control max function size.
static int max_initial_value_ids();
......@@ -525,8 +511,8 @@ class LAllocator BASE_EMBEDDED {
void AddInitialIntervals(HBasicBlock* block, BitVector* live_out);
void ProcessInstructions(HBasicBlock* block, BitVector* live);
void MeetRegisterConstraints(HBasicBlock* block);
void MeetConstraintsBetween(InstructionSummary* first,
InstructionSummary* second,
void MeetConstraintsBetween(LInstruction* first,
LInstruction* second,
int gap_index);
void ResolvePhis(HBasicBlock* block);
......@@ -604,12 +590,6 @@ class LAllocator BASE_EMBEDDED {
// Return the block which contains give lifetime position.
HBasicBlock* GetBlock(LifetimePosition pos);
// Current active summary.
InstructionSummary* current_summary() const { return summary_stack_.last(); }
// Get summary for given instruction index.
InstructionSummary* GetSummary(int index) const { return summaries_[index]; }
// Helper methods for the fixed registers.
int RegisterCount() const;
static int FixedLiveRangeID(int index) { return -index - 1; }
......@@ -618,15 +598,17 @@ class LAllocator BASE_EMBEDDED {
LiveRange* FixedDoubleLiveRangeFor(int index);
LiveRange* LiveRangeFor(int index);
HPhi* LookupPhi(LOperand* operand) const;
LGap* GetLastGap(HBasicBlock* block) const;
LGap* GetLastGap(HBasicBlock* block);
const char* RegisterName(int allocation_index);
LChunk* chunk_;
ZoneList<InstructionSummary*> summaries_;
InstructionSummary* next_summary_;
inline bool IsGapAt(int index);
ZoneList<InstructionSummary*> summary_stack_;
inline LInstruction* InstructionAt(int index);
inline LGap* GapAt(int index);
LChunk* chunk_;
// During liveness analysis keep a mapping from block id to live_in sets
// for blocks already analyzed.
......
......@@ -509,6 +509,82 @@ class LEnvironment: public ZoneObject {
friend class LCodegen;
};
// Iterates over the non-null, non-constant operands in an environment.
class ShallowIterator BASE_EMBEDDED {
public:
explicit ShallowIterator(LEnvironment* env)
: env_(env),
limit_(env != NULL ? env->values()->length() : 0),
current_(0) {
current_ = AdvanceToNext(0);
}
inline bool HasNext() {
return env_ != NULL && current_ < limit_;
}
inline LOperand* Next() {
ASSERT(HasNext());
return env_->values()->at(current_);
}
inline void Advance() {
current_ = AdvanceToNext(current_ + 1);
}
inline LEnvironment* env() { return env_; }
private:
inline int AdvanceToNext(int start) {
while (start < limit_ &&
(env_->values()->at(start) == NULL ||
env_->values()->at(start)->IsConstantOperand())) {
start++;
}
return start;
}
LEnvironment* env_;
int limit_;
int current_;
};
// Iterator for non-null, non-constant operands incl. outer environments.
class DeepIterator BASE_EMBEDDED {
public:
explicit DeepIterator(LEnvironment* env)
: current_iterator_(env) { }
inline bool HasNext() {
if (current_iterator_.HasNext()) return true;
if (current_iterator_.env() == NULL) return false;
AdvanceToOuter();
return current_iterator_.HasNext();
}
inline LOperand* Next() {
ASSERT(current_iterator_.HasNext());
return current_iterator_.Next();
}
inline void Advance() {
if (current_iterator_.HasNext()) {
current_iterator_.Advance();
} else {
AdvanceToOuter();
}
}
private:
inline void AdvanceToOuter() {
current_iterator_ = ShallowIterator(current_iterator_.env()->outer());
}
ShallowIterator current_iterator_;
};
} } // namespace v8::internal
#endif // V8_LITHIUM_H_
......@@ -29,6 +29,7 @@
#if defined(V8_TARGET_ARCH_X64)
#include "lithium-allocator-inl.h"
#include "x64/lithium-x64.h"
#include "x64/lithium-codegen-x64.h"
......@@ -68,11 +69,35 @@ void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
}
#ifdef DEBUG
void LInstruction::VerifyCall() {
// Call instructions can use only fixed registers as
// temporaries and outputs because all registers
// are blocked by the calling convention.
// Inputs can use either fixed register or have a short lifetime (be
// used at start of the instruction).
ASSERT(Output() == NULL ||
LUnallocated::cast(Output())->HasFixedPolicy() ||
!LUnallocated::cast(Output())->HasRegisterPolicy());
for (UseIterator it(this); it.HasNext(); it.Advance()) {
LOperand* operand = it.Next();
ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
LUnallocated::cast(operand)->IsUsedAtStart() ||
!LUnallocated::cast(operand)->HasRegisterPolicy());
}
for (TempIterator it(this); it.HasNext(); it.Advance()) {
LOperand* operand = it.Next();
ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
!LUnallocated::cast(operand)->HasRegisterPolicy());
}
}
#endif
void LInstruction::PrintTo(StringStream* stream) {
stream->Add("%s ", this->Mnemonic());
if (HasResult()) {
PrintOutputOperandTo(stream);
}
PrintDataTo(stream);
......@@ -393,7 +418,7 @@ void LStoreKeyed::PrintDataTo(StringStream* stream) {
}
int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
LGap* gap = new LGap(block);
int index = -1;
if (instr->IsControl()) {
......@@ -409,7 +434,6 @@ int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
pointer_maps_.Add(instr->pointer_map());
instr->pointer_map()->set_lithium_position(index);
}
return index;
}
......@@ -677,7 +701,10 @@ void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
HInstruction* hinstr,
CanDeoptimize can_deoptimize) {
allocator_->MarkAsCall();
#ifdef DEBUG
instr->VerifyCall();
#endif
instr->MarkAsCall();
instr = AssignPointerMap(instr);
if (hinstr->HasSideEffects()) {
......@@ -702,7 +729,7 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
allocator_->MarkAsSaveDoubles();
instr->MarkAsSaveDoubles();
return instr;
}
......@@ -907,7 +934,6 @@ void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
void LChunkBuilder::VisitInstruction(HInstruction* current) {
HInstruction* old_current = current_instruction_;
current_instruction_ = current;
allocator_->BeginInstruction();
if (current->has_position()) position_ = current->position();
LInstruction* instr = current->CompileToLithium(this);
......@@ -930,11 +956,7 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
instr->set_hydrogen_value(current);
}
int index = chunk_->AddInstruction(instr, current_block_);
allocator_->SummarizeInstruction(index);
} else {
// This instruction should be omitted.
allocator_->OmitInstruction();
chunk_->AddInstruction(instr, current_block_);
}
current_instruction_ = old_current;
}
......
......@@ -287,7 +287,11 @@ class LCodeGen;
class LInstruction: public ZoneObject {
public:
LInstruction()
: hydrogen_value_(NULL) { }
: environment_(NULL),
hydrogen_value_(NULL),
is_call_(false),
is_save_doubles_(false) { }
virtual ~LInstruction() { }
virtual void CompileToNative(LCodeGen* generator) = 0;
......@@ -304,16 +308,14 @@ class LInstruction: public ZoneObject {
virtual bool IsControl() const { return false; }
virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
void set_environment(LEnvironment* env) { environment_.set(env); }
LEnvironment* environment() const { return environment_.get(); }
bool HasEnvironment() const { return environment_.is_set(); }
void set_environment(LEnvironment* env) { environment_ = env; }
LEnvironment* environment() const { return environment_; }
bool HasEnvironment() const { return environment_ != NULL; }
void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
virtual bool HasResult() const = 0;
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
......@@ -327,11 +329,35 @@ class LInstruction: public ZoneObject {
return deoptimization_environment_.is_set();
}
void MarkAsCall() { is_call_ = true; }
void MarkAsSaveDoubles() { is_save_doubles_ = true; }
// Interface to the register allocator and iterators.
bool IsMarkedAsCall() const { return is_call_; }
bool IsMarkedAsSaveDoubles() const { return is_save_doubles_; }
virtual bool HasResult() const = 0;
virtual LOperand* result() = 0;
virtual int InputCount() = 0;
virtual LOperand* InputAt(int i) = 0;
virtual int TempCount() = 0;
virtual LOperand* TempAt(int i) = 0;
LOperand* FirstInput() { return InputAt(0); }
LOperand* Output() { return HasResult() ? result() : NULL; }
#ifdef DEBUG
void VerifyCall();
#endif
private:
SetOncePointer<LEnvironment> environment_;
LEnvironment* environment_;
SetOncePointer<LPointerMap> pointer_map_;
HValue* hydrogen_value_;
SetOncePointer<LEnvironment> deoptimization_environment_;
bool is_call_;
bool is_save_doubles_;
};
......@@ -358,6 +384,11 @@ class OperandContainer<ElementType, 0> {
public:
int length() { return 0; }
void PrintOperandsTo(StringStream* stream) { }
ElementType& operator[](int i) {
UNREACHABLE();
static ElementType t = 0;
return t;
}
};
......@@ -1785,7 +1816,7 @@ class LChunk: public ZoneObject {
pointer_maps_(8),
inlined_closures_(1) { }
int AddInstruction(LInstruction* instruction, HBasicBlock* block);
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
LConstantOperand* DefineConstantOperand(HConstant* constant);
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
......
......@@ -441,6 +441,7 @@
'../../src/lithium.h',
'../../src/lithium-allocator.cc',
'../../src/lithium-allocator.h',
'../../src/lithium-allocator-inl.h',
'../../src/liveedit.cc',
'../../src/liveedit.h',
'../../src/liveobjectlist-inl.h',
......
......@@ -704,6 +704,10 @@
RelativePath="..\..\src\lithium-allocator.h"
>
</File>
<File
RelativePath="..\..\src\lithium-allocator-inl.h"
>
</File>
<File
RelativePath="..\..\src\ia32\lithium-ia32.cc"
>
......
......@@ -696,6 +696,10 @@
RelativePath="..\..\src\lithium-allocator.h"
>
</File>
<File
RelativePath="..\..\src\lithium-allocator-inl.h"
>
</File>
<File
RelativePath="..\..\src\arm\lithium-arm.cc"
>
......
......@@ -705,6 +705,10 @@
RelativePath="..\..\src\lithium-allocator.h"
>
</File>
<File
RelativePath="..\..\src\lithium-allocator-inl.h"
>
</File>
<File
RelativePath="..\..\src\x64\lithium-x64.cc"
>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment