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

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: Incorporated review comments 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 bool Map::RestoreOneBackPointer(Object* object,
7288 Object* real_prototype,
7289 bool* keep_entry) {
7290 if (!object->IsMap()) return false;
7291 Map* map = Map::cast(object);
7292 if (Marking::MarkBitFrom(map).Get()) {
7293 *keep_entry = true;
7294 return false;
7295 }
7296 ASSERT(map->prototype() == this || map->prototype() == real_prototype);
7297 // Getter prototype() is read-only, set_prototype() has side effects.
7298 *RawField(map, Map::kPrototypeOffset) = real_prototype;
7299 return true;
7300 }
7301
7302
7267 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) { 7303 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
7268 // Live DescriptorArray objects will be marked, so we must use 7304 DescriptorArray* d = DescriptorArray::cast(
7269 // low-level accessors to get and modify their data.
7270 DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
7271 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset)); 7305 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
7272 if (d->IsEmpty()) return; 7306 if (d->IsEmpty()) return;
7273 Smi* NullDescriptorDetails = 7307 Smi* NullDescriptorDetails =
7274 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); 7308 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
7275 FixedArray* contents = reinterpret_cast<FixedArray*>( 7309 FixedArray* contents = FixedArray::cast(
7276 d->get(DescriptorArray::kContentArrayIndex)); 7310 d->get(DescriptorArray::kContentArrayIndex));
7277 ASSERT(contents->length() >= 2); 7311 ASSERT(contents->length() >= 2);
7278 for (int i = 0; i < contents->length(); i += 2) { 7312 for (int i = 0; i < contents->length(); i += 2) {
7279 // If the pair (value, details) is a map transition, 7313 // 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. 7314 // 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 7315 // 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 7316 // pointer from a non-live object.
7283 // non-live object. 7317 bool keep_entry = false;
7284 PropertyDetails details(Smi::cast(contents->get(i + 1))); 7318 PropertyDetails details(Smi::cast(contents->get(i + 1)));
7285 if (IsTransitionType(details.type())) { 7319 switch (details.type()) {
7286 Object* object = reinterpret_cast<Object*>(contents->get(i)); 7320 case MAP_TRANSITION:
7287 if (object->IsMap()) { 7321 case CONSTANT_TRANSITION:
7288 Map* target = reinterpret_cast<Map*>(object); 7322 RestoreOneBackPointer(contents->get(i), real_prototype, &keep_entry);
7289 ASSERT(target->IsHeapObject()); 7323 break;
7290 MarkBit map_mark = Marking::MarkBitFrom(target); 7324 case ELEMENTS_TRANSITION: {
7291 if (!map_mark.Get()) { 7325 Object* object = contents->get(i);
7292 ASSERT(target->IsMap()); 7326 if (object->IsMap()) {
7293 contents->set_unchecked(i + 1, NullDescriptorDetails); 7327 RestoreOneBackPointer(object, real_prototype, &keep_entry);
7294 contents->set_null_unchecked(heap, i); 7328 } else {
7295 ASSERT(target->prototype() == this || 7329 FixedArray* array = FixedArray::cast(object);
7296 target->prototype() == real_prototype); 7330 for (int j = 0; j < array->length(); ++j) {
7297 // Getter prototype() is read-only, set_prototype() has side effects. 7331 if (RestoreOneBackPointer(array->get(j),
7298 *RawField(target, Map::kPrototypeOffset) = real_prototype; 7332 real_prototype,
7299 } 7333 &keep_entry)) {
7300 } else { 7334 array->set_undefined(j);
7301 ASSERT(object->IsFixedArray()); 7335 }
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 ||
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 } 7336 }
7320 } 7337 }
7321 // If no map was found, make sure the FixedArray also gets collected. 7338 break;
7322 if (!reachable_map_found) { 7339 }
7323 contents->set_unchecked(i + 1, NullDescriptorDetails); 7340 case CALLBACKS: {
7324 contents->set_null_unchecked(heap, i); 7341 Object* object = contents->get(i);
7342 if (object->IsAccessorPair()) {
7343 AccessorPair* accessors = AccessorPair::cast(object);
7344 if (RestoreOneBackPointer(accessors->getter(),
7345 real_prototype,
7346 &keep_entry)) {
7347 accessors->set_getter(heap->the_hole_value());
7348 }
7349 if (RestoreOneBackPointer(accessors->setter(),
7350 real_prototype,
7351 &keep_entry)) {
7352 accessors->set_setter(heap->the_hole_value());
7353 }
7354 } else {
7355 keep_entry = true;
7325 } 7356 }
7357 break;
7326 } 7358 }
7359 case NORMAL:
7360 case FIELD:
7361 case CONSTANT_FUNCTION:
7362 case HANDLER:
7363 case INTERCEPTOR:
7364 case NULL_DESCRIPTOR:
7365 keep_entry = true;
7366 break;
7367 }
7368 // Make sure that an entry containing only dead transitions gets collected.
7369 // What we *really* want to do here is removing this entry completely, but
7370 // for technical reasons we can't do this, so we zero it out instead.
7371 if (!keep_entry) {
7372 contents->set_unchecked(i + 1, NullDescriptorDetails);
7373 contents->set_null_unchecked(heap, i);
7327 } 7374 }
7328 } 7375 }
7329 } 7376 }
7330 7377
7331 7378
7332 int Map::Hash() { 7379 int Map::Hash() {
7333 // For performance reasons we only hash the 3 most variable fields of a map: 7380 // For performance reasons we only hash the 3 most variable fields of a map:
7334 // constructor, prototype and bit_field2. 7381 // constructor, prototype and bit_field2.
7335 7382
7336 // Shift away the tag. 7383 // Shift away the tag.
(...skipping 5639 matching lines...) Expand 10 before | Expand all | Expand 10 after
12976 if (break_point_objects()->IsUndefined()) return 0; 13023 if (break_point_objects()->IsUndefined()) return 0;
12977 // Single break point. 13024 // Single break point.
12978 if (!break_point_objects()->IsFixedArray()) return 1; 13025 if (!break_point_objects()->IsFixedArray()) return 1;
12979 // Multiple break points. 13026 // Multiple break points.
12980 return FixedArray::cast(break_point_objects())->length(); 13027 return FixedArray::cast(break_point_objects())->length();
12981 } 13028 }
12982 #endif // ENABLE_DEBUGGER_SUPPORT 13029 #endif // ENABLE_DEBUGGER_SUPPORT
12983 13030
12984 13031
12985 } } // namespace v8::internal 13032 } } // 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