Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(800)

Unified Diff: src/objects.h

Issue 3329019: Dynamically determine optimal instance size.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/objects.h
===================================================================
--- src/objects.h (revision 5500)
+++ src/objects.h (working copy)
@@ -1576,7 +1576,7 @@
// initialized by set_properties
// Note: this call does not update write barrier, it is caller's
// reponsibility to ensure that *v* can be collected without WB here.
- inline void InitializeBody(int object_size);
+ inline void InitializeBody(int object_size, Object* value);
// Check whether this object references another object
bool ReferencesObject(Object* obj);
@@ -3151,6 +3151,12 @@
return ((1 << kHasFastElements) & bit_field2()) != 0;
}
+ // Tells whether the map is attached to SharedFunctionInfo
+ // (for inobject slack tracking).
+ inline void set_attached_to_shared_function_info(bool value);
+
+ inline bool attached_to_shared_function_info();
+
// Tells whether the instance needs security checks when accessing its
// properties.
inline void set_is_access_check_needed(bool access_check_needed);
@@ -3162,6 +3168,8 @@
// [constructor]: points back to the function responsible for this map.
DECL_ACCESSORS(constructor, Object)
+ inline JSFunction* unchecked_constructor();
+
// [instance descriptors]: describes the object.
DECL_ACCESSORS(instance_descriptors, DescriptorArray)
@@ -3240,6 +3248,10 @@
inline int visitor_id();
inline void set_visitor_id(int visitor_id);
+ typedef void (*TraverseCallback)(Map* map, void* data);
+
+ void TraverseTransitionTree(TraverseCallback callback, void* data);
+
static const int kMaxPreAllocatedPropertyFields = 255;
// Layout description.
@@ -3293,6 +3305,7 @@
static const int kFunctionWithPrototype = 1;
static const int kHasFastElements = 2;
static const int kStringWrapperSafeForDefaultValueOf = 3;
+ static const int kAttachedToSharedFunctionInfo = 4;
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
@@ -3447,6 +3460,95 @@
inline int expected_nof_properties();
inline void set_expected_nof_properties(int value);
+ // Inobject slack tracking is the way to reclaim unused inobject space.
+ //
+ // The instance size is initially determined by adding some slack to
+ // expected_nof_properties (to allow for a few extra properties added
+ // after the constructor). There is no guarantee that the extra space
+ // will not be wasted.
+ //
+ // Here is the algorithm to reclaim the unused inobject space:
+ // - Detect the first constructor call for this SharedFunctionInfo.
+ // When it happens enter the "in progress" state: remember the
+ // constructor's initial_map and install a special construct stub that
+ // counts constructor calls.
+ // - While the tracking is in progress create objects filled with
+ // one_pointer_filler_map instead of undefined_value. This way they can be
+ // resized quickly and safely.
+ // - Once enough (kGenerousAllocationCount) objects have been created
+ // compute the 'slack' (traverse the map transition tree starting from the
+ // initial_map and find the lowest value of unused_property_fields).
+ // - Traverse the transition tree again and decrease the instance size
+ // of every map. Existing objects will resize automatically (they are
+ // filled with one_pointer_filler_map). All further allocations will
+ // use the adjusted instance size.
+ // - Decrease expected_nof_properties so that an allocations made from
+ // another context will use the adjusted instance size too.
+ // - Exit "in progress" state by clearing the reference to the initial_map
+ // and setting the regular construct stub (generic or inline).
+ //
+ // The above is the main event sequence. Two special cases are possible
+ // while the tracking is in progress:
+ //
+ // - GC occurs.
+ // Check if the initial_map is referenced by any live objects (except this
+ // SharedFunctionInfo). If it is, continue tracking as usual.
+ // If it is not, clear the reference and reset the tracking state. The
+ // tracking will be initiated again on the next constructor call.
+ //
+ // - The constructor is called from another context.
Vitaly Repeshko 2010/09/22 14:40:25 As we discussed this probably applies also to the
Vladislav Kaznacheev 2010/09/23 08:38:16 Done.
+ // Immediately complete the tracking, perform all the necessary changes
+ // to maps. This is necessary because there is no efficient way to track
+ // object creation in multiple contexts.
+ // Proceed to create an object in the current context (with the adjusted
+ // size).
+ //
+ // Important: inobject slack tracking is not attempted during the snapshot
+ // creation.
+
+ static const int kGenerousAllocationCount = 16;
+
+ // [construction_count]: Counter for constructor calls made during
+ // the tracking phase.
+ inline int construction_count();
+ inline void set_construction_count(int value);
+
+ // [initial_map]: initial map of the first function called as a constructor.
+ // Saved for the duration of the tracking phase.
+ // This is a weak link (GC resets it to undefined_value if no other live
+ // object reference this map).
+ DECL_ACCESSORS(initial_map, Object)
+
+ // True if the initial_map is not undefined and the countdown stub is
+ // installed.
+ inline bool IsInobjectSlackTrackingInProgress();
+
+ // Starts the tracking.
+ // Stores the initial map and installs the countdown stub.
+ // IsInobjectSlackTrackingInProgress is normally true after this call,
+ // except when tracking have not been started (e.g. the map has no unused
+ // properties or the snapshot is being built).
+ void StartInobjectSlackTracking(Map* map);
+
+ // Completes the tracking.
+ // IsInobjectSlackTrackingInProgress is false after this call.
+ void CompleteInobjectSlackTracking();
+
+ // Clears the initial_map before the GC marking phase to ensure the reference
+ // is weak. IsInobjectSlackTrackingInProgress is false after this call.
+ void DetachInitialMap();
+
+ // Restores the link to the initial map after the GC marking phase.
+ // IsInobjectSlackTrackingInProgress is true after this call.
+ void AttachInitialMap(Map* map);
+
+ // False if there are definitely no live objects created from this function.
+ // True if live objects _may_ exist (existence not guaranteed).
+ // May go back from true to false after GC.
+ inline bool live_objects_may_exist();
+
+ inline void set_live_objects_may_exist(bool value);
+
// [instance class name]: class name for instances.
DECL_ACCESSORS(instance_class_name, Object)
@@ -3598,8 +3700,10 @@
static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
+ static const int kInitialMapOffset =
+ kInferredNameOffset + kPointerSize;
static const int kThisPropertyAssignmentsOffset =
- kInferredNameOffset + kPointerSize;
+ kInitialMapOffset + kPointerSize;
#if V8_HOST_ARCH_32_BIT
// Smi fields.
static const int kLengthOffset =
@@ -3623,7 +3727,7 @@
static const int kSize = kThisPropertyAssignmentsCountOffset + kPointerSize;
#else
// The only reason to use smi fields instead of int fields
- // is to allow interation without maps decoding during
+ // is to allow iteration without maps decoding during
// garbage collections.
// To avoid wasting space on 64-bit architectures we use
// the following trick: we group integer fields into pairs
@@ -3658,6 +3762,18 @@
static const int kSize = kThisPropertyAssignmentsCountOffset + kIntSize;
#endif
+
+ // The construction counter for inobject slack tracking is stored in the
+ // most significant byte of compiler_hints which is otherwise unused.
+ // Its offset depends on the endian-ness of the architecture.
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ static const int kConstructionCountOffset = kCompilerHintsOffset + 3;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ static const int kConstructionCountOffset = kCompilerHintsOffset + 0;
+#else
+#error Unknown byte ordering
+#endif
+
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
typedef FixedBodyDescriptor<kNameOffset,
@@ -3677,7 +3793,8 @@
static const int kHasOnlySimpleThisPropertyAssignments = 0;
static const int kTryFullCodegen = 1;
static const int kAllowLazyCompilation = 2;
- static const int kCodeAgeShift = 3;
+ static const int kLiveObjectsMayExist = 3;
+ static const int kCodeAgeShift = 4;
static const int kCodeAgeMask = 7;
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);

Powered by Google App Engine
This is Rietveld 408576698