Store HValue uses in a custom small list structure.
authorvitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Mar 2011 14:44:19 +0000 (14:44 +0000)
committervitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Mar 2011 14:44:19 +0000 (14:44 +0000)
This saves about 700K of zone allocation when compiling the V8
benchmark suite.

Review URL: http://codereview.chromium.org/6707001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7330 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/hydrogen-instructions.h
src/hydrogen.cc
src/small-pointer-list.h [new file with mode: 0644]
tools/gyp/v8.gyp
tools/v8.xcodeproj/project.pbxproj
tools/visual_studio/v8_base.vcproj
tools/visual_studio/v8_base_arm.vcproj
tools/visual_studio/v8_base_x64.vcproj

index 7f85bbe..c08540f 100644 (file)
@@ -29,7 +29,9 @@
 #define V8_HYDROGEN_INSTRUCTIONS_H_
 
 #include "v8.h"
+
 #include "code-stubs.h"
+#include "small-pointer-list.h"
 #include "string-stream.h"
 #include "zone.h"
 
@@ -451,7 +453,6 @@ class HValue: public ZoneObject {
 
   HValue() : block_(NULL),
              id_(kNoNumber),
-             uses_(2),
              type_(HType::Tagged()),
              range_(NULL),
              flags_(0) {}
@@ -463,7 +464,7 @@ class HValue: public ZoneObject {
   int id() const { return id_; }
   void set_id(int id) { id_ = id; }
 
-  ZoneList<HValue*>* uses() { return &uses_; }
+  SmallPointerList<HValue>* uses() { return &uses_; }
 
   virtual bool EmitAtUses() { return false; }
   Representation representation() const { return representation_; }
@@ -607,7 +608,7 @@ class HValue: public ZoneObject {
   int id_;
 
   Representation representation_;
-  ZoneList<HValue*> uses_;
+  SmallPointerList<HValue> uses_;
   HType type_;
   Range* range_;
   int flags_;
index e9bfafd..28a8908 100644 (file)
@@ -745,7 +745,7 @@ void HGraph::EliminateRedundantPhis() {
     if (value != NULL) {
       // Iterate through uses finding the ones that should be
       // replaced.
-      ZoneList<HValue*>* uses = phi->uses();
+      SmallPointerList<HValue>* uses = phi->uses();
       while (!uses->is_empty()) {
         HValue* use = uses->RemoveLast();
         if (use != NULL) {
diff --git a/src/small-pointer-list.h b/src/small-pointer-list.h
new file mode 100644 (file)
index 0000000..6291d9e
--- /dev/null
@@ -0,0 +1,163 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_SMALL_POINTER_LIST_H_
+#define V8_SMALL_POINTER_LIST_H_
+
+#include "checks.h"
+#include "v8globals.h"
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+// SmallPointerList is a list optimized for storing no or just a
+// single value. When more values are given it falls back to ZoneList.
+//
+// The interface tries to be as close to List from list.h as possible.
+template <typename T>
+class SmallPointerList {
+ public:
+  SmallPointerList() : data_(kEmptyTag) {}
+
+  bool is_empty() const { return length() == 0; }
+
+  int length() const {
+    if ((data_ & kTagMask) == kEmptyTag) return 0;
+    if ((data_ & kTagMask) == kSingletonTag) return 1;
+    return list()->length();
+  }
+
+  void Add(T* pointer) {
+    ASSERT(IsAligned(reinterpret_cast<intptr_t>(pointer), kPointerAlignment));
+    if ((data_ & kTagMask) == kEmptyTag) {
+      data_ = reinterpret_cast<intptr_t>(pointer) | kSingletonTag;
+      return;
+    }
+    if ((data_ & kTagMask) == kSingletonTag) {
+      PointerList* list = new PointerList(2);
+      list->Add(single_value());
+      list->Add(pointer);
+      ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
+      data_ = reinterpret_cast<intptr_t>(list) | kListTag;
+      return;
+    }
+    list()->Add(pointer);
+  }
+
+  // Note: returns T* and not T*& (unlike List from list.h).
+  // This makes the implementation simpler and more const correct.
+  T* at(int i) const {
+    ASSERT((data_ & kTagMask) != kEmptyTag);
+    if ((data_ & kTagMask) == kSingletonTag) {
+      ASSERT(i == 0);
+      return single_value();
+    }
+    return list()->at(i);
+  }
+
+  // See the note above.
+  T* operator[](int i) const { return at(i); }
+
+  // Remove the given element from the list (if present).
+  void RemoveElement(T* pointer) {
+    if ((data_ & kTagMask) == kEmptyTag) return;
+    if ((data_ & kTagMask) == kSingletonTag) {
+      if (pointer == single_value()) {
+        data_ = kEmptyTag;
+      }
+      return;
+    }
+    list()->RemoveElement(pointer);
+  }
+
+  T* RemoveLast() {
+    ASSERT((data_ & kTagMask) != kEmptyTag);
+    if ((data_ & kTagMask) == kSingletonTag) {
+      T* result = single_value();
+      data_ = kEmptyTag;
+      return result;
+    }
+    return list()->RemoveLast();
+  }
+
+  void Rewind(int pos) {
+    if ((data_ & kTagMask) == kEmptyTag) {
+      ASSERT(pos == 0);
+      return;
+    }
+    if ((data_ & kTagMask) == kSingletonTag) {
+      ASSERT(pos == 0 || pos == 1);
+      if (pos == 0) {
+        data_ = kEmptyTag;
+      }
+      return;
+    }
+    list()->Rewind(pos);
+  }
+
+  int CountOccurrences(T* pointer, int start, int end) const {
+    if ((data_ & kTagMask) == kEmptyTag) return 0;
+    if ((data_ & kTagMask) == kSingletonTag) {
+      if (start == 0 && end >= 0) {
+        return (single_value() == pointer) ? 1 : 0;
+      }
+      return 0;
+    }
+    return list()->CountOccurrences(pointer, start, end);
+  }
+
+ private:
+  typedef ZoneList<T*> PointerList;
+
+  static const intptr_t kEmptyTag = 1;
+  static const intptr_t kSingletonTag = 0;
+  static const intptr_t kListTag = 2;
+  static const intptr_t kTagMask = 3;
+  static const intptr_t kValueMask = ~kTagMask;
+
+  STATIC_ASSERT(kTagMask + 1 <= kPointerAlignment);
+
+  T* single_value() const {
+    ASSERT((data_ & kTagMask) == kSingletonTag);
+    STATIC_ASSERT(kSingletonTag == 0);
+    return reinterpret_cast<T*>(data_);
+  }
+
+  PointerList* list() const {
+    ASSERT((data_ & kTagMask) == kListTag);
+    return reinterpret_cast<PointerList*>(data_ & kValueMask);
+  }
+
+  intptr_t data_;
+
+  DISALLOW_COPY_AND_ASSIGN(SmallPointerList);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SMALL_POINTER_LIST_H_
index e82b098..4d27bc0 100644 (file)
             '../../src/serialize.cc',
             '../../src/serialize.h',
             '../../src/shell.h',
+            '../../src/small-pointer-list.h',
             '../../src/smart-pointer.h',
             '../../src/snapshot-common.cc',
             '../../src/snapshot.h',
index f7eafbd..560b035 100644 (file)
                89F3605A12DCDF6400ACF8A6 /* lithium-codegen-x64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-codegen-x64.cc"; path = "x64/lithium-codegen-x64.cc"; sourceTree = "<group>"; };
                89FB0E360F8E531900B04B3C /* d8-posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-posix.cc"; path = "../src/d8-posix.cc"; sourceTree = "<group>"; };
                89FB0E370F8E531900B04B3C /* d8-windows.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-windows.cc"; path = "../src/d8-windows.cc"; sourceTree = "<group>"; };
+               9C1F8E1D133906180068B362 /* small-pointer-list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "small-pointer-list.h"; sourceTree = "<group>"; };
                9F11D99E105AF0A300EBE5B2 /* heap-profiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "heap-profiler.cc"; sourceTree = "<group>"; };
                9F11D99F105AF0A300EBE5B2 /* heap-profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "heap-profiler.h"; sourceTree = "<group>"; };
                9F2B370E114FF62D007CDAF4 /* circular-queue-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "circular-queue-inl.h"; sourceTree = "<group>"; };
                                897FF17B0E719B8F00D62E90 /* serialize.h */,
                                897FF17C0E719B8F00D62E90 /* shell.h */,
                                893E24A012B14B3D0083370F /* simulator.h */,
+                               9C1F8E1D133906180068B362 /* small-pointer-list.h */,
                                897FF1810E719B8F00D62E90 /* smart-pointer.h */,
                                897FF1820E719B8F00D62E90 /* snapshot-common.cc */,
                                897FF1830E719B8F00D62E90 /* snapshot-empty.cc */,
index 0156616..9c2e355 100644 (file)
         >
       </File>
       <File
+        RelativePath="..\..\src\small-pointer-list.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\snapshot-common.cc"
         >
       </File>
index 6ae962c..87c178a 100644 (file)
         >
       </File>
       <File
+        RelativePath="..\..\src\small-pointer-list.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\snapshot-common.cc"
         >
       </File>
index dc2167b..de921bc 100644 (file)
         >
       </File>
       <File
+        RelativePath="..\..\src\small-pointer-list.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\snapshot-common.cc"
         >
       </File>