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

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

Issue 2266003: X64: Many small tweaks and more usages of "load smi as int32". (Closed)
Patch Set: Created 10 years, 7 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
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 __ movq(rax, Immediate(scope()->num_parameters())); 850 __ movq(rax, Immediate(scope()->num_parameters()));
851 for (int i = 0; i < scope()->num_parameters(); i++) { 851 for (int i = 0; i < scope()->num_parameters(); i++) {
852 __ push(frame_->ParameterAt(i)); 852 __ push(frame_->ParameterAt(i));
853 } 853 }
854 __ jmp(&invoke); 854 __ jmp(&invoke);
855 855
856 // Arguments adaptor frame present. Copy arguments from there, but 856 // Arguments adaptor frame present. Copy arguments from there, but
857 // avoid copying too many arguments to avoid stack overflows. 857 // avoid copying too many arguments to avoid stack overflows.
858 __ bind(&adapted); 858 __ bind(&adapted);
859 static const uint32_t kArgumentsLimit = 1 * KB; 859 static const uint32_t kArgumentsLimit = 1 * KB;
860 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 860 __ SmiToInteger32(rax,
861 __ SmiToInteger32(rax, rax); 861 Operand(rdx,
862 __ movq(rcx, rax); 862 ArgumentsAdaptorFrameConstants::kLengthOffset));
863 __ cmpq(rax, Immediate(kArgumentsLimit)); 863 __ movl(rcx, rax);
864 __ cmpl(rax, Immediate(kArgumentsLimit));
864 __ j(above, &build_args); 865 __ j(above, &build_args);
865 866
866 // Loop through the arguments pushing them onto the execution 867 // Loop through the arguments pushing them onto the execution
867 // stack. We don't inform the virtual frame of the push, so we don't 868 // stack. We don't inform the virtual frame of the push, so we don't
868 // have to worry about getting rid of the elements from the virtual 869 // have to worry about getting rid of the elements from the virtual
869 // frame. 870 // frame.
870 Label loop; 871 Label loop;
871 // rcx is a small non-negative integer, due to the test above. 872 // rcx is a small non-negative integer, due to the test above.
872 __ testl(rcx, rcx); 873 __ testl(rcx, rcx);
873 __ j(zero, &invoke); 874 __ j(zero, &invoke);
(...skipping 3631 matching lines...) Expand 10 before | Expand all | Expand 10 after
4505 Register cache, 4506 Register cache,
4506 Register key, 4507 Register key,
4507 Register scratch) 4508 Register scratch)
4508 : dst_(dst), cache_(cache), key_(key), scratch_(scratch) { 4509 : dst_(dst), cache_(cache), key_(key), scratch_(scratch) {
4509 set_comment("[ DeferredSearchCache"); 4510 set_comment("[ DeferredSearchCache");
4510 } 4511 }
4511 4512
4512 virtual void Generate(); 4513 virtual void Generate();
4513 4514
4514 private: 4515 private:
4515 Register dst_; // on invocation index of finger (as Smi), on exit 4516 Register dst_; // on invocation index of finger (as int32), on exit
4516 // holds value being looked up. 4517 // holds value being looked up.
4517 Register cache_; // instance of JSFunctionResultCache. 4518 Register cache_; // instance of JSFunctionResultCache.
4518 Register key_; // key being looked up. 4519 Register key_; // key being looked up.
4519 Register scratch_; 4520 Register scratch_;
4520 }; 4521 };
4521 4522
4522 4523
4523 // Return a position of the element at |index| + |additional_offset| 4524 // Return a position of the element at |index| + |additional_offset|
4524 // in FixedArray pointer to which is held in |array|. |index| is int32. 4525 // in FixedArray pointer to which is held in |array|. |index| is int32.
4525 static Operand ArrayElement(Register array, 4526 static Operand ArrayElement(Register array,
4526 Register index, 4527 Register index,
4527 int additional_offset = 0) { 4528 int additional_offset = 0) {
4528 int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize; 4529 int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize;
4529 return FieldOperand(array, index, times_pointer_size, offset); 4530 return FieldOperand(array, index, times_pointer_size, offset);
4530 } 4531 }
4531 4532
4532 4533
4533 void DeferredSearchCache::Generate() { 4534 void DeferredSearchCache::Generate() {
4534 Label first_loop, search_further, second_loop, cache_miss; 4535 Label first_loop, search_further, second_loop, cache_miss;
4535 4536
4536 Immediate kEntriesIndexImm = Immediate(JSFunctionResultCache::kEntriesIndex); 4537 Immediate kEntriesIndexImm = Immediate(JSFunctionResultCache::kEntriesIndex);
4537 Immediate kEntrySizeImm = Immediate(JSFunctionResultCache::kEntrySize); 4538 Immediate kEntrySizeImm = Immediate(JSFunctionResultCache::kEntrySize);
4538 4539
4539 __ SmiToInteger32(dst_, dst_);
4540 // Check the cache from finger to start of the cache. 4540 // Check the cache from finger to start of the cache.
4541 __ bind(&first_loop); 4541 __ bind(&first_loop);
4542 __ subq(dst_, kEntrySizeImm); 4542 __ subl(dst_, kEntrySizeImm);
4543 __ cmpq(dst_, kEntriesIndexImm); 4543 __ cmpl(dst_, kEntriesIndexImm);
4544 __ j(less, &search_further); 4544 __ j(less, &search_further);
4545 4545
4546 __ cmpq(ArrayElement(cache_, dst_), key_); 4546 __ cmpq(ArrayElement(cache_, dst_), key_);
4547 __ j(not_equal, &first_loop); 4547 __ j(not_equal, &first_loop);
4548 4548
4549 __ Integer32ToSmi(scratch_, dst_); 4549 __ Integer32ToSmi(scratch_, dst_);
4550 __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_); 4550 __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_);
4551 __ movq(dst_, ArrayElement(cache_, dst_, 1)); 4551 __ movq(dst_, ArrayElement(cache_, dst_, 1));
4552 __ jmp(exit_label()); 4552 __ jmp(exit_label());
4553 4553
4554 __ bind(&search_further); 4554 __ bind(&search_further);
4555 4555
4556 // Check the cache from end of cache up to finger. 4556 // Check the cache from end of cache up to finger.
4557 __ movq(dst_, FieldOperand(cache_, JSFunctionResultCache::kCacheSizeOffset)); 4557 __ SmiToInteger32(dst_,
4558 __ movq(scratch_, FieldOperand(cache_, JSFunctionResultCache::kFingerOffset)); 4558 FieldOperand(cache_,
4559 __ SmiToInteger32(dst_, dst_); 4559 JSFunctionResultCache::kCacheSizeOffset));
4560 __ SmiToInteger32(scratch_, scratch_); 4560 __ SmiToInteger32(scratch_,
4561 FieldOperand(cache_, JSFunctionResultCache::kFingerOffset));
4561 4562
4562 __ bind(&second_loop); 4563 __ bind(&second_loop);
4563 __ subq(dst_, kEntrySizeImm); 4564 __ subl(dst_, kEntrySizeImm);
4564 __ cmpq(dst_, scratch_); 4565 __ cmpl(dst_, scratch_);
4565 __ j(less_equal, &cache_miss); 4566 __ j(less_equal, &cache_miss);
4566 4567
4567 __ cmpq(ArrayElement(cache_, dst_), key_); 4568 __ cmpq(ArrayElement(cache_, dst_), key_);
4568 __ j(not_equal, &second_loop); 4569 __ j(not_equal, &second_loop);
4569 4570
4570 __ Integer32ToSmi(scratch_, dst_); 4571 __ Integer32ToSmi(scratch_, dst_);
4571 __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_); 4572 __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_);
4572 __ movq(dst_, ArrayElement(cache_, dst_, 1)); 4573 __ movq(dst_, ArrayElement(cache_, dst_, 1));
4573 __ jmp(exit_label()); 4574 __ jmp(exit_label());
4574 4575
(...skipping 10 matching lines...) Expand all
4585 4586
4586 // Find a place to put new cached value into. 4587 // Find a place to put new cached value into.
4587 Label add_new_entry, update_cache; 4588 Label add_new_entry, update_cache;
4588 __ movq(rcx, Operand(rsp, kPointerSize)); // restore the cache 4589 __ movq(rcx, Operand(rsp, kPointerSize)); // restore the cache
4589 // Possible optimization: cache size is constant for the given cache 4590 // Possible optimization: cache size is constant for the given cache
4590 // so technically we could use a constant here. However, if we have 4591 // so technically we could use a constant here. However, if we have
4591 // cache miss this optimization would hardly matter much. 4592 // cache miss this optimization would hardly matter much.
4592 4593
4593 // Check if we could add new entry to cache. 4594 // Check if we could add new entry to cache.
4594 __ movl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); 4595 __ movl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
4595 __ movq(r9, FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset)); 4596 __ SmiToInteger32(r9,
4596 __ SmiToInteger32(r9, r9); 4597 FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset));
4597 __ cmpq(rbx, r9); 4598 __ cmpl(rbx, r9);
4598 __ j(greater, &add_new_entry); 4599 __ j(greater, &add_new_entry);
4599 4600
4600 // Check if we could evict entry after finger. 4601 // Check if we could evict entry after finger.
4601 __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset)); 4602 __ SmiToInteger32(rdx,
4602 __ SmiToInteger32(rdx, rdx); 4603 FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
4603 __ addq(rdx, kEntrySizeImm); 4604 __ addq(rdx, kEntrySizeImm);
4604 Label forward; 4605 Label forward;
4605 __ cmpq(rbx, rdx); 4606 __ cmpq(rbx, rdx);
4606 __ j(greater, &forward); 4607 __ j(greater, &forward);
4607 // Need to wrap over the cache. 4608 // Need to wrap over the cache.
4608 __ movq(rdx, kEntriesIndexImm); 4609 __ movl(rdx, kEntriesIndexImm);
4609 __ bind(&forward); 4610 __ bind(&forward);
4610 __ Integer32ToSmi(r9, rdx); 4611 __ Integer32ToSmi(r9, rdx);
4611 __ jmp(&update_cache); 4612 __ jmp(&update_cache);
4612 4613
4613 __ bind(&add_new_entry); 4614 __ bind(&add_new_entry);
4614 // r9 holds cache size as int. 4615 // r9 holds cache size as int.
4615 __ movq(rdx, r9); 4616 __ movl(rdx, r9);
4616 __ Integer32ToSmi(r9, r9); 4617 __ Integer32ToSmi(r9, r9);
4617 __ SmiAddConstant(rbx, r9, Smi::FromInt(JSFunctionResultCache::kEntrySize)); 4618 __ leal(rbx, Operand(rdx, JSFunctionResultCache::kEntrySize));
4619 __ Integer32ToSmi(rbx, rbx);
4618 __ movq(FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx); 4620 __ movq(FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx);
4619 4621
4620 // Update the cache itself. 4622 // Update the cache itself.
4621 // rdx holds the index as int. 4623 // rdx holds the index as int.
4622 // r9 holds the index as smi. 4624 // r9 holds the index as smi.
4623 __ bind(&update_cache); 4625 __ bind(&update_cache);
4624 __ pop(rbx); // restore the key 4626 __ pop(rbx); // restore the key
4625 __ movq(FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9); 4627 __ movq(FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9);
4626 // Store key. 4628 // Store key.
4627 __ movq(ArrayElement(rcx, rdx), rbx); 4629 __ movq(ArrayElement(rcx, rdx), rbx);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
4678 ASSERT(scratch.is_valid()); 4680 ASSERT(scratch.is_valid());
4679 4681
4680 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(), 4682 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(),
4681 cache.reg(), 4683 cache.reg(),
4682 key.reg(), 4684 key.reg(),
4683 scratch.reg()); 4685 scratch.reg());
4684 4686
4685 const int kFingerOffset = 4687 const int kFingerOffset =
4686 FixedArray::OffsetOfElementAt(JSFunctionResultCache::kFingerIndex); 4688 FixedArray::OffsetOfElementAt(JSFunctionResultCache::kFingerIndex);
4687 // tmp.reg() now holds finger offset as a smi. 4689 // tmp.reg() now holds finger offset as a smi.
4688 __ movq(tmp.reg(), FieldOperand(cache.reg(), kFingerOffset)); 4690 __ SmiToInteger32(tmp.reg(), FieldOperand(cache.reg(), kFingerOffset));
4689 SmiIndex index =
4690 masm()->SmiToIndex(kScratchRegister, tmp.reg(), kPointerSizeLog2);
4691 __ cmpq(key.reg(), FieldOperand(cache.reg(), 4691 __ cmpq(key.reg(), FieldOperand(cache.reg(),
4692 index.reg, index.scale, 4692 tmp.reg(), times_pointer_size,
4693 FixedArray::kHeaderSize)); 4693 FixedArray::kHeaderSize));
4694 // Do NOT alter index.reg or tmp.reg() before cmpq below.
4695 deferred->Branch(not_equal); 4694 deferred->Branch(not_equal);
4696 __ movq(tmp.reg(), FieldOperand(cache.reg(), 4695 __ movq(tmp.reg(), FieldOperand(cache.reg(),
4697 index.reg, index.scale, 4696 tmp.reg(), times_pointer_size,
4698 FixedArray::kHeaderSize + kPointerSize)); 4697 FixedArray::kHeaderSize + kPointerSize));
4699 4698
4700 deferred->BindExit(); 4699 deferred->BindExit();
4701 frame_->Push(&tmp); 4700 frame_->Push(&tmp);
4702 } 4701 }
4703 4702
4704 4703
4705 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { 4704 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) {
4706 ASSERT_EQ(args->length(), 1); 4705 ASSERT_EQ(args->length(), 1);
4707 4706
(...skipping 3776 matching lines...) Expand 10 before | Expand all | Expand 10 after
8484 // Keep track on aliasing between argX defined above and the registers used. 8483 // Keep track on aliasing between argX defined above and the registers used.
8485 // rax: subject string 8484 // rax: subject string
8486 // rbx: previous index 8485 // rbx: previous index
8487 // rdi: encoding of subject string (1 if ascii 0 if two_byte); 8486 // rdi: encoding of subject string (1 if ascii 0 if two_byte);
8488 // r12: code 8487 // r12: code
8489 8488
8490 // Argument 4: End of string data 8489 // Argument 4: End of string data
8491 // Argument 3: Start of string data 8490 // Argument 3: Start of string data
8492 Label setup_two_byte, setup_rest; 8491 Label setup_two_byte, setup_rest;
8493 __ testb(rdi, rdi); 8492 __ testb(rdi, rdi);
8494 __ movq(rdi, FieldOperand(rax, String::kLengthOffset));
8495 __ j(zero, &setup_two_byte); 8493 __ j(zero, &setup_two_byte);
8496 __ SmiToInteger32(rdi, rdi); 8494 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
8497 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); 8495 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize));
8498 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); 8496 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize));
8499 __ jmp(&setup_rest); 8497 __ jmp(&setup_rest);
8500 __ bind(&setup_two_byte); 8498 __ bind(&setup_two_byte);
8501 __ SmiToInteger32(rdi, rdi); 8499 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
8502 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); 8500 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize));
8503 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); 8501 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize));
8504 8502
8505 __ bind(&setup_rest); 8503 __ bind(&setup_rest);
8506 // Argument 2: Previous index. 8504 // Argument 2: Previous index.
8507 __ movq(arg2, rbx); 8505 __ movq(arg2, rbx);
8508 8506
8509 // Argument 1: Subject string. 8507 // Argument 1: Subject string.
8510 __ movq(arg1, rax); 8508 __ movq(arg1, rax);
8511 8509
8512 // Locate the code entry and call it. 8510 // Locate the code entry and call it.
8513 __ addq(r12, Immediate(Code::kHeaderSize - kHeapObjectTag)); 8511 __ addq(r12, Immediate(Code::kHeaderSize - kHeapObjectTag));
8514 __ CallCFunction(r12, kRegExpExecuteArguments); 8512 __ CallCFunction(r12, kRegExpExecuteArguments);
8515 8513
8516 // rsi is caller save, as it is used to pass parameter. 8514 // rsi is caller save, as it is used to pass parameter.
8517 __ pop(rsi); 8515 __ pop(rsi);
8518 8516
8519 // Check the result. 8517 // Check the result.
8520 Label success; 8518 Label success;
8521 __ cmpq(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); 8519 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
8522 __ j(equal, &success); 8520 __ j(equal, &success);
8523 Label failure; 8521 Label failure;
8524 __ cmpq(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 8522 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
8525 __ j(equal, &failure); 8523 __ j(equal, &failure);
8526 __ cmpq(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); 8524 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
8527 // If not exception it can only be retry. Handle that in the runtime system. 8525 // If not exception it can only be retry. Handle that in the runtime system.
8528 __ j(not_equal, &runtime); 8526 __ j(not_equal, &runtime);
8529 // Result must now be exception. If there is no pending exception already a 8527 // Result must now be exception. If there is no pending exception already a
8530 // stack overflow (on the backtrack stack) was detected in RegExp code but 8528 // stack overflow (on the backtrack stack) was detected in RegExp code but
8531 // haven't created the exception yet. Handle that in the runtime system. 8529 // haven't created the exception yet. Handle that in the runtime system.
8532 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 8530 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
8533 ExternalReference pending_exception_address(Top::k_pending_exception_address); 8531 ExternalReference pending_exception_address(Top::k_pending_exception_address);
8534 __ movq(kScratchRegister, pending_exception_address); 8532 __ movq(kScratchRegister, pending_exception_address);
8535 __ Cmp(kScratchRegister, Factory::the_hole_value()); 8533 __ Cmp(kScratchRegister, Factory::the_hole_value());
8536 __ j(equal, &runtime); 8534 __ j(equal, &runtime);
(...skipping 2440 matching lines...) Expand 10 before | Expand all | Expand 10 after
10977 __ j(zero, &string_add_runtime); 10975 __ j(zero, &string_add_runtime);
10978 10976
10979 __ bind(&make_flat_ascii_string); 10977 __ bind(&make_flat_ascii_string);
10980 // Both strings are ascii strings. As they are short they are both flat. 10978 // Both strings are ascii strings. As they are short they are both flat.
10981 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 10979 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
10982 // rcx: result string 10980 // rcx: result string
10983 __ movq(rbx, rcx); 10981 __ movq(rbx, rcx);
10984 // Locate first character of result. 10982 // Locate first character of result.
10985 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 10983 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
10986 // Locate first character of first argument 10984 // Locate first character of first argument
10987 __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); 10985 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
10988 __ SmiToInteger32(rdi, rdi);
10989 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 10986 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
10990 // rax: first char of first argument 10987 // rax: first char of first argument
10991 // rbx: result string 10988 // rbx: result string
10992 // rcx: first character of result 10989 // rcx: first character of result
10993 // rdx: second string 10990 // rdx: second string
10994 // rdi: length of first argument 10991 // rdi: length of first argument
10995 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true); 10992 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true);
10996 // Locate first character of second argument. 10993 // Locate first character of second argument.
10997 __ movq(rdi, FieldOperand(rdx, String::kLengthOffset)); 10994 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset));
10998 __ SmiToInteger32(rdi, rdi);
10999 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 10995 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
11000 // rbx: result string 10996 // rbx: result string
11001 // rcx: next character of result 10997 // rcx: next character of result
11002 // rdx: first char of second argument 10998 // rdx: first char of second argument
11003 // rdi: length of second argument 10999 // rdi: length of second argument
11004 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true); 11000 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
11005 __ movq(rax, rbx); 11001 __ movq(rax, rbx);
11006 __ IncrementCounter(&Counters::string_add_native, 1); 11002 __ IncrementCounter(&Counters::string_add_native, 1);
11007 __ ret(2 * kPointerSize); 11003 __ ret(2 * kPointerSize);
11008 11004
11009 // Handle creating a flat two byte result. 11005 // Handle creating a flat two byte result.
11010 // rax: first string - known to be two byte 11006 // rax: first string - known to be two byte
11011 // rbx: length of resulting flat string 11007 // rbx: length of resulting flat string
11012 // rdx: second string 11008 // rdx: second string
11013 // r8: instance type of first string 11009 // r8: instance type of first string
11014 // r9: instance type of first string 11010 // r9: instance type of first string
11015 __ bind(&non_ascii_string_add_flat_result); 11011 __ bind(&non_ascii_string_add_flat_result);
11016 __ and_(r9, Immediate(kAsciiStringTag)); 11012 __ and_(r9, Immediate(kAsciiStringTag));
11017 __ j(not_zero, &string_add_runtime); 11013 __ j(not_zero, &string_add_runtime);
11018 // Both strings are two byte strings. As they are short they are both 11014 // Both strings are two byte strings. As they are short they are both
11019 // flat. 11015 // flat.
11020 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 11016 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
11021 // rcx: result string 11017 // rcx: result string
11022 __ movq(rbx, rcx); 11018 __ movq(rbx, rcx);
11023 // Locate first character of result. 11019 // Locate first character of result.
11024 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 11020 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
11025 // Locate first character of first argument. 11021 // Locate first character of first argument.
11026 __ movq(rdi, FieldOperand(rax, String::kLengthOffset)); 11022 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
11027 __ SmiToInteger32(rdi, rdi);
11028 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 11023 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
11029 // rax: first char of first argument 11024 // rax: first char of first argument
11030 // rbx: result string 11025 // rbx: result string
11031 // rcx: first character of result 11026 // rcx: first character of result
11032 // rdx: second argument 11027 // rdx: second argument
11033 // rdi: length of first argument 11028 // rdi: length of first argument
11034 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false); 11029 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false);
11035 // Locate first character of second argument. 11030 // Locate first character of second argument.
11036 __ movq(rdi, FieldOperand(rdx, String::kLengthOffset)); 11031 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset));
11037 __ SmiToInteger32(rdi, rdi);
11038 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 11032 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
11039 // rbx: result string 11033 // rbx: result string
11040 // rcx: next character of result 11034 // rcx: next character of result
11041 // rdx: first char of second argument 11035 // rdx: first char of second argument
11042 // rdi: length of second argument 11036 // rdi: length of second argument
11043 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false); 11037 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
11044 __ movq(rax, rbx); 11038 __ movq(rax, rbx);
11045 __ IncrementCounter(&Counters::string_add_native, 1); 11039 __ IncrementCounter(&Counters::string_add_native, 1);
11046 __ ret(2 * kPointerSize); 11040 __ ret(2 * kPointerSize);
11047 11041
11048 // Just jump to runtime to add the two strings. 11042 // Just jump to runtime to add the two strings.
11049 __ bind(&string_add_runtime); 11043 __ bind(&string_add_runtime);
11050 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 11044 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
11051 } 11045 }
11052 11046
11053 11047
11054 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 11048 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
11055 Register dest, 11049 Register dest,
11056 Register src, 11050 Register src,
11057 Register count, 11051 Register count,
11058 bool ascii) { 11052 bool ascii) {
11059 Label loop; 11053 Label loop;
11060 __ bind(&loop); 11054 __ bind(&loop);
11061 // This loop just copies one character at a time, as it is only used for very 11055 // This loop just copies one character at a time, as it is only used for very
11062 // short strings. 11056 // short strings.
11063 if (ascii) { 11057 if (ascii) {
11064 __ movb(kScratchRegister, Operand(src, 0)); 11058 __ movb(kScratchRegister, Operand(src, 0));
11065 __ movb(Operand(dest, 0), kScratchRegister); 11059 __ movb(Operand(dest, 0), kScratchRegister);
11066 __ addq(src, Immediate(1)); 11060 __ incq(src);
11067 __ addq(dest, Immediate(1)); 11061 __ incq(dest);
11068 } else { 11062 } else {
11069 __ movzxwl(kScratchRegister, Operand(src, 0)); 11063 __ movzxwl(kScratchRegister, Operand(src, 0));
11070 __ movw(Operand(dest, 0), kScratchRegister); 11064 __ movw(Operand(dest, 0), kScratchRegister);
11071 __ addq(src, Immediate(2)); 11065 __ addq(src, Immediate(2));
11072 __ addq(dest, Immediate(2)); 11066 __ addq(dest, Immediate(2));
11073 } 11067 }
11074 __ subl(count, Immediate(1)); 11068 __ decl(count);
11075 __ j(not_zero, &loop); 11069 __ j(not_zero, &loop);
11076 } 11070 }
11077 11071
11078 11072
11079 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 11073 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
11080 Register dest, 11074 Register dest,
11081 Register src, 11075 Register src,
11082 Register count, 11076 Register count,
11083 bool ascii) { 11077 bool ascii) {
11084 // Copy characters using rep movs of doublewords. Align destination on 4 byte 11078 // Copy characters using rep movs of doublewords. Align destination on 4 byte
11085 // boundary before starting rep movs. Copy remaining characters after running 11079 // boundary before starting rep movs. Copy remaining characters after running
William Hesse 2010/05/27 08:36:03 Where is the destination aligned to a 4-byte bound
11086 // rep movs. 11080 // rep movs.
11081 // Count is positive int32, dest and src are character pointers.
11087 ASSERT(dest.is(rdi)); // rep movs destination 11082 ASSERT(dest.is(rdi)); // rep movs destination
11088 ASSERT(src.is(rsi)); // rep movs source 11083 ASSERT(src.is(rsi)); // rep movs source
11089 ASSERT(count.is(rcx)); // rep movs count 11084 ASSERT(count.is(rcx)); // rep movs count
11090 11085
11091 // Nothing to do for zero characters. 11086 // Nothing to do for zero characters.
11092 Label done; 11087 Label done;
11093 __ testq(count, count); 11088 __ testl(count, count);
11094 __ j(zero, &done); 11089 __ j(zero, &done);
11095 11090
11096 // Make count the number of bytes to copy. 11091 // Make count the number of bytes to copy.
11097 if (!ascii) { 11092 if (!ascii) {
11098 ASSERT_EQ(2, sizeof(uc16)); // NOLINT 11093 ASSERT_EQ(2, sizeof(uc16)); // NOLINT
11099 __ addq(count, count); 11094 __ addl(count, count);
11100 } 11095 }
11101 11096
11102 // Don't enter the rep movs if there are less than 4 bytes to copy. 11097 // Don't enter the rep movs if there are less than 4 bytes to copy.
11103 Label last_bytes; 11098 Label last_bytes;
11104 __ testq(count, Immediate(~7)); 11099 __ testl(count, Immediate(~7));
11105 __ j(zero, &last_bytes); 11100 __ j(zero, &last_bytes);
11106 11101
11107 // Copy from edi to esi using rep movs instruction. 11102 // Copy from edi to esi using rep movs instruction.
11108 __ movq(kScratchRegister, count); 11103 __ movl(kScratchRegister, count);
11109 __ sar(count, Immediate(3)); // Number of doublewords to copy. 11104 __ shr(count, Immediate(3)); // Number of doublewords to copy.
11110 __ repmovsq(); 11105 __ repmovsq();
11111 11106
11112 // Find number of bytes left. 11107 // Find number of bytes left.
11113 __ movq(count, kScratchRegister); 11108 __ movl(count, kScratchRegister);
11114 __ and_(count, Immediate(7)); 11109 __ and_(count, Immediate(7));
11115 11110
11116 // Check if there are more bytes to copy. 11111 // Check if there are more bytes to copy.
11117 __ bind(&last_bytes); 11112 __ bind(&last_bytes);
11118 __ testq(count, count); 11113 __ testl(count, count);
11119 __ j(zero, &done); 11114 __ j(zero, &done);
11120 11115
11121 // Copy remaining characters. 11116 // Copy remaining characters.
11122 Label loop; 11117 Label loop;
11123 __ bind(&loop); 11118 __ bind(&loop);
11124 __ movb(kScratchRegister, Operand(src, 0)); 11119 __ movb(kScratchRegister, Operand(src, 0));
11125 __ movb(Operand(dest, 0), kScratchRegister); 11120 __ movb(Operand(dest, 0), kScratchRegister);
11126 __ addq(src, Immediate(1)); 11121 __ incq(src);
11127 __ addq(dest, Immediate(1)); 11122 __ incq(dest);
11128 __ subq(count, Immediate(1)); 11123 __ decl(count);
11129 __ j(not_zero, &loop); 11124 __ j(not_zero, &loop);
11130 11125
11131 __ bind(&done); 11126 __ bind(&done);
11132 } 11127 }
11133 11128
11134 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 11129 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
11135 Register c1, 11130 Register c1,
11136 Register c2, 11131 Register c2,
11137 Register scratch1, 11132 Register scratch1,
11138 Register scratch2, 11133 Register scratch2,
11139 Register scratch3, 11134 Register scratch3,
11140 Register scratch4, 11135 Register scratch4,
11141 Label* not_found) { 11136 Label* not_found) {
11142 // Register scratch3 is the general scratch register in this function. 11137 // Register scratch3 is the general scratch register in this function.
11143 Register scratch = scratch3; 11138 Register scratch = scratch3;
11144 11139
11145 // Make sure that both characters are not digits as such strings has a 11140 // Make sure that both characters are not digits as such strings has a
11146 // different hash algorithm. Don't try to look for these in the symbol table. 11141 // different hash algorithm. Don't try to look for these in the symbol table.
11147 Label not_array_index; 11142 Label not_array_index;
11148 __ movq(scratch, c1); 11143 __ leal(scratch, Operand(c1, -'0'));
11149 __ subq(scratch, Immediate(static_cast<int>('0'))); 11144 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
11150 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0')));
11151 __ j(above, &not_array_index); 11145 __ j(above, &not_array_index);
11152 __ movq(scratch, c2); 11146 __ leal(scratch, Operand(c2, -'0'));
11153 __ subq(scratch, Immediate(static_cast<int>('0'))); 11147 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
11154 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0')));
11155 __ j(below_equal, not_found); 11148 __ j(below_equal, not_found);
11156 11149
11157 __ bind(&not_array_index); 11150 __ bind(&not_array_index);
11158 // Calculate the two character string hash. 11151 // Calculate the two character string hash.
11159 Register hash = scratch1; 11152 Register hash = scratch1;
11160 GenerateHashInit(masm, hash, c1, scratch); 11153 GenerateHashInit(masm, hash, c1, scratch);
11161 GenerateHashAddCharacter(masm, hash, c2, scratch); 11154 GenerateHashAddCharacter(masm, hash, c2, scratch);
11162 GenerateHashGetHash(masm, hash, scratch); 11155 GenerateHashGetHash(masm, hash, scratch);
11163 11156
11164 // Collect the two characters in a register. 11157 // Collect the two characters in a register.
11165 Register chars = c1; 11158 Register chars = c1;
11166 __ shl(c2, Immediate(kBitsPerByte)); 11159 __ shl(c2, Immediate(kBitsPerByte));
11167 __ orl(chars, c2); 11160 __ orl(chars, c2);
11168 11161
11169 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 11162 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
11170 // hash: hash of two character string. 11163 // hash: hash of two character string.
11171 11164
11172 // Load the symbol table. 11165 // Load the symbol table.
11173 Register symbol_table = c2; 11166 Register symbol_table = c2;
11174 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); 11167 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
11175 11168
11176 // Calculate capacity mask from the symbol table capacity. 11169 // Calculate capacity mask from the symbol table capacity.
11177 Register mask = scratch2; 11170 Register mask = scratch2;
11178 __ movq(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); 11171 __ SmiToInteger32(mask,
11179 __ SmiToInteger32(mask, mask); 11172 FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
11180 __ decl(mask); 11173 __ decl(mask);
11181 11174
11182 Register undefined = scratch4; 11175 Register undefined = scratch4;
11183 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 11176 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
11184 11177
11185 // Registers 11178 // Registers
11186 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 11179 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
11187 // hash: hash of two character string (32-bit int) 11180 // hash: hash of two character string (32-bit int)
11188 // symbol_table: symbol table 11181 // symbol_table: symbol table
11189 // mask: capacity mask (32-bit int) 11182 // mask: capacity mask (32-bit int)
11190 // undefined: undefined value 11183 // undefined: undefined value
11191 // scratch: - 11184 // scratch: -
11192 11185
11193 // Perform a number of probes in the symbol table. 11186 // Perform a number of probes in the symbol table.
11194 static const int kProbes = 4; 11187 static const int kProbes = 4;
11195 Label found_in_symbol_table; 11188 Label found_in_symbol_table;
11196 Label next_probe[kProbes]; 11189 Label next_probe[kProbes];
11197 for (int i = 0; i < kProbes; i++) { 11190 for (int i = 0; i < kProbes; i++) {
11198 // Calculate entry in symbol table. 11191 // Calculate entry in symbol table.
11199 __ movl(scratch, hash); 11192 __ movl(scratch, hash);
11200 if (i > 0) { 11193 if (i > 0) {
11201 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i))); 11194 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
11202 } 11195 }
11203 __ andl(scratch, mask); 11196 __ andl(scratch, mask);
11204 11197
11205 // Load the entry from the symble table. 11198 // Load the entry from the symble table.
11206 Register candidate = scratch; // Scratch register contains candidate. 11199 Register candidate = scratch; // Scratch register contains candidate.
11207 ASSERT_EQ(1, SymbolTable::kEntrySize); 11200 ASSERT_EQ(1, SymbolTable::kEntrySize);
11208 __ movq(candidate, 11201 __ movq(candidate,
11209 FieldOperand(symbol_table, 11202 FieldOperand(symbol_table,
11210 scratch, 11203 scratch,
11211 times_pointer_size, 11204 times_pointer_size,
11212 SymbolTable::kElementsStartOffset)); 11205 SymbolTable::kElementsStartOffset));
11213 11206
11214 // If entry is undefined no string with this hash can be found. 11207 // If entry is undefined no string with this hash can be found.
11215 __ cmpq(candidate, undefined); 11208 __ cmpq(candidate, undefined);
11216 __ j(equal, not_found); 11209 __ j(equal, not_found);
11217 11210
11218 // If length is not 2 the string is not a candidate. 11211 // If length is not 2 the string is not a candidate.
11219 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), 11212 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
11220 Smi::FromInt(2)); 11213 Smi::FromInt(2));
11221 __ j(not_equal, &next_probe[i]); 11214 __ j(not_equal, &next_probe[i]);
11222 11215
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
11279 __ movl(scratch, hash); 11272 __ movl(scratch, hash);
11280 __ sarl(scratch, Immediate(6)); 11273 __ sarl(scratch, Immediate(6));
11281 __ xorl(hash, scratch); 11274 __ xorl(hash, scratch);
11282 } 11275 }
11283 11276
11284 11277
11285 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, 11278 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
11286 Register hash, 11279 Register hash,
11287 Register scratch) { 11280 Register scratch) {
11288 // hash += hash << 3; 11281 // hash += hash << 3;
11289 __ movl(scratch, hash); 11282 __ leal(hash, Operand(hash, hash, times_8, 0));
11290 __ shll(scratch, Immediate(3));
11291 __ addl(hash, scratch);
11292 // hash ^= hash >> 11; 11283 // hash ^= hash >> 11;
11293 __ movl(scratch, hash); 11284 __ movl(scratch, hash);
11294 __ sarl(scratch, Immediate(11)); 11285 __ sarl(scratch, Immediate(11));
11295 __ xorl(hash, scratch); 11286 __ xorl(hash, scratch);
11296 // hash += hash << 15; 11287 // hash += hash << 15;
11297 __ movl(scratch, hash); 11288 __ movl(scratch, hash);
11298 __ shll(scratch, Immediate(15)); 11289 __ shll(scratch, Immediate(15));
11299 __ addl(hash, scratch); 11290 __ addl(hash, scratch);
11300 11291
11301 // if (hash == 0) hash = 27; 11292 // if (hash == 0) hash = 27;
11302 Label hash_not_zero; 11293 Label hash_not_zero;
11303 __ testl(hash, hash);
11304 __ j(not_zero, &hash_not_zero); 11294 __ j(not_zero, &hash_not_zero);
11305 __ movl(hash, Immediate(27)); 11295 __ movl(hash, Immediate(27));
11306 __ bind(&hash_not_zero); 11296 __ bind(&hash_not_zero);
11307 } 11297 }
11308 11298
11309 void SubStringStub::Generate(MacroAssembler* masm) { 11299 void SubStringStub::Generate(MacroAssembler* masm) {
11310 Label runtime; 11300 Label runtime;
11311 11301
11312 // Stack frame on entry. 11302 // Stack frame on entry.
11313 // rsp[0]: return address 11303 // rsp[0]: return address
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
11665 } 11655 }
11666 11656
11667 #endif 11657 #endif
11668 11658
11669 11659
11670 #undef __ 11660 #undef __
11671 11661
11672 } } // namespace v8::internal 11662 } } // namespace v8::internal
11673 11663
11674 #endif // V8_TARGET_ARCH_X64 11664 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.h ('k') | src/x64/ic-x64.cc » ('j') | src/x64/macro-assembler-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698