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:
parent
76e69df735
commit
ab924c3d8a
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user