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

Side by Side 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, 10 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 | src/jump-target.h » ('j') | 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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 3470 matching lines...) Expand 10 before | Expand all | Expand 10 after
3481 } 3481 }
3482 3482
3483 3483
3484 // This generates code that performs a charCodeAt() call or returns 3484 // This generates code that performs a charCodeAt() call or returns
3485 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3485 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3486 // It can handle flat and sliced strings, 8 and 16 bit characters and 3486 // It can handle flat and sliced strings, 8 and 16 bit characters and
3487 // cons strings where the answer is found in the left hand branch of the 3487 // cons strings where the answer is found in the left hand branch of the
3488 // cons. The slow case will flatten the string, which will ensure that 3488 // cons. The slow case will flatten the string, which will ensure that
3489 // the answer is in the left hand side the next time around. 3489 // the answer is in the left hand side the next time around.
3490 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3490 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3491 VirtualFrame::SpilledScope spilled_scope(this);
3492 ASSERT(args->length() == 2); 3491 ASSERT(args->length() == 2);
3493 3492
3494 JumpTarget slow_case(this); 3493 JumpTarget slow_case(this);
3495 JumpTarget end(this); 3494 JumpTarget end(this);
3496 JumpTarget not_a_flat_string(this); 3495 JumpTarget not_a_flat_string(this);
3497 JumpTarget not_a_cons_string_either(this); 3496 JumpTarget a_cons_string(this);
3498 JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL); 3497 JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL);
3499 JumpTarget ascii_string(this); 3498 JumpTarget ascii_string(this);
3500 JumpTarget got_char_code(this); 3499 JumpTarget got_char_code(this);
3501 3500
3502 // Load the string into eax and the index into ebx. 3501 Load(args->at(0));
3503 LoadAndSpill(args->at(0)); 3502 Load(args->at(1));
3504 LoadAndSpill(args->at(1)); 3503 // Reserve register ecx, to use as shift amount later
3505 frame_->EmitPop(ebx); 3504 Result shift_amount = allocator()->Allocate(ecx);
3506 frame_->EmitPop(eax); 3505 ASSERT(shift_amount.is_valid());
3506 Result index = frame_->Pop();
3507 index.ToRegister();
3508 Result object = frame_->Pop();
3509 object.ToRegister();
3507 // If the receiver is a smi return undefined. 3510 // If the receiver is a smi return undefined.
3508 ASSERT(kSmiTag == 0); 3511 ASSERT(kSmiTag == 0);
3509 __ test(eax, Immediate(kSmiTagMask)); 3512 __ test(object.reg(), Immediate(kSmiTagMask));
3510 slow_case.Branch(zero, not_taken); 3513 slow_case.Branch(zero, not_taken);
3511 3514
3512 // Check for negative or non-smi index. 3515 // Check for negative or non-smi index.
3513 ASSERT(kSmiTag == 0); 3516 ASSERT(kSmiTag == 0);
3514 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 3517 __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000));
3515 slow_case.Branch(not_zero, not_taken); 3518 slow_case.Branch(not_zero, not_taken);
3516 // Get rid of the smi tag on the index. 3519 // Get rid of the smi tag on the index.
3517 __ sar(ebx, kSmiTagSize); 3520 frame_->Spill(index.reg());
3521 __ sar(index.reg(), kSmiTagSize);
3518 3522
3519 try_again_with_new_string.Bind(); 3523 try_again_with_new_string.Bind(&object, &index, &shift_amount);
3520 // Get the type of the heap object into edi. 3524 // Get the type of the heap object.
3521 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3525 Result object_type = allocator()->Allocate();
3522 __ movzx_b(edi, FieldOperand(edx, Map::kInstanceTypeOffset)); 3526 ASSERT(object_type.is_valid());
3527 __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
3528 __ movzx_b(object_type.reg(),
3529 FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
3523 // We don't handle non-strings. 3530 // We don't handle non-strings.
3524 __ test(edi, Immediate(kIsNotStringMask)); 3531 __ test(object_type.reg(), Immediate(kIsNotStringMask));
3525 slow_case.Branch(not_zero, not_taken); 3532 slow_case.Branch(not_zero, not_taken);
3526 3533
3527 // Here we make assumptions about the tag values and the shifts needed. 3534 // Here we make assumptions about the tag values and the shifts needed.
3528 // See the comment in objects.h. 3535 // See the comment in objects.h.
3529 ASSERT(kLongStringTag == 0); 3536 ASSERT(kLongStringTag == 0);
3530 ASSERT(kMediumStringTag + String::kLongLengthShift == 3537 ASSERT(kMediumStringTag + String::kLongLengthShift ==
3531 String::kMediumLengthShift); 3538 String::kMediumLengthShift);
3532 ASSERT(kShortStringTag + String::kLongLengthShift == 3539 ASSERT(kShortStringTag + String::kLongLengthShift ==
3533 String::kShortLengthShift); 3540 String::kShortLengthShift);
3534 __ mov(ecx, Operand(edi)); 3541 __ mov(shift_amount.reg(), Operand(object_type.reg()));
3535 __ and_(ecx, kStringSizeMask); 3542 __ and_(shift_amount.reg(), kStringSizeMask);
3536 __ add(Operand(ecx), Immediate(String::kLongLengthShift)); 3543 __ add(Operand(shift_amount.reg()), Immediate(String::kLongLengthShift));
3537 // Get the length field. 3544 // Get the length field. Temporary register now used for length.
3538 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); 3545 Result length = object_type;
3539 __ shr(edx); // ecx is implicit operand. 3546 __ mov(length.reg(), FieldOperand(object.reg(), String::kLengthOffset));
3540 // edx is now the length of the string. 3547 __ shr(length.reg()); // shift_amount, in ecx, is implicit operand.
3541
3542 // Check for index out of range. 3548 // Check for index out of range.
3543 __ cmp(ebx, Operand(edx)); 3549 __ cmp(index.reg(), Operand(length.reg()));
3544 slow_case.Branch(greater_equal, not_taken); 3550 slow_case.Branch(greater_equal, not_taken);
3551 length.Unuse();
3552 // Load the object type into object_type again.
3553 // These two instructions are duplicated from above, to save a register.
3554 __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
3555 __ movzx_b(object_type.reg(),
3556 FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
3545 3557
3546 // We need special handling for non-flat strings. 3558 // We need special handling for non-flat strings.
3547 ASSERT(kSeqStringTag == 0); 3559 ASSERT(kSeqStringTag == 0);
3548 __ test(edi, Immediate(kStringRepresentationMask)); 3560 __ test(object_type.reg(), Immediate(kStringRepresentationMask));
3549 not_a_flat_string.Branch(not_zero, not_taken); 3561 not_a_flat_string.Branch(not_zero, &object, &index, &object_type,
3550 3562 &shift_amount, not_taken);
3563 shift_amount.Unuse();
3551 // Check for 1-byte or 2-byte string. 3564 // Check for 1-byte or 2-byte string.
3552 __ test(edi, Immediate(kStringEncodingMask)); 3565 __ test(object_type.reg(), Immediate(kStringEncodingMask));
3553 ascii_string.Branch(not_zero, taken); 3566 ascii_string.Branch(not_zero, &object, &index, &object_type, taken);
3554 3567
3555 // 2-byte string. 3568 // 2-byte string.
3556 // Load the 2-byte character code. 3569 // Load the 2-byte character code.
3557 __ movzx_w(eax, 3570 __ movzx_w(object_type.reg(), FieldOperand(object.reg(),
3558 FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); 3571 index.reg(),
3559 got_char_code.Jump(); 3572 times_2,
3573 SeqTwoByteString::kHeaderSize));
3574 object.Unuse();
3575 index.Unuse();
3576 got_char_code.Jump(&object_type);
3560 3577
3561 // ASCII string. 3578 // ASCII string.
3562 ascii_string.Bind(); 3579 ascii_string.Bind(&object, &index, &object_type);
3563 // Load the byte. 3580 // Load the byte.
3564 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 3581 __ movzx_b(object_type.reg(), FieldOperand(object.reg(),
3565 3582 index.reg(),
3566 got_char_code.Bind(); 3583 times_1,
3584 SeqAsciiString::kHeaderSize));
3585 object.Unuse();
3586 index.Unuse();
3587 got_char_code.Bind(&object_type);
3567 ASSERT(kSmiTag == 0); 3588 ASSERT(kSmiTag == 0);
3568 __ shl(eax, kSmiTagSize); 3589 __ shl(object_type.reg(), kSmiTagSize);
3569 frame_->EmitPush(eax); 3590 frame_->Push(&object_type);
3570 end.Jump(); 3591 end.Jump();
3571 3592
3572 // Handle non-flat strings. 3593 // Handle non-flat strings.
3573 not_a_flat_string.Bind(); 3594 not_a_flat_string.Bind(&object, &index, &object_type, &shift_amount);
3574 __ and_(edi, kStringRepresentationMask); 3595 __ and_(object_type.reg(), kStringRepresentationMask);
3575 __ cmp(edi, kConsStringTag); 3596 __ cmp(object_type.reg(), kConsStringTag);
3576 not_a_cons_string_either.Branch(not_equal, not_taken); 3597 a_cons_string.Branch(equal, &object, &index, &shift_amount, taken);
3577 3598 __ cmp(object_type.reg(), kSlicedStringTag);
3578 // ConsString.
3579 // Get the first of the two strings.
3580 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
3581 try_again_with_new_string.Jump();
3582
3583 not_a_cons_string_either.Bind();
3584 __ cmp(edi, kSlicedStringTag);
3585 slow_case.Branch(not_equal, not_taken); 3599 slow_case.Branch(not_equal, not_taken);
3600 object_type.Unuse();
3586 3601
3587 // SlicedString. 3602 // SlicedString.
3588 // Add the offset to the index. 3603 // Add the offset to the index.
3589 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset)); 3604 __ add(index.reg(), FieldOperand(object.reg(), SlicedString::kStartOffset));
3590 slow_case.Branch(overflow); 3605 slow_case.Branch(overflow);
3591 // Get the underlying string. 3606 // Getting the underlying string is done by running the cons string code.
3592 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset));
3593 try_again_with_new_string.Jump();
3594 3607
3608 // ConsString.
3609 a_cons_string.Bind(&object, &index, &shift_amount);
3610 // Get the first of the two strings.
3611 frame_->Spill(object.reg());
3612 // Both sliced and cons strings store their source string at the same place.
3613 ASSERT(SlicedString::kBufferOffset == ConsString::kFirstOffset);
3614 __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset));
3615 try_again_with_new_string.Jump(&object, &index, &shift_amount);
3616
3617 // No results live at this point.
3595 slow_case.Bind(); 3618 slow_case.Bind();
3596 frame_->EmitPush(Immediate(Factory::undefined_value())); 3619 frame_->Push(Factory::undefined_value());
3597
3598 end.Bind(); 3620 end.Bind();
3599 } 3621 }
3600 3622
3601 3623
3602 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3624 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3603 ASSERT(args->length() == 1); 3625 ASSERT(args->length() == 1);
3604 Load(args->at(0)); 3626 Load(args->at(0));
3605 Result value = frame_->Pop(); 3627 Result value = frame_->Pop();
3606 value.ToRegister(); 3628 value.ToRegister();
3607 ASSERT(value.is_valid()); 3629 ASSERT(value.is_valid());
(...skipping 2658 matching lines...) Expand 10 before | Expand all | Expand 10 after
6266 6288
6267 // Slow-case: Go through the JavaScript implementation. 6289 // Slow-case: Go through the JavaScript implementation.
6268 __ bind(&slow); 6290 __ bind(&slow);
6269 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6291 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6270 } 6292 }
6271 6293
6272 6294
6273 #undef __ 6295 #undef __
6274 6296
6275 } } // namespace v8::internal 6297 } } // namespace v8::internal
OLDNEW
« 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