Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 7477045: Tentative implementation of string slices (hidden under the flag --string-slices). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Implemented suggested changes. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/heap-inl.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | src/jsregexp.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698