Commit 35ff259b authored by ulan's avatar ulan Committed by Commit bot

Refactor Map::ConstructionCount.

This combines Map::DoneInobjectSlackTracking and Map::ConstructionCount into one more generic 4-bit counter.

Counter values from 15 down to 8 are used for in-object slack tracking, values from 7 down to 0 are free to be used for a new counter when in-object slack tracking is inactive.

Review URL: https://codereview.chromium.org/767253002

Cr-Commit-Position: refs/heads/master@{#25689}
parent 5ce364d8
......@@ -372,13 +372,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset);
// Check if slack tracking is enabled.
__ ldr(r4, bit_field3);
__ DecodeField<Map::ConstructionCount>(r3, r4);
__ cmp(r3, Operand(JSFunction::kNoSlackTracking));
__ b(eq, &allocate);
__ DecodeField<Map::Counter>(r3, r4);
__ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
__ b(lt, &allocate);
// Decrease generous allocation count.
__ sub(r4, r4, Operand(1 << Map::ConstructionCount::kShift));
__ sub(r4, r4, Operand(1 << Map::Counter::kShift));
__ str(r4, bit_field3);
__ cmp(r3, Operand(JSFunction::kFinishSlackTracking));
__ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
__ b(ne, &allocate);
__ push(r1);
......@@ -431,9 +431,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Check if slack tracking is enabled.
__ ldr(ip, FieldMemOperand(r2, Map::kBitField3Offset));
__ DecodeField<Map::ConstructionCount>(ip);
__ cmp(ip, Operand(JSFunction::kNoSlackTracking));
__ b(eq, &no_inobject_slack_tracking);
__ DecodeField<Map::Counter>(ip);
__ cmp(ip, Operand(Map::kSlackTrackingCounterEnd));
__ b(lt, &no_inobject_slack_tracking);
// Allocate object with a slack.
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
......
......@@ -367,13 +367,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
FieldMemOperand(init_map, Map::kBitField3Offset);
// Check if slack tracking is enabled.
__ Ldr(x4, bit_field3);
__ DecodeField<Map::ConstructionCount>(constructon_count, x4);
__ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking));
__ B(eq, &allocate);
__ DecodeField<Map::Counter>(constructon_count, x4);
__ Cmp(constructon_count, Operand(Map::kSlackTrackingCounterEnd));
__ B(lt, &allocate);
// Decrease generous allocation count.
__ Subs(x4, x4, Operand(1 << Map::ConstructionCount::kShift));
__ Subs(x4, x4, Operand(1 << Map::Counter::kShift));
__ Str(x4, bit_field3);
__ Cmp(constructon_count, Operand(JSFunction::kFinishSlackTracking));
__ Cmp(constructon_count, Operand(Map::kSlackTrackingCounterEnd));
__ B(ne, &allocate);
// Push the constructor and map to the stack, and the constructor again
......@@ -381,7 +381,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ Push(constructor, init_map, constructor);
__ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
__ Pop(init_map, constructor);
__ Mov(constructon_count, Operand(JSFunction::kNoSlackTracking));
__ Mov(constructon_count, Operand(Map::kSlackTrackingCounterEnd - 1));
__ Bind(&allocate);
}
......@@ -434,8 +434,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Label no_inobject_slack_tracking;
// Check if slack tracking is enabled.
__ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking));
__ B(eq, &no_inobject_slack_tracking);
__ Cmp(constructon_count, Operand(Map::kSlackTrackingCounterEnd));
__ B(lt, &no_inobject_slack_tracking);
constructon_count = NoReg;
// Fill the pre-allocated fields with undef.
......
......@@ -2365,7 +2365,8 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
reinterpret_cast<Map*>(result)->set_bit_field(0);
reinterpret_cast<Map*>(result)->set_bit_field2(0);
int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
Map::OwnsDescriptors::encode(true);
Map::OwnsDescriptors::encode(true) |
Map::Counter::encode(Map::kRetainingCounterStart);
reinterpret_cast<Map*>(result)->set_bit_field3(bit_field3);
return result;
}
......@@ -2401,7 +2402,8 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type,
map->set_bit_field(0);
map->set_bit_field2(1 << Map::kIsExtensible);
int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
Map::OwnsDescriptors::encode(true);
Map::OwnsDescriptors::encode(true) |
Map::Counter::encode(Map::kRetainingCounterStart);
map->set_bit_field3(bit_field3);
map->set_elements_kind(elements_kind);
......
......@@ -160,18 +160,17 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (!is_api_function) {
Label allocate;
// The code below relies on these assumptions.
STATIC_ASSERT(JSFunction::kNoSlackTracking == 0);
STATIC_ASSERT(Map::ConstructionCount::kShift +
Map::ConstructionCount::kSize == 32);
STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
// Check if slack tracking is enabled.
__ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
__ shr(esi, Map::ConstructionCount::kShift);
__ j(zero, &allocate); // JSFunction::kNoSlackTracking
__ shr(esi, Map::Counter::kShift);
__ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(less, &allocate);
// Decrease generous allocation count.
__ sub(FieldOperand(eax, Map::kBitField3Offset),
Immediate(1 << Map::ConstructionCount::kShift));
Immediate(1 << Map::Counter::kShift));
__ cmp(esi, JSFunction::kFinishSlackTracking);
__ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(not_equal, &allocate);
__ push(eax);
......@@ -182,7 +181,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ pop(edi);
__ pop(eax);
__ xor_(esi, esi); // JSFunction::kNoSlackTracking
__ mov(esi, Map::kSlackTrackingCounterEnd - 1);
__ bind(&allocate);
}
......@@ -219,8 +218,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Label no_inobject_slack_tracking;
// Check if slack tracking is enabled.
__ cmp(esi, JSFunction::kNoSlackTracking);
__ j(equal, &no_inobject_slack_tracking);
__ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
__ movzx_b(esi,
......
......@@ -4627,24 +4627,12 @@ bool Map::is_migration_target() {
}
void Map::set_done_inobject_slack_tracking(bool value) {
set_bit_field3(DoneInobjectSlackTracking::update(bit_field3(), value));
void Map::set_counter(int value) {
set_bit_field3(Counter::update(bit_field3(), value));
}
bool Map::done_inobject_slack_tracking() {
return DoneInobjectSlackTracking::decode(bit_field3());
}
void Map::set_construction_count(int value) {
set_bit_field3(ConstructionCount::update(bit_field3(), value));
}
int Map::construction_count() {
return ConstructionCount::decode(bit_field3());
}
int Map::counter() { return Counter::decode(bit_field3()); }
void Map::freeze() {
......@@ -6052,7 +6040,7 @@ bool JSFunction::IsInOptimizationQueue() {
bool JSFunction::IsInobjectSlackTrackingInProgress() {
return has_initial_map() &&
initial_map()->construction_count() != JSFunction::kNoSlackTracking;
initial_map()->counter() >= Map::kSlackTrackingCounterEnd;
}
......
......@@ -6622,8 +6622,7 @@ Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
if (!map->is_dictionary_map()) {
new_bit_field3 = IsUnstable::update(new_bit_field3, false);
}
new_bit_field3 = ConstructionCount::update(new_bit_field3,
JSFunction::kNoSlackTracking);
new_bit_field3 = Counter::update(new_bit_field3, kRetainingCounterStart);
result->set_bit_field3(new_bit_field3);
return result;
}
......@@ -10262,17 +10261,13 @@ void JSFunction::StartInobjectSlackTracking() {
Map* map = initial_map();
// Only initiate the tracking the first time.
if (map->done_inobject_slack_tracking()) return;
map->set_done_inobject_slack_tracking(true);
// No tracking during the snapshot construction phase.
Isolate* isolate = GetIsolate();
if (isolate->serializer_enabled()) return;
if (map->unused_property_fields() == 0) return;
map->set_construction_count(kGenerousAllocationCount);
map->set_counter(Map::kSlackTrackingCounterStart);
}
......@@ -10319,8 +10314,8 @@ void JSFunction::CompleteInobjectSlackTracking() {
DCHECK(has_initial_map());
Map* map = initial_map();
DCHECK(map->done_inobject_slack_tracking());
map->set_construction_count(kNoSlackTracking);
DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
map->set_counter(Map::kRetainingCounterStart);
int slack = map->unused_property_fields();
map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
......
......@@ -5665,12 +5665,18 @@ class Map: public HeapObject {
class IsFrozen : public BitField<bool, 24, 1> {};
class IsUnstable : public BitField<bool, 25, 1> {};
class IsMigrationTarget : public BitField<bool, 26, 1> {};
class DoneInobjectSlackTracking : public BitField<bool, 27, 1> {};
// Bit 28 is free.
// Bit 27 is free.
// Keep this bit field at the very end for better code in
// Builtins::kJSConstructStubGeneric stub.
class ConstructionCount: public BitField<int, 29, 3> {};
// This counter is used for in-object slack tracking and for map aging.
// The in-object slack tracking is considered enabled when the counter is
// in the range [kSlackTrackingCounterStart, kSlackTrackingCounterEnd].
class Counter : public BitField<bool, 28, 4> {};
static const int kSlackTrackingCounterStart = 14;
static const int kSlackTrackingCounterEnd = 8;
static const int kRetainingCounterStart = kSlackTrackingCounterEnd - 1;
static const int kRetainingCounterEnd = 0;
// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
......@@ -6012,10 +6018,8 @@ 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 set_counter(int value);
inline int counter();
inline void deprecate();
inline bool is_deprecated();
inline bool CanBeDeprecated();
......@@ -7366,13 +7370,12 @@ class JSFunction: public JSObject {
// 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.
// counter in the initial_map.
// - 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
// - Once enough 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
......@@ -7385,23 +7388,17 @@ class JSFunction: public JSObject {
// 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.
static const int kGenerousAllocationCount =
Map::kSlackTrackingCounterStart - Map::kSlackTrackingCounterEnd + 1;
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
......
......@@ -158,22 +158,20 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// rax: initial map
__ CmpInstanceType(rax, JS_FUNCTION_TYPE);
__ j(equal, &rt_call);
if (!is_api_function) {
Label allocate;
// The code below relies on these assumptions.
STATIC_ASSERT(JSFunction::kNoSlackTracking == 0);
STATIC_ASSERT(Map::ConstructionCount::kShift +
Map::ConstructionCount::kSize == 32);
STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
// Check if slack tracking is enabled.
__ movl(rsi, FieldOperand(rax, Map::kBitField3Offset));
__ shrl(rsi, Immediate(Map::ConstructionCount::kShift));
__ j(zero, &allocate); // JSFunction::kNoSlackTracking
__ shrl(rsi, Immediate(Map::Counter::kShift));
__ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
__ j(less, &allocate);
// Decrease generous allocation count.
__ subl(FieldOperand(rax, Map::kBitField3Offset),
Immediate(1 << Map::ConstructionCount::kShift));
Immediate(1 << Map::Counter::kShift));
__ cmpl(rsi, Immediate(JSFunction::kFinishSlackTracking));
__ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
__ j(not_equal, &allocate);
__ Push(rax);
......@@ -184,7 +182,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ Pop(rdi);
__ Pop(rax);
__ xorl(rsi, rsi); // JSFunction::kNoSlackTracking
__ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1));
__ bind(&allocate);
}
......@@ -222,8 +220,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Label no_inobject_slack_tracking;
// Check if slack tracking is enabled.
__ cmpl(rsi, Immediate(JSFunction::kNoSlackTracking));
__ j(equal, &no_inobject_slack_tracking);
__ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
__ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
__ movzxbp(rsi,
......
......@@ -160,18 +160,17 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (!is_api_function) {
Label allocate;
// The code below relies on these assumptions.
STATIC_ASSERT(JSFunction::kNoSlackTracking == 0);
STATIC_ASSERT(Map::ConstructionCount::kShift +
Map::ConstructionCount::kSize == 32);
STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
// Check if slack tracking is enabled.
__ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
__ shr(esi, Map::ConstructionCount::kShift);
__ j(zero, &allocate); // JSFunction::kNoSlackTracking
__ shr(esi, Map::Counter::kShift);
__ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(less, &allocate);
// Decrease generous allocation count.
__ sub(FieldOperand(eax, Map::kBitField3Offset),
Immediate(1 << Map::ConstructionCount::kShift));
Immediate(1 << Map::Counter::kShift));
__ cmp(esi, JSFunction::kFinishSlackTracking);
__ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(not_equal, &allocate);
__ push(eax);
......@@ -182,7 +181,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ pop(edi);
__ pop(eax);
__ xor_(esi, esi); // JSFunction::kNoSlackTracking
__ mov(esi, Map::kSlackTrackingCounterEnd - 1);
__ bind(&allocate);
}
......@@ -219,8 +218,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Label no_inobject_slack_tracking;
// Check if slack tracking is enabled.
__ cmp(esi, JSFunction::kNoSlackTracking);
__ j(equal, &no_inobject_slack_tracking);
__ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
__ movzx_b(esi,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment