| 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 // Returns true for a character in a range. Both limits are inclusive. | 290 Handle<String> Factory::NewConsString(Handle<String> first, |
| 291 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { | 291 Handle<String> second) { |
| 292 // This makes uses of the the unsigned wraparound. | 292 CALL_HEAP_FUNCTION(isolate(), |
| 293 return character - from <= to - from; | 293 isolate()->heap()->AllocateConsString(*first, *second), |
| 294 String); |
| 294 } | 295 } |
| 295 | 296 |
| 296 | 297 |
| 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 | |
| 330 template<typename SinkChar, typename StringType> | 298 template<typename SinkChar, typename StringType> |
| 331 Handle<String> ConcatStringContent(Handle<StringType> result, | 299 Handle<String> ConcatStringContent(Handle<StringType> result, |
| 332 Handle<String> first, | 300 Handle<String> first, |
| 333 Handle<String> second) { | 301 Handle<String> second) { |
| 334 DisallowHeapAllocation pointer_stays_valid; | 302 DisallowHeapAllocation pointer_stays_valid; |
| 335 SinkChar* sink = result->GetChars(); | 303 SinkChar* sink = result->GetChars(); |
| 336 String::WriteToFlat(*first, sink, 0, first->length()); | 304 String::WriteToFlat(*first, sink, 0, first->length()); |
| 337 String::WriteToFlat(*second, sink + first->length(), 0, second->length()); | 305 String::WriteToFlat(*second, sink + first->length(), 0, second->length()); |
| 338 return result; | 306 return result; |
| 339 } | 307 } |
| 340 | 308 |
| 341 | 309 |
| 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 | |
| 435 Handle<String> Factory::NewFlatConcatString(Handle<String> first, | 310 Handle<String> Factory::NewFlatConcatString(Handle<String> first, |
| 436 Handle<String> second) { | 311 Handle<String> second) { |
| 437 int total_length = first->length() + second->length(); | 312 int total_length = first->length() + second->length(); |
| 438 if (first->IsOneByteRepresentationUnderneath() && | 313 if (first->IsOneByteRepresentationUnderneath() && |
| 439 second->IsOneByteRepresentationUnderneath()) { | 314 second->IsOneByteRepresentationUnderneath()) { |
| 440 return ConcatStringContent<uint8_t>( | 315 return ConcatStringContent<uint8_t>( |
| 441 NewRawOneByteString(total_length), first, second); | 316 NewRawOneByteString(total_length), first, second); |
| 442 } else { | 317 } else { |
| 443 return ConcatStringContent<uc16>( | 318 return ConcatStringContent<uc16>( |
| 444 NewRawTwoByteString(total_length), first, second); | 319 NewRawTwoByteString(total_length), first, second); |
| 445 } | 320 } |
| 446 } | 321 } |
| 447 | 322 |
| 448 | 323 |
| 449 Handle<SlicedString> Factory::NewRawSlicedString(String::Encoding encoding) { | 324 Handle<String> Factory::NewSubString(Handle<String> str, |
| 450 Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING) | 325 int begin, |
| 451 ? sliced_ascii_string_map() : sliced_string_map(); | 326 int end) { |
| 452 CALL_HEAP_FUNCTION(isolate(), | 327 CALL_HEAP_FUNCTION(isolate(), |
| 453 isolate()->heap()->Allocate(*map, NEW_SPACE), | 328 str->SubString(begin, end), |
| 454 SlicedString); | 329 String); |
| 455 } | 330 } |
| 456 | 331 |
| 457 | 332 |
| 458 Handle<String> Factory::NewProperSubString(Handle<String> str, | 333 Handle<String> Factory::NewProperSubString(Handle<String> str, |
| 459 int begin, | 334 int begin, |
| 460 int end) { | 335 int end) { |
| 461 #if VERIFY_HEAP | |
| 462 if (FLAG_verify_heap) str->StringVerify(); | |
| 463 #endif | |
| 464 ASSERT(begin > 0 || end < str->length()); | 336 ASSERT(begin > 0 || end < str->length()); |
| 465 | 337 CALL_HEAP_FUNCTION(isolate(), |
| 466 int length = end - begin; | 338 isolate()->heap()->AllocateSubString(*str, begin, end), |
| 467 if (length <= 0) return empty_string(); | 339 String); |
| 468 if (length == 1) { | |
| 469 return LookupSingleCharacterStringFromCode(isolate(), str->Get(begin)); | |
| 470 } | |
| 471 if (length == 2) { | |
| 472 // Optimization for 2-byte strings often used as keys in a decompression | |
| 473 // dictionary. Check whether we already have the string in the string | |
| 474 // table to prevent creation of many unnecessary strings. | |
| 475 uint16_t c1 = str->Get(begin); | |
| 476 uint16_t c2 = str->Get(begin + 1); | |
| 477 return MakeOrFindTwoCharacterString(isolate(), c1, c2); | |
| 478 } | |
| 479 | |
| 480 if (!FLAG_string_slices || length < SlicedString::kMinLength) { | |
| 481 if (str->IsOneByteRepresentation()) { | |
| 482 Handle<SeqOneByteString> result = NewRawOneByteString(length); | |
| 483 uint8_t* dest = result->GetChars(); | |
| 484 DisallowHeapAllocation no_gc; | |
| 485 String::WriteToFlat(*str, dest, begin, end); | |
| 486 return result; | |
| 487 } else { | |
| 488 Handle<SeqTwoByteString> result = NewRawTwoByteString(length); | |
| 489 uc16* dest = result->GetChars(); | |
| 490 DisallowHeapAllocation no_gc; | |
| 491 String::WriteToFlat(*str, dest, begin, end); | |
| 492 return result; | |
| 493 } | |
| 494 } | |
| 495 | |
| 496 int offset = begin; | |
| 497 | |
| 498 while (str->IsConsString()) { | |
| 499 Handle<ConsString> cons = Handle<ConsString>::cast(str); | |
| 500 int split = cons->first()->length(); | |
| 501 if (split <= offset) { | |
| 502 // Slice is fully contained in the second part. | |
| 503 str = Handle<String>(cons->second(), isolate()); | |
| 504 offset -= split; // Adjust for offset. | |
| 505 continue; | |
| 506 } else if (offset + length <= split) { | |
| 507 // Slice is fully contained in the first part. | |
| 508 str = Handle<String>(cons->first(), isolate()); | |
| 509 continue; | |
| 510 } | |
| 511 break; | |
| 512 } | |
| 513 | |
| 514 if (str->IsSlicedString()) { | |
| 515 Handle<SlicedString> slice = Handle<SlicedString>::cast(str); | |
| 516 str = Handle<String>(slice->parent(), isolate()); | |
| 517 offset += slice->offset(); | |
| 518 } else { | |
| 519 str = FlattenGetString(str); | |
| 520 } | |
| 521 | |
| 522 ASSERT(str->IsSeqString() || str->IsExternalString()); | |
| 523 Handle<SlicedString> slice = NewRawSlicedString( | |
| 524 str->IsOneByteRepresentation() ? String::ONE_BYTE_ENCODING | |
| 525 : String::TWO_BYTE_ENCODING); | |
| 526 | |
| 527 slice->set_hash_field(String::kEmptyHashField); | |
| 528 slice->set_length(length); | |
| 529 slice->set_parent(*str); | |
| 530 slice->set_offset(offset); | |
| 531 return slice; | |
| 532 } | 340 } |
| 533 | 341 |
| 534 | 342 |
| 535 Handle<String> Factory::NewExternalStringFromAscii( | 343 Handle<String> Factory::NewExternalStringFromAscii( |
| 536 const ExternalAsciiString::Resource* resource) { | 344 const ExternalAsciiString::Resource* resource) { |
| 537 CALL_HEAP_FUNCTION( | 345 CALL_HEAP_FUNCTION( |
| 538 isolate(), | 346 isolate(), |
| 539 isolate()->heap()->AllocateExternalStringFromAscii(resource), | 347 isolate()->heap()->AllocateExternalStringFromAscii(resource), |
| 540 String); | 348 String); |
| 541 } | 349 } |
| (...skipping 1430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1972 return Handle<Object>::null(); | 1780 return Handle<Object>::null(); |
| 1973 } | 1781 } |
| 1974 | 1782 |
| 1975 | 1783 |
| 1976 Handle<Object> Factory::ToBoolean(bool value) { | 1784 Handle<Object> Factory::ToBoolean(bool value) { |
| 1977 return value ? true_value() : false_value(); | 1785 return value ? true_value() : false_value(); |
| 1978 } | 1786 } |
| 1979 | 1787 |
| 1980 | 1788 |
| 1981 } } // namespace v8::internal | 1789 } } // namespace v8::internal |
| OLD | NEW |