| 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 |