| OLD | NEW | 
|     1 // Copyright 2013 the V8 project authors. All rights reserved. |     1 // Copyright 2013 the V8 project authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #if V8_TARGET_ARCH_X64 |     5 #if V8_TARGET_ARCH_X64 | 
|     6  |     6  | 
|     7 #include "src/bootstrapper.h" |     7 #include "src/bootstrapper.h" | 
|     8 #include "src/code-stubs.h" |     8 #include "src/code-stubs.h" | 
|     9 #include "src/codegen.h" |     9 #include "src/codegen.h" | 
|    10 #include "src/ic/handler-compiler.h" |    10 #include "src/ic/handler-compiler.h" | 
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   660   // Or              number_of_captures <= offsets vector size / 2 - 1 |   660   // Or              number_of_captures <= offsets vector size / 2 - 1 | 
|   661   STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |   661   STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 
|   662   __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); |   662   __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); | 
|   663   __ j(above, &runtime); |   663   __ j(above, &runtime); | 
|   664  |   664  | 
|   665   // Reset offset for possibly sliced string. |   665   // Reset offset for possibly sliced string. | 
|   666   __ Set(r14, 0); |   666   __ Set(r14, 0); | 
|   667   __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); |   667   __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); | 
|   668   __ JumpIfSmi(rdi, &runtime); |   668   __ JumpIfSmi(rdi, &runtime); | 
|   669   __ movp(r15, rdi);  // Make a copy of the original subject string. |   669   __ movp(r15, rdi);  // Make a copy of the original subject string. | 
|   670   __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |  | 
|   671   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |  | 
|   672   // rax: RegExp data (FixedArray) |   670   // rax: RegExp data (FixedArray) | 
|   673   // rdi: subject string |   671   // rdi: subject string | 
|   674   // r15: subject string |   672   // r15: subject string | 
|   675   // Handle subject string according to its encoding and representation: |   673   // Handle subject string according to its encoding and representation: | 
|   676   // (1) Sequential two byte?  If yes, go to (9). |   674   // (1) Sequential two byte?  If yes, go to (9). | 
|   677   // (2) Sequential one byte?  If yes, go to (6). |   675   // (2) Sequential one byte?  If yes, go to (5). | 
|   678   // (3) Anything but sequential or cons?  If yes, go to (7). |   676   // (3) Sequential or cons?  If not, go to (6). | 
|   679   // (4) Cons string.  If the string is flat, replace subject with first string. |   677   // (4) Cons string.  If the string is flat, replace subject with first string | 
|   680   //     Otherwise bailout. |   678   //     and go to (1). Otherwise bail out to runtime. | 
|   681   // (5a) Is subject sequential two byte?  If yes, go to (9). |   679   // (5) One byte sequential.  Load regexp code for one byte. | 
|   682   // (5b) Is subject external?  If yes, go to (8). |  | 
|   683   // (6) One byte sequential.  Load regexp code for one byte. |  | 
|   684   // (E) Carry on. |   680   // (E) Carry on. | 
|   685   /// [...] |   681   /// [...] | 
|   686  |   682  | 
|   687   // Deferred code at the end of the stub: |   683   // Deferred code at the end of the stub: | 
|   688   // (7) Not a long external string?  If yes, go to (10). |   684   // (6) Long external string?  If not, go to (10). | 
|   689   // (8) External string.  Make it, offset-wise, look like a sequential string. |   685   // (7) External string.  Make it, offset-wise, look like a sequential string. | 
|   690   // (8a) Is the external string one byte?  If yes, go to (6). |   686   // (8) Is the external string one byte?  If yes, go to (5). | 
|   691   // (9) Two byte sequential.  Load regexp code for one byte. Go to (E). |   687   // (9) Two byte sequential.  Load regexp code for two byte. Go to (E). | 
|   692   // (10) Short external string or not a string?  If yes, bail out to runtime. |   688   // (10) Short external string or not a string?  If yes, bail out to runtime. | 
|   693   // (11) Sliced string.  Replace subject with parent. Go to (5a). |   689   // (11) Sliced string.  Replace subject with parent. Go to (1). | 
|   694  |   690  | 
|   695   Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, |   691   Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, | 
|   696         external_string /* 8 */, check_underlying /* 5a */, |   692       external_string /* 7 */, check_underlying /* 1 */, | 
|   697         not_seq_nor_cons /* 7 */, check_code /* E */, |   693       not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; | 
|   698         not_long_external /* 10 */; |   694  | 
 |   695   __ bind(&check_underlying); | 
 |   696   __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 
 |   697   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 
