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

Side by Side Diff: src/builtins/builtins-string.cc

Issue 2448993002: [turbofan]: Convert StringFromCharCode to var-args style TF builtin (Closed)
Patch Set: Fix comments Created 4 years, 1 month 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
« no previous file with comments | « src/builtins/builtins.cc ('k') | src/code-factory.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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/regexp/regexp-utils.h" 9 #include "src/regexp/regexp-utils.h"
10 10
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 417
418 // ----------------------------------------------------------------------------- 418 // -----------------------------------------------------------------------------
419 // ES6 section 21.1 String Objects 419 // ES6 section 21.1 String Objects
420 420
421 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits ) 421 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
422 void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) { 422 void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
423 typedef CodeStubAssembler::Label Label; 423 typedef CodeStubAssembler::Label Label;
424 typedef compiler::Node Node; 424 typedef compiler::Node Node;
425 typedef CodeStubAssembler::Variable Variable; 425 typedef CodeStubAssembler::Variable Variable;
426 426
427 Node* code = assembler->Parameter(1); 427 Node* argc = assembler->ChangeInt32ToIntPtr(
428 Node* context = assembler->Parameter(4); 428 assembler->Parameter(BuiltinDescriptor::kArgumentsCount));
429 Node* context = assembler->Parameter(BuiltinDescriptor::kContext);
430
431 CodeStubArguments arguments(assembler, argc);
429 432
430 // Check if we have exactly one argument (plus the implicit receiver), i.e. 433 // Check if we have exactly one argument (plus the implicit receiver), i.e.
431 // if the parent frame is not an arguments adaptor frame. 434 // if the parent frame is not an arguments adaptor frame.
432 Label if_oneargument(assembler), if_notoneargument(assembler); 435 Label if_oneargument(assembler), if_notoneargument(assembler);
433 Node* parent_frame_pointer = assembler->LoadParentFramePointer(); 436 assembler->Branch(assembler->WordEqual(argc, assembler->IntPtrConstant(1)),
434 Node* parent_frame_type = 437 &if_oneargument, &if_notoneargument);
435 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
436 assembler->IntPtrConstant(
437 CommonFrameConstants::kContextOrFrameTypeOffset));
438 assembler->Branch(
439 assembler->WordEqual(
440 parent_frame_type,
441 assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
442 &if_notoneargument, &if_oneargument);
443 438
444 assembler->Bind(&if_oneargument); 439 assembler->Bind(&if_oneargument);
445 { 440 {
446 // Single argument case, perform fast single character string cache lookup 441 // Single argument case, perform fast single character string cache lookup
447 // for one-byte code units, or fall back to creating a single character 442 // for one-byte code units, or fall back to creating a single character
448 // string on the fly otherwise. 443 // string on the fly otherwise.
444 Node* code = arguments.AtIndex(0);
449 Node* code32 = assembler->TruncateTaggedToWord32(context, code); 445 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
450 Node* code16 = assembler->Word32And( 446 Node* code16 = assembler->Word32And(
451 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); 447 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
452 Node* result = assembler->StringFromCharCode(code16); 448 Node* result = assembler->StringFromCharCode(code16);
453 assembler->Return(result); 449 arguments.PopAndReturn(result);
454 } 450 }
455 451
452 Node* code16 = nullptr;
456 assembler->Bind(&if_notoneargument); 453 assembler->Bind(&if_notoneargument);
457 { 454 {
458 // Determine the resulting string length. 455 Label two_byte(assembler);
459 Node* length = assembler->LoadAndUntagSmi( 456 // Assume that the resulting string contains only one-byte characters.
460 parent_frame_pointer, ArgumentsAdaptorFrameConstants::kLengthOffset); 457 Node* one_byte_result = assembler->AllocateSeqOneByteString(context, argc);
461 458
462 // Assume that the resulting string contains only one-byte characters. 459 Variable max_index(assembler, MachineType::PointerRepresentation());
463 Node* result = assembler->AllocateSeqOneByteString(context, length); 460 max_index.Bind(assembler->IntPtrConstant(0));
464 461
465 // Truncate all input parameters and append them to the resulting string. 462 // Iterate over the incoming arguments, converting them to 8-bit character
466 Variable var_offset(assembler, MachineType::PointerRepresentation()); 463 // codes. Stop if any of the conversions generates a code that doesn't fit
467 Label loop(assembler, &var_offset), done_loop(assembler); 464 // in 8 bits.
468 var_offset.Bind(assembler->IntPtrConstant(0)); 465 CodeStubAssembler::VariableList vars({&max_index}, assembler->zone());
469 assembler->Goto(&loop); 466 arguments.ForEach(vars, [context, &two_byte, &max_index, &code16,
470 assembler->Bind(&loop); 467 one_byte_result](CodeStubAssembler* assembler,
471 { 468 Node* arg) {
472 // Load the current {offset}. 469 Node* code32 = assembler->TruncateTaggedToWord32(context, arg);
473 Node* offset = var_offset.value(); 470 code16 = assembler->Word32And(
474
475 // Check if we're done with the string.
476 assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
477
478 // Load the next code point and truncate it to a 16-bit value.
479 Node* code = assembler->Load(
480 MachineType::AnyTagged(), parent_frame_pointer,
481 assembler->IntPtrAdd(
482 assembler->WordShl(assembler->IntPtrSub(length, offset),
483 assembler->IntPtrConstant(kPointerSizeLog2)),
484 assembler->IntPtrConstant(
485 CommonFrameConstants::kFixedFrameSizeAboveFp -
486 kPointerSize)));
487 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
488 Node* code16 = assembler->Word32And(
489 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); 471 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
490 472
491 // Check if {code16} fits into a one-byte string. 473 assembler->GotoIf(
492 Label if_codeisonebyte(assembler), if_codeistwobyte(assembler); 474 assembler->Int32GreaterThan(
493 assembler->Branch(
494 assembler->Int32LessThanOrEqual(
495 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)), 475 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
496 &if_codeisonebyte, &if_codeistwobyte); 476 &two_byte);
497 477
498 assembler->Bind(&if_codeisonebyte); 478 // The {code16} fits into the SeqOneByteString {one_byte_result}.
499 { 479 Node* offset = assembler->ElementOffsetFromIndex(
500 // The {code16} fits into the SeqOneByteString {result}. 480 max_index.value(), UINT8_ELEMENTS,
501 assembler->StoreNoWriteBarrier( 481 CodeStubAssembler::INTPTR_PARAMETERS,
502 MachineRepresentation::kWord8, result, 482 SeqOneByteString::kHeaderSize - kHeapObjectTag);
503 assembler->IntPtrAdd( 483 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord8,
504 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize - 484 one_byte_result, offset, code16);
505 kHeapObjectTag), 485 max_index.Bind(assembler->IntPtrAdd(max_index.value(),
506 offset), 486 assembler->IntPtrConstant(1)));
507 code16); 487 });
508 var_offset.Bind( 488 arguments.PopAndReturn(one_byte_result);
509 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
510 assembler->Goto(&loop);
511 }
512 489
513 assembler->Bind(&if_codeistwobyte); 490 assembler->Bind(&two_byte);
514 {
515 // Allocate a SeqTwoByteString to hold the resulting string.
516 Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
517 491
518 // Copy all characters that were previously written to the 492 // At least one of the characters in the string requires a 16-bit
519 // SeqOneByteString in {result} over to the new {cresult}. 493 // representation. Allocate a SeqTwoByteString to hold the resulting
520 Variable var_coffset(assembler, MachineType::PointerRepresentation()); 494 // string.
521 Label cloop(assembler, &var_coffset), done_cloop(assembler); 495 Node* two_byte_result = assembler->AllocateSeqTwoByteString(context, argc);
522 var_coffset.Bind(assembler->IntPtrConstant(0));
523 assembler->Goto(&cloop);
524 assembler->Bind(&cloop);
525 {
526 Node* coffset = var_coffset.value();
527 assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
528 Node* ccode = assembler->Load(
529 MachineType::Uint8(), result,
530 assembler->IntPtrAdd(
531 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
532 kHeapObjectTag),
533 coffset));
534 assembler->StoreNoWriteBarrier(
535 MachineRepresentation::kWord16, cresult,
536 assembler->IntPtrAdd(
537 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
538 kHeapObjectTag),
539 assembler->WordShl(coffset, 1)),
540 ccode);
541 var_coffset.Bind(
542 assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
543 assembler->Goto(&cloop);
544 }
545 496
546 // Write the pending {code16} to {offset}. 497 // Copy the characters that have already been put in the 8-bit string into
547 assembler->Bind(&done_cloop); 498 // their corresponding positions in the new 16-bit string.
548 assembler->StoreNoWriteBarrier( 499 Node* zero = assembler->IntPtrConstant(0);
549 MachineRepresentation::kWord16, cresult, 500 assembler->CopyStringCharacters(
550 assembler->IntPtrAdd( 501 one_byte_result, two_byte_result, zero, zero, max_index.value(),
551 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize - 502 String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
552 kHeapObjectTag), 503 CodeStubAssembler::INTPTR_PARAMETERS);
553 assembler->WordShl(offset, 1)),
554 code16);
555 504
556 // Copy the remaining parameters to the SeqTwoByteString {cresult}. 505 // Write the character that caused the 8-bit to 16-bit fault.
557 Label floop(assembler, &var_offset), done_floop(assembler); 506 Node* max_index_offset = assembler->ElementOffsetFromIndex(
558 assembler->Goto(&floop); 507 max_index.value(), UINT16_ELEMENTS,
559 assembler->Bind(&floop); 508 CodeStubAssembler::INTPTR_PARAMETERS,
560 { 509 SeqTwoByteString::kHeaderSize - kHeapObjectTag);
561 // Compute the next {offset}. 510 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16,
562 Node* offset = assembler->IntPtrAdd(var_offset.value(), 511 two_byte_result, max_index_offset, code16);
563 assembler->IntPtrConstant(1)); 512 max_index.Bind(
513 assembler->IntPtrAdd(max_index.value(), assembler->IntPtrConstant(1)));
564 514
565 // Check if we're done with the string. 515 // Resume copying the passed-in arguments from the same place where the
566 assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop); 516 // 8-bit copy stopped, but this time copying over all of the characters
567 517 // using a 16-bit representation.
568 // Load the next code point and truncate it to a 16-bit value. 518 arguments.ForEach(
569 Node* code = assembler->Load( 519 vars,
570 MachineType::AnyTagged(), parent_frame_pointer, 520 [context, two_byte_result, &max_index](CodeStubAssembler* assembler,
571 assembler->IntPtrAdd( 521 Node* arg) {
572 assembler->WordShl( 522 Node* code32 = assembler->TruncateTaggedToWord32(context, arg);
573 assembler->IntPtrSub(length, offset),
574 assembler->IntPtrConstant(kPointerSizeLog2)),
575 assembler->IntPtrConstant(
576 CommonFrameConstants::kFixedFrameSizeAboveFp -
577 kPointerSize)));
578 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
579 Node* code16 = assembler->Word32And( 523 Node* code16 = assembler->Word32And(
580 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); 524 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
581 525
582 // Store the truncated {code} point at the next offset. 526 Node* offset = assembler->ElementOffsetFromIndex(
583 assembler->StoreNoWriteBarrier( 527 max_index.value(), UINT16_ELEMENTS,
584 MachineRepresentation::kWord16, cresult, 528 CodeStubAssembler::INTPTR_PARAMETERS,
585 assembler->IntPtrAdd( 529 SeqTwoByteString::kHeaderSize - kHeapObjectTag);
586 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize - 530 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16,
587 kHeapObjectTag), 531 two_byte_result, offset, code16);
588 assembler->WordShl(offset, 1)), 532 max_index.Bind(assembler->IntPtrAdd(max_index.value(),
589 code16); 533 assembler->IntPtrConstant(1)));
590 var_offset.Bind(offset); 534 },
591 assembler->Goto(&floop); 535 max_index.value());
592 }
593 536
594 // Return the SeqTwoByteString. 537 arguments.PopAndReturn(two_byte_result);
595 assembler->Bind(&done_floop);
596 assembler->Return(cresult);
597 }
598 }
599
600 assembler->Bind(&done_loop);
601 assembler->Return(result);
602 } 538 }
603 } 539 }
604 540
605 namespace { // for String.fromCodePoint 541 namespace { // for String.fromCodePoint
606 542
607 bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) { 543 bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
608 if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) { 544 if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
609 return false; 545 return false;
610 } 546 }
611 547
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 Runtime::kThrowIncompatibleMethodReceiver, context, 1427 Runtime::kThrowIncompatibleMethodReceiver, context,
1492 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( 1428 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
1493 "String Iterator.prototype.next", TENURED)), 1429 "String Iterator.prototype.next", TENURED)),
1494 iterator); 1430 iterator);
1495 assembler->Return(result); // Never reached. 1431 assembler->Return(result); // Never reached.
1496 } 1432 }
1497 } 1433 }
1498 1434
1499 } // namespace internal 1435 } // namespace internal
1500 } // namespace v8 1436 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.cc ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698