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

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

Issue 8931025: Handle external strings in generated code when concatenating short strings. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 9 years 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 | « no previous file | test/mjsunit/string-external-cached.js » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 5456 matching lines...) Expand 10 before | Expand all | Expand 10 after
5467 5467
5468 void StringCharAtGenerator::GenerateSlow( 5468 void StringCharAtGenerator::GenerateSlow(
5469 MacroAssembler* masm, 5469 MacroAssembler* masm,
5470 const RuntimeCallHelper& call_helper) { 5470 const RuntimeCallHelper& call_helper) {
5471 char_code_at_generator_.GenerateSlow(masm, call_helper); 5471 char_code_at_generator_.GenerateSlow(masm, call_helper);
5472 char_from_code_generator_.GenerateSlow(masm, call_helper); 5472 char_from_code_generator_.GenerateSlow(masm, call_helper);
5473 } 5473 }
5474 5474
5475 5475
5476 void StringAddStub::Generate(MacroAssembler* masm) { 5476 void StringAddStub::Generate(MacroAssembler* masm) {
5477 Label string_add_runtime, call_builtin; 5477 Label call_runtime, call_builtin;
5478 Builtins::JavaScript builtin_id = Builtins::ADD; 5478 Builtins::JavaScript builtin_id = Builtins::ADD;
5479 5479
5480 // Load the two arguments. 5480 // Load the two arguments.
5481 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 5481 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
5482 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 5482 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
5483 5483
5484 // Make sure that both arguments are strings if not known in advance. 5484 // Make sure that both arguments are strings if not known in advance.
5485 if (flags_ == NO_STRING_ADD_FLAGS) { 5485 if (flags_ == NO_STRING_ADD_FLAGS) {
5486 __ JumpIfSmi(eax, &string_add_runtime); 5486 __ JumpIfSmi(eax, &call_runtime);
5487 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); 5487 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
5488 __ j(above_equal, &string_add_runtime); 5488 __ j(above_equal, &call_runtime);
5489 5489
5490 // First argument is a a string, test second. 5490 // First argument is a a string, test second.
5491 __ JumpIfSmi(edx, &string_add_runtime); 5491 __ JumpIfSmi(edx, &call_runtime);
5492 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); 5492 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
5493 __ j(above_equal, &string_add_runtime); 5493 __ j(above_equal, &call_runtime);
5494 } else { 5494 } else {
5495 // Here at least one of the arguments is definitely a string. 5495 // Here at least one of the arguments is definitely a string.
5496 // We convert the one that is not known to be a string. 5496 // We convert the one that is not known to be a string.
5497 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { 5497 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
5498 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); 5498 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
5499 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi, 5499 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi,
5500 &call_builtin); 5500 &call_builtin);
5501 builtin_id = Builtins::STRING_ADD_RIGHT; 5501 builtin_id = Builtins::STRING_ADD_RIGHT;
5502 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { 5502 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
5503 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); 5503 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
(...skipping 30 matching lines...) Expand all
5534 // eax: first string 5534 // eax: first string
5535 // ebx: length of first string as a smi 5535 // ebx: length of first string as a smi
5536 // ecx: length of second string as a smi 5536 // ecx: length of second string as a smi
5537 // edx: second string 5537 // edx: second string
5538 // Look at the length of the result of adding the two strings. 5538 // Look at the length of the result of adding the two strings.
5539 Label string_add_flat_result, longer_than_two; 5539 Label string_add_flat_result, longer_than_two;
5540 __ bind(&both_not_zero_length); 5540 __ bind(&both_not_zero_length);
5541 __ add(ebx, ecx); 5541 __ add(ebx, ecx);
5542 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); 5542 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
5543 // Handle exceptionally long strings in the runtime system. 5543 // Handle exceptionally long strings in the runtime system.
5544 __ j(overflow, &string_add_runtime); 5544 __ j(overflow, &call_runtime);
5545 // Use the symbol table when adding two one character strings, as it 5545 // Use the symbol table when adding two one character strings, as it
5546 // helps later optimizations to return a symbol here. 5546 // helps later optimizations to return a symbol here.
5547 __ cmp(ebx, Immediate(Smi::FromInt(2))); 5547 __ cmp(ebx, Immediate(Smi::FromInt(2)));
5548 __ j(not_equal, &longer_than_two); 5548 __ j(not_equal, &longer_than_two);
5549 5549
5550 // Check that both strings are non-external ascii strings. 5550 // Check that both strings are non-external ascii strings.
5551 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 5551 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime);
5552 &string_add_runtime);
5553 5552
5554 // Get the two characters forming the new string. 5553 // Get the two characters forming the new string.
5555 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 5554 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
5556 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 5555 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
5557 5556
5558 // Try to lookup two character string in symbol table. If it is not found 5557 // Try to lookup two character string in symbol table. If it is not found
5559 // just allocate a new one. 5558 // just allocate a new one.
5560 Label make_two_character_string, make_two_character_string_no_reload; 5559 Label make_two_character_string, make_two_character_string_no_reload;
5561 StringHelper::GenerateTwoCharacterSymbolTableProbe( 5560 StringHelper::GenerateTwoCharacterSymbolTableProbe(
5562 masm, ebx, ecx, eax, edx, edi, 5561 masm, ebx, ecx, eax, edx, edi,
5563 &make_two_character_string_no_reload, &make_two_character_string); 5562 &make_two_character_string_no_reload, &make_two_character_string);
5564 __ IncrementCounter(counters->string_add_native(), 1); 5563 __ IncrementCounter(counters->string_add_native(), 1);
5565 __ ret(2 * kPointerSize); 5564 __ ret(2 * kPointerSize);
5566 5565
5567 // Allocate a two character string. 5566 // Allocate a two character string.
5568 __ bind(&make_two_character_string); 5567 __ bind(&make_two_character_string);
5569 // Reload the arguments. 5568 // Reload the arguments.
5570 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 5569 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
5571 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 5570 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
5572 // Get the two characters forming the new string. 5571 // Get the two characters forming the new string.
5573 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 5572 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
5574 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 5573 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
5575 __ bind(&make_two_character_string_no_reload); 5574 __ bind(&make_two_character_string_no_reload);
5576 __ IncrementCounter(counters->string_add_make_two_char(), 1); 5575 __ IncrementCounter(counters->string_add_make_two_char(), 1);
5577 __ AllocateAsciiString(eax, // Result. 5576 __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime);
5578 2, // Length.
5579 edi, // Scratch 1.
5580 edx, // Scratch 2.
5581 &string_add_runtime);
5582 // Pack both characters in ebx. 5577 // Pack both characters in ebx.
5583 __ shl(ecx, kBitsPerByte); 5578 __ shl(ecx, kBitsPerByte);
5584 __ or_(ebx, ecx); 5579 __ or_(ebx, ecx);
5585 // Set the characters in the new string. 5580 // Set the characters in the new string.
5586 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx); 5581 __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx);
5587 __ IncrementCounter(counters->string_add_native(), 1); 5582 __ IncrementCounter(counters->string_add_native(), 1);
5588 __ ret(2 * kPointerSize); 5583 __ ret(2 * kPointerSize);
5589 5584
5590 __ bind(&longer_than_two); 5585 __ bind(&longer_than_two);
5591 // Check if resulting string will be flat. 5586 // Check if resulting string will be flat.
5592 __ cmp(ebx, Immediate(Smi::FromInt(String::kMinNonFlatLength))); 5587 __ cmp(ebx, Immediate(Smi::FromInt(String::kMinNonFlatLength)));
5593 __ j(below, &string_add_flat_result); 5588 __ j(below, &string_add_flat_result);
5594 5589
5595 // If result is not supposed to be flat allocate a cons string object. If both 5590 // If result is not supposed to be flat allocate a cons string object. If both
5596 // strings are ascii the result is an ascii cons string. 5591 // strings are ascii the result is an ascii cons string.
5597 Label non_ascii, allocated, ascii_data; 5592 Label non_ascii, allocated, ascii_data;
5598 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); 5593 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
5599 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); 5594 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
5600 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 5595 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
5601 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset)); 5596 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
5602 __ and_(ecx, edi); 5597 __ and_(ecx, edi);
5603 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 5598 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5604 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 5599 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5605 __ test(ecx, Immediate(kStringEncodingMask)); 5600 __ test(ecx, Immediate(kStringEncodingMask));
5606 __ j(zero, &non_ascii); 5601 __ j(zero, &non_ascii, Label::kNear);
5607 __ bind(&ascii_data); 5602 __ bind(&ascii_data);
5608 // Allocate an acsii cons string. 5603 // Allocate an acsii cons string.
5609 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); 5604 __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime);
5610 __ bind(&allocated); 5605 __ bind(&allocated);
5611 // Fill the fields of the cons string. 5606 // Fill the fields of the cons string.
5612 if (FLAG_debug_code) __ AbortIfNotSmi(ebx); 5607 if (FLAG_debug_code) __ AbortIfNotSmi(ebx);
5613 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); 5608 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
5614 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), 5609 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
5615 Immediate(String::kEmptyHashField)); 5610 Immediate(String::kEmptyHashField));
5616 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 5611 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
5617 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 5612 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
5618 __ mov(eax, ecx); 5613 __ mov(eax, ecx);
5619 __ IncrementCounter(counters->string_add_native(), 1); 5614 __ IncrementCounter(counters->string_add_native(), 1);
5620 __ ret(2 * kPointerSize); 5615 __ ret(2 * kPointerSize);
5621 __ bind(&non_ascii); 5616 __ bind(&non_ascii);
5622 // At least one of the strings is two-byte. Check whether it happens 5617 // At least one of the strings is two-byte. Check whether it happens
5623 // to contain only ascii characters. 5618 // to contain only ascii characters.
5624 // ecx: first instance type AND second instance type. 5619 // ecx: first instance type AND second instance type.
5625 // edi: second instance type. 5620 // edi: second instance type.
5626 __ test(ecx, Immediate(kAsciiDataHintMask)); 5621 __ test(ecx, Immediate(kAsciiDataHintMask));
5627 __ j(not_zero, &ascii_data); 5622 __ j(not_zero, &ascii_data);
5628 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 5623 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
5629 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 5624 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
5630 __ xor_(edi, ecx); 5625 __ xor_(edi, ecx);
5631 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); 5626 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
5632 __ and_(edi, kAsciiStringTag | kAsciiDataHintTag); 5627 __ and_(edi, kAsciiStringTag | kAsciiDataHintTag);
5633 __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag); 5628 __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag);
5634 __ j(equal, &ascii_data); 5629 __ j(equal, &ascii_data);
5635 // Allocate a two byte cons string. 5630 // Allocate a two byte cons string.
5636 __ AllocateTwoByteConsString(ecx, edi, no_reg, &string_add_runtime); 5631 __ AllocateTwoByteConsString(ecx, edi, no_reg, &call_runtime);
5637 __ jmp(&allocated); 5632 __ jmp(&allocated);
5638 5633
5639 // Handle creating a flat result. First check that both strings are not 5634 // We cannot encounter sliced strings or cons strings here since:
5640 // external strings. 5635 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
5636 // Handle creating a flat result from either external or sequential strings.
5637 // Locate the first characters' locations.
5641 // eax: first string 5638 // eax: first string
5642 // ebx: length of resulting flat string as a smi 5639 // ebx: length of resulting flat string as a smi
5643 // edx: second string 5640 // edx: second string
5641 Label first_prepared, second_prepared;
5642 Label first_is_sequential, second_is_sequential;
5644 __ bind(&string_add_flat_result); 5643 __ bind(&string_add_flat_result);
5645 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 5644 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
5646 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 5645 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
5647 __ and_(ecx, kStringRepresentationMask); 5646 // ecx: instance type of first string
5648 __ cmp(ecx, kExternalStringTag); 5647 STATIC_ASSERT(kSeqStringTag == 0);
5649 __ j(equal, &string_add_runtime); 5648 __ test_b(ecx, kStringRepresentationMask);
5650 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 5649 __ j(zero, &first_is_sequential, Label::kNear);
5651 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 5650 // Rule out short external string and prepare it so that offset-wise, it
5652 __ and_(ecx, kStringRepresentationMask); 5651 // looks like a sequential string.
5653 __ cmp(ecx, kExternalStringTag); 5652 STATIC_ASSERT(kShortExternalStringTag != 0);
5654 __ j(equal, &string_add_runtime); 5653 __ test_b(ecx, kShortExternalStringMask);
5655 // We cannot encounter sliced strings here since: 5654 __ j(not_zero, &call_runtime);
5656 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); 5655 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
5657 // Now check if both strings are ascii strings. 5656 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
5658 // eax: first string 5657 __ jmp(&first_prepared, Label::kNear);
5659 // ebx: length of resulting flat string as a smi 5658 __ bind(&first_is_sequential);
5660 // edx: second string 5659 __ add(eax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5661 Label non_ascii_string_add_flat_result; 5660 __ bind(&first_prepared);
5662 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 5661
5663 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 5662 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
5664 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 5663 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
5665 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask); 5664 // Check whether both strings have same encoding.
5665 // edi: instance type of second string
5666 __ xor_(ecx, edi);
5667 __ test_b(ecx, kStringEncodingMask);
5668 __ j(not_zero, &call_runtime);
5669 STATIC_ASSERT(kSeqStringTag == 0);
5670 __ test_b(edi, kStringRepresentationMask);
5671 __ j(zero, &second_is_sequential, Label::kNear);
5672 // Rule out short external string and prepare it so that offset-wise, it
5673 // looks like a sequential string.
5674 STATIC_ASSERT(kShortExternalStringTag != 0);
5675 __ test_b(edi, kShortExternalStringMask);
5676 __ j(not_zero, &call_runtime);
5677 __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset));
5678 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
5679 __ jmp(&second_prepared, Label::kNear);
5680 __ bind(&second_is_sequential);
5681 __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5682 __ bind(&second_prepared);
5683
5684 // Push the addresses of both strings' first characters onto the stack.
5685 __ push(edx);
5686 __ push(eax);
5687
5688 Label non_ascii_string_add_flat_result, call_runtime_drop_two;
5689 // edi: instance type of second string
5690 // First string and second string have the same encoding.
5691 STATIC_ASSERT(kTwoByteStringTag == 0);
5692 __ test_b(edi, kStringEncodingMask);
5666 __ j(zero, &non_ascii_string_add_flat_result); 5693 __ j(zero, &non_ascii_string_add_flat_result);
5667 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
5668 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
5669 __ j(zero, &string_add_runtime);
5670 5694
5671 // Both strings are ascii strings. As they are short they are both flat. 5695 // Both strings are ascii strings.
5672 // ebx: length of resulting flat string as a smi 5696 // ebx: length of resulting flat string as a smi
5673 __ SmiUntag(ebx); 5697 __ SmiUntag(ebx);
5674 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime); 5698 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
5675 // eax: result string 5699 // eax: result string
5676 __ mov(ecx, eax); 5700 __ mov(ecx, eax);
5677 // Locate first character of result. 5701 // Locate first character of result.
5678 __ add(ecx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5702 __ add(ecx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5679 // Load first argument and locate first character. 5703 // Load first argument's length and first character location. Account for
5680 __ mov(edx, Operand(esp, 2 * kPointerSize)); 5704 // values currently on the stack when fetching arguments from it.
5705 __ mov(edx, Operand(esp, 4 * kPointerSize));
5681 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 5706 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5682 __ SmiUntag(edi); 5707 __ SmiUntag(edi);
5683 __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5708 __ pop(edx);
5684 // eax: result string 5709 // eax: result string
5685 // ecx: first character of result 5710 // ecx: first character of result
5686 // edx: first char of first argument 5711 // edx: first char of first argument
5687 // edi: length of first argument 5712 // edi: length of first argument
5688 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 5713 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
5689 // Load second argument and locate first character. 5714 // Load second argument's length and first character location. Account for
5690 __ mov(edx, Operand(esp, 1 * kPointerSize)); 5715 // values currently on the stack when fetching arguments from it.
5716 __ mov(edx, Operand(esp, 2 * kPointerSize));
5691 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 5717 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5692 __ SmiUntag(edi); 5718 __ SmiUntag(edi);
5693 __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5719 __ pop(edx);
5694 // eax: result string 5720 // eax: result string
5695 // ecx: next character of result 5721 // ecx: next character of result
5696 // edx: first char of second argument 5722 // edx: first char of second argument
5697 // edi: length of second argument 5723 // edi: length of second argument
5698 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 5724 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
5699 __ IncrementCounter(counters->string_add_native(), 1); 5725 __ IncrementCounter(counters->string_add_native(), 1);
5700 __ ret(2 * kPointerSize); 5726 __ ret(2 * kPointerSize);
5701 5727
5702 // Handle creating a flat two byte result. 5728 // Handle creating a flat two byte result.
5703 // eax: first string - known to be two byte 5729 // eax: first string - known to be two byte
5704 // ebx: length of resulting flat string as a smi 5730 // ebx: length of resulting flat string as a smi
5705 // edx: second string 5731 // edx: second string
5706 __ bind(&non_ascii_string_add_flat_result); 5732 __ bind(&non_ascii_string_add_flat_result);
5707 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 5733 // Both strings are two byte strings.
5708 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
5709 __ j(not_zero, &string_add_runtime);
5710 // Both strings are two byte strings. As they are short they are both
5711 // flat.
5712 __ SmiUntag(ebx); 5734 __ SmiUntag(ebx);
5713 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 5735 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
5714 // eax: result string 5736 // eax: result string
5715 __ mov(ecx, eax); 5737 __ mov(ecx, eax);
5716 // Locate first character of result. 5738 // Locate first character of result.
5717 __ add(ecx, 5739 __ add(ecx,
5718 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 5740 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5719 // Load first argument and locate first character. 5741 // Load second argument's length and first character location. Account for
5720 __ mov(edx, Operand(esp, 2 * kPointerSize)); 5742 // values currently on the stack when fetching arguments from it.
5743 __ mov(edx, Operand(esp, 4 * kPointerSize));
5721 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 5744 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5722 __ SmiUntag(edi); 5745 __ SmiUntag(edi);
5723 __ add(edx, 5746 __ pop(edx);
5724 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5725 // eax: result string 5747 // eax: result string
5726 // ecx: first character of result 5748 // ecx: first character of result
5727 // edx: first char of first argument 5749 // edx: first char of first argument
5728 // edi: length of first argument 5750 // edi: length of first argument
5729 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 5751 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
5730 // Load second argument and locate first character. 5752 // Load second argument's length and first character location. Account for
5731 __ mov(edx, Operand(esp, 1 * kPointerSize)); 5753 // values currently on the stack when fetching arguments from it.
5754 __ mov(edx, Operand(esp, 2 * kPointerSize));
5732 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 5755 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5733 __ SmiUntag(edi); 5756 __ SmiUntag(edi);
5734 __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5757 __ pop(edx);
5735 // eax: result string 5758 // eax: result string
5736 // ecx: next character of result 5759 // ecx: next character of result
5737 // edx: first char of second argument 5760 // edx: first char of second argument
5738 // edi: length of second argument 5761 // edi: length of second argument
5739 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 5762 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
5740 __ IncrementCounter(counters->string_add_native(), 1); 5763 __ IncrementCounter(counters->string_add_native(), 1);
5741 __ ret(2 * kPointerSize); 5764 __ ret(2 * kPointerSize);
5742 5765
5766 // Recover stack pointer before jumping to runtime.
5767 __ bind(&call_runtime_drop_two);
5768 __ Drop(2);
5743 // Just jump to runtime to add the two strings. 5769 // Just jump to runtime to add the two strings.
5744 __ bind(&string_add_runtime); 5770 __ bind(&call_runtime);
5745 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 5771 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
5746 5772
5747 if (call_builtin.is_linked()) { 5773 if (call_builtin.is_linked()) {
5748 __ bind(&call_builtin); 5774 __ bind(&call_builtin);
5749 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); 5775 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
5750 } 5776 }
5751 } 5777 }
5752 5778
5753 5779
5754 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, 5780 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
(...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after
7310 false); 7336 false);
7311 __ pop(edx); 7337 __ pop(edx);
7312 __ ret(0); 7338 __ ret(0);
7313 } 7339 }
7314 7340
7315 #undef __ 7341 #undef __
7316 7342
7317 } } // namespace v8::internal 7343 } } // namespace v8::internal
7318 7344
7319 #endif // V8_TARGET_ARCH_IA32 7345 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/string-external-cached.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698