OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |