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