Upgrade V8 to 8.8.278.14

Bug: 162604069
Bug: 167389063
Test: gts-tradefed run gts-dev --module GtsGmscoreHostTestCases
      --test com.google.android.gts.devicepolicy.DeviceOwnerTest#testProxyPacProxyTest
Test: m -j proxy_resolver_v8_unittest && adb sync && adb shell \
      /data/nativetest/proxy_resolver_v8_unittest/proxy_resolver_v8_unittest

Merged-In: Ifb09923b9d7f6d8990fb062d7dc0294edf2c098e
Change-Id: Ifb09923b9d7f6d8990fb062d7dc0294edf2c098e
(cherry picked from commit 9580a23bc5b8874a0979001d3595d027cbb68128)
diff --git a/src/compiler/node.cc b/src/compiler/node.cc
index 16dc2db..8525fa0 100644
--- a/src/compiler/node.cc
+++ b/src/compiler/node.cc
@@ -11,7 +11,8 @@
 Node::OutOfLineInputs* Node::OutOfLineInputs::New(Zone* zone, int capacity) {
   size_t size =
       sizeof(OutOfLineInputs) + capacity * (sizeof(Node*) + sizeof(Use));
-  intptr_t raw_buffer = reinterpret_cast<intptr_t>(zone->New(size));
+  intptr_t raw_buffer =
+      reinterpret_cast<intptr_t>(zone->Allocate<Node::OutOfLineInputs>(size));
   Node::OutOfLineInputs* outline =
       reinterpret_cast<OutOfLineInputs*>(raw_buffer + capacity * sizeof(Use));
   outline->capacity_ = capacity;
@@ -19,13 +20,14 @@
   return outline;
 }
 
