Added descriptor lookup cache to eliminate some search overhead.
authorbak@chromium.org <bak@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Jun 2009 14:29:35 +0000 (14:29 +0000)
committerbak@chromium.org <bak@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Jun 2009 14:29:35 +0000 (14:29 +0000)
Reduced the KeyedLookupCache length to 64.
Review URL: http://codereview.chromium.org/141046

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

src/heap.cc
src/heap.h
src/objects-inl.h
src/objects.cc

index 879d6a16a5009d54695d2a55bfb1a4cd0d86098e..2573be8f2be3a0f92cbf522cdd292bba41bf503a 100644 (file)
@@ -502,6 +502,7 @@ void Heap::MarkCompactPrologue(bool is_compacting) {
   // maps.
   KeyedLookupCache::Clear();
   ContextSlotCache::Clear();
+  DescriptorLookupCache::Clear();
 
   CompilationCache::MarkCompactPrologue();
 
@@ -630,6 +631,9 @@ void Heap::Scavenge() {
   // Implements Cheney's copying algorithm
   LOG(ResourceEvent("scavenge", "begin"));
 
+  // Clear descriptor cache.
+  DescriptorLookupCache::Clear();
+
   // Used for updating survived_since_last_expansion_ at function end.
   int survived_watermark = PromotedSpaceSize();
 
@@ -1392,6 +1396,9 @@ bool Heap::CreateInitialObjects() {
   // Initialize context slot cache.
   ContextSlotCache::Clear();
 
+  // Initialize descriptor cache.
+  DescriptorLookupCache::Clear();
+
   // Initialize compilation cache.
   CompilationCache::Clear();
 
@@ -3559,6 +3566,17 @@ KeyedLookupCache::Key KeyedLookupCache::keys_[KeyedLookupCache::kLength];
 int KeyedLookupCache::field_offsets_[KeyedLookupCache::kLength];
 
 
+void DescriptorLookupCache::Clear() {
+  for (int index = 0; index < kLength; index++) keys_[index].array = NULL;
+}
+
+
+DescriptorLookupCache::Key
+DescriptorLookupCache::keys_[DescriptorLookupCache::kLength];
+
+int DescriptorLookupCache::results_[DescriptorLookupCache::kLength];
+
+
 #ifdef DEBUG
 bool Heap::GarbageCollectionGreedyCheck() {
   ASSERT(FLAG_gc_greedy);
index 0191b69c292941ac8dea88ce8d2ecdc071f43227..75bd7fc5ae7788320d474168bdd73b295116d072 100644 (file)
@@ -1148,7 +1148,7 @@ class KeyedLookupCache {
   static void Clear();
  private:
   inline static int Hash(Map* map, String* name);
-  static const int kLength = 128;
+  static const int kLength = 64;
   struct Key {
     Map* map;
     String* name;
@@ -1158,6 +1158,60 @@ class KeyedLookupCache {
 };
 
 
+
+// Cache for mapping (array, property name) into descriptor index.
+// The cache contains both positive and negative results.
+// Descriptor index equals kNotFound means the property is absent.
+// Cleared at startup and prior to any gc.
+class DescriptorLookupCache {
+ public:
+  // Lookup descriptor index for (map, name).
+  // If absent, kAbsent is returned.
+  static int Lookup(DescriptorArray* array, String* name) {
+    if(!StringShape(name).IsSymbol()) return kAbsent;
+    int index = Hash(array, name);
+    Key& key = keys_[index];
+    if ((key.array == array) && (key.name == name)) return results_[index];
+    return kAbsent;
+  }
+
+  // Update an element in the cache.
+  static void Update(DescriptorArray* array, String* name, int result) {
+    ASSERT(result != kAbsent);
+    if(StringShape(name).IsSymbol()) {
+      int index = Hash(array, name);
+      Key& key = keys_[index];
+      key.array = array;
+      key.name = name;
+      results_[index] = result;
+    }
+  }
+
+  // Clear the cache.
+  static void Clear();
+
+  static const int kAbsent = -2;
+ private:
+  static int Hash(DescriptorArray* array, String* name) {
+    // Uses only lower 32 bits if pointers are larger.
+    uintptr_t array_hash =
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(array)) >> 2;
+    uintptr_t name_hash =
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name)) >> 2;
+    return (array_hash ^ name_hash) % kLength;
+  }
+
+  static const int kLength = 64;
+  struct Key {
+    DescriptorArray* array;
+    String* name;
+  };
+
+  static Key keys_[kLength];
+  static int results_[kLength];
+};
+
+
 // ----------------------------------------------------------------------------
 // Marking stack for tracing live objects.
 
index 2b996529ea7b4322949f3d0bd1c7c392a5186348..af03b5a849a9ec14b7bdfd802dd05aefc5ac806e 100644 (file)
@@ -1299,7 +1299,6 @@ int DescriptorArray::Search(String* name) {
 }
 
 
-
 String* DescriptorArray::GetKey(int descriptor_number) {
   ASSERT(descriptor_number < number_of_descriptors());
   return String::cast(get(ToKeyIndex(descriptor_number)));
index 0457269bc1f71041e020214570336b9604cc0bfc..fd615be46baca7cf9f63cd8bfdaf7a46e1f217ad 100644 (file)
@@ -1565,7 +1565,11 @@ Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
 
 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
   DescriptorArray* descriptors = map()->instance_descriptors();
-  int number = descriptors->Search(name);
+  int number = DescriptorLookupCache::Lookup(descriptors, name);
+  if (number == DescriptorLookupCache::kAbsent) {
+    number = descriptors->Search(name);
+    DescriptorLookupCache::Update(descriptors, name, number);
+  }
   if (number != DescriptorArray::kNotFound) {
     result->DescriptorResult(this, descriptors->GetDetails(number), number);
   } else {