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

Side by Side Diff: src/objects.cc

Issue 9225056: Handle CALLBACKS with map transitions when doing GC in the map tree. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 10 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 7204 matching lines...) Expand 10 before | Expand all | Expand 10 after
7215 7215
7216 7216
7217 void String::PrintOn(FILE* file) { 7217 void String::PrintOn(FILE* file) {
7218 int length = this->length(); 7218 int length = this->length();
7219 for (int i = 0; i < length; i++) { 7219 for (int i = 0; i < length; i++) {
7220 fprintf(file, "%c", Get(i)); 7220 fprintf(file, "%c", Get(i));
7221 } 7221 }
7222 } 7222 }
7223 7223
7224 7224
7225 void Map::CreateOneBackPointer(Map* target) { 7225 void Map::CreateOneBackPointer(Object* transition_target) {
7226 if (!transition_target->IsMap()) return;
7227 Map* target = Map::cast(transition_target);
7226 #ifdef DEBUG 7228 #ifdef DEBUG
7227 // Verify target. 7229 // Verify target.
7228 Object* source_prototype = prototype(); 7230 Object* source_prototype = prototype();
7229 Object* target_prototype = target->prototype(); 7231 Object* target_prototype = target->prototype();
7230 ASSERT(source_prototype->IsJSReceiver() || 7232 ASSERT(source_prototype->IsJSReceiver() ||
7231 source_prototype->IsMap() || 7233 source_prototype->IsMap() ||
7232 source_prototype->IsNull()); 7234 source_prototype->IsNull());
7233 ASSERT(target_prototype->IsJSReceiver() || 7235 ASSERT(target_prototype->IsJSReceiver() ||
7234 target_prototype->IsNull()); 7236 target_prototype->IsNull());
7235 ASSERT(source_prototype->IsMap() || 7237 ASSERT(source_prototype->IsMap() ||
7236 source_prototype == target_prototype); 7238 source_prototype == target_prototype);
7237 #endif 7239 #endif
7238 // Point target back to source. set_prototype() will not let us set 7240 // Point target back to source. set_prototype() will not let us set
7239 // the prototype to a map, as we do here. 7241 // the prototype to a map, as we do here.
7240 *RawField(target, kPrototypeOffset) = this; 7242 *RawField(target, kPrototypeOffset) = this;
7241 } 7243 }
7242 7244
7243 7245
7244 void Map::CreateBackPointers() { 7246 void Map::CreateBackPointers() {
7245 DescriptorArray* descriptors = instance_descriptors(); 7247 DescriptorArray* descriptors = instance_descriptors();
7246 for (int i = 0; i < descriptors->number_of_descriptors(); i++) { 7248 for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
7247 if (descriptors->IsTransition(i)) { 7249 switch (descriptors->GetType(i)) {
7248 Object* object = reinterpret_cast<Object*>(descriptors->GetValue(i)); 7250 case MAP_TRANSITION:
7249 if (object->IsMap()) { 7251 case CONSTANT_TRANSITION:
7250 CreateOneBackPointer(reinterpret_cast<Map*>(object)); 7252 CreateOneBackPointer(descriptors->GetValue(i));
7251 } else { 7253 break;
7252 ASSERT(object->IsFixedArray()); 7254 case ELEMENTS_TRANSITION: {
7253 ASSERT(descriptors->GetType(i) == ELEMENTS_TRANSITION); 7255 Object* object = descriptors->GetValue(i);
7254 FixedArray* array = reinterpret_cast<FixedArray*>(object); 7256 if (object->IsMap()) {
7255 for (int i = 0; i < array->length(); ++i) { 7257 CreateOneBackPointer(object);
7256 Map* target = reinterpret_cast<Map*>(array->get(i)); 7258 } else {
7257 if (!target->IsUndefined()) { 7259 FixedArray* array = FixedArray::cast(object);
7258 CreateOneBackPointer(target); 7260 for (int i = 0; i < array->length(); ++i) {
7261 CreateOneBackPointer(array->get(i));
7259 } 7262 }
7260 } 7263 }
7264 break;
7261 } 7265 }
7266 case CALLBACKS: {
7267 Object* object = descriptors->GetValue(i);
7268 if (object->IsAccessorPair()) {
7269 AccessorPair* accessors = AccessorPair::cast(object);
7270 CreateOneBackPointer(accessors->getter());
7271 CreateOneBackPointer(accessors->setter());
7272 }
7273 break;
7274 }
7275 case NORMAL:
7276 case FIELD:
7277 case CONSTANT_FUNCTION:
7278 case HANDLER:
7279 case INTERCEPTOR:
7280 case NULL_DESCRIPTOR:
7281 break;
7262 } 7282 }
7263 } 7283 }
7264 } 7284 }
7265 7285
7266 7286
7287 static bool RestoreProto(Object* object,
Michael Starzinger 2012/01/30 12:57:56 I would prefer "RestorePrototype" as a name. Also
Sven Panne 2012/01/30 13:34:39 Done.
7288 Object* real_prototype,
7289 bool* keep_entry) {
7290 if (!object->IsMap()) return false;
7291 Map* map = static_cast<Map*>(object);
Michael Starzinger 2012/01/30 12:57:56 If object->IsMap() is usable at this point, then M
Sven Panne 2012/01/30 13:34:39 Done.
7292 if (Marking::MarkBitFrom(map).Get()) {
7293 *keep_entry = true;
7294 return false;
7295 }
7296 // Getter prototype() is read-only, set_prototype() has side effects.
7297 *HeapObject::RawField(map, Map::kPrototypeOffset) = real_prototype;
7298 return true;
7299 }
7300
7301
7267 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) { 7302 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
7268 // Live DescriptorArray objects will be marked, so we must use 7303 // Live DescriptorArray objects will be marked, so we must use low-level
Michael Starzinger 2012/01/30 12:57:56 The comment is no longer accurate.
Sven Panne 2012/01/30 13:34:39 Done.
7269 // low-level accessors to get and modify their data. 7304 // accessors to get and modify their data.
7270 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( 7305 DescriptorArray* d = static_cast<DescriptorArray*>(
Michael Starzinger 2012/01/30 12:57:56 I think we can use our internal casts here. Could
Sven Panne 2012/01/30 13:34:39 Done.
7271 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset)); 7306 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
7272 if (d->IsEmpty()) return; 7307 if (d->IsEmpty()) return;
7273 Smi* NullDescriptorDetails = 7308 Smi* NullDescriptorDetails =
7274 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); 7309 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
7275 FixedArray* contents = reinterpret_cast<FixedArray*>( 7310 FixedArray* contents = static_cast<FixedArray*>(
Michael Starzinger 2012/01/30 12:57:56 Likewise.
Sven Panne 2012/01/30 13:34:39 Done.
7276 d->get(DescriptorArray::kContentArrayIndex)); 7311 d->get(DescriptorArray::kContentArrayIndex));
7277 ASSERT(contents->length() >= 2); 7312 ASSERT(contents->length() >= 2);
7278 for (int i = 0; i < contents->length(); i += 2) { 7313 for (int i = 0; i < contents->length(); i += 2) {
7279 // If the pair (value, details) is a map transition, 7314 // If the pair (value, details) is a map transition, check if the target is
7280 // check if the target is live. If not, null the descriptor. 7315 // live. If not, null the descriptor. Also drop the back pointer for that
7281 // Also drop the back pointer for that map transition, so that this 7316 // map transition, so that this map is not reached again by following a back
7282 // map is not reached again by following a back pointer from a 7317 // pointer from a non-live object.
7283 // non-live object. 7318 bool keep_entry = false;
7284 PropertyDetails details(Smi::cast(contents->get(i + 1))); 7319 PropertyDetails details(Smi::cast(contents->get(i + 1)));
7285 if (IsTransitionType(details.type())) { 7320 switch (details.type()) {
7286 Object* object = reinterpret_cast<Object*>(contents->get(i)); 7321 case MAP_TRANSITION:
7287 if (object->IsMap()) { 7322 case CONSTANT_TRANSITION:
7288 Map* target = reinterpret_cast<Map*>(object); 7323 RestoreProto(contents->get(i), real_prototype, &keep_entry);
7289 ASSERT(target->IsHeapObject()); 7324 break;
7290 MarkBit map_mark = Marking::MarkBitFrom(target); 7325 case ELEMENTS_TRANSITION: {
7291 if (!map_mark.Get()) { 7326 Object* object = contents->get(i);
7292 ASSERT(target->IsMap()); 7327 if (object->IsMap()) {
7293 contents->set_unchecked(i + 1, NullDescriptorDetails); 7328 RestoreProto(object, real_prototype, &keep_entry);
7294 contents->set_null_unchecked(heap, i); 7329 } else {
7295 ASSERT(target->prototype() == this || 7330 FixedArray* array = FixedArray::cast(object);
Michael Starzinger 2012/01/30 12:57:56 Can we keep this assertion around? If we turn Rest
Sven Panne 2012/01/30 13:34:39 Done.
7296 target->prototype() == real_prototype); 7331 for (int j = 0; j < array->length(); ++j) {
7297 // Getter prototype() is read-only, set_prototype() has side effects. 7332 if (RestoreProto(array->get(j), real_prototype, &keep_entry)) {
7298 *RawField(target, Map::kPrototypeOffset) = real_prototype; 7333 array->set_undefined(j);
7299 } 7334 }
7300 } else {
7301 ASSERT(object->IsFixedArray());
7302 ASSERT(details.type() == ELEMENTS_TRANSITION);
7303 FixedArray* array = reinterpret_cast<FixedArray*>(object);
7304 bool reachable_map_found = false;
7305 for (int j = 0; j < array->length(); ++j) {
7306 Map* target = reinterpret_cast<Map*>(array->get(j));
7307 ASSERT(target->IsHeapObject());
7308 MarkBit map_mark = Marking::MarkBitFrom(target);
7309 if (!map_mark.Get()) {
7310 ASSERT(target->IsMap());
7311 array->set_undefined(j);
7312 ASSERT(target->prototype() == this ||
Michael Starzinger 2012/01/30 12:57:56 Likewise.
Sven Panne 2012/01/30 13:34:39 Done.
7313 target->prototype() == real_prototype);
7314 // Getter prototype() is read-only, set_prototype() has side
7315 // effects.
7316 *RawField(target, Map::kPrototypeOffset) = real_prototype;
7317 } else if (target->IsMap()) {
7318 reachable_map_found = true;
7319 } 7335 }
7320 } 7336 }
7321 // If no map was found, make sure the FixedArray also gets collected. 7337 break;
Michael Starzinger 2012/01/30 12:57:56 Can we keep this comment (and place it above line
Sven Panne 2012/01/30 13:34:39 Done.
7322 if (!reachable_map_found) { 7338 }
7323 contents->set_unchecked(i + 1, NullDescriptorDetails); 7339 case CALLBACKS: {
7324 contents->set_null_unchecked(heap, i); 7340 Object* object = contents->get(i);
7341 if (object->IsAccessorPair()) {
7342 AccessorPair* accessors = AccessorPair::cast(object);
7343 if (RestoreProto(accessors->getter(), real_prototype, &keep_entry)) {
7344 accessors->set_getter(heap->the_hole_value());
7345 }
7346 if (RestoreProto(accessors->setter(), real_prototype, &keep_entry)) {
7347 accessors->set_setter(heap->the_hole_value());
7348 }
7349 } else {
7350 keep_entry = true;
7325 } 7351 }
7352 break;
7326 } 7353 }
7354 case NORMAL:
7355 case FIELD:
7356 case CONSTANT_FUNCTION:
7357 case HANDLER:
7358 case INTERCEPTOR:
7359 case NULL_DESCRIPTOR:
7360 keep_entry = true;
7361 break;
7362 }
7363 if (!keep_entry) {
7364 contents->set_unchecked(i + 1, NullDescriptorDetails);
7365 contents->set_null_unchecked(heap, i);
7327 } 7366 }
7328 } 7367 }
7329 } 7368 }
7330 7369
7331 7370
7332 int Map::Hash() { 7371 int Map::Hash() {
7333 // For performance reasons we only hash the 3 most variable fields of a map: 7372 // For performance reasons we only hash the 3 most variable fields of a map:
7334 // constructor, prototype and bit_field2. 7373 // constructor, prototype and bit_field2.
7335 7374
7336 // Shift away the tag. 7375 // Shift away the tag.
(...skipping 5639 matching lines...) Expand 10 before | Expand all | Expand 10 after
12976 if (break_point_objects()->IsUndefined()) return 0; 13015 if (break_point_objects()->IsUndefined()) return 0;
12977 // Single break point. 13016 // Single break point.
12978 if (!break_point_objects()->IsFixedArray()) return 1; 13017 if (!break_point_objects()->IsFixedArray()) return 1;
12979 // Multiple break points. 13018 // Multiple break points.
12980 return FixedArray::cast(break_point_objects())->length(); 13019 return FixedArray::cast(break_point_objects())->length();
12981 } 13020 }
12982 #endif // ENABLE_DEBUGGER_SUPPORT 13021 #endif // ENABLE_DEBUGGER_SUPPORT
12983 13022
12984 13023
12985 } } // namespace v8::internal 13024 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698