Merge V8 5.2.361.47  DO NOT MERGE

https://chromium.googlesource.com/v8/v8/+/5.2.361.47

FPIIM-449

Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/compiler/instruction.cc b/src/compiler/instruction.cc
index c757557..26aebca 100644
--- a/src/compiler/instruction.cc
+++ b/src/compiler/instruction.cc
@@ -127,12 +127,12 @@
       LocationOperand allocated = LocationOperand::cast(op);
       if (op.IsStackSlot()) {
         os << "[stack:" << LocationOperand::cast(op).index();
-      } else if (op.IsDoubleStackSlot()) {
-        os << "[double_stack:" << LocationOperand::cast(op).index();
+      } else if (op.IsFPStackSlot()) {
+        os << "[fp_stack:" << LocationOperand::cast(op).index();
       } else if (op.IsRegister()) {
         os << "[" << LocationOperand::cast(op).GetRegister().ToString() << "|R";
       } else {
-        DCHECK(op.IsDoubleRegister());
+        DCHECK(op.IsFPRegister());
         os << "[" << LocationOperand::cast(op).GetDoubleRegister().ToString()
            << "|R";
       }
@@ -251,17 +251,16 @@
                  DoubleRegister::from_code(index).IsAllocatable());
 }
 
-
 Instruction::Instruction(InstructionCode opcode)
     : opcode_(opcode),
       bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
                  TempCountField::encode(0) | IsCallField::encode(false)),