-
-void Node::OutOfLineInputs::ExtractFrom(Use* old_use_ptr, Node** old_input_ptr,
-                                        int count) {
+void Node::OutOfLineInputs::ExtractFrom(Use* old_use_ptr,
+                                        ZoneNodePtr* old_input_ptr, int count) {
+  DCHECK_GE(count, 0);
   // Extract the inputs from the old use and input pointers and copy them
   // to this out-of-line-storage.
   Use* new_use_ptr = reinterpret_cast<Use*>(this) - 1;
-  Node** new_input_ptr = inputs_;
+  ZoneNodePtr* new_input_ptr = inputs();
+  CHECK_IMPLIES(count > 0, Use::InputIndexField::is_valid(count - 1));
   for (int current = 0; current < count; current++) {
     new_use_ptr->bit_field_ =
         Use::InputIndexField::encode(current) | Use::InlineField::encode(false);
@@ -48,23 +50,29 @@
   this->count_ = count;
 }
 
+// These structs are just type tags for Zone::Allocate<T>(size_t) calls.
+struct NodeWithOutOfLineInputs {};
+struct NodeWithInLineInputs {};
 
-Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count,
-                Node* const* inputs, bool has_extensible_inputs) {
-  Node** input_ptr;
+template <typename NodePtrT>
+Node* Node::NewImpl(Zone* zone, NodeId id, const Operator* op, int input_count,
+                    NodePtrT const* inputs, bool has_extensible_inputs) {
+  // Node uses compressed pointers, so zone must support pointer compression.
+  DCHECK_IMPLIES(kCompressGraphZone, zone->supports_compression());
+  DCHECK_GE(input_count, 0);
+
+  ZoneNodePtr* input_ptr;
   Use* use_ptr;
   Node* node;
   bool is_inline;
 
-#if DEBUG
   // Verify that none of the inputs are {nullptr}.
   for (int i = 0; i < input_count; i++) {
     if (inputs[i] == nullptr) {
-      V8_Fatal(__FILE__, __LINE__, "Node::New() Error: #%d:%s[%d] is nullptr",
-               static_cast<int>(id), op->mnemonic(), i);
+      FATAL("Node::New() Error: #%d:%s[%d] is nullptr", static_cast<int>(id),
+            op->mnemonic(), i);
     }
   }
-#endif
 
   if (input_count > kMaxInlineCapacity) {
     // Allocate out-of-line inputs.
@@ -72,37 +80,42 @@
         has_extensible_inputs ? input_count + kMaxInlineCapacity : input_count;
     OutOfLineInputs* outline = OutOfLineInputs::New(zone, capacity);
 
-    // Allocate node.
-    void* node_buffer = zone->New(sizeof(Node));
+    // Allocate node, with space for OutOfLineInputs pointer.
+    void* node_buffer = zone->Allocate<NodeWithOutOfLineInputs>(
+        sizeof(Node) + sizeof(ZoneOutOfLineInputsPtr));
     node = new (node_buffer) Node(id, op, kOutlineMarker, 0);
-    node->inputs_.outline_ = outline;
+    node->set_outline_inputs(outline);
 
     outline->node_ = node;
     outline->count_ = input_count;
 
-    input_ptr = outline->inputs_;
+    input_ptr = outline->inputs();
     use_ptr = reinterpret_cast<Use*>(outline);
     is_inline = false;
   } else {
-    // Allocate node with inline inputs.
-    int capacity = input_count;
+    // Allocate node with inline inputs. Capacity must be at least 1 so that
+    // an OutOfLineInputs pointer can be stored when inputs are added later.
+    int capacity = std::max(1, input_count);
     if (has_extensible_inputs) {
       const int max = kMaxInlineCapacity;
       capacity = std::min(input_count + 3, max);
     }
 
-    size_t size = sizeof(Node) + capacity * (sizeof(Node*) + sizeof(Use));
-    intptr_t raw_buffer = reinterpret_cast<intptr_t>(zone->New(size));
+    size_t size = sizeof(Node) + capacity * (sizeof(ZoneNodePtr) + sizeof(Use));
+    intptr_t raw_buffer =
+        reinterpret_cast<intptr_t>(zone->Allocate<NodeWithInLineInputs>(size));
     void* node_buffer =
         reinterpret_cast<void*>(raw_buffer + capacity * sizeof(Use));
 
     node = new (node_buffer) Node(id, op, input_count, capacity);
-    input_ptr = node->inputs_.inline_;
+    input_ptr = node->inline_inputs();
     use_ptr = reinterpret_cast<Use*>(node);
     is_inline = true;
   }
 
   // Initialize the input pointers and the uses.
+  CHECK_IMPLIES(input_count > 0,
+                Use::InputIndexField::is_valid(input_count - 1));
   for (int current = 0; current < input_count; ++current) {
     Node* to = *inputs++;
     input_ptr[current] = to;
@@ -115,13 +128,17 @@
   return node;
 }
 
+Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count,
+                Node* const* inputs, bool has_extensible_inputs) {
+  return NewImpl(zone, id, op, input_count, inputs, has_extensible_inputs);
+}
 
 Node* Node::Clone(Zone* zone, NodeId id, const Node* node) {
   int const input_count = node->InputCount();
-  Node* const* const inputs = node->has_inline_inputs()
-                                  ? node->inputs_.inline_
-                                  : node->inputs_.outline_->inputs_;
-  Node* const clone = New(zone, id, node->op(), input_count, inputs, false);
+  ZoneNodePtr const* const inputs = node->has_inline_inputs()
+                                        ? node->inline_inputs()
+                                        : node->outline_inputs()->inputs();
+  Node* const clone = NewImpl(zone, id, node->op(), input_count, inputs, false);
   clone->set_type(node->type());
   return clone;
 }
@@ -138,19 +155,20 @@
   DCHECK_NOT_NULL(zone);
   DCHECK_NOT_NULL(new_to);
 
-  int inline_count = InlineCountField::decode(bit_field_);
-  int inline_capacity = InlineCapacityField::decode(bit_field_);
+  int const inline_count = InlineCountField::decode(bit_field_);
+  int const inline_capacity = InlineCapacityField::decode(bit_field_);
   if (inline_count < inline_capacity) {
     // Append inline input.
     bit_field_ = InlineCountField::update(bit_field_, inline_count + 1);
     *GetInputPtr(inline_count) = new_to;
     Use* use = GetUsePtr(inline_count);
+    STATIC_ASSERT(InlineCapacityField::kMax <= Use::InputIndexField::kMax);
     use->bit_field_ = Use::InputIndexField::encode(inline_count) |
                       Use::InlineField::encode(true);
     new_to->AppendUse(use);
   } else {
     // Append out-of-line input.
-    int input_count = InputCount();
+    int const input_count = InputCount();
     OutOfLineInputs* outline = nullptr;
     if (inline_count != kOutlineMarker) {
       // switch to out of line inputs.
@@ -158,21 +176,22 @@
       outline->node_ = this;
       outline->ExtractFrom(GetUsePtr(0), GetInputPtr(0), input_count);
       bit_field_ = InlineCountField::update(bit_field_, kOutlineMarker);
-      inputs_.outline_ = outline;
+      set_outline_inputs(outline);
     } else {
       // use current out of line inputs.
-      outline = inputs_.outline_;
+      outline = outline_inputs();
       if (input_count >= outline->capacity_) {
         // out of space in out-of-line inputs.
         outline = OutOfLineInputs::New(zone, input_count * 2 + 3);
         outline->node_ = this;
         outline->ExtractFrom(GetUsePtr(0), GetInputPtr(0), input_count);
-        inputs_.outline_ = outline;
+        set_outline_inputs(outline);
       }
     }
     outline->count_++;
     *GetInputPtr(input_count) = new_to;
     Use* use = GetUsePtr(input_count);
+    CHECK(Use::InputIndexField::is_valid(input_count));
     use->bit_field_ = Use::InputIndexField::encode(input_count) |
                       Use::InlineField::encode(false);
     new_to->AppendUse(use);
@@ -199,9 +218,9 @@
   DCHECK_LT(0, count);
   DCHECK_LT(index, InputCount());
   for (int i = 0; i < count; i++) {
-    AppendInput(zone, InputAt(Max(InputCount() - count, 0)));
+    AppendInput(zone, InputAt(std::max(InputCount() - count, 0)));
   }
-  for (int i = InputCount() - count - 1; i >= Max(index, count); --i) {
+  for (int i = InputCount() - count - 1; i >= std::max(index, count); --i) {
     ReplaceInput(i, InputAt(i - count));
   }
   for (int i = 0; i < count; i++) {
@@ -210,19 +229,20 @@
   Verify();
 }
 
-void Node::RemoveInput(int index) {
+Node* Node::RemoveInput(int index) {
   DCHECK_LE(0, index);
   DCHECK_LT(index, InputCount());
+  Node* result = InputAt(index);
   for (; index < InputCount() - 1; ++index) {
     ReplaceInput(index, InputAt(index + 1));
   }
   TrimInputCount(InputCount() - 1);
   Verify();
+  return result;
 }
 
-
 void Node::ClearInputs(int start, int count) {
-  Node** input_ptr = GetInputPtr(start);
+  ZoneNodePtr* input_ptr = GetInputPtr(start);
   Use* use_ptr = GetUsePtr(start);
   while (count-- > 0) {
     DCHECK_EQ(input_ptr, use_ptr->input_ptr());
@@ -247,10 +267,23 @@
   if (has_inline_inputs()) {
     bit_field_ = InlineCountField::update(bit_field_, new_input_count);
   } else {
-    inputs_.outline_->count_ = new_input_count;
+    outline_inputs()->count_ = new_input_count;
   }
 }
 
+void Node::EnsureInputCount(Zone* zone, int new_input_count) {
+  int current_count = InputCount();
+  DCHECK_NE(current_count, 0);
+  if (current_count > new_input_count) {
+    TrimInputCount(new_input_count);
+  } else if (current_count < new_input_count) {
+    Node* dummy = InputAt(current_count - 1);
+    do {
+      AppendInput(zone, dummy);
+      current_count++;
+    } while (current_count < new_input_count);
+  }
+}
 
 int Node::UseCount() const {
   int use_count = 0;
@@ -280,6 +313,17 @@
   first_use_ = nullptr;
 }
 
+bool Node::OwnedBy(Node const* owner) const {
+  unsigned mask = 0;
+  for (Use* use = first_use_; use; use = use->next) {
+    if (use->from() == owner) {
+      mask |= 1;
+    } else {
+      return false;
+    }
+  }
+  return mask == 1;
+}
 
 bool Node::OwnedBy(Node const* owner1, Node const* owner2) const {
   unsigned mask = 0;
@@ -296,26 +340,32 @@
   return mask == 3;
 }
 
-bool Node::OwnedByAddressingOperand() const {
-  for (Use* use = first_use_; use; use = use->next) {
-    Node* from = use->from();
-    if (from->opcode() != IrOpcode::kLoad &&
-        // If {from} is store, make sure it does not use {this} as value
-        (from->opcode() != IrOpcode::kStore || from->InputAt(2) == this) &&
-        from->opcode() != IrOpcode::kInt32Add &&
-        from->opcode() != IrOpcode::kInt64Add) {
-      return false;
-    }
-  }
-  return true;
+void Node::Print(int depth) const {
+  StdoutStream os;
+  Print(os, depth);
 }
 
-void Node::Print() const {
-  OFStream os(stdout);
-  os << *this << std::endl;
-  for (Node* input : this->inputs()) {
-    os << "  " << *input << std::endl;
+namespace {
+void PrintNode(const Node* node, std::ostream& os, int depth,
+               int indentation = 0) {
+  for (int i = 0; i < indentation; ++i) {
+    os << "  ";
   }
+  if (node) {
+    os << *node;
+  } else {
+    os << "(NULL)";
+  }
+  os << std::endl;
+  if (depth <= 0) return;
+  for (Node* input : node->inputs()) {
+    PrintNode(input, os, depth - 1, indentation + 1);
+  }
+}
+}  // namespace
+
+void Node::Print(std::ostream& os, int depth) const {
+  PrintNode(this, os, depth);
 }
 
 std::ostream& operator<<(std::ostream& os, const Node& n) {
@@ -337,14 +387,17 @@
 
 Node::Node(NodeId id, const Operator* op, int inline_count, int inline_capacity)
     : op_(op),
-      type_(nullptr),
       mark_(0),
       bit_field_(IdField::encode(id) | InlineCountField::encode(inline_count) |
                  InlineCapacityField::encode(inline_capacity)),
       first_use_(nullptr) {
+  // Check that the id didn't overflow.
+  STATIC_ASSERT(IdField::kMax < std::numeric_limits<NodeId>::max());
+  CHECK(IdField::is_valid(id));
+
   // Inputs must either be out of line or within the inline capacity.
-  DCHECK(inline_capacity <= kMaxInlineCapacity);
   DCHECK(inline_count == kOutlineMarker || inline_count <= inline_capacity);
+  DCHECK_LE(inline_capacity, kMaxInlineCapacity);
 }
 
 
@@ -375,7 +428,7 @@
 
 #if DEBUG
 void Node::Verify() {
-  // Check basic sanity of input data structures.
+  // Check basic validity of input data structures.
   fflush(stdout);
   int count = this->InputCount();
   // Avoid quadratic explosion for mega nodes; only verify if the input
@@ -383,29 +436,29 @@
   if (count > 200 && count % 100) return;
 
   for (int i = 0; i < count; i++) {
-    CHECK_EQ(i, this->GetUsePtr(i)->input_index());
-    CHECK_EQ(this->GetInputPtr(i), this->GetUsePtr(i)->input_ptr());
-    CHECK_EQ(count, this->InputCount());
+    DCHECK_EQ(i, this->GetUsePtr(i)->input_index());
+    DCHECK_EQ(this->GetInputPtr(i), this->GetUsePtr(i)->input_ptr());
+    DCHECK_EQ(count, this->InputCount());
   }
   {  // Direct input iteration.
     int index = 0;
     for (Node* input : this->inputs()) {
-      CHECK_EQ(this->InputAt(index), input);
+      DCHECK_EQ(this->InputAt(index), input);
       index++;
     }
-    CHECK_EQ(count, index);
-    CHECK_EQ(this->InputCount(), index);
+    DCHECK_EQ(count, index);
+    DCHECK_EQ(this->InputCount(), index);
   }
   {  // Input edge iteration.
     int index = 0;
     for (Edge edge : this->input_edges()) {
-      CHECK_EQ(edge.from(), this);
-      CHECK_EQ(index, edge.index());
-      CHECK_EQ(this->InputAt(index), edge.to());
+      DCHECK_EQ(edge.from(), this);
+      DCHECK_EQ(index, edge.index());
+      DCHECK_EQ(this->InputAt(index), edge.to());
       index++;
     }
-    CHECK_EQ(count, index);
-    CHECK_EQ(this->InputCount(), index);
+    DCHECK_EQ(count, index);
+    DCHECK_EQ(this->InputCount(), index);
   }
 }
 #endif