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

Side by Side Diff: src/objects.cc

Issue 219103002: Make sure when we shrink an object that we store a filler first into the free memory before updatin… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 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') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 1262 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 // Morph the string to an external string by replacing the map and 1273 // Morph the string to an external string by replacing the map and
1274 // reinitializing the fields. This won't work if 1274 // reinitializing the fields. This won't work if
1275 // - the space the existing string occupies is too small for a regular 1275 // - the space the existing string occupies is too small for a regular
1276 // external string. 1276 // external string.
1277 // - the existing string is in old pointer space and the backing store of 1277 // - the existing string is in old pointer space and the backing store of
1278 // the external string is not aligned. The GC cannot deal with a field 1278 // the external string is not aligned. The GC cannot deal with a field
1279 // containing a possibly unaligned address to outside of V8's heap. 1279 // containing a possibly unaligned address to outside of V8's heap.
1280 // In either case we resort to a short external string instead, omitting 1280 // In either case we resort to a short external string instead, omitting
1281 // the field caching the address of the backing store. When we encounter 1281 // the field caching the address of the backing store. When we encounter
1282 // short external strings in generated code, we need to bailout to runtime. 1282 // short external strings in generated code, we need to bailout to runtime.
1283 Map* new_map;
1283 if (size < ExternalString::kSize || 1284 if (size < ExternalString::kSize ||
1284 heap->old_pointer_space()->Contains(this)) { 1285 heap->old_pointer_space()->Contains(this)) {
1285 this->set_map_no_write_barrier( 1286 new_map = is_internalized
1286 is_internalized 1287 ? (is_ascii
1287 ? (is_ascii 1288 ? heap->
1288 ? heap-> 1289 short_external_internalized_string_with_one_byte_data_map()
1289 short_external_internalized_string_with_one_byte_data_map() 1290 : heap->short_external_internalized_string_map())
1290 : heap->short_external_internalized_string_map()) 1291 : (is_ascii
1291 : (is_ascii 1292 ? heap->short_external_string_with_one_byte_data_map()
1292 ? heap->short_external_string_with_one_byte_data_map() 1293 : heap->short_external_string_map());
1293 : heap->short_external_string_map()));
1294 } else { 1294 } else {
1295 this->set_map_no_write_barrier( 1295 new_map = is_internalized
1296 is_internalized 1296 ? (is_ascii
1297 ? (is_ascii 1297 ? heap->external_internalized_string_with_one_byte_data_map()
1298 ? heap->external_internalized_string_with_one_byte_data_map() 1298 : heap->external_internalized_string_map())
1299 : heap->external_internalized_string_map()) 1299 : (is_ascii
1300 : (is_ascii 1300 ? heap->external_string_with_one_byte_data_map()
1301 ? heap->external_string_with_one_byte_data_map() 1301 : heap->external_string_map());
1302 : heap->external_string_map()));
1303 } 1302 }
1303
1304 // Byte size of the external String object.
1305 int new_size = this->SizeFromMap(new_map);
1306 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1307
1308 // We are storing the new map using release store after creating a filler for
1309 // the left-over space to avoid races with the sweeper thread.
1310 this->synchronized_set_map(new_map);
1311
1304 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); 1312 ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1305 self->set_resource(resource); 1313 self->set_resource(resource);
1306 if (is_internalized) self->Hash(); // Force regeneration of the hash value. 1314 if (is_internalized) self->Hash(); // Force regeneration of the hash value.
1307 1315
1308 // Fill the remainder of the string with dead wood.
1309 int new_size = this->Size(); // Byte size of the external String object.
1310 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1311 heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR); 1316 heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1312 return true; 1317 return true;
1313 } 1318 }
1314 1319
1315 1320
1316 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { 1321 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
1317 #ifdef ENABLE_SLOW_ASSERTS 1322 #ifdef ENABLE_SLOW_ASSERTS
1318 if (FLAG_enable_slow_asserts) { 1323 if (FLAG_enable_slow_asserts) {
1319 // Assert that the resource and the string are equivalent. 1324 // Assert that the resource and the string are equivalent.
1320 ASSERT(static_cast<size_t>(this->length()) == resource->length()); 1325 ASSERT(static_cast<size_t>(this->length()) == resource->length());
(...skipping 19 matching lines...) Expand all
1340 // Morph the string to an external string by replacing the map and 1345 // Morph the string to an external string by replacing the map and
1341 // reinitializing the fields. This won't work if 1346 // reinitializing the fields. This won't work if
1342 // - the space the existing string occupies is too small for a regular 1347 // - the space the existing string occupies is too small for a regular
1343 // external string. 1348 // external string.
1344 // - the existing string is in old pointer space and the backing store of 1349 // - the existing string is in old pointer space and the backing store of
1345 // the external string is not aligned. The GC cannot deal with a field 1350 // the external string is not aligned. The GC cannot deal with a field
1346 // containing a possibly unaligned address to outside of V8's heap. 1351 // containing a possibly unaligned address to outside of V8's heap.
1347 // In either case we resort to a short external string instead, omitting 1352 // In either case we resort to a short external string instead, omitting
1348 // the field caching the address of the backing store. When we encounter 1353 // the field caching the address of the backing store. When we encounter
1349 // short external strings in generated code, we need to bailout to runtime. 1354 // short external strings in generated code, we need to bailout to runtime.
1355 Map* new_map;
1350 if (size < ExternalString::kSize || 1356 if (size < ExternalString::kSize ||
1351 heap->old_pointer_space()->Contains(this)) { 1357 heap->old_pointer_space()->Contains(this)) {
1352 this->set_map_no_write_barrier( 1358 new_map = is_internalized
1353 is_internalized ? heap->short_external_ascii_internalized_string_map() 1359 ? heap->short_external_ascii_internalized_string_map()
1354 : heap->short_external_ascii_string_map()); 1360 : heap->short_external_ascii_string_map();
1355 } else { 1361 } else {
1356 this->set_map_no_write_barrier( 1362 new_map = is_internalized
1357 is_internalized ? heap->external_ascii_internalized_string_map() 1363 ? heap->external_ascii_internalized_string_map()
1358 : heap->external_ascii_string_map()); 1364 : heap->external_ascii_string_map();
1359 } 1365 }
1366
1367 // Byte size of the external String object.
1368 int new_size = this->SizeFromMap(new_map);
1369 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1370
1371 // We are storing the new map using release store after creating a filler for
1372 // the left-over space to avoid races with the sweeper thread.
1373 this->synchronized_set_map(new_map);
1374
1360 ExternalAsciiString* self = ExternalAsciiString::cast(this); 1375 ExternalAsciiString* self = ExternalAsciiString::cast(this);
1361 self->set_resource(resource); 1376 self->set_resource(resource);
1362 if (is_internalized) self->Hash(); // Force regeneration of the hash value. 1377 if (is_internalized) self->Hash(); // Force regeneration of the hash value.
1363 1378
1364 // Fill the remainder of the string with dead wood.
1365 int new_size = this->Size(); // Byte size of the external String object.
1366 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1367 heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR); 1379 heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1368 return true; 1380 return true;
1369 } 1381 }
1370 1382
1371 1383
1372 void String::StringShortPrint(StringStream* accumulator) { 1384 void String::StringShortPrint(StringStream* accumulator) {
1373 int len = length(); 1385 int len = length();
1374 if (len > kMaxShortPrintLength) { 1386 if (len > kMaxShortPrintLength) {
1375 accumulator->Add("<Very long string[%u]>", len); 1387 accumulator->Add("<Very long string[%u]>", len);
1376 return; 1388 return;
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
2290 ZapEndOfFixedArray(new_end, to_trim); 2302 ZapEndOfFixedArray(new_end, to_trim);
2291 } 2303 }
2292 2304
2293 int size_delta = to_trim * kPointerSize; 2305 int size_delta = to_trim * kPointerSize;
2294 2306
2295 // Technically in new space this write might be omitted (except for 2307 // Technically in new space this write might be omitted (except for
2296 // debug mode which iterates through the heap), but to play safer 2308 // debug mode which iterates through the heap), but to play safer
2297 // we still do it. 2309 // we still do it.
2298 heap->CreateFillerObjectAt(new_end, size_delta); 2310 heap->CreateFillerObjectAt(new_end, size_delta);
2299 2311
2300 elms->set_length(len - to_trim); 2312 // We are storing the new length using release store after creating a filler
2313 // for the left-over space to avoid races with the sweeper thread.
2314 elms->synchronized_set_length(len - to_trim);
2301 2315
2302 heap->AdjustLiveBytes(elms->address(), -size_delta, mode); 2316 heap->AdjustLiveBytes(elms->address(), -size_delta, mode);
2303 2317
2304 // The array may not be moved during GC, 2318 // The array may not be moved during GC,
2305 // and size has to be adjusted nevertheless. 2319 // and size has to be adjusted nevertheless.
2306 HeapProfiler* profiler = heap->isolate()->heap_profiler(); 2320 HeapProfiler* profiler = heap->isolate()->heap_profiler();
2307 if (profiler->is_tracking_allocations()) { 2321 if (profiler->is_tracking_allocations()) {
2308 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); 2322 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size());
2309 } 2323 }
2310 } 2324 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2365 Isolate* isolate = object->GetIsolate(); 2379 Isolate* isolate = object->GetIsolate();
2366 Handle<Map> old_map(object->map()); 2380 Handle<Map> old_map(object->map());
2367 int number_of_fields = new_map->NumberOfFields(); 2381 int number_of_fields = new_map->NumberOfFields();
2368 int inobject = new_map->inobject_properties(); 2382 int inobject = new_map->inobject_properties();
2369 int unused = new_map->unused_property_fields(); 2383 int unused = new_map->unused_property_fields();
2370 2384
2371 // Nothing to do if no functions were converted to fields and no smis were 2385 // Nothing to do if no functions were converted to fields and no smis were
2372 // converted to doubles. 2386 // converted to doubles.
2373 if (!old_map->InstancesNeedRewriting( 2387 if (!old_map->InstancesNeedRewriting(
2374 *new_map, number_of_fields, inobject, unused)) { 2388 *new_map, number_of_fields, inobject, unused)) {
2375 object->set_map(*new_map); 2389 // Writing the new map here does not require synchronization since it does
2390 // not change the actual object size.
2391 object->synchronized_set_map(*new_map);
2376 return; 2392 return;
2377 } 2393 }
2378 2394
2379 int total_size = number_of_fields + unused; 2395 int total_size = number_of_fields + unused;
2380 int external = total_size - inobject; 2396 int external = total_size - inobject;
2381 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); 2397 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2382 2398
2383 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); 2399 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2384 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); 2400 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2385 int old_nof = old_map->NumberOfOwnDescriptors(); 2401 int old_nof = old_map->NumberOfOwnDescriptors();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2435 int limit = Min(inobject, number_of_fields); 2451 int limit = Min(inobject, number_of_fields);
2436 for (int i = 0; i < limit; i++) { 2452 for (int i = 0; i < limit; i++) {
2437 object->FastPropertyAtPut(i, array->get(external + i)); 2453 object->FastPropertyAtPut(i, array->get(external + i));
2438 } 2454 }
2439 2455
2440 // Create filler object past the new instance size. 2456 // Create filler object past the new instance size.
2441 int new_instance_size = new_map->instance_size(); 2457 int new_instance_size = new_map->instance_size();
2442 int instance_size_delta = old_map->instance_size() - new_instance_size; 2458 int instance_size_delta = old_map->instance_size() - new_instance_size;
2443 ASSERT(instance_size_delta >= 0); 2459 ASSERT(instance_size_delta >= 0);
2444 Address address = object->address() + new_instance_size; 2460 Address address = object->address() + new_instance_size;
2461
2462 // The trimming is performed on a newly allocated object, which is on a
2463 // fresly allocated page or on an already swept page. Hence, the sweeper
2464 // thread can not get confused with the filler creation. No synchronization
2465 // needed.
2445 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta); 2466 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
2446 2467
2447 // If there are properties in the new backing store, trim it to the correct 2468 // If there are properties in the new backing store, trim it to the correct
2448 // size and install the backing store into the object. 2469 // size and install the backing store into the object.
2449 if (external > 0) { 2470 if (external > 0) {
2450 RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject); 2471 RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject);
2451 object->set_properties(*array); 2472 object->set_properties(*array);
2452 } 2473 }
2453 2474
2475 // The trimming is performed on a newly allocated object, which is on a
2476 // fresly allocated page or on an already swept page. Hence, the sweeper
2477 // thread can not get confused with the filler creation. No synchronization
2478 // needed.
2454 object->set_map(*new_map); 2479 object->set_map(*new_map);
2455 } 2480 }
2456 2481
2457 2482
2458 Handle<TransitionArray> Map::AddTransition(Handle<Map> map, 2483 Handle<TransitionArray> Map::AddTransition(Handle<Map> map,
2459 Handle<Name> key, 2484 Handle<Name> key,
2460 Handle<Map> target, 2485 Handle<Map> target,
2461 SimpleTransitionFlag flag) { 2486 SimpleTransitionFlag flag) {
2462 CALL_HEAP_FUNCTION(map->GetIsolate(), 2487 CALL_HEAP_FUNCTION(map->GetIsolate(),
2463 map->AddTransition(*key, *target, flag), 2488 map->AddTransition(*key, *target, flag),
(...skipping 2171 matching lines...) Expand 10 before | Expand all | Expand 10 after
4635 int new_instance_size = new_map->instance_size(); 4660 int new_instance_size = new_map->instance_size();
4636 int instance_size_delta = map->instance_size() - new_instance_size; 4661 int instance_size_delta = map->instance_size() - new_instance_size;
4637 ASSERT(instance_size_delta >= 0); 4662 ASSERT(instance_size_delta >= 0);
4638 Heap* heap = isolate->heap(); 4663 Heap* heap = isolate->heap();
4639 heap->CreateFillerObjectAt(object->address() + new_instance_size, 4664 heap->CreateFillerObjectAt(object->address() + new_instance_size,
4640 instance_size_delta); 4665 instance_size_delta);
4641 heap->AdjustLiveBytes(object->address(), 4666 heap->AdjustLiveBytes(object->address(),
4642 -instance_size_delta, 4667 -instance_size_delta,
4643 Heap::FROM_MUTATOR); 4668 Heap::FROM_MUTATOR);
4644 4669
4645 object->set_map(*new_map); 4670 // We are storing the new map using release store after creating a filler for
4671 // the left-over space to avoid races with the sweeper thread.
4672 object->synchronized_set_map(*new_map);
4673
4646 map->NotifyLeafMapLayoutChange(); 4674 map->NotifyLeafMapLayoutChange();
4647 4675
4648 object->set_properties(*dictionary); 4676 object->set_properties(*dictionary);
4649 4677
4650 isolate->counters()->props_to_dictionary()->Increment(); 4678 isolate->counters()->props_to_dictionary()->Increment();
4651 4679
4652 #ifdef DEBUG 4680 #ifdef DEBUG
4653 if (FLAG_trace_normalization) { 4681 if (FLAG_trace_normalization) {
4654 PrintF("Object properties have been normalized:\n"); 4682 PrintF("Object properties have been normalized:\n");
4655 object->Print(); 4683 object->Print();
(...skipping 4488 matching lines...) Expand 10 before | Expand all | Expand 10 after
9144 if (string->IsSeqOneByteString()) { 9172 if (string->IsSeqOneByteString()) {
9145 old_size = SeqOneByteString::SizeFor(old_length); 9173 old_size = SeqOneByteString::SizeFor(old_length);
9146 new_size = SeqOneByteString::SizeFor(new_length); 9174 new_size = SeqOneByteString::SizeFor(new_length);
9147 } else { 9175 } else {
9148 ASSERT(string->IsSeqTwoByteString()); 9176 ASSERT(string->IsSeqTwoByteString());
9149 old_size = SeqTwoByteString::SizeFor(old_length); 9177 old_size = SeqTwoByteString::SizeFor(old_length);
9150 new_size = SeqTwoByteString::SizeFor(new_length); 9178 new_size = SeqTwoByteString::SizeFor(new_length);
9151 } 9179 }
9152 9180
9153 int delta = old_size - new_size; 9181 int delta = old_size - new_size;
9154 string->set_length(new_length);
9155 9182
9156 Address start_of_string = string->address(); 9183 Address start_of_string = string->address();
9157 ASSERT_OBJECT_ALIGNED(start_of_string); 9184 ASSERT_OBJECT_ALIGNED(start_of_string);
9158 ASSERT_OBJECT_ALIGNED(start_of_string + new_size); 9185 ASSERT_OBJECT_ALIGNED(start_of_string + new_size);
9159 9186
9160 Heap* heap = string->GetHeap(); 9187 Heap* heap = string->GetHeap();
9161 NewSpace* newspace = heap->new_space(); 9188 NewSpace* newspace = heap->new_space();
9162 if (newspace->Contains(start_of_string) && 9189 if (newspace->Contains(start_of_string) &&
9163 newspace->top() == start_of_string + old_size) { 9190 newspace->top() == start_of_string + old_size) {
9164 // Last allocated object in new space. Simply lower allocation top. 9191 // Last allocated object in new space. Simply lower allocation top.
9165 newspace->set_top(start_of_string + new_size); 9192 newspace->set_top(start_of_string + new_size);
9166 } else { 9193 } else {
9167 // Sizes are pointer size aligned, so that we can use filler objects 9194 // Sizes are pointer size aligned, so that we can use filler objects
9168 // that are a multiple of pointer size. 9195 // that are a multiple of pointer size.
9169 heap->CreateFillerObjectAt(start_of_string + new_size, delta); 9196 heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9170 } 9197 }
9171 heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR); 9198 heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
9172 9199
9200 // We are storing the new length using release store after creating a filler
9201 // for the left-over space to avoid races with the sweeper thread.
9202 string->synchronized_set_length(new_length);
9203
9173 if (new_length == 0) return heap->isolate()->factory()->empty_string(); 9204 if (new_length == 0) return heap->isolate()->factory()->empty_string();
9174 return string; 9205 return string;
9175 } 9206 }
9176 9207
9177 9208
9178 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { 9209 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9179 // For array indexes mix the length into the hash as an array index could 9210 // For array indexes mix the length into the hash as an array index could
9180 // be zero. 9211 // be zero.
9181 ASSERT(length > 0); 9212 ASSERT(length > 0);
9182 ASSERT(length <= String::kMaxArrayIndexSize); 9213 ASSERT(length <= String::kMaxArrayIndexSize);
(...skipping 7180 matching lines...) Expand 10 before | Expand all | Expand 10 after
16363 #define ERROR_MESSAGES_TEXTS(C, T) T, 16394 #define ERROR_MESSAGES_TEXTS(C, T) T,
16364 static const char* error_messages_[] = { 16395 static const char* error_messages_[] = {
16365 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16396 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16366 }; 16397 };
16367 #undef ERROR_MESSAGES_TEXTS 16398 #undef ERROR_MESSAGES_TEXTS
16368 return error_messages_[reason]; 16399 return error_messages_[reason];
16369 } 16400 }
16370 16401
16371 16402
16372 } } // namespace v8::internal 16403 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698