Revision: 10371
Author:   [email protected]
Date:     Tue Jan 10 08:11:33 2012
Log: Use a separate new type AccessorPair for JavaScript callbacks instead of a FixedArray of length 2
http://code.google.com/p/v8/source/detail?r=10371

Modified:
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/runtime.cc

=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Jan  5 09:16:19 2012
+++ /branches/bleeding_edge/src/bootstrapper.cc Tue Jan 10 08:11:33 2012
@@ -264,13 +264,13 @@
   Handle<Map> CreateStrictModeFunctionMap(
       PrototypePropertyMode prototype_mode,
       Handle<JSFunction> empty_function,
-      Handle<FixedArray> arguments_callbacks,
-      Handle<FixedArray> caller_callbacks);
+      Handle<AccessorPair> arguments_callbacks,
+      Handle<AccessorPair> caller_callbacks);

   Handle<DescriptorArray> ComputeStrictFunctionInstanceDescriptor(
       PrototypePropertyMode propertyMode,
-      Handle<FixedArray> arguments,
-      Handle<FixedArray> caller);
+      Handle<AccessorPair> arguments,
+      Handle<AccessorPair> caller);

   static bool CompileBuiltin(Isolate* isolate, int index);
   static bool CompileExperimentalBuiltin(Isolate* isolate, int index);
@@ -540,8 +540,8 @@

 Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
     PrototypePropertyMode prototypeMode,
-    Handle<FixedArray> arguments,
-    Handle<FixedArray> caller) {
+    Handle<AccessorPair> arguments,
+    Handle<AccessorPair> caller) {
   Handle<DescriptorArray> descriptors =
       factory()->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE
                                     ? 4
@@ -611,8 +611,8 @@
 Handle<Map> Genesis::CreateStrictModeFunctionMap(
     PrototypePropertyMode prototype_mode,
     Handle<JSFunction> empty_function,
-    Handle<FixedArray> arguments_callbacks,
-    Handle<FixedArray> caller_callbacks) {
+    Handle<AccessorPair> arguments_callbacks,
+    Handle<AccessorPair> caller_callbacks) {
   Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
   Handle<DescriptorArray> descriptors =
       ComputeStrictFunctionInstanceDescriptor(prototype_mode,
@@ -629,8 +629,8 @@
   // Create the callbacks arrays for ThrowTypeError functions.
   // The get/set callacks are filled in after the maps are created below.
   Factory* factory = empty->GetIsolate()->factory();
-  Handle<FixedArray> arguments = factory->NewFixedArray(2, TENURED);
-  Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED);
+  Handle<AccessorPair> arguments(factory->NewAccessorPair());
+  Handle<AccessorPair> caller(factory->NewAccessorPair());

   // Allocate map for the strict mode function instances.
   Handle<Map> strict_mode_function_instance_map =
@@ -665,11 +665,11 @@
   Handle<JSFunction> throw_function =
       GetThrowTypeErrorFunction();

-  // Complete the callback fixed arrays.
-  arguments->set(0, *throw_function);
-  arguments->set(1, *throw_function);
-  caller->set(0, *throw_function);
-  caller->set(1, *throw_function);
+  // Complete the callbacks.
+  arguments->set_getter(*throw_function);
+  arguments->set_setter(*throw_function);
+  caller->set_getter(*throw_function);
+  caller->set_setter(*throw_function);
 }


@@ -1142,17 +1142,17 @@
       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);

     // Create the ThrowTypeError functions.
-    Handle<FixedArray> callee = factory->NewFixedArray(2, TENURED);
-    Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED);
+    Handle<AccessorPair> callee = factory->NewAccessorPair();
+    Handle<AccessorPair> caller = factory->NewAccessorPair();

     Handle<JSFunction> throw_function =
         GetThrowTypeErrorFunction();

     // Install the ThrowTypeError functions.
