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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 8909004: Porting r10252 to x64 (handle external strings in generated code when concatenating short strings). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 9 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/ia32/code-stubs-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 4416 matching lines...) Expand 10 before | Expand all | Expand 10 after
4427 4427
4428 void StringCharAtGenerator::GenerateSlow( 4428 void StringCharAtGenerator::GenerateSlow(
4429 MacroAssembler* masm, 4429 MacroAssembler* masm,
4430 const RuntimeCallHelper& call_helper) { 4430 const RuntimeCallHelper& call_helper) {
4431 char_code_at_generator_.GenerateSlow(masm, call_helper); 4431 char_code_at_generator_.GenerateSlow(masm, call_helper);
4432 char_from_code_generator_.GenerateSlow(masm, call_helper); 4432 char_from_code_generator_.GenerateSlow(masm, call_helper);
4433 } 4433 }
4434 4434
4435 4435
4436 void StringAddStub::Generate(MacroAssembler* masm) { 4436 void StringAddStub::Generate(MacroAssembler* masm) {
4437 Label string_add_runtime, call_builtin; 4437 Label call_runtime, call_builtin;
4438 Builtins::JavaScript builtin_id = Builtins::ADD; 4438 Builtins::JavaScript builtin_id = Builtins::ADD;
4439 4439
4440 // Load the two arguments. 4440 // Load the two arguments.
4441 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left). 4441 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left).
4442 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right). 4442 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right).
4443 4443
4444 // Make sure that both arguments are strings if not known in advance. 4444 // Make sure that both arguments are strings if not known in advance.
4445 if (flags_ == NO_STRING_ADD_FLAGS) { 4445 if (flags_ == NO_STRING_ADD_FLAGS) {
4446 __ JumpIfSmi(rax, &string_add_runtime); 4446 __ JumpIfSmi(rax, &call_runtime);
4447 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); 4447 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
4448 __ j(above_equal, &string_add_runtime); 4448 __ j(above_equal, &call_runtime);
4449 4449
4450 // First argument is a a string, test second. 4450 // First argument is a a string, test second.
4451 __ JumpIfSmi(rdx, &string_add_runtime); 4451 __ JumpIfSmi(rdx, &call_runtime);
4452 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9); 4452 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
4453 __ j(above_equal, &string_add_runtime); 4453 __ j(above_equal, &call_runtime);
4454 } else { 4454 } else {
4455 // Here at least one of the arguments is definitely a string. 4455 // Here at least one of the arguments is definitely a string.
4456 // We convert the one that is not known to be a string. 4456 // We convert the one that is not known to be a string.
4457 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { 4457 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
4458 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); 4458 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
4459 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi, 4459 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
4460 &call_builtin); 4460 &call_builtin);
4461 builtin_id = Builtins::STRING_ADD_RIGHT; 4461 builtin_id = Builtins::STRING_ADD_RIGHT;
4462 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { 4462 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
4463 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); 4463 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4511 // Look at the length of the result of adding the two strings. 4511 // Look at the length of the result of adding the two strings.
4512 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); 4512 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
4513 __ SmiAdd(rbx, rbx, rcx); 4513 __ SmiAdd(rbx, rbx, rcx);
4514 // Use the symbol table when adding two one character strings, as it 4514 // Use the symbol table when adding two one character strings, as it
4515 // helps later optimizations to return a symbol here. 4515 // helps later optimizations to return a symbol here.
4516 __ SmiCompare(rbx, Smi::FromInt(2)); 4516 __ SmiCompare(rbx, Smi::FromInt(2));
4517 __ j(not_equal, &longer_than_two); 4517 __ j(not_equal, &longer_than_two);
4518 4518
4519 // Check that both strings are non-external ascii strings. 4519 // Check that both strings are non-external ascii strings.
4520 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, 4520 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
4521 &string_add_runtime); 4521 &call_runtime);
4522 4522
4523 // Get the two characters forming the sub string. 4523 // Get the two characters forming the sub string.
4524 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); 4524 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
4525 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); 4525 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
4526 4526
4527 // Try to lookup two character string in symbol table. If it is not found 4527 // Try to lookup two character string in symbol table. If it is not found
4528 // just allocate a new one. 4528 // just allocate a new one.
4529 Label make_two_character_string, make_flat_ascii_string; 4529 Label make_two_character_string, make_flat_ascii_string;
4530 StringHelper::GenerateTwoCharacterSymbolTableProbe( 4530 StringHelper::GenerateTwoCharacterSymbolTableProbe(
4531 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); 4531 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
4532 __ IncrementCounter(counters->string_add_native(), 1); 4532 __ IncrementCounter(counters->string_add_native(), 1);
4533 __ ret(2 * kPointerSize); 4533 __ ret(2 * kPointerSize);
4534 4534
4535 __ bind(&make_two_character_string); 4535 __ bind(&make_two_character_string);
4536 __ Set(rbx, 2); 4536 __ Set(rdi, 2);
4537 __ jmp(&make_flat_ascii_string); 4537 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime);
4538 // rbx - first byte: first character
4539 // rbx - second byte: *maybe* second character
4540 // Make sure that the second byte of rbx contains the second character.
4541 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
4542 __ shll(rcx, Immediate(kBitsPerByte));
4543 __ orl(rbx, rcx);
4544 // Write both characters to the new string.
4545 __ movw(FieldOperand(rax, SeqAsciiString::kHeaderSize), rbx);
4546 __ IncrementCounter(counters->string_add_native(), 1);
4547 __ ret(2 * kPointerSize);
4538 4548
4539 __ bind(&longer_than_two); 4549 __ bind(&longer_than_two);
4540 // Check if resulting string will be flat. 4550 // Check if resulting string will be flat.
4541 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength)); 4551 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength));
4542 __ j(below, &string_add_flat_result); 4552 __ j(below, &string_add_flat_result);
4543 // Handle exceptionally long strings in the runtime system. 4553 // Handle exceptionally long strings in the runtime system.
4544 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); 4554 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
4545 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength)); 4555 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
4546 __ j(above, &string_add_runtime); 4556 __ j(above, &call_runtime);
4547 4557
4548 // If result is not supposed to be flat, allocate a cons string object. If 4558 // If result is not supposed to be flat, allocate a cons string object. If
4549 // both strings are ascii the result is an ascii cons string. 4559 // both strings are ascii the result is an ascii cons string.
4550 // rax: first string 4560 // rax: first string
4551 // rbx: length of resulting flat string 4561 // rbx: length of resulting flat string
4552 // rdx: second string 4562 // rdx: second string
4553 // r8: instance type of first string 4563 // r8: instance type of first string
4554 // r9: instance type of second string 4564 // r9: instance type of second string
4555 Label non_ascii, allocated, ascii_data; 4565 Label non_ascii, allocated, ascii_data;
4556 __ movl(rcx, r8); 4566 __ movl(rcx, r8);
4557 __ and_(rcx, r9); 4567 __ and_(rcx, r9);
4558 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 4568 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4559 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 4569 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4560 __ testl(rcx, Immediate(kStringEncodingMask)); 4570 __ testl(rcx, Immediate(kStringEncodingMask));
4561 __ j(zero, &non_ascii); 4571 __ j(zero, &non_ascii);
4562 __ bind(&ascii_data); 4572 __ bind(&ascii_data);
4563 // Allocate an acsii cons string. 4573 // Allocate an acsii cons string.
4564 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); 4574 __ AllocateAsciiConsString(rcx, rdi, no_reg, &call_runtime);
4565 __ bind(&allocated); 4575 __ bind(&allocated);
4566 // Fill the fields of the cons string. 4576 // Fill the fields of the cons string.
4567 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); 4577 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
4568 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), 4578 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset),
4569 Immediate(String::kEmptyHashField)); 4579 Immediate(String::kEmptyHashField));
4570 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); 4580 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
4571 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); 4581 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
4572 __ movq(rax, rcx); 4582 __ movq(rax, rcx);
4573 __ IncrementCounter(counters->string_add_native(), 1); 4583 __ IncrementCounter(counters->string_add_native(), 1);
4574 __ ret(2 * kPointerSize); 4584 __ ret(2 * kPointerSize);
4575 __ bind(&non_ascii); 4585 __ bind(&non_ascii);
4576 // At least one of the strings is two-byte. Check whether it happens 4586 // At least one of the strings is two-byte. Check whether it happens
4577 // to contain only ascii characters. 4587 // to contain only ascii characters.
4578 // rcx: first instance type AND second instance type. 4588 // rcx: first instance type AND second instance type.
4579 // r8: first instance type. 4589 // r8: first instance type.
4580 // r9: second instance type. 4590 // r9: second instance type.
4581 __ testb(rcx, Immediate(kAsciiDataHintMask)); 4591 __ testb(rcx, Immediate(kAsciiDataHintMask));
4582 __ j(not_zero, &ascii_data); 4592 __ j(not_zero, &ascii_data);
4583 __ xor_(r8, r9); 4593 __ xor_(r8, r9);
4584 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); 4594 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
4585 __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); 4595 __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
4586 __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); 4596 __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
4587 __ j(equal, &ascii_data); 4597 __ j(equal, &ascii_data);
4588 // Allocate a two byte cons string. 4598 // Allocate a two byte cons string.
4589 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &string_add_runtime); 4599 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &call_runtime);
4590 __ jmp(&allocated); 4600 __ jmp(&allocated);
4591 4601
4592 // Handle creating a flat result. First check that both strings are not 4602 // We cannot encounter sliced strings or cons strings here since:
4593 // external strings. 4603 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
4604 // Handle creating a flat result from either external or sequential strings.
4605 // Locate the first characters' locations.
4594 // rax: first string 4606 // rax: first string
4595 // rbx: length of resulting flat string as smi 4607 // rbx: length of resulting flat string as smi
4596 // rdx: second string 4608 // rdx: second string
4597 // r8: instance type of first string 4609 // r8: instance type of first string
4598 // r9: instance type of first string 4610 // r9: instance type of first string
4611 Label first_prepared, second_prepared;
4612 Label first_is_sequential, second_is_sequential;
4599 __ bind(&string_add_flat_result); 4613 __ bind(&string_add_flat_result);
4614
4615 __ SmiToInteger32(r14, FieldOperand(rax, SeqString::kLengthOffset));
4616 // r14: length of first string
4617 STATIC_ASSERT(kSeqStringTag == 0);
4618 __ testb(r8, Immediate(kStringRepresentationMask));
4619 __ j(zero, &first_is_sequential, Label::kNear);
4620 // Rule out short external string and load string resource.
4621 STATIC_ASSERT(kShortExternalStringTag != 0);
4622 __ testb(r8, Immediate(kShortExternalStringMask));
4623 __ j(not_zero, &call_runtime);
4624 __ movq(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset));
4625 __ jmp(&first_prepared, Label::kNear);
4626 __ bind(&first_is_sequential);
4627 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4628 __ lea(rcx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
4629 __ bind(&first_prepared);
4630
4631 // Check whether both strings have same encoding.
4632 __ xorl(r8, r9);
4633 __ testb(r8, Immediate(kStringEncodingMask));
4634 __ j(not_zero, &call_runtime);
4635
4636 __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset));
4637 // r15: length of second string
4638 STATIC_ASSERT(kSeqStringTag == 0);
4639 __ testb(r9, Immediate(kStringRepresentationMask));
4640 __ j(zero, &second_is_sequential, Label::kNear);
4641 // Rule out short external string and load string resource.
4642 STATIC_ASSERT(kShortExternalStringTag != 0);
4643 __ testb(r9, Immediate(kShortExternalStringMask));
4644 __ j(not_zero, &call_runtime);
4645 __ movq(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset));
4646 __ jmp(&second_prepared, Label::kNear);
4647 __ bind(&second_is_sequential);
4648 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4649 __ lea(rdx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
4650 __ bind(&second_prepared);
4651
4652 Label non_ascii_string_add_flat_result;
4653 // r9: instance type of second string
4654 // First string and second string have the same encoding.
4655 STATIC_ASSERT(kTwoByteStringTag == 0);
4600 __ SmiToInteger32(rbx, rbx); 4656 __ SmiToInteger32(rbx, rbx);
4601 __ movl(rcx, r8); 4657 __ testb(r9, Immediate(kStringEncodingMask));
4602 __ and_(rcx, Immediate(kStringRepresentationMask));
4603 __ cmpl(rcx, Immediate(kExternalStringTag));
4604 __ j(equal, &string_add_runtime);
4605 __ movl(rcx, r9);
4606 __ and_(rcx, Immediate(kStringRepresentationMask));
4607 __ cmpl(rcx, Immediate(kExternalStringTag));
4608 __ j(equal, &string_add_runtime);
4609 // We cannot encounter sliced strings here since:
4610 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
4611 // Now check if both strings are ascii strings.
4612 // rax: first string
4613 // rbx: length of resulting flat string
4614 // rdx: second string
4615 // r8: instance type of first string
4616 // r9: instance type of second string
4617 Label non_ascii_string_add_flat_result;
4618 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4619 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4620 __ testl(r8, Immediate(kStringEncodingMask));
4621 __ j(zero, &non_ascii_string_add_flat_result); 4658 __ j(zero, &non_ascii_string_add_flat_result);
4622 __ testl(r9, Immediate(kStringEncodingMask));
4623 __ j(zero, &string_add_runtime);
4624 4659
4625 __ bind(&make_flat_ascii_string); 4660 __ bind(&make_flat_ascii_string);
4626 // Both strings are ascii strings. As they are short they are both flat. 4661 // Both strings are ascii strings. As they are short they are both flat.
4627 __ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime); 4662 __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime);
4628 // rcx: result string 4663 // rax: result string
4629 __ movq(rbx, rcx);
4630 // Locate first character of result. 4664 // Locate first character of result.
4631 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 4665 __ lea(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
4632 // Locate first character of first argument 4666 // rcx: first char of first string
4633 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 4667 // rbx: first character of result
4634 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 4668 // r14: length of first string
4635 // rax: first char of first argument 4669 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true);
4636 // rbx: result string 4670 // rbx: next character of result
4637 // rcx: first character of result 4671 // rdx: first char of second string
4638 // rdx: second string 4672 // r15: length of second string
4639 // rdi: length of first argument 4673 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true);
4640 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true);
4641 // Locate first character of second argument.
4642 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset));
4643 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
4644 // rbx: result string
4645 // rcx: next character of result
4646 // rdx: first char of second argument
4647 // rdi: length of second argument
4648 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
4649 __ movq(rax, rbx);
4650 __ IncrementCounter(counters->string_add_native(), 1); 4674 __ IncrementCounter(counters->string_add_native(), 1);
4651 __ ret(2 * kPointerSize); 4675 __ ret(2 * kPointerSize);
4652 4676
4653 // Handle creating a flat two byte result.
4654 // rax: first string - known to be two byte
4655 // rbx: length of resulting flat string
4656 // rdx: second string
4657 // r8: instance type of first string
4658 // r9: instance type of first string
4659 __ bind(&non_ascii_string_add_flat_result); 4677 __ bind(&non_ascii_string_add_flat_result);
4660 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 4678 // Both strings are ascii strings. As they are short they are both flat.
4661 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 4679 __ AllocateTwoByteString(rax, rbx, rdi, r8, r9, &call_runtime);
4662 __ and_(r9, Immediate(kStringEncodingMask)); 4680 // rax: result string
4663 __ j(not_zero, &string_add_runtime);
4664 // Both strings are two byte strings. As they are short they are both
4665 // flat.
4666 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
4667 // rcx: result string
4668 __ movq(rbx, rcx);
4669 // Locate first character of result. 4681 // Locate first character of result.
4670 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 4682 __ lea(rbx, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
4671 // Locate first character of first argument. 4683 // rcx: first char of first string
4672 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 4684 // rbx: first character of result
4673 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 4685 // r14: length of first string
4674 // rax: first char of first argument 4686 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false);
4675 // rbx: result string 4687 // rbx: next character of result
4676 // rcx: first character of result 4688 // rdx: first char of second string
4677 // rdx: second argument 4689 // r15: length of second string
4678 // rdi: length of first argument 4690 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false);
4679 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false);
4680 // Locate first character of second argument.
4681 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset));
4682 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
4683 // rbx: result string
4684 // rcx: next character of result
4685 // rdx: first char of second argument
4686 // rdi: length of second argument
4687 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
4688 __ movq(rax, rbx);
4689 __ IncrementCounter(counters->string_add_native(), 1); 4691 __ IncrementCounter(counters->string_add_native(), 1);
4690 __ ret(2 * kPointerSize); 4692 __ ret(2 * kPointerSize);
4691 4693
4692 // Just jump to runtime to add the two strings. 4694 // Just jump to runtime to add the two strings.
4693 __ bind(&string_add_runtime); 4695 __ bind(&call_runtime);
4694 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 4696 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
4695 4697
4696 if (call_builtin.is_linked()) { 4698 if (call_builtin.is_linked()) {
4697 __ bind(&call_builtin); 4699 __ bind(&call_builtin);
4698 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); 4700 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
4699 } 4701 }
4700 } 4702 }
4701 4703
4702 4704
4703 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, 4705 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
(...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after
6229 xmm0, 6231 xmm0,
6230 &slow_elements); 6232 &slow_elements);
6231 __ ret(0); 6233 __ ret(0);
6232 } 6234 }
6233 6235
6234 #undef __ 6236 #undef __
6235 6237
6236 } } // namespace v8::internal 6238 } } // namespace v8::internal
6237 6239
6238 #endif // V8_TARGET_ARCH_X64 6240 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698