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

Side by Side Diff: src/arm/codegen-arm.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/arm/codegen-arm.h ('k') | src/arm/macro-assembler-arm.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 7231 matching lines...) Expand 10 before | Expand all | Expand 10 after
7242 __ cmp(dest, Operand(limit)); 7242 __ cmp(dest, Operand(limit));
7243 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); 7243 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt);
7244 __ b(ge, &done); 7244 __ b(ge, &done);
7245 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 7245 __ strb(scratch1, MemOperand(dest, 1, PostIndex));
7246 __ b(&byte_loop); 7246 __ b(&byte_loop);
7247 7247
7248 __ bind(&done); 7248 __ bind(&done);
7249 } 7249 }
7250 7250
7251 7251
7252 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
7253 Register c1,
7254 Register c2,
7255 Register scratch1,
7256 Register scratch2,
7257 Register scratch3,
7258 Register scratch4,
7259 Register scratch5,
7260 Label* not_found) {
7261 // Register scratch3 is the general scratch register in this function.
7262 Register scratch = scratch3;
7263
7264 // Make sure that both characters are not digits as such strings has a
7265 // different hash algorithm. Don't try to look for these in the symbol table.
7266 Label not_array_index;
7267 __ sub(scratch, c1, Operand(static_cast<int>('0')));
7268 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
7269 __ b(hi, &not_array_index);
7270 __ sub(scratch, c2, Operand(static_cast<int>('0')));
7271 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
7272
7273 // If check failed combine both characters into single halfword.
7274 // This is required by the contract of the method: code at the
7275 // not_found branch expects this combination in c1 register
7276 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls);
7277 __ b(ls, not_found);
7278
7279 __ bind(&not_array_index);
7280 // Calculate the two character string hash.
7281 Register hash = scratch1;
7282 GenerateHashInit(masm, hash, c1);
7283 GenerateHashAddCharacter(masm, hash, c2);
7284 GenerateHashGetHash(masm, hash);
7285
7286 // Collect the two characters in a register.
7287 Register chars = c1;
7288 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte));
7289
7290 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
7291 // hash: hash of two character string.
7292
7293 // Load symbol table
7294 // Load address of first element of the symbol table.
7295 Register symbol_table = c2;
7296 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
7297
7298 // Load undefined value
7299 Register undefined = scratch4;
7300 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
7301
7302 // Calculate capacity mask from the symbol table capacity.
7303 Register mask = scratch2;
7304 __ ldr(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset));
7305 __ mov(mask, Operand(mask, ASR, 1));
7306 __ sub(mask, mask, Operand(1));
7307
7308 // Calculate untagged address of the first element of the symbol table.
7309 Register first_symbol_table_element = symbol_table;
7310 __ add(first_symbol_table_element, symbol_table,
7311 Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag));
7312
7313 // Registers
7314 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
7315 // hash: hash of two character string
7316 // mask: capacity mask
7317 // first_symbol_table_element: address of the first element of
7318 // the symbol table
7319 // scratch: -
7320
7321 // Perform a number of probes in the symbol table.
7322 static const int kProbes = 4;
7323 Label found_in_symbol_table;
7324 Label next_probe[kProbes];
7325 for (int i = 0; i < kProbes; i++) {
7326 Register candidate = scratch5; // Scratch register contains candidate.
7327
7328 // Calculate entry in symbol table.
7329 if (i > 0) {
7330 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
7331 } else {
7332 __ mov(candidate, hash);
7333 }
7334
7335 __ and_(candidate, candidate, Operand(mask));
7336
7337 // Load the entry from the symble table.
7338 ASSERT_EQ(1, SymbolTable::kEntrySize);
7339 __ ldr(candidate,
7340 MemOperand(first_symbol_table_element,
7341 candidate,
7342 LSL,
7343 kPointerSizeLog2));
7344
7345 // If entry is undefined no string with this hash can be found.
7346 __ cmp(candidate, undefined);
7347 __ b(eq, not_found);
7348
7349 // If length is not 2 the string is not a candidate.
7350 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset));
7351 __ cmp(scratch, Operand(2));
7352 __ b(ne, &next_probe[i]);
7353
7354 // Check that the candidate is a non-external ascii string.
7355 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset));
7356 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
7357 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch,
7358 &next_probe[i]);
7359
7360 // Check if the two characters match.
7361 // Assumes that word load is little endian.
7362 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize));
7363 __ cmp(chars, scratch);
7364 __ b(eq, &found_in_symbol_table);
7365 __ bind(&next_probe[i]);
7366 }
7367
7368 // No matching 2 character string found by probing.
7369 __ jmp(not_found);
7370
7371 // Scratch register contains result when we fall through to here.
7372 Register result = scratch;
7373 __ bind(&found_in_symbol_table);
7374 if (!result.is(r0)) {
7375 __ mov(r0, result);
7376 }
7377 }
7378
7379
7380 void StringStubBase::GenerateHashInit(MacroAssembler* masm,
7381 Register hash,
7382 Register character) {
7383 // hash = character + (character << 10);
7384 __ add(hash, character, Operand(character, LSL, 10));
7385 // hash ^= hash >> 6;
7386 __ eor(hash, hash, Operand(hash, ASR, 6));
7387 }
7388
7389
7390 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm,
7391 Register hash,
7392 Register character) {
7393 // hash += character;
7394 __ add(hash, hash, Operand(character));
7395 // hash += hash << 10;
7396 __ add(hash, hash, Operand(hash, LSL, 10));
7397 // hash ^= hash >> 6;
7398 __ eor(hash, hash, Operand(hash, ASR, 6));
7399 }
7400
7401
7402 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm,
7403 Register hash) {
7404 // hash += hash << 3;
7405 __ add(hash, hash, Operand(hash, LSL, 3));
7406 // hash ^= hash >> 11;
7407 __ eor(hash, hash, Operand(hash, ASR, 11));
7408 // hash += hash << 15;
7409 __ add(hash, hash, Operand(hash, LSL, 15), SetCC);
7410
7411 // if (hash == 0) hash = 27;
7412 __ mov(hash, Operand(27), LeaveCC, nz);
7413 }
7414
7415
7252 void SubStringStub::Generate(MacroAssembler* masm) { 7416 void SubStringStub::Generate(MacroAssembler* masm) {
7253 Label runtime; 7417 Label runtime;
7254 7418
7255 // Stack frame on entry. 7419 // Stack frame on entry.
7256 // lr: return address 7420 // lr: return address
7257 // sp[0]: to 7421 // sp[0]: to
7258 // sp[4]: from 7422 // sp[4]: from
7259 // sp[8]: string 7423 // sp[8]: string
7260 7424
7261 // This stub is called from the native-call %_SubString(...), so 7425 // This stub is called from the native-call %_SubString(...), so
(...skipping 15 matching lines...) Expand all
7277 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 7441 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
7278 // I.e., arithmetic shift right by one un-smi-tags. 7442 // I.e., arithmetic shift right by one un-smi-tags.
7279 __ mov(r2, Operand(r7, ASR, 1), SetCC); 7443 __ mov(r2, Operand(r7, ASR, 1), SetCC);
7280 __ mov(r3, Operand(r6, ASR, 1), SetCC, cc); 7444 __ mov(r3, Operand(r6, ASR, 1), SetCC, cc);
7281 // If either r2 or r6 had the smi tag bit set, then carry is set now. 7445 // If either r2 or r6 had the smi tag bit set, then carry is set now.
7282 __ b(cs, &runtime); // Either "from" or "to" is not a smi. 7446 __ b(cs, &runtime); // Either "from" or "to" is not a smi.
7283 __ b(mi, &runtime); // From is negative. 7447 __ b(mi, &runtime); // From is negative.
7284 7448
7285 __ sub(r2, r2, Operand(r3), SetCC); 7449 __ sub(r2, r2, Operand(r3), SetCC);
7286 __ b(mi, &runtime); // Fail if from > to. 7450 __ b(mi, &runtime); // Fail if from > to.
7287 // Handle sub-strings of length 2 and less in the runtime system. 7451 // Special handling of sub-strings of length 1 and 2. One character strings
7452 // are handled in the runtime system (looked up in the single character
7453 // cache). Two character strings are looked for in the symbol cache.
7288 __ cmp(r2, Operand(2)); 7454 __ cmp(r2, Operand(2));
7289 __ b(le, &runtime); 7455 __ b(lt, &runtime);
7290 7456
7291 // r2: length 7457 // r2: length
7458 // r3: from index (untaged smi)
7292 // r6: from (smi) 7459 // r6: from (smi)
7293 // r7: to (smi) 7460 // r7: to (smi)
7294 7461
7295 // Make sure first argument is a sequential (or flat) string. 7462 // Make sure first argument is a sequential (or flat) string.
7296 __ ldr(r5, MemOperand(sp, kStringOffset)); 7463 __ ldr(r5, MemOperand(sp, kStringOffset));
7297 ASSERT_EQ(0, kSmiTag); 7464 ASSERT_EQ(0, kSmiTag);
7298 __ tst(r5, Operand(kSmiTagMask)); 7465 __ tst(r5, Operand(kSmiTagMask));
7299 __ b(eq, &runtime); 7466 __ b(eq, &runtime);
7300 Condition is_string = masm->IsObjectStringType(r5, r1); 7467 Condition is_string = masm->IsObjectStringType(r5, r1);
7301 __ b(NegateCondition(is_string), &runtime); 7468 __ b(NegateCondition(is_string), &runtime);
7302 7469
7303 // r1: instance type 7470 // r1: instance type
7304 // r2: length 7471 // r2: length
7472 // r3: from index (untaged smi)
7305 // r5: string 7473 // r5: string
7306 // r6: from (smi) 7474 // r6: from (smi)
7307 // r7: to (smi) 7475 // r7: to (smi)
7308 Label seq_string; 7476 Label seq_string;
7309 __ and_(r4, r1, Operand(kStringRepresentationMask)); 7477 __ and_(r4, r1, Operand(kStringRepresentationMask));
7310 ASSERT(kSeqStringTag < kConsStringTag); 7478 ASSERT(kSeqStringTag < kConsStringTag);
7311 ASSERT(kExternalStringTag > kConsStringTag); 7479 ASSERT(kExternalStringTag > kConsStringTag);
7312 __ cmp(r4, Operand(kConsStringTag)); 7480 __ cmp(r4, Operand(kConsStringTag));
7313 __ b(gt, &runtime); // External strings go to runtime. 7481 __ b(gt, &runtime); // External strings go to runtime.
7314 __ b(lt, &seq_string); // Sequential strings are handled directly. 7482 __ b(lt, &seq_string); // Sequential strings are handled directly.
7315 7483
7316 // Cons string. Try to recurse (once) on the first substring. 7484 // Cons string. Try to recurse (once) on the first substring.
7317 // (This adds a little more generality than necessary to handle flattened 7485 // (This adds a little more generality than necessary to handle flattened
7318 // cons strings, but not much). 7486 // cons strings, but not much).
7319 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset)); 7487 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset));
7320 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); 7488 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
7321 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 7489 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset));
7322 __ tst(r1, Operand(kStringRepresentationMask)); 7490 __ tst(r1, Operand(kStringRepresentationMask));
7323 ASSERT_EQ(0, kSeqStringTag); 7491 ASSERT_EQ(0, kSeqStringTag);
7324 __ b(ne, &runtime); // Cons and External strings go to runtime. 7492 __ b(ne, &runtime); // Cons and External strings go to runtime.
7325 7493
7326 // Definitly a sequential string. 7494 // Definitly a sequential string.
7327 __ bind(&seq_string); 7495 __ bind(&seq_string);
7328 7496
7329 // r1: instance type. 7497 // r1: instance type.
7330 // r2: length 7498 // r2: length
7499 // r3: from index (untaged smi)
7331 // r5: string 7500 // r5: string
7332 // r6: from (smi) 7501 // r6: from (smi)
7333 // r7: to (smi) 7502 // r7: to (smi)
7334 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); 7503 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset));
7335 __ cmp(r4, Operand(r7, ASR, 1)); 7504 __ cmp(r4, Operand(r7, ASR, 1));
7336 __ b(lt, &runtime); // Fail if to > length. 7505 __ b(lt, &runtime); // Fail if to > length.
7337 7506
7338 // r1: instance type. 7507 // r1: instance type.
7339 // r2: result string length. 7508 // r2: result string length.
7509 // r3: from index (untaged smi)
7340 // r5: string. 7510 // r5: string.
7341 // r6: from offset (smi) 7511 // r6: from offset (smi)
7342 // Check for flat ascii string. 7512 // Check for flat ascii string.
7343 Label non_ascii_flat; 7513 Label non_ascii_flat;
7344 __ tst(r1, Operand(kStringEncodingMask)); 7514 __ tst(r1, Operand(kStringEncodingMask));
7345 ASSERT_EQ(0, kTwoByteStringTag); 7515 ASSERT_EQ(0, kTwoByteStringTag);
7346 __ b(eq, &non_ascii_flat); 7516 __ b(eq, &non_ascii_flat);
7347 7517
7518 Label result_longer_than_two;
7519 __ cmp(r2, Operand(2));
7520 __ b(gt, &result_longer_than_two);
7521
7522 // Sub string of length 2 requested.
7523 // Get the two characters forming the sub string.
7524 __ add(r5, r5, Operand(r3));
7525 __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize));
7526 __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1));
7527
7528 // Try to lookup two character string in symbol table.
7529 Label make_two_character_string;
7530 GenerateTwoCharacterSymbolTableProbe(masm, r3, r4, r1, r5, r6, r7, r9,
7531 &make_two_character_string);
7532 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
7533 __ add(sp, sp, Operand(3 * kPointerSize));
7534 __ Ret();
7535
7536 // r2: result string length.
7537 // r3: two characters combined into halfword in little endian byte order.
7538 __ bind(&make_two_character_string);
7539 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime);
7540 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
7541 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
7542 __ add(sp, sp, Operand(3 * kPointerSize));
7543 __ Ret();
7544
7545 __ bind(&result_longer_than_two);
7546
7348 // Allocate the result. 7547 // Allocate the result.
7349 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); 7548 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime);
7350 7549
7351 // r0: result string. 7550 // r0: result string.
7352 // r2: result string length. 7551 // r2: result string length.
7353 // r5: string. 7552 // r5: string.
7354 // r6: from offset (smi) 7553 // r6: from offset (smi)
7355 // Locate first character of result. 7554 // Locate first character of result.
7356 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 7555 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
7357 // Locate 'from' character of string. 7556 // Locate 'from' character of string.
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
7546 } 7745 }
7547 7746
7548 // Both strings are non-empty. 7747 // Both strings are non-empty.
7549 // r0: first string 7748 // r0: first string
7550 // r1: second string 7749 // r1: second string
7551 // r2: length of first string 7750 // r2: length of first string
7552 // r3: length of second string 7751 // r3: length of second string
7553 // r4: first string instance type (if string_check_) 7752 // r4: first string instance type (if string_check_)
7554 // r5: second string instance type (if string_check_) 7753 // r5: second string instance type (if string_check_)
7555 // Look at the length of the result of adding the two strings. 7754 // Look at the length of the result of adding the two strings.
7556 Label string_add_flat_result; 7755 Label string_add_flat_result, longer_than_two;
7557 // Adding two lengths can't overflow. 7756 // Adding two lengths can't overflow.
7558 ASSERT(String::kMaxLength * 2 > String::kMaxLength); 7757 ASSERT(String::kMaxLength * 2 > String::kMaxLength);
7559 __ add(r6, r2, Operand(r3)); 7758 __ add(r6, r2, Operand(r3));
7560 // Use the runtime system when adding two one character strings, as it 7759 // Use the runtime system when adding two one character strings, as it
7561 // contains optimizations for this specific case using the symbol table. 7760 // contains optimizations for this specific case using the symbol table.
7562 __ cmp(r6, Operand(2)); 7761 __ cmp(r6, Operand(2));
7563 __ b(eq, &string_add_runtime); 7762 __ b(ne, &longer_than_two);
7763
7764 // Check that both strings are non-external ascii strings.
7765 if (!string_check_) {
7766 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
7767 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
7768 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
7769 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
7770 }
7771 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
7772 &string_add_runtime);
7773
7774 // Get the two characters forming the sub string.
7775 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
7776 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize));
7777
7778 // Try to lookup two character string in symbol table. If it is not found
7779 // just allocate a new one.
7780 Label make_two_character_string;
7781 GenerateTwoCharacterSymbolTableProbe(masm, r2, r3, r6, r7, r4, r5, r9,
7782 &make_two_character_string);
7783 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
7784 __ add(sp, sp, Operand(2 * kPointerSize));
7785 __ Ret();
7786
7787 __ bind(&make_two_character_string);
7788 // Resulting string has length 2 and first chars of two strings
7789 // are combined into single halfword in r2 register.
7790 // So we can fill resulting string without two loops by a single
7791 // halfword store instruction (which assumes that processor is
7792 // in a little endian mode)
7793 __ mov(r6, Operand(2));
7794 __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime);
7795 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
7796 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
7797 __ add(sp, sp, Operand(2 * kPointerSize));
7798 __ Ret();
7799
7800 __ bind(&longer_than_two);
7564 // Check if resulting string will be flat. 7801 // Check if resulting string will be flat.
7565 __ cmp(r6, Operand(String::kMinNonFlatLength)); 7802 __ cmp(r6, Operand(String::kMinNonFlatLength));
7566 __ b(lt, &string_add_flat_result); 7803 __ b(lt, &string_add_flat_result);
7567 // Handle exceptionally long strings in the runtime system. 7804 // Handle exceptionally long strings in the runtime system.
7568 ASSERT((String::kMaxLength & 0x80000000) == 0); 7805 ASSERT((String::kMaxLength & 0x80000000) == 0);
7569 ASSERT(IsPowerOf2(String::kMaxLength + 1)); 7806 ASSERT(IsPowerOf2(String::kMaxLength + 1));
7570 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. 7807 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
7571 __ cmp(r6, Operand(String::kMaxLength + 1)); 7808 __ cmp(r6, Operand(String::kMaxLength + 1));
7572 __ b(hs, &string_add_runtime); 7809 __ b(hs, &string_add_runtime);
7573 7810
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
7632 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. 7869 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test.
7633 __ eor(r7, r4, Operand(r5)); 7870 __ eor(r7, r4, Operand(r5));
7634 __ tst(r7, Operand(kStringEncodingMask)); 7871 __ tst(r7, Operand(kStringEncodingMask));
7635 __ b(ne, &string_add_runtime); 7872 __ b(ne, &string_add_runtime);
7636 // And see if it's ASCII or two-byte. 7873 // And see if it's ASCII or two-byte.
7637 __ tst(r4, Operand(kStringEncodingMask)); 7874 __ tst(r4, Operand(kStringEncodingMask));
7638 __ b(eq, &non_ascii_string_add_flat_result); 7875 __ b(eq, &non_ascii_string_add_flat_result);
7639 7876
7640 // Both strings are sequential ASCII strings. We also know that they are 7877 // Both strings are sequential ASCII strings. We also know that they are
7641 // short (since the sum of the lengths is less than kMinNonFlatLength). 7878 // short (since the sum of the lengths is less than kMinNonFlatLength).
7879 // r6: length of resulting flat string
7642 __ AllocateAsciiString(r7, r6, r4, r5, r9, &string_add_runtime); 7880 __ AllocateAsciiString(r7, r6, r4, r5, r9, &string_add_runtime);
7643 // Locate first character of result. 7881 // Locate first character of result.
7644 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 7882 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
7645 // Locate first character of first argument. 7883 // Locate first character of first argument.
7646 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 7884 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
7647 // r0: first character of first string. 7885 // r0: first character of first string.
7648 // r1: second string. 7886 // r1: second string.
7649 // r2: length of first string. 7887 // r2: length of first string.
7650 // r3: length of second string. 7888 // r3: length of second string.
7651 // r6: first character of result. 7889 // r6: first character of result.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
7707 7945
7708 // Just jump to runtime to add the two strings. 7946 // Just jump to runtime to add the two strings.
7709 __ bind(&string_add_runtime); 7947 __ bind(&string_add_runtime);
7710 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 7948 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
7711 } 7949 }
7712 7950
7713 7951
7714 #undef __ 7952 #undef __
7715 7953
7716 } } // namespace v8::internal 7954 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698