Revision: 3556
Author: [email protected]
Date: Thu Jan 7 02:25:20 2010
Log: 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
http://code.google.com/p/v8/source/detail?r=3556
Modified:
/branches/bleeding_edge/src/builtins.cc
/branches/bleeding_edge/src/builtins.h
/branches/bleeding_edge/src/ia32/ic-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/ic.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/runtime.js
=======================================
--- /branches/bleeding_edge/src/builtins.cc Mon Nov 23 06:43:00 2009
+++ /branches/bleeding_edge/src/builtins.cc Thu Jan 7 02:25:20 2010
@@ -542,6 +542,11 @@
static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
KeyedLoadIC::GenerateGeneric(masm);
}
+
+
+static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
+ KeyedLoadIC::GenerateString(masm);
+}
static void Generate_KeyedLoadIC_ExternalByteArray(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/builtins.h Tue Oct 20 08:26:17 2009
+++ /branches/bleeding_edge/src/builtins.h Thu Jan 7 02:25:20 2010
@@ -74,6 +74,7 @@
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 @@
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;
=======================================
--- /branches/bleeding_edge/src/ia32/ic-ia32.cc Thu Dec 17 02:23:20 2009
+++ /branches/bleeding_edge/src/ia32/ic-ia32.cc Thu Jan 7 02:25:20 2010
@@ -389,6 +389,48 @@
__ shr(eax, String::kHashShift);
__ jmp(&index_int);
}
+
+
+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,
=======================================
--- /branches/bleeding_edge/src/ic.cc Thu Dec 17 02:23:20 2009
+++ /branches/bleeding_edge/src/ic.cc Thu Jan 7 02:25:20 2010
@@ -874,7 +874,9 @@
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());
=======================================
--- /branches/bleeding_edge/src/ic.h Thu Dec 17 02:23:20 2009
+++ /branches/bleeding_edge/src/ic.h Thu Jan 7 02:25:20 2010
@@ -280,6 +280,7 @@
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 @@
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);
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu Jan 7 01:59:37 2010
+++ /branches/bleeding_edge/src/runtime.cc Thu Jan 7 02:25:20 2010
@@ -1382,6 +1382,17 @@
}
return Smi::FromInt(subject->Get(i));
}
+
+
+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) {
@@ -1392,18 +1403,19 @@
Object* index = args[1];
return CharCodeAt(subject, index);
}
+
+
+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.
=======================================
--- /branches/bleeding_edge/src/runtime.h Wed Jan 6 06:40:21 2010
+++ /branches/bleeding_edge/src/runtime.h Thu Jan 7 02:25:20 2010
@@ -146,6 +146,7 @@
\
/* Strings */ \
F(StringCharCodeAt, 2, 1) \
+ F(StringCharAt, 2, 1) \
F(StringIndexOf, 3, 1) \
F(StringLastIndexOf, 3, 1) \
F(StringLocaleCompare, 2, 1) \
=======================================
--- /branches/bleeding_edge/src/runtime.js Thu Jan 7 01:40:50 2010
+++ /branches/bleeding_edge/src/runtime.js Thu Jan 7 02:25:20 2010
@@ -475,6 +475,17 @@
function TO_STRING() {
return %ToString(this);
}
+
+
+// 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);
+}
/* -------------------------------------
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev