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