Optimize string plus smi
When adding a string with a smi value the number string cache is checked in generated code. If the there is a string value in the number string cache the resulting string is produced in generated code. Review URL: http://codereview.chromium.org/596082 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3843 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
46020b3169
commit
e60efbff28
@ -231,7 +231,8 @@ enum ScaleFactor {
|
||||
times_8 = 3,
|
||||
times_int_size = times_4,
|
||||
times_half_pointer_size = times_2,
|
||||
times_pointer_size = times_4
|
||||
times_pointer_size = times_4,
|
||||
times_twice_pointer_size = times_8
|
||||
};
|
||||
|
||||
|
||||
|
@ -7639,7 +7639,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
switch (op_) {
|
||||
case Token::ADD: {
|
||||
// Test for string arguments before calling runtime.
|
||||
Label not_strings, not_string1, string1;
|
||||
Label not_strings, not_string1, string1, string1_smi2;
|
||||
Result answer;
|
||||
__ test(edx, Immediate(kSmiTagMask));
|
||||
__ j(zero, ¬_string1);
|
||||
@ -7648,15 +7648,56 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// First argument is a string, test second.
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(zero, &string1);
|
||||
__ j(zero, &string1_smi2);
|
||||
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
|
||||
__ j(above_equal, &string1);
|
||||
|
||||
// First and second argument are strings. Jump to the string add stub.
|
||||
StringAddStub stub(NO_STRING_CHECK_IN_STUB);
|
||||
__ TailCallStub(&stub);
|
||||
StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
|
||||
__ TailCallStub(&string_add_stub);
|
||||
|
||||
__ bind(&string1_smi2);
|
||||
// First argument is a string, second is a smi. Try to lookup the number
|
||||
// string for the smi in the number string cache.
|
||||
// Load the number string cache.
|
||||
ExternalReference roots_address = ExternalReference::roots_address();
|
||||
__ mov(ecx, Immediate(Heap::kNumberStringCacheRootIndex));
|
||||
__ mov(ebx,
|
||||
Operand::StaticArray(ecx, times_pointer_size, roots_address));
|
||||
// Make the hash mask from the length of the number string cache. It
|
||||
// contains two elements (number and string) for each cache entry.
|
||||
__ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
|
||||
__ shr(ecx, 1); // Divide length by two (length is not a smi).
|
||||
__ sub(Operand(ecx), Immediate(1)); // Make mask.
|
||||
// Calculate the entry in the number string cache. The hash value in the
|
||||
// number string cache for smis is just the smi value.
|
||||
__ mov(edi, eax);
|
||||
__ SmiUntag(edi);
|
||||
__ and_(edi, Operand(ecx));
|
||||
// Check if the entry is the smi we are looking for.
|
||||
__ cmp(eax,
|
||||
FieldOperand(ebx,
|
||||
edi,
|
||||
times_twice_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
__ IncrementCounter(equal, &Counters::string_plus_smi_hit, 1);
|
||||
__ IncrementCounter(not_equal, &Counters::string_plus_smi_miss, 1);
|
||||
__ j(not_equal, &string1);
|
||||
|
||||
// Get the string from the cache and call the string add stub to make the
|
||||
// result.
|
||||
__ mov(edi,
|
||||
FieldOperand(ebx,
|
||||
edi,
|
||||
times_twice_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ EnterInternalFrame();
|
||||
__ push(edx); // Original first argument.
|
||||
__ push(edi); // Number to string result for second argument.
|
||||
__ CallStub(&string_add_stub);
|
||||
__ LeaveInternalFrame();
|
||||
__ ret(2 * kPointerSize);
|
||||
|
||||
// Only first argument is a string.
|
||||
__ bind(&string1);
|
||||
__ InvokeBuiltin(
|
||||
HasArgsReversed() ?
|
||||
|
@ -167,7 +167,9 @@ namespace internal {
|
||||
SC(string_compare_native, V8.StringCompareNative) \
|
||||
SC(string_compare_runtime, V8.StringCompareRuntime) \
|
||||
SC(regexp_entry_runtime, V8.RegExpEntryRuntime) \
|
||||
SC(regexp_entry_native, V8.RegExpEntryNative)
|
||||
SC(regexp_entry_native, V8.RegExpEntryNative) \
|
||||
SC(string_plus_smi_hit, V8.StringPlusSmiHit) \
|
||||
SC(string_plus_smi_miss, V8.StringPlusSmiMiss)
|
||||
|
||||
// This file contains all the v8 counters that are in use.
|
||||
class Counters : AllStatic {
|
||||
|
Loading…
Reference in New Issue
Block a user