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

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: Some more 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.
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698