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; ...@@ -147,6 +147,9 @@ const int kPointerSizeLog2 = 2;
const intptr_t kIntptrSignBit = 0x80000000; const intptr_t kIntptrSignBit = 0x80000000;
#endif #endif
// Mask for the sign bit in a smi.
const intptr_t kSmiSignMask = kIntptrSignBit;
const int kObjectAlignmentBits = kPointerSizeLog2; const int kObjectAlignmentBits = kPointerSizeLog2;
const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits; const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
const intptr_t kObjectAlignmentMask = kObjectAlignment - 1; const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
......
This diff is collapsed.
...@@ -883,13 +883,42 @@ class GenericBinaryOpStub: public CodeStub { ...@@ -883,13 +883,42 @@ class GenericBinaryOpStub: public CodeStub {
}; };
class StringStubBase: public CodeStub { class StringHelper : public AllStatic {
public: 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 // 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 // be used in places where the number of characters is small and the
// additional setup and checking in GenerateCopyCharactersREP adds too much // additional setup and checking in GenerateCopyCharactersREP adds too much
// overhead. Copying of overlapping regions is not supported. // overhead. Copying of overlapping regions is not supported.
void GenerateCopyCharacters(MacroAssembler* masm, static void GenerateCopyCharacters(MacroAssembler* masm,
Register dest, Register dest,
Register src, Register src,
Register count, Register count,
...@@ -899,18 +928,18 @@ class StringStubBase: public CodeStub { ...@@ -899,18 +928,18 @@ class StringStubBase: public CodeStub {
// Generate code for copying characters using the rep movs instruction. // Generate code for copying characters using the rep movs instruction.
// Copies ecx characters from esi to edi. Copying of overlapping regions is // Copies ecx characters from esi to edi. Copying of overlapping regions is
// not supported. // not supported.
void GenerateCopyCharactersREP(MacroAssembler* masm, static void GenerateCopyCharactersREP(MacroAssembler* masm,
Register dest, // Must be edi. Register dest, // Must be edi.
Register src, // Must be esi. Register src, // Must be esi.
Register count, // Must be ecx. Register count, // Must be ecx.
Register scratch, // Neither of the above. Register scratch, // Neither of above.
bool ascii); bool ascii);
// Probe the symbol table for a two character string. If the string is // 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 // 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 // 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. // 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 c1,
Register c2, Register c2,
Register scratch1, Register scratch1,
...@@ -919,17 +948,20 @@ class StringStubBase: public CodeStub { ...@@ -919,17 +948,20 @@ class StringStubBase: public CodeStub {
Label* not_found); Label* not_found);
// Generate string hash. // Generate string hash.
void GenerateHashInit(MacroAssembler* masm, static void GenerateHashInit(MacroAssembler* masm,
Register hash, Register hash,
Register character, Register character,
Register scratch); Register scratch);
void GenerateHashAddCharacter(MacroAssembler* masm, static void GenerateHashAddCharacter(MacroAssembler* masm,
Register hash, Register hash,
Register character, Register character,
Register scratch); Register scratch);
void GenerateHashGetHash(MacroAssembler* masm, static void GenerateHashGetHash(MacroAssembler* masm,
Register hash, Register hash,
Register scratch); Register scratch);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
}; };
...@@ -940,7 +972,7 @@ enum StringAddFlags { ...@@ -940,7 +972,7 @@ enum StringAddFlags {
}; };
class StringAddStub: public StringStubBase { class StringAddStub: public CodeStub {
public: public:
explicit StringAddStub(StringAddFlags flags) { explicit StringAddStub(StringAddFlags flags) {
string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0); string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
...@@ -957,7 +989,7 @@ class StringAddStub: public StringStubBase { ...@@ -957,7 +989,7 @@ class StringAddStub: public StringStubBase {
}; };
class SubStringStub: public StringStubBase { class SubStringStub: public CodeStub {
public: public:
SubStringStub() {} SubStringStub() {}
...@@ -969,7 +1001,7 @@ class SubStringStub: public StringStubBase { ...@@ -969,7 +1001,7 @@ class SubStringStub: public StringStubBase {
}; };
class StringCompareStub: public StringStubBase { class StringCompareStub: public CodeStub {
public: public:
explicit StringCompareStub() { explicit StringCompareStub() {
} }
......
...@@ -491,39 +491,58 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -491,39 +491,58 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
void KeyedLoadIC::GenerateString(MacroAssembler* masm) { void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key (index)
// -- edx : receiver // -- edx : receiver
// -- esp[0] : return address // -- esp[0] : return address
// ----------------------------------- // -----------------------------------
Label miss, index_ok; Label miss;
Label not_positive_smi;
// Pop return address. Label slow_char_code;
// Performing the load early is better in the common case. Label got_char_code;
__ pop(ebx);
__ test(edx, Immediate(kSmiTagMask)); Register receiver = edx;
__ j(zero, &miss); Register index = eax;
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); Register code = ebx;
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); Register scratch = ecx;
__ test(ecx, Immediate(kIsNotStringMask));
__ j(not_zero, &miss); 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. // Check if key is a smi or a heap number.
__ test(eax, Immediate(kSmiTagMask)); __ bind(&not_positive_smi);
__ j(zero, &index_ok); ASSERT(kSmiTag == 0);
__ test(index, Immediate(kSmiTagMask));
__ j(zero, &slow_char_code);
__ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(ecx, Factory::heap_number_map()); __ cmp(ecx, Factory::heap_number_map());
__ j(not_equal, &miss); __ j(not_equal, &miss);
__ bind(&index_ok); // Push receiver and key on the stack (now that we know they are a
// Push receiver and key on the stack, and make a tail call. // string and a number), and call runtime.
__ push(edx); // receiver __ bind(&slow_char_code);
__ push(eax); // key __ EnterInternalFrame();
__ push(ebx); // return address __ push(receiver);
__ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); __ push(index);
__ CallRuntime(Runtime::kStringCharCodeAt, 1);
ASSERT(!code.is(eax));
__ mov(code, eax);
__ LeaveInternalFrame();
__ jmp(&got_char_code);
__ bind(&miss); __ bind(&miss);
__ push(ebx);
GenerateMiss(masm); 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