Add DependentCode to PropertyCells

R=mstarzinger@chromium.org, ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15341 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2013-06-26 16:17:12 +00:00
parent 3da5ba9ac3
commit 00709075ea
14 changed files with 147 additions and 74 deletions

View File

@ -87,7 +87,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
RegisterDependentCodeForEmbeddedMaps(code);
}
PopulateDeoptimizationData(code);
info()->CommitDependentMaps(code);
info()->CommitDependencies(code);
}

View File

@ -118,7 +118,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
? new List<OffsetRange>(2) : NULL;
for (int i = 0; i < DependentCode::kGroupCount; i++) {
dependent_maps_[i] = NULL;
dependencies_[i] = NULL;
}
if (mode == STUB) {
mode_ = STUB;
@ -143,36 +143,42 @@ CompilationInfo::~CompilationInfo() {
// Check that no dependent maps have been added or added dependent maps have
// been rolled back or committed.
for (int i = 0; i < DependentCode::kGroupCount; i++) {
ASSERT_EQ(NULL, dependent_maps_[i]);
ASSERT_EQ(NULL, dependencies_[i]);
}
#endif // DEBUG
}
void CompilationInfo::CommitDependentMaps(Handle<Code> code) {
void CompilationInfo::CommitDependencies(Handle<Code> code) {
for (int i = 0; i < DependentCode::kGroupCount; i++) {
ZoneList<Handle<Map> >* group_maps = dependent_maps_[i];
if (group_maps == NULL) continue;
ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
if (group_objects == NULL) continue;
ASSERT(!object_wrapper_.is_null());
for (int j = 0; j < group_maps->length(); j++) {
group_maps->at(j)->dependent_code()->UpdateToFinishedCode(
static_cast<DependentCode::DependencyGroup>(i), this, *code);
for (int j = 0; j < group_objects->length(); j++) {
DependentCode::DependencyGroup group =
static_cast<DependentCode::DependencyGroup>(i);
DependentCode* dependent_code =
DependentCode::ForObject(group_objects->at(j), group);
dependent_code->UpdateToFinishedCode(group, this, *code);
}
dependent_maps_[i] = NULL; // Zone-allocated, no need to delete.
dependencies_[i] = NULL; // Zone-allocated, no need to delete.
}
}
void CompilationInfo::RollbackDependentMaps() {
void CompilationInfo::RollbackDependencies() {
// Unregister from all dependent maps if not yet committed.
for (int i = 0; i < DependentCode::kGroupCount; i++) {
ZoneList<Handle<Map> >* group_maps = dependent_maps_[i];
if (group_maps == NULL) continue;
for (int j = 0; j < group_maps->length(); j++) {
group_maps->at(j)->dependent_code()->RemoveCompilationInfo(
static_cast<DependentCode::DependencyGroup>(i), this);
ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
if (group_objects == NULL) continue;
for (int j = 0; j < group_objects->length(); j++) {
DependentCode::DependencyGroup group =
static_cast<DependentCode::DependencyGroup>(i);
DependentCode* dependent_code =
DependentCode::ForObject(group_objects->at(j), group);
dependent_code->RemoveCompilationInfo(group, this);
}
dependent_maps_[i] = NULL; // Zone-allocated, no need to delete.
dependencies_[i] = NULL; // Zone-allocated, no need to delete.
}
}
@ -1052,7 +1058,7 @@ void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
// If crankshaft succeeded, install the optimized code else install
// the unoptimized code.
OptimizingCompiler::Status status = optimizing_compiler->last_status();
if (info->HasAbortedDueToDependentMap()) {
if (info->HasAbortedDueToDependencyChange()) {
info->set_bailout_reason("bailed out due to dependent map");
status = optimizing_compiler->AbortOptimization();
} else if (status != OptimizingCompiler::SUCCEEDED) {

View File

@ -240,16 +240,17 @@ class CompilationInfo {
deferred_handles_ = deferred_handles;
}
ZoneList<Handle<Map> >* dependent_maps(DependentCode::DependencyGroup group) {
if (dependent_maps_[group] == NULL) {
dependent_maps_[group] = new(zone_) ZoneList<Handle<Map> >(2, zone_);
ZoneList<Handle<HeapObject> >* dependencies(
DependentCode::DependencyGroup group) {
if (dependencies_[group] == NULL) {
dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_);
}
return dependent_maps_[group];
return dependencies_[group];
}
void CommitDependentMaps(Handle<Code> code);
void CommitDependencies(Handle<Code> code);
void RollbackDependentMaps();
void RollbackDependencies();
void SaveHandles() {
SaveHandle(&closure_);
@ -292,12 +293,12 @@ class CompilationInfo {
return object_wrapper_;
}
void AbortDueToDependentMap() {
mode_ = DEPENDENT_MAP_ABORT;
void AbortDueToDependencyChange() {
mode_ = DEPENDENCY_CHANGE_ABORT;
}
bool HasAbortedDueToDependentMap() {
return mode_ == DEPENDENT_MAP_ABORT;
bool HasAbortedDueToDependencyChange() {
return mode_ == DEPENDENCY_CHANGE_ABORT;
}
protected:
@ -325,7 +326,7 @@ class CompilationInfo {
OPTIMIZE,
NONOPT,
STUB,
DEPENDENT_MAP_ABORT
DEPENDENCY_CHANGE_ABORT
};
void Initialize(Isolate* isolate, Mode mode, Zone* zone, Zone* phase_zone);
@ -408,7 +409,7 @@ class CompilationInfo {
DeferredHandles* deferred_handles_;
ZoneList<Handle<Map> >* dependent_maps_[DependentCode::kGroupCount];
ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount];
template<typename T>
void SaveHandle(Handle<T> *object) {
@ -459,7 +460,7 @@ class CompilationInfoWithZone: public CompilationInfo {
// zone scope and get rid of dependent maps even when the destructor is
// called when cast as a CompilationInfo.
virtual ~CompilationInfoWithZone() {
RollbackDependentMaps();
RollbackDependencies();
}
private:

View File

@ -2859,8 +2859,11 @@ MaybeObject* Heap::AllocatePropertyCell(Object* value) {
}
HeapObject::cast(result)->set_map_no_write_barrier(
global_property_cell_map());
PropertyCell::cast(result)->set_value(value);
PropertyCell::cast(result)->set_type(Type::None());
PropertyCell* cell = PropertyCell::cast(result);
cell->set_dependent_code(DependentCode::cast(empty_fixed_array()),
SKIP_WRITE_BARRIER);
cell->set_value(value);
cell->set_type(Type::None());
return result;
}

View File

@ -109,7 +109,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
if (!info()->IsStub()) {
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
}
info()->CommitDependentMaps(code);
info()->CommitDependencies(code);
}

View File

@ -2251,14 +2251,7 @@ void MarkCompactCollector::MarkLiveObjects() {
while ((cell = js_global_property_cell_iterator.Next()) != NULL) {
ASSERT(cell->IsPropertyCell());
if (IsMarked(cell)) {
int offset = PropertyCell::kValueOffset;
MarkCompactMarkingVisitor::VisitPointer(
heap(),
reinterpret_cast<Object**>(cell->address() + offset));
offset = PropertyCell::kTypeOffset;
MarkCompactMarkingVisitor::VisitPointer(
heap(),
reinterpret_cast<Object**>(cell->address() + offset));
MarkCompactMarkingVisitor::VisitPropertyCell(cell->map(), cell);
}
}
}
@ -2437,11 +2430,22 @@ void MarkCompactCollector::ClearNonLiveReferences() {
ClearNonLiveMapTransitions(map, map_mark);
if (map_mark.Get()) {
ClearNonLiveDependentCode(map);
ClearNonLiveDependentCode(map->dependent_code());
} else {
ClearAndDeoptimizeDependentCode(map);
}
}
// Iterate over property cell space, removing dependent code that is not
// otherwise kept alive by strong references.
HeapObjectIterator cell_iterator(heap_->property_cell_space());
for (HeapObject* cell = cell_iterator.Next();
cell != NULL;
cell = cell_iterator.Next()) {
if (IsMarked(cell)) {
ClearNonLiveDependentCode(PropertyCell::cast(cell)->dependent_code());
}
}
}
@ -2527,9 +2531,8 @@ void MarkCompactCollector::ClearAndDeoptimizeDependentCode(Map* map) {
}
void MarkCompactCollector::ClearNonLiveDependentCode(Map* map) {
void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) {
DisallowHeapAllocation no_allocation;
DependentCode* entries = map->dependent_code();
DependentCode::GroupStartIndexes starts(entries);
int number_of_entries = starts.number_of_entries();
if (number_of_entries == 0) return;
@ -3398,9 +3401,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
cell != NULL;
cell = cell_iterator.Next()) {
if (cell->IsCell()) {
Address value_address = reinterpret_cast<Address>(cell) +
(Cell::kValueOffset - kHeapObjectTag);
updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
Cell::BodyDescriptor::IterateBody(cell, &updating_visitor);
}
}
@ -3410,14 +3411,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
cell != NULL;
cell = js_global_property_cell_iterator.Next()) {
if (cell->IsPropertyCell()) {
Address value_address =
reinterpret_cast<Address>(cell) +
(PropertyCell::kValueOffset - kHeapObjectTag);
updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
Address type_address =
reinterpret_cast<Address>(cell) +
(PropertyCell::kTypeOffset - kHeapObjectTag);
updating_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
PropertyCell::BodyDescriptor::IterateBody(cell, &updating_visitor);
}
}

View File

@ -880,7 +880,7 @@ class MarkCompactCollector {
void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark);
void ClearAndDeoptimizeDependentCode(Map* map);
void ClearNonLiveDependentCode(Map* map);
void ClearNonLiveDependentCode(DependentCode* dependent_code);
// Marking detaches initial maps from SharedFunctionInfo objects
// to make this reference weak. We need to reattach initial maps

View File

@ -87,7 +87,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
RegisterDependentCodeForEmbeddedMaps(code);
}
PopulateDeoptimizationData(code);
info()->CommitDependentMaps(code);
info()->CommitDependencies(code);
}

View File

@ -1641,6 +1641,7 @@ void Cell::set_value(Object* val, WriteBarrierMode ignored) {
WRITE_FIELD(this, kValueOffset, val);
}
ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
Object* PropertyCell::type_raw() {
return READ_FIELD(this, kTypeOffset);

View File

@ -221,10 +221,7 @@ void StaticMarkingVisitor<StaticVisitor>::Initialize() {
Cell::BodyDescriptor,
void>::Visit);
table_.Register(kVisitPropertyCell,
&FixedBodyVisitor<StaticVisitor,
PropertyCell::BodyDescriptor,
void>::Visit);
table_.Register(kVisitPropertyCell, &VisitPropertyCell);
table_.template RegisterSpecializations<DataObjectVisitor,
kVisitDataObject,
@ -358,6 +355,30 @@ void StaticMarkingVisitor<StaticVisitor>::VisitMap(
}
template<typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::VisitPropertyCell(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
Object** slot =
HeapObject::RawField(object, PropertyCell::kDependentCodeOffset);
if (FLAG_collect_maps) {
// Mark property cell dependent codes array but do not push it onto marking
// stack, this will make references from it weak. We will clean dead
// codes when we iterate over property cells in ClearNonLiveReferences.
HeapObject* obj = HeapObject::cast(*slot);
heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
StaticVisitor::MarkObjectWithoutPush(heap, obj);
} else {
StaticVisitor::VisitPointer(heap, slot);
}
StaticVisitor::VisitPointers(heap,
HeapObject::RawField(object, PropertyCell::kPointerFieldsBeginOffset),
HeapObject::RawField(object, PropertyCell::kPointerFieldsEndOffset));
}
template<typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::VisitCode(
Map* map, HeapObject* object) {

View File

@ -395,6 +395,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
table_.GetVisitor(map)(map, obj);
}
INLINE(static void VisitPropertyCell(Map* map, HeapObject* object));
INLINE(static void VisitCodeEntry(Heap* heap, Address entry_address));
INLINE(static void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo));
INLINE(static void VisitCell(Heap* heap, RelocInfo* rinfo));

View File

@ -661,8 +661,7 @@ MaybeObject* JSObject::SetNormalizedProperty(Name* name,
Object* store_value = value;
if (IsGlobalObject()) {
Heap* heap = name->GetHeap();
MaybeObject* maybe_store_value =
heap->AllocatePropertyCell(value);
MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value);
if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
}
Object* dict;
@ -11060,7 +11059,7 @@ void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group,
Handle<DependentCode> codes =
DependentCode::Insert(dep, group, info->object_wrapper());
if (*codes != dependent_code()) set_dependent_code(*codes);
info->dependent_maps(group)->Add(Handle<Map>(this), info->zone());
info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone());
}
@ -11086,6 +11085,16 @@ void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
}
DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
DependencyGroup group) {
AllowDeferredHandleDereference dependencies_are_safe;
if (group == DependentCode::kPropertyCellChangedGroup) {
return Handle<PropertyCell>::cast(object)->dependent_code();
}
return Handle<Map>::cast(object)->dependent_code();
}
Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
DependencyGroup group,
Handle<Object> object) {
@ -11224,7 +11233,7 @@ void DependentCode::DeoptimizeDependentCodeGroup(
code->set_marked_for_deoptimization(true);
} else {
CompilationInfo* info = compilation_info_at(i);
info->AbortDueToDependentMap();
info->AbortDueToDependencyChange();
}
}
// Compact the array by moving all subsequent groups to fill in the new holes.
@ -15757,4 +15766,23 @@ void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) {
}
void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) {
Handle<DependentCode> dep(dependent_code());
Handle<DependentCode> codes =
DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup,
info->object_wrapper());
if (*codes != dependent_code()) set_dependent_code(*codes);
info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
Handle<HeapObject>(this), info->zone());
}
void PropertyCell::AddDependentCode(Handle<Code> code) {
Handle<DependentCode> codes = DependentCode::Insert(
Handle<DependentCode>(dependent_code()),
DependentCode::kPropertyCellChangedGroup, code);
if (*codes != dependent_code()) set_dependent_code(*codes);
}
} } // namespace v8::internal

