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