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