Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/factory.cc

Issue 114943004: Reland "Handlify concat string and substring." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix test case. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/factory.h ('k') | src/handles.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/factory.h ('k') | src/handles.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698