|   699  |   698  | 
|   700   // (1) Sequential two byte?  If yes, go to (9). |   699   // (1) Sequential two byte?  If yes, go to (9). | 
|   701   __ andb(rbx, Immediate(kIsNotStringMask | |   700   __ andb(rbx, Immediate(kIsNotStringMask | | 
|   702                          kStringRepresentationMask | |   701                          kStringRepresentationMask | | 
|   703                          kStringEncodingMask | |   702                          kStringEncodingMask | | 
|   704                          kShortExternalStringMask)); |   703                          kShortExternalStringMask)); | 
|   705   STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |   704   STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 
|   706   __ j(zero, &seq_two_byte_string);  // Go to (9). |   705   __ j(zero, &seq_two_byte_string);  // Go to (9). | 
|   707  |   706  | 
|   708   // (2) Sequential one byte?  If yes, go to (6). |   707   // (2) Sequential one byte?  If yes, go to (5). | 
|   709   // Any other sequential string must be one byte. |   708   // Any other sequential string must be one byte. | 
|   710   __ andb(rbx, Immediate(kIsNotStringMask | |   709   __ andb(rbx, Immediate(kIsNotStringMask | | 
|   711                          kStringRepresentationMask | |   710                          kStringRepresentationMask | | 
|   712                          kShortExternalStringMask)); |   711                          kShortExternalStringMask)); | 
|   713   __ j(zero, &seq_one_byte_string, Label::kNear);  // Go to (6). |   712   __ j(zero, &seq_one_byte_string, Label::kNear);  // Go to (5). | 
|   714  |   713  | 
|   715   // (3) Anything but sequential or cons?  If yes, go to (7). |   714   // (3) Sequential or cons?  If not, go to (6). | 
|   716   // We check whether the subject string is a cons, since sequential strings |   715   // We check whether the subject string is a cons, since sequential strings | 
|   717   // have already been covered. |   716   // have already been covered. | 
|   718   STATIC_ASSERT(kConsStringTag < kExternalStringTag); |   717   STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 
|   719   STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |   718   STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 
|   720   STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |   719   STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 
|   721   STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |   720   STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 
|   722   __ cmpp(rbx, Immediate(kExternalStringTag)); |   721   __ cmpp(rbx, Immediate(kExternalStringTag)); | 
|   723   __ j(greater_equal, ¬_seq_nor_cons);  // Go to (7). |   722   __ j(greater_equal, ¬_seq_nor_cons);  // Go to (6). | 
|   724  |   723  | 
|   725   // (4) Cons string.  Check that it's flat. |   724   // (4) Cons string.  Check that it's flat. | 
|   726   // Replace subject with first string and reload instance type. |   725   // Replace subject with first string and reload instance type. | 
|   727   __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), |   726   __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), | 
|   728                  Heap::kempty_stringRootIndex); |   727                  Heap::kempty_stringRootIndex); | 
|   729   __ j(not_equal, &runtime); |   728   __ j(not_equal, &runtime); | 
|   730   __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |   729   __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); | 
|   731   __ bind(&check_underlying); |   730   __ jmp(&check_underlying); | 
|   732   __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |  | 
|   733   __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |  | 
|   734  |   731  | 
|   735   // (5a) Is subject sequential two byte?  If yes, go to (9). |   732   // (5) One byte sequential.  Load regexp code for one byte. | 
|   736   __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); |  | 
|   737   STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |  | 
|   738   __ j(zero, &seq_two_byte_string);  // Go to (9). |  | 
|   739   // (5b) Is subject external?  If yes, go to (8). |  | 
|   740   __ testb(rbx, Immediate(kStringRepresentationMask)); |  | 
|   741   // The underlying external string is never a short external string. |  | 
|   742   STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); |  | 
|   743   STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); |  | 
|   744   __ j(not_zero, &external_string);  // Go to (8) |  | 
|   745  |  | 
|   746   // (6) One byte sequential.  Load regexp code for one byte. |  | 
|   747   __ bind(&seq_one_byte_string); |   733   __ bind(&seq_one_byte_string); | 
|   748   // rax: RegExp data (FixedArray) |   734   // rax: RegExp data (FixedArray) | 
|   749   __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); |   735   __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); | 
|   750   __ Set(rcx, 1);  // Type is one byte. |   736   __ Set(rcx, 1);  // Type is one byte. | 
|   751  |   737  | 
|   752   // (E) Carry on.  String handling is done. |   738   // (E) Carry on.  String handling is done. | 
|   753   __ bind(&check_code); |   739   __ bind(&check_code); | 
|   754   // r11: irregexp code |   740   // r11: irregexp code | 
|   755   // Check that the irregexp code has been generated for the actual string |   741   // Check that the irregexp code has been generated for the actual string | 
|   756   // encoding. If it has, the field contains a code object otherwise it contains |   742   // encoding. If it has, the field contains a code object otherwise it contains | 
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   983   __ j(equal, &runtime); |   969   __ j(equal, &runtime); | 
|   984  |   970  | 
|   985   // For exception, throw the exception again. |   971   // For exception, throw the exception again. | 
|   986   __ TailCallRuntime(Runtime::kRegExpExecReThrow); |   972   __ TailCallRuntime(Runtime::kRegExpExecReThrow); | 
|   987  |   973  | 
|   988   // Do the runtime call to execute the regexp. |   974   // Do the runtime call to execute the regexp. | 
|   989   __ bind(&runtime); |   975   __ bind(&runtime); | 
|   990   __ TailCallRuntime(Runtime::kRegExpExec); |   976   __ TailCallRuntime(Runtime::kRegExpExec); | 
|   991  |   977  | 
|   992   // Deferred code for string handling. |   978   // Deferred code for string handling. | 
|   993   // (7) Not a long external string?  If yes, go to (10). |   979   // (6) Long external string?  If not, go to (10). | 
|   994   __ bind(¬_seq_nor_cons); |   980   __ bind(¬_seq_nor_cons); | 
|   995   // Compare flags are still set from (3). |   981   // Compare flags are still set from (3). | 
|   996   __ j(greater, ¬_long_external, Label::kNear);  // Go to (10). |   982   __ j(greater, ¬_long_external, Label::kNear);  // Go to (10). | 
|   997  |   983  | 
|   998   // (8) External string.  Short external strings have been ruled out. |   984   // (7) External string.  Short external strings have been ruled out. | 
|   999   __ bind(&external_string); |   985   __ bind(&external_string); | 
|  1000   __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |   986   __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 
|  1001   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |   987   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 
|  1002   if (FLAG_debug_code) { |   988   if (FLAG_debug_code) { | 
|  1003     // Assert that we do not have a cons or slice (indirect strings) here. |   989     // Assert that we do not have a cons or slice (indirect strings) here. | 
|  1004     // Sequential strings have already been ruled out. |   990     // Sequential strings have already been ruled out. | 
|  1005     __ testb(rbx, Immediate(kIsIndirectStringMask)); |   991     __ testb(rbx, Immediate(kIsIndirectStringMask)); | 
|  1006     __ Assert(zero, kExternalStringExpectedButNotFound); |   992     __ Assert(zero, kExternalStringExpectedButNotFound); | 
|  1007   } |   993   } | 
|  1008   __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |   994   __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 
|  1009   // Move the pointer so that offset-wise, it looks like a sequential string. |   995   // Move the pointer so that offset-wise, it looks like a sequential string. | 
|  1010   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |   996   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 
|  1011   __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |   997   __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 
|  1012   STATIC_ASSERT(kTwoByteStringTag == 0); |   998   STATIC_ASSERT(kTwoByteStringTag == 0); | 
|  1013   // (8a) Is the external string one byte?  If yes, go to (6). |   999   // (8) Is the external string one byte?  If yes, go to (5). | 
|  1014   __ testb(rbx, Immediate(kStringEncodingMask)); |  1000   __ testb(rbx, Immediate(kStringEncodingMask)); | 
|  1015   __ j(not_zero, &seq_one_byte_string);  // Goto (6). |  1001   __ j(not_zero, &seq_one_byte_string);  // Go to (5). | 
|  1016  |  1002  | 
|  1017   // rdi: subject string (flat two-byte) |  1003   // rdi: subject string (flat two-byte) | 
|  1018   // rax: RegExp data (FixedArray) |  1004   // rax: RegExp data (FixedArray) | 
|  1019   // (9) Two byte sequential.  Load regexp code for one byte.  Go to (E). |  1005   // (9) Two byte sequential.  Load regexp code for two byte.  Go to (E). | 
|  1020   __ bind(&seq_two_byte_string); |  1006   __ bind(&seq_two_byte_string); | 
|  1021   __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |  1007   __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); | 
|  1022   __ Set(rcx, 0);  // Type is two byte. |  1008   __ Set(rcx, 0);  // Type is two byte. | 
|  1023   __ jmp(&check_code);  // Go to (E). |  1009   __ jmp(&check_code);  // Go to (E). | 
|  1024  |  1010  | 
|  1025   // (10) Not a string or a short external string?  If yes, bail out to runtime. |  1011   // (10) Not a string or a short external string?  If yes, bail out to runtime. | 
|  1026   __ bind(¬_long_external); |  1012   __ bind(¬_long_external); | 
|  1027   // Catch non-string subject or short external string. |  1013   // Catch non-string subject or short external string. | 
|  1028   STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |  1014   STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 
|  1029   __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); |  1015   __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); | 
|  1030   __ j(not_zero, &runtime); |  1016   __ j(not_zero, &runtime); | 
|  1031  |  1017  | 
|  1032   // (11) Sliced string.  Replace subject with parent. Go to (5a). |  1018   // (11) Sliced string.  Replace subject with parent. Go to (1). | 
|  1033   // Load offset into r14 and replace subject string with parent. |  1019   // Load offset into r14 and replace subject string with parent. | 
|  1034   __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |  1020   __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); | 
|  1035   __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |  1021   __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | 
|  1036   __ jmp(&check_underlying); |  1022   __ jmp(&check_underlying); | 
|  1037 #endif  // V8_INTERPRETED_REGEXP |  1023 #endif  // V8_INTERPRETED_REGEXP | 
|  1038 } |  1024 } | 
|  1039  |  1025  | 
|  1040  |  1026  | 
|  1041 static int NegativeComparisonResult(Condition cc) { |  1027 static int NegativeComparisonResult(Condition cc) { | 
|  1042   DCHECK(cc != equal); |  1028   DCHECK(cc != equal); | 
| (...skipping 4600 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  5643                            NULL); |  5629                            NULL); | 
|  5644 } |  5630 } | 
|  5645  |  5631  | 
|  5646  |  5632  | 
|  5647 #undef __ |  5633 #undef __ | 
|  5648  |  5634  | 
|  5649 }  // namespace internal |  5635 }  // namespace internal | 
|  5650 }  // namespace v8 |  5636 }  // namespace v8 | 
|  5651  |  5637  | 
|  5652 #endif  // V8_TARGET_ARCH_X64 |  5638 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW |