Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(674)

Unified Diff: src/objects.cc

Issue 10381053: Implement explicit back pointers in transition tree. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed some comments by Vyacheslav Egorov. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 970fc24550878072e45297bd6c0601a576165ba3..cde43f9f23e0a352702adb360de479b4143c3547 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1604,6 +1604,7 @@ MaybeObject* JSObject::AddFastProperty(String* name,
// We have now allocated all the necessary objects.
// All the changes can be applied at once, so they are atomic.
map()->set_instance_descriptors(old_descriptors);
+ new_map->SetBackPointer(map());
new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
set_map(new_map);
return FastPropertyAtPut(index, value);
@@ -1664,6 +1665,7 @@ MaybeObject* JSObject::AddConstantFunctionProperty(
}
}
old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+ Map::cast(new_map)->SetBackPointer(old_map);
return function;
}
@@ -1824,6 +1826,7 @@ MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition(
}
}
old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+ map()->SetBackPointer(old_map);
return result;
}
@@ -2408,6 +2411,7 @@ MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
return maybe_new_descriptors;
}
set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+ transitioned_map->SetBackPointer(this);
return this;
}
@@ -4653,6 +4657,7 @@ static MaybeObject* CreateFreshAccessor(JSObject* obj,
// step 6: everything went well so far, so we make our changes visible
obj->set_map(map2);
map1->set_instance_descriptors(descriptors1);
+ map2->SetBackPointer(map1);
return obj;
}
@@ -4705,6 +4710,7 @@ static MaybeObject* NewCallbackTransition(JSObject* obj,
// step 4: everything went well so far, so we make our changes visible
obj->set_map(map3);
accessors2->set(component, map3);
+ map3->SetBackPointer(map2);
return obj;
}
@@ -5137,7 +5143,7 @@ class IntrusiveMapTransitionIterator {
// underlying array while it is running.
class IntrusivePrototypeTransitionIterator {
public:
- explicit IntrusivePrototypeTransitionIterator(FixedArray* proto_trans)
+ explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans)
: proto_trans_(proto_trans) { }
void Start() {
@@ -5162,7 +5168,7 @@ class IntrusivePrototypeTransitionIterator {
private:
bool HasTransitions() {
- return proto_trans_->length() >= Map::kProtoTransitionHeaderSize;
+ return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray();
}
Object** Header() {
@@ -5170,12 +5176,16 @@ class IntrusivePrototypeTransitionIterator {
}
int NumberOfTransitions() {
- Object* num = proto_trans_->get(Map::kProtoTransitionNumberOfEntriesOffset);
+ ASSERT(HasTransitions());
+ FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
+ Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
return Smi::cast(num)->value();
}
Map* GetTransition(int transitionNumber) {
- return Map::cast(proto_trans_->get(IndexFor(transitionNumber)));
+ ASSERT(HasTransitions());
+ FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
+ return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
}
int IndexFor(int transitionNumber) {
@@ -5184,7 +5194,7 @@ class IntrusivePrototypeTransitionIterator {
transitionNumber * Map::kProtoTransitionElementsPerEntry;
}
- FixedArray* proto_trans_;
+ HeapObject* proto_trans_;
};
@@ -7346,85 +7356,23 @@ void String::PrintOn(FILE* file) {
}
-void Map::CreateOneBackPointer(Object* transition_target) {
- if (!transition_target->IsMap()) return;
- Map* target = Map::cast(transition_target);
-#ifdef DEBUG
- // Verify target.
- Object* source_prototype = prototype();
- Object* target_prototype = target->prototype();
- ASSERT(source_prototype->IsJSReceiver() ||
- source_prototype->IsMap() ||
- source_prototype->IsNull());
- ASSERT(target_prototype->IsJSReceiver() ||
- target_prototype->IsNull());
- ASSERT(source_prototype->IsMap() ||
- source_prototype == target_prototype);
-#endif
- // Point target back to source. set_prototype() will not let us set
- // the prototype to a map, as we do here.
- *RawField(target, kPrototypeOffset) = this;
-}
-
-
-void Map::CreateBackPointers() {
- DescriptorArray* descriptors = instance_descriptors();
- for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
- switch (descriptors->GetType(i)) {
- case MAP_TRANSITION:
- case CONSTANT_TRANSITION:
- CreateOneBackPointer(descriptors->GetValue(i));
- break;
- case ELEMENTS_TRANSITION: {
- Object* object = descriptors->GetValue(i);
- if (object->IsMap()) {
- CreateOneBackPointer(object);
- } else {
- FixedArray* array = FixedArray::cast(object);
- for (int i = 0; i < array->length(); ++i) {
- CreateOneBackPointer(array->get(i));
- }
- }
- break;
- }
- case CALLBACKS: {
- Object* object = descriptors->GetValue(i);
- if (object->IsAccessorPair()) {
- AccessorPair* accessors = AccessorPair::cast(object);
- CreateOneBackPointer(accessors->getter());
- CreateOneBackPointer(accessors->setter());
- }
- break;
- }
- case NORMAL:
- case FIELD:
- case CONSTANT_FUNCTION:
- case HANDLER:
- case INTERCEPTOR:
- case NULL_DESCRIPTOR:
- break;
- }
- }
-}
-
-
-bool Map::RestoreOneBackPointer(Object* object,
- Object* real_prototype,
- bool* keep_entry) {
- if (!object->IsMap()) return false;
- Map* map = Map::cast(object);
+// Clear a possible back pointer in case the transition leads to a dead map.
+// Return true in case a back pointer has been cleared and false otherwise.
+// Set *keep_entry to true when a live map transition has been found.
+static bool ClearBackPointer(Heap* heap, Object* target, bool* keep_entry) {
+ if (!target->IsMap()) return false;
+ Map* map = Map::cast(target);
if (Marking::MarkBitFrom(map).Get()) {
*keep_entry = true;
return false;
+ } else {
+ map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
+ return true;
}
- ASSERT(map->prototype() == this || map->prototype() == real_prototype);
- // Getter prototype() is read-only, set_prototype() has side effects.
- *RawField(map, Map::kPrototypeOffset) = real_prototype;
- return true;
}
-void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
+void Map::ClearNonLiveTransitions(Heap* heap) {
DescriptorArray* d = DescriptorArray::cast(
*RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
if (d->IsEmpty()) return;
@@ -7437,24 +7385,22 @@ void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
// If the pair (value, details) is a map transition, check if the target is
// live. If not, null the descriptor. Also drop the back pointer for that
// map transition, so that this map is not reached again by following a back
- // pointer from a non-live object.
+ // pointer from that non-live map.
bool keep_entry = false;
PropertyDetails details(Smi::cast(contents->get(i + 1)));
switch (details.type()) {
case MAP_TRANSITION:
case CONSTANT_TRANSITION:
- RestoreOneBackPointer(contents->get(i), real_prototype, &keep_entry);
+ ClearBackPointer(heap, contents->get(i), &keep_entry);
break;
case ELEMENTS_TRANSITION: {
Object* object = contents->get(i);
if (object->IsMap()) {
- RestoreOneBackPointer(object, real_prototype, &keep_entry);
+ ClearBackPointer(heap, object, &keep_entry);
} else {
FixedArray* array = FixedArray::cast(object);
for (int j = 0; j < array->length(); ++j) {
- if (RestoreOneBackPointer(array->get(j),
- real_prototype,
- &keep_entry)) {
+ if (ClearBackPointer(heap, array->get(j), &keep_entry)) {
array->set_undefined(j);
}
}
@@ -7465,14 +7411,10 @@ void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
Object* object = contents->get(i);
if (object->IsAccessorPair()) {
AccessorPair* accessors = AccessorPair::cast(object);
- if (RestoreOneBackPointer(accessors->getter(),
- real_prototype,
- &keep_entry)) {
+ if (ClearBackPointer(heap, accessors->getter(), &keep_entry)) {
accessors->set_getter(heap->the_hole_value());
}
- if (RestoreOneBackPointer(accessors->setter(),
- real_prototype,
- &keep_entry)) {
+ if (ClearBackPointer(heap, accessors->setter(), &keep_entry)) {
accessors->set_setter(heap->the_hole_value());
}
} else {
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698