| Index: src/objects.h
|
| diff --git a/src/objects.h b/src/objects.h
|
| index d642e1e7da88b4f57bf49f79b485031f771a1ef3..805b7f894f0ddf454686cb62a376c36608118891 100644
|
| --- a/src/objects.h
|
| +++ b/src/objects.h
|
| @@ -5964,6 +5964,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
|
| @@ -6145,12 +6149,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.
|
| @@ -6285,6 +6283,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();
|
| @@ -6525,7 +6527,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;
|
| @@ -6918,108 +6920,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)
|
|
|
| @@ -7265,12 +7175,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;
|
| @@ -7306,7 +7214,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;
|
|
|
| @@ -7340,21 +7248,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.
|
| @@ -7369,7 +7266,6 @@ class SharedFunctionInfo: public HeapObject {
|
| enum CompilerHints {
|
| kAllowLazyCompilation,
|
| kAllowLazyCompilationWithoutContext,
|
| - kLiveObjectsMayExist,
|
| kOptimizationDisabled,
|
| kStrictModeFunction,
|
| kUsesArguments,
|
| @@ -7583,6 +7479,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.
|
| //
|
|
|