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

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

Issue 164135: X64: Implement fast charCodeAt. (Closed)
Patch Set: Created 11 years, 4 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
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | 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 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 3405 matching lines...) Expand 10 before | Expand all | Expand 10 after
3416 // ArgumentsAccessStub takes the parameter count as an input argument 3416 // ArgumentsAccessStub takes the parameter count as an input argument
3417 // in register eax. Create a constant result for it. 3417 // in register eax. Create a constant result for it.
3418 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); 3418 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
3419 // Call the shared stub to get to the arguments.length. 3419 // Call the shared stub to get to the arguments.length.
3420 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 3420 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
3421 Result result = frame_->CallStub(&stub, &count); 3421 Result result = frame_->CallStub(&stub, &count);
3422 frame_->Push(&result); 3422 frame_->Push(&result);
3423 } 3423 }
3424 3424
3425 3425
3426 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* a) { 3426 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3427 // TODO(X64): Implement this function. 3427 Comment(masm_, "[ GenerateFastCharCodeAt");
3428 // Ignore arguments and return undefined, to signal failure. 3428 ASSERT(args->length() == 2);
3429 frame_->Push(Factory::undefined_value()); 3429
3430 Label slow_case;
3431 Label end;
3432 Label not_a_flat_string;
3433 Label a_cons_string;
3434 Label try_again_with_new_string;
3435 Label ascii_string;
3436 Label got_char_code;
3437
3438 Load(args->at(0));
3439 Load(args->at(1));
3440 Result index = frame_->Pop();
3441 Result object = frame_->Pop();
3442
3443 // Get register rcx to use as shift amount later.
3444 Result shift_amount;
3445 if (object.is_register() && object.reg().is(rcx)) {
3446 Result fresh = allocator_->Allocate();
3447 shift_amount = object;
3448 object = fresh;
3449 __ movq(object.reg(), rcx);
3450 }
3451 if (index.is_register() && index.reg().is(rcx)) {
3452 Result fresh = allocator_->Allocate();
3453 shift_amount = index;
3454 index = fresh;
3455 __ movq(index.reg(), rcx);
3456 }
3457 // There could be references to ecx in the frame. Allocating will
3458 // spill them, otherwise spill explicitly.
3459 if (shift_amount.is_valid()) {
3460 frame_->Spill(rcx);
3461 } else {
3462 shift_amount = allocator()->Allocate(rcx);
3463 }
3464 ASSERT(shift_amount.is_register());
3465 ASSERT(shift_amount.reg().is(rcx));
3466 ASSERT(allocator_->count(rcx) == 1);
3467
3468 // We will mutate the index register and possibly the object register.
3469 // The case where they are somehow the same register is handled
3470 // because we only mutate them in the case where the receiver is a
3471 // heap object and the index is not.
3472 object.ToRegister();
3473 index.ToRegister();
3474 frame_->Spill(object.reg());
3475 frame_->Spill(index.reg());
3476
3477 // We need a single extra temporary register.
3478 Result temp = allocator()->Allocate();
3479 ASSERT(temp.is_valid());
3480
3481 // There is no virtual frame effect from here up to the final result
3482 // push.
3483
3484 // If the receiver is a smi trigger the slow case.
3485 ASSERT(kSmiTag == 0);
3486 __ testl(object.reg(), Immediate(kSmiTagMask));
3487 __ j(zero, &slow_case);
3488
3489 // If the index is negative or non-smi trigger the slow case.
3490 ASSERT(kSmiTag == 0);
3491 __ testl(index.reg(),
3492 Immediate(static_cast<uint32_t>(kSmiTagMask | 0x80000000U)));
William Hesse 2009/08/07 10:27:15 shouldn't this be a static cast to int32_t. I thi
Lasse Reichstein 2009/08/07 10:44:27 Done.
3493 __ j(not_zero, &slow_case);
3494 // Untag the index.
3495 __ sarl(index.reg(), Immediate(kSmiTagSize));
3496
3497 __ bind(&try_again_with_new_string);
3498 // Fetch the instance type of the receiver into rcx.
3499 __ movq(rcx, FieldOperand(object.reg(), HeapObject::kMapOffset));
3500 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
3501 // If the receiver is not a string trigger the slow case.
3502 __ testb(rcx, Immediate(kIsNotStringMask));
3503 __ j(not_zero, &slow_case);
3504
3505 // Here we make assumptions about the tag values and the shifts needed.
3506 // See the comment in objects.h.
3507 ASSERT(kLongStringTag == 0);
3508 ASSERT(kMediumStringTag + String::kLongLengthShift ==
3509 String::kMediumLengthShift);
3510 ASSERT(kShortStringTag + String::kLongLengthShift ==
3511 String::kShortLengthShift);
3512 __ and_(rcx, Immediate(kStringSizeMask));
3513 __ addq(rcx, Immediate(String::kLongLengthShift));
3514 // Fetch the length field into the temporary register.
3515 __ movl(temp.reg(), FieldOperand(object.reg(), String::kLengthOffset));
3516 __ shrl(temp.reg()); // The shift amount in ecx is implicit operand.
William Hesse 2009/08/07 10:27:15 cl (low byte of rcx), not ecx. Is this a shr or sa
Lasse Reichstein 2009/08/07 10:44:27 Not sure whether high bit can be 1 (would be waste
3517 // Check for index out of range.
3518 __ cmpl(index.reg(), temp.reg());
3519 __ j(greater_equal, &slow_case);
William Hesse 2009/08/07 10:27:15 greater_equal or below_equal? Are either of these
Lasse Reichstein 2009/08/07 10:44:27 The string length is definitly positive, the index
3520 // Reload the instance type (into the temp register this time)..
3521 __ movq(temp.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
3522 __ movzxbl(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
3523
3524 // We need special handling for non-flat strings.
3525 ASSERT(kSeqStringTag == 0);
3526 __ testb(temp.reg(), Immediate(kStringRepresentationMask));
3527 __ j(not_zero, &not_a_flat_string);
3528 // Check for 1-byte or 2-byte string.
3529 __ testb(temp.reg(), Immediate(kStringEncodingMask));
3530 __ j(not_zero, &ascii_string);
3531
3532 // 2-byte string.
3533 // Load the 2-byte character code into the temp register.
3534 __ movzxwl(temp.reg(), FieldOperand(object.reg(),
William Hesse 2009/08/07 10:27:15 Add the new operations to the disassembler.
Lasse Reichstein 2009/08/07 10:44:27 Already there. It's just a another operand size fo
Lasse Reichstein 2009/08/07 10:44:27 Already there. It's just a another operand size fo
3535 index.reg(),
3536 times_2,
3537 SeqTwoByteString::kHeaderSize));
3538 __ jmp(&got_char_code);
3539
3540 // ASCII string.
3541 __ bind(&ascii_string);
3542 // Load the byte into the temp register.
3543 __ movzxbl(temp.reg(), FieldOperand(object.reg(),
3544 index.reg(),
3545 times_1,
3546 SeqAsciiString::kHeaderSize));
3547 __ bind(&got_char_code);
3548 ASSERT(kSmiTag == 0);
3549 __ shl(temp.reg(), Immediate(kSmiTagSize));
3550 __ jmp(&end);
3551
3552 // Handle non-flat strings.
3553 __ bind(&not_a_flat_string);
3554 __ and_(temp.reg(), Immediate(kStringRepresentationMask));
3555 __ cmpb(temp.reg(), Immediate(kConsStringTag));
3556 __ j(equal, &a_cons_string);
3557 __ cmpb(temp.reg(), Immediate(kSlicedStringTag));
3558 __ j(not_equal, &slow_case);
3559
3560 // SlicedString.
3561 // Add the offset to the index and trigger the slow case on overflow.
3562 __ addl(index.reg(), FieldOperand(object.reg(), SlicedString::kStartOffset));
3563 __ j(overflow, &slow_case);
3564 // Getting the underlying string is done by running the cons string code.
3565
3566 // ConsString.
3567 __ bind(&a_cons_string);
3568 // Get the first of the two strings. Both sliced and cons strings
3569 // store their source string at the same offset.
3570 ASSERT(SlicedString::kBufferOffset == ConsString::kFirstOffset);
3571 __ movq(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset));
3572 __ jmp(&try_again_with_new_string);
3573
3574 __ bind(&slow_case);
3575 // Move the undefined value into the result register, which will
3576 // trigger the slow case.
3577 __ Move(temp.reg(), Factory::undefined_value());
3578
3579 __ bind(&end);
3580 frame_->Push(&temp);
3430 } 3581 }
3431 3582
3432 3583
3433 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3584 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3434 ASSERT(args->length() == 1); 3585 ASSERT(args->length() == 1);
3435 Load(args->at(0)); 3586 Load(args->at(0));
3436 Result value = frame_->Pop(); 3587 Result value = frame_->Pop();
3437 value.ToRegister(); 3588 value.ToRegister();
3438 ASSERT(value.is_valid()); 3589 ASSERT(value.is_valid());
3439 __ testl(value.reg(), 3590 __ testl(value.reg(),
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
4145 __ Cmp(value.reg(), Factory::the_hole_value()); 4296 __ Cmp(value.reg(), Factory::the_hole_value());
4146 frame_->Push(&value); 4297 frame_->Push(&value);
4147 exit.Branch(not_equal); 4298 exit.Branch(not_equal);
4148 Result arguments = StoreArgumentsObject(false); 4299 Result arguments = StoreArgumentsObject(false);
4149 frame_->SetElementAt(0, &arguments); 4300 frame_->SetElementAt(0, &arguments);
4150 exit.Bind(); 4301 exit.Bind();
4151 } 4302 }
4152 4303
4153 4304
4154 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 4305 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
4155 // TODO(X64): Enable more types of slot.
4156
4157 if (slot->type() == Slot::LOOKUP) { 4306 if (slot->type() == Slot::LOOKUP) {
4158 ASSERT(slot->var()->is_dynamic()); 4307 ASSERT(slot->var()->is_dynamic());
4159 4308
4160 // For now, just do a runtime call. Since the call is inevitable, 4309 // For now, just do a runtime call. Since the call is inevitable,
4161 // we eagerly sync the virtual frame so we can directly push the 4310 // we eagerly sync the virtual frame so we can directly push the
4162 // arguments into place. 4311 // arguments into place.
4163 frame_->SyncRange(0, frame_->element_count() - 1); 4312 frame_->SyncRange(0, frame_->element_count() - 1);
4164 4313
4165 frame_->EmitPush(rsi); 4314 frame_->EmitPush(rsi);
4166 frame_->EmitPush(slot->var()->name()); 4315 frame_->EmitPush(slot->var()->name());
(...skipping 3114 matching lines...) Expand 10 before | Expand all | Expand 10 after
7281 int CompareStub::MinorKey() { 7430 int CompareStub::MinorKey() {
7282 // Encode the two parameters in a unique 16 bit value. 7431 // Encode the two parameters in a unique 16 bit value.
7283 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7432 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7284 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7433 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7285 } 7434 }
7286 7435
7287 7436
7288 #undef __ 7437 #undef __
7289 7438
7290 } } // namespace v8::internal 7439 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698