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/test/unittests/compiler/zone-pool-unittest.cc b/test/unittests/compiler/zone-pool-unittest.cc
new file mode 100644
index 0000000..e23557a
--- /dev/null
+++ b/test/unittests/compiler/zone-pool-unittest.cc
@@ -0,0 +1,162 @@
+// Copyright 2014 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.
+
+#include "src/base/utils/random-number-generator.h"
+#include "src/compiler/zone-pool.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class ZonePoolTest : public TestWithIsolate {
+ public:
+  ZonePoolTest() : zone_pool_(isolate()) {}
+
+ protected:
+  ZonePool* zone_pool() { return &zone_pool_; }
+
+  void ExpectForPool(size_t current, size_t max, size_t total) {
+    ASSERT_EQ(current, zone_pool()->GetCurrentAllocatedBytes());
+    ASSERT_EQ(max, zone_pool()->GetMaxAllocatedBytes());
+    ASSERT_EQ(total, zone_pool()->GetTotalAllocatedBytes());
+  }
+
+  void Expect(ZonePool::StatsScope* stats, size_t current, size_t max,
+              size_t total) {
+    ASSERT_EQ(current, stats->GetCurrentAllocatedBytes());
+    ASSERT_EQ(max, stats->GetMaxAllocatedBytes());
+    ASSERT_EQ(total, stats->GetTotalAllocatedBytes());
+  }
+
+  size_t Allocate(Zone* zone) {
+    size_t bytes = rng.NextInt(25) + 7;
+    int size_before = zone->allocation_size();
+    zone->New(static_cast<int>(bytes));
+    return static_cast<size_t>(zone->allocation_size() - size_before);
+  }
+
+ private:
+  ZonePool zone_pool_;
+  base::RandomNumberGenerator rng;
+};
+
+
+TEST_F(ZonePoolTest, Empty) {
+  ExpectForPool(0, 0, 0);
+  {
+    ZonePool::StatsScope stats(zone_pool());
+    Expect(&stats, 0, 0, 0);
+  }
+  ExpectForPool(0, 0, 0);
+  {
+    ZonePool::Scope scope(zone_pool());
+    scope.zone();
+  }
+  ExpectForPool(0, 0, 0);
+}
+
+
+TEST_F(ZonePoolTest, MultipleZonesWithDeletion) {
+  static const size_t kArraySize = 10;
+
+  ZonePool::Scope* scopes[kArraySize];
+
+  // Initialize.
+  size_t before_stats = 0;
+  for (size_t i = 0; i < kArraySize; ++i) {
+    scopes[i] = new ZonePool::Scope(zone_pool());
+    before_stats += Allocate(scopes[i]->zone());  // Add some stuff.
+  }
+
+  ExpectForPool(before_stats, before_stats, before_stats);
+
+  ZonePool::StatsScope stats(zone_pool());
+
+  size_t before_deletion = 0;
+  for (size_t i = 0; i < kArraySize; ++i) {
+    before_deletion += Allocate(scopes[i]->zone());  // Add some stuff.
+  }
+
+  Expect(&stats, before_deletion, before_deletion, before_deletion);
+  ExpectForPool(before_stats + before_deletion, before_stats + before_deletion,
+                before_stats + before_deletion);
+
+  // Delete the scopes and create new ones.
+  for (size_t i = 0; i < kArraySize; ++i) {
+    delete scopes[i];
+    scopes[i] = new ZonePool::Scope(zone_pool());
+  }
+
+  Expect(&stats, 0, before_deletion, before_deletion);
+  ExpectForPool(0, before_stats + before_deletion,
+                before_stats + before_deletion);
+
+  size_t after_deletion = 0;
+  for (size_t i = 0; i < kArraySize; ++i) {
+    after_deletion += Allocate(scopes[i]->zone());  // Add some stuff.
+  }
+
+  Expect(&stats, after_deletion, std::max(after_deletion, before_deletion),
+         before_deletion + after_deletion);
+  ExpectForPool(after_deletion,
+                std::max(after_deletion, before_stats + before_deletion),
+                before_stats + before_deletion + after_deletion);
+
+  // Cleanup.
+  for (size_t i = 0; i < kArraySize; ++i) {
+    delete scopes[i];
+  }
+
+  Expect(&stats, 0, std::max(after_deletion, before_deletion),
+         before_deletion + after_deletion);
+  ExpectForPool(0, std::max(after_deletion, before_stats + before_deletion),
+                before_stats + before_deletion + after_deletion);
+}
+
+
+TEST_F(ZonePoolTest, SimpleAllocationLoop) {
+  int runs = 20;
+  size_t total_allocated = 0;
+  size_t max_loop_allocation = 0;
+  ZonePool::StatsScope outer_stats(zone_pool());
+  {
+    ZonePool::Scope outer_scope(zone_pool());
+    size_t outer_allocated = 0;
+    for (int i = 0; i < runs; ++i) {
+      {
+        size_t bytes = Allocate(outer_scope.zone());
+        outer_allocated += bytes;
+        total_allocated += bytes;
+      }
+      ZonePool::StatsScope inner_stats(zone_pool());
+      size_t allocated = 0;
+      {
+        ZonePool::Scope inner_scope(zone_pool());
+        for (int j = 0; j < 20; ++j) {
+          size_t bytes = Allocate(inner_scope.zone());
+          allocated += bytes;
+          total_allocated += bytes;
+          max_loop_allocation =
+              std::max(max_loop_allocation, outer_allocated + allocated);
+          Expect(&inner_stats, allocated, allocated, allocated);
+          Expect(&outer_stats, outer_allocated + allocated, max_loop_allocation,
+                 total_allocated);
+          ExpectForPool(outer_allocated + allocated, max_loop_allocation,
+                        total_allocated);
+        }
+      }
+      Expect(&inner_stats, 0, allocated, allocated);
+      Expect(&outer_stats, outer_allocated, max_loop_allocation,
+             total_allocated);
+      ExpectForPool(outer_allocated, max_loop_allocation, total_allocated);
+    }
+  }
+  Expect(&outer_stats, 0, max_loop_allocation, total_allocated);
+  ExpectForPool(0, max_loop_allocation, total_allocated);
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8