Chromium Code Reviews| Index: src/builtins/builtins-string.cc |
| diff --git a/src/builtins/builtins-string.cc b/src/builtins/builtins-string.cc |
| index 7828dd231f1405874ee451211950f874c1562083..ebf2dc3a344e7ad939603dc24a7782af65524248 100644 |
| --- a/src/builtins/builtins-string.cc |
| +++ b/src/builtins/builtins-string.cc |
| @@ -424,181 +424,117 @@ void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) { |
| typedef compiler::Node Node; |
| typedef CodeStubAssembler::Variable Variable; |
| - Node* code = assembler->Parameter(1); |
| - Node* context = assembler->Parameter(4); |
| + Node* argc = assembler->ChangeInt32ToIntPtr( |
| + assembler->Parameter(BuiltinDescriptor::kArgumentsCount)); |
| + Node* context = assembler->Parameter(BuiltinDescriptor::kContext); |
| + |
| + CodeStubArguments arguments(assembler, argc); |
| // Check if we have exactly one argument (plus the implicit receiver), i.e. |
| // if the parent frame is not an arguments adaptor frame. |
| Label if_oneargument(assembler), if_notoneargument(assembler); |
| - Node* parent_frame_pointer = assembler->LoadParentFramePointer(); |
| - Node* parent_frame_type = |
| - assembler->Load(MachineType::Pointer(), parent_frame_pointer, |
| - assembler->IntPtrConstant( |
| - CommonFrameConstants::kContextOrFrameTypeOffset)); |
| - assembler->Branch( |
| - assembler->WordEqual( |
| - parent_frame_type, |
| - assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))), |
|
Igor Sheludko
2016/11/04 12:55:58
Wow! What a hack! :)
danno
2016/11/07 16:43:52
Acknowledged.
|
| - &if_notoneargument, &if_oneargument); |
| + assembler->Branch(assembler->WordEqual(argc, assembler->Int32Constant(1)), |
| + &if_oneargument, &if_notoneargument); |
| assembler->Bind(&if_oneargument); |
| { |
| // Single argument case, perform fast single character string cache lookup |
| // for one-byte code units, or fall back to creating a single character |
| // string on the fly otherwise. |
| + Node* code = arguments.AtIndex(0); |
| Node* code32 = assembler->TruncateTaggedToWord32(context, code); |
| Node* code16 = assembler->Word32And( |
| code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); |
| Node* result = assembler->StringFromCharCode(code16); |
| - assembler->Return(result); |
| + arguments.PopAndReturn(result); |
| } |
| + Node* code16 = nullptr; |
| assembler->Bind(&if_notoneargument); |
| { |
| - // Determine the resulting string length. |
| - Node* length = assembler->LoadAndUntagSmi( |
| - parent_frame_pointer, ArgumentsAdaptorFrameConstants::kLengthOffset); |
| - |
| + Label two_byte(assembler); |
| // Assume that the resulting string contains only one-byte characters. |
| - Node* result = assembler->AllocateSeqOneByteString(context, length); |
| - |
| - // Truncate all input parameters and append them to the resulting string. |
| - Variable var_offset(assembler, MachineType::PointerRepresentation()); |
| - Label loop(assembler, &var_offset), done_loop(assembler); |
| - var_offset.Bind(assembler->IntPtrConstant(0)); |
| - assembler->Goto(&loop); |
| - assembler->Bind(&loop); |
| - { |
| - // Load the current {offset}. |
| - Node* offset = var_offset.value(); |
| - |
| - // Check if we're done with the string. |
| - assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop); |
| - |
| - // Load the next code point and truncate it to a 16-bit value. |
| - Node* code = assembler->Load( |
| - MachineType::AnyTagged(), parent_frame_pointer, |
| - assembler->IntPtrAdd( |
| - assembler->WordShl(assembler->IntPtrSub(length, offset), |
| - assembler->IntPtrConstant(kPointerSizeLog2)), |
| - assembler->IntPtrConstant( |
| - CommonFrameConstants::kFixedFrameSizeAboveFp - |
| - kPointerSize))); |
| - Node* code32 = assembler->TruncateTaggedToWord32(context, code); |
| - Node* code16 = assembler->Word32And( |
| + Node* one_byte_result = assembler->AllocateSeqOneByteString(context, argc); |
| + |
| + Variable max_index(assembler, MachineRepresentation::kWord32); |
|
Igor Sheludko
2016/11/04 12:55:58
Why is max_index not of an intptr_t type? I suppos
danno
2016/11/07 16:43:52
Done. Made it an IntPtr.
|
| + max_index.Bind(assembler->Int32Constant(0)); |
| + |
| + // Iterate over the incoming arguments, converting them to 8-bit character |
| + // codes. Stope if any of the conversions generates a code that doesn't fit |
|
Igor Sheludko
2016/11/04 12:55:58
s/Stope/Stop/
danno
2016/11/07 16:43:52
Done.
|
| + // in 8 bits. |
| + CodeStubAssembler::VariableList vars({&max_index}, assembler->zone()); |
| + arguments.ForEach(vars, [context, &two_byte, &max_index, &code16, |
| + one_byte_result](CodeStubAssembler* assembler, |
| + Node* arg) { |
| + Node* code32 = assembler->TruncateTaggedToWord32(context, arg); |
| + code16 = assembler->Word32And( |
| code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); |
| - // Check if {code16} fits into a one-byte string. |
| - Label if_codeisonebyte(assembler), if_codeistwobyte(assembler); |
| - assembler->Branch( |
| - assembler->Int32LessThanOrEqual( |
| + assembler->GotoIf( |
| + assembler->Int32GreaterThan( |
| code16, assembler->Int32Constant(String::kMaxOneByteCharCode)), |
| - &if_codeisonebyte, &if_codeistwobyte); |
| - |
| - assembler->Bind(&if_codeisonebyte); |
| - { |
| - // The {code16} fits into the SeqOneByteString {result}. |
| - assembler->StoreNoWriteBarrier( |
| - MachineRepresentation::kWord8, result, |
| - assembler->IntPtrAdd( |
| - assembler->IntPtrConstant(SeqOneByteString::kHeaderSize - |
| - kHeapObjectTag), |
| - offset), |
| - code16); |
| - var_offset.Bind( |
| - assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1))); |
| - assembler->Goto(&loop); |
| - } |
| - |
| - assembler->Bind(&if_codeistwobyte); |
| - { |
| - // Allocate a SeqTwoByteString to hold the resulting string. |
| - Node* cresult = assembler->AllocateSeqTwoByteString(context, length); |
| - |
| - // Copy all characters that were previously written to the |
| - // SeqOneByteString in {result} over to the new {cresult}. |
| - Variable var_coffset(assembler, MachineType::PointerRepresentation()); |
| - Label cloop(assembler, &var_coffset), done_cloop(assembler); |
| - var_coffset.Bind(assembler->IntPtrConstant(0)); |
| - assembler->Goto(&cloop); |
| - assembler->Bind(&cloop); |
| - { |
| - Node* coffset = var_coffset.value(); |
| - assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop); |
| - Node* ccode = assembler->Load( |
| - MachineType::Uint8(), result, |
| - assembler->IntPtrAdd( |
| - assembler->IntPtrConstant(SeqOneByteString::kHeaderSize - |
| - kHeapObjectTag), |
| - coffset)); |
| - assembler->StoreNoWriteBarrier( |
| - MachineRepresentation::kWord16, cresult, |
| - assembler->IntPtrAdd( |
| - assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize - |
| - kHeapObjectTag), |
| - assembler->WordShl(coffset, 1)), |
| - ccode); |
| - var_coffset.Bind( |
| - assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1))); |
| - assembler->Goto(&cloop); |
| - } |
| + &two_byte); |
| + |
| + // The {code16} fits into the SeqOneByteString {one_byte_result}. |
| + Node* offset = assembler->ElementOffsetFromIndex( |
| + max_index.value(), UINT8_ELEMENTS, |
| + CodeStubAssembler::INTPTR_PARAMETERS, |
|
Igor Sheludko
2016/11/04 12:55:58
Parameter mode here is not in sync with max_index
danno
2016/11/07 16:43:52
Done.
|
| + SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| + assembler->StoreNoWriteBarrier(MachineRepresentation::kWord8, |
| + one_byte_result, offset, code16); |
| + max_index.Bind( |
| + assembler->Int32Add(max_index.value(), assembler->Int32Constant(1))); |
| + }); |
| + arguments.PopAndReturn(one_byte_result); |
| + |
| + assembler->Bind(&two_byte); |
| + |
| + // At least one of the characters in the string requires a 16-bit |
| + // representation. Allocate a SeqTwoByteString to hold the resulting |
| + // string. |
| + Node* two_byte_result = assembler->AllocateSeqTwoByteString(context, argc); |
| + |
| + // Copy the character that have already been put in the 8-bit string into |
| + // their corresponding positions in the new 16-bit string. |
| + Node* zero = assembler->Int32Constant(0); |
|
Igor Sheludko
2016/11/04 12:55:58
Not an intptr_t zero.
danno
2016/11/07 16:43:52
Done.
|
| + assembler->CopyStringCharacters( |
| + one_byte_result, two_byte_result, zero, zero, max_index.value(), |
| + String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING, |
| + CodeStubAssembler::INTPTR_PARAMETERS); |
|
Igor Sheludko
2016/11/04 12:55:58
Same here.
danno
2016/11/07 16:43:52
Done.
|
| - // Write the pending {code16} to {offset}. |
| - assembler->Bind(&done_cloop); |
| - assembler->StoreNoWriteBarrier( |
| - MachineRepresentation::kWord16, cresult, |
| - assembler->IntPtrAdd( |
| - assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize - |
| - kHeapObjectTag), |
| - assembler->WordShl(offset, 1)), |
| - code16); |
| - |
| - // Copy the remaining parameters to the SeqTwoByteString {cresult}. |
| - Label floop(assembler, &var_offset), done_floop(assembler); |
| - assembler->Goto(&floop); |
| - assembler->Bind(&floop); |
| - { |
| - // Compute the next {offset}. |
| - Node* offset = assembler->IntPtrAdd(var_offset.value(), |
| - assembler->IntPtrConstant(1)); |
| - |
| - // Check if we're done with the string. |
| - assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop); |
| - |
| - // Load the next code point and truncate it to a 16-bit value. |
| - Node* code = assembler->Load( |
| - MachineType::AnyTagged(), parent_frame_pointer, |
| - assembler->IntPtrAdd( |
| - assembler->WordShl( |
| - assembler->IntPtrSub(length, offset), |
| - assembler->IntPtrConstant(kPointerSizeLog2)), |
| - assembler->IntPtrConstant( |
| - CommonFrameConstants::kFixedFrameSizeAboveFp - |
| - kPointerSize))); |
| - Node* code32 = assembler->TruncateTaggedToWord32(context, code); |
| + // Write back the character that caused the 8-bit to 16-bit fault. |
| + Node* max_index_offset = assembler->ElementOffsetFromIndex( |
| + max_index.value(), UINT16_ELEMENTS, |
| + CodeStubAssembler::INTPTR_PARAMETERS, |
|
Igor Sheludko
2016/11/04 12:55:58
And here.
danno
2016/11/07 16:43:52
Done.
|
| + SeqTwoByteString::kHeaderSize - kHeapObjectTag); |
| + assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16, |
| + two_byte_result, max_index_offset, code16); |
| + max_index.Bind( |
| + assembler->Int32Add(max_index.value(), assembler->Int32Constant(1))); |
| + |
| + // Resume copying the passed-in arguments from the same place where the |
| + // 8-bit copy stopped, but this time copying over all of the characters at |
| + // 16-bit. |
| + arguments.ForEach( |
| + vars, |
| + [context, two_byte_result, &max_index](CodeStubAssembler* assembler, |
| + Node* arg) { |
| + Node* code32 = assembler->TruncateTaggedToWord32(context, arg); |
| Node* code16 = assembler->Word32And( |
| code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); |
| - // Store the truncated {code} point at the next offset. |
| - assembler->StoreNoWriteBarrier( |
| - MachineRepresentation::kWord16, cresult, |
| - assembler->IntPtrAdd( |
| - assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize - |
| - kHeapObjectTag), |
| - assembler->WordShl(offset, 1)), |
| - code16); |
| - var_offset.Bind(offset); |
| - assembler->Goto(&floop); |
| - } |
| - |
| - // Return the SeqTwoByteString. |
| - assembler->Bind(&done_floop); |
| - assembler->Return(cresult); |
| - } |
| - } |
| - |
| - assembler->Bind(&done_loop); |
| - assembler->Return(result); |
| + Node* offset = assembler->ElementOffsetFromIndex( |
| + max_index.value(), UINT16_ELEMENTS, |
| + CodeStubAssembler::INTPTR_PARAMETERS, |
|
Igor Sheludko
2016/11/04 12:55:58
Same here.
danno
2016/11/07 16:43:52
Done.
|
| + SeqTwoByteString::kHeaderSize - kHeapObjectTag); |
| + assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16, |
| + two_byte_result, offset, code16); |
| + max_index.Bind(assembler->Int32Add(max_index.value(), |
| + assembler->Int32Constant(1))); |
| + }, |
| + max_index.value()); |
|
Igor Sheludko
2016/11/04 12:55:58
Same here (default parameter mode is INTPTR_PARAME
danno
2016/11/07 16:43:52
Done.
|
| + |
| + arguments.PopAndReturn(two_byte_result); |
| } |
| } |