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

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

Issue 1706013: Changing string length field type from int to SMI. It will make it be a regu... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 10 years, 7 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/objects-inl.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 5848 matching lines...) Expand 10 before | Expand all | Expand 10 after
5859 5859
5860 is_string.Bind(&left_side); 5860 is_string.Bind(&left_side);
5861 // left_side is a sequential ASCII string. 5861 // left_side is a sequential ASCII string.
5862 ASSERT(left_side.reg().is(left_reg)); 5862 ASSERT(left_side.reg().is(left_reg));
5863 right_side = Result(right_val); 5863 right_side = Result(right_val);
5864 Result temp2 = allocator_->Allocate(); 5864 Result temp2 = allocator_->Allocate();
5865 ASSERT(temp2.is_valid()); 5865 ASSERT(temp2.is_valid());
5866 // Test string equality and comparison. 5866 // Test string equality and comparison.
5867 if (cc == equal) { 5867 if (cc == equal) {
5868 Label comparison_done; 5868 Label comparison_done;
5869 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset), 5869 __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset),
5870 Immediate(1)); 5870 Smi::FromInt(1));
5871 __ j(not_equal, &comparison_done); 5871 __ j(not_equal, &comparison_done);
5872 uint8_t char_value = 5872 uint8_t char_value =
5873 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); 5873 static_cast<uint8_t>(String::cast(*right_val)->Get(0));
5874 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), 5874 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
5875 Immediate(char_value)); 5875 Immediate(char_value));
5876 __ bind(&comparison_done); 5876 __ bind(&comparison_done);
5877 } else { 5877 } else {
5878 __ movl(temp2.reg(), 5878 __ movq(temp2.reg(),
5879 FieldOperand(left_side.reg(), String::kLengthOffset)); 5879 FieldOperand(left_side.reg(), String::kLengthOffset));
5880 __ subl(temp2.reg(), Immediate(1)); 5880 __ SmiSubConstant(temp2.reg(), temp2.reg(), Smi::FromInt(1));
5881 Label comparison; 5881 Label comparison;
5882 // If the length is 0 then the subtraction gave -1 which compares less 5882 // If the length is 0 then the subtraction gave -1 which compares less
5883 // than any character. 5883 // than any character.
5884 __ j(negative, &comparison); 5884 __ j(negative, &comparison);
5885 // Otherwise load the first character. 5885 // Otherwise load the first character.
5886 __ movzxbl(temp2.reg(), 5886 __ movzxbl(temp2.reg(),
5887 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize)); 5887 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
5888 __ bind(&comparison); 5888 __ bind(&comparison);
5889 // Compare the first character of the string with the 5889 // Compare the first character of the string with the
5890 // constant 1-character string. 5890 // constant 1-character string.
5891 uint8_t char_value = 5891 uint8_t char_value =
5892 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0)); 5892 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0));
5893 __ cmpb(temp2.reg(), Immediate(char_value)); 5893 __ cmpb(temp2.reg(), Immediate(char_value));
5894 Label characters_were_different; 5894 Label characters_were_different;
5895 __ j(not_equal, &characters_were_different); 5895 __ j(not_equal, &characters_were_different);
5896 // If the first character is the same then the long string sorts after 5896 // If the first character is the same then the long string sorts after
5897 // the short one. 5897 // the short one.
5898 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset), 5898 __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset),
5899 Immediate(1)); 5899 Smi::FromInt(1));
5900 __ bind(&characters_were_different); 5900 __ bind(&characters_were_different);
5901 } 5901 }
5902 temp2.Unuse(); 5902 temp2.Unuse();
5903 left_side.Unuse(); 5903 left_side.Unuse();
5904 right_side.Unuse(); 5904 right_side.Unuse();
5905 dest->Split(cc); 5905 dest->Split(cc);
5906 } 5906 }
5907 } else { 5907 } else {
5908 // Neither side is a constant Smi, constant 1-char string, or constant null. 5908 // Neither side is a constant Smi, constant 1-char string, or constant null.
5909 // If either side is a non-smi constant, skip the smi check. 5909 // If either side is a non-smi constant, skip the smi check.
(...skipping 1598 matching lines...) Expand 10 before | Expand all | Expand 10 after
7508 __ and_(rbx, Immediate(1 << Map::kIsUndetectable)); 7508 __ and_(rbx, Immediate(1 << Map::kIsUndetectable));
7509 __ j(not_zero, &false_result); 7509 __ j(not_zero, &false_result);
7510 7510
7511 // JavaScript object => true. 7511 // JavaScript object => true.
7512 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE)); 7512 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE));
7513 __ j(above_equal, &true_result); 7513 __ j(above_equal, &true_result);
7514 7514
7515 // String value => false iff empty. 7515 // String value => false iff empty.
7516 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE)); 7516 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE));
7517 __ j(above_equal, &not_string); 7517 __ j(above_equal, &not_string);
7518 __ movl(rdx, FieldOperand(rax, String::kLengthOffset)); 7518 __ movq(rdx, FieldOperand(rax, String::kLengthOffset));
7519 __ testl(rdx, rdx); 7519 __ SmiTest(rdx);
7520 __ j(zero, &false_result); 7520 __ j(zero, &false_result);
7521 __ jmp(&true_result); 7521 __ jmp(&true_result);
7522 7522
7523 __ bind(&not_string); 7523 __ bind(&not_string);
7524 // HeapNumber => false iff +0, -0, or NaN. 7524 // HeapNumber => false iff +0, -0, or NaN.
7525 // These three cases set C3 when compared to zero in the FPU. 7525 // These three cases set C3 when compared to zero in the FPU.
7526 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); 7526 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
7527 __ j(not_equal, &true_result); 7527 __ j(not_equal, &true_result);
7528 __ fldz(); // Load zero onto fp stack 7528 __ fldz(); // Load zero onto fp stack
7529 // Load heap-number double value onto fp stack 7529 // Load heap-number double value onto fp stack
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
8116 __ j(above, &runtime); 8116 __ j(above, &runtime);
8117 8117
8118 // rcx: RegExp data (FixedArray) 8118 // rcx: RegExp data (FixedArray)
8119 // rdx: Number of capture registers 8119 // rdx: Number of capture registers
8120 // Check that the second argument is a string. 8120 // Check that the second argument is a string.
8121 __ movq(rax, Operand(rsp, kSubjectOffset)); 8121 __ movq(rax, Operand(rsp, kSubjectOffset));
8122 __ JumpIfSmi(rax, &runtime); 8122 __ JumpIfSmi(rax, &runtime);
8123 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); 8123 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
8124 __ j(NegateCondition(is_string), &runtime); 8124 __ j(NegateCondition(is_string), &runtime);
8125 // Get the length of the string to rbx. 8125 // Get the length of the string to rbx.
8126 __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); 8126 __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
8127 8127
8128 // rbx: Length of subject string 8128 // rbx: Length of subject string as smi
8129 // rcx: RegExp data (FixedArray) 8129 // rcx: RegExp data (FixedArray)
8130 // rdx: Number of capture registers 8130 // rdx: Number of capture registers
8131 // Check that the third argument is a positive smi less than the string 8131 // Check that the third argument is a positive smi less than the string
8132 // length. A negative value will be greater (unsigned comparison). 8132 // length. A negative value will be greater (unsigned comparison).
8133 __ movq(rax, Operand(rsp, kPreviousIndexOffset)); 8133 __ movq(rax, Operand(rsp, kPreviousIndexOffset));
8134 __ SmiToInteger32(rax, rax); 8134 __ JumpIfNotSmi(rax, &runtime);
8135 __ cmpl(rax, rbx); 8135 __ SmiCompare(rax, rbx);
8136 __ j(above, &runtime); 8136 __ j(above_equal, &runtime);
8137 8137
8138 // rcx: RegExp data (FixedArray) 8138 // rcx: RegExp data (FixedArray)
8139 // rdx: Number of capture registers 8139 // rdx: Number of capture registers
8140 // Check that the fourth object is a JSArray object. 8140 // Check that the fourth object is a JSArray object.
8141 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); 8141 __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
8142 __ JumpIfSmi(rax, &runtime); 8142 __ JumpIfSmi(rax, &runtime);
8143 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); 8143 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister);
8144 __ j(not_equal, &runtime); 8144 __ j(not_equal, &runtime);
8145 // Check that the JSArray is in fast case. 8145 // Check that the JSArray is in fast case.
8146 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); 8146 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset));
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
8279 // Keep track on aliasing between argX defined above and the registers used. 8279 // Keep track on aliasing between argX defined above and the registers used.
8280 // rax: subject string 8280 // rax: subject string
8281 // rbx: previous index 8281 // rbx: previous index
8282 // rdi: encoding of subject string (1 if ascii 0 if two_byte); 8282 // rdi: encoding of subject string (1 if ascii 0 if two_byte);
8283 // r12: code 8283 // r12: code
8284 8284
8285 // Argument 4: End of string data 8285 // Argument 4: End of string data
8286 // Argument 3: Start of string data 8286 // Argument 3: Start of string data
8287 Label setup_two_byte, setup_rest; 8287 Label setup_two_byte, setup_rest;
8288 __ testb(rdi, rdi); 8288 __ testb(rdi, rdi);
8289 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); 8289 __ movq(rdi, FieldOperand(rax, String::kLengthOffset));
8290 __ j(zero, &setup_two_byte); 8290 __ j(zero, &setup_two_byte);
8291 __ SmiToInteger32(rdi, rdi);
8291 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); 8292 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize));
8292 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); 8293 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize));
8293 __ jmp(&setup_rest); 8294 __ jmp(&setup_rest);
8294 __ bind(&setup_two_byte); 8295 __ bind(&setup_two_byte);
8296 __ SmiToInteger32(rdi, rdi);
8295 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); 8297 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize));
8296 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); 8298 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize));
8297 8299
8298 __ bind(&setup_rest); 8300 __ bind(&setup_rest);
8299 // Argument 2: Previous index. 8301 // Argument 2: Previous index.
8300 __ movq(arg2, rbx); 8302 __ movq(arg2, rbx);
8301 8303
8302 // Argument 1: Subject string. 8304 // Argument 1: Subject string.
8303 __ movq(arg1, rax); 8305 __ movq(arg1, rax);
8304 8306
(...skipping 2144 matching lines...) Expand 10 before | Expand all | Expand 10 after
10449 // Fetch the instance type of the receiver into result register. 10451 // Fetch the instance type of the receiver into result register.
10450 __ movq(result, FieldOperand(object, HeapObject::kMapOffset)); 10452 __ movq(result, FieldOperand(object, HeapObject::kMapOffset));
10451 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 10453 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
10452 // If the receiver is not a string trigger the non-string case. 10454 // If the receiver is not a string trigger the non-string case.
10453 __ testb(result, Immediate(kIsNotStringMask)); 10455 __ testb(result, Immediate(kIsNotStringMask));
10454 __ j(not_zero, receiver_not_string); 10456 __ j(not_zero, receiver_not_string);
10455 10457
10456 // If the index is non-smi trigger the non-smi case. 10458 // If the index is non-smi trigger the non-smi case.
10457 __ JumpIfNotSmi(index, index_not_smi); 10459 __ JumpIfNotSmi(index, index_not_smi);
10458 10460
10459 // Put untagged index into scratch register.
10460 __ SmiToInteger32(scratch, index);
10461
10462 // Check for index out of range. 10461 // Check for index out of range.
10463 __ cmpl(scratch, FieldOperand(object, String::kLengthOffset)); 10462 __ SmiCompare(index, FieldOperand(object, String::kLengthOffset));
10464 __ j(above_equal, index_out_of_range); 10463 __ j(above_equal, index_out_of_range);
10465 10464
10466 __ bind(&try_again_with_new_string); 10465 __ bind(&try_again_with_new_string);
10467 // ----------- S t a t e ------------- 10466 // ----------- S t a t e -------------
10468 // -- object : string to access 10467 // -- object : string to access
10469 // -- result : instance type of the string 10468 // -- result : instance type of the string
10470 // -- scratch : non-negative index < length 10469 // -- scratch : non-negative index < length
10471 // ----------------------------------- 10470 // -----------------------------------
10472 10471
10473 // We need special handling for non-flat strings. 10472 // We need special handling for non-flat strings.
10474 ASSERT_EQ(0, kSeqStringTag); 10473 ASSERT_EQ(0, kSeqStringTag);
10475 __ testb(result, Immediate(kStringRepresentationMask)); 10474 __ testb(result, Immediate(kStringRepresentationMask));
10476 __ j(not_zero, &not_a_flat_string); 10475 __ j(not_zero, &not_a_flat_string);
10477 10476
10477 // Put untagged index into scratch register.
10478 __ SmiToInteger32(scratch, index);
10479
10478 // Check for 1-byte or 2-byte string. 10480 // Check for 1-byte or 2-byte string.
10479 ASSERT_EQ(0, kTwoByteStringTag); 10481 ASSERT_EQ(0, kTwoByteStringTag);
10480 __ testb(result, Immediate(kStringEncodingMask)); 10482 __ testb(result, Immediate(kStringEncodingMask));
10481 __ j(not_zero, &ascii_string); 10483 __ j(not_zero, &ascii_string);
10482 10484
10483 // 2-byte string. 10485 // 2-byte string.
10484 // Load the 2-byte character code into the result register. 10486 // Load the 2-byte character code into the result register.
10485 __ movzxwl(result, FieldOperand(object, 10487 __ movzxwl(result, FieldOperand(object,
10486 scratch, 10488 scratch,
10487 times_2, 10489 times_2,
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
10589 __ j(is_smi, &string_add_runtime); 10591 __ j(is_smi, &string_add_runtime);
10590 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9); 10592 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
10591 __ j(above_equal, &string_add_runtime); 10593 __ j(above_equal, &string_add_runtime);
10592 } 10594 }
10593 10595
10594 // Both arguments are strings. 10596 // Both arguments are strings.
10595 // rax: first string 10597 // rax: first string
10596 // rdx: second string 10598 // rdx: second string
10597 // Check if either of the strings are empty. In that case return the other. 10599 // Check if either of the strings are empty. In that case return the other.
10598 Label second_not_zero_length, both_not_zero_length; 10600 Label second_not_zero_length, both_not_zero_length;
10599 __ movl(rcx, FieldOperand(rdx, String::kLengthOffset)); 10601 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset));
10600 __ testl(rcx, rcx); 10602 __ SmiTest(rcx);
10601 __ j(not_zero, &second_not_zero_length); 10603 __ j(not_zero, &second_not_zero_length);
10602 // Second string is empty, result is first string which is already in rax. 10604 // Second string is empty, result is first string which is already in rax.
10603 __ IncrementCounter(&Counters::string_add_native, 1); 10605 __ IncrementCounter(&Counters::string_add_native, 1);
10604 __ ret(2 * kPointerSize); 10606 __ ret(2 * kPointerSize);
10605 __ bind(&second_not_zero_length); 10607 __ bind(&second_not_zero_length);
10606 __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); 10608 __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
10607 __ testl(rbx, rbx); 10609 __ SmiTest(rbx);
10608 __ j(not_zero, &both_not_zero_length); 10610 __ j(not_zero, &both_not_zero_length);
10609 // First string is empty, result is second string which is in rdx. 10611 // First string is empty, result is second string which is in rdx.
10610 __ movq(rax, rdx); 10612 __ movq(rax, rdx);
10611 __ IncrementCounter(&Counters::string_add_native, 1); 10613 __ IncrementCounter(&Counters::string_add_native, 1);
10612 __ ret(2 * kPointerSize); 10614 __ ret(2 * kPointerSize);
10613 10615
10614 // Both strings are non-empty. 10616 // Both strings are non-empty.
10615 // rax: first string 10617 // rax: first string
10616 // rbx: length of first string 10618 // rbx: length of first string
10617 // rcx: length of second string 10619 // rcx: length of second string
10618 // rdx: second string 10620 // rdx: second string
10619 // r8: map of first string if string check was performed above 10621 // r8: map of first string if string check was performed above
10620 // r9: map of second string if string check was performed above 10622 // r9: map of second string if string check was performed above
10621 Label string_add_flat_result, longer_than_two; 10623 Label string_add_flat_result, longer_than_two;
10622 __ bind(&both_not_zero_length); 10624 __ bind(&both_not_zero_length);
10623 10625
10624 // If arguments where known to be strings, maps are not loaded to r8 and r9 10626 // If arguments where known to be strings, maps are not loaded to r8 and r9
10625 // by the code above. 10627 // by the code above.
10626 if (!string_check_) { 10628 if (!string_check_) {
10627 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); 10629 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
10628 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); 10630 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
10629 } 10631 }
10630 // Get the instance types of the two strings as they will be needed soon. 10632 // Get the instance types of the two strings as they will be needed soon.
10631 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); 10633 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
10632 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); 10634 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
10633 10635
10634 // Look at the length of the result of adding the two strings. 10636 // Look at the length of the result of adding the two strings.
10635 __ addl(rbx, rcx); 10637 ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
10638 __ SmiAdd(rbx, rbx, rcx, NULL);
10636 // Use the runtime system when adding two one character strings, as it 10639 // Use the runtime system when adding two one character strings, as it
10637 // contains optimizations for this specific case using the symbol table. 10640 // contains optimizations for this specific case using the symbol table.
10638 __ cmpl(rbx, Immediate(2)); 10641 __ SmiCompare(rbx, Smi::FromInt(2));
10639 __ j(not_equal, &longer_than_two); 10642 __ j(not_equal, &longer_than_two);
10640 10643
10641 // Check that both strings are non-external ascii strings. 10644 // Check that both strings are non-external ascii strings.
10642 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, 10645 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
10643 &string_add_runtime); 10646 &string_add_runtime);
10644 10647
10645 // Get the two characters forming the sub string. 10648 // Get the two characters forming the sub string.
10646 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); 10649 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
10647 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); 10650 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
10648 10651
10649 // Try to lookup two character string in symbol table. If it is not found 10652 // Try to lookup two character string in symbol table. If it is not found
10650 // just allocate a new one. 10653 // just allocate a new one.
10651 Label make_two_character_string, make_flat_ascii_string; 10654 Label make_two_character_string, make_flat_ascii_string;
10652 StringHelper::GenerateTwoCharacterSymbolTableProbe( 10655 StringHelper::GenerateTwoCharacterSymbolTableProbe(
10653 masm, rbx, rcx, r14, r12, rdi, r15, &make_two_character_string); 10656 masm, rbx, rcx, r14, r12, rdi, r15, &make_two_character_string);
10654 __ IncrementCounter(&Counters::string_add_native, 1); 10657 __ IncrementCounter(&Counters::string_add_native, 1);
10655 __ ret(2 * kPointerSize); 10658 __ ret(2 * kPointerSize);
10656 10659
10657 __ bind(&make_two_character_string); 10660 __ bind(&make_two_character_string);
10658 __ Set(rbx, 2); 10661 __ Set(rbx, 2);
10659 __ jmp(&make_flat_ascii_string); 10662 __ jmp(&make_flat_ascii_string);
10660 10663
10661 __ bind(&longer_than_two); 10664 __ bind(&longer_than_two);
10662 // Check if resulting string will be flat. 10665 // Check if resulting string will be flat.
10663 __ cmpl(rbx, Immediate(String::kMinNonFlatLength)); 10666 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength));
10664 __ j(below, &string_add_flat_result); 10667 __ j(below, &string_add_flat_result);
10665 // Handle exceptionally long strings in the runtime system. 10668 // Handle exceptionally long strings in the runtime system.
10666 ASSERT((String::kMaxLength & 0x80000000) == 0); 10669 ASSERT((String::kMaxLength & 0x80000000) == 0);
10667 __ cmpl(rbx, Immediate(String::kMaxLength)); 10670 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
10668 __ j(above, &string_add_runtime); 10671 __ j(above, &string_add_runtime);
10669 10672
10670 // If result is not supposed to be flat, allocate a cons string object. If 10673 // If result is not supposed to be flat, allocate a cons string object. If
10671 // both strings are ascii the result is an ascii cons string. 10674 // both strings are ascii the result is an ascii cons string.
10672 // rax: first string 10675 // rax: first string
10673 // ebx: length of resulting flat string 10676 // ebx: length of resulting flat string
10674 // rdx: second string 10677 // rdx: second string
10675 // r8: instance type of first string 10678 // r8: instance type of first string
10676 // r9: instance type of second string 10679 // r9: instance type of second string
10677 Label non_ascii, allocated; 10680 Label non_ascii, allocated;
10678 __ movl(rcx, r8); 10681 __ movl(rcx, r8);
10679 __ and_(rcx, r9); 10682 __ and_(rcx, r9);
10680 ASSERT(kStringEncodingMask == kAsciiStringTag); 10683 ASSERT(kStringEncodingMask == kAsciiStringTag);
10681 __ testl(rcx, Immediate(kAsciiStringTag)); 10684 __ testl(rcx, Immediate(kAsciiStringTag));
10682 __ j(zero, &non_ascii); 10685 __ j(zero, &non_ascii);
10683 // Allocate an acsii cons string. 10686 // Allocate an acsii cons string.
10684 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); 10687 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime);
10685 __ bind(&allocated); 10688 __ bind(&allocated);
10686 // Fill the fields of the cons string. 10689 // Fill the fields of the cons string.
10687 __ movl(FieldOperand(rcx, ConsString::kLengthOffset), rbx); 10690 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
10688 __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset), 10691 __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset),
10689 Immediate(String::kEmptyHashField)); 10692 Immediate(String::kEmptyHashField));
10690 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); 10693 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
10691 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); 10694 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
10692 __ movq(rax, rcx); 10695 __ movq(rax, rcx);
10693 __ IncrementCounter(&Counters::string_add_native, 1); 10696 __ IncrementCounter(&Counters::string_add_native, 1);
10694 __ ret(2 * kPointerSize); 10697 __ ret(2 * kPointerSize);
10695 __ bind(&non_ascii); 10698 __ bind(&non_ascii);
10696 // Allocate a two byte cons string. 10699 // Allocate a two byte cons string.
10697 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime); 10700 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime);
10698 __ jmp(&allocated); 10701 __ jmp(&allocated);
10699 10702
10700 // Handle creating a flat result. First check that both strings are not 10703 // Handle creating a flat result. First check that both strings are not
10701 // external strings. 10704 // external strings.
10702 // rax: first string 10705 // rax: first string
10703 // ebx: length of resulting flat string 10706 // ebx: length of resulting flat string as smi
10704 // rdx: second string 10707 // rdx: second string
10705 // r8: instance type of first string 10708 // r8: instance type of first string
10706 // r9: instance type of first string 10709 // r9: instance type of first string
10707 __ bind(&string_add_flat_result); 10710 __ bind(&string_add_flat_result);
10711 __ SmiToInteger32(rbx, rbx);
10708 __ movl(rcx, r8); 10712 __ movl(rcx, r8);
10709 __ and_(rcx, Immediate(kStringRepresentationMask)); 10713 __ and_(rcx, Immediate(kStringRepresentationMask));
10710 __ cmpl(rcx, Immediate(kExternalStringTag)); 10714 __ cmpl(rcx, Immediate(kExternalStringTag));
10711 __ j(equal, &string_add_runtime); 10715 __ j(equal, &string_add_runtime);
10712 __ movl(rcx, r9); 10716 __ movl(rcx, r9);
10713 __ and_(rcx, Immediate(kStringRepresentationMask)); 10717 __ and_(rcx, Immediate(kStringRepresentationMask));
10714 __ cmpl(rcx, Immediate(kExternalStringTag)); 10718 __ cmpl(rcx, Immediate(kExternalStringTag));
10715 __ j(equal, &string_add_runtime); 10719 __ j(equal, &string_add_runtime);
10716 // Now check if both strings are ascii strings. 10720 // Now check if both strings are ascii strings.
10717 // rax: first string 10721 // rax: first string
10718 // ebx: length of resulting flat string 10722 // ebx: length of resulting flat string
10719 // rdx: second string 10723 // rdx: second string
10720 // r8: instance type of first string 10724 // r8: instance type of first string
10721 // r9: instance type of second string 10725 // r9: instance type of second string
10722 Label non_ascii_string_add_flat_result; 10726 Label non_ascii_string_add_flat_result;
10723 ASSERT(kStringEncodingMask == kAsciiStringTag); 10727 ASSERT(kStringEncodingMask == kAsciiStringTag);
10724 __ testl(r8, Immediate(kAsciiStringTag)); 10728 __ testl(r8, Immediate(kAsciiStringTag));
10725 __ j(zero, &non_ascii_string_add_flat_result); 10729 __ j(zero, &non_ascii_string_add_flat_result);
10726 __ testl(r9, Immediate(kAsciiStringTag)); 10730 __ testl(r9, Immediate(kAsciiStringTag));
10727 __ j(zero, &string_add_runtime); 10731 __ j(zero, &string_add_runtime);
10728 10732
10729 __ bind(&make_flat_ascii_string); 10733 __ bind(&make_flat_ascii_string);
10730 // Both strings are ascii strings. As they are short they are both flat. 10734 // Both strings are ascii strings. As they are short they are both flat.
10731 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 10735 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
10732 // rcx: result string 10736 // rcx: result string
10733 __ movq(rbx, rcx); 10737 __ movq(rbx, rcx);
10734 // Locate first character of result. 10738 // Locate first character of result.
10735 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 10739 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
10736 // Locate first character of first argument 10740 // Locate first character of first argument
10737 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); 10741 __ movq(rdi, FieldOperand(rax, String::kLengthOffset));
10742 __ SmiToInteger32(rdi, rdi);
10738 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 10743 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
10739 // rax: first char of first argument 10744 // rax: first char of first argument
10740 // rbx: result string 10745 // rbx: result string
10741 // rcx: first character of result 10746 // rcx: first character of result
10742 // rdx: second string 10747 // rdx: second string
10743 // rdi: length of first argument 10748 // rdi: length of first argument
10744 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true); 10749 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true);
10745 // Locate first character of second argument. 10750 // Locate first character of second argument.
10746 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); 10751 __ movq(rdi, FieldOperand(rdx, String::kLengthOffset));
10752 __ SmiToInteger32(rdi, rdi);
10747 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 10753 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
10748 // rbx: result string 10754 // rbx: result string
10749 // rcx: next character of result 10755 // rcx: next character of result
10750 // rdx: first char of second argument 10756 // rdx: first char of second argument
10751 // rdi: length of second argument 10757 // rdi: length of second argument
10752 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true); 10758 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
10753 __ movq(rax, rbx); 10759 __ movq(rax, rbx);
10754 __ IncrementCounter(&Counters::string_add_native, 1); 10760 __ IncrementCounter(&Counters::string_add_native, 1);
10755 __ ret(2 * kPointerSize); 10761 __ ret(2 * kPointerSize);
10756 10762
10757 // Handle creating a flat two byte result. 10763 // Handle creating a flat two byte result.
10758 // rax: first string - known to be two byte 10764 // rax: first string - known to be two byte
10759 // rbx: length of resulting flat string 10765 // rbx: length of resulting flat string
10760 // rdx: second string 10766 // rdx: second string
10761 // r8: instance type of first string 10767 // r8: instance type of first string
10762 // r9: instance type of first string 10768 // r9: instance type of first string
10763 __ bind(&non_ascii_string_add_flat_result); 10769 __ bind(&non_ascii_string_add_flat_result);
10764 __ and_(r9, Immediate(kAsciiStringTag)); 10770 __ and_(r9, Immediate(kAsciiStringTag));
10765 __ j(not_zero, &string_add_runtime); 10771 __ j(not_zero, &string_add_runtime);
10766 // Both strings are two byte strings. As they are short they are both 10772 // Both strings are two byte strings. As they are short they are both
10767 // flat. 10773 // flat.
10768 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 10774 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
10769 // rcx: result string 10775 // rcx: result string
10770 __ movq(rbx, rcx); 10776 __ movq(rbx, rcx);
10771 // Locate first character of result. 10777 // Locate first character of result.
10772 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 10778 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
10773 // Locate first character of first argument. 10779 // Locate first character of first argument.
10774 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); 10780 __ movq(rdi, FieldOperand(rax, String::kLengthOffset));
10781 __ SmiToInteger32(rdi, rdi);
10775 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 10782 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
10776 // rax: first char of first argument 10783 // rax: first char of first argument
10777 // rbx: result string 10784 // rbx: result string
10778 // rcx: first character of result 10785 // rcx: first character of result
10779 // rdx: second argument 10786 // rdx: second argument
10780 // rdi: length of first argument 10787 // rdi: length of first argument
10781 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false); 10788 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false);
10782 // Locate first character of second argument. 10789 // Locate first character of second argument.
10783 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); 10790 __ movq(rdi, FieldOperand(rdx, String::kLengthOffset));
10791 __ SmiToInteger32(rdi, rdi);
10784 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 10792 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
10785 // rbx: result string 10793 // rbx: result string
10786 // rcx: next character of result 10794 // rcx: next character of result
10787 // rdx: first char of second argument 10795 // rdx: first char of second argument
10788 // rdi: length of second argument 10796 // rdi: length of second argument
10789 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false); 10797 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
10790 __ movq(rax, rbx); 10798 __ movq(rax, rbx);
10791 __ IncrementCounter(&Counters::string_add_native, 1); 10799 __ IncrementCounter(&Counters::string_add_native, 1);
10792 __ ret(2 * kPointerSize); 10800 __ ret(2 * kPointerSize);
10793 10801
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
10955 FieldOperand(symbol_table, 10963 FieldOperand(symbol_table,
10956 scratch, 10964 scratch,
10957 times_pointer_size, 10965 times_pointer_size,
10958 SymbolTable::kElementsStartOffset)); 10966 SymbolTable::kElementsStartOffset));
10959 10967
10960 // If entry is undefined no string with this hash can be found. 10968 // If entry is undefined no string with this hash can be found.
10961 __ cmpq(candidate, undefined); 10969 __ cmpq(candidate, undefined);
10962 __ j(equal, not_found); 10970 __ j(equal, not_found);
10963 10971
10964 // If length is not 2 the string is not a candidate. 10972 // If length is not 2 the string is not a candidate.
10965 __ cmpl(FieldOperand(candidate, String::kLengthOffset), Immediate(2)); 10973 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
10974 Smi::FromInt(2));
10966 __ j(not_equal, &next_probe[i]); 10975 __ j(not_equal, &next_probe[i]);
10967 10976
10968 // We use kScratchRegister as a temporary register in assumption that 10977 // We use kScratchRegister as a temporary register in assumption that
10969 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly 10978 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
10970 Register temp = kScratchRegister; 10979 Register temp = kScratchRegister;
10971 10980
10972 // Check that the candidate is a non-external ascii string. 10981 // Check that the candidate is a non-external ascii string.
10973 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset)); 10982 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset));
10974 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 10983 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
10975 __ JumpIfInstanceTypeIsNotSequentialAscii( 10984 __ JumpIfInstanceTypeIsNotSequentialAscii(
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
11199 Register right, 11208 Register right,
11200 Register scratch1, 11209 Register scratch1,
11201 Register scratch2, 11210 Register scratch2,
11202 Register scratch3, 11211 Register scratch3,
11203 Register scratch4) { 11212 Register scratch4) {
11204 // Ensure that you can always subtract a string length from a non-negative 11213 // Ensure that you can always subtract a string length from a non-negative
11205 // number (e.g. another length). 11214 // number (e.g. another length).
11206 ASSERT(String::kMaxLength < 0x7fffffff); 11215 ASSERT(String::kMaxLength < 0x7fffffff);
11207 11216
11208 // Find minimum length and length difference. 11217 // Find minimum length and length difference.
11209 __ movl(scratch1, FieldOperand(left, String::kLengthOffset)); 11218 __ movq(scratch1, FieldOperand(left, String::kLengthOffset));
11210 __ movl(scratch4, scratch1); 11219 __ movq(scratch4, scratch1);
11211 __ subl(scratch4, FieldOperand(right, String::kLengthOffset)); 11220 __ SmiSub(scratch4,
11221 scratch4,
11222 FieldOperand(right, String::kLengthOffset),
11223 NULL);
11212 // Register scratch4 now holds left.length - right.length. 11224 // Register scratch4 now holds left.length - right.length.
11213 const Register length_difference = scratch4; 11225 const Register length_difference = scratch4;
11214 Label left_shorter; 11226 Label left_shorter;
11215 __ j(less, &left_shorter); 11227 __ j(less, &left_shorter);
11216 // The right string isn't longer that the left one. 11228 // The right string isn't longer that the left one.
11217 // Get the right string's length by subtracting the (non-negative) difference 11229 // Get the right string's length by subtracting the (non-negative) difference
11218 // from the left string's length. 11230 // from the left string's length.
11219 __ subl(scratch1, length_difference); 11231 __ SmiSub(scratch1, scratch1, length_difference, NULL);
11220 __ bind(&left_shorter); 11232 __ bind(&left_shorter);
11221 // Register scratch1 now holds Min(left.length, right.length). 11233 // Register scratch1 now holds Min(left.length, right.length).
11222 const Register min_length = scratch1; 11234 const Register min_length = scratch1;
11223 11235
11224 Label compare_lengths; 11236 Label compare_lengths;
11225 // If min-length is zero, go directly to comparing lengths. 11237 // If min-length is zero, go directly to comparing lengths.
11226 __ testl(min_length, min_length); 11238 __ SmiTest(min_length);
11227 __ j(zero, &compare_lengths); 11239 __ j(zero, &compare_lengths);
11228 11240
11241 __ SmiToInteger32(min_length, min_length);
11242
11229 // Registers scratch2 and scratch3 are free. 11243 // Registers scratch2 and scratch3 are free.
11230 Label result_not_equal; 11244 Label result_not_equal;
11231 Label loop; 11245 Label loop;
11232 { 11246 {
11233 // Check characters 0 .. min_length - 1 in a loop. 11247 // Check characters 0 .. min_length - 1 in a loop.
11234 // Use scratch3 as loop index, min_length as limit and scratch2 11248 // Use scratch3 as loop index, min_length as limit and scratch2
11235 // for computation. 11249 // for computation.
11236 const Register index = scratch3; 11250 const Register index = scratch3;
11237 __ movl(index, Immediate(0)); // Index into strings. 11251 __ movl(index, Immediate(0)); // Index into strings.
11238 __ bind(&loop); 11252 __ bind(&loop);
(...skipping 10 matching lines...) Expand all
11249 index, 11263 index,
11250 times_1, 11264 times_1,
11251 SeqAsciiString::kHeaderSize - 1)); 11265 SeqAsciiString::kHeaderSize - 1));
11252 __ j(not_equal, &result_not_equal); 11266 __ j(not_equal, &result_not_equal);
11253 __ cmpl(index, min_length); 11267 __ cmpl(index, min_length);
11254 __ j(not_equal, &loop); 11268 __ j(not_equal, &loop);
11255 } 11269 }
11256 // Completed loop without finding different characters. 11270 // Completed loop without finding different characters.
11257 // Compare lengths (precomputed). 11271 // Compare lengths (precomputed).
11258 __ bind(&compare_lengths); 11272 __ bind(&compare_lengths);
11259 __ testl(length_difference, length_difference); 11273 __ SmiTest(length_difference);
11260 __ j(not_zero, &result_not_equal); 11274 __ j(not_zero, &result_not_equal);
11261 11275
11262 // Result is EQUAL. 11276 // Result is EQUAL.
11263 __ Move(rax, Smi::FromInt(EQUAL)); 11277 __ Move(rax, Smi::FromInt(EQUAL));
11264 __ ret(2 * kPointerSize); 11278 __ ret(2 * kPointerSize);
11265 11279
11266 Label result_greater; 11280 Label result_greater;
11267 __ bind(&result_not_equal); 11281 __ bind(&result_not_equal);
11268 // Unequal comparison of left to right, either character or length. 11282 // Unequal comparison of left to right, either character or length.
11269 __ j(greater, &result_greater); 11283 __ j(greater, &result_greater);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
11403 // Call the function from C++. 11417 // Call the function from C++.
11404 return FUNCTION_CAST<ModuloFunction>(buffer); 11418 return FUNCTION_CAST<ModuloFunction>(buffer);
11405 } 11419 }
11406 11420
11407 #endif 11421 #endif
11408 11422
11409 11423
11410 #undef __ 11424 #undef __
11411 11425
11412 } } // namespace v8::internal 11426 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects-inl.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698