Improve keyed loads on strings by using a new stub.
Instead of going through a runtime function for keyed loads on strings we invoke a separate specialized stub that assumes string as receiver type and the key to be a number. The stub calls a JS builtin function to return the corresponding one-character string. Review URL: http://codereview.chromium.org/521041 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3556 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
33079fb851
commit
903301248e
@ -544,6 +544,11 @@ static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
|
||||
KeyedLoadIC::GenerateString(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_ExternalByteArray(MacroAssembler* masm) {
|
||||
KeyedLoadIC::GenerateExternalArray(masm, kExternalByteArray);
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ namespace internal {
|
||||
V(KeyedLoadIC_Initialize, KEYED_LOAD_IC, UNINITIALIZED) \
|
||||
V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC) \
|
||||
V(KeyedLoadIC_Generic, KEYED_LOAD_IC, MEGAMORPHIC) \
|
||||
V(KeyedLoadIC_String, KEYED_LOAD_IC, MEGAMORPHIC) \
|
||||
V(KeyedLoadIC_ExternalByteArray, KEYED_LOAD_IC, MEGAMORPHIC) \
|
||||
V(KeyedLoadIC_ExternalUnsignedByteArray, KEYED_LOAD_IC, MEGAMORPHIC) \
|
||||
V(KeyedLoadIC_ExternalShortArray, KEYED_LOAD_IC, MEGAMORPHIC) \
|
||||
@ -147,7 +148,8 @@ namespace internal {
|
||||
V(STRING_ADD_LEFT, 1) \
|
||||
V(STRING_ADD_RIGHT, 1) \
|
||||
V(APPLY_PREPARE, 1) \
|
||||
V(APPLY_OVERFLOW, 1)
|
||||
V(APPLY_OVERFLOW, 1) \
|
||||
V(STRING_CHAR_AT, 1)
|
||||
|
||||
|
||||
class ObjectVisitor;
|
||||
|
@ -391,6 +391,48 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : key
|
||||
// -- esp[8] : receiver
|
||||
// -----------------------------------
|
||||
Label miss, index_ok;
|
||||
|
||||
// Pop return address.
|
||||
// Performing the load early is better in the common case.
|
||||
__ pop(eax);
|
||||
|
||||
__ mov(ebx, Operand(esp, 1 * kPointerSize));
|
||||
__ test(ebx, Immediate(kSmiTagMask));
|
||||
__ j(zero, &miss);
|
||||
__ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
|
||||
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
|
||||
__ test(ecx, Immediate(kIsNotStringMask));
|
||||
__ j(not_zero, &miss);
|
||||
|
||||
// Check if key is a smi or a heap number.
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
__ test(edx, Immediate(kSmiTagMask));
|
||||
__ j(zero, &index_ok);
|
||||
__ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
|
||||
__ cmp(ecx, Factory::heap_number_map());
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
__ bind(&index_ok);
|
||||
// Duplicate receiver and key since they are expected on the stack after
|
||||
// the KeyedLoadIC call.
|
||||
__ push(ebx); // receiver
|
||||
__ push(edx); // key
|
||||
__ push(eax); // return address
|
||||
__ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION);
|
||||
|
||||
__ bind(&miss);
|
||||
__ push(eax);
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
|
||||
ExternalArrayType array_type) {
|
||||
// ----------- S t a t e -------------
|
||||
|
@ -874,7 +874,9 @@ Object* KeyedLoadIC::Load(State state,
|
||||
|
||||
if (use_ic) {
|
||||
Code* stub = generic_stub();
|
||||
if (object->IsJSObject()) {
|
||||
if (object->IsString() && key->IsNumber()) {
|
||||
stub = string_stub();
|
||||
} else if (object->IsJSObject()) {
|
||||
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
||||
if (receiver->HasExternalArrayElements()) {
|
||||
stub = external_array_stub(receiver->GetElementsKind());
|
||||
|
4
src/ic.h
4
src/ic.h
@ -280,6 +280,7 @@ class KeyedLoadIC: public IC {
|
||||
static void GenerateInitialize(MacroAssembler* masm);
|
||||
static void GeneratePreMonomorphic(MacroAssembler* masm);
|
||||
static void GenerateGeneric(MacroAssembler* masm);
|
||||
static void GenerateString(MacroAssembler* masm);
|
||||
|
||||
// Generators for external array types. See objects.h.
|
||||
// These are similar to the generic IC; they optimize the case of
|
||||
@ -313,6 +314,9 @@ class KeyedLoadIC: public IC {
|
||||
static Code* pre_monomorphic_stub() {
|
||||
return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
|
||||
}
|
||||
static Code* string_stub() {
|
||||
return Builtins::builtin(Builtins::KeyedLoadIC_String);
|
||||
}
|
||||
static Code* external_array_stub(JSObject::ElementsKind elements_kind);
|
||||
|
||||
static void Clear(Address address, Code* target);
|
||||
|
@ -1384,6 +1384,17 @@ static Object* CharCodeAt(String* subject, Object* index) {
|
||||
}
|
||||
|
||||
|
||||
static Object* CharFromCode(Object* char_code) {
|
||||
uint32_t code;
|
||||
if (Array::IndexFromObject(char_code, &code)) {
|
||||
if (code <= 0xffff) {
|
||||
return Heap::LookupSingleCharacterStringFromCode(code);
|
||||
}
|
||||
}
|
||||
return Heap::empty_string();
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_StringCharCodeAt(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 2);
|
||||
@ -1394,16 +1405,17 @@ static Object* Runtime_StringCharCodeAt(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_StringCharAt(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 2);
|
||||
return CharFromCode(Runtime_StringCharCodeAt(args));
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_CharFromCode(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
uint32_t code;
|
||||
if (Array::IndexFromObject(args[0], &code)) {
|
||||
if (code <= 0xffff) {
|
||||
return Heap::LookupSingleCharacterStringFromCode(code);
|
||||
}
|
||||
}
|
||||
return Heap::empty_string();
|
||||
return CharFromCode(args[0]);
|
||||
}
|
||||
|
||||
// Forward declarations.
|
||||
|
@ -146,6 +146,7 @@ namespace internal {
|
||||
\
|
||||
/* Strings */ \
|
||||
F(StringCharCodeAt, 2, 1) \
|
||||
F(StringCharAt, 2, 1) \
|
||||
F(StringIndexOf, 3, 1) \
|
||||
F(StringLastIndexOf, 3, 1) \
|
||||
F(StringLocaleCompare, 2, 1) \
|
||||
|
@ -477,6 +477,17 @@ function TO_STRING() {
|
||||
}
|
||||
|
||||
|
||||
// Specialized version of String.charAt. It assumes string as
|
||||
// the receiver type and that the index is a number.
|
||||
function STRING_CHAR_AT(pos) {
|
||||
var char_code = %_FastCharCodeAt(this, pos);
|
||||
if (!%_IsSmi(char_code)) {
|
||||
return %StringCharAt(this, pos);
|
||||
}
|
||||
return %CharFromCode(char_code);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------
|
||||
- - - C o n v e r s i o n s - - -
|
||||
-------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user