-      reference_map_(nullptr) {
+      reference_map_(nullptr),
+      block_(nullptr) {
   parallel_moves_[0] = nullptr;
   parallel_moves_[1] = nullptr;
 }
 
-
 Instruction::Instruction(InstructionCode opcode, size_t output_count,
                          InstructionOperand* outputs, size_t input_count,
                          InstructionOperand* inputs, size_t temp_count,
@@ -271,7 +270,8 @@
                  InputCountField::encode(input_count) |
                  TempCountField::encode(temp_count) |
                  IsCallField::encode(false)),
-      reference_map_(nullptr) {
+      reference_map_(nullptr),
+      block_(nullptr) {
   parallel_moves_[0] = nullptr;
   parallel_moves_[1] = nullptr;
   size_t offset = 0;
@@ -335,7 +335,7 @@
 void ReferenceMap::RecordReference(const AllocatedOperand& op) {
   // Do not record arguments as pointers.
   if (op.IsStackSlot() && LocationOperand::cast(op).index() < 0) return;
-  DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot());
+  DCHECK(!op.IsFPRegister() && !op.IsFPStackSlot());
   reference_operands_.push_back(op);
 }
 
@@ -504,6 +504,27 @@
 
 Constant::Constant(int32_t v) : type_(kInt32), value_(v) {}
 
+Constant::Constant(RelocatablePtrConstantInfo info) {
+  if (info.type() == RelocatablePtrConstantInfo::kInt32) {
+    type_ = kInt32;
+  } else if (info.type() == RelocatablePtrConstantInfo::kInt64) {
+    type_ = kInt64;
+  } else {
+    UNREACHABLE();
+  }
+  value_ = info.value();
+  rmode_ = info.rmode();
+}
+
+Handle<HeapObject> Constant::ToHeapObject() const {
+  DCHECK_EQ(kHeapObject, type());
+  Handle<HeapObject> value(
+      bit_cast<HeapObject**>(static_cast<intptr_t>(value_)));
+  if (value->IsConsString()) {
+    value = String::Flatten(Handle<String>::cast(value), TENURED);
+  }
+  return value;
+}
 
 std::ostream& operator<<(std::ostream& os, const Constant& constant) {
   switch (constant.type()) {
@@ -603,7 +624,6 @@
   return instr_block;
 }
 
-
 InstructionBlocks* InstructionSequence::InstructionBlocksFor(
     Zone* zone, const Schedule* schedule) {
   InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
@@ -620,7 +640,7 @@
   return blocks;
 }
 
-void InstructionSequence::ValidateEdgeSplitForm() {
+void InstructionSequence::ValidateEdgeSplitForm() const {
   // Validate blocks are in edge-split form: no block with multiple successors
   // has an edge to a block (== a successor) with more than one predecessors.
   for (const InstructionBlock* block : instruction_blocks()) {
@@ -635,7 +655,7 @@
   }
 }
 
-void InstructionSequence::ValidateDeferredBlockExitPaths() {
+void InstructionSequence::ValidateDeferredBlockExitPaths() const {
   // A deferred block with more than one successor must have all its successors
   // deferred.
   for (const InstructionBlock* block : instruction_blocks()) {
@@ -646,7 +666,21 @@
   }
 }
 
-void InstructionSequence::ValidateSSA() {
+void InstructionSequence::ValidateDeferredBlockEntryPaths() const {
+  // If a deferred block has multiple predecessors, they have to
+  // all be deferred. Otherwise, we can run into a situation where a range
+  // that spills only in deferred blocks inserts its spill in the block, but
+  // other ranges need moves inserted by ResolveControlFlow in the predecessors,
+  // which may clobber the register of this range.
+  for (const InstructionBlock* block : instruction_blocks()) {
+    if (!block->IsDeferred() || block->PredecessorCount() <= 1) continue;
+    for (RpoNumber predecessor_id : block->predecessors()) {
+      CHECK(InstructionBlockAt(predecessor_id)->IsDeferred());
+    }
+  }
+}
+
+void InstructionSequence::ValidateSSA() const {
   // TODO(mtrofin): We could use a local zone here instead.
   BitVector definitions(VirtualRegisterCount(), zone());
   for (const Instruction* instruction : *this) {
@@ -675,7 +709,6 @@
   }
 }
 
-
 InstructionSequence::InstructionSequence(Isolate* isolate,
                                          Zone* instruction_zone,
                                          InstructionBlocks* instruction_blocks)
@@ -683,7 +716,6 @@
       zone_(instruction_zone),
       instruction_blocks_(instruction_blocks),
       source_positions_(zone()),
-      block_starts_(zone()),
       constants_(ConstantMap::key_compare(),
                  ConstantMap::allocator_type(zone())),
       immediates_(zone()),
@@ -691,10 +723,8 @@
       next_virtual_register_(0),
       reference_maps_(zone()),
       representations_(zone()),
-      deoptimization_entries_(zone()) {
-  block_starts_.reserve(instruction_blocks_->size());
-}
-
+      deoptimization_entries_(zone()),
+      current_block_(nullptr) {}
 
 int InstructionSequence::NextVirtualRegister() {
   int virtual_register = next_virtual_register_++;
@@ -710,28 +740,31 @@
 
 
 void InstructionSequence::StartBlock(RpoNumber rpo) {
-  DCHECK(block_starts_.size() == rpo.ToSize());
-  InstructionBlock* block = InstructionBlockAt(rpo);
+  DCHECK_NULL(current_block_);
+  current_block_ = InstructionBlockAt(rpo);
   int code_start = static_cast<int>(instructions_.size());
-  block->set_code_start(code_start);
-  block_starts_.push_back(code_start);
+  current_block_->set_code_start(code_start);
 }
 
 
 void InstructionSequence::EndBlock(RpoNumber rpo) {
   int end = static_cast<int>(instructions_.size());
-  InstructionBlock* block = InstructionBlockAt(rpo);
-  if (block->code_start() == end) {  // Empty block.  Insert a nop.
+  DCHECK_EQ(current_block_->rpo_number(), rpo);
+  if (current_block_->code_start() == end) {  // Empty block.  Insert a nop.
     AddInstruction(Instruction::New(zone(), kArchNop));
     end = static_cast<int>(instructions_.size());
   }
-  DCHECK(block->code_start() >= 0 && block->code_start() < end);
-  block->set_code_end(end);
+  DCHECK(current_block_->code_start() >= 0 &&
+         current_block_->code_start() < end);
+  current_block_->set_code_end(end);
+  current_block_ = nullptr;
 }
 
 
 int InstructionSequence::AddInstruction(Instruction* instr) {
+  DCHECK_NOT_NULL(current_block_);
   int index = static_cast<int>(instructions_.size());
+  instr->set_block(current_block_);
   instructions_.push_back(instr);
   if (instr->NeedsReferenceMap()) {
     DCHECK(instr->reference_map() == nullptr);
@@ -746,18 +779,7 @@
 
 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);
-  // Post condition of std::lower_bound:
-  DCHECK(end == block_starts_.end() || *end >= instruction_index);
-  if (end == block_starts_.end() || *end > instruction_index) --end;
-  DCHECK(*end <= instruction_index);
-  size_t index = std::distance(begin, end);
-  InstructionBlock* block = instruction_blocks_->at(index);
-  DCHECK(block->code_start() <= instruction_index &&
-         instruction_index < block->code_end());
-  return block;
+  return instructions()[instruction_index]->block();
 }