Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.
Original commit message:
Version 4.1.0.21 (cherry-pick)
Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412
Unlink pages from the space page list after evacuation.
BUG=430201
LOG=N
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/953813002
Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h
index 6d00784..daa83f2 100644
--- a/src/compiler/instruction.h
+++ b/src/compiler/instruction.h
@@ -6,48 +6,39 @@
#define V8_COMPILER_INSTRUCTION_H_
#include <deque>
+#include <iosfwd>
#include <map>
#include <set>
#include "src/compiler/common-operator.h"
#include "src/compiler/frame.h"
-#include "src/compiler/graph.h"
#include "src/compiler/instruction-codes.h"
#include "src/compiler/opcodes.h"
+#include "src/compiler/register-configuration.h"
#include "src/compiler/schedule.h"
-// TODO(titzer): don't include the macro-assembler?
-#include "src/macro-assembler.h"
+#include "src/compiler/source-position.h"
#include "src/zone-allocator.h"
namespace v8 {
namespace internal {
-
-// Forward declarations.
-class OStream;
-
namespace compiler {
-// Forward declarations.
-class Linkage;
-
// A couple of reserved opcodes are used for internal use.
const InstructionCode kGapInstruction = -1;
const InstructionCode kBlockStartInstruction = -2;
const InstructionCode kSourcePositionInstruction = -3;
-
-#define INSTRUCTION_OPERAND_LIST(V) \
- V(Constant, CONSTANT, 128) \
- V(Immediate, IMMEDIATE, 128) \
- V(StackSlot, STACK_SLOT, 128) \
- V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
- V(Register, REGISTER, Register::kNumRegisters) \
- V(DoubleRegister, DOUBLE_REGISTER, DoubleRegister::kMaxNumRegisters)
+#define INSTRUCTION_OPERAND_LIST(V) \
+ V(Constant, CONSTANT, 0) \
+ V(Immediate, IMMEDIATE, 0) \
+ V(StackSlot, STACK_SLOT, 128) \
+ V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
+ V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \
+ V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters)
class InstructionOperand : public ZoneObject {
public:
enum Kind {
- INVALID,
UNALLOCATED,
CONSTANT,
IMMEDIATE,
@@ -57,7 +48,6 @@
DOUBLE_REGISTER
};
- InstructionOperand() : value_(KindField::encode(INVALID)) {}
InstructionOperand(Kind kind, int index) { ConvertTo(kind, index); }
Kind kind() const { return KindField::decode(value_); }
@@ -66,16 +56,15 @@
bool Is##name() const { return kind() == type; }
INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0)
- INSTRUCTION_OPERAND_PREDICATE(Ignored, INVALID, 0)
#undef INSTRUCTION_OPERAND_PREDICATE
- bool Equals(InstructionOperand* other) const {
+ bool Equals(const InstructionOperand* other) const {
return value_ == other->value_;
}
void ConvertTo(Kind kind, int index) {
if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
value_ = KindField::encode(kind);
- value_ |= index << KindField::kSize;
+ value_ |= bit_cast<unsigned>(index << KindField::kSize);
DCHECK(this->index() == index);
}
@@ -84,14 +73,20 @@
static void TearDownCaches();
protected:
- typedef BitField<Kind, 0, 3> KindField;
+ typedef BitField64<Kind, 0, 3> KindField;
- unsigned value_;
+ uint64_t value_;
};
typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
-OStream& operator<<(OStream& os, const InstructionOperand& op);
+struct PrintableInstructionOperand {
+ const RegisterConfiguration* register_configuration_;
+ const InstructionOperand* op_;
+};
+
+std::ostream& operator<<(std::ostream& os,
+ const PrintableInstructionOperand& op);
class UnallocatedOperand : public InstructionOperand {
public:
@@ -122,6 +117,7 @@
explicit UnallocatedOperand(ExtendedPolicy policy)
: InstructionOperand(UNALLOCATED, 0) {
+ value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
value_ |= ExtendedPolicyField::encode(policy);
value_ |= LifetimeField::encode(USED_AT_END);
@@ -130,14 +126,16 @@
UnallocatedOperand(BasicPolicy policy, int index)
: InstructionOperand(UNALLOCATED, 0) {
DCHECK(policy == FIXED_SLOT);
+ value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
value_ |= BasicPolicyField::encode(policy);
- value_ |= index << FixedSlotIndexField::kShift;
+ value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
DCHECK(this->fixed_slot_index() == index);
}
UnallocatedOperand(ExtendedPolicy policy, int index)
: InstructionOperand(UNALLOCATED, 0) {
DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
+ value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
value_ |= ExtendedPolicyField::encode(policy);
value_ |= LifetimeField::encode(USED_AT_END);
@@ -146,6 +144,7 @@
UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime)
: InstructionOperand(UNALLOCATED, 0) {
+ value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
value_ |= ExtendedPolicyField::encode(policy);
value_ |= LifetimeField::encode(lifetime);
@@ -183,24 +182,25 @@
// +------------------------------------------+ P ... Policy
//
// The slot index is a signed value which requires us to decode it manually
- // instead of using the BitField utility class.
+ // instead of using the BitField64 utility class.
// The superclass has a KindField.
STATIC_ASSERT(KindField::kSize == 3);
// BitFields for all unallocated operands.
- class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {};
- class VirtualRegisterField : public BitField<unsigned, 4, 18> {};
+ class BasicPolicyField : public BitField64<BasicPolicy, 3, 1> {};
+ class VirtualRegisterField : public BitField64<unsigned, 4, 30> {};
// BitFields specific to BasicPolicy::FIXED_SLOT.
- class FixedSlotIndexField : public BitField<int, 22, 10> {};
+ class FixedSlotIndexField : public BitField64<int, 34, 30> {};
// BitFields specific to BasicPolicy::EXTENDED_POLICY.
- class ExtendedPolicyField : public BitField<ExtendedPolicy, 22, 3> {};
- class LifetimeField : public BitField<Lifetime, 25, 1> {};
- class FixedRegisterField : public BitField<int, 26, 6> {};
+ class ExtendedPolicyField : public BitField64<ExtendedPolicy, 34, 3> {};
+ class LifetimeField : public BitField64<Lifetime, 37, 1> {};
+ class FixedRegisterField : public BitField64<int, 38, 6> {};
- static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1;
+ static const int kInvalidVirtualRegister = VirtualRegisterField::kMax;
+ static const int kMaxVirtualRegisters = VirtualRegisterField::kMax;
static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize;
static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
@@ -244,7 +244,8 @@
// [fixed_slot_index]: Only for FIXED_SLOT.
int fixed_slot_index() const {
DCHECK(HasFixedSlotPolicy());
- return static_cast<int>(value_) >> FixedSlotIndexField::kShift;
+ return static_cast<int>(bit_cast<int64_t>(value_) >>
+ FixedSlotIndexField::kShift);
}
// [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
@@ -260,7 +261,7 @@
}
// [lifetime]: Only for non-FIXED_SLOT.
- bool IsUsedAtStart() {
+ bool IsUsedAtStart() const {
DCHECK(basic_policy() == EXTENDED_POLICY);
return LifetimeField::decode(value_) == USED_AT_START;
}
@@ -288,16 +289,12 @@
}
// A move is redundant if it's been eliminated, if its source and
- // destination are the same, or if its destination is unneeded or constant.
+ // destination are the same, or if its destination is constant.
bool IsRedundant() const {
- return IsEliminated() || source_->Equals(destination_) || IsIgnored() ||
+ return IsEliminated() || source_->Equals(destination_) ||
(destination_ != NULL && destination_->IsConstant());
}
- bool IsIgnored() const {
- return destination_ != NULL && destination_->IsIgnored();
- }
-
// We clear both operands to indicate move that's been eliminated.
void Eliminate() { source_ = destination_ = NULL; }
bool IsEliminated() const {
@@ -310,7 +307,15 @@
InstructionOperand* destination_;
};
-OStream& operator<<(OStream& os, const MoveOperands& mo);
+
+struct PrintableMoveOperands {
+ const RegisterConfiguration* register_configuration_;
+ const MoveOperands* move_operands_;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
+
template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
class SubKindOperand FINAL : public InstructionOperand {
@@ -326,13 +331,18 @@
return reinterpret_cast<SubKindOperand*>(op);
}
+ static const SubKindOperand* cast(const InstructionOperand* op) {
+ DCHECK(op->kind() == kOperandKind);
+ return reinterpret_cast<const SubKindOperand*>(op);
+ }
+
static void SetUpCache();
static void TearDownCache();
private:
static SubKindOperand* cache;
- SubKindOperand() : InstructionOperand() {}
+ SubKindOperand() : InstructionOperand(kOperandKind, 0) {} // For the caches.
explicit SubKindOperand(int index)
: InstructionOperand(kOperandKind, index) {}
};
@@ -363,7 +373,15 @@
ZoneList<MoveOperands> move_operands_;
};
-OStream& operator<<(OStream& os, const ParallelMove& pm);
+
+struct PrintableParallelMove {
+ const RegisterConfiguration* register_configuration_;
+ const ParallelMove* parallel_move_;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
+
class PointerMap FINAL : public ZoneObject {
public:
@@ -391,14 +409,14 @@
void RecordUntagged(InstructionOperand* op, Zone* zone);
private:
- friend OStream& operator<<(OStream& os, const PointerMap& pm);
+ friend std::ostream& operator<<(std::ostream& os, const PointerMap& pm);
ZoneList<InstructionOperand*> pointer_operands_;
ZoneList<InstructionOperand*> untagged_operands_;
int instruction_position_;
};
-OStream& operator<<(OStream& os, const PointerMap& pm);
+std::ostream& operator<<(std::ostream& os, const PointerMap& pm);
// TODO(titzer): s/PointerMap/ReferenceMap/
class Instruction : public ZoneObject {
@@ -417,6 +435,10 @@
DCHECK(i < InputCount());
return operands_[OutputCount() + i];
}
+ void SetInputAt(size_t i, InstructionOperand* operand) {
+ DCHECK(i < InputCount());
+ operands_[OutputCount() + i] = operand;
+ }
size_t TempCount() const { return TempCountField::decode(bit_field_); }
InstructionOperand* TempAt(size_t i) const {
@@ -496,6 +518,17 @@
void operator delete(void* pointer, void* location) { UNREACHABLE(); }
+ void OverwriteWithNop() {
+ opcode_ = ArchOpcodeField::encode(kArchNop);
+ bit_field_ = 0;
+ pointer_map_ = NULL;
+ }
+
+ bool IsNop() const {
+ return arch_opcode() == kArchNop && InputCount() == 0 &&
+ OutputCount() == 0 && TempCount() == 0;
+ }
+
protected:
explicit Instruction(InstructionCode opcode)
: opcode_(opcode),
@@ -538,7 +571,13 @@
InstructionOperand* operands_[1];
};
-OStream& operator<<(OStream& os, const Instruction& instr);
+
+struct PrintableInstruction {
+ const RegisterConfiguration* register_configuration_;
+ const Instruction* instr_;
+};
+std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
+
// Represents moves inserted before an instruction due to register allocation.
// TODO(titzer): squash GapInstruction back into Instruction, since essentially
@@ -565,6 +604,14 @@
return parallel_moves_[pos];
}
+ const ParallelMove* GetParallelMove(InnerPosition pos) const {
+ return parallel_moves_[pos];
+ }
+
+ bool IsRedundant() const;
+
+ ParallelMove** parallel_moves() { return parallel_moves_; }
+
static GapInstruction* New(Zone* zone) {
void* buffer = zone->New(sizeof(GapInstruction));
return new (buffer) GapInstruction(kGapInstruction);
@@ -589,22 +636,19 @@
}
private:
- friend OStream& operator<<(OStream& os, const Instruction& instr);
+ friend std::ostream& operator<<(std::ostream& os,
+ const PrintableInstruction& instr);
ParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
};
// This special kind of gap move instruction represents the beginning of a
// block of code.
-// TODO(titzer): move code_start and code_end from BasicBlock to here.
class BlockStartInstruction FINAL : public GapInstruction {
public:
- BasicBlock* block() const { return block_; }
- Label* label() { return &label_; }
-
- static BlockStartInstruction* New(Zone* zone, BasicBlock* block) {
+ static BlockStartInstruction* New(Zone* zone) {
void* buffer = zone->New(sizeof(BlockStartInstruction));
- return new (buffer) BlockStartInstruction(block);
+ return new (buffer) BlockStartInstruction();
}
static BlockStartInstruction* cast(Instruction* instr) {
@@ -612,12 +656,13 @@
return static_cast<BlockStartInstruction*>(instr);
}
- private:
- explicit BlockStartInstruction(BasicBlock* block)
- : GapInstruction(kBlockStartInstruction), block_(block) {}
+ static const BlockStartInstruction* cast(const Instruction* instr) {
+ DCHECK(instr->IsBlockStart());
+ return static_cast<const BlockStartInstruction*>(instr);
+ }
- BasicBlock* block_;
- Label label_;
+ private:
+ BlockStartInstruction() : GapInstruction(kBlockStartInstruction) {}
};
@@ -654,21 +699,34 @@
class Constant FINAL {
public:
- enum Type { kInt32, kInt64, kFloat64, kExternalReference, kHeapObject };
+ enum Type {
+ kInt32,
+ kInt64,
+ kFloat32,
+ kFloat64,
+ kExternalReference,
+ kHeapObject,
+ kRpoNumber
+ };
explicit Constant(int32_t v) : type_(kInt32), value_(v) {}
explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
+ explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
explicit Constant(ExternalReference ref)
: type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
explicit Constant(Handle<HeapObject> obj)
: type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
+ explicit Constant(BasicBlock::RpoNumber rpo)
+ : type_(kRpoNumber), value_(rpo.ToInt()) {}
Type type() const { return type_; }
int32_t ToInt32() const {
- DCHECK_EQ(kInt32, type());
- return static_cast<int32_t>(value_);
+ DCHECK(type() == kInt32 || type() == kInt64);
+ const int32_t value = static_cast<int32_t>(value_);
+ DCHECK_EQ(value_, static_cast<int64_t>(value));
+ return value;
}
int64_t ToInt64() const {
@@ -677,6 +735,11 @@
return value_;
}
+ float ToFloat32() const {
+ DCHECK_EQ(kFloat32, type());
+ return bit_cast<float>(static_cast<int32_t>(value_));
+ }
+
double ToFloat64() const {
if (type() == kInt32) return ToInt32();
DCHECK_EQ(kFloat64, type());
@@ -688,6 +751,11 @@
return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
}
+ BasicBlock::RpoNumber ToRpoNumber() const {
+ DCHECK_EQ(kRpoNumber, type());
+ return BasicBlock::RpoNumber::FromInt(static_cast<int>(value_));
+ }
+
Handle<HeapObject> ToHeapObject() const {
DCHECK_EQ(kHeapObject, type());
return bit_cast<Handle<HeapObject> >(static_cast<intptr_t>(value_));
@@ -701,18 +769,10 @@
class FrameStateDescriptor : public ZoneObject {
public:
- FrameStateDescriptor(const FrameStateCallInfo& state_info,
+ FrameStateDescriptor(Zone* zone, const FrameStateCallInfo& state_info,
size_t parameters_count, size_t locals_count,
size_t stack_count,
- FrameStateDescriptor* outer_state = NULL)
- : type_(state_info.type()),
- bailout_id_(state_info.bailout_id()),
- frame_state_combine_(state_info.state_combine()),
- parameters_count_(parameters_count),
- locals_count_(locals_count),
- stack_count_(stack_count),
- outer_state_(outer_state),
- jsfunction_(state_info.jsfunction()) {}
+ FrameStateDescriptor* outer_state = NULL);
FrameStateType type() const { return type_; }
BailoutId bailout_id() const { return bailout_id_; }
@@ -722,55 +782,17 @@
size_t stack_count() const { return stack_count_; }
FrameStateDescriptor* outer_state() const { return outer_state_; }
MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
-
- size_t size() const {
- return parameters_count_ + locals_count_ + stack_count_ +
- (HasContext() ? 1 : 0);
- }
-
- size_t GetTotalSize() const {
- size_t total_size = 0;
- for (const FrameStateDescriptor* iter = this; iter != NULL;
- iter = iter->outer_state_) {
- total_size += iter->size();
- }
- return total_size;
- }
-
- size_t GetHeight(OutputFrameStateCombine override) const {
- size_t height = size() - parameters_count();
- switch (override) {
- case kPushOutput:
- ++height;
- break;
- case kIgnoreOutput:
- break;
- }
- return height;
- }
-
- size_t GetFrameCount() const {
- size_t count = 0;
- for (const FrameStateDescriptor* iter = this; iter != NULL;
- iter = iter->outer_state_) {
- ++count;
- }
- return count;
- }
-
- size_t GetJSFrameCount() const {
- size_t count = 0;
- for (const FrameStateDescriptor* iter = this; iter != NULL;
- iter = iter->outer_state_) {
- if (iter->type_ == JS_FRAME) {
- ++count;
- }
- }
- return count;
- }
-
bool HasContext() const { return type_ == JS_FRAME; }
+ size_t GetSize(OutputFrameStateCombine combine =
+ OutputFrameStateCombine::Ignore()) const;
+ size_t GetTotalSize() const;
+ size_t GetFrameCount() const;
+ size_t GetJSFrameCount() const;
+
+ MachineType GetType(size_t index) const;
+ void SetType(size_t index, MachineType type);
+
private:
FrameStateType type_;
BailoutId bailout_id_;
@@ -778,11 +800,128 @@
size_t parameters_count_;
size_t locals_count_;
size_t stack_count_;
+ ZoneVector<MachineType> types_;
FrameStateDescriptor* outer_state_;
MaybeHandle<JSFunction> jsfunction_;
};
-OStream& operator<<(OStream& os, const Constant& constant);
+std::ostream& operator<<(std::ostream& os, const Constant& constant);
+
+
+class PhiInstruction FINAL : public ZoneObject {
+ public:
+ typedef ZoneVector<InstructionOperand*> Inputs;
+
+ PhiInstruction(Zone* zone, int virtual_register, size_t reserved_input_count)
+ : virtual_register_(virtual_register),
+ operands_(zone),
+ output_(nullptr),
+ inputs_(zone) {
+ UnallocatedOperand* output =
+ new (zone) UnallocatedOperand(UnallocatedOperand::NONE);
+ output->set_virtual_register(virtual_register);
+ output_ = output;
+ inputs_.reserve(reserved_input_count);
+ operands_.reserve(reserved_input_count);
+ }
+
+ int virtual_register() const { return virtual_register_; }
+ const IntVector& operands() const { return operands_; }
+
+ void Extend(Zone* zone, int virtual_register) {
+ UnallocatedOperand* input =
+ new (zone) UnallocatedOperand(UnallocatedOperand::ANY);
+ input->set_virtual_register(virtual_register);
+ operands_.push_back(virtual_register);
+ inputs_.push_back(input);
+ }
+
+ InstructionOperand* output() const { return output_; }
+ const Inputs& inputs() const { return inputs_; }
+ Inputs& inputs() { return inputs_; }
+
+ private:
+ // TODO(dcarney): some of these fields are only for verification, move them to
+ // verifier.
+ const int virtual_register_;
+ IntVector operands_;
+ InstructionOperand* output_;
+ Inputs inputs_;
+};
+
+
+// Analogue of BasicBlock for Instructions instead of Nodes.
+class InstructionBlock FINAL : public ZoneObject {
+ public:
+ InstructionBlock(Zone* zone, BasicBlock::Id id,
+ BasicBlock::RpoNumber rpo_number,
+ BasicBlock::RpoNumber loop_header,
+ BasicBlock::RpoNumber loop_end, bool deferred);
+
+ // Instruction indexes (used by the register allocator).
+ int first_instruction_index() const {
+ DCHECK(code_start_ >= 0);
+ DCHECK(code_end_ > 0);
+ DCHECK(code_end_ >= code_start_);
+ return code_start_;
+ }
+ int last_instruction_index() const {
+ DCHECK(code_start_ >= 0);
+ DCHECK(code_end_ > 0);
+ DCHECK(code_end_ >= code_start_);
+ return code_end_ - 1;
+ }
+
+ int32_t code_start() const { return code_start_; }
+ void set_code_start(int32_t start) { code_start_ = start; }
+
+ int32_t code_end() const { return code_end_; }
+ void set_code_end(int32_t end) { code_end_ = end; }
+
+ bool IsDeferred() const { return deferred_; }
+
+ BasicBlock::Id id() const { return id_; }
+ BasicBlock::RpoNumber ao_number() const { return ao_number_; }
+ BasicBlock::RpoNumber rpo_number() const { return rpo_number_; }
+ BasicBlock::RpoNumber loop_header() const { return loop_header_; }
+ BasicBlock::RpoNumber loop_end() const {
+ DCHECK(IsLoopHeader());
+ return loop_end_;
+ }
+ inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
+
+ typedef ZoneVector<BasicBlock::RpoNumber> Predecessors;
+ Predecessors& predecessors() { return predecessors_; }
+ const Predecessors& predecessors() const { return predecessors_; }
+ size_t PredecessorCount() const { return predecessors_.size(); }
+ size_t PredecessorIndexOf(BasicBlock::RpoNumber rpo_number) const;
+
+ typedef ZoneVector<BasicBlock::RpoNumber> Successors;
+ Successors& successors() { return successors_; }
+ const Successors& successors() const { return successors_; }
+ size_t SuccessorCount() const { return successors_.size(); }
+
+ typedef ZoneVector<PhiInstruction*> PhiInstructions;
+ const PhiInstructions& phis() const { return phis_; }
+ void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
+
+ void set_ao_number(BasicBlock::RpoNumber ao_number) {
+ ao_number_ = ao_number;
+ }
+
+ private:
+ Successors successors_;
+ Predecessors predecessors_;
+ PhiInstructions phis_;
+ const BasicBlock::Id id_;
+ BasicBlock::RpoNumber ao_number_; // Assembly order number.
+ const BasicBlock::RpoNumber rpo_number_;
+ const BasicBlock::RpoNumber loop_header_;
+ const BasicBlock::RpoNumber loop_end_;
+ int32_t code_start_; // start index of arch-specific code.
+ int32_t code_end_; // end index of arch-specific code.
+ const bool deferred_; // Block contains deferred code.
+};
typedef ZoneDeque<Constant> ConstantDeque;
typedef std::map<int, Constant, std::less<int>,
@@ -791,49 +930,49 @@
typedef ZoneDeque<Instruction*> InstructionDeque;
typedef ZoneDeque<PointerMap*> PointerMapDeque;
typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
+typedef ZoneVector<InstructionBlock*> InstructionBlocks;
+
+struct PrintableInstructionSequence;
+
// Represents architecture-specific generated code before, during, and after
// register allocation.
// TODO(titzer): s/IsDouble/IsFloat64/
-class InstructionSequence FINAL {
+class InstructionSequence FINAL : public ZoneObject {
public:
- InstructionSequence(Linkage* linkage, Graph* graph, Schedule* schedule)
- : graph_(graph),
- linkage_(linkage),
- schedule_(schedule),
- constants_(ConstantMap::key_compare(),
- ConstantMap::allocator_type(zone())),
- immediates_(zone()),
- instructions_(zone()),
- next_virtual_register_(graph->NodeCount()),
- pointer_maps_(zone()),
- doubles_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
- references_(std::less<int>(),
- VirtualRegisterSet::allocator_type(zone())),
- deoptimization_entries_(zone()) {}
+ static InstructionBlocks* InstructionBlocksFor(Zone* zone,
+ const Schedule* schedule);
+ // Puts the deferred blocks last.
+ static void ComputeAssemblyOrder(InstructionBlocks* blocks);
+
+ InstructionSequence(Zone* zone, InstructionBlocks* instruction_blocks);
int NextVirtualRegister() { return next_virtual_register_++; }
int VirtualRegisterCount() const { return next_virtual_register_; }
- int ValueCount() const { return graph_->NodeCount(); }
-
- int BasicBlockCount() const {
- return static_cast<int>(schedule_->rpo_order()->size());
+ const InstructionBlocks& instruction_blocks() const {
+ return *instruction_blocks_;
}
- BasicBlock* BlockAt(int rpo_number) const {
- return (*schedule_->rpo_order())[rpo_number];
+ int InstructionBlockCount() const {
+ return static_cast<int>(instruction_blocks_->size());
}
- BasicBlock* GetContainingLoop(BasicBlock* block) {
- return block->loop_header_;
+ InstructionBlock* InstructionBlockAt(BasicBlock::RpoNumber rpo_number) {
+ return instruction_blocks_->at(rpo_number.ToSize());
}
- int GetLoopEnd(BasicBlock* block) const { return block->loop_end_; }
+ int LastLoopInstructionIndex(const InstructionBlock* block) {
+ return instruction_blocks_->at(block->loop_end().ToSize() - 1)
+ ->last_instruction_index();
+ }
- BasicBlock* GetBasicBlock(int instruction_index);
+ const InstructionBlock* InstructionBlockAt(
+ BasicBlock::RpoNumber rpo_number) const {
+ return instruction_blocks_->at(rpo_number.ToSize());
+ }
- int GetVirtualRegister(Node* node) const { return node->id(); }
+ const InstructionBlock* GetInstructionBlock(int instruction_index) const;
bool IsReference(int virtual_register) const;
bool IsDouble(int virtual_register) const;
@@ -843,12 +982,12 @@
void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to);
- Label* GetLabel(BasicBlock* block);
- BlockStartInstruction* GetBlockStart(BasicBlock* block);
+ BlockStartInstruction* GetBlockStart(BasicBlock::RpoNumber rpo) const;
typedef InstructionDeque::const_iterator const_iterator;
const_iterator begin() const { return instructions_.begin(); }
const_iterator end() const { return instructions_.end(); }
+ const InstructionDeque& instructions() const { return instructions_; }
GapInstruction* GapAt(int index) const {
return GapInstruction::cast(InstructionAt(index));
@@ -860,22 +999,22 @@
return instructions_[index];
}
- Frame* frame() { return &frame_; }
- Graph* graph() const { return graph_; }
Isolate* isolate() const { return zone()->isolate(); }
- Linkage* linkage() const { return linkage_; }
- Schedule* schedule() const { return schedule_; }
const PointerMapDeque* pointer_maps() const { return &pointer_maps_; }
- Zone* zone() const { return graph_->zone(); }
+ Zone* zone() const { return zone_; }
- // Used by the code generator while adding instructions.
- int AddInstruction(Instruction* instr, BasicBlock* block);
- void StartBlock(BasicBlock* block);
- void EndBlock(BasicBlock* block);
+ // Used by the instruction selector while adding instructions.
+ int AddInstruction(Instruction* instr);
+ void StartBlock(BasicBlock::RpoNumber rpo);
+ void EndBlock(BasicBlock::RpoNumber rpo);
- void AddConstant(int virtual_register, Constant constant) {
+ int AddConstant(int virtual_register, Constant constant) {
+ // TODO(titzer): allow RPO numbers as constants?
+ DCHECK(constant.type() != Constant::kRpoNumber);
+ DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
DCHECK(constants_.find(virtual_register) == constants_.end());
constants_.insert(std::make_pair(virtual_register, constant));
+ return virtual_register;
}
Constant GetConstant(int virtual_register) const {
ConstantMap::const_iterator it = constants_.find(virtual_register);
@@ -884,8 +1023,8 @@
return it->second;
}
- typedef ConstantDeque Immediates;
- const Immediates& immediates() const { return immediates_; }
+ typedef ZoneVector<Constant> Immediates;
+ Immediates& immediates() { return immediates_; }
int AddImmediate(Constant constant) {
int index = static_cast<int>(immediates_.size());
@@ -912,26 +1051,43 @@
FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
int GetFrameStateDescriptorCount();
+ BasicBlock::RpoNumber InputRpo(Instruction* instr, size_t index) {
+ InstructionOperand* operand = instr->InputAt(index);
+ Constant constant = operand->IsImmediate() ? GetImmediate(operand->index())
+ : GetConstant(operand->index());
+ return constant.ToRpoNumber();
+ }
+
private:
- friend OStream& operator<<(OStream& os, const InstructionSequence& code);
+ friend std::ostream& operator<<(std::ostream& os,
+ const PrintableInstructionSequence& code);
typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
- Graph* graph_;
- Linkage* linkage_;
- Schedule* schedule_;
+ Zone* const zone_;
+ InstructionBlocks* const instruction_blocks_;
+ IntVector block_starts_;
ConstantMap constants_;
- ConstantDeque immediates_;
+ Immediates immediates_;
InstructionDeque instructions_;
int next_virtual_register_;
PointerMapDeque pointer_maps_;
VirtualRegisterSet doubles_;
VirtualRegisterSet references_;
- Frame frame_;
DeoptimizationVector deoptimization_entries_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
};
-OStream& operator<<(OStream& os, const InstructionSequence& code);
+
+struct PrintableInstructionSequence {
+ const RegisterConfiguration* register_configuration_;
+ const InstructionSequence* sequence_;
+};
+
+
+std::ostream& operator<<(std::ostream& os,
+ const PrintableInstructionSequence& code);
} // namespace compiler
} // namespace internal