AllocationSite::kNestedSiteOffset),
graph()->GetConstant0());
- // Pretenuring calculation fields.
+ // Pretenuring calculation field.
Add<HStoreNamedField>(object,
HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoFoundCountOffset),
+ AllocationSite::kPretenureDataOffset),
graph()->GetConstant0());
+ // Pretenuring memento creation count field.
Add<HStoreNamedField>(object,
HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoCreateCountOffset),
- graph()->GetConstant0());
-
- Add<HStoreNamedField>(object,
- HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kPretenureDecisionOffset),
+ AllocationSite::kPretenureCreateCountOffset),
graph()->GetConstant0());
// Store an empty fixed array for the code dependency.
AllocationSite::kTransitionInfoOffset);
SetInternalReference(site, entry, "nested_site", site->nested_site(),
AllocationSite::kNestedSiteOffset);
- SetInternalReference(site, entry, "memento_found_count",
- site->memento_found_count(),
- AllocationSite::kMementoFoundCountOffset);
- SetInternalReference(site, entry, "memento_create_count",
- site->memento_create_count(),
- AllocationSite::kMementoCreateCountOffset);
- SetInternalReference(site, entry, "pretenure_decision",
- site->pretenure_decision(),
- AllocationSite::kPretenureDecisionOffset);
+ SetInternalReference(site, entry, "pretenure_data",
+ site->pretenure_data(),
+ AllocationSite::kPretenureDataOffset);
+ SetInternalReference(site, entry, "pretenure_create_count",
+ site->pretenure_create_count(),
+ AllocationSite::kPretenureCreateCountOffset);
SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
AllocationSite::kDependentCodeOffset);
}
list_element->IsAllocationSite()) {
AllocationSite* site = use_scratchpad ?
allocation_sites_scratchpad[i] : AllocationSite::cast(list_element);
- allocation_mementos_found += site->memento_found_count()->value();
- if (site->memento_found_count()->value() > 0) {
+ allocation_mementos_found += site->memento_found_count();
+ if (site->memento_found_count() > 0) {
active_allocation_sites++;
}
if (site->DigestPretenuringFeedback()) {
return HObjectAccess(kInobject, offset, Representation::Tagged());
case AllocationSite::kNestedSiteOffset:
return HObjectAccess(kInobject, offset, Representation::Tagged());
- case AllocationSite::kMementoFoundCountOffset:
+ case AllocationSite::kPretenureDataOffset:
return HObjectAccess(kInobject, offset, Representation::Smi());
- case AllocationSite::kMementoCreateCountOffset:
- return HObjectAccess(kInobject, offset, Representation::Smi());
- case AllocationSite::kPretenureDecisionOffset:
+ case AllocationSite::kPretenureCreateCountOffset:
return HObjectAccess(kInobject, offset, Representation::Smi());
case AllocationSite::kDependentCodeOffset:
return HObjectAccess(kInobject, offset, Representation::Tagged());
if (FLAG_allocation_site_pretenuring) {
HValue* memento_create_count = Add<HLoadNamedField>(
allocation_site, HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoCreateCountOffset));
+ AllocationSite::kPretenureCreateCountOffset));
memento_create_count = AddUncasted<HAdd>(
memento_create_count, graph()->GetConstant1());
// This smi value is reset to zero after every gc, overflow isn't a problem
memento_create_count->ClearFlag(HValue::kCanOverflow);
HStoreNamedField* store = Add<HStoreNamedField>(
allocation_site, HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoCreateCountOffset), memento_create_count);
+ AllocationSite::kPretenureCreateCountOffset), memento_create_count);
// No write barrier needed to store a smi.
store->SkipWriteBarrier();
}
#include "factory.h"
#include "incremental-marking.h"
#include "transitions-inl.h"
+#include "objects-visiting.h"
namespace v8 {
namespace internal {
set_transition_info(Smi::FromInt(0));
SetElementsKind(GetInitialFastElementsKind());
set_nested_site(Smi::FromInt(0));
- set_memento_create_count(Smi::FromInt(0));
- set_memento_found_count(Smi::FromInt(0));
- set_pretenure_decision(Smi::FromInt(0));
+ set_pretenure_data(Smi::FromInt(0));
+ set_pretenure_create_count(Smi::FromInt(0));
set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
SKIP_WRITE_BARRIER);
}
void AllocationSite::MarkZombie() {
ASSERT(!IsZombie());
Initialize();
- set_pretenure_decision(Smi::FromInt(kZombie));
+ set_pretenure_decision(kZombie);
}
}
+inline void AllocationSite::set_memento_found_count(int count) {
+ int value = pretenure_data()->value();
+ // Verify that we can count more mementos than we can possibly find in one
+ // new space collection.
+ ASSERT((GetHeap()->MaxSemiSpaceSize() /
+ (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
+ AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
+ ASSERT(count < MementoFoundCountBits::kMax);
+ set_pretenure_data(
+ Smi::FromInt(MementoFoundCountBits::update(value, count)),
+ SKIP_WRITE_BARRIER);
+}
+
inline bool AllocationSite::IncrementMementoFoundCount() {
if (IsZombie()) return false;
- int value = memento_found_count()->value();
- set_memento_found_count(Smi::FromInt(value + 1));
+ int value = memento_found_count();
+ set_memento_found_count(value + 1);
return value == 0;
}
inline void AllocationSite::IncrementMementoCreateCount() {
ASSERT(FLAG_allocation_site_pretenuring);
- int value = memento_create_count()->value();
- set_memento_create_count(Smi::FromInt(value + 1));
+ int value = memento_create_count();
+ set_memento_create_count(value + 1);
}
inline bool AllocationSite::DigestPretenuringFeedback() {
bool decision_made = false;
- int create_count = memento_create_count()->value();
+ int create_count = memento_create_count();
if (create_count >= kPretenureMinimumCreated) {
- int found_count = memento_found_count()->value();
+ int found_count = memento_found_count();
double ratio = static_cast<double>(found_count) / create_count;
if (FLAG_trace_track_allocation_sites) {
PrintF("AllocationSite: %p (created, found, ratio) (%d, %d, %f)\n",
static_cast<void*>(this), create_count, found_count, ratio);
}
int current_mode = GetPretenureMode();
- int result = ratio >= kPretenureRatio ? kTenure : kDontTenure;
- set_pretenure_decision(Smi::FromInt(result));
+ PretenureDecision result = ratio >= kPretenureRatio
+ ? kTenure
+ : kDontTenure;
+ set_pretenure_decision(result);
decision_made = true;
if (current_mode != GetPretenureMode()) {
dependent_code()->DeoptimizeDependentCodeGroup(
}
// Clear feedback calculation fields until the next gc.
- set_memento_found_count(Smi::FromInt(0));
- set_memento_create_count(Smi::FromInt(0));
+ set_memento_found_count(0);
+ set_memento_create_count(0);
return decision_made;
}
ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
-ACCESSORS_TO_SMI(AllocationSite, memento_found_count, kMementoFoundCountOffset)
-ACCESSORS_TO_SMI(AllocationSite, memento_create_count,
- kMementoCreateCountOffset)
-ACCESSORS_TO_SMI(AllocationSite, pretenure_decision, kPretenureDecisionOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
+ kPretenureCreateCountOffset)
ACCESSORS(AllocationSite, dependent_code, DependentCode,
kDependentCodeOffset)
ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
PrintF(out, "\n - nested site: ");
nested_site()->ShortPrint(out);
PrintF(out, "\n - memento found count: ");
- memento_found_count()->ShortPrint(out);
+ Smi::FromInt(memento_found_count())->ShortPrint(out);
PrintF(out, "\n - memento create count: ");
- memento_create_count()->ShortPrint(out);
+ Smi::FromInt(memento_create_count())->ShortPrint(out);
PrintF(out, "\n - pretenure decision: ");
- pretenure_decision()->ShortPrint(out);
+ Smi::FromInt(pretenure_decision())->ShortPrint(out);
PrintF(out, "\n - transition_info: ");
if (transition_info()->IsSmi()) {
ElementsKind kind = GetElementsKind();
#include "isolate-inl.h"
#include "log.h"
#include "objects-inl.h"
-#include "objects-visiting.h"
#include "objects-visiting-inl.h"
#include "macro-assembler.h"
#include "mark-compact.h"
dependent_code()->DeoptimizeDependentCodeGroup(
GetIsolate(),
DependentCode::kAllocationSiteTenuringChangedGroup);
- set_pretenure_decision(Smi::FromInt(kUndecided));
- set_memento_found_count(Smi::FromInt(0));
- set_memento_create_count(Smi::FromInt(0));
+ set_pretenure_decision(kUndecided);
+ set_memento_found_count(0);
+ set_memento_create_count(0);
}
PretenureFlag AllocationSite::GetPretenureMode() {
- int mode = pretenure_decision()->value();
+ PretenureDecision mode = pretenure_decision();
// Zombie objects "decide" to be untenured.
return (mode == kTenure && GetHeap()->GetPretenureMode() == TENURED)
? TENURED : NOT_TENURED;
static const int kPretenureMinimumCreated = 100;
// Values for pretenure decision field.
- enum {
+ enum PretenureDecision {
kUndecided = 0,
kDontTenure = 1,
kTenure = 2,
- kZombie = 3
+ kZombie = 3,
+ kLastPretenureDecisionValue = kZombie
};
DECL_ACCESSORS(transition_info, Object)
// walked in a particular order. So [[1, 2], 1, 2] will have one
// nested_site, but [[1, 2], 3, [4]] will have a list of two.
DECL_ACCESSORS(nested_site, Object)
- DECL_ACCESSORS(memento_found_count, Smi)
- DECL_ACCESSORS(memento_create_count, Smi)
- // TODO(mvstanton): we don't need a whole integer to record pretenure
- // decision. Consider sharing space with memento_found_count.
- DECL_ACCESSORS(pretenure_decision, Smi)
+ DECL_ACCESSORS(pretenure_data, Smi)
+ DECL_ACCESSORS(pretenure_create_count, Smi)
DECL_ACCESSORS(dependent_code, DependentCode)
DECL_ACCESSORS(weak_next, Object)
// This method is expensive, it should only be called for reporting.
bool IsNestedSite();
+ // transition_info bitfields, for constructed array transition info.
class ElementsKindBits: public BitField<ElementsKind, 0, 15> {};
class UnusedBits: public BitField<int, 15, 14> {};
class DoNotInlineBit: public BitField<bool, 29, 1> {};
+ // Bitfields for pretenure_data
+ class MementoFoundCountBits: public BitField<int, 0, 28> {};
+ class PretenureDecisionBits: public BitField<PretenureDecision, 28, 2> {};
+ STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue);
+
// Increments the mementos found counter and returns true when the first
// memento was found for a given allocation site.
inline bool IncrementMementoFoundCount();
void ResetPretenureDecision();
+ PretenureDecision pretenure_decision() {
+ int value = pretenure_data()->value();
+ return PretenureDecisionBits::decode(value);
+ }
+
+ void set_pretenure_decision(PretenureDecision decision) {
+ int value = pretenure_data()->value();
+ set_pretenure_data(
+ Smi::FromInt(PretenureDecisionBits::update(value, decision)),
+ SKIP_WRITE_BARRIER);
+ }
+
+ int memento_found_count() {
+ int value = pretenure_data()->value();
+ return MementoFoundCountBits::decode(value);
+ }
+
+ inline void set_memento_found_count(int count);
+
+ int memento_create_count() {
+ return pretenure_create_count()->value();
+ }
+
+ void set_memento_create_count(int count) {
+ set_pretenure_create_count(Smi::FromInt(count), SKIP_WRITE_BARRIER);
+ }
+
// The pretenuring decision is made during gc, and the zombie state allows
// us to recognize when an allocation site is just being kept alive because
// a later traversal of new space may discover AllocationMementos that point
// to this AllocationSite.
bool IsZombie() {
- return pretenure_decision()->value() == kZombie;
+ return pretenure_decision() == kZombie;
}
inline void MarkZombie();
static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
- static const int kMementoFoundCountOffset = kNestedSiteOffset + kPointerSize;
- static const int kMementoCreateCountOffset =
- kMementoFoundCountOffset + kPointerSize;
- static const int kPretenureDecisionOffset =
- kMementoCreateCountOffset + kPointerSize;
+ static const int kPretenureDataOffset = kNestedSiteOffset + kPointerSize;
+ static const int kPretenureCreateCountOffset =
+ kPretenureDataOffset + kPointerSize;
static const int kDependentCodeOffset =
- kPretenureDecisionOffset + kPointerSize;
+ kPretenureCreateCountOffset + kPointerSize;
static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
static const int kSize = kWeakNextOffset + kPointerSize;
private:
inline DependentCode::DependencyGroup ToDependencyGroup(Reason reason);
bool PretenuringDecisionMade() {
- return pretenure_decision()->value() != kUndecided;
+ return pretenure_decision() != kUndecided;
}
DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationSite);