From ab924c3d8ad8fc3a5779b3f5b93d8b2ea3801154 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Thu, 1 Dec 2011 08:31:09 +0000 Subject: [PATCH] MIPS: Porting r10023 and r10054 to arm (pointer cache for external strings). Port r10059 (c32f98a9) Original commit message: BUG= TEST= Review URL: http://codereview.chromium.org/8746015 Patch from Daniel Kalmar . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10107 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/code-stubs-mips.cc | 76 +++----------------------- src/mips/codegen-mips.cc | 92 ++++++++++++++++++++++++++++++++ src/mips/codegen-mips.h | 15 ++++++ src/mips/lithium-codegen-mips.cc | 86 ++--------------------------- 4 files changed, 119 insertions(+), 150 deletions(-) diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index e7dda3fae..ae73f9d33 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -5288,77 +5288,14 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); __ Branch(index_out_of_range_, ls, t0, Operand(index_)); - // We need special handling for non-flat strings. - STATIC_ASSERT(kSeqStringTag == 0); - __ And(t0, result_, Operand(kStringRepresentationMask)); - __ Branch(&flat_string, eq, t0, Operand(zero_reg)); - - // Handle non-flat strings. - __ And(result_, result_, Operand(kStringRepresentationMask)); - STATIC_ASSERT(kConsStringTag < kExternalStringTag); - STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); - __ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag)); - __ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag)); - - // ConsString. - // Check whether the right hand side is the empty string (i.e. if - // this is really a flat string in a cons string). If that is not - // the case we would rather go to the runtime system now to flatten - // the string. - Label assure_seq_string; - __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); - __ LoadRoot(t0, Heap::kEmptyStringRootIndex); - __ Branch(&call_runtime_, ne, result_, Operand(t0)); - - // Get the first of the two parts. - __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); - __ jmp(&assure_seq_string); - - // SlicedString, unpack and add offset. - __ bind(&sliced_string); - __ lw(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset)); - __ Addu(index_, index_, result_); - __ lw(object_, FieldMemOperand(object_, SlicedString::kParentOffset)); - - // Assure that we are dealing with a sequential string. Go to runtime if not. - __ bind(&assure_seq_string); - __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); - __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); - // Check that parent is not an external string. Go to runtime otherwise. - // Note that if the original string is a cons or slice with an external - // string as underlying string, we pass that unpacked underlying string with - // the adjusted index to the runtime function. - STATIC_ASSERT(kSeqStringTag == 0); - - __ And(t0, result_, Operand(kStringRepresentationMask)); - __ Branch(&call_runtime_, ne, t0, Operand(zero_reg)); - - // Check for 1-byte or 2-byte string. - __ bind(&flat_string); - STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); - STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); - __ And(t0, result_, Operand(kStringEncodingMask)); - __ Branch(&ascii_string, ne, t0, Operand(zero_reg)); - - // 2-byte string. - // Load the 2-byte character code into the result register. We can - // add without shifting since the smi tag size is the log2 of the - // number of bytes in a two-byte character. - STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0); - __ Addu(index_, object_, Operand(index_)); - __ lhu(result_, FieldMemOperand(index_, SeqTwoByteString::kHeaderSize)); - __ Branch(&got_char_code); - - // ASCII string. - // Load the byte into the result register. - __ bind(&ascii_string); - - __ srl(t0, index_, kSmiTagSize); - __ Addu(index_, object_, t0); + __ sra(index_, index_, kSmiTagSize); - __ lbu(result_, FieldMemOperand(index_, SeqAsciiString::kHeaderSize)); + StringCharLoadGenerator::Generate(masm, + object_, + index_, + result_, + &call_runtime_); - __ bind(&got_char_code); __ sll(result_, result_, kSmiTagSize); __ bind(&exit_); } @@ -5407,6 +5344,7 @@ void StringCharCodeAtGenerator::GenerateSlow( // is too complex (e.g., when the string needs to be flattened). __ bind(&call_runtime_); call_helper.BeforeCall(masm); + __ sll(index_, index_, kSmiTagSize); __ Push(object_, index_); __ CallRuntime(Runtime::kStringCharCodeAt, 2); diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc index c94e0fa52..0b6838497 100644 --- a/src/mips/codegen-mips.cc +++ b/src/mips/codegen-mips.cc @@ -310,6 +310,98 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( __ pop(ra); } + +void StringCharLoadGenerator::Generate(MacroAssembler* masm, + Register string, + Register index, + Register result, + Label* call_runtime) { + // Fetch the instance type of the receiver into result register. + __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset)); + __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); + + // We need special handling for indirect strings. + Label check_sequential; + __ And(at, result, Operand(kIsIndirectStringMask)); + __ Branch(&check_sequential, eq, at, Operand(zero_reg)); + + // Dispatch on the indirect string shape: slice or cons. + Label cons_string; + __ And(at, result, Operand(kSlicedNotConsMask)); + __ Branch(&cons_string, eq, at, Operand(zero_reg)); + + // Handle slices. + Label indirect_string_loaded; + __ lw(result, FieldMemOperand(string, SlicedString::kOffsetOffset)); + __ sra(at, result, kSmiTagSize); + __ Addu(index, index, at); + __ lw(string, FieldMemOperand(string, SlicedString::kParentOffset)); + __ jmp(&indirect_string_loaded); + + // Handle cons strings. + // Check whether the right hand side is the empty string (i.e. if + // this is really a flat string in a cons string). If that is not + // the case we would rather go to the runtime system now to flatten + // the string. + __ bind(&cons_string); + __ lw(result, FieldMemOperand(string, ConsString::kSecondOffset)); + __ LoadRoot(at, Heap::kEmptyStringRootIndex); + __ Branch(call_runtime, ne, result, Operand(at)); + // Get the first of the two strings and load its instance type. + __ lw(string, FieldMemOperand(string, ConsString::kFirstOffset)); + + __ bind(&indirect_string_loaded); + __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset)); + __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); + + // Distinguish sequential and external strings. Only these two string + // representations can reach here (slices and flat cons strings have been + // reduced to the underlying sequential or external string). + Label external_string, check_encoding; + __ bind(&check_sequential); + STATIC_ASSERT(kSeqStringTag == 0); + __ And(at, result, Operand(kStringRepresentationMask)); + __ Branch(&external_string, ne, at, Operand(zero_reg)); + + // Prepare sequential strings + STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); + __ Addu(string, + string, + SeqTwoByteString::kHeaderSize - kHeapObjectTag); + __ jmp(&check_encoding); + + // Handle external strings. + __ bind(&external_string); + if (FLAG_debug_code) { + // Assert that we do not have a cons or slice (indirect strings) here. + // Sequential strings have already been ruled out. + __ And(at, result, Operand(kIsIndirectStringMask)); + __ Assert(eq, "external string expected, but not found", + at, Operand(zero_reg)); + } + // Rule out short external strings. + STATIC_CHECK(kShortExternalStringTag != 0); + __ And(at, result, Operand(kShortExternalStringMask)); + __ Branch(call_runtime, ne, at, Operand(zero_reg)); + __ lw(string, FieldMemOperand(string, ExternalString::kResourceDataOffset)); + + Label ascii, done; + __ bind(&check_encoding); + STATIC_ASSERT(kTwoByteStringTag == 0); + __ And(at, result, Operand(kStringEncodingMask)); + __ Branch(&ascii, ne, at, Operand(zero_reg)); + // Two-byte string. + __ sll(at, index, 1); + __ Addu(at, string, at); + __ lhu(result, MemOperand(at)); + __ jmp(&done); + __ bind(&ascii); + // Ascii string. + __ Addu(at, string, index); + __ lbu(result, MemOperand(at)); + __ bind(&done); +} + #undef __ } } // namespace v8::internal diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h index 4549509f3..e704c4f56 100644 --- a/src/mips/codegen-mips.h +++ b/src/mips/codegen-mips.h @@ -75,6 +75,21 @@ class CodeGenerator: public AstVisitor { }; +class StringCharLoadGenerator : public AllStatic { + public: + // Generates the code for handling different string types and loading the + // indexed character into |result|. We expect |index| as untagged input and + // |result| as untagged output. + static void Generate(MacroAssembler* masm, + Register string, + Register index, + Register result, + Label* call_runtime); + + private: + DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator); +}; + } } // namespace v8::internal #endif // V8_MIPS_CODEGEN_MIPS_H_ diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index c0879bbd9..32e7dc710 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -3520,89 +3520,13 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { LStringCharCodeAt* instr_; }; - Register temp = scratch1(); - Register string = ToRegister(instr->string()); - Register index = ToRegister(instr->index()); - Register result = ToRegister(instr->result()); DeferredStringCharCodeAt* deferred = new DeferredStringCharCodeAt(this, instr); - - // Fetch the instance type of the receiver into result register. - __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset)); - __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); - - // We need special handling for indirect strings. - Label check_sequential; - __ And(temp, result, kIsIndirectStringMask); - __ Branch(&check_sequential, eq, temp, Operand(zero_reg)); - - // Dispatch on the indirect string shape: slice or cons. - Label cons_string; - __ And(temp, result, kSlicedNotConsMask); - __ Branch(&cons_string, eq, temp, Operand(zero_reg)); - - // Handle slices. - Label indirect_string_loaded; - __ lw(result, FieldMemOperand(string, SlicedString::kOffsetOffset)); - __ sra(temp, result, kSmiTagSize); - __ addu(index, index, temp); - __ lw(string, FieldMemOperand(string, SlicedString::kParentOffset)); - __ jmp(&indirect_string_loaded); - - // Handle conses. - // Check whether the right hand side is the empty string (i.e. if - // this is really a flat string in a cons string). If that is not - // the case we would rather go to the runtime system now to flatten - // the string. - __ bind(&cons_string); - __ lw(result, FieldMemOperand(string, ConsString::kSecondOffset)); - __ LoadRoot(temp, Heap::kEmptyStringRootIndex); - __ Branch(deferred->entry(), ne, result, Operand(temp)); - // Get the first of the two strings and load its instance type. - __ lw(string, FieldMemOperand(string, ConsString::kFirstOffset)); - - __ bind(&indirect_string_loaded); - __ lw(result, FieldMemOperand(string, HeapObject::kMapOffset)); - __ lbu(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); - - // Check whether the string is sequential. The only non-sequential - // shapes we support have just been unwrapped above. - // Note that if the original string is a cons or slice with an external - // string as underlying string, we pass that unpacked underlying string with - // the adjusted index to the runtime function. - __ bind(&check_sequential); - STATIC_ASSERT(kSeqStringTag == 0); - __ And(temp, result, Operand(kStringRepresentationMask)); - __ Branch(deferred->entry(), ne, temp, Operand(zero_reg)); - - // Dispatch on the encoding: ASCII or two-byte. - Label ascii_string; - STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); - STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); - __ And(temp, result, Operand(kStringEncodingMask)); - __ Branch(&ascii_string, ne, temp, Operand(zero_reg)); - - // Two-byte string. - // Load the two-byte character code into the result register. - Label done; - __ Addu(result, - string, - Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); - __ sll(temp, index, 1); - __ Addu(result, result, temp); - __ lhu(result, MemOperand(result, 0)); - __ Branch(&done); - - // ASCII string. - // Load the byte into the result register. - __ bind(&ascii_string); - __ Addu(result, - string, - Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); - __ Addu(result, result, index); - __ lbu(result, MemOperand(result, 0)); - - __ bind(&done); + StringCharLoadGenerator::Generate(masm(), + ToRegister(instr->string()), + ToRegister(instr->index()), + ToRegister(instr->result()), + deferred->entry()); __ bind(deferred->exit()); } -- 2.34.1