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 <kalmard@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10107 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2011-12-01 08:31:09 +00:00
parent 76e69df735
commit ab924c3d8a
4 changed files with 119 additions and 150 deletions

View File

@ -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));
__ sra(index_, index_, kSmiTagSize);
// 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));
StringCharLoadGenerator::Generate(masm,
object_,
index_,
result_,
&call_runtime_);
// 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);
__ lbu(result_, FieldMemOperand(index_, SeqAsciiString::kHeaderSize));
__ 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);

View File

@ -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

View File

@ -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_

View File

@ -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());
}