Porting r10252 to x64 (handle external strings in generated code when concatenating short strings).
Review URL: http://codereview.chromium.org/8909004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10261 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d1e762d782
commit
4ed4a7a652
@ -5647,8 +5647,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ test_b(ecx, kStringRepresentationMask);
|
||||
__ j(zero, &first_is_sequential, Label::kNear);
|
||||
// Rule out short external string and prepare it so that offset-wise, it
|
||||
// looks like a sequential string.
|
||||
// Rule out short external string and load string resource.
|
||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||
__ test_b(ecx, kShortExternalStringMask);
|
||||
__ j(not_zero, &call_runtime);
|
||||
@ -5669,8 +5668,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ test_b(edi, kStringRepresentationMask);
|
||||
__ j(zero, &second_is_sequential, Label::kNear);
|
||||
// Rule out short external string and prepare it so that offset-wise, it
|
||||
// looks like a sequential string.
|
||||
// Rule out short external string and load string resource.
|
||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||
__ test_b(edi, kShortExternalStringMask);
|
||||
__ j(not_zero, &call_runtime);
|
||||
@ -5736,8 +5734,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
// eax: result string
|
||||
__ mov(ecx, eax);
|
||||
// Locate first character of result.
|
||||
__ add(ecx,
|
||||
Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
__ add(ecx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
// Load second argument's length and first character location. Account for
|
||||
// values currently on the stack when fetching arguments from it.
|
||||
__ mov(edx, Operand(esp, 4 * kPointerSize));
|
||||
|
@ -4434,7 +4434,7 @@ void StringCharAtGenerator::GenerateSlow(
|
||||
|
||||
|
||||
void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
Label string_add_runtime, call_builtin;
|
||||
Label call_runtime, call_builtin;
|
||||
Builtins::JavaScript builtin_id = Builtins::ADD;
|
||||
|
||||
// Load the two arguments.
|
||||
@ -4443,14 +4443,14 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Make sure that both arguments are strings if not known in advance.
|
||||
if (flags_ == NO_STRING_ADD_FLAGS) {
|
||||
__ JumpIfSmi(rax, &string_add_runtime);
|
||||
__ JumpIfSmi(rax, &call_runtime);
|
||||
__ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
|
||||
__ j(above_equal, &string_add_runtime);
|
||||
__ j(above_equal, &call_runtime);
|
||||
|
||||
// First argument is a a string, test second.
|
||||
__ JumpIfSmi(rdx, &string_add_runtime);
|
||||
__ JumpIfSmi(rdx, &call_runtime);
|
||||
__ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
|
||||
__ j(above_equal, &string_add_runtime);
|
||||
__ j(above_equal, &call_runtime);
|
||||
} else {
|
||||
// Here at least one of the arguments is definitely a string.
|
||||
// We convert the one that is not known to be a string.
|
||||
@ -4518,7 +4518,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Check that both strings are non-external ascii strings.
|
||||
__ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
|
||||
&string_add_runtime);
|
||||
&call_runtime);
|
||||
|
||||
// Get the two characters forming the sub string.
|
||||
__ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
|
||||
@ -4533,8 +4533,18 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ ret(2 * kPointerSize);
|
||||
|
||||
__ bind(&make_two_character_string);
|
||||
__ Set(rbx, 2);
|
||||
__ jmp(&make_flat_ascii_string);
|
||||
__ Set(rdi, 2);
|
||||
__ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime);
|
||||
// rbx - first byte: first character
|
||||
// rbx - second byte: *maybe* second character
|
||||
// Make sure that the second byte of rbx contains the second character.
|
||||
__ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
|
||||
__ shll(rcx, Immediate(kBitsPerByte));
|
||||
__ orl(rbx, rcx);
|
||||
// Write both characters to the new string.
|
||||
__ movw(FieldOperand(rax, SeqAsciiString::kHeaderSize), rbx);
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
__ ret(2 * kPointerSize);
|
||||
|
||||
__ bind(&longer_than_two);
|
||||
// Check if resulting string will be flat.
|
||||
@ -4543,7 +4553,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
// Handle exceptionally long strings in the runtime system.
|
||||
STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
|
||||
__ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
|
||||
__ j(above, &string_add_runtime);
|
||||
__ j(above, &call_runtime);
|
||||
|
||||
// If result is not supposed to be flat, allocate a cons string object. If
|
||||
// both strings are ascii the result is an ascii cons string.
|
||||
@ -4561,7 +4571,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ j(zero, &non_ascii);
|
||||
__ bind(&ascii_data);
|
||||
// Allocate an acsii cons string.
|
||||
__ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime);
|
||||
__ AllocateAsciiConsString(rcx, rdi, no_reg, &call_runtime);
|
||||
__ bind(&allocated);
|
||||
// Fill the fields of the cons string.
|
||||
__ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
|
||||
@ -4586,111 +4596,103 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
|
||||
__ j(equal, &ascii_data);
|
||||
// Allocate a two byte cons string.
|
||||
__ AllocateTwoByteConsString(rcx, rdi, no_reg, &string_add_runtime);
|
||||
__ AllocateTwoByteConsString(rcx, rdi, no_reg, &call_runtime);
|
||||
__ jmp(&allocated);
|
||||
|
||||
// Handle creating a flat result. First check that both strings are not
|
||||
// external strings.
|
||||
// We cannot encounter sliced strings or cons strings here since:
|
||||
STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
|
||||
// Handle creating a flat result from either external or sequential strings.
|
||||
// Locate the first characters' locations.
|
||||
// rax: first string
|
||||
// rbx: length of resulting flat string as smi
|
||||
// rdx: second string
|
||||
// r8: instance type of first string
|
||||
// r9: instance type of first string
|
||||
Label first_prepared, second_prepared;
|
||||
Label first_is_sequential, second_is_sequential;
|
||||
__ bind(&string_add_flat_result);
|
||||
__ SmiToInteger32(rbx, rbx);
|
||||
__ movl(rcx, r8);
|
||||
__ and_(rcx, Immediate(kStringRepresentationMask));
|
||||
__ cmpl(rcx, Immediate(kExternalStringTag));
|
||||
__ j(equal, &string_add_runtime);
|
||||
__ movl(rcx, r9);
|
||||
__ and_(rcx, Immediate(kStringRepresentationMask));
|
||||
__ cmpl(rcx, Immediate(kExternalStringTag));
|
||||
__ j(equal, &string_add_runtime);
|
||||
// We cannot encounter sliced strings here since:
|
||||
STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
|
||||
// Now check if both strings are ascii strings.
|
||||
// rax: first string
|
||||
// rbx: length of resulting flat string
|
||||
// rdx: second string
|
||||
// r8: instance type of first string
|
||||
// r9: instance type of second string
|
||||
|
||||
__ SmiToInteger32(r14, FieldOperand(rax, SeqString::kLengthOffset));
|
||||
// r14: length of first string
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(r8, Immediate(kStringRepresentationMask));
|
||||
__ j(zero, &first_is_sequential, Label::kNear);
|
||||
// Rule out short external string and load string resource.
|
||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||
__ testb(r8, Immediate(kShortExternalStringMask));
|
||||
__ j(not_zero, &call_runtime);
|
||||
__ movq(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset));
|
||||
__ jmp(&first_prepared, Label::kNear);
|
||||
__ bind(&first_is_sequential);
|
||||
STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
|
||||
__ lea(rcx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
|
||||
__ bind(&first_prepared);
|
||||
|
||||
// Check whether both strings have same encoding.
|
||||
__ xorl(r8, r9);
|
||||
__ testb(r8, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &call_runtime);
|
||||
|
||||
__ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset));
|
||||
// r15: length of second string
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(r9, Immediate(kStringRepresentationMask));
|
||||
__ j(zero, &second_is_sequential, Label::kNear);
|
||||
// Rule out short external string and load string resource.
|
||||
STATIC_ASSERT(kShortExternalStringTag != 0);
|
||||
__ testb(r9, Immediate(kShortExternalStringMask));
|
||||
__ j(not_zero, &call_runtime);
|
||||
__ movq(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset));
|
||||
__ jmp(&second_prepared, Label::kNear);
|
||||
__ bind(&second_is_sequential);
|
||||
STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
|
||||
__ lea(rdx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
|
||||
__ bind(&second_prepared);
|
||||
|
||||
Label non_ascii_string_add_flat_result;
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ testl(r8, Immediate(kStringEncodingMask));
|
||||
// r9: instance type of second string
|
||||
// First string and second string have the same encoding.
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
__ SmiToInteger32(rbx, rbx);
|
||||
__ testb(r9, Immediate(kStringEncodingMask));
|
||||
__ j(zero, &non_ascii_string_add_flat_result);
|
||||
__ testl(r9, Immediate(kStringEncodingMask));
|
||||
__ j(zero, &string_add_runtime);
|
||||
|
||||
__ bind(&make_flat_ascii_string);
|
||||
// Both strings are ascii strings. As they are short they are both flat.
|
||||
__ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
|
||||
// rcx: result string
|
||||
__ movq(rbx, rcx);
|
||||
__ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime);
|
||||
// rax: result string
|
||||
// Locate first character of result.
|
||||
__ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
||||
// Locate first character of first argument
|
||||
__ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
|
||||
__ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
||||
// rax: first char of first argument
|
||||
// rbx: result string
|
||||
// rcx: first character of result
|
||||
// rdx: second string
|
||||
// rdi: length of first argument
|
||||
StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true);
|
||||
// Locate first character of second argument.
|
||||
__ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset));
|
||||
__ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
||||
// rbx: result string
|
||||
// rcx: next character of result
|
||||
// rdx: first char of second argument
|
||||
// rdi: length of second argument
|
||||
StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
|
||||
__ movq(rax, rbx);
|
||||
__ lea(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
|
||||
// rcx: first char of first string
|
||||
// rbx: first character of result
|
||||
// r14: length of first string
|
||||
StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true);
|
||||
// rbx: next character of result
|
||||
// rdx: first char of second string
|
||||
// r15: length of second string
|
||||
StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true);
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
__ ret(2 * kPointerSize);
|
||||
|
||||
// Handle creating a flat two byte result.
|
||||
// rax: first string - known to be two byte
|
||||
// rbx: length of resulting flat string
|
||||
// rdx: second string
|
||||
// r8: instance type of first string
|
||||
// r9: instance type of first string
|
||||
__ bind(&non_ascii_string_add_flat_result);
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ and_(r9, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &string_add_runtime);
|
||||
// Both strings are two byte strings. As they are short they are both
|
||||
// flat.
|
||||
__ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
|
||||
// rcx: result string
|
||||
__ movq(rbx, rcx);
|
||||
// Both strings are ascii strings. As they are short they are both flat.
|
||||
__ AllocateTwoByteString(rax, rbx, rdi, r8, r9, &call_runtime);
|
||||
// rax: result string
|
||||
// Locate first character of result.
|
||||
__ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
// Locate first character of first argument.
|
||||
__ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
|
||||
__ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
// rax: first char of first argument
|
||||
// rbx: result string
|
||||
// rcx: first character of result
|
||||
// rdx: second argument
|
||||
// rdi: length of first argument
|
||||
StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false);
|
||||
// Locate first character of second argument.
|
||||
__ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset));
|
||||
__ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
// rbx: result string
|
||||
// rcx: next character of result
|
||||
// rdx: first char of second argument
|
||||
// rdi: length of second argument
|
||||
StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
|
||||
__ movq(rax, rbx);
|
||||
__ lea(rbx, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
|
||||
// rcx: first char of first string
|
||||
// rbx: first character of result
|
||||
// r14: length of first string
|
||||
StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false);
|
||||
// rbx: next character of result
|
||||
// rdx: first char of second string
|
||||
// r15: length of second string
|
||||
StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false);
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
__ ret(2 * kPointerSize);
|
||||
|
||||
// Just jump to runtime to add the two strings.
|
||||
__ bind(&string_add_runtime);
|
||||
__ bind(&call_runtime);
|
||||
__ TailCallRuntime(Runtime::kStringAdd, 2, 1);
|
||||
|
||||
if (call_builtin.is_linked()) {
|
||||
|
Loading…
Reference in New Issue
Block a user