-    callee->set(0, *throw_function);
-    callee->set(1, *throw_function);
-    caller->set(0, *throw_function);
-    caller->set(1, *throw_function);
+    callee->set_getter(*throw_function);
+    callee->set_setter(*throw_function);
+    caller->set_getter(*throw_function);
+    caller->set_setter(*throw_function);

     // Create the descriptor array for the arguments object.
     Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
=======================================
--- /branches/bleeding_edge/src/factory.cc      Thu Jan  5 09:16:19 2012
+++ /branches/bleeding_edge/src/factory.cc      Tue Jan 10 08:11:33 2012
@@ -129,6 +129,13 @@
                                                         pretenure),
                      DeoptimizationOutputData);
 }
+
+
+Handle<AccessorPair> Factory::NewAccessorPair() {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateAccessorPair(),
+                     AccessorPair);
+}


 // Symbols are created in the old generation (data space).
=======================================
--- /branches/bleeding_edge/src/factory.h       Fri Dec  9 00:50:19 2011
+++ /branches/bleeding_edge/src/factory.h       Tue Jan 10 08:11:33 2012
@@ -69,6 +69,7 @@
   Handle<DeoptimizationOutputData> NewDeoptimizationOutputData(
       int deopt_entry_count,
       PretenureFlag pretenure);
+  Handle<AccessorPair> NewAccessorPair();

   Handle<String> LookupSymbol(Vector<const char> str);
   Handle<String> LookupSymbol(Handle<String> str);
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/heap.cc Tue Jan 10 08:11:33 2012
@@ -1867,6 +1867,19 @@
 MaybeObject* Heap::AllocatePolymorphicCodeCache() {
   return AllocateStruct(POLYMORPHIC_CODE_CACHE_TYPE);
 }
+
+
+MaybeObject* Heap::AllocateAccessorPair() {
+  Object* result;
+  { MaybeObject* maybe_result = AllocateStruct(ACCESSOR_PAIR_TYPE);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+  AccessorPair* accessors = AccessorPair::cast(result);
+  // Later we will have to distinguish between undefined and the hole...
+  // accessors->set_getter(the_hole_value(), SKIP_WRITE_BARRIER);
+  // accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER);
+  return accessors;
+}


 const Heap::StringTypeTable Heap::string_type_table[] = {
=======================================
--- /branches/bleeding_edge/src/heap.h  Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/heap.h  Tue Jan 10 08:11:33 2012
@@ -615,6 +615,9 @@
   // Allocates an empty PolymorphicCodeCache.
   MUST_USE_RESULT MaybeObject* AllocatePolymorphicCodeCache();

+  // Allocates an empty AccessorPair.
+  MaybeObject* AllocateAccessorPair();
+
   // Clear the Instanceof cache (used when a prototype changes).
   inline void ClearInstanceofCache();

=======================================
--- /branches/bleeding_edge/src/objects-debug.cc        Tue Oct 25 07:14:56 2011
+++ /branches/bleeding_edge/src/objects-debug.cc        Tue Jan 10 08:11:33 2012
@@ -600,6 +600,13 @@
   VerifyPointer(data());
   VerifyPointer(flag());
 }
+
+
+void AccessorPair::AccessorPairVerify() {
+  CHECK(IsAccessorPair());
+  VerifyPointer(getter());
+  VerifyPointer(setter());
+}


 void AccessCheckInfo::AccessCheckInfoVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/objects-inl.h   Tue Jan 10 08:11:33 2012
@@ -3386,6 +3386,9 @@
 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)

+ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
+ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
+
 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc      Wed Nov 23 05:08:28 2011
+++ /branches/bleeding_edge/src/objects-printer.cc      Tue Jan 10 08:11:33 2012
@@ -784,6 +784,15 @@
   PrintF(out, "\n - flag: ");
   flag()->ShortPrint(out);
 }
+
+
+void AccessorPair::AccessorPairPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "AccessorPair");
+  PrintF(out, "\n - getter: ");
+  getter()->ShortPrint(out);
+  PrintF(out, "\n - setter: ");
+  setter()->ShortPrint(out);
+}


 void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
