Revision: 9985
Author:   [email protected]
Date:     Mon Nov 14 03:13:29 2011
Log:      Fix missing fast property accessors in heap snapshots.

Implementation for this case

var x = {};
x.__defineGetter__("y", function Y() { return 42; });

BUG=v8:1818
TEST=cctest/test-heap-profiler/FastCaseGetter

Review URL: http://codereview.chromium.org/8491041
Patch from Ilya Tikhonovsky <[email protected]>.
http://code.google.com/p/v8/source/detail?r=9985

Modified:
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h
 /branches/bleeding_edge/test/cctest/test-heap-profiler.cc

=======================================
--- /branches/bleeding_edge/src/objects.cc      Mon Nov 14 00:58:47 2011
+++ /branches/bleeding_edge/src/objects.cc      Mon Nov 14 03:13:29 2011
@@ -103,11 +103,6 @@
 }


-// Getters and setters are stored in a fixed array property.  These are
-// constants for their indices.
-const int kGetterIndex = 0;
-const int kSetterIndex = 1;
-
 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
                                                   Object* value) {
   Object* result;
@@ -208,6 +203,13 @@
   ASSERT(*attributes <= ABSENT);
   return value;
 }
+
+
+// This may seem strange but the standard requires inline static const
+// definition, and w/o these the code doesn't link when being built in debug
+// mode using gcc.
+const int JSObject::kGetterIndex;
+const int JSObject::kSetterIndex;


 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
=======================================
--- /branches/bleeding_edge/src/objects.h       Mon Nov 14 00:58:47 2011
+++ /branches/bleeding_edge/src/objects.h       Mon Nov 14 03:13:29 2011
@@ -1886,6 +1886,11 @@
 #endif
   Object* SlowReverseLookup(Object* value);

+  // Getters and setters are stored in a fixed array property.
+  // These are constants for their indices.
+  static const int kGetterIndex = 0;
+  static const int kSetterIndex = 1;
+
   // Maximal number of fast properties for the JSObject. Used to
   // restrict the number of map transitions to avoid an explosion in
   // the number of maps for objects used as dictionaries.
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Wed Nov 9 04:47:15 2011 +++ /branches/bleeding_edge/src/profile-generator.cc Mon Nov 14 03:13:29 2011
@@ -1918,6 +1918,7 @@
           SetPropertyReference(
               obj, entry,
               heap_->prototype_symbol(), proto_or_map,
+              NULL,
               JSFunction::kPrototypeOrInitialMapOffset);
         } else {
           SetPropertyReference(
@@ -2101,6 +2102,7 @@
             SetPropertyReference(
                 js_obj, entry,
                 descs->GetKey(i), js_obj->InObjectPropertyAt(index),
+                NULL,
                 js_obj->GetInObjectPropertyOffset(index));
           } else {
             SetPropertyReference(
@@ -2114,6 +2116,21 @@
               js_obj, entry,
               descs->GetKey(i), descs->GetConstantFunction(i));
           break;
+        case CALLBACKS: {
+          Object* callback_obj = descs->GetValue(i);
+          if (callback_obj->IsFixedArray()) {
+            FixedArray* accessors = FixedArray::cast(callback_obj);
+            if (Object* getter = accessors->get(JSObject::kGetterIndex)) {
+              SetPropertyReference(js_obj, entry, descs->GetKey(i),
+                                   getter, "get-%s");
+            }
+            if (Object* setter = accessors->get(JSObject::kSetterIndex)) {
+              SetPropertyReference(js_obj, entry, descs->GetKey(i),
+                                   setter, "set-%s");
+            }
+          }
+          break;
+        }
         case NORMAL:  // only in slow mode
         case HANDLER:  // only in lookup results, not in descriptors
         case INTERCEPTOR:  // only in lookup results, not in descriptors
@@ -2122,9 +2139,6 @@
         case CONSTANT_TRANSITION:
         case NULL_DESCRIPTOR:  // ... and not about "holes"
           break;
-          // TODO(svenpanne): Should we really ignore accessors here?
-        case CALLBACKS:
-          break;
       }
     }
   } else {
@@ -2349,15 +2363,23 @@
                                           HeapEntry* parent_entry,
                                           String* reference_name,
                                           Object* child_obj,
+                                          const char* name_format_string,
                                           int field_offset) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     HeapGraphEdge::Type type = reference_name->length() > 0 ?
         HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
+    const char* name = name_format_string  != NULL ?
+        collection_->names()->GetFormatted(
+            name_format_string,
+            *reference_name->ToCString(DISALLOW_NULLS,
+                                       ROBUST_STRING_TRAVERSAL)) :
+        collection_->names()->GetName(reference_name);
+
     filler_->SetNamedReference(type,
                                parent_obj,
                                parent_entry,
- collection_->names()->GetName(reference_name),
+                               name,
                                child_obj,
                                child_entry);
     IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
=======================================
--- /branches/bleeding_edge/src/profile-generator.h     Wed Nov  9 04:15:35 2011
+++ /branches/bleeding_edge/src/profile-generator.h     Mon Nov 14 03:13:29 2011
@@ -973,6 +973,7 @@
                             HeapEntry* parent,
                             String* reference_name,
                             Object* child,
+                            const char* name_format_string = NULL,
                             int field_offset = -1);
   void SetPropertyShortcutReference(HeapObject* parent_obj,
                                     HeapEntry* parent,
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Fri Oct 21 06:05:37 2011 +++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Mon Nov 14 03:13:29 2011
@@ -1023,3 +1023,30 @@
   CHECK_EQ(0, StringCmp(
       "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
 }
+
+TEST(FastCaseGetter) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun("var obj1 = {};\n"
+             "obj1.__defineGetter__('propWithGetter', function Y() {\n"
+             "  return 42;\n"
+             "});\n"
+ "obj1.__defineSetter__('propWithSetter', function Z(value) {\n"
+             "  return this.value_ = value;\n"
+             "});\n");
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter"));
+
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  CHECK_NE(NULL, global);
+  const v8::HeapGraphNode* obj1 =
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "obj1");
+  CHECK_NE(NULL, obj1);
+  const v8::HeapGraphNode* getterFunction =
+ GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter");
+  CHECK_NE(NULL, getterFunction);
+  const v8::HeapGraphNode* setterFunction =
+ GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter");
+  CHECK_NE(NULL, setterFunction);
+}

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to