OLD | NEW |
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 Loading... |
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 Loading... |
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, ¬_string); | 7517 __ j(above_equal, ¬_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(¬_string); | 7523 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_a_flat_string); | 10475 __ j(not_zero, ¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |