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/memory-optimizer.h b/src/compiler/memory-optimizer.h
new file mode 100644
index 0000000..f0cd546
--- /dev/null
+++ b/src/compiler/memory-optimizer.h
@@ -0,0 +1,149 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_MEMORY_OPTIMIZER_H_
+#define V8_COMPILER_MEMORY_OPTIMIZER_H_
+
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Forward declarations.
+class CommonOperatorBuilder;
+struct ElementAccess;
+class Graph;
+class JSGraph;
+class MachineOperatorBuilder;
+class Node;
+class Operator;
+
+// NodeIds are identifying numbers for nodes that can be used to index auxiliary
+// out-of-line data associated with each node.
+typedef uint32_t NodeId;
+
+// Lowers all simplified memory access and allocation related nodes (i.e.
+// Allocate, LoadField, StoreField and friends) to machine operators.
+// Performs allocation folding and store write barrier elimination
+// implicitly.
+class MemoryOptimizer final {
+ public:
+  MemoryOptimizer(JSGraph* jsgraph, Zone* zone);
+  ~MemoryOptimizer() {}
+
+  void Optimize();
+
+ private:
+  // An allocation group represents a set of allocations that have been folded
+  // together.
+  class AllocationGroup final : public ZoneObject {
+   public:
+    AllocationGroup(Node* node, PretenureFlag pretenure, Zone* zone);
+    AllocationGroup(Node* node, PretenureFlag pretenure, Node* size,
+                    Zone* zone);
+    ~AllocationGroup() {}
+
+    void Add(Node* object);
+    bool Contains(Node* object) const;
+    bool IsNewSpaceAllocation() const { return pretenure() == NOT_TENURED; }
+
+    PretenureFlag pretenure() const { return pretenure_; }
+    Node* size() const { return size_; }
+
+   private:
+    ZoneSet<NodeId> node_ids_;
+    PretenureFlag const pretenure_;
+    Node* const size_;
+
+    DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationGroup);
+  };
+
+  // An allocation state is propagated on the effect paths through the graph.
+  class AllocationState final : public ZoneObject {
+   public:
+    static AllocationState const* Empty(Zone* zone) {
+      return new (zone) AllocationState();
+    }
+    static AllocationState const* Closed(AllocationGroup* group, Zone* zone) {
+      return new (zone) AllocationState(group);
+    }
+    static AllocationState const* Open(AllocationGroup* group, int size,
+                                       Node* top, Zone* zone) {
+      return new (zone) AllocationState(group, size, top);
+    }
+
+    bool IsNewSpaceAllocation() const;
+
+    AllocationGroup* group() const { return group_; }
+    Node* top() const { return top_; }
+    int size() const { return size_; }
+
+   private:
+    AllocationState();
+    explicit AllocationState(AllocationGroup* group);
+    AllocationState(AllocationGroup* group, int size, Node* top);
+
+    AllocationGroup* const group_;
+    // The upper bound of the combined allocated object size on the current path
+    // (max int if allocation folding is impossible on this path).
+    int const size_;
+    Node* const top_;
+
+    DISALLOW_COPY_AND_ASSIGN(AllocationState);
+  };
+
+  // An array of allocation states used to collect states on merges.
+  typedef ZoneVector<AllocationState const*> AllocationStates;
+
+  // We thread through tokens to represent the current state on a given effect
+  // path through the graph.
+  struct Token {
+    Node* node;
+    AllocationState const* state;
+  };
+
+  void VisitNode(Node*, AllocationState const*);
+  void VisitAllocate(Node*, AllocationState const*);
+  void VisitCall(Node*, AllocationState const*);
+  void VisitLoadElement(Node*, AllocationState const*);
+  void VisitLoadField(Node*, AllocationState const*);
+  void VisitStoreElement(Node*, AllocationState const*);
+  void VisitStoreField(Node*, AllocationState const*);
+  void VisitOtherEffect(Node*, AllocationState const*);
+
+  Node* ComputeIndex(ElementAccess const&, Node*);
+  WriteBarrierKind ComputeWriteBarrierKind(Node* object,
+                                           AllocationState const* state,
+                                           WriteBarrierKind);
+
+  AllocationState const* MergeStates(AllocationStates const& states);
+
+  void EnqueueMerge(Node*, int, AllocationState const*);
+  void EnqueueUses(Node*, AllocationState const*);
+  void EnqueueUse(Node*, int, AllocationState const*);
+
+  AllocationState const* empty_state() const { return empty_state_; }
+  Graph* graph() const;
+  Isolate* isolate() const;
+  JSGraph* jsgraph() const { return jsgraph_; }
+  CommonOperatorBuilder* common() const;
+  MachineOperatorBuilder* machine() const;
+  Zone* zone() const { return zone_; }
+
+  SetOncePointer<const Operator> allocate_operator_;
+  JSGraph* const jsgraph_;
+  AllocationState const* const empty_state_;
+  ZoneMap<NodeId, AllocationStates> pending_;
+  ZoneQueue<Token> tokens_;
+  Zone* const zone_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryOptimizer);
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_MEMORY_OPTIMIZER_H_