OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3380 __ cmp(eax, factory->fixed_array_map()); | 3380 __ cmp(eax, factory->fixed_array_map()); |
3381 __ j(not_equal, &runtime); | 3381 __ j(not_equal, &runtime); |
3382 // Check that the last match info has space for the capture registers and the | 3382 // Check that the last match info has space for the capture registers and the |
3383 // additional information. | 3383 // additional information. |
3384 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); | 3384 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); |
3385 __ SmiUntag(eax); | 3385 __ SmiUntag(eax); |
3386 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); | 3386 __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead)); |
3387 __ cmp(edx, Operand(eax)); | 3387 __ cmp(edx, Operand(eax)); |
3388 __ j(greater, &runtime); | 3388 __ j(greater, &runtime); |
3389 | 3389 |
3390 // Reset offset for possibly sliced string. This also serves as indicator | |
3391 // whether the subject string is a sliced string. 0 is not suitable for this | |
3392 // purpose because a slice can start at offset 0 but have a shorter length. | |
3393 #define NOT_SLICED -1 | |
Vitaly Repeshko
2011/08/12 19:01:00
Ugh, use a constant instead.
| |
3394 __ Set(edi, Immediate(NOT_SLICED)); | |
3390 // ecx: RegExp data (FixedArray) | 3395 // ecx: RegExp data (FixedArray) |
3391 // Check the representation and encoding of the subject string. | 3396 // Check the representation and encoding of the subject string. |
3392 Label seq_ascii_string, seq_two_byte_string, check_code; | 3397 Label seq_ascii_string, seq_two_byte_string, check_code; |
3393 __ mov(eax, Operand(esp, kSubjectOffset)); | 3398 __ mov(eax, Operand(esp, kSubjectOffset)); |
3394 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3399 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3395 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 3400 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
3396 // First check for flat two byte string. | 3401 // First check for flat two byte string. |
3397 __ and_(ebx, | 3402 __ and_(ebx, |
3398 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); | 3403 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); |
3399 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 3404 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
3400 __ j(zero, &seq_two_byte_string); | 3405 __ j(zero, &seq_two_byte_string); |
3401 // Any other flat string must be a flat ascii string. | 3406 // Any other flat string must be a flat ascii string. |
3402 __ test(Operand(ebx), | 3407 __ and_(Operand(ebx), |
3403 Immediate(kIsNotStringMask | kStringRepresentationMask)); | 3408 Immediate(kIsNotStringMask | kStringRepresentationMask)); |
3404 __ j(zero, &seq_ascii_string); | 3409 __ j(zero, &seq_ascii_string); |
3405 | 3410 |
3406 // Check for flat cons string. | 3411 // Check for flat cons string or truncated sliced string. |
Vitaly Repeshko
2011/08/12 19:01:00
Update the comment.
| |
3407 // A flat cons string is a cons string where the second part is the empty | 3412 // A flat cons string is a cons string where the second part is the empty |
3408 // string. In that case the subject string is just the first part of the cons | 3413 // string. In that case the subject string is just the first part of the cons |
3409 // string. Also in this case the first part of the cons string is known to be | 3414 // string. Also in this case the first part of the cons string is known to be |
3410 // a sequential string or an external string. | 3415 // a sequential string or an external string. |
3411 STATIC_ASSERT(kExternalStringTag != 0); | 3416 // A truncated sliced string has the offset 0 and the same length as the |
3412 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 3417 // parent string. |
3413 __ test(Operand(ebx), | 3418 Label cons_string, check_encoding; |
3414 Immediate(kIsNotStringMask | kExternalStringTag)); | 3419 __ cmp(Operand(ebx), Immediate(kConsStringTag)); |
3415 __ j(not_zero, &runtime); | 3420 __ j(equal, &cons_string); |
3416 // String is a cons string. | 3421 __ cmp(Operand(ebx), Immediate(kSlicedStringTag)); |
3417 __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset)); | 3422 // If subject is not a sliced string, it can only be a non-string or an |
3418 __ cmp(Operand(edx), factory->empty_string()); | 3423 // external string. |
3424 __ j(not_equal, &runtime); | |
3425 // String is sliced. | |
3426 __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); | |
3427 __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); | |
3428 // edi: offset of sliced string, smi-tagged. | |
3429 // eax: parent string. | |
3430 __ jmp(&check_encoding); | |
3431 // String is a cons string, check whether it is flat. | |
3432 __ bind(&cons_string); | |
3433 __ mov(ebx, FieldOperand(eax, ConsString::kSecondOffset)); | |
3434 __ cmp(Operand(ebx), factory->empty_string()); | |
3419 __ j(not_equal, &runtime); | 3435 __ j(not_equal, &runtime); |
3420 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 3436 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
3437 // eax: first part of cons string or parent of sliced string. | |
3438 // edx: map of first part of cons string or map of parent of sliced string. | |
3439 // Is first part of cons or parent of slice a flat two byte string? | |
3440 __ bind(&check_encoding); | |
3421 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3441 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3422 // String is a cons string with empty second part. | |
3423 // eax: first part of cons string. | |
3424 // ebx: map of first part of cons string. | |
3425 // Is first part a flat two byte string? | |
3426 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3442 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
3427 kStringRepresentationMask | kStringEncodingMask); | 3443 kStringRepresentationMask | kStringEncodingMask); |
3428 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3444 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
3429 __ j(zero, &seq_two_byte_string); | 3445 __ j(zero, &seq_two_byte_string); |
3430 // Any other flat string must be ascii. | 3446 // Any other flat string must be ascii. |
3431 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3447 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), |
3432 kStringRepresentationMask); | 3448 kStringRepresentationMask); |
3433 __ j(not_zero, &runtime); | 3449 __ j(not_zero, &runtime); |
3434 | 3450 |
3435 __ bind(&seq_ascii_string); | 3451 __ bind(&seq_ascii_string); |
3436 // eax: subject string (flat ascii) | 3452 // eax: subject string (flat ascii) |
3437 // ecx: RegExp data (FixedArray) | 3453 // ecx: RegExp data (FixedArray) |
3438 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 3454 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
3439 __ Set(edi, Immediate(1)); // Type is ascii. | 3455 __ Set(ecx, Immediate(1)); // Type is ascii. |
3440 __ jmp(&check_code); | 3456 __ jmp(&check_code); |
3441 | 3457 |
3442 __ bind(&seq_two_byte_string); | 3458 __ bind(&seq_two_byte_string); |
3443 // eax: subject string (flat two byte) | 3459 // eax: subject string (flat two byte) |
3444 // ecx: RegExp data (FixedArray) | 3460 // ecx: RegExp data (FixedArray) |
3445 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | 3461 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
3446 __ Set(edi, Immediate(0)); // Type is two byte. | 3462 __ Set(ecx, Immediate(0)); // Type is two byte. |
3447 | 3463 |
3448 __ bind(&check_code); | 3464 __ bind(&check_code); |
3449 // Check that the irregexp code has been generated for the actual string | 3465 // Check that the irregexp code has been generated for the actual string |
3450 // encoding. If it has, the field contains a code object otherwise it contains | 3466 // encoding. If it has, the field contains a code object otherwise it contains |
3451 // a smi (code flushing support). | 3467 // a smi (code flushing support). |
3452 __ JumpIfSmi(edx, &runtime); | 3468 __ JumpIfSmi(edx, &runtime); |
3453 | 3469 |
3454 // eax: subject string | 3470 // eax: subject string |
3455 // edx: code | 3471 // edx: code |
3456 // edi: encoding of subject string (1 if ascii, 0 if two_byte); | 3472 // edi: encoding of subject string (1 if ascii, 0 if two_byte); |
Vitaly Repeshko
2011/08/12 19:01:00
Update the comment.
| |
3457 // Load used arguments before starting to push arguments for call to native | 3473 // Load used arguments before starting to push arguments for call to native |
3458 // RegExp code to avoid handling changing stack height. | 3474 // RegExp code to avoid handling changing stack height. |
3459 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 3475 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
3460 __ SmiUntag(ebx); // Previous index from smi. | 3476 __ SmiUntag(ebx); // Previous index from smi. |
3461 | 3477 |
3462 // eax: subject string | 3478 // eax: subject string |
3463 // ebx: previous index | 3479 // ebx: previous index |
3464 // edx: code | 3480 // edx: code |
3465 // edi: encoding of subject string (1 if ascii 0 if two_byte); | 3481 // edi: encoding of subject string (1 if ascii 0 if two_byte); |
3466 // All checks done. Now push arguments for native regexp code. | 3482 // All checks done. Now push arguments for native regexp code. |
3467 Counters* counters = masm->isolate()->counters(); | 3483 Counters* counters = masm->isolate()->counters(); |
3468 __ IncrementCounter(counters->regexp_entry_native(), 1); | 3484 __ IncrementCounter(counters->regexp_entry_native(), 1); |
3469 | 3485 |
3470 // Isolates: note we add an additional parameter here (isolate pointer). | 3486 // Isolates: note we add an additional parameter here (isolate pointer). |
3471 static const int kRegExpExecuteArguments = 8; | 3487 static const int kRegExpExecuteArguments = 8; |
3472 __ EnterApiExitFrame(kRegExpExecuteArguments); | 3488 __ EnterApiExitFrame(kRegExpExecuteArguments); |
3473 | 3489 |
3474 // Argument 8: Pass current isolate address. | 3490 // Argument 8: Pass current isolate address. |
3475 __ mov(Operand(esp, 7 * kPointerSize), | 3491 __ mov(Operand(esp, 7 * kPointerSize), |
3476 Immediate(ExternalReference::isolate_address())); | 3492 Immediate(ExternalReference::isolate_address())); |
3477 | 3493 |
3478 // Argument 7: Indicate that this is a direct call from JavaScript. | 3494 // Argument 7: Indicate that this is a direct call from JavaScript. |
3479 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); | 3495 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); |
3480 | 3496 |
3481 // Argument 6: Start (high end) of backtracking stack memory area. | 3497 // Argument 6: Start (high end) of backtracking stack memory area. |
3482 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); | 3498 __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address)); |
3483 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3499 __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
3484 __ mov(Operand(esp, 5 * kPointerSize), ecx); | 3500 __ mov(Operand(esp, 5 * kPointerSize), esi); |
3485 | 3501 |
3486 // Argument 5: static offsets vector buffer. | 3502 // Argument 5: static offsets vector buffer. |
3487 __ mov(Operand(esp, 4 * kPointerSize), | 3503 __ mov(Operand(esp, 4 * kPointerSize), |
3488 Immediate(ExternalReference::address_of_static_offsets_vector( | 3504 Immediate(ExternalReference::address_of_static_offsets_vector( |
3489 masm->isolate()))); | 3505 masm->isolate()))); |
3490 | 3506 |
3507 // Argument 2: Previous index. | |
3508 __ mov(Operand(esp, 1 * kPointerSize), ebx); | |
3509 | |
3510 // Argument 1: Original subject string. | |
3511 // The original subject is in the previous stack frame. Therefore we have to | |
3512 // use ebp, which points exactly to one pointer size below the previous esp. | |
3513 // (Because creating a new stack frame pushes the previous ebp onto the stack | |
3514 // and thereby moves up esp by one kPointerSize.) | |
3515 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); | |
3516 __ mov(Operand(esp, 0 * kPointerSize), esi); | |
3517 // esi: original subject string | |
3518 // eax: underlying subject string | |
3519 | |
3491 // Argument 4: End of string data | 3520 // Argument 4: End of string data |
3492 // Argument 3: Start of string data | 3521 // Argument 3: Start of string data |
3493 Label setup_two_byte, setup_rest; | 3522 Label setup_two_byte, setup_rest, length_not_from_slice, got_length; |
3494 __ test(edi, Operand(edi)); | 3523 // Prepare start and end index of the input. |
3495 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); | 3524 // Load the length from the original sliced string if that is the case. |
3525 __ cmp(edi, NOT_SLICED); | |
3526 __ j(equal, &length_not_from_slice); | |
3527 __ mov(esi, FieldOperand(esi, String::kLengthOffset)); | |
3528 __ add(esi, Operand(edi)); // Calculate input end wrt offset. | |
3529 __ SmiUntag(edi); | |
3530 __ add(ebx, Operand(edi)); // Calculate input start wrt offset. | |
3531 __ jmp(&got_length); | |
3532 __ bind(&length_not_from_slice); | |
3533 __ mov(esi, FieldOperand(eax, String::kLengthOffset)); | |
3534 __ bind(&got_length); | |
3535 | |
3536 // ebx: start index of the input string | |
3537 // esi: end index of the input string | |
3538 __ test(ecx, Operand(ecx)); | |
3496 __ j(zero, &setup_two_byte, Label::kNear); | 3539 __ j(zero, &setup_two_byte, Label::kNear); |
3497 __ SmiUntag(edi); | 3540 __ SmiUntag(esi); |
3498 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); | 3541 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqAsciiString::kHeaderSize)); |
3499 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3542 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
3500 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); | 3543 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); |
3501 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 3544 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
3502 __ jmp(&setup_rest, Label::kNear); | 3545 __ jmp(&setup_rest, Label::kNear); |
3503 | 3546 |
3504 __ bind(&setup_two_byte); | 3547 __ bind(&setup_two_byte); |
3505 STATIC_ASSERT(kSmiTag == 0); | 3548 STATIC_ASSERT(kSmiTag == 0); |
3506 STATIC_ASSERT(kSmiTagSize == 1); // edi is smi (powered by 2). | 3549 STATIC_ASSERT(kSmiTagSize == 1); // esi is smi (powered by 2). |
3507 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize)); | 3550 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize)); |
3508 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3551 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
3509 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); | 3552 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); |
3510 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 3553 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
3511 | 3554 |
3512 __ bind(&setup_rest); | 3555 __ bind(&setup_rest); |
3513 | 3556 |
3514 // Argument 2: Previous index. | |
3515 __ mov(Operand(esp, 1 * kPointerSize), ebx); | |
3516 | |
3517 // Argument 1: Subject string. | |
3518 __ mov(Operand(esp, 0 * kPointerSize), eax); | |
3519 | |
3520 // Locate the code entry and call it. | 3557 // Locate the code entry and call it. |
3521 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 3558 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
3522 __ call(Operand(edx)); | 3559 __ call(Operand(edx)); |
3523 | 3560 |
3524 // Drop arguments and come back to JS mode. | 3561 // Drop arguments and come back to JS mode. |
3525 __ LeaveApiExitFrame(); | 3562 __ LeaveApiExitFrame(); |
3526 | 3563 |
3527 // Check the result. | 3564 // Check the result. |
3528 Label success; | 3565 Label success; |
3529 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); | 3566 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); |
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4820 } | 4857 } |
4821 | 4858 |
4822 | 4859 |
4823 // ------------------------------------------------------------------------- | 4860 // ------------------------------------------------------------------------- |
4824 // StringCharCodeAtGenerator | 4861 // StringCharCodeAtGenerator |
4825 | 4862 |
4826 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 4863 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
4827 Label flat_string; | 4864 Label flat_string; |
4828 Label ascii_string; | 4865 Label ascii_string; |
4829 Label got_char_code; | 4866 Label got_char_code; |
4867 Label sliced_string; | |
4830 | 4868 |
4831 // If the receiver is a smi trigger the non-string case. | 4869 // If the receiver is a smi trigger the non-string case. |
4832 STATIC_ASSERT(kSmiTag == 0); | 4870 STATIC_ASSERT(kSmiTag == 0); |
4833 __ JumpIfSmi(object_, receiver_not_string_); | 4871 __ JumpIfSmi(object_, receiver_not_string_); |
4834 | 4872 |
4835 // Fetch the instance type of the receiver into result register. | 4873 // Fetch the instance type of the receiver into result register. |
4836 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 4874 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
4837 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 4875 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
4838 // If the receiver is not a string trigger the non-string case. | 4876 // If the receiver is not a string trigger the non-string case. |
4839 __ test(result_, Immediate(kIsNotStringMask)); | 4877 __ test(result_, Immediate(kIsNotStringMask)); |
(...skipping 10 matching lines...) Expand all Loading... | |
4850 // Check for index out of range. | 4888 // Check for index out of range. |
4851 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); | 4889 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); |
4852 __ j(above_equal, index_out_of_range_); | 4890 __ j(above_equal, index_out_of_range_); |
4853 | 4891 |
4854 // We need special handling for non-flat strings. | 4892 // We need special handling for non-flat strings. |
4855 STATIC_ASSERT(kSeqStringTag == 0); | 4893 STATIC_ASSERT(kSeqStringTag == 0); |
4856 __ test(result_, Immediate(kStringRepresentationMask)); | 4894 __ test(result_, Immediate(kStringRepresentationMask)); |
4857 __ j(zero, &flat_string); | 4895 __ j(zero, &flat_string); |
4858 | 4896 |
4859 // Handle non-flat strings. | 4897 // Handle non-flat strings. |
4860 __ test(result_, Immediate(kIsConsStringMask)); | 4898 __ and_(result_, kStringRepresentationMask); |
4861 __ j(zero, &call_runtime_); | 4899 __ cmp(result_, kSlicedStringTag); |
4900 __ j(equal, &sliced_string); | |
4901 __ cmp(result_, kExternalStringTag); | |
4902 __ j(equal, &call_runtime_); | |
4862 | 4903 |
4863 // ConsString. | 4904 // ConsString. |
4864 // Check whether the right hand side is the empty string (i.e. if | 4905 // Check whether the right hand side is the empty string (i.e. if |
4865 // this is really a flat string in a cons string). If that is not | 4906 // this is really a flat string in a cons string). If that is not |
4866 // the case we would rather go to the runtime system now to flatten | 4907 // the case we would rather go to the runtime system now to flatten |
4867 // the string. | 4908 // the string. |
4868 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), | 4909 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), |
4869 Immediate(masm->isolate()->factory()->empty_string())); | 4910 Immediate(masm->isolate()->factory()->empty_string())); |
4870 __ j(not_equal, &call_runtime_); | 4911 __ j(not_equal, &call_runtime_); |
4871 // Get the first of the two strings and load its instance type. | 4912 // Get the first of the two strings and load its instance type. |
4872 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); | 4913 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); |
4873 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 4914 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
4874 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 4915 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
4875 // If the first cons component is also non-flat, then go to runtime. | 4916 // If the first cons component is also non-flat, then go to runtime. |
4876 STATIC_ASSERT(kSeqStringTag == 0); | 4917 STATIC_ASSERT(kSeqStringTag == 0); |
4877 __ test(result_, Immediate(kStringRepresentationMask)); | 4918 __ test(result_, Immediate(kStringRepresentationMask)); |
4878 __ j(not_zero, &call_runtime_); | 4919 __ j(not_zero, &call_runtime_); |
4920 __ jmp(&flat_string); | |
4921 | |
4922 // SlicedString, unpack and add offset. | |
4923 __ bind(&sliced_string); | |
4924 __ add(scratch_, FieldOperand(object_, SlicedString::kOffsetOffset)); | |
4925 __ mov(object_, FieldOperand(object_, SlicedString::kParentOffset)); | |
4926 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | |
4927 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | |
4879 | 4928 |
4880 // Check for 1-byte or 2-byte string. | 4929 // Check for 1-byte or 2-byte string. |
4881 __ bind(&flat_string); | 4930 __ bind(&flat_string); |
4882 STATIC_ASSERT(kAsciiStringTag != 0); | 4931 STATIC_ASSERT(kAsciiStringTag != 0); |
4883 __ test(result_, Immediate(kStringEncodingMask)); | 4932 __ test(result_, Immediate(kStringEncodingMask)); |
4884 __ j(not_zero, &ascii_string); | 4933 __ j(not_zero, &ascii_string); |
4885 | 4934 |
4886 // 2-byte string. | 4935 // 2-byte string. |
4887 // Load the 2-byte character code into the result register. | 4936 // Load the 2-byte character code into the result register. |
4888 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 4937 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5194 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 5243 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
5195 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 5244 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
5196 __ and_(ecx, kStringRepresentationMask); | 5245 __ and_(ecx, kStringRepresentationMask); |
5197 __ cmp(ecx, kExternalStringTag); | 5246 __ cmp(ecx, kExternalStringTag); |
5198 __ j(equal, &string_add_runtime); | 5247 __ j(equal, &string_add_runtime); |
5199 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 5248 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
5200 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 5249 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
5201 __ and_(ecx, kStringRepresentationMask); | 5250 __ and_(ecx, kStringRepresentationMask); |
5202 __ cmp(ecx, kExternalStringTag); | 5251 __ cmp(ecx, kExternalStringTag); |
5203 __ j(equal, &string_add_runtime); | 5252 __ j(equal, &string_add_runtime); |
5253 // We cannot encounter sliced strings here since: | |
5254 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); | |
5204 // Now check if both strings are ascii strings. | 5255 // Now check if both strings are ascii strings. |
5205 // eax: first string | 5256 // eax: first string |
5206 // ebx: length of resulting flat string as a smi | 5257 // ebx: length of resulting flat string as a smi |
5207 // edx: second string | 5258 // edx: second string |
5208 Label non_ascii_string_add_flat_result; | 5259 Label non_ascii_string_add_flat_result; |
5209 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag); | 5260 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag); |
5210 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 5261 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
5211 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); | 5262 __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag); |
5212 __ j(zero, &non_ascii_string_add_flat_result); | 5263 __ j(zero, &non_ascii_string_add_flat_result); |
5213 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 5264 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5605 __ test(hash, Operand(hash)); | 5656 __ test(hash, Operand(hash)); |
5606 __ j(not_zero, &hash_not_zero, Label::kNear); | 5657 __ j(not_zero, &hash_not_zero, Label::kNear); |
5607 __ mov(hash, Immediate(27)); | 5658 __ mov(hash, Immediate(27)); |
5608 __ bind(&hash_not_zero); | 5659 __ bind(&hash_not_zero); |
5609 } | 5660 } |
5610 | 5661 |
5611 | 5662 |
5612 void SubStringStub::Generate(MacroAssembler* masm) { | 5663 void SubStringStub::Generate(MacroAssembler* masm) { |
5613 Label runtime; | 5664 Label runtime; |
5614 | 5665 |
5666 if (FLAG_string_slices) { | |
5667 __ jmp(&runtime); | |
5668 } | |
5615 // Stack frame on entry. | 5669 // Stack frame on entry. |
5616 // esp[0]: return address | 5670 // esp[0]: return address |
5617 // esp[4]: to | 5671 // esp[4]: to |
5618 // esp[8]: from | 5672 // esp[8]: from |
5619 // esp[12]: string | 5673 // esp[12]: string |
5620 | 5674 |
5621 // Make sure first argument is a string. | 5675 // Make sure first argument is a string. |
5622 __ mov(eax, Operand(esp, 3 * kPointerSize)); | 5676 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
5623 STATIC_ASSERT(kSmiTag == 0); | 5677 STATIC_ASSERT(kSmiTag == 0); |
5624 __ JumpIfSmi(eax, &runtime); | 5678 __ JumpIfSmi(eax, &runtime); |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6381 __ Drop(1); | 6435 __ Drop(1); |
6382 __ ret(2 * kPointerSize); | 6436 __ ret(2 * kPointerSize); |
6383 } | 6437 } |
6384 | 6438 |
6385 | 6439 |
6386 #undef __ | 6440 #undef __ |
6387 | 6441 |
6388 } } // namespace v8::internal | 6442 } } // namespace v8::internal |
6389 | 6443 |
6390 #endif // V8_TARGET_ARCH_IA32 | 6444 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |