Commit e504873d authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Inline fast cases in string keyed load IC.

String keyed load used to call STRING_CHAR_AT builtin that performs
two steps (get a char code, construct a one-char string from the
code), both of which have fast cases implemented as inline runtime
functions. In this chage most of the code from these functions is
extracted to a set of common generator functions in StringStubBase and
the fast cases are grouped together in the IC code.

Review URL: http://codereview.chromium.org/1539039

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4444 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e1b3b92a
......@@ -147,6 +147,9 @@ const int kPointerSizeLog2 = 2;
const intptr_t kIntptrSignBit = 0x80000000;
#endif
// Mask for the sign bit in a smi.
const intptr_t kSmiSignMask = kIntptrSignBit;
const int kObjectAlignmentBits = kPointerSizeLog2;
const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
......
This diff is collapsed.
......@@ -883,13 +883,42 @@ class GenericBinaryOpStub: public CodeStub {
};
class StringStubBase: public CodeStub {
class StringHelper : public AllStatic {
public:
// Generates fast code for getting a char code out of a string
// object at the given index. May bail out for three reasons (in the
// listed order):
// * Receiver is not a string (receiver_not_string label).
// * Index is not a positive smi (index_not_positive_smi label).
// * Some other reason (slow_case label). In this case it's
// guaranteed that the above conditions are not violated,
// e.g. it's safe to assume the receiver is a string and the
// index is a positive smi.
// When successful, object, index, and scratch are clobbered.
// Otherwise, scratch and result are clobbered.
static void GenerateFastCharCodeAt(MacroAssembler* masm,
Register object,
Register index,
Register scratch,
Register result,
Label* receiver_not_string,
Label* index_not_positive_smi,
Label* slow_case);
// Generates code for creating a one-char string from the given char
// code. May do a runtime call, so any register can be clobbered
// and, if the given invoke flag specifies a call, an internal frame
// is required. In tail call mode the result must be eax register.
static void GenerateCharFromCode(MacroAssembler* masm,
Register code,
Register result,
InvokeFlag flag);
// Generate code for copying characters using a simple loop. This should only
// be used in places where the number of characters is small and the
// additional setup and checking in GenerateCopyCharactersREP adds too much
// overhead. Copying of overlapping regions is not supported.
void GenerateCopyCharacters(MacroAssembler* masm,
static void GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
Register count,
......@@ -899,18 +928,18 @@ class StringStubBase: public CodeStub {
// Generate code for copying characters using the rep movs instruction.
// Copies ecx characters from esi to edi. Copying of overlapping regions is
// not supported.
void GenerateCopyCharactersREP(MacroAssembler* masm,
static void GenerateCopyCharactersREP(MacroAssembler* masm,
Register dest, // Must be edi.
Register src, // Must be esi.
Register count, // Must be ecx.
Register scratch, // Neither of the above.
Register scratch, // Neither of above.
bool ascii);
// Probe the symbol table for a two character string. If the string is
// not found by probing a jump to the label not_found is performed. This jump
// does not guarantee that the string is not in the symbol table. If the
// string is found the code falls through with the string in register eax.
void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
Register c1,
Register c2,
Register scratch1,
......@@ -919,17 +948,20 @@ class StringStubBase: public CodeStub {
Label* not_found);
// Generate string hash.
void GenerateHashInit(MacroAssembler* masm,
static void GenerateHashInit(MacroAssembler* masm,
Register hash,
Register character,
Register scratch);
void GenerateHashAddCharacter(MacroAssembler* masm,
static void GenerateHashAddCharacter(MacroAssembler* masm,
Register hash,
Register character,
Register scratch);
void GenerateHashGetHash(MacroAssembler* masm,
static void GenerateHashGetHash(MacroAssembler* masm,
Register hash,
Register scratch);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
};
......@@ -940,7 +972,7 @@ enum StringAddFlags {
};
class StringAddStub: public StringStubBase {
class StringAddStub: public CodeStub {
public:
explicit StringAddStub(StringAddFlags flags) {
string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
......@@ -957,7 +989,7 @@ class StringAddStub: public StringStubBase {
};
class SubStringStub: public StringStubBase {
class SubStringStub: public CodeStub {
public:
SubStringStub() {}
......@@ -969,7 +1001,7 @@ class SubStringStub: public StringStubBase {
};
class StringCompareStub: public StringStubBase {
class StringCompareStub: public CodeStub {
public:
explicit StringCompareStub() {
}
......
......@@ -491,39 +491,58 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : key
// -- eax : key (index)
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss, index_ok;
// Pop return address.
// Performing the load early is better in the common case.
__ pop(ebx);
Label miss;
Label not_positive_smi;
Label slow_char_code;
Label got_char_code;
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, &miss);
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
__ test(ecx, Immediate(kIsNotStringMask));
__ j(not_zero, &miss);
Register receiver = edx;
Register index = eax;
Register code = ebx;
Register scratch = ecx;
StringHelper::GenerateFastCharCodeAt(masm,
receiver,
index,
scratch,
code,
&miss, // When not a string.
&not_positive_smi,
&slow_char_code);
// If we didn't bail out, code register contains smi tagged char
// code.
__ bind(&got_char_code);
StringHelper::GenerateCharFromCode(masm, code, eax, JUMP_FUNCTION);
#ifdef DEBUG
__ Abort("Unexpected fall-through from char from code tail call");
#endif
// Check if key is a smi or a heap number.
__ test(eax, Immediate(kSmiTagMask));
__ j(zero, &index_ok);
__ bind(&not_positive_smi);
ASSERT(kSmiTag == 0);
__ test(index, Immediate(kSmiTagMask));
__ j(zero, &slow_char_code);
__ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(ecx, Factory::heap_number_map());
__ j(not_equal, &miss);
__ bind(&index_ok);
// Push receiver and key on the stack, and make a tail call.
__ push(edx); // receiver
__ push(eax); // key
__ push(ebx); // return address
__ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION);
// Push receiver and key on the stack (now that we know they are a
// string and a number), and call runtime.
__ bind(&slow_char_code);
__ EnterInternalFrame();
__ push(receiver);
__ push(index);
__ CallRuntime(Runtime::kStringCharCodeAt, 1);
ASSERT(!code.is(eax));
__ mov(code, eax);
__ LeaveInternalFrame();
__ jmp(&got_char_code);
__ bind(&miss);
__ push(ebx);
GenerateMiss(masm);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment