Index: src/objects.h |
diff --git a/src/objects.h b/src/objects.h |
index 47fea39e4d9e7566646541c0cd8869ef743b3251..f26dc07c1e170f176855e28259b97b75af596a56 100644 |
--- a/src/objects.h |
+++ b/src/objects.h |
@@ -6001,6 +6001,10 @@ class Map: public HeapObject { |
class IsFrozen: public BitField<bool, 25, 1> {}; |
class IsUnstable: public BitField<bool, 26, 1> {}; |
class IsMigrationTarget: public BitField<bool, 27, 1> {}; |
+ class DoneInobjectSlackTracking: public BitField<bool, 28, 1> {}; |
+ // Keep this bit field at the very end for better code in |
+ // Builtins::kJSConstructStubGeneric stub. |
+ class ConstructionCount: public BitField<int, 29, 3> {}; |
// Tells whether the object in the prototype property will be used |
// for instances created from this function. If the prototype |
@@ -6182,12 +6186,6 @@ class Map: public HeapObject { |
// function that was used to instantiate the object). |
String* constructor_name(); |
- // 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 map is shared between objects that may have different |
// behavior. If true, the map should never be modified, instead a clone |
// should be created and modified. |
@@ -6322,6 +6320,10 @@ class Map: public HeapObject { |
inline bool is_stable(); |
inline void set_migration_target(bool value); |
inline bool is_migration_target(); |
+ inline void set_done_inobject_slack_tracking(bool value); |
+ inline bool done_inobject_slack_tracking(); |
+ inline void set_construction_count(int value); |
+ inline int construction_count(); |
inline void deprecate(); |
inline bool is_deprecated(); |
inline bool CanBeDeprecated(); |
@@ -6562,7 +6564,7 @@ class Map: public HeapObject { |
// Bit positions for bit field 2 |
static const int kIsExtensible = 0; |
static const int kStringWrapperSafeForDefaultValueOf = 1; |
- static const int kAttachedToSharedFunctionInfo = 2; |
+ // Currently bit 2 is not used. |
// No bits can be used after kElementsKindFirstBit, they are all reserved for |
// storing ElementKind. |
static const int kElementsKindShift = 3; |
@@ -6955,108 +6957,16 @@ class SharedFunctionInfo: public HeapObject { |
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. Some 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. |
- // Immediately complete the tracking, perform all the necessary changes |
- // to maps. This is necessary because there is no efficient way to track |
- // multiple initial_maps. |
- // Proceed to create an object in the current context (with the adjusted |
- // size). |
- // |
- // - A different constructor function sharing the same SharedFunctionInfo is |
- // called in the same context. This could be another closure in the same |
- // context, or the first function could have been disposed. |
- // This is handled the same way as the previous case. |
- // |
- // Important: inobject slack tracking is not attempted during the snapshot |
- // creation. |
- |
- static const int kGenerousAllocationCount = 8; |
- |
- // [construction_count]: Counter for constructor calls made during |
- // the tracking phase. |
- inline int construction_count(); |
- inline void set_construction_count(int value); |
- |
// [feedback_vector] - accumulates ast node feedback from full-codegen and |
// (increasingly) from crankshafted code where sufficient feedback isn't |
// available. Currently the field is duplicated in |
// TypeFeedbackInfo::feedback_vector, but the allocation is done here. |
DECL_ACCESSORS(feedback_vector, FixedArray) |
- // [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(); |
- |
// Invoked before pointers in SharedFunctionInfo are being marked. |
// Also clears the optimized code map. |
inline void BeforeVisitingPointers(); |
- // 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. |
- DECL_BOOLEAN_ACCESSORS(live_objects_may_exist) |
- |
// [instance class name]: class name for instances. |
DECL_ACCESSORS(instance_class_name, Object) |
@@ -7302,12 +7212,10 @@ class SharedFunctionInfo: public HeapObject { |
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize; |
static const int kFeedbackVectorOffset = |
kInferredNameOffset + kPointerSize; |
- static const int kInitialMapOffset = |
- kFeedbackVectorOffset + kPointerSize; |
#if V8_HOST_ARCH_32_BIT |
// Smi fields. |
static const int kLengthOffset = |
- kInitialMapOffset + kPointerSize; |
+ kFeedbackVectorOffset + kPointerSize; |
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize; |
static const int kExpectedNofPropertiesOffset = |
kFormalParameterCountOffset + kPointerSize; |
@@ -7343,7 +7251,7 @@ class SharedFunctionInfo: public HeapObject { |
// word is not set and thus this word cannot be treated as pointer |
// to HeapObject during old space traversal. |
static const int kLengthOffset = |
- kInitialMapOffset + kPointerSize; |
+ kFeedbackVectorOffset + kPointerSize; |
static const int kFormalParameterCountOffset = |
kLengthOffset + kIntSize; |
@@ -7377,21 +7285,10 @@ class SharedFunctionInfo: public HeapObject { |
#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 defined(V8_TARGET_LITTLE_ENDIAN) |
- static const int kConstructionCountOffset = kCompilerHintsOffset + 3; |
-#elif defined(V8_TARGET_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, |
- kInitialMapOffset + kPointerSize, |
+ kFeedbackVectorOffset + kPointerSize, |
kSize> BodyDescriptor; |
// Bit positions in start_position_and_type. |
@@ -7406,7 +7303,6 @@ class SharedFunctionInfo: public HeapObject { |
enum CompilerHints { |
kAllowLazyCompilation, |
kAllowLazyCompilationWithoutContext, |
- kLiveObjectsMayExist, |
kOptimizationDisabled, |
kStrictModeFunction, |
kUsesArguments, |
@@ -7622,6 +7518,54 @@ class JSFunction: public JSObject { |
// Tells whether or not the function is on the concurrent recompilation queue. |
inline bool IsInOptimizationQueue(); |
+ // 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 JSFunction. |
+ // When it happens enter the "in progress" state: initialize construction |
+ // counter in the initial_map and set the |done_inobject_slack_tracking| |
+ // flag. |
+ // - 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. |
+ // - SharedFunctionInfo's expected_nof_properties left unmodified since |
+ // allocations made using different closures could actually create different |
+ // kind of objects (see prototype inheritance pattern). |
+ // |
+ // Important: inobject slack tracking is not attempted during the snapshot |
+ // creation. |
+ |
+ static const int kGenerousAllocationCount = Map::ConstructionCount::kMax; |
+ static const int kFinishSlackTracking = 1; |
+ static const int kNoSlackTracking = 0; |
+ |
+ // True if the initial_map is set and the object constructions countdown |
+ // counter is not zero. |
+ inline bool IsInobjectSlackTrackingInProgress(); |
+ |
+ // Starts the tracking. |
+ // Initializes object constructions countdown counter in the initial map. |
+ // 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(); |
+ |
+ // Completes the tracking. |
+ // IsInobjectSlackTrackingInProgress is false after this call. |
+ void CompleteInobjectSlackTracking(); |
+ |
// [literals_or_bindings]: Fixed array holding either |
// the materialized literals or the bindings of a bound function. |
// |