OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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, ¬_array_index); | 11145 __ j(above, ¬_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(¬_array_index); | 11150 __ bind(¬_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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |