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

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

Powered by Google App Engine
This is Rietveld 408576698