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