OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 5429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5440 Load(args->at(0)); | 5440 Load(args->at(0)); |
5441 Load(args->at(1)); | 5441 Load(args->at(1)); |
5442 Load(args->at(2)); | 5442 Load(args->at(2)); |
5443 | 5443 |
5444 SubStringStub stub; | 5444 SubStringStub stub; |
5445 Result answer = frame_->CallStub(&stub, 3); | 5445 Result answer = frame_->CallStub(&stub, 3); |
5446 frame_->Push(&answer); | 5446 frame_->Push(&answer); |
5447 } | 5447 } |
5448 | 5448 |
5449 | 5449 |
| 5450 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { |
| 5451 ASSERT_EQ(2, args->length()); |
| 5452 |
| 5453 Load(args->at(0)); |
| 5454 Load(args->at(1)); |
| 5455 |
| 5456 StringCompareStub stub; |
| 5457 Result answer = frame_->CallStub(&stub, 2); |
| 5458 frame_->Push(&answer); |
| 5459 } |
| 5460 |
| 5461 |
5450 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 5462 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
5451 ASSERT_EQ(args->length(), 4); | 5463 ASSERT_EQ(args->length(), 4); |
5452 | 5464 |
5453 // Load the arguments on the stack and call the stub. | 5465 // Load the arguments on the stack and call the stub. |
5454 Load(args->at(0)); | 5466 Load(args->at(0)); |
5455 Load(args->at(1)); | 5467 Load(args->at(1)); |
5456 Load(args->at(2)); | 5468 Load(args->at(2)); |
5457 Load(args->at(3)); | 5469 Load(args->at(3)); |
5458 RegExpExecStub stub; | 5470 RegExpExecStub stub; |
5459 Result result = frame_->CallStub(&stub, 4); | 5471 Result result = frame_->CallStub(&stub, 4); |
(...skipping 3095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8555 ASSERT(cc_ != not_equal); | 8567 ASSERT(cc_ != not_equal); |
8556 if (cc_ == less || cc_ == less_equal) { | 8568 if (cc_ == less || cc_ == less_equal) { |
8557 __ mov(eax, Immediate(Smi::FromInt(1))); | 8569 __ mov(eax, Immediate(Smi::FromInt(1))); |
8558 } else { | 8570 } else { |
8559 __ mov(eax, Immediate(Smi::FromInt(-1))); | 8571 __ mov(eax, Immediate(Smi::FromInt(-1))); |
8560 } | 8572 } |
8561 __ ret(2 * kPointerSize); // eax, edx were pushed | 8573 __ ret(2 * kPointerSize); // eax, edx were pushed |
8562 | 8574 |
8563 // Fast negative check for symbol-to-symbol equality. | 8575 // Fast negative check for symbol-to-symbol equality. |
8564 __ bind(&check_for_symbols); | 8576 __ bind(&check_for_symbols); |
| 8577 Label check_for_strings; |
8565 if (cc_ == equal) { | 8578 if (cc_ == equal) { |
8566 BranchIfNonSymbol(masm, &call_builtin, eax, ecx); | 8579 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx); |
8567 BranchIfNonSymbol(masm, &call_builtin, edx, ecx); | 8580 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); |
8568 | 8581 |
8569 // We've already checked for object identity, so if both operands | 8582 // We've already checked for object identity, so if both operands |
8570 // are symbols they aren't equal. Register eax already holds a | 8583 // are symbols they aren't equal. Register eax already holds a |
8571 // non-zero value, which indicates not equal, so just return. | 8584 // non-zero value, which indicates not equal, so just return. |
8572 __ ret(2 * kPointerSize); | 8585 __ ret(2 * kPointerSize); |
8573 } | 8586 } |
8574 | 8587 |
| 8588 __ bind(&check_for_strings); |
| 8589 |
| 8590 // Check that both objects are not smis. |
| 8591 ASSERT_EQ(0, kSmiTag); |
| 8592 __ mov(ebx, Operand(edx)); |
| 8593 __ and_(ebx, Operand(eax)); |
| 8594 __ test(ebx, Immediate(kSmiTagMask)); |
| 8595 __ j(zero, &call_builtin); |
| 8596 |
| 8597 // Load instance type for both objects. |
| 8598 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 8599 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 8600 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| 8601 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 8602 |
| 8603 // Check that both are flat ascii strings. |
| 8604 Label non_ascii_flat; |
| 8605 ASSERT(kNotStringTag != 0); |
| 8606 const int kFlatAsciiString = |
| 8607 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 8608 __ and_(ecx, kFlatAsciiString); |
| 8609 __ cmp(ecx, kStringTag | kSeqStringTag | kAsciiStringTag); |
| 8610 __ j(not_equal, &call_builtin); |
| 8611 __ and_(ebx, kFlatAsciiString); |
| 8612 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); |
| 8613 __ j(not_equal, &call_builtin); |
| 8614 |
| 8615 // Inline comparison of ascii strings. |
| 8616 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
| 8617 edx, |
| 8618 eax, |
| 8619 ecx, |
| 8620 ebx, |
| 8621 edi); |
| 8622 #ifdef DEBUG |
| 8623 __ Abort("Unexpected fall-through from string comparison"); |
| 8624 #endif |
| 8625 |
8575 __ bind(&call_builtin); | 8626 __ bind(&call_builtin); |
8576 // must swap argument order | 8627 // must swap argument order |
8577 __ pop(ecx); | 8628 __ pop(ecx); |
8578 __ pop(edx); | 8629 __ pop(edx); |
8579 __ pop(eax); | 8630 __ pop(eax); |
8580 __ push(edx); | 8631 __ push(edx); |
8581 __ push(eax); | 8632 __ push(eax); |
8582 | 8633 |
8583 // Figure out which native to call and setup the arguments. | 8634 // Figure out which native to call and setup the arguments. |
8584 Builtins::JavaScript builtin; | 8635 Builtins::JavaScript builtin; |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9572 GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); | 9623 GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); |
9573 __ mov(esi, edx); // Restore esi. | 9624 __ mov(esi, edx); // Restore esi. |
9574 __ IncrementCounter(&Counters::sub_string_native, 1); | 9625 __ IncrementCounter(&Counters::sub_string_native, 1); |
9575 __ ret(3 * kPointerSize); | 9626 __ ret(3 * kPointerSize); |
9576 | 9627 |
9577 // Just jump to runtime to create the sub string. | 9628 // Just jump to runtime to create the sub string. |
9578 __ bind(&runtime); | 9629 __ bind(&runtime); |
9579 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); | 9630 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); |
9580 } | 9631 } |
9581 | 9632 |
| 9633 |
| 9634 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
| 9635 Register left, |
| 9636 Register right, |
| 9637 Register counter, |
| 9638 Register scratch1, |
| 9639 Register scratch2) { |
| 9640 ASSERT(counter.is(ecx)); |
| 9641 Label compare_lengths, compare_lengths_1; |
| 9642 |
| 9643 // Find minimum length. If either length is zero just compare lengths. |
| 9644 __ mov(counter, FieldOperand(left, String::kLengthOffset)); |
| 9645 __ test(counter, Operand(counter)); |
| 9646 __ j(zero, &compare_lengths_1); |
| 9647 __ mov(scratch1, FieldOperand(right, String::kLengthOffset)); |
| 9648 __ test(scratch1, Operand(scratch1)); |
| 9649 __ j(zero, &compare_lengths_1); |
| 9650 __ cmp(counter, Operand(scratch1)); |
| 9651 if (CpuFeatures::IsSupported(CMOV)) { |
| 9652 CpuFeatures::Scope use_cmov(CMOV); |
| 9653 __ cmov(less, counter, Operand(scratch1)); |
| 9654 } else { |
| 9655 Label l; |
| 9656 __ j(less, &l); |
| 9657 __ mov(counter, scratch1); |
| 9658 __ bind(&l); |
| 9659 } |
| 9660 |
| 9661 Label result_greater, result_less; |
| 9662 Label loop; |
| 9663 // Compare next character. |
| 9664 __ mov(scratch2, Immediate(-1)); // Index into strings. |
| 9665 __ bind(&loop); |
| 9666 // Compare characters. |
| 9667 __ add(Operand(scratch2), Immediate(1)); |
| 9668 __ mov_b(scratch1, Operand(left, |
| 9669 scratch2, |
| 9670 times_1, |
| 9671 SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 9672 __ subb(scratch1, Operand(right, |
| 9673 scratch2, |
| 9674 times_1, |
| 9675 SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 9676 __ loope(&loop); |
| 9677 // If min length characters match compare lengths otherwise last character |
| 9678 // compare is the result. |
| 9679 __ j(equal, &compare_lengths); |
| 9680 __ j(less, &result_less); |
| 9681 __ jmp(&result_greater); |
| 9682 |
| 9683 // Compare lengths. |
| 9684 Label result_not_equal; |
| 9685 __ bind(&compare_lengths); |
| 9686 __ mov(counter, FieldOperand(left, String::kLengthOffset)); |
| 9687 __ bind(&compare_lengths_1); |
| 9688 __ sub(counter, FieldOperand(right, String::kLengthOffset)); |
| 9689 __ j(not_zero, &result_not_equal); |
| 9690 |
| 9691 // Result is EQUAL. |
| 9692 ASSERT_EQ(0, EQUAL); |
| 9693 ASSERT_EQ(0, kSmiTag); |
| 9694 __ xor_(eax, Operand(eax)); |
| 9695 __ IncrementCounter(&Counters::string_compare_native, 1); |
| 9696 __ ret(2 * kPointerSize); |
| 9697 __ bind(&result_not_equal); |
| 9698 __ j(greater, &result_greater); |
| 9699 |
| 9700 // Result is LESS. |
| 9701 __ bind(&result_less); |
| 9702 __ mov(eax, Immediate(Smi::FromInt(LESS)->value())); |
| 9703 __ IncrementCounter(&Counters::string_compare_native, 1); |
| 9704 __ ret(2 * kPointerSize); |
| 9705 |
| 9706 // Result is GREATER. |
| 9707 __ bind(&result_greater); |
| 9708 __ mov(eax, Immediate(Smi::FromInt(GREATER)->value())); |
| 9709 __ IncrementCounter(&Counters::string_compare_native, 1); |
| 9710 __ ret(2 * kPointerSize); |
| 9711 } |
| 9712 |
| 9713 |
| 9714 void StringCompareStub::Generate(MacroAssembler* masm) { |
| 9715 Label runtime; |
| 9716 |
| 9717 // Stack frame on entry. |
| 9718 // esp[0]: return address |
| 9719 // esp[4]: right string |
| 9720 // esp[8]: left string |
| 9721 |
| 9722 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left |
| 9723 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right |
| 9724 |
| 9725 Label not_same; |
| 9726 __ cmp(edx, Operand(eax)); |
| 9727 __ j(not_equal, ¬_same); |
| 9728 ASSERT_EQ(0, EQUAL); |
| 9729 ASSERT_EQ(0, kSmiTag); |
| 9730 __ xor_(eax, Operand(eax)); |
| 9731 __ IncrementCounter(&Counters::string_compare_native, 1); |
| 9732 __ ret(2 * kPointerSize); |
| 9733 |
| 9734 __ bind(¬_same); |
| 9735 |
| 9736 // Check that both objects are not smis. |
| 9737 ASSERT_EQ(0, kSmiTag); |
| 9738 __ mov(ebx, Operand(edx)); |
| 9739 __ and_(ebx, Operand(eax)); |
| 9740 __ test(ebx, Immediate(kSmiTagMask)); |
| 9741 __ j(zero, &runtime); |
| 9742 |
| 9743 // Load instance type for both strings. |
| 9744 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 9745 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 9746 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| 9747 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 9748 |
| 9749 // Check that both are flat ascii strings. |
| 9750 Label non_ascii_flat; |
| 9751 __ and_(ecx, kStringRepresentationMask | kStringEncodingMask); |
| 9752 __ cmp(ecx, kSeqStringTag | kAsciiStringTag); |
| 9753 __ j(not_equal, &non_ascii_flat); |
| 9754 const int kFlatAsciiString = |
| 9755 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 9756 __ and_(ebx, kFlatAsciiString); |
| 9757 __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag); |
| 9758 __ j(not_equal, &non_ascii_flat); |
| 9759 |
| 9760 // Compare flat ascii strings. |
| 9761 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
| 9762 |
| 9763 __ bind(&non_ascii_flat); |
| 9764 |
| 9765 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 9766 // tagged as a small integer. |
| 9767 __ bind(&runtime); |
| 9768 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
| 9769 } |
| 9770 |
9582 #undef __ | 9771 #undef __ |
9583 | 9772 |
9584 } } // namespace v8::internal | 9773 } } // namespace v8::internal |
OLD | NEW |