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.cc b/src/compiler/instruction.cc
index 9ab81b6..f83cdeb 100644
--- a/src/compiler/instruction.cc
+++ b/src/compiler/instruction.cc
@@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/instruction.h"
-
#include "src/compiler/common-operator.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/instruction.h"
namespace v8 {
namespace internal {
namespace compiler {
-OStream& operator<<(OStream& os, const InstructionOperand& op) {
+std::ostream& operator<<(std::ostream& os,
+ const PrintableInstructionOperand& printable) {
+ const InstructionOperand& op = *printable.op_;
+ const RegisterConfiguration* conf = printable.register_configuration_;
switch (op.kind()) {
- case InstructionOperand::INVALID:
- return os << "(0)";
case InstructionOperand::UNALLOCATED: {
const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op);
os << "v" << unalloc->virtual_register();
@@ -24,10 +25,10 @@
case UnallocatedOperand::NONE:
return os;
case UnallocatedOperand::FIXED_REGISTER:
- return os << "(=" << Register::AllocationIndexToString(
+ return os << "(=" << conf->general_register_name(
unalloc->fixed_register_index()) << ")";
case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
- return os << "(=" << DoubleRegister::AllocationIndexToString(
+ return os << "(=" << conf->double_register_name(
unalloc->fixed_register_index()) << ")";
case UnallocatedOperand::MUST_HAVE_REGISTER:
return os << "(R)";
@@ -46,11 +47,9 @@
case InstructionOperand::DOUBLE_STACK_SLOT:
return os << "[double_stack:" << op.index() << "]";
case InstructionOperand::REGISTER:
- return os << "[" << Register::AllocationIndexToString(op.index())
- << "|R]";
+ return os << "[" << conf->general_register_name(op.index()) << "|R]";
case InstructionOperand::DOUBLE_REGISTER:
- return os << "[" << DoubleRegister::AllocationIndexToString(op.index())
- << "|R]";
+ return os << "[" << conf->double_register_name(op.index()) << "|R]";
}
UNREACHABLE();
return os;
@@ -95,9 +94,17 @@
}
-OStream& operator<<(OStream& os, const MoveOperands& mo) {
- os << *mo.destination();
- if (!mo.source()->Equals(mo.destination())) os << " = " << *mo.source();
+std::ostream& operator<<(std::ostream& os,
+ const PrintableMoveOperands& printable) {
+ const MoveOperands& mo = *printable.move_operands_;
+ PrintableInstructionOperand printable_op = {printable.register_configuration_,
+ mo.destination()};
+
+ os << printable_op;
+ if (!mo.source()->Equals(mo.destination())) {
+ printable_op.op_ = mo.source();
+ os << " = " << printable_op;
+ }
return os << ";";
}
@@ -110,14 +117,27 @@
}
-OStream& operator<<(OStream& os, const ParallelMove& pm) {
+bool GapInstruction::IsRedundant() const {
+ for (int i = GapInstruction::FIRST_INNER_POSITION;
+ i <= GapInstruction::LAST_INNER_POSITION; i++) {
+ if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant())
+ return false;
+ }
+ return true;
+}
+
+
+std::ostream& operator<<(std::ostream& os,
+ const PrintableParallelMove& printable) {
+ const ParallelMove& pm = *printable.parallel_move_;
bool first = true;
for (ZoneList<MoveOperands>::iterator move = pm.move_operands()->begin();
move != pm.move_operands()->end(); ++move) {
if (move->IsEliminated()) continue;
if (!first) os << " ";
first = false;
- os << *move;
+ PrintableMoveOperands pmo = {printable.register_configuration_, move};
+ os << pmo;
}
return os;
}
@@ -152,7 +172,7 @@
}
-OStream& operator<<(OStream& os, const PointerMap& pm) {
+std::ostream& operator<<(std::ostream& os, const PointerMap& pm) {
os << "{";
for (ZoneList<InstructionOperand*>::iterator op =
pm.pointer_operands_.begin();
@@ -164,7 +184,7 @@
}
-OStream& operator<<(OStream& os, const ArchOpcode& ao) {
+std::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) {
switch (ao) {
#define CASE(Name) \
case k##Name: \
@@ -177,7 +197,7 @@
}
-OStream& operator<<(OStream& os, const AddressingMode& am) {
+std::ostream& operator<<(std::ostream& os, const AddressingMode& am) {
switch (am) {
case kMode_None:
return os;
@@ -192,7 +212,7 @@
}
-OStream& operator<<(OStream& os, const FlagsMode& fm) {
+std::ostream& operator<<(std::ostream& os, const FlagsMode& fm) {
switch (fm) {
case kFlags_none:
return os;
@@ -206,7 +226,7 @@
}
-OStream& operator<<(OStream& os, const FlagsCondition& fc) {
+std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
switch (fc) {
case kEqual:
return os << "equal";
@@ -250,11 +270,16 @@
}
-OStream& operator<<(OStream& os, const Instruction& instr) {
+std::ostream& operator<<(std::ostream& os,
+ const PrintableInstruction& printable) {
+ const Instruction& instr = *printable.instr_;
+ PrintableInstructionOperand printable_op = {printable.register_configuration_,
+ NULL};
if (instr.OutputCount() > 1) os << "(";
for (size_t i = 0; i < instr.OutputCount(); i++) {
if (i > 0) os << ", ";
- os << *instr.OutputAt(i);
+ printable_op.op_ = instr.OutputAt(i);
+ os << printable_op;
}
if (instr.OutputCount() > 1) os << ") = ";
@@ -266,7 +291,11 @@
for (int i = GapInstruction::FIRST_INNER_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) {
os << "(";
- if (gap->parallel_moves_[i] != NULL) os << *gap->parallel_moves_[i];
+ if (gap->parallel_moves_[i] != NULL) {
+ PrintableParallelMove ppm = {printable.register_configuration_,
+ gap->parallel_moves_[i]};
+ os << ppm;
+ }
os << ") ";
}
} else if (instr.IsSourcePosition()) {
@@ -287,57 +316,175 @@
}
if (instr.InputCount() > 0) {
for (size_t i = 0; i < instr.InputCount(); i++) {
- os << " " << *instr.InputAt(i);
+ printable_op.op_ = instr.InputAt(i);
+ os << " " << printable_op;
}
}
- return os << "\n";
+ return os;
}
-OStream& operator<<(OStream& os, const Constant& constant) {
+std::ostream& operator<<(std::ostream& os, const Constant& constant) {
switch (constant.type()) {
case Constant::kInt32:
return os << constant.ToInt32();
case Constant::kInt64:
return os << constant.ToInt64() << "l";
+ case Constant::kFloat32:
+ return os << constant.ToFloat32() << "f";
case Constant::kFloat64:
return os << constant.ToFloat64();
case Constant::kExternalReference:
- return os << constant.ToExternalReference().address();
+ return os << static_cast<const void*>(
+ constant.ToExternalReference().address());
case Constant::kHeapObject:
return os << Brief(*constant.ToHeapObject());
+ case Constant::kRpoNumber:
+ return os << "RPO" << constant.ToRpoNumber().ToInt();
}
UNREACHABLE();
return os;
}
-Label* InstructionSequence::GetLabel(BasicBlock* block) {
- return GetBlockStart(block)->label();
+InstructionBlock::InstructionBlock(Zone* zone, BasicBlock::Id id,
+ BasicBlock::RpoNumber rpo_number,
+ BasicBlock::RpoNumber loop_header,
+ BasicBlock::RpoNumber loop_end,
+ bool deferred)
+ : successors_(zone),
+ predecessors_(zone),
+ phis_(zone),
+ id_(id),
+ ao_number_(rpo_number),
+ rpo_number_(rpo_number),
+ loop_header_(loop_header),
+ loop_end_(loop_end),
+ code_start_(-1),
+ code_end_(-1),
+ deferred_(deferred) {}
+
+
+size_t InstructionBlock::PredecessorIndexOf(
+ BasicBlock::RpoNumber rpo_number) const {
+ size_t j = 0;
+ for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin();
+ i != predecessors_.end(); ++i, ++j) {
+ if (*i == rpo_number) break;
+ }
+ return j;
}
-BlockStartInstruction* InstructionSequence::GetBlockStart(BasicBlock* block) {
- return BlockStartInstruction::cast(InstructionAt(block->code_start_));
+static BasicBlock::RpoNumber GetRpo(BasicBlock* block) {
+ if (block == NULL) return BasicBlock::RpoNumber::Invalid();
+ return block->GetRpoNumber();
}
-void InstructionSequence::StartBlock(BasicBlock* block) {
- block->code_start_ = static_cast<int>(instructions_.size());
- BlockStartInstruction* block_start =
- BlockStartInstruction::New(zone(), block);
- AddInstruction(block_start, block);
+static BasicBlock::RpoNumber GetLoopEndRpo(const BasicBlock* block) {
+ if (!block->IsLoopHeader()) return BasicBlock::RpoNumber::Invalid();
+ return block->loop_end()->GetRpoNumber();
}
-void InstructionSequence::EndBlock(BasicBlock* block) {
+static InstructionBlock* InstructionBlockFor(Zone* zone,
+ const BasicBlock* block) {
+ InstructionBlock* instr_block = new (zone) InstructionBlock(
+ zone, block->id(), block->GetRpoNumber(), GetRpo(block->loop_header()),
+ GetLoopEndRpo(block), block->deferred());
+ // Map successors and precessors
+ instr_block->successors().reserve(block->SuccessorCount());
+ for (auto it = block->successors_begin(); it != block->successors_end();
+ ++it) {
+ instr_block->successors().push_back((*it)->GetRpoNumber());
+ }
+ instr_block->predecessors().reserve(block->PredecessorCount());
+ for (auto it = block->predecessors_begin(); it != block->predecessors_end();
+ ++it) {
+ instr_block->predecessors().push_back((*it)->GetRpoNumber());
+ }
+ return instr_block;
+}
+
+
+InstructionBlocks* InstructionSequence::InstructionBlocksFor(
+ Zone* zone, const Schedule* schedule) {
+ InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
+ new (blocks) InstructionBlocks(
+ static_cast<int>(schedule->rpo_order()->size()), NULL, zone);
+ size_t rpo_number = 0;
+ for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin();
+ it != schedule->rpo_order()->end(); ++it, ++rpo_number) {
+ DCHECK_EQ(NULL, (*blocks)[rpo_number]);
+ DCHECK((*it)->GetRpoNumber().ToSize() == rpo_number);
+ (*blocks)[rpo_number] = InstructionBlockFor(zone, *it);
+ }
+ ComputeAssemblyOrder(blocks);
+ return blocks;
+}
+
+
+void InstructionSequence::ComputeAssemblyOrder(InstructionBlocks* blocks) {
+ int ao = 0;
+ for (auto const block : *blocks) {
+ if (!block->IsDeferred()) {
+ block->set_ao_number(BasicBlock::RpoNumber::FromInt(ao++));
+ }
+ }
+ for (auto const block : *blocks) {
+ if (block->IsDeferred()) {
+ block->set_ao_number(BasicBlock::RpoNumber::FromInt(ao++));
+ }
+ }
+}
+
+
+InstructionSequence::InstructionSequence(Zone* instruction_zone,
+ InstructionBlocks* instruction_blocks)
+ : zone_(instruction_zone),
+ instruction_blocks_(instruction_blocks),
+ block_starts_(zone()),
+ constants_(ConstantMap::key_compare(),
+ ConstantMap::allocator_type(zone())),
+ immediates_(zone()),
+ instructions_(zone()),
+ next_virtual_register_(0),
+ pointer_maps_(zone()),
+ doubles_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
+ references_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
+ deoptimization_entries_(zone()) {
+ block_starts_.reserve(instruction_blocks_->size());
+}
+
+
+BlockStartInstruction* InstructionSequence::GetBlockStart(
+ BasicBlock::RpoNumber rpo) const {
+ const InstructionBlock* block = InstructionBlockAt(rpo);
+ return BlockStartInstruction::cast(InstructionAt(block->code_start()));
+}
+
+
+void InstructionSequence::StartBlock(BasicBlock::RpoNumber rpo) {
+ DCHECK(block_starts_.size() == rpo.ToSize());
+ InstructionBlock* block = InstructionBlockAt(rpo);
+ int code_start = static_cast<int>(instructions_.size());
+ block->set_code_start(code_start);
+ block_starts_.push_back(code_start);
+ BlockStartInstruction* block_start = BlockStartInstruction::New(zone());
+ AddInstruction(block_start);
+}
+
+
+void InstructionSequence::EndBlock(BasicBlock::RpoNumber rpo) {
int end = static_cast<int>(instructions_.size());
- DCHECK(block->code_start_ >= 0 && block->code_start_ < end);
- block->code_end_ = end;
+ InstructionBlock* block = InstructionBlockAt(rpo);
+ DCHECK(block->code_start() >= 0 && block->code_start() < end);
+ block->set_code_end(end);
}
-int InstructionSequence::AddInstruction(Instruction* instr, BasicBlock* block) {
+int InstructionSequence::AddInstruction(Instruction* instr) {
// TODO(titzer): the order of these gaps is a holdover from Lithium.
GapInstruction* gap = GapInstruction::New(zone());
if (instr->IsControl()) instructions_.push_back(gap);
@@ -355,15 +502,17 @@
}
-BasicBlock* InstructionSequence::GetBasicBlock(int instruction_index) {
- // TODO(turbofan): Optimize this.
- for (;;) {
- DCHECK_LE(0, instruction_index);
- Instruction* instruction = InstructionAt(instruction_index--);
- if (instruction->IsBlockStart()) {
- return BlockStartInstruction::cast(instruction)->block();
- }
- }
+const InstructionBlock* InstructionSequence::GetInstructionBlock(
+ int instruction_index) const {
+ DCHECK(instruction_blocks_->size() == block_starts_.size());
+ auto begin = block_starts_.begin();
+ auto end = std::lower_bound(begin, block_starts_.end(), instruction_index,
+ std::less_equal<int>());
+ size_t index = std::distance(begin, end) - 1;
+ auto block = instruction_blocks_->at(index);
+ DCHECK(block->code_start() <= instruction_index &&
+ instruction_index < block->code_end());
+ return block;
}
@@ -412,7 +561,81 @@
}
-OStream& operator<<(OStream& os, const InstructionSequence& code) {
+FrameStateDescriptor::FrameStateDescriptor(
+ Zone* zone, const FrameStateCallInfo& state_info, size_t parameters_count,
+ size_t locals_count, size_t stack_count, FrameStateDescriptor* outer_state)
+ : 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),
+ types_(zone),
+ outer_state_(outer_state),
+ jsfunction_(state_info.jsfunction()) {
+ types_.resize(GetSize(), kMachNone);
+}
+
+size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const {
+ size_t size = parameters_count() + locals_count() + stack_count() +
+ (HasContext() ? 1 : 0);
+ switch (combine.kind()) {
+ case OutputFrameStateCombine::kPushOutput:
+ size += combine.GetPushCount();
+ break;
+ case OutputFrameStateCombine::kPokeAt:
+ break;
+ }
+ return size;
+}
+
+
+size_t FrameStateDescriptor::GetTotalSize() const {
+ size_t total_size = 0;
+ for (const FrameStateDescriptor* iter = this; iter != NULL;
+ iter = iter->outer_state_) {
+ total_size += iter->GetSize();
+ }
+ return total_size;
+}
+
+
+size_t FrameStateDescriptor::GetFrameCount() const {
+ size_t count = 0;
+ for (const FrameStateDescriptor* iter = this; iter != NULL;
+ iter = iter->outer_state_) {
+ ++count;
+ }
+ return count;
+}
+
+
+size_t FrameStateDescriptor::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;
+}
+
+
+MachineType FrameStateDescriptor::GetType(size_t index) const {
+ return types_[index];
+}
+
+
+void FrameStateDescriptor::SetType(size_t index, MachineType type) {
+ DCHECK(index < GetSize());
+ types_[index] = type;
+}
+
+
+std::ostream& operator<<(std::ostream& os,
+ const PrintableInstructionSequence& printable) {
+ const InstructionSequence& code = *printable.sequence_;
for (size_t i = 0; i < code.immediates_.size(); ++i) {
Constant constant = code.immediates_[i];
os << "IMM#" << i << ": " << constant << "\n";
@@ -422,57 +645,53 @@
it != code.constants_.end(); ++i, ++it) {
os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n";
}
- for (int i = 0; i < code.BasicBlockCount(); i++) {
- BasicBlock* block = code.BlockAt(i);
+ for (int i = 0; i < code.InstructionBlockCount(); i++) {
+ BasicBlock::RpoNumber rpo = BasicBlock::RpoNumber::FromInt(i);
+ const InstructionBlock* block = code.InstructionBlockAt(rpo);
+ CHECK(block->rpo_number() == rpo);
- int bid = block->id();
- os << "RPO#" << block->rpo_number_ << ": B" << bid;
- CHECK(block->rpo_number_ == i);
+ os << "RPO#" << block->rpo_number();
+ os << ": AO#" << block->ao_number();
+ os << ": B" << block->id();
+ if (block->IsDeferred()) os << " (deferred)";
if (block->IsLoopHeader()) {
- os << " loop blocks: [" << block->rpo_number_ << ", " << block->loop_end_
- << ")";
+ os << " loop blocks: [" << block->rpo_number() << ", "
+ << block->loop_end() << ")";
}
- os << " instructions: [" << block->code_start_ << ", " << block->code_end_
- << ")\n predecessors:";
+ os << " instructions: [" << block->code_start() << ", "
+ << block->code_end() << ")\n predecessors:";
- BasicBlock::Predecessors predecessors = block->predecessors();
- for (BasicBlock::Predecessors::iterator iter = predecessors.begin();
- iter != predecessors.end(); ++iter) {
- os << " B" << (*iter)->id();
+ for (auto pred : block->predecessors()) {
+ const InstructionBlock* pred_block = code.InstructionBlockAt(pred);
+ os << " B" << pred_block->id();
}
os << "\n";
- for (BasicBlock::const_iterator j = block->begin(); j != block->end();
- ++j) {
- Node* phi = *j;
- if (phi->opcode() != IrOpcode::kPhi) continue;
- os << " phi: v" << phi->id() << " =";
- Node::Inputs inputs = phi->inputs();
- for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
- ++iter) {
- os << " v" << (*iter)->id();
+ for (auto phi : block->phis()) {
+ PrintableInstructionOperand printable_op = {
+ printable.register_configuration_, phi->output()};
+ os << " phi: " << printable_op << " =";
+ for (auto input : phi->inputs()) {
+ printable_op.op_ = input;
+ os << " " << printable_op;
}
os << "\n";
}
ScopedVector<char> buf(32);
+ PrintableInstruction printable_instr;
+ printable_instr.register_configuration_ = printable.register_configuration_;
for (int j = block->first_instruction_index();
j <= block->last_instruction_index(); j++) {
// TODO(svenpanne) Add some basic formatting to our streams.
SNPrintF(buf, "%5d", j);
- os << " " << buf.start() << ": " << *code.InstructionAt(j);
+ printable_instr.instr_ = code.InstructionAt(j);
+ os << " " << buf.start() << ": " << printable_instr << "\n";
}
- os << " " << block->control_;
-
- if (block->control_input_ != NULL) {
- os << " v" << block->control_input_->id();
- }
-
- BasicBlock::Successors successors = block->successors();
- for (BasicBlock::Successors::iterator iter = successors.begin();
- iter != successors.end(); ++iter) {
- os << " B" << (*iter)->id();
+ for (auto succ : block->successors()) {
+ const InstructionBlock* succ_block = code.InstructionBlockAt(succ);
+ os << " B" << succ_block->id();
}
os << "\n";
}