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

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

Issue 119302: Change IA32's CodeGenerator::GenerateFastCharCodeAt to eagerly... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 4607 matching lines...) Expand 10 before | Expand all | Expand 10 after
4618 } 4618 }
4619 4619
4620 4620
4621 // This generates code that performs a charCodeAt() call or returns 4621 // This generates code that performs a charCodeAt() call or returns
4622 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 4622 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
4623 // It can handle flat and sliced strings, 8 and 16 bit characters and 4623 // It can handle flat and sliced strings, 8 and 16 bit characters and
4624 // cons strings where the answer is found in the left hand branch of the 4624 // cons strings where the answer is found in the left hand branch of the
4625 // cons. The slow case will flatten the string, which will ensure that 4625 // cons. The slow case will flatten the string, which will ensure that
4626 // the answer is in the left hand side the next time around. 4626 // the answer is in the left hand side the next time around.
4627 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 4627 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
4628 Comment(masm_, "[ GenerateFastCharCodeAt");
4628 ASSERT(args->length() == 2); 4629 ASSERT(args->length() == 2);
4629 4630
4630 JumpTarget slow_case; 4631 Label slow_case;
4631 JumpTarget end; 4632 Label end;
4632 JumpTarget not_a_flat_string; 4633 Label not_a_flat_string;
4633 JumpTarget a_cons_string; 4634 Label a_cons_string;
4634 JumpTarget try_again_with_new_string(JumpTarget::BIDIRECTIONAL); 4635 Label try_again_with_new_string;
4635 JumpTarget ascii_string; 4636 Label ascii_string;
4636 JumpTarget got_char_code; 4637 Label got_char_code;
4637 4638
4638 Load(args->at(0)); 4639 Load(args->at(0));
4639 Load(args->at(1)); 4640 Load(args->at(1));
4640 // Reserve register ecx, to use as shift amount later
4641 Result shift_amount = allocator()->Allocate(ecx);
4642 ASSERT(shift_amount.is_valid());
4643 Result index = frame_->Pop(); 4641 Result index = frame_->Pop();
4642 Result object = frame_->Pop();
4643
4644 // Get register ecx to use as shift amount later.
4645 Result shift_amount;
4646 if (object.is_register() && object.reg().is(ecx)) {
4647 Result fresh = allocator_->Allocate();
4648 shift_amount = object;
4649 object = fresh;
4650 __ mov(object.reg(), ecx);
4651 }
4652 if (index.is_register() && index.reg().is(ecx)) {
4653 Result fresh = allocator_->Allocate();
4654 shift_amount = index;
4655 index = fresh;
4656 __ mov(index.reg(), ecx);
4657 }
4658 // There could be references to ecx in the frame. Allocating will
4659 // spill them, otherwise spill explicitly.
4660 if (shift_amount.is_valid()) {
4661 frame_->Spill(ecx);
4662 } else {
4663 shift_amount = allocator()->Allocate(ecx);
4664 }
4665 ASSERT(shift_amount.is_register());
4666 ASSERT(shift_amount.reg().is(ecx));
4667 ASSERT(allocator_->count(ecx) == 1);
4668
4669 // We will mutate the index register and possibly the object register.
4670 // The case where they are somehow the same register is handled
4671 // because we only mutate them in the case where the receiver is a
4672 // heap object and the index is not.
4673 object.ToRegister();
4644 index.ToRegister(); 4674 index.ToRegister();
4645 Result object = frame_->Pop(); 4675 frame_->Spill(object.reg());
4646 object.ToRegister(); 4676 frame_->Spill(index.reg());
4647 // If the receiver is a smi return undefined. 4677
4678 // We need a single extra temporary register.
4679 Result temp = allocator()->Allocate();
4680 ASSERT(temp.is_valid());
4681
4682 // There is no virtual frame effect from here up to the final result
4683 // push.
4684
4685 // If the receiver is a smi trigger the slow case.
4648 ASSERT(kSmiTag == 0); 4686 ASSERT(kSmiTag == 0);
4649 __ test(object.reg(), Immediate(kSmiTagMask)); 4687 __ test(object.reg(), Immediate(kSmiTagMask));
4650 slow_case.Branch(zero, not_taken); 4688 __ j(zero, &slow_case);
4651 4689
4652 // Check for negative or non-smi index. 4690 // If the index is negative or non-smi trigger the slow case.
4653 ASSERT(kSmiTag == 0); 4691 ASSERT(kSmiTag == 0);
4654 __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000)); 4692 __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000));
4655 slow_case.Branch(not_zero, not_taken); 4693 __ j(not_zero, &slow_case);
4656 // Get rid of the smi tag on the index. 4694 // Untag the index.
4657 frame_->Spill(index.reg());
4658 __ sar(index.reg(), kSmiTagSize); 4695 __ sar(index.reg(), kSmiTagSize);
4659 4696
4660 try_again_with_new_string.Bind(&object, &index, &shift_amount); 4697 __ bind(&try_again_with_new_string);
4661 // Get the type of the heap object. 4698 // Fetch the instance type of the receiver into ecx.
4662 Result object_type = allocator()->Allocate(); 4699 __ mov(ecx, FieldOperand(object.reg(), HeapObject::kMapOffset));
4663 ASSERT(object_type.is_valid()); 4700 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
4664 __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset)); 4701 // If the receiver is not a string trigger the slow case.
4665 __ movzx_b(object_type.reg(), 4702 __ test(ecx, Immediate(kIsNotStringMask));
4666 FieldOperand(object_type.reg(), Map::kInstanceTypeOffset)); 4703 __ j(not_zero, &slow_case);
4667 // We don't handle non-strings.
4668 __ test(object_type.reg(), Immediate(kIsNotStringMask));
4669 slow_case.Branch(not_zero, not_taken);
4670 4704
4671 // Here we make assumptions about the tag values and the shifts needed. 4705 // Here we make assumptions about the tag values and the shifts needed.
4672 // See the comment in objects.h. 4706 // See the comment in objects.h.
4673 ASSERT(kLongStringTag == 0); 4707 ASSERT(kLongStringTag == 0);
4674 ASSERT(kMediumStringTag + String::kLongLengthShift == 4708 ASSERT(kMediumStringTag + String::kLongLengthShift ==
4675 String::kMediumLengthShift); 4709 String::kMediumLengthShift);
4676 ASSERT(kShortStringTag + String::kLongLengthShift == 4710 ASSERT(kShortStringTag + String::kLongLengthShift ==
4677 String::kShortLengthShift); 4711 String::kShortLengthShift);
4678 __ mov(shift_amount.reg(), Operand(object_type.reg())); 4712 __ and_(ecx, kStringSizeMask);
4679 __ and_(shift_amount.reg(), kStringSizeMask); 4713 __ add(Operand(ecx), Immediate(String::kLongLengthShift));
4680 __ add(Operand(shift_amount.reg()), Immediate(String::kLongLengthShift)); 4714 // Fetch the length field into the temporary register.
4681 // Get the length field. Temporary register now used for length. 4715 __ mov(temp.reg(), FieldOperand(object.reg(), String::kLengthOffset));
4682 Result length = object_type; 4716 __ shr(temp.reg()); // The shift amount in ecx is implicit operand.
4683 __ mov(length.reg(), FieldOperand(object.reg(), String::kLengthOffset));
4684 __ shr(length.reg()); // shift_amount, in ecx, is implicit operand.
4685 // Check for index out of range. 4717 // Check for index out of range.
4686 __ cmp(index.reg(), Operand(length.reg())); 4718 __ cmp(index.reg(), Operand(temp.reg()));
4687 slow_case.Branch(greater_equal, not_taken); 4719 __ j(greater_equal, &slow_case);
4688 length.Unuse(); 4720 // Reload the instance type (into the temp register this time)..
4689 // Load the object type into object_type again. 4721 __ mov(temp.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
4690 // These two instructions are duplicated from above, to save a register. 4722 __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
4691 __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
4692 __ movzx_b(object_type.reg(),
4693 FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
4694 4723
4695 // We need special handling for non-flat strings. 4724 // We need special handling for non-flat strings.
4696 ASSERT(kSeqStringTag == 0); 4725 ASSERT(kSeqStringTag == 0);
4697 __ test(object_type.reg(), Immediate(kStringRepresentationMask)); 4726 __ test(temp.reg(), Immediate(kStringRepresentationMask));
4698 not_a_flat_string.Branch(not_zero, &object, &index, &object_type, 4727 __ j(not_zero, &not_a_flat_string);
4699 &shift_amount, not_taken);
4700 shift_amount.Unuse();
4701 // Check for 1-byte or 2-byte string. 4728 // Check for 1-byte or 2-byte string.
4702 __ test(object_type.reg(), Immediate(kStringEncodingMask)); 4729 __ test(temp.reg(), Immediate(kStringEncodingMask));
4703 ascii_string.Branch(not_zero, &object, &index, &object_type, taken); 4730 __ j(not_zero, &ascii_string);
4704 4731
4705 // 2-byte string. 4732 // 2-byte string.
4706 // Load the 2-byte character code. 4733 // Load the 2-byte character code into the temp register.
4707 __ movzx_w(object_type.reg(), FieldOperand(object.reg(), 4734 __ movzx_w(temp.reg(), FieldOperand(object.reg(),
4708 index.reg(), 4735 index.reg(),
4709 times_2, 4736 times_2,
4710 SeqTwoByteString::kHeaderSize)); 4737 SeqTwoByteString::kHeaderSize));
4711 object.Unuse(); 4738 __ jmp(&got_char_code);
4712 index.Unuse();
4713 got_char_code.Jump(&object_type);
4714 4739
4715 // ASCII string. 4740 // ASCII string.
4716 ascii_string.Bind(&object, &index, &object_type); 4741 __ bind(&ascii_string);
4717 // Load the byte. 4742 // Load the byte into the temp register.
4718 __ movzx_b(object_type.reg(), FieldOperand(object.reg(), 4743 __ movzx_b(temp.reg(), FieldOperand(object.reg(),
4719 index.reg(), 4744 index.reg(),
4720 times_1, 4745 times_1,
4721 SeqAsciiString::kHeaderSize)); 4746 SeqAsciiString::kHeaderSize));
4722 object.Unuse(); 4747 __ bind(&got_char_code);
4723 index.Unuse();
4724 got_char_code.Bind(&object_type);
4725 ASSERT(kSmiTag == 0); 4748 ASSERT(kSmiTag == 0);
4726 __ shl(object_type.reg(), kSmiTagSize); 4749 __ shl(temp.reg(), kSmiTagSize);
4727 frame_->Push(&object_type); 4750 __ jmp(&end);
4728 end.Jump();
4729 4751
4730 // Handle non-flat strings. 4752 // Handle non-flat strings.
4731 not_a_flat_string.Bind(&object, &index, &object_type, &shift_amount); 4753 __ bind(&not_a_flat_string);
4732 __ and_(object_type.reg(), kStringRepresentationMask); 4754 __ and_(temp.reg(), kStringRepresentationMask);
4733 __ cmp(object_type.reg(), kConsStringTag); 4755 __ cmp(temp.reg(), kConsStringTag);
4734 a_cons_string.Branch(equal, &object, &index, &shift_amount, taken); 4756 __ j(equal, &a_cons_string);
4735 __ cmp(object_type.reg(), kSlicedStringTag); 4757 __ cmp(temp.reg(), kSlicedStringTag);
4736 slow_case.Branch(not_equal, not_taken); 4758 __ j(not_equal, &slow_case);
4737 object_type.Unuse();
4738 4759
4739 // SlicedString. 4760 // SlicedString.
4740 // Add the offset to the index. 4761 // Add the offset to the index and trigger the slow case on overflow.
4741 __ add(index.reg(), FieldOperand(object.reg(), SlicedString::kStartOffset)); 4762 __ add(index.reg(), FieldOperand(object.reg(), SlicedString::kStartOffset));
4742 slow_case.Branch(overflow); 4763 __ j(overflow, &slow_case);
4743 // Getting the underlying string is done by running the cons string code. 4764 // Getting the underlying string is done by running the cons string code.
4744 4765
4745 // ConsString. 4766 // ConsString.
4746 a_cons_string.Bind(&object, &index, &shift_amount); 4767 __ bind(&a_cons_string);
4747 // Get the first of the two strings. 4768 // Get the first of the two strings. Both sliced and cons strings
4748 frame_->Spill(object.reg()); 4769 // store their source string at the same offset.
4749 // Both sliced and cons strings store their source string at the same place.
4750 ASSERT(SlicedString::kBufferOffset == ConsString::kFirstOffset); 4770 ASSERT(SlicedString::kBufferOffset == ConsString::kFirstOffset);
4751 __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset)); 4771 __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset));
4752 try_again_with_new_string.Jump(&object, &index, &shift_amount); 4772 __ jmp(&try_again_with_new_string);
4753 4773
4754 // No results live at this point. 4774 __ bind(&slow_case);
4755 slow_case.Bind(); 4775 // Move the undefined value into the result register, which will
4756 frame_->Push(Factory::undefined_value()); 4776 // trigger the slow case.
4757 end.Bind(); 4777 __ Set(temp.reg(), Immediate(Factory::undefined_value()));
4778
4779 __ bind(&end);
4780 frame_->Push(&temp);
4758 } 4781 }
4759 4782
4760 4783
4761 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 4784 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
4762 ASSERT(args->length() == 1); 4785 ASSERT(args->length() == 1);
4763 Load(args->at(0)); 4786 Load(args->at(0));
4764 Result value = frame_->Pop(); 4787 Result value = frame_->Pop();
4765 value.ToRegister(); 4788 value.ToRegister();
4766 ASSERT(value.is_valid()); 4789 ASSERT(value.is_valid());
4767 __ test(value.reg(), Immediate(kSmiTagMask)); 4790 __ test(value.reg(), Immediate(kSmiTagMask));
(...skipping 2543 matching lines...) Expand 10 before | Expand all | Expand 10 after
7311 7334
7312 // Slow-case: Go through the JavaScript implementation. 7335 // Slow-case: Go through the JavaScript implementation.
7313 __ bind(&slow); 7336 __ bind(&slow);
7314 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7337 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7315 } 7338 }
7316 7339
7317 7340
7318 #undef __ 7341 #undef __
7319 7342
7320 } } // namespace v8::internal 7343 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698