Chromium Code Reviews| 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); |