From 780934e17f2df2135b2913aaf610ea1c5e91a436 Mon Sep 17 00:00:00 2001 From: "vitalyr@chromium.org" Date: Wed, 1 Sep 2010 17:20:36 +0000 Subject: [PATCH] ia32 StringAddStub: fast two character case. Review URL: http://codereview.chromium.org/3327001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5397 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/code-stubs-ia32.cc | 37 +++++++++++++++++++++++++++++-------- src/ia32/code-stubs-ia32.h | 13 +++++++++---- src/ia32/macro-assembler-ia32.cc | 25 +++++++++++++++++++++++++ src/ia32/macro-assembler-ia32.h | 5 +++++ src/v8-counters.h | 1 + 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 8106886..d735419 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -3828,21 +3828,41 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &string_add_runtime); - // Get the two characters forming the sub string. + // Get the two characters forming the new string. __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); // Try to lookup two character string in symbol table. If it is not found // just allocate a new one. - Label make_two_character_string, make_flat_ascii_string; + Label make_two_character_string, make_two_character_string_no_reload; StringHelper::GenerateTwoCharacterSymbolTableProbe( - masm, ebx, ecx, eax, edx, edi, &make_two_character_string); + masm, ebx, ecx, eax, edx, edi, + &make_two_character_string_no_reload, &make_two_character_string); __ IncrementCounter(&Counters::string_add_native, 1); __ ret(2 * kPointerSize); + // Allocate a two character string. __ bind(&make_two_character_string); - __ Set(ebx, Immediate(Smi::FromInt(2))); - __ jmp(&make_flat_ascii_string); + // Reload the arguments. + __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. + __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. + // Get the two characters forming the new string. + __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); + __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); + __ bind(&make_two_character_string_no_reload); + __ IncrementCounter(&Counters::string_add_make_two_char, 1); + __ AllocateAsciiString(eax, // Result. + 2, // Length. + edi, // Scratch 1. + edx, // Scratch 2. + &string_add_runtime); + // Pack both characters in ebx. + __ shl(ecx, kBitsPerByte); + __ or_(ebx, Operand(ecx)); + // Set the characters in the new string. + __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx); + __ IncrementCounter(&Counters::string_add_native, 1); + __ ret(2 * kPointerSize); __ bind(&longer_than_two); // Check if resulting string will be flat. @@ -3921,7 +3941,6 @@ void StringAddStub::Generate(MacroAssembler* masm) { __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); __ j(zero, &string_add_runtime); - __ bind(&make_flat_ascii_string); // Both strings are ascii strings. As they are short they are both flat. // ebx: length of resulting flat string as a smi __ SmiUntag(ebx); @@ -4092,6 +4111,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3, + Label* not_probed, Label* not_found) { // Register scratch3 is the general scratch register in this function. Register scratch = scratch3; @@ -4106,7 +4126,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, __ mov(scratch, c2); __ sub(Operand(scratch), Immediate(static_cast('0'))); __ cmp(Operand(scratch), Immediate(static_cast('9' - '0'))); - __ j(below_equal, not_found); + __ j(below_equal, not_probed); __ bind(¬_array_index); // Calculate the two character string hash. @@ -4320,7 +4340,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { // Try to lookup two character string in symbol table. Label make_two_character_string; StringHelper::GenerateTwoCharacterSymbolTableProbe( - masm, ebx, ecx, eax, edx, edi, &make_two_character_string); + masm, ebx, ecx, eax, edx, edi, + &make_two_character_string, &make_two_character_string); __ ret(3 * kPointerSize); __ bind(&make_two_character_string); diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index acf4a6f..4eac9a9 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -234,16 +234,21 @@ class StringHelper : public AllStatic { 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. + // Probe the symbol table for a two character string. If the string + // requires non-standard hashing a jump to the label not_probed is + // performed and registers c1 and c2 are preserved. In all other + // cases they are clobbered. 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. static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, Register c1, Register c2, Register scratch1, Register scratch2, Register scratch3, + Label* not_probed, Label* not_found); // Generate string hash. diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index c215142..87e25d7 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -782,6 +782,31 @@ void MacroAssembler::AllocateAsciiString(Register result, } +void MacroAssembler::AllocateAsciiString(Register result, + int length, + Register scratch1, + Register scratch2, + Label* gc_required) { + ASSERT(length > 0); + + // Allocate ascii string in new space. + AllocateInNewSpace(SeqAsciiString::SizeFor(length), + result, + scratch1, + scratch2, + gc_required, + TAG_OBJECT); + + // Set the map, length and hash field. + mov(FieldOperand(result, HeapObject::kMapOffset), + Immediate(Factory::ascii_string_map())); + mov(FieldOperand(result, String::kLengthOffset), + Immediate(Smi::FromInt(length))); + mov(FieldOperand(result, String::kHashFieldOffset), + Immediate(String::kEmptyHashField)); +} + + void MacroAssembler::AllocateConsString(Register result, Register scratch1, Register scratch2, diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 5e850c0..a7534cb 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -356,6 +356,11 @@ class MacroAssembler: public Assembler { Register scratch2, Register scratch3, Label* gc_required); + void AllocateAsciiString(Register result, + int length, + Register scratch1, + Register scratch2, + Label* gc_required); // Allocate a raw cons string object. Only the map field of the result is // initialized. diff --git a/src/v8-counters.h b/src/v8-counters.h index b8b3d9f..af657f1 100644 --- a/src/v8-counters.h +++ b/src/v8-counters.h @@ -203,6 +203,7 @@ namespace internal { SC(string_add_runtime_ext_to_ascii, V8.StringAddRuntimeExtToAscii) \ SC(sub_string_runtime, V8.SubStringRuntime) \ SC(sub_string_native, V8.SubStringNative) \ + SC(string_add_make_two_char, V8.StringAddMakeTwoChar) \ SC(string_compare_native, V8.StringCompareNative) \ SC(string_compare_runtime, V8.StringCompareRuntime) \ SC(regexp_entry_runtime, V8.RegExpEntryRuntime) \ -- 2.7.4