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 |