Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 661469: Port of changes from r3842 (symbol table probing for two character strings) t... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 8982 matching lines...) Expand 10 before | Expand all | Expand 10 after
8993 // First string is empty, result is second string which is in rdx. 8993 // First string is empty, result is second string which is in rdx.
8994 __ movq(rax, rdx); 8994 __ movq(rax, rdx);
8995 __ IncrementCounter(&Counters::string_add_native, 1); 8995 __ IncrementCounter(&Counters::string_add_native, 1);
8996 __ ret(2 * kPointerSize); 8996 __ ret(2 * kPointerSize);
8997 8997
8998 // Both strings are non-empty. 8998 // Both strings are non-empty.
8999 // rax: first string 8999 // rax: first string
9000 // rbx: length of first string 9000 // rbx: length of first string
9001 // rcx: length of second string 9001 // rcx: length of second string
9002 // rdx: second string 9002 // rdx: second string
9003 // r8: instance type of first string if string check was performed above 9003 // r8: map of first string if string check was performed above
9004 // r9: instance type of first string if string check was performed above 9004 // r9: map of second string if string check was performed above
9005 Label string_add_flat_result; 9005 Label string_add_flat_result, longer_than_two;
9006 __ bind(&both_not_zero_length); 9006 __ bind(&both_not_zero_length);
9007 // Look at the length of the result of adding the two strings. 9007
9008 __ addl(rbx, rcx);
9009 // Use the runtime system when adding two one character strings, as it
9010 // contains optimizations for this specific case using the symbol table.
9011 __ cmpl(rbx, Immediate(2));
9012 __ j(equal, &string_add_runtime);
9013 // If arguments where known to be strings, maps are not loaded to r8 and r9 9008 // If arguments where known to be strings, maps are not loaded to r8 and r9
9014 // by the code above. 9009 // by the code above.
9015 if (!string_check_) { 9010 if (!string_check_) {
9016 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); 9011 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
9017 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); 9012 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
9018 } 9013 }
9019 // Get the instance types of the two strings as they will be needed soon. 9014 // Get the instance types of the two strings as they will be needed soon.
9020 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); 9015 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
9021 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); 9016 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
9017
9018 // Look at the length of the result of adding the two strings.
9019 __ addl(rbx, rcx);
9020 // Use the runtime system when adding two one character strings, as it
9021 // contains optimizations for this specific case using the symbol table.
9022 __ cmpl(rbx, Immediate(2));
9023 __ j(not_equal, &longer_than_two);
9024
9025 // Check that both strings are non-external ascii strings.
9026 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
9027 &string_add_runtime);
9028
9029 // Get the two characters forming the sub string.
9030 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
9031 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
9032
9033 // Try to lookup two character string in symbol table. If it is not found
9034 // just allocate a new one.
9035 Label make_two_character_string, make_flat_ascii_string;
9036 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, r14, r12, rdi, r15,
9037 &make_two_character_string);
9038 __ IncrementCounter(&Counters::string_add_native, 1);
9039 __ ret(2 * kPointerSize);
9040
9041 __ bind(&make_two_character_string);
9042 __ Set(rbx, 2);
9043 __ jmp(&make_flat_ascii_string);
9044
9045 __ bind(&longer_than_two);
9022 // Check if resulting string will be flat. 9046 // Check if resulting string will be flat.
9023 __ cmpl(rbx, Immediate(String::kMinNonFlatLength)); 9047 __ cmpl(rbx, Immediate(String::kMinNonFlatLength));
9024 __ j(below, &string_add_flat_result); 9048 __ j(below, &string_add_flat_result);
9025 // Handle exceptionally long strings in the runtime system. 9049 // Handle exceptionally long strings in the runtime system.
9026 ASSERT((String::kMaxLength & 0x80000000) == 0); 9050 ASSERT((String::kMaxLength & 0x80000000) == 0);
9027 __ cmpl(rbx, Immediate(String::kMaxLength)); 9051 __ cmpl(rbx, Immediate(String::kMaxLength));
9028 __ j(above, &string_add_runtime); 9052 __ j(above, &string_add_runtime);
9029 9053
9030 // If result is not supposed to be flat, allocate a cons string object. If 9054 // If result is not supposed to be flat, allocate a cons string object. If
9031 // both strings are ascii the result is an ascii cons string. 9055 // both strings are ascii the result is an ascii cons string.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
9078 // ebx: length of resulting flat string 9102 // ebx: length of resulting flat string
9079 // rdx: second string 9103 // rdx: second string
9080 // r8: instance type of first string 9104 // r8: instance type of first string
9081 // r9: instance type of second string 9105 // r9: instance type of second string
9082 Label non_ascii_string_add_flat_result; 9106 Label non_ascii_string_add_flat_result;
9083 ASSERT(kStringEncodingMask == kAsciiStringTag); 9107 ASSERT(kStringEncodingMask == kAsciiStringTag);
9084 __ testl(r8, Immediate(kAsciiStringTag)); 9108 __ testl(r8, Immediate(kAsciiStringTag));
9085 __ j(zero, &non_ascii_string_add_flat_result); 9109 __ j(zero, &non_ascii_string_add_flat_result);
9086 __ testl(r9, Immediate(kAsciiStringTag)); 9110 __ testl(r9, Immediate(kAsciiStringTag));
9087 __ j(zero, &string_add_runtime); 9111 __ j(zero, &string_add_runtime);
9112
9113 __ bind(&make_flat_ascii_string);
9088 // Both strings are ascii strings. As they are short they are both flat. 9114 // Both strings are ascii strings. As they are short they are both flat.
9089 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 9115 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
9090 // rcx: result string 9116 // rcx: result string
9091 __ movq(rbx, rcx); 9117 __ movq(rbx, rcx);
9092 // Locate first character of result. 9118 // Locate first character of result.
9093 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9119 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9094 // Locate first character of first argument 9120 // Locate first character of first argument
9095 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); 9121 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
9096 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9122 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9097 // rax: first char of first argument 9123 // rax: first char of first argument
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
9228 __ movb(kScratchRegister, Operand(src, 0)); 9254 __ movb(kScratchRegister, Operand(src, 0));
9229 __ movb(Operand(dest, 0), kScratchRegister); 9255 __ movb(Operand(dest, 0), kScratchRegister);
9230 __ addq(src, Immediate(1)); 9256 __ addq(src, Immediate(1));
9231 __ addq(dest, Immediate(1)); 9257 __ addq(dest, Immediate(1));
9232 __ subq(count, Immediate(1)); 9258 __ subq(count, Immediate(1));
9233 __ j(not_zero, &loop); 9259 __ j(not_zero, &loop);
9234 9260
9235 __ bind(&done); 9261 __ bind(&done);
9236 } 9262 }
9237 9263
9264 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
9265 Register c1,
9266 Register c2,
9267 Register scratch1,
9268 Register scratch2,
9269 Register scratch3,
9270 Register scratch4,
9271 Label* not_found) {
9272 // Register scratch3 is the general scratch register in this function.
9273 Register scratch = scratch3;
9274
9275 // Make sure that both characters are not digits as such strings has a
9276 // different hash algorithm. Don't try to look for these in the symbol table.
9277 Label not_array_index;
9278 __ movq(scratch, c1);
9279 __ subq(scratch, Immediate(static_cast<int>('0')));
9280 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0')));
9281 __ j(above, &not_array_index);
9282 __ movq(scratch, c2);
9283 __ subq(scratch, Immediate(static_cast<int>('0')));
9284 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0')));
9285 __ j(below_equal, not_found);
9286
9287 __ bind(&not_array_index);
9288 // Calculate the two character string hash.
9289 Register hash = scratch1;
9290 GenerateHashInit(masm, hash, c1, scratch);
9291 GenerateHashAddCharacter(masm, hash, c2, scratch);
9292 GenerateHashGetHash(masm, hash, scratch);
9293
9294 // Collect the two characters in a register.
9295 Register chars = c1;
9296 __ shl(c2, Immediate(kBitsPerByte));
9297 __ orl(chars, c2);
9298
9299 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
9300 // hash: hash of two character string.
9301
9302 // Load the symbol table.
9303 Register symbol_table = c2;
9304 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
9305
9306 // Calculate capacity mask from the symbol table capacity.
9307 Register mask = scratch2;
9308 __ movq(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
9309 __ SmiToInteger32(mask, mask);
9310 __ decl(mask);
9311
9312 Register undefined = scratch4;
9313 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
9314
9315 // Registers
9316 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
9317 // hash: hash of two character string (32-bit int)
9318 // symbol_table: symbol table
9319 // mask: capacity mask (32-bit int)
9320 // undefined: undefined value
9321 // scratch: -
9322
9323 // Perform a number of probes in the symbol table.
9324 static const int kProbes = 4;
9325 Label found_in_symbol_table;
9326 Label next_probe[kProbes];
9327 for (int i = 0; i < kProbes; i++) {
9328 // Calculate entry in symbol table.
9329 __ movl(scratch, hash);
9330 if (i > 0) {
9331 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
9332 }
9333 __ andl(scratch, mask);
9334
9335 // Load the entry from the symble table.
9336 Register candidate = scratch; // Scratch register contains candidate.
9337 ASSERT_EQ(1, SymbolTable::kEntrySize);
9338 __ movq(candidate,
9339 FieldOperand(symbol_table,
9340 scratch,
9341 times_pointer_size,
9342 SymbolTable::kElementsStartOffset));
9343
9344 // If entry is undefined no string with this hash can be found.
9345 __ cmpq(candidate, undefined);
9346 __ j(equal, not_found);
9347
9348 // If length is not 2 the string is not a candidate.
9349 __ cmpl(FieldOperand(candidate, String::kLengthOffset), Immediate(2));
9350 __ j(not_equal, &next_probe[i]);
9351
9352 // We use kScratchRegister as a temporary register in assumption that
9353 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
9354 Register temp = kScratchRegister;
9355
9356 // Check that the candidate is a non-external ascii string.
9357 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset));
9358 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
9359 __ JumpIfInstanceTypeIsNotSequentialAscii(
9360 temp, temp, &next_probe[i]);
9361
9362 // Check if the two characters match.
9363 __ movl(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize));
9364 __ andl(temp, Immediate(0x0000ffff));
9365 __ cmpl(chars, temp);
9366 __ j(equal, &found_in_symbol_table);
9367 __ bind(&next_probe[i]);
9368 }
9369
9370 // No matching 2 character string found by probing.
9371 __ jmp(not_found);
9372
9373 // Scratch register contains result when we fall through to here.
9374 Register result = scratch;
9375 __ bind(&found_in_symbol_table);
9376 if (!result.is(rax)) {
9377 __ movq(rax, result);
9378 }
9379 }
9380
9381
9382 void StringStubBase::GenerateHashInit(MacroAssembler* masm,
9383 Register hash,
9384 Register character,
9385 Register scratch) {
9386 // hash = character + (character << 10);
9387 __ movl(hash, character);
9388 __ shll(hash, Immediate(10));
9389 __ addl(hash, character);
9390 // hash ^= hash >> 6;
9391 __ movl(scratch, hash);
9392 __ sarl(scratch, Immediate(6));
9393 __ xorl(hash, scratch);
9394 }
9395
9396
9397 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm,
9398 Register hash,
9399 Register character,
9400 Register scratch) {
9401 // hash += character;
9402 __ addl(hash, character);
9403 // hash += hash << 10;
9404 __ movl(scratch, hash);
9405 __ shll(scratch, Immediate(10));
9406 __ addl(hash, scratch);
9407 // hash ^= hash >> 6;
9408 __ movl(scratch, hash);
9409 __ sarl(scratch, Immediate(6));
9410 __ xorl(hash, scratch);
9411 }
9412
9413
9414 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm,
9415 Register hash,
9416 Register scratch) {
9417 // hash += hash << 3;
9418 __ movl(scratch, hash);
9419 __ shll(scratch, Immediate(3));
9420 __ addl(hash, scratch);
9421 // hash ^= hash >> 11;
9422 __ movl(scratch, hash);
9423 __ sarl(scratch, Immediate(11));
9424 __ xorl(hash, scratch);
9425 // hash += hash << 15;
9426 __ movl(scratch, hash);
9427 __ shll(scratch, Immediate(15));
9428 __ addl(hash, scratch);
9429
9430 // if (hash == 0) hash = 27;
9431 Label hash_not_zero;
9432 __ testl(hash, hash);
9433 __ j(not_zero, &hash_not_zero);
9434 __ movl(hash, Immediate(27));
9435 __ bind(&hash_not_zero);
9436 }
9238 9437
9239 void SubStringStub::Generate(MacroAssembler* masm) { 9438 void SubStringStub::Generate(MacroAssembler* masm) {
9240 Label runtime; 9439 Label runtime;
9241 9440
9242 // Stack frame on entry. 9441 // Stack frame on entry.
9243 // rsp[0]: return address 9442 // rsp[0]: return address
9244 // rsp[8]: to 9443 // rsp[8]: to
9245 // rsp[16]: from 9444 // rsp[16]: from
9246 // rsp[24]: string 9445 // rsp[24]: string
9247 9446
9248 const int kToOffset = 1 * kPointerSize; 9447 const int kToOffset = 1 * kPointerSize;
9249 const int kFromOffset = kToOffset + kPointerSize; 9448 const int kFromOffset = kToOffset + kPointerSize;
9250 const int kStringOffset = kFromOffset + kPointerSize; 9449 const int kStringOffset = kFromOffset + kPointerSize;
9251 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; 9450 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset;
9252 9451
9253 // Make sure first argument is a string. 9452 // Make sure first argument is a string.
9254 __ movq(rax, Operand(rsp, kStringOffset)); 9453 __ movq(rax, Operand(rsp, kStringOffset));
9255 ASSERT_EQ(0, kSmiTag); 9454 ASSERT_EQ(0, kSmiTag);
9256 __ testl(rax, Immediate(kSmiTagMask)); 9455 __ testl(rax, Immediate(kSmiTagMask));
9257 __ j(zero, &runtime); 9456 __ j(zero, &runtime);
9258 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); 9457 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
9259 __ j(NegateCondition(is_string), &runtime); 9458 __ j(NegateCondition(is_string), &runtime);
9260 9459
9261 // rax: string 9460 // rax: string
9262 // rbx: instance type 9461 // rbx: instance type
9263 // Calculate length of sub string using the smi values. 9462 // Calculate length of sub string using the smi values.
9463 Label result_longer_than_two;
9264 __ movq(rcx, Operand(rsp, kToOffset)); 9464 __ movq(rcx, Operand(rsp, kToOffset));
9265 __ movq(rdx, Operand(rsp, kFromOffset)); 9465 __ movq(rdx, Operand(rsp, kFromOffset));
9266 __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime); 9466 __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime);
9267 9467
9268 __ SmiSub(rcx, rcx, rdx, NULL); // Overflow doesn't happen. 9468 __ SmiSub(rcx, rcx, rdx, NULL); // Overflow doesn't happen.
9269 __ j(negative, &runtime); 9469 __ j(negative, &runtime);
9270 // Handle sub-strings of length 2 and less in the runtime system. 9470 // Special handling of sub-strings of length 1 and 2. One character strings
9471 // are handled in the runtime system (looked up in the single character
9472 // cache). Two character strings are looked for in the symbol cache.
9271 __ SmiToInteger32(rcx, rcx); 9473 __ SmiToInteger32(rcx, rcx);
9272 __ cmpl(rcx, Immediate(2)); 9474 __ cmpl(rcx, Immediate(2));
9273 __ j(below_equal, &runtime); 9475 __ j(greater, &result_longer_than_two);
9476 __ j(less, &runtime);
9477
9478 // Sub string of length 2 requested.
9479 // rax: string
9480 // rbx: instance type
9481 // rcx: sub string length (value is 2)
9482 // rdx: from index (smi)
9483 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &runtime);
9484
9485 // Get the two characters forming the sub string.
9486 __ SmiToInteger32(rdx, rdx); // From index is no longer smi.
9487 __ movzxbq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize));
9488 __ movzxbq(rcx,
9489 FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize + 1));
9490
9491 // Try to lookup two character string in symbol table.
9492 Label make_two_character_string;
9493 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, rax, rdx, rdi, r14,
9494 &make_two_character_string);
9495 __ ret(3 * kPointerSize);
9496
9497 __ bind(&make_two_character_string);
9498 // Setup registers for allocating the two character string.
9499 __ movq(rax, Operand(rsp, kStringOffset));
9500 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
9501 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
9502 __ Set(rcx, 2);
9503
9504 __ bind(&result_longer_than_two);
9274 9505
9275 // rax: string 9506 // rax: string
9276 // rbx: instance type 9507 // rbx: instance type
9277 // rcx: result string length 9508 // rcx: result string length
9278 // Check for flat ascii string 9509 // Check for flat ascii string
9279 Label non_ascii_flat; 9510 Label non_ascii_flat;
9280 __ and_(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); 9511 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &non_ascii_flat);
9281 __ cmpb(rbx, Immediate(kSeqStringTag | kAsciiStringTag));
9282 __ j(not_equal, &non_ascii_flat);
9283 9512
9284 // Allocate the result. 9513 // Allocate the result.
9285 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); 9514 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime);
9286 9515
9287 // rax: result string 9516 // rax: result string
9288 // rcx: result string length 9517 // rcx: result string length
9289 __ movq(rdx, rsi); // esi used by following code. 9518 __ movq(rdx, rsi); // esi used by following code.
9290 // Locate first character of result. 9519 // Locate first character of result.
9291 __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize)); 9520 __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize));
9292 // Load string argument and locate character of sub string start. 9521 // Load string argument and locate character of sub string start.
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
9558 // Call the function from C++. 9787 // Call the function from C++.
9559 return FUNCTION_CAST<ModuloFunction>(buffer); 9788 return FUNCTION_CAST<ModuloFunction>(buffer);
9560 } 9789 }
9561 9790
9562 #endif 9791 #endif
9563 9792
9564 9793
9565 #undef __ 9794 #undef __
9566 9795
9567 } } // namespace v8::internal 9796 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698