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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 144023009: Get rid of the unused native code StringAddStub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove obsolete StringHelper methods. Created 6 years, 11 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/code-stubs-arm.h ('k') | src/arm/full-codegen-arm.cc » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 Isolate* isolate, 343 Isolate* isolate,
344 CodeStubInterfaceDescriptor* descriptor) { 344 CodeStubInterfaceDescriptor* descriptor) {
345 static Register registers[] = { r2, r1, r0 }; 345 static Register registers[] = { r2, r1, r0 };
346 descriptor->register_param_count_ = 3; 346 descriptor->register_param_count_ = 3;
347 descriptor->register_params_ = registers; 347 descriptor->register_params_ = registers;
348 descriptor->deoptimization_handler_ = 348 descriptor->deoptimization_handler_ =
349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); 349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
350 } 350 }
351 351
352 352
353 void NewStringAddStub::InitializeInterfaceDescriptor( 353 void StringAddStub::InitializeInterfaceDescriptor(
354 Isolate* isolate, 354 Isolate* isolate,
355 CodeStubInterfaceDescriptor* descriptor) { 355 CodeStubInterfaceDescriptor* descriptor) {
356 static Register registers[] = { r1, r0 }; 356 static Register registers[] = { r1, r0 };
357 descriptor->register_param_count_ = 2; 357 descriptor->register_param_count_ = 2;
358 descriptor->register_params_ = registers; 358 descriptor->register_params_ = registers;
359 descriptor->deoptimization_handler_ = 359 descriptor->deoptimization_handler_ =
360 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 360 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
361 } 361 }
362 362
363 363
(...skipping 3097 matching lines...) Expand 10 before | Expand all | Expand 10 after
3461 __ push(code_); 3461 __ push(code_);
3462 __ CallRuntime(Runtime::kCharFromCode, 1); 3462 __ CallRuntime(Runtime::kCharFromCode, 1);
3463 __ Move(result_, r0); 3463 __ Move(result_, r0);
3464 call_helper.AfterCall(masm); 3464 call_helper.AfterCall(masm);
3465 __ jmp(&exit_); 3465 __ jmp(&exit_);
3466 3466
3467 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3467 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3468 } 3468 }
3469 3469
3470 3470
3471 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3472 Register dest,
3473 Register src,
3474 Register count,
3475 Register scratch,
3476 bool ascii) {
3477 Label loop;
3478 Label done;
3479 // This loop just copies one character at a time, as it is only used for very
3480 // short strings.
3481 if (!ascii) {
3482 __ add(count, count, Operand(count), SetCC);
3483 } else {
3484 __ cmp(count, Operand::Zero());
3485 }
3486 __ b(eq, &done);
3487
3488 __ bind(&loop);
3489 __ ldrb(scratch, MemOperand(src, 1, PostIndex));
3490 // Perform sub between load and dependent store to get the load time to
3491 // complete.
3492 __ sub(count, count, Operand(1), SetCC);
3493 __ strb(scratch, MemOperand(dest, 1, PostIndex));
3494 // last iteration.
3495 __ b(gt, &loop);
3496
3497 __ bind(&done);
3498 }
3499
3500
3501 enum CopyCharactersFlags { 3471 enum CopyCharactersFlags {
3502 COPY_ASCII = 1, 3472 COPY_ASCII = 1,
3503 DEST_ALWAYS_ALIGNED = 2 3473 DEST_ALWAYS_ALIGNED = 2
3504 }; 3474 };
3505 3475
3506 3476
3507 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, 3477 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
3508 Register dest, 3478 Register dest,
3509 Register src, 3479 Register src,
3510 Register count, 3480 Register count,
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
3638 __ cmp(dest, Operand(limit)); 3608 __ cmp(dest, Operand(limit));
3639 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); 3609 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt);
3640 __ b(ge, &done); 3610 __ b(ge, &done);
3641 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 3611 __ strb(scratch1, MemOperand(dest, 1, PostIndex));
3642 __ b(&byte_loop); 3612 __ b(&byte_loop);
3643 3613
3644 __ bind(&done); 3614 __ bind(&done);
3645 } 3615 }
3646 3616
3647 3617
3648 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
3649 Register c1,
3650 Register c2,
3651 Register scratch1,
3652 Register scratch2,
3653 Register scratch3,
3654 Register scratch4,
3655 Register scratch5,
3656 Label* not_found) {
3657 // Register scratch3 is the general scratch register in this function.
3658 Register scratch = scratch3;
3659
3660 // Make sure that both characters are not digits as such strings has a
3661 // different hash algorithm. Don't try to look for these in the string table.
3662 Label not_array_index;
3663 __ sub(scratch, c1, Operand(static_cast<int>('0')));
3664 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
3665 __ b(hi, &not_array_index);
3666 __ sub(scratch, c2, Operand(static_cast<int>('0')));
3667 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
3668
3669 // If check failed combine both characters into single halfword.
3670 // This is required by the contract of the method: code at the
3671 // not_found branch expects this combination in c1 register
3672 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls);
3673 __ b(ls, not_found);
3674
3675 __ bind(&not_array_index);
3676 // Calculate the two character string hash.
3677 Register hash = scratch1;
3678 StringHelper::GenerateHashInit(masm, hash, c1);
3679 StringHelper::GenerateHashAddCharacter(masm, hash, c2);
3680 StringHelper::GenerateHashGetHash(masm, hash);
3681
3682 // Collect the two characters in a register.
3683 Register chars = c1;
3684 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte));
3685
3686 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3687 // hash: hash of two character string.
3688
3689 // Load string table
3690 // Load address of first element of the string table.
3691 Register string_table = c2;
3692 __ LoadRoot(string_table, Heap::kStringTableRootIndex);
3693
3694 Register undefined = scratch4;
3695 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
3696
3697 // Calculate capacity mask from the string table capacity.
3698 Register mask = scratch2;
3699 __ ldr(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset));
3700 __ mov(mask, Operand(mask, ASR, 1));
3701 __ sub(mask, mask, Operand(1));
3702
3703 // Calculate untagged address of the first element of the string table.
3704 Register first_string_table_element = string_table;
3705 __ add(first_string_table_element, string_table,
3706 Operand(StringTable::kElementsStartOffset - kHeapObjectTag));
3707
3708 // Registers
3709 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3710 // hash: hash of two character string
3711 // mask: capacity mask
3712 // first_string_table_element: address of the first element of
3713 // the string table
3714 // undefined: the undefined object
3715 // scratch: -
3716
3717 // Perform a number of probes in the string table.
3718 const int kProbes = 4;
3719 Label found_in_string_table;
3720 Label next_probe[kProbes];
3721 Register candidate = scratch5; // Scratch register contains candidate.
3722 for (int i = 0; i < kProbes; i++) {
3723 // Calculate entry in string table.
3724 if (i > 0) {
3725 __ add(candidate, hash, Operand(StringTable::GetProbeOffset(i)));
3726 } else {
3727 __ mov(candidate, hash);
3728 }
3729
3730 __ and_(candidate, candidate, Operand(mask));
3731
3732 // Load the entry from the symble table.
3733 STATIC_ASSERT(StringTable::kEntrySize == 1);
3734 __ ldr(candidate,
3735 MemOperand(first_string_table_element,
3736 candidate,
3737 LSL,
3738 kPointerSizeLog2));
3739
3740 // If entry is undefined no string with this hash can be found.
3741 Label is_string;
3742 __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE);
3743 __ b(ne, &is_string);
3744
3745 __ cmp(undefined, candidate);
3746 __ b(eq, not_found);
3747 // Must be the hole (deleted entry).
3748 if (FLAG_debug_code) {
3749 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3750 __ cmp(ip, candidate);
3751 __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole);
3752 }
3753 __ jmp(&next_probe[i]);
3754
3755 __ bind(&is_string);
3756
3757 // Check that the candidate is a non-external ASCII string. The instance
3758 // type is still in the scratch register from the CompareObjectType
3759 // operation.
3760 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]);
3761
3762 // If length is not 2 the string is not a candidate.
3763 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset));
3764 __ cmp(scratch, Operand(Smi::FromInt(2)));
3765 __ b(ne, &next_probe[i]);
3766
3767 // Check if the two characters match.
3768 // Assumes that word load is little endian.
3769 __ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize));
3770 __ cmp(chars, scratch);
3771 __ b(eq, &found_in_string_table);
3772 __ bind(&next_probe[i]);
3773 }
3774
3775 // No matching 2 character string found by probing.
3776 __ jmp(not_found);
3777
3778 // Scratch register contains result when we fall through to here.
3779 Register result = candidate;
3780 __ bind(&found_in_string_table);
3781 __ Move(r0, result);
3782 }
3783
3784
3785 void StringHelper::GenerateHashInit(MacroAssembler* masm, 3618 void StringHelper::GenerateHashInit(MacroAssembler* masm,
3786 Register hash, 3619 Register hash,
3787 Register character) { 3620 Register character) {
3788 // hash = character + (character << 10); 3621 // hash = character + (character << 10);
3789 __ LoadRoot(hash, Heap::kHashSeedRootIndex); 3622 __ LoadRoot(hash, Heap::kHashSeedRootIndex);
3790 // Untag smi seed and add the character. 3623 // Untag smi seed and add the character.
3791 __ add(hash, character, Operand(hash, LSR, kSmiTagSize)); 3624 __ add(hash, character, Operand(hash, LSR, kSmiTagSize));
3792 // hash += hash << 10; 3625 // hash += hash << 10;
3793 __ add(hash, hash, Operand(hash, LSL, 10)); 3626 __ add(hash, hash, Operand(hash, LSL, 10));
3794 // hash ^= hash >> 6; 3627 // hash ^= hash >> 6;
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after
4426 __ Assert(eq, kExpectedAllocationSite); 4259 __ Assert(eq, kExpectedAllocationSite);
4427 } 4260 }
4428 4261
4429 // Tail call into the stub that handles binary operations with allocation 4262 // Tail call into the stub that handles binary operations with allocation
4430 // sites. 4263 // sites.
4431 BinaryOpWithAllocationSiteStub stub(state_); 4264 BinaryOpWithAllocationSiteStub stub(state_);
4432 __ TailCallStub(&stub); 4265 __ TailCallStub(&stub);
4433 } 4266 }
4434 4267
4435 4268
4436 void StringAddStub::Generate(MacroAssembler* masm) {
4437 Label call_runtime, call_builtin;
4438 Builtins::JavaScript builtin_id = Builtins::ADD;
4439
4440 Counters* counters = masm->isolate()->counters();
4441
4442 // Stack on entry:
4443 // sp[0]: second argument (right).
4444 // sp[4]: first argument (left).
4445
4446 // Load the two arguments.
4447 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument.
4448 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument.
4449
4450 // Make sure that both arguments are strings if not known in advance.
4451 // Otherwise, at least one of the arguments is definitely a string,
4452 // and we convert the one that is not known to be a string.
4453 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
4454 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
4455 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
4456 __ JumpIfEitherSmi(r0, r1, &call_runtime);
4457 // Load instance types.
4458 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
4459 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
4460 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
4461 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
4462 STATIC_ASSERT(kStringTag == 0);
4463 // If either is not a string, go to runtime.
4464 __ tst(r4, Operand(kIsNotStringMask));
4465 __ tst(r5, Operand(kIsNotStringMask), eq);
4466 __ b(ne, &call_runtime);
4467 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
4468 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
4469 GenerateConvertArgument(
4470 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin);
4471 builtin_id = Builtins::STRING_ADD_RIGHT;
4472 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
4473 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
4474 GenerateConvertArgument(
4475 masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin);
4476 builtin_id = Builtins::STRING_ADD_LEFT;
4477 }
4478
4479 // Both arguments are strings.
4480 // r0: first string
4481 // r1: second string
4482 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
4483 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
4484 {
4485 Label strings_not_empty;
4486 // Check if either of the strings are empty. In that case return the other.
4487 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset));
4488 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset));
4489 STATIC_ASSERT(kSmiTag == 0);
4490 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty.
4491 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second.
4492 STATIC_ASSERT(kSmiTag == 0);
4493 // Else test if second string is empty.
4494 __ cmp(r3, Operand(Smi::FromInt(0)), ne);
4495 __ b(ne, &strings_not_empty); // If either string was empty, return r0.
4496
4497 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
4498 __ add(sp, sp, Operand(2 * kPointerSize));
4499 __ Ret();
4500
4501 __ bind(&strings_not_empty);
4502 }
4503
4504 __ SmiUntag(r2);
4505 __ SmiUntag(r3);
4506 // Both strings are non-empty.
4507 // r0: first string
4508 // r1: second string
4509 // r2: length of first string
4510 // r3: length of second string
4511 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
4512 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
4513 // Look at the length of the result of adding the two strings.
4514 Label string_add_flat_result, longer_than_two;
4515 // Adding two lengths can't overflow.
4516 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
4517 __ add(r6, r2, Operand(r3));
4518 // Use the string table when adding two one character strings, as it
4519 // helps later optimizations to return a string here.
4520 __ cmp(r6, Operand(2));
4521 __ b(ne, &longer_than_two);
4522
4523 // Check that both strings are non-external ASCII strings.
4524 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
4525 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
4526 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
4527 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
4528 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
4529 }
4530 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r3,
4531 &call_runtime);
4532
4533 // Get the two characters forming the sub string.
4534 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
4535 __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize));
4536
4537 // Try to lookup two character string in string table. If it is not found
4538 // just allocate a new one.
4539 Label make_two_character_string;
4540 StringHelper::GenerateTwoCharacterStringTableProbe(
4541 masm, r2, r3, r6, r0, r4, r5, r9, &make_two_character_string);
4542 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
4543 __ add(sp, sp, Operand(2 * kPointerSize));
4544 __ Ret();
4545
4546 __ bind(&make_two_character_string);
4547 // Resulting string has length 2 and first chars of two strings
4548 // are combined into single halfword in r2 register.
4549 // So we can fill resulting string without two loops by a single
4550 // halfword store instruction (which assumes that processor is
4551 // in a little endian mode)
4552 __ mov(r6, Operand(2));
4553 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime);
4554 __ strh(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
4555 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
4556 __ add(sp, sp, Operand(2 * kPointerSize));
4557 __ Ret();
4558
4559 __ bind(&longer_than_two);
4560 // Check if resulting string will be flat.
4561 __ cmp(r6, Operand(ConsString::kMinLength));
4562 __ b(lt, &string_add_flat_result);
4563 // Handle exceptionally long strings in the runtime system.
4564 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
4565 ASSERT(IsPowerOf2(String::kMaxLength + 1));
4566 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
4567 __ cmp(r6, Operand(String::kMaxLength + 1));
4568 __ b(hs, &call_runtime);
4569
4570 // If result is not supposed to be flat, allocate a cons string object.
4571 // If both strings are ASCII the result is an ASCII cons string.
4572 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
4573 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
4574 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
4575 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
4576 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
4577 }
4578 Label non_ascii, allocated, ascii_data;
4579 STATIC_ASSERT(kTwoByteStringTag == 0);
4580 __ tst(r4, Operand(kStringEncodingMask));
4581 __ tst(r5, Operand(kStringEncodingMask), ne);
4582 __ b(eq, &non_ascii);
4583
4584 // Allocate an ASCII cons string.
4585 __ bind(&ascii_data);
4586 __ AllocateAsciiConsString(r3, r6, r4, r5, &call_runtime);
4587 __ bind(&allocated);
4588 // Fill the fields of the cons string.
4589 Label skip_write_barrier, after_writing;
4590 ExternalReference high_promotion_mode = ExternalReference::
4591 new_space_high_promotion_mode_active_address(masm->isolate());
4592 __ mov(r4, Operand(high_promotion_mode));
4593 __ ldr(r4, MemOperand(r4, 0));
4594 __ cmp(r4, Operand::Zero());
4595 __ b(eq, &skip_write_barrier);
4596
4597 __ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
4598 __ RecordWriteField(r3,
4599 ConsString::kFirstOffset,
4600 r0,
4601 r4,
4602 kLRHasNotBeenSaved,
4603 kDontSaveFPRegs);
4604 __ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
4605 __ RecordWriteField(r3,
4606 ConsString::kSecondOffset,
4607 r1,
4608 r4,
4609 kLRHasNotBeenSaved,
4610 kDontSaveFPRegs);
4611 __ jmp(&after_writing);
4612
4613 __ bind(&skip_write_barrier);
4614 __ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
4615 __ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
4616
4617 __ bind(&after_writing);
4618
4619 __ mov(r0, Operand(r3));
4620 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
4621 __ add(sp, sp, Operand(2 * kPointerSize));
4622 __ Ret();
4623
4624 __ bind(&non_ascii);
4625 // At least one of the strings is two-byte. Check whether it happens
4626 // to contain only one byte characters.
4627 // r4: first instance type.
4628 // r5: second instance type.
4629 __ tst(r4, Operand(kOneByteDataHintMask));
4630 __ tst(r5, Operand(kOneByteDataHintMask), ne);
4631 __ b(ne, &ascii_data);
4632 __ eor(r4, r4, Operand(r5));
4633 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
4634 __ and_(r4, r4, Operand(kOneByteStringTag | kOneByteDataHintTag));
4635 __ cmp(r4, Operand(kOneByteStringTag | kOneByteDataHintTag));
4636 __ b(eq, &ascii_data);
4637
4638 // Allocate a two byte cons string.
4639 __ AllocateTwoByteConsString(r3, r6, r4, r5, &call_runtime);
4640 __ jmp(&allocated);
4641
4642 // We cannot encounter sliced strings or cons strings here since:
4643 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
4644 // Handle creating a flat result from either external or sequential strings.
4645 // Locate the first characters' locations.
4646 // r0: first string
4647 // r1: second string
4648 // r2: length of first string
4649 // r3: length of second string
4650 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
4651 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
4652 // r6: sum of lengths.
4653 Label first_prepared, second_prepared;
4654 __ bind(&string_add_flat_result);
4655 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
4656 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
4657 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
4658 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
4659 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
4660 }
4661
4662 // Check whether both strings have same encoding
4663 __ eor(ip, r4, Operand(r5));
4664 ASSERT(__ ImmediateFitsAddrMode1Instruction(kStringEncodingMask));
4665 __ tst(ip, Operand(kStringEncodingMask));
4666 __ b(ne, &call_runtime);
4667
4668 STATIC_ASSERT(kSeqStringTag == 0);
4669 __ tst(r4, Operand(kStringRepresentationMask));
4670 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4671 __ add(r6,
4672 r0,
4673 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
4674 LeaveCC,
4675 eq);
4676 __ b(eq, &first_prepared);
4677 // External string: rule out short external string and load string resource.
4678 STATIC_ASSERT(kShortExternalStringTag != 0);
4679 __ tst(r4, Operand(kShortExternalStringMask));
4680 __ b(ne, &call_runtime);
4681 __ ldr(r6, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
4682 __ bind(&first_prepared);
4683
4684 STATIC_ASSERT(kSeqStringTag == 0);
4685 __ tst(r5, Operand(kStringRepresentationMask));
4686 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4687 __ add(r1,
4688 r1,
4689 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
4690 LeaveCC,
4691 eq);
4692 __ b(eq, &second_prepared);
4693 // External string: rule out short external string and load string resource.
4694 STATIC_ASSERT(kShortExternalStringTag != 0);
4695 __ tst(r5, Operand(kShortExternalStringMask));
4696 __ b(ne, &call_runtime);
4697 __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset));
4698 __ bind(&second_prepared);
4699
4700 Label non_ascii_string_add_flat_result;
4701 // r6: first character of first string
4702 // r1: first character of second string
4703 // r2: length of first string.
4704 // r3: length of second string.
4705 // Both strings have the same encoding.
4706 STATIC_ASSERT(kTwoByteStringTag == 0);
4707 __ tst(r5, Operand(kStringEncodingMask));
4708 __ b(eq, &non_ascii_string_add_flat_result);
4709
4710 __ add(r2, r2, Operand(r3));
4711 __ AllocateAsciiString(r0, r2, r4, r5, r9, &call_runtime);
4712 __ sub(r2, r2, Operand(r3));
4713 __ add(r5, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4714 // r0: result string.
4715 // r6: first character of first string.
4716 // r1: first character of second string.
4717 // r2: length of first string.
4718 // r3: length of second string.
4719 // r5: first character of result.
4720 StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, true);
4721 // r5: next character of result.
4722 StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, true);
4723 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
4724 __ add(sp, sp, Operand(2 * kPointerSize));
4725 __ Ret();
4726
4727 __ bind(&non_ascii_string_add_flat_result);
4728 __ add(r2, r2, Operand(r3));
4729 __ AllocateTwoByteString(r0, r2, r4, r5, r9, &call_runtime);
4730 __ sub(r2, r2, Operand(r3));
4731 __ add(r5, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
4732 // r0: result string.
4733 // r6: first character of first string.
4734 // r1: first character of second string.
4735 // r2: length of first string.
4736 // r3: length of second string.
4737 // r5: first character of result.
4738 StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, false);
4739 // r5: next character of result.
4740 StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, false);
4741 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
4742 __ add(sp, sp, Operand(2 * kPointerSize));
4743 __ Ret();
4744
4745 // Just jump to runtime to add the two strings.
4746 __ bind(&call_runtime);
4747 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
4748
4749 if (call_builtin.is_linked()) {
4750 __ bind(&call_builtin);
4751 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
4752 }
4753 }
4754
4755
4756 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
4757 __ push(r0);
4758 __ push(r1);
4759 }
4760
4761
4762 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm) {
4763 __ pop(r1);
4764 __ pop(r0);
4765 }
4766
4767
4768 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
4769 int stack_offset,
4770 Register arg,
4771 Register scratch1,
4772 Register scratch2,
4773 Register scratch3,
4774 Register scratch4,
4775 Label* slow) {
4776 // First check if the argument is already a string.
4777 Label not_string, done;
4778 __ JumpIfSmi(arg, &not_string);
4779 __ CompareObjectType(arg, scratch1, scratch1, FIRST_NONSTRING_TYPE);
4780 __ b(lt, &done);
4781
4782 // Check the number to string cache.
4783 __ bind(&not_string);
4784 // Puts the cached result into scratch1.
4785 __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, scratch4, slow);
4786 __ mov(arg, scratch1);
4787 __ str(arg, MemOperand(sp, stack_offset));
4788 __ bind(&done);
4789 }
4790
4791
4792 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 4269 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
4793 ASSERT(state_ == CompareIC::SMI); 4270 ASSERT(state_ == CompareIC::SMI);
4794 Label miss; 4271 Label miss;
4795 __ orr(r2, r1, r0); 4272 __ orr(r2, r1, r0);
4796 __ JumpIfNotSmi(r2, &miss); 4273 __ JumpIfNotSmi(r2, &miss);
4797 4274
4798 if (GetCondition() == eq) { 4275 if (GetCondition() == eq) {
4799 // For equality we do not care about the sign of the result. 4276 // For equality we do not care about the sign of the result.
4800 __ sub(r0, r0, r1, SetCC); 4277 __ sub(r0, r0, r1, SetCC);
4801 } else { 4278 } else {
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after
6053 __ bind(&fast_elements_case); 5530 __ bind(&fast_elements_case);
6054 GenerateCase(masm, FAST_ELEMENTS); 5531 GenerateCase(masm, FAST_ELEMENTS);
6055 } 5532 }
6056 5533
6057 5534
6058 #undef __ 5535 #undef __
6059 5536
6060 } } // namespace v8::internal 5537 } } // namespace v8::internal
6061 5538
6062 #endif // V8_TARGET_ARCH_ARM 5539 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698