From 626b61f9678e54c0a1552a448fb2a5c62b13cc36 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Thu, 15 Dec 2011 11:04:58 +0000 Subject: [PATCH] Porting r10252 to ARM (handle external strings in generated code when concatenating short strings). BUG= TEST= Review URL: http://codereview.chromium.org/8913010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10262 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 150 ++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 78 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index c110644676..209c48e2a0 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -6140,7 +6140,7 @@ void StringCompareStub::Generate(MacroAssembler* masm) { void StringAddStub::Generate(MacroAssembler* masm) { - Label string_add_runtime, call_builtin; + Label call_runtime, call_builtin; Builtins::JavaScript builtin_id = Builtins::ADD; Counters* counters = masm->isolate()->counters(); @@ -6155,7 +6155,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Make sure that both arguments are strings if not known in advance. if (flags_ == NO_STRING_ADD_FLAGS) { - __ JumpIfEitherSmi(r0, r1, &string_add_runtime); + __ JumpIfEitherSmi(r0, r1, &call_runtime); // Load instance types. __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); @@ -6165,7 +6165,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // If either is not a string, go to runtime. __ tst(r4, Operand(kIsNotStringMask)); __ tst(r5, Operand(kIsNotStringMask), eq); - __ b(ne, &string_add_runtime); + __ b(ne, &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. @@ -6234,7 +6234,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); } __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, - &string_add_runtime); + &call_runtime); // Get the two characters forming the sub string. __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); @@ -6256,7 +6256,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // halfword store instruction (which assumes that processor is // in a little endian mode) __ mov(r6, Operand(2)); - __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime); + __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); __ IncrementCounter(counters->string_add_native(), 1, r2, r3); __ add(sp, sp, Operand(2 * kPointerSize)); @@ -6271,7 +6271,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { ASSERT(IsPowerOf2(String::kMaxLength + 1)); // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. __ cmp(r6, Operand(String::kMaxLength + 1)); - __ b(hs, &string_add_runtime); + __ b(hs, &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. @@ -6289,7 +6289,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // Allocate an ASCII cons string. __ bind(&ascii_data); - __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime); + __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime); __ bind(&allocated); // Fill the fields of the cons string. __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); @@ -6314,11 +6314,13 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ b(eq, &ascii_data); // Allocate a two byte cons string. - __ AllocateTwoByteConsString(r7, r6, r4, r5, &string_add_runtime); + __ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime); __ jmp(&allocated); - // Handle creating a flat result. First check that both strings are - // sequential and that they have the same encoding. + // 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. // r0: first string // r1: second string // r2: length of first string @@ -6326,6 +6328,7 @@ void StringAddStub::Generate(MacroAssembler* masm) { // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) // r6: sum of lengths. + Label first_prepared, second_prepared; __ bind(&string_add_flat_result); if (flags_ != NO_STRING_ADD_FLAGS) { __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); @@ -6333,97 +6336,88 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); } - // Check that both strings are sequential. - STATIC_ASSERT(kSeqStringTag == 0); - __ tst(r4, Operand(kStringRepresentationMask)); - __ tst(r5, Operand(kStringRepresentationMask), eq); - __ b(ne, &string_add_runtime); - // Now check if both strings have the same encoding (ASCII/Two-byte). - // r0: first string. - // r1: second string. - // r2: length of first string. - // r3: length of second string. - // r6: sum of lengths.. - Label non_ascii_string_add_flat_result; - ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. + + // Check whether both strings have same encoding __ eor(r7, r4, Operand(r5)); __ tst(r7, Operand(kStringEncodingMask)); - __ b(ne, &string_add_runtime); - // And see if it's ASCII or two-byte. - __ tst(r4, Operand(kStringEncodingMask)); + __ b(ne, &call_runtime); + + STATIC_ASSERT(kSeqStringTag == 0); + __ tst(r4, Operand(kStringRepresentationMask)); + STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); + __ add(r7, + r0, + Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag), + LeaveCC, + eq); + __ b(eq, &first_prepared); + // External string: rule out short external string and load string resource. + STATIC_ASSERT(kShortExternalStringTag != 0); + __ tst(r4, Operand(kShortExternalStringMask)); + __ b(ne, &call_runtime); + __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset)); + __ bind(&first_prepared); + + STATIC_ASSERT(kSeqStringTag == 0); + __ tst(r5, Operand(kStringRepresentationMask)); + STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); + __ add(r1, + r1, + Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag), + LeaveCC, + eq); + __ b(eq, &second_prepared); + // External string: rule out short external string and load string resource. + STATIC_ASSERT(kShortExternalStringTag != 0); + __ tst(r5, Operand(kShortExternalStringMask)); + __ b(ne, &call_runtime); + __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset)); + __ bind(&second_prepared); + + Label non_ascii_string_add_flat_result; + // r7: first character of first string + // r1: first character of second string + // r2: length of first string. + // r3: length of second string. + // r6: sum of lengths. + // Both strings have the same encoding. + STATIC_ASSERT(kTwoByteStringTag == 0); + __ tst(r5, Operand(kStringEncodingMask)); __ b(eq, &non_ascii_string_add_flat_result); - // Both strings are sequential ASCII strings. We also know that they are - // short (since the sum of the lengths is less than kMinNonFlatLength). - // r6: length of resulting flat string - __ AllocateAsciiString(r7, r6, r4, r5, r9, &string_add_runtime); - // Locate first character of result. - __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); - // Locate first character of first argument. - __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); - // r0: first character of first string. - // r1: second string. + __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); + __ add(r6, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); + // r0: result string. + // r7: first character of first string. + // r1: first character of second string. // r2: length of first string. // r3: length of second string. // r6: first character of result. - // r7: result string. - StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, true); - - // Load second argument and locate first character. - __ add(r1, r1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); - // r1: first character of second string. - // r3: length of second string. + StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true); // r6: next character of result. - // r7: result string. StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); - __ mov(r0, Operand(r7)); __ IncrementCounter(counters->string_add_native(), 1, r2, r3); __ add(sp, sp, Operand(2 * kPointerSize)); __ Ret(); __ bind(&non_ascii_string_add_flat_result); - // Both strings are sequential two byte strings. - // r0: first string. - // r1: second string. - // r2: length of first string. - // r3: length of second string. - // r6: sum of length of strings. - __ AllocateTwoByteString(r7, r6, r4, r5, r9, &string_add_runtime); - // r0: first string. - // r1: second string. - // r2: length of first string. - // r3: length of second string. - // r7: result string. - - // Locate first character of result. - __ add(r6, r7, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); - // Locate first character of first argument. - __ add(r0, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); - - // r0: first character of first string. - // r1: second string. + __ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime); + __ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); + // r0: result string. + // r7: first character of first string. + // r1: first character of second string. // r2: length of first string. // r3: length of second string. // r6: first character of result. - // r7: result string. - StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, false); - - // Locate first character of second argument. - __ add(r1, r1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); - - // r1: first character of second string. - // r3: length of second string. - // r6: next character of result (after copy of first string). - // r7: result string. + StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); + // r6: next character of result. StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); - - __ mov(r0, Operand(r7)); __ IncrementCounter(counters->string_add_native(), 1, r2, r3); __ add(sp, sp, Operand(2 * kPointerSize)); __ Ret(); // 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()) {