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

Unified Diff: src/codegen-ia32.cc

Issue 19425: Change FastCharCodeAt to use a virtual frame. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/jump-target.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-ia32.cc
===================================================================
--- src/codegen-ia32.cc (revision 1192)
+++ src/codegen-ia32.cc (working copy)
@@ -3488,113 +3488,135 @@
// cons. The slow case will flatten the string, which will ensure that
// the answer is in the left hand side the next time around.
void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
- VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 2);
JumpTarget slow_case(this);
JumpTarget end(this);
JumpTarget not_a_flat_string(this);
- JumpTarget not_a_cons_string_either(this);
+ JumpTarget a_cons_string(this);
JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL);
JumpTarget ascii_string(this);
JumpTarget got_char_code(this);
- // Load the string into eax and the index into ebx.
- LoadAndSpill(args->at(0));
- LoadAndSpill(args->at(1));
- frame_->EmitPop(ebx);
- frame_->EmitPop(eax);
+ Load(args->at(0));
+ Load(args->at(1));
+ // Reserve register ecx, to use as shift amount later
+ Result shift_amount = allocator()->Allocate(ecx);
+ ASSERT(shift_amount.is_valid());
+ Result index = frame_->Pop();
+ index.ToRegister();
+ Result object = frame_->Pop();
+ object.ToRegister();
// If the receiver is a smi return undefined.
ASSERT(kSmiTag == 0);
- __ test(eax, Immediate(kSmiTagMask));
+ __ test(object.reg(), Immediate(kSmiTagMask));
slow_case.Branch(zero, not_taken);
// Check for negative or non-smi index.
ASSERT(kSmiTag == 0);
- __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
+ __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000));
slow_case.Branch(not_zero, not_taken);
// Get rid of the smi tag on the index.
- __ sar(ebx, kSmiTagSize);
+ frame_->Spill(index.reg());
+ __ sar(index.reg(), kSmiTagSize);
- try_again_with_new_string.Bind();
- // Get the type of the heap object into edi.
- __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(edi, FieldOperand(edx, Map::kInstanceTypeOffset));
+ try_again_with_new_string.Bind(&object, &index, &shift_amount);
+ // Get the type of the heap object.
+ Result object_type = allocator()->Allocate();
+ ASSERT(object_type.is_valid());
+ __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
+ __ movzx_b(object_type.reg(),
+ FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
// We don't handle non-strings.
- __ test(edi, Immediate(kIsNotStringMask));
+ __ test(object_type.reg(), Immediate(kIsNotStringMask));
slow_case.Branch(not_zero, not_taken);
// Here we make assumptions about the tag values and the shifts needed.
// See the comment in objects.h.
ASSERT(kLongStringTag == 0);
ASSERT(kMediumStringTag + String::kLongLengthShift ==
- String::kMediumLengthShift);
+ String::kMediumLengthShift);
ASSERT(kShortStringTag + String::kLongLengthShift ==
- String::kShortLengthShift);
- __ mov(ecx, Operand(edi));
- __ and_(ecx, kStringSizeMask);
- __ add(Operand(ecx), Immediate(String::kLongLengthShift));
- // Get the length field.
- __ mov(edx, FieldOperand(eax, String::kLengthOffset));
- __ shr(edx); // ecx is implicit operand.
- // edx is now the length of the string.
-
+ String::kShortLengthShift);
+ __ mov(shift_amount.reg(), Operand(object_type.reg()));
+ __ and_(shift_amount.reg(), kStringSizeMask);
+ __ add(Operand(shift_amount.reg()), Immediate(String::kLongLengthShift));
+ // Get the length field. Temporary register now used for length.
+ Result length = object_type;
+ __ mov(length.reg(), FieldOperand(object.reg(), String::kLengthOffset));
+ __ shr(length.reg()); // shift_amount, in ecx, is implicit operand.
// Check for index out of range.
- __ cmp(ebx, Operand(edx));
+ __ cmp(index.reg(), Operand(length.reg()));
slow_case.Branch(greater_equal, not_taken);
+ length.Unuse();
+ // Load the object type into object_type again.
+ // These two instructions are duplicated from above, to save a register.
+ __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
+ __ movzx_b(object_type.reg(),
+ FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
// We need special handling for non-flat strings.
ASSERT(kSeqStringTag == 0);
- __ test(edi, Immediate(kStringRepresentationMask));
- not_a_flat_string.Branch(not_zero, not_taken);
-
+ __ test(object_type.reg(), Immediate(kStringRepresentationMask));
+ not_a_flat_string.Branch(not_zero, &object, &index, &object_type,
+ &shift_amount, not_taken);
+ shift_amount.Unuse();
// Check for 1-byte or 2-byte string.
- __ test(edi, Immediate(kStringEncodingMask));
- ascii_string.Branch(not_zero, taken);
+ __ test(object_type.reg(), Immediate(kStringEncodingMask));
+ ascii_string.Branch(not_zero, &object, &index, &object_type, taken);
// 2-byte string.
// Load the 2-byte character code.
- __ movzx_w(eax,
- FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
- got_char_code.Jump();
+ __ movzx_w(object_type.reg(), FieldOperand(object.reg(),
+ index.reg(),
+ times_2,
+ SeqTwoByteString::kHeaderSize));
+ object.Unuse();
+ index.Unuse();
+ got_char_code.Jump(&object_type);
// ASCII string.
- ascii_string.Bind();
+ ascii_string.Bind(&object, &index, &object_type);
// Load the byte.
- __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
-
- got_char_code.Bind();
+ __ movzx_b(object_type.reg(), FieldOperand(object.reg(),
+ index.reg(),
+ times_1,
+ SeqAsciiString::kHeaderSize));
+ object.Unuse();
+ index.Unuse();
+ got_char_code.Bind(&object_type);
ASSERT(kSmiTag == 0);
- __ shl(eax, kSmiTagSize);
- frame_->EmitPush(eax);
+ __ shl(object_type.reg(), kSmiTagSize);
+ frame_->Push(&object_type);
end.Jump();
// Handle non-flat strings.
- not_a_flat_string.Bind();
- __ and_(edi, kStringRepresentationMask);
- __ cmp(edi, kConsStringTag);
- not_a_cons_string_either.Branch(not_equal, not_taken);
-
- // ConsString.
- // Get the first of the two strings.
- __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
- try_again_with_new_string.Jump();
-
- not_a_cons_string_either.Bind();
- __ cmp(edi, kSlicedStringTag);
+ not_a_flat_string.Bind(&object, &index, &object_type, &shift_amount);
+ __ and_(object_type.reg(), kStringRepresentationMask);
+ __ cmp(object_type.reg(), kConsStringTag);
+ a_cons_string.Branch(equal, &object, &index, &shift_amount, taken);
+ __ cmp(object_type.reg(), kSlicedStringTag);
slow_case.Branch(not_equal, not_taken);
+ object_type.Unuse();
// SlicedString.
// Add the offset to the index.
- __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset));
+ __ add(index.reg(), FieldOperand(object.reg(), SlicedString::kStartOffset));
slow_case.Branch(overflow);
- // Get the underlying string.
- __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset));
- try_again_with_new_string.Jump();
+ // Getting the underlying string is done by running the cons string code.
+ // ConsString.
+ a_cons_string.Bind(&object, &index, &shift_amount);
+ // Get the first of the two strings.
+ frame_->Spill(object.reg());
+ // Both sliced and cons strings store their source string at the same place.
+ ASSERT(SlicedString::kBufferOffset == ConsString::kFirstOffset);
+ __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset));
+ try_again_with_new_string.Jump(&object, &index, &shift_amount);
+
+ // No results live at this point.
slow_case.Bind();
- frame_->EmitPush(Immediate(Factory::undefined_value()));
-
+ frame_->Push(Factory::undefined_value());
end.Bind();
}
« no previous file with comments | « no previous file | src/jump-target.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698