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 |