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 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 280 |
281 Handle<SeqTwoByteString> Factory::NewRawTwoByteString(int length, | 281 Handle<SeqTwoByteString> Factory::NewRawTwoByteString(int length, |
282 PretenureFlag pretenure) { | 282 PretenureFlag pretenure) { |
283 CALL_HEAP_FUNCTION( | 283 CALL_HEAP_FUNCTION( |
284 isolate(), | 284 isolate(), |
285 isolate()->heap()->AllocateRawTwoByteString(length, pretenure), | 285 isolate()->heap()->AllocateRawTwoByteString(length, pretenure), |
286 SeqTwoByteString); | 286 SeqTwoByteString); |
287 } | 287 } |
288 | 288 |
289 | 289 |
290 Handle<String> Factory::NewConsString(Handle<String> first, | 290 // Returns true for a character in a range. Both limits are inclusive. |
291 Handle<String> second) { | 291 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { |
292 CALL_HEAP_FUNCTION(isolate(), | 292 // This makes uses of the the unsigned wraparound. |
293 isolate()->heap()->AllocateConsString(*first, *second), | 293 return character - from <= to - from; |
294 String); | |
295 } | 294 } |
296 | 295 |
297 | 296 |
| 297 static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate, |
| 298 uint16_t c1, |
| 299 uint16_t c2) { |
| 300 // Numeric strings have a different hash algorithm not known by |
| 301 // LookupTwoCharsStringIfExists, so we skip this step for such strings. |
| 302 if (!Between(c1, '0', '9') || !Between(c2, '0', '9')) { |
| 303 String* result; |
| 304 StringTable* table = isolate->heap()->string_table(); |
| 305 if (table->LookupTwoCharsStringIfExists(c1, c2, &result)) { |
| 306 return handle(result); |
| 307 } |
| 308 } |
| 309 |
| 310 // Now we know the length is 2, we might as well make use of that fact |
| 311 // when building the new string. |
| 312 if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) { |
| 313 // We can do this. |
| 314 ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this. |
| 315 Handle<SeqOneByteString> str = isolate->factory()->NewRawOneByteString(2); |
| 316 uint8_t* dest = str->GetChars(); |
| 317 dest[0] = static_cast<uint8_t>(c1); |
| 318 dest[1] = static_cast<uint8_t>(c2); |
| 319 return str; |
| 320 } else { |
| 321 Handle<SeqTwoByteString> str = isolate->factory()->NewRawTwoByteString(2); |
| 322 uc16* dest = str->GetChars(); |
| 323 dest[0] = c1; |
| 324 dest[1] = c2; |
| 325 return str; |
| 326 } |
| 327 } |
| 328 |
| 329 |
298 template<typename SinkChar, typename StringType> | 330 template<typename SinkChar, typename StringType> |
299 Handle<String> ConcatStringContent(Handle<StringType> result, | 331 Handle<String> ConcatStringContent(Handle<StringType> result, |
300 Handle<String> first, | 332 Handle<String> first, |
301 Handle<String> second) { | 333 Handle<String> second) { |
302 DisallowHeapAllocation pointer_stays_valid; | 334 DisallowHeapAllocation pointer_stays_valid; |
303 SinkChar* sink = result->GetChars(); | 335 SinkChar* sink = result->GetChars(); |
304 String::WriteToFlat(*first, sink, 0, first->length()); | 336 String::WriteToFlat(*first, sink, 0, first->length()); |
305 String::WriteToFlat(*second, sink + first->length(), 0, second->length()); | 337 String::WriteToFlat(*second, sink + first->length(), 0, second->length()); |
306 return result; | 338 return result; |
307 } | 339 } |
308 | 340 |
309 | 341 |
| 342 Handle<ConsString> Factory::NewRawConsString(String::Encoding encoding) { |
| 343 Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING) |
| 344 ? cons_ascii_string_map() : cons_string_map(); |
| 345 CALL_HEAP_FUNCTION(isolate(), |
| 346 isolate()->heap()->Allocate(*map, NEW_SPACE), |
| 347 ConsString); |
| 348 } |
| 349 |
| 350 |
| 351 Handle<String> Factory::NewConsString(Handle<String> left, |
| 352 Handle<String> right) { |
| 353 int left_length = left->length(); |
| 354 if (left_length == 0) return right; |
| 355 int right_length = right->length(); |
| 356 if (right_length == 0) return left; |
| 357 |
| 358 int length = left_length + right_length; |
| 359 |
| 360 if (length == 2) { |
| 361 uint16_t c1 = left->Get(0); |
| 362 uint16_t c2 = right->Get(0); |
| 363 return MakeOrFindTwoCharacterString(isolate(), c1, c2); |
| 364 } |
| 365 |
| 366 // Make sure that an out of memory exception is thrown if the length |
| 367 // of the new cons string is too large. |
| 368 if (length > String::kMaxLength || length < 0) { |
| 369 isolate()->context()->mark_out_of_memory(); |
| 370 V8::FatalProcessOutOfMemory("String concatenation result too large."); |
| 371 UNREACHABLE(); |
| 372 return Handle<String>::null(); |
| 373 } |
| 374 |
| 375 bool left_is_one_byte = left->IsOneByteRepresentation(); |
| 376 bool right_is_one_byte = right->IsOneByteRepresentation(); |
| 377 bool is_one_byte = left_is_one_byte && right_is_one_byte; |
| 378 bool is_one_byte_data_in_two_byte_string = false; |
| 379 if (!is_one_byte) { |
| 380 // At least one of the strings uses two-byte representation so we |
| 381 // can't use the fast case code for short ASCII strings below, but |
| 382 // we can try to save memory if all chars actually fit in ASCII. |
| 383 is_one_byte_data_in_two_byte_string = |
| 384 left->HasOnlyOneByteChars() && right->HasOnlyOneByteChars(); |
| 385 if (is_one_byte_data_in_two_byte_string) { |
| 386 isolate()->counters()->string_add_runtime_ext_to_ascii()->Increment(); |
| 387 } |
| 388 } |
| 389 |
| 390 // If the resulting string is small make a flat string. |
| 391 if (length < ConsString::kMinLength) { |
| 392 // Note that neither of the two inputs can be a slice because: |
| 393 STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength); |
| 394 ASSERT(left->IsFlat()); |
| 395 ASSERT(right->IsFlat()); |
| 396 |
| 397 if (is_one_byte) { |
| 398 Handle<SeqOneByteString> result = NewRawOneByteString(length); |
| 399 DisallowHeapAllocation no_gc; |
| 400 uint8_t* dest = result->GetChars(); |
| 401 // Copy left part. |
| 402 const uint8_t* src = left->IsExternalString() |
| 403 ? Handle<ExternalAsciiString>::cast(left)->GetChars() |
| 404 : Handle<SeqOneByteString>::cast(left)->GetChars(); |
| 405 for (int i = 0; i < left_length; i++) *dest++ = src[i]; |
| 406 // Copy right part. |
| 407 src = right->IsExternalString() |
| 408 ? Handle<ExternalAsciiString>::cast(right)->GetChars() |
| 409 : Handle<SeqOneByteString>::cast(right)->GetChars(); |
| 410 for (int i = 0; i < right_length; i++) *dest++ = src[i]; |
| 411 return result; |
| 412 } |
| 413 |
| 414 return (is_one_byte_data_in_two_byte_string) |
| 415 ? ConcatStringContent<uint8_t>(NewRawOneByteString(length), left, right) |
| 416 : ConcatStringContent<uc16>(NewRawTwoByteString(length), left, right); |
| 417 } |
| 418 |
| 419 Handle<ConsString> result = NewRawConsString( |
| 420 (is_one_byte || is_one_byte_data_in_two_byte_string) |
| 421 ? String::ONE_BYTE_ENCODING |
| 422 : String::TWO_BYTE_ENCODING); |
| 423 |
| 424 DisallowHeapAllocation no_gc; |
| 425 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 426 |
| 427 result->set_hash_field(String::kEmptyHashField); |
| 428 result->set_length(length); |
| 429 result->set_first(*left, mode); |
| 430 result->set_second(*right, mode); |
| 431 return result; |
| 432 } |
| 433 |
| 434 |
310 Handle<String> Factory::NewFlatConcatString(Handle<String> first, | 435 Handle<String> Factory::NewFlatConcatString(Handle<String> first, |
311 Handle<String> second) { | 436 Handle<String> second) { |
312 int total_length = first->length() + second->length(); | 437 int total_length = first->length() + second->length(); |
313 if (first->IsOneByteRepresentation() && second->IsOneByteRepresentation()) { | 438 if (first->IsOneByteRepresentation() && second->IsOneByteRepresentation()) { |
314 return ConcatStringContent<uint8_t>( | 439 return ConcatStringContent<uint8_t>( |
315 NewRawOneByteString(total_length), first, second); | 440 NewRawOneByteString(total_length), first, second); |
316 } else { | 441 } else { |
317 return ConcatStringContent<uc16>( | 442 return ConcatStringContent<uc16>( |
318 NewRawTwoByteString(total_length), first, second); | 443 NewRawTwoByteString(total_length), first, second); |
319 } | 444 } |
320 } | 445 } |
321 | 446 |
322 | 447 |
323 Handle<String> Factory::NewSubString(Handle<String> str, | 448 Handle<SlicedString> Factory::NewRawSlicedString(String::Encoding encoding) { |
324 int begin, | 449 Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING) |
325 int end) { | 450 ? sliced_ascii_string_map() : sliced_string_map(); |
326 CALL_HEAP_FUNCTION(isolate(), | 451 CALL_HEAP_FUNCTION(isolate(), |
327 str->SubString(begin, end), | 452 isolate()->heap()->Allocate(*map, NEW_SPACE), |
328 String); | 453 SlicedString); |
329 } | 454 } |
330 | 455 |
331 | 456 |
332 Handle<String> Factory::NewProperSubString(Handle<String> str, | 457 Handle<String> Factory::NewProperSubString(Handle<String> str, |
333 int begin, | 458 int begin, |
334 int end) { | 459 int end) { |
| 460 #if VERIFY_HEAP |
| 461 if (FLAG_verify_heap) str->StringVerify(); |
| 462 #endif |
335 ASSERT(begin > 0 || end < str->length()); | 463 ASSERT(begin > 0 || end < str->length()); |
336 CALL_HEAP_FUNCTION(isolate(), | 464 |
337 isolate()->heap()->AllocateSubString(*str, begin, end), | 465 int length = end - begin; |
338 String); | 466 if (length <= 0) return empty_string(); |
| 467 if (length == 1) { |
| 468 return LookupSingleCharacterStringFromCode(isolate(), str->Get(begin)); |
| 469 } |
| 470 if (length == 2) { |
| 471 // Optimization for 2-byte strings often used as keys in a decompression |
| 472 // dictionary. Check whether we already have the string in the string |
| 473 // table to prevent creation of many unnecessary strings. |
| 474 uint16_t c1 = str->Get(begin); |
| 475 uint16_t c2 = str->Get(begin + 1); |
| 476 return MakeOrFindTwoCharacterString(isolate(), c1, c2); |
| 477 } |
| 478 |
| 479 if (!FLAG_string_slices || length < SlicedString::kMinLength) { |
| 480 if (str->IsOneByteRepresentation()) { |
| 481 Handle<SeqOneByteString> result = NewRawOneByteString(length); |
| 482 uint8_t* dest = result->GetChars(); |
| 483 DisallowHeapAllocation no_gc; |
| 484 String::WriteToFlat(*str, dest, begin, end); |
| 485 return result; |
| 486 } else { |
| 487 Handle<SeqTwoByteString> result = NewRawTwoByteString(length); |
| 488 uc16* dest = result->GetChars(); |
| 489 DisallowHeapAllocation no_gc; |
| 490 String::WriteToFlat(*str, dest, begin, end); |
| 491 return result; |
| 492 } |
| 493 } |
| 494 |
| 495 int offset = begin; |
| 496 |
| 497 while (str->IsConsString()) { |
| 498 Handle<ConsString> cons = Handle<ConsString>::cast(str); |
| 499 int split = cons->first()->length(); |
| 500 if (split <= offset) { |
| 501 // Slice is fully contained in the second part. |
| 502 str = Handle<String>(cons->second(), isolate()); |
| 503 offset -= split; // Adjust for offset. |
| 504 continue; |
| 505 } else if (offset + length <= split) { |
| 506 // Slice is fully contained in the first part. |
| 507 str = Handle<String>(cons->first(), isolate()); |
| 508 continue; |
| 509 } |
| 510 break; |
| 511 } |
| 512 |
| 513 if (str->IsSlicedString()) { |
| 514 Handle<SlicedString> slice = Handle<SlicedString>::cast(str); |
| 515 str = Handle<String>(slice->parent(), isolate()); |
| 516 offset += slice->offset(); |
| 517 } else { |
| 518 str = FlattenGetString(str); |
| 519 } |
| 520 |
| 521 ASSERT(str->IsSeqString() || str->IsExternalString()); |
| 522 Handle<SlicedString> slice = NewRawSlicedString( |
| 523 str->IsOneByteRepresentation() ? String::ONE_BYTE_ENCODING |
| 524 : String::TWO_BYTE_ENCODING); |
| 525 |
| 526 slice->set_hash_field(String::kEmptyHashField); |
| 527 slice->set_length(length); |
| 528 slice->set_parent(*str); |
| 529 slice->set_offset(offset); |
| 530 return slice; |
339 } | 531 } |
340 | 532 |
341 | 533 |
342 Handle<String> Factory::NewExternalStringFromAscii( | 534 Handle<String> Factory::NewExternalStringFromAscii( |
343 const ExternalAsciiString::Resource* resource) { | 535 const ExternalAsciiString::Resource* resource) { |
344 CALL_HEAP_FUNCTION( | 536 CALL_HEAP_FUNCTION( |
345 isolate(), | 537 isolate(), |
346 isolate()->heap()->AllocateExternalStringFromAscii(resource), | 538 isolate()->heap()->AllocateExternalStringFromAscii(resource), |
347 String); | 539 String); |
348 } | 540 } |
(...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 return Handle<Object>::null(); | 1989 return Handle<Object>::null(); |
1798 } | 1990 } |
1799 | 1991 |
1800 | 1992 |
1801 Handle<Object> Factory::ToBoolean(bool value) { | 1993 Handle<Object> Factory::ToBoolean(bool value) { |
1802 return value ? true_value() : false_value(); | 1994 return value ? true_value() : false_value(); |
1803 } | 1995 } |
1804 | 1996 |
1805 | 1997 |
1806 } } // namespace v8::internal | 1998 } } // namespace v8::internal |
OLD | NEW |