View File

@ -5027,7 +5027,10 @@ class DependentCode: public FixedArray {
// Group of code that depends on elements not being added to objects with
// this map.
kElementsCantBeAddedGroup,
kGroupCount = kElementsCantBeAddedGroup + 1
// Group of code that depends on global property values in property cells
// not being changed.
kPropertyCellChangedGroup,
kGroupCount = kPropertyCellChangedGroup + 1
};
// Array for holding the index of the first code object of each group.
@ -5069,6 +5072,9 @@ class DependentCode: public FixedArray {
inline void copy(int from, int to);
static inline DependentCode* cast(Object* object);
static DependentCode* ForObject(Handle<HeapObject> object,
DependencyGroup group);
private:
// Make a room at the end of the given group by moving out the first
// code objects of the subsequent groups.
@ -5566,7 +5572,7 @@ class Map: public HeapObject {
inline bool CanOmitPrototypeChecks();
void AddDependentCompilationInfo(DependentCode::DependencyGroup group,
CompilationInfo* info);
CompilationInfo* info);
void AddDependentCode(DependentCode::DependencyGroup group,
Handle<Code> code);
@ -8566,9 +8572,14 @@ class Cell: public HeapObject {
class PropertyCell: public Cell {
public:
// [type]: type of the global property.
Type* type();
void set_type(Type* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// [dependent_code]: dependent code that depends on the type of the global
// property.
DECL_ACCESSORS(dependent_code, DependentCode)
// Casting.
static inline PropertyCell* cast(Object* obj);
@ -8582,12 +8593,19 @@ class PropertyCell: public Cell {
// Layout description.
static const int kTypeOffset = kValueOffset + kPointerSize;
static const int kSize = kTypeOffset + kPointerSize;
static const int kDependentCodeOffset = kTypeOffset + kPointerSize;
static const int kSize = kDependentCodeOffset + kPointerSize;
typedef FixedBodyDescriptor<
kValueOffset,
kTypeOffset + kPointerSize,
PropertyCell::kSize> BodyDescriptor;
static const int kPointerFieldsBeginOffset = kValueOffset;
static const int kPointerFieldsEndOffset = kDependentCodeOffset;
typedef FixedBodyDescriptor<kValueOffset,
kSize,
kSize> BodyDescriptor;
void AddDependentCompilationInfo(CompilationInfo* info);
void AddDependentCode(Handle<Code> code);
private:
DECL_ACCESSORS(type_raw, Object)

View File

@ -92,7 +92,7 @@ void LCodeGen::FinishCode(Handle<Code> code) {
RegisterDependentCodeForEmbeddedMaps(code);
}
PopulateDeoptimizationData(code);
info()->CommitDependentMaps(code);
info()->CommitDependencies(code);
}