=======================================
--- /branches/bleeding_edge/src/objects.cc      Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/objects.cc      Tue Jan 10 08:11:33 2012
@@ -246,8 +246,8 @@
   }

   // __defineGetter__ callback
-  if (structure->IsFixedArray()) {
-    Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
+  if (structure->IsAccessorPair()) {
+    Object* getter = AccessorPair::cast(structure)->getter();
     if (getter->IsSpecFunction()) {
       // TODO(rossberg): nicer would be to cast to some JSCallable here...
return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
@@ -2039,8 +2039,8 @@
     return *value_handle;
   }

-  if (structure->IsFixedArray()) {
-    Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
+  if (structure->IsAccessorPair()) {
+    Object* setter = AccessorPair::cast(structure)->setter();
     if (setter->IsSpecFunction()) {
       // TODO(rossberg): nicer would be to cast to some JSCallable here...
      return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
@@ -4353,10 +4353,9 @@


 // Search for a getter or setter in an elements dictionary and update its
-// attributes. Returns either undefined if the element is non-deletable, or
-// the getter/setter pair (fixed array) if there is an existing one, or the
-// hole value if the element does not exist or is a normal non-getter/setter
-// data element.
+// attributes. Returns either undefined if the element is non-deletable, or the
+// getter/setter pair if there is an existing one, or the hole value if the
+// element does not exist or is a normal non-getter/setter data element.
 static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary,
                                               uint32_t index,
PropertyAttributes attributes,
@@ -4367,7 +4366,7 @@
     PropertyDetails details = dictionary->DetailsAt(entry);
// TODO(mstarzinger): We should check for details.IsDontDelete() here once
     // we only call into the runtime once to set both getter and setter.
-    if (details.type() == CALLBACKS && result->IsFixedArray()) {
+    if (details.type() == CALLBACKS && result->IsAccessorPair()) {
       if (details.attributes() != attributes) {
         dictionary->DetailsAtPut(entry,
PropertyDetails(attributes, CALLBACKS, index));
@@ -4455,7 +4454,7 @@
       if (result.type() == CALLBACKS) {
         Object* obj = result.GetCallbackObject();
         // Need to preserve old getters/setters.
-        if (obj->IsFixedArray()) {
+        if (obj->IsAccessorPair()) {
           // Use set to update attributes.
           return SetPropertyCallback(name, obj, attributes);
         }
@@ -4463,16 +4462,15 @@
     }
   }

-  // Allocate the fixed array to hold getter and setter.
-  Object* structure;
-  { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED);
-    if (!maybe_structure->ToObject(&structure)) return maybe_structure;
+  AccessorPair* accessors;
+  { MaybeObject* maybe_accessors = heap->AllocateAccessorPair();
+ if (!maybe_accessors->To<AccessorPair>(&accessors)) return maybe_accessors;
   }

   if (is_element) {
-    return SetElementCallback(index, structure, attributes);
+    return SetElementCallback(index, accessors, attributes);
   } else {
-    return SetPropertyCallback(name, structure, attributes);
+    return SetPropertyCallback(name, accessors, attributes);
   }
 }

@@ -4608,12 +4606,15 @@
                                                  fun, attributes);
   }

-  Object* array;
-  { MaybeObject* maybe_array = DefineGetterSetter(name, attributes);
-    if (!maybe_array->ToObject(&array)) return maybe_array;
-  }
-  if (array->IsUndefined()) return array;
-  FixedArray::cast(array)->set(is_getter ? 0 : 1, fun);
+  AccessorPair* accessors;
+  { MaybeObject* maybe_accessors = DefineGetterSetter(name, attributes);
+ if (!maybe_accessors->To<AccessorPair>(&accessors)) return maybe_accessors;
+  }
+  if (is_getter) {
+    accessors->set_getter(fun);
+  } else {
+    accessors->set_setter(fun);
+  }
   return this;
 }

@@ -4717,11 +4718,6 @@
   }

   // Make the lookup and include prototypes.
-  // Introducing constants below makes static constants usage purely static
-  // and avoids linker errors in debug build using gcc.
-  const int getter_index = kGetterIndex;
-  const int setter_index = kSetterIndex;
-  int accessor_index = is_getter ? getter_index : setter_index;
   uint32_t index = 0;
   if (name->AsArrayIndex(&index)) {
     for (Object* obj = this;
@@ -4735,8 +4731,9 @@
           Object* element = dictionary->ValueAt(entry);
           PropertyDetails details = dictionary->DetailsAt(entry);
           if (details.type() == CALLBACKS) {
-            if (element->IsFixedArray()) {
-              return FixedArray::cast(element)->get(accessor_index);
+            if (element->IsAccessorPair()) {
+              AccessorPair *accessors = AccessorPair::cast(element);
+              return is_getter ? accessors->getter() : accessors->setter();
             }
           }
         }
@@ -4752,8 +4749,9 @@
         if (result.IsReadOnly()) return heap->undefined_value();
         if (result.type() == CALLBACKS) {
           Object* obj = result.GetCallbackObject();
-          if (obj->IsFixedArray()) {
-            return FixedArray::cast(obj)->get(accessor_index);
+          if (obj->IsAccessorPair()) {
+            AccessorPair *accessors = AccessorPair::cast(obj);
+            return is_getter ? accessors->getter() : accessors->setter();
           }
         }
       }
@@ -9060,8 +9058,8 @@
   }

   // __defineGetter__ callback
-  if (structure->IsFixedArray()) {
-    Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
+  if (structure->IsAccessorPair()) {
+    Object* getter = AccessorPair::cast(structure)->getter();
     if (getter->IsSpecFunction()) {
       // TODO(rossberg): nicer would be to cast to some JSCallable here...
return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
@@ -9117,8 +9115,8 @@
     return *value_handle;
   }

-  if (structure->IsFixedArray()) {
-    Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex));
+  if (structure->IsAccessorPair()) {
+    Handle<Object> setter(AccessorPair::cast(structure)->setter());
     if (setter->IsSpecFunction()) {
       // TODO(rossberg): nicer would be to cast to some JSCallable here...
return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/objects.h       Tue Jan 10 08:11:33 2012
@@ -107,6 +107,7 @@
 //       - SharedFunctionInfo
 //       - Struct
 //         - AccessorInfo
+//         - AccessorPair
 //         - AccessCheckInfo
 //         - InterceptorInfo
 //         - CallHandlerInfo
@@ -275,6 +276,7 @@
V(FILLER_TYPE) \ \ V(ACCESSOR_INFO_TYPE) \ + V(ACCESSOR_PAIR_TYPE) \ V(ACCESS_CHECK_INFO_TYPE) \ V(INTERCEPTOR_INFO_TYPE) \ V(CALL_HANDLER_INFO_TYPE) \
@@ -422,6 +424,7 @@
 // manually.
#define STRUCT_LIST_ALL(V) \ V(ACCESSOR_INFO, AccessorInfo, accessor_info) \ + V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \ V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \ V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \ V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
@@ -575,6 +578,7 @@

   // Structs.
   ACCESSOR_INFO_TYPE,
+  ACCESSOR_PAIR_TYPE,
   ACCESS_CHECK_INFO_TYPE,
   INTERCEPTOR_INFO_TYPE,
   CALL_HANDLER_INFO_TYPE,
@@ -2006,11 +2010,6 @@
 #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.
@@ -7636,6 +7635,35 @@
 };


+// Support for JavaScript accessors: A pair of a getter and a setter. Each
+// accessor can either be
+//   * a pointer to a JavaScript function or proxy: a real accessor
+//   * undefined: considered an accessor by the spec, too, strangely enough
+//   * the hole: an accessor which has not been set
+//   * a pointer to a map: a transition used to ensure map sharing
+class AccessorPair: public Struct {
+ public:
+  DECL_ACCESSORS(getter, Object)
+  DECL_ACCESSORS(setter, Object)
+
+  static inline AccessorPair* cast(Object* obj);
+
+#ifdef OBJECT_PRINT
+  void AccessorPairPrint(FILE* out = stdout);
+#endif
+#ifdef DEBUG
+  void AccessorPairVerify();
+#endif
+
+  static const int kGetterOffset = HeapObject::kHeaderSize;
+  static const int kSetterOffset = kGetterOffset + kPointerSize;
+  static const int kSize = kSetterOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair);
+};
+
+
 class AccessCheckInfo: public Struct {
  public:
   DECL_ACCESSORS(named_callback, Object)
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Jan 10 05:24:18 2012 +++ /branches/bleeding_edge/src/profile-generator.cc Tue Jan 10 08:11:33 2012
@@ -2230,13 +2230,13 @@
           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)) {
+          if (callback_obj->IsAccessorPair()) {
+            AccessorPair* accessors = AccessorPair::cast(callback_obj);
+            if (Object* getter = accessors->getter()) {
               SetPropertyReference(js_obj, entry, descs->GetKey(i),
                                    getter, "get-%s");
             }
-            if (Object* setter = accessors->get(JSObject::kSetterIndex)) {
+            if (Object* setter = accessors->setter()) {
               SetPropertyReference(js_obj, entry, descs->GetKey(i),
                                    setter, "set-%s");
             }
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Jan 10 08:06:32 2012
+++ /branches/bleeding_edge/src/runtime.cc      Tue Jan 10 08:11:33 2012
@@ -1056,14 +1056,14 @@
         switch (details.type()) {
           case CALLBACKS: {
             // This is an accessor property with getter and/or setter.
-            FixedArray* callbacks =
-                FixedArray::cast(dictionary->ValueAt(entry));
+            AccessorPair* accessors =
+                AccessorPair::cast(dictionary->ValueAt(entry));
             elms->set(IS_ACCESSOR_INDEX, heap->true_value());
             if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
-              elms->set(GETTER_INDEX, callbacks->get(0));
+              elms->set(GETTER_INDEX, accessors->getter());
             }
             if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
-              elms->set(SETTER_INDEX, callbacks->get(1));
+              elms->set(SETTER_INDEX, accessors->setter());
             }
             break;
           }
@@ -1102,18 +1102,18 @@
   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));

   bool is_js_accessor = (result.type() == CALLBACKS) &&
-                        (result.GetCallbackObject()->IsFixedArray());
+                        (result.GetCallbackObject()->IsAccessorPair());

   if (is_js_accessor) {
     // __defineGetter__/__defineSetter__ callback.
     elms->set(IS_ACCESSOR_INDEX, heap->true_value());

-    FixedArray* structure = FixedArray::cast(result.GetCallbackObject());
+ AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
     if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
-      elms->set(GETTER_INDEX, structure->get(0));
+      elms->set(GETTER_INDEX, accessors->getter());
     }
     if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
-      elms->set(SETTER_INDEX, structure->get(1));
+      elms->set(SETTER_INDEX, accessors->setter());
     }
   } else {
     elms->set(IS_ACCESSOR_INDEX, heap->false_value());
@@ -10474,15 +10474,15 @@
// If the callback object is a fixed array then it contains JavaScript
       // getter and/or setter.
       bool hasJavaScriptAccessors = result_type == CALLBACKS &&
-                                    result_callback_obj->IsFixedArray();
+                                    result_callback_obj->IsAccessorPair();
       Handle<FixedArray> details =
isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
       details->set(0, *value);
       details->set(1, property_details);
       if (hasJavaScriptAccessors) {
         details->set(2, isolate->heap()->ToBoolean(caught_exception));
-        details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
-        details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
+ details->set(3, AccessorPair::cast(*result_callback_obj)->getter()); + details->set(4, AccessorPair::cast(*result_callback_obj)->setter());
       }

       return *isolate->factory()->NewJSArrayWithElements(details);

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

Reply via email to