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 4321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4332 __ cmp(r0, ip); | 4332 __ cmp(r0, ip); |
4333 __ b(ne, &runtime); | 4333 __ b(ne, &runtime); |
4334 // Check that the last match info has space for the capture registers and the | 4334 // Check that the last match info has space for the capture registers and the |
4335 // additional information. | 4335 // additional information. |
4336 __ ldr(r0, | 4336 __ ldr(r0, |
4337 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); | 4337 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); |
4338 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead)); | 4338 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead)); |
4339 __ cmp(r2, Operand(r0, ASR, kSmiTagSize)); | 4339 __ cmp(r2, Operand(r0, ASR, kSmiTagSize)); |
4340 __ b(gt, &runtime); | 4340 __ b(gt, &runtime); |
4341 | 4341 |
4342 // Reset offset for possibly sliced string. | |
4343 __ mov(r9, Operand(0)); | |
4342 // subject: Subject string | 4344 // subject: Subject string |
4343 // regexp_data: RegExp data (FixedArray) | 4345 // regexp_data: RegExp data (FixedArray) |
4344 // Check the representation and encoding of the subject string. | 4346 // Check the representation and encoding of the subject string. |
4345 Label seq_string; | 4347 Label seq_string; |
4346 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4348 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
4347 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 4349 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
4348 // First check for flat string. | 4350 // First check for flat string. |
4349 __ tst(r0, Operand(kIsNotStringMask | kStringRepresentationMask)); | 4351 __ and_(r1, r0, Operand(kIsNotStringMask | kStringRepresentationMask), SetCC); |
4350 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | 4352 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); |
4351 __ b(eq, &seq_string); | 4353 __ b(eq, &seq_string); |
4352 | 4354 |
4353 // subject: Subject string | 4355 // subject: Subject string |
4354 // regexp_data: RegExp data (FixedArray) | 4356 // regexp_data: RegExp data (FixedArray) |
4355 // Check for flat cons string. | 4357 // Check for flat cons string or sliced string. |
4356 // A flat cons string is a cons string where the second part is the empty | 4358 // A flat cons string is a cons string where the second part is the empty |
4357 // string. In that case the subject string is just the first part of the cons | 4359 // string. In that case the subject string is just the first part of the cons |
4358 // string. Also in this case the first part of the cons string is known to be | 4360 // string. Also in this case the first part of the cons string is known to be |
4359 // a sequential string or an external string. | 4361 // a sequential string or an external string. |
4360 STATIC_ASSERT(kExternalStringTag !=0); | 4362 // In the case of a sliced string its offset has to be taken into account. |
4361 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 4363 Label cons_string, check_encoding; |
4362 __ tst(r0, Operand(kIsNotStringMask | kExternalStringTag)); | 4364 STATIC_ASSERT((kConsStringTag < kExternalStringTag)); |
4363 __ b(ne, &runtime); | 4365 STATIC_ASSERT((kSlicedStringTag > kExternalStringTag)); |
4366 __ cmp(r1, Operand(kExternalStringTag)); | |
4367 __ b(lt, &cons_string); | |
4368 __ b(eq, &runtime); | |
4369 | |
4370 // String is sliced. | |
4371 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | |
4372 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); | |
4373 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | |
4374 // r9: offset of sliced string, smi-tagged. | |
4375 __ jmp(&check_encoding); | |
4376 // String is a cons string, check whether it is flat. | |
4377 __ bind(&cons_string); | |
4364 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 4378 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
4365 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); | 4379 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); |
4366 __ cmp(r0, r1); | 4380 __ cmp(r0, r1); |
4367 __ b(ne, &runtime); | 4381 __ b(ne, &runtime); |
4368 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 4382 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
4383 // Is first part of cons or parent of slice a flat string? | |
4384 __ bind(&check_encoding); | |
4369 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4385 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
4370 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 4386 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
4371 // Is first part a flat string? | |
4372 STATIC_ASSERT(kSeqStringTag == 0); | 4387 STATIC_ASSERT(kSeqStringTag == 0); |
4373 __ tst(r0, Operand(kStringRepresentationMask)); | 4388 __ tst(r0, Operand(kStringRepresentationMask)); |
4374 __ b(ne, &runtime); | 4389 __ b(ne, &runtime); |
4375 | |
4376 __ bind(&seq_string); | 4390 __ bind(&seq_string); |
4377 // subject: Subject string | 4391 // subject: Subject string |
4378 // regexp_data: RegExp data (FixedArray) | 4392 // regexp_data: RegExp data (FixedArray) |
4379 // r0: Instance type of subject string | 4393 // r0: Instance type of subject string |
4380 STATIC_ASSERT(4 == kAsciiStringTag); | 4394 STATIC_ASSERT(4 == kAsciiStringTag); |
4381 STATIC_ASSERT(kTwoByteStringTag == 0); | 4395 STATIC_ASSERT(kTwoByteStringTag == 0); |
4382 // Find the code object based on the assumptions above. | 4396 // Find the code object based on the assumptions above. |
4383 __ and_(r0, r0, Operand(kStringEncodingMask)); | 4397 __ and_(r0, r0, Operand(kStringEncodingMask)); |
4384 __ mov(r3, Operand(r0, ASR, 2), SetCC); | 4398 __ mov(r3, Operand(r0, ASR, 2), SetCC); |
4385 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); | 4399 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4431 __ add(r0, r0, Operand(r2)); | 4445 __ add(r0, r0, Operand(r2)); |
4432 __ str(r0, MemOperand(sp, 2 * kPointerSize)); | 4446 __ str(r0, MemOperand(sp, 2 * kPointerSize)); |
4433 | 4447 |
4434 // Argument 5 (sp[4]): static offsets vector buffer. | 4448 // Argument 5 (sp[4]): static offsets vector buffer. |
4435 __ mov(r0, | 4449 __ mov(r0, |
4436 Operand(ExternalReference::address_of_static_offsets_vector(isolate))); | 4450 Operand(ExternalReference::address_of_static_offsets_vector(isolate))); |
4437 __ str(r0, MemOperand(sp, 1 * kPointerSize)); | 4451 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
4438 | 4452 |
4439 // For arguments 4 and 3 get string length, calculate start of string data and | 4453 // For arguments 4 and 3 get string length, calculate start of string data and |
4440 // calculate the shift of the index (0 for ASCII and 1 for two byte). | 4454 // calculate the shift of the index (0 for ASCII and 1 for two byte). |
4441 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); | |
4442 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | |
4443 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 4455 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
4444 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4456 __ add(r8, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
4445 __ eor(r3, r3, Operand(1)); | 4457 __ eor(r3, r3, Operand(1)); |
4446 // Argument 4 (r3): End of string data | 4458 // Load the length from the original subject string from the previous stack |
4447 // Argument 3 (r2): Start of string data | 4459 // frame. Therefore we have to use fp, which points exactly to two pointer |
4460 // sizes below the previous sp. (Because creating a new stack frame pushes | |
4461 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) | |
4462 __ ldr(r0, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); | |
4463 // If slice offset is not 0, load the length from the original sliced string. | |
4464 // Argument 4, r3: End of string data | |
4465 // Argument 3, r2: Start of string data | |
4466 // Prepare start and end index of the input. | |
4467 __ add(r9, r8, Operand(r9, LSL, r3)); | |
4448 __ add(r2, r9, Operand(r1, LSL, r3)); | 4468 __ add(r2, r9, Operand(r1, LSL, r3)); |
4449 __ add(r3, r9, Operand(r0, LSL, r3)); | 4469 |
4470 __ ldr(r8, FieldMemOperand(r0, String::kLengthOffset)); | |
4471 __ mov(r8, Operand(r8, ASR, kSmiTagSize)); | |
4472 __ add(r3, r9, Operand(r8, LSL, r3)); | |
4450 | 4473 |
4451 // Argument 2 (r1): Previous index. | 4474 // Argument 2 (r1): Previous index. |
4452 // Already there | 4475 // Already there |
4453 | 4476 |
4454 // Argument 1 (r0): Subject string. | 4477 // Argument 1 (r0): Subject string. |
4455 __ mov(r0, subject); | 4478 // Already there |
4456 | 4479 |
4457 // Locate the code entry and call it. | 4480 // Locate the code entry and call it. |
4458 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4481 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); |
4459 DirectCEntryStub stub; | 4482 DirectCEntryStub stub; |
4460 stub.GenerateCall(masm, r7); | 4483 stub.GenerateCall(masm, r7); |
4461 | 4484 |
4462 __ LeaveExitFrame(false, no_reg); | 4485 __ LeaveExitFrame(false, no_reg); |
4463 | 4486 |
4464 // r0: result | 4487 // r0: result |
4465 // subject: subject string (callee saved) | 4488 // subject: subject string (callee saved) |
4466 // regexp_data: RegExp data (callee saved) | 4489 // regexp_data: RegExp data (callee saved) |
4467 // last_match_info_elements: Last match info elements (callee saved) | 4490 // last_match_info_elements: Last match info elements (callee saved) |
4468 | 4491 |
4469 // Check the result. | 4492 // Check the result. |
4470 Label success; | 4493 Label success; |
4471 | 4494 |
4472 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); | 4495 __ cmp(subject, Operand(NativeRegExpMacroAssembler::SUCCESS)); |
4473 __ b(eq, &success); | 4496 __ b(eq, &success); |
4474 Label failure; | 4497 Label failure; |
4475 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 4498 __ cmp(subject, Operand(NativeRegExpMacroAssembler::FAILURE)); |
4476 __ b(eq, &failure); | 4499 __ b(eq, &failure); |
4477 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 4500 __ cmp(subject, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
4478 // If not exception it can only be retry. Handle that in the runtime system. | 4501 // If not exception it can only be retry. Handle that in the runtime system. |
4479 __ b(ne, &runtime); | 4502 __ b(ne, &runtime); |
4480 // Result must now be exception. If there is no pending exception already a | 4503 // Result must now be exception. If there is no pending exception already a |
4481 // stack overflow (on the backtrack stack) was detected in RegExp code but | 4504 // stack overflow (on the backtrack stack) was detected in RegExp code but |
4482 // haven't created the exception yet. Handle that in the runtime system. | 4505 // haven't created the exception yet. Handle that in the runtime system. |
4483 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 4506 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
4484 __ mov(r1, Operand(ExternalReference::the_hole_value_location(isolate))); | 4507 __ mov(r1, Operand(ExternalReference::the_hole_value_location(isolate))); |
4485 __ ldr(r1, MemOperand(r1, 0)); | 4508 __ ldr(r1, MemOperand(r1, 0)); |
4486 __ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address, | 4509 __ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address, |
4487 isolate))); | 4510 isolate))); |
4488 __ ldr(r0, MemOperand(r2, 0)); | 4511 __ ldr(r0, MemOperand(r2, 0)); |
4489 __ cmp(r0, r1); | 4512 __ cmp(subject, r1); |
4490 __ b(eq, &runtime); | 4513 __ b(eq, &runtime); |
4491 | 4514 |
4492 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. | 4515 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. |
4493 | 4516 |
4494 // Check if the exception is a termination. If so, throw as uncatchable. | 4517 // Check if the exception is a termination. If so, throw as uncatchable. |
4495 __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex); | 4518 __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex); |
4496 __ cmp(r0, ip); | 4519 __ cmp(subject, ip); |
4497 Label termination_exception; | 4520 Label termination_exception; |
4498 __ b(eq, &termination_exception); | 4521 __ b(eq, &termination_exception); |
4499 | 4522 |
4500 __ Throw(r0); // Expects thrown value in r0. | 4523 __ Throw(subject); // Expects thrown value in r0. |
4501 | 4524 |
4502 __ bind(&termination_exception); | 4525 __ bind(&termination_exception); |
4503 __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0. | 4526 __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0. |
4504 | 4527 |
4505 __ bind(&failure); | 4528 __ bind(&failure); |
4506 // For failure and exception return null. | 4529 // For failure and exception return null. |
4507 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); | 4530 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); |
4508 __ add(sp, sp, Operand(4 * kPointerSize)); | 4531 __ add(sp, sp, Operand(4 * kPointerSize)); |
4509 __ Ret(); | 4532 __ Ret(); |
4510 | 4533 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4768 | IncludeNumberCompareField::encode(include_number_compare_) | 4791 | IncludeNumberCompareField::encode(include_number_compare_) |
4769 | IncludeSmiCompareField::encode(include_smi_compare_); | 4792 | IncludeSmiCompareField::encode(include_smi_compare_); |
4770 } | 4793 } |
4771 | 4794 |
4772 | 4795 |
4773 // StringCharCodeAtGenerator | 4796 // StringCharCodeAtGenerator |
4774 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 4797 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
4775 Label flat_string; | 4798 Label flat_string; |
4776 Label ascii_string; | 4799 Label ascii_string; |
4777 Label got_char_code; | 4800 Label got_char_code; |
4801 Label sliced_string; | |
4778 | 4802 |
4779 // If the receiver is a smi trigger the non-string case. | 4803 // If the receiver is a smi trigger the non-string case. |
4780 __ JumpIfSmi(object_, receiver_not_string_); | 4804 __ JumpIfSmi(object_, receiver_not_string_); |
4781 | 4805 |
4782 // Fetch the instance type of the receiver into result register. | 4806 // Fetch the instance type of the receiver into result register. |
4783 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4807 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
4784 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4808 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
4785 // If the receiver is not a string trigger the non-string case. | 4809 // If the receiver is not a string trigger the non-string case. |
4786 __ tst(result_, Operand(kIsNotStringMask)); | 4810 __ tst(result_, Operand(kIsNotStringMask)); |
4787 __ b(ne, receiver_not_string_); | 4811 __ b(ne, receiver_not_string_); |
4788 | 4812 |
4789 // If the index is non-smi trigger the non-smi case. | 4813 // If the index is non-smi trigger the non-smi case. |
4790 __ JumpIfNotSmi(index_, &index_not_smi_); | 4814 __ JumpIfNotSmi(index_, &index_not_smi_); |
4791 | 4815 |
4792 // Put smi-tagged index into scratch register. | 4816 // Put smi-tagged index into scratch register. |
4793 __ mov(scratch_, index_); | 4817 __ mov(scratch_, index_); |
4794 __ bind(&got_smi_index_); | 4818 __ bind(&got_smi_index_); |
4795 | 4819 |
4796 // Check for index out of range. | 4820 // Check for index out of range. |
4797 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); | 4821 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); |
4798 __ cmp(ip, Operand(scratch_)); | 4822 __ cmp(ip, Operand(scratch_)); |
4799 __ b(ls, index_out_of_range_); | 4823 __ b(ls, index_out_of_range_); |
4800 | 4824 |
4801 // We need special handling for non-flat strings. | 4825 // We need special handling for non-flat strings. |
4802 STATIC_ASSERT(kSeqStringTag == 0); | 4826 STATIC_ASSERT(kSeqStringTag == 0); |
4803 __ tst(result_, Operand(kStringRepresentationMask)); | 4827 __ tst(result_, Operand(kStringRepresentationMask)); |
4804 __ b(eq, &flat_string); | 4828 __ b(eq, &flat_string); |
4805 | 4829 |
4806 // Handle non-flat strings. | 4830 // Handle non-flat strings. |
4807 __ tst(result_, Operand(kIsConsStringMask)); | 4831 __ and_(result_, result_, Operand(kStringRepresentationMask)); |
4832 STATIC_ASSERT((kConsStringTag < kExternalStringTag)); | |
4833 STATIC_ASSERT((kSlicedStringTag > kExternalStringTag)); | |
4834 __ cmp(result_, Operand(kExternalStringTag)); | |
4835 __ b(gt, &sliced_string); | |
4808 __ b(eq, &call_runtime_); | 4836 __ b(eq, &call_runtime_); |
4809 | 4837 |
4810 // ConsString. | 4838 // ConsString. |
4811 // Check whether the right hand side is the empty string (i.e. if | 4839 // Check whether the right hand side is the empty string (i.e. if |
4812 // this is really a flat string in a cons string). If that is not | 4840 // this is really a flat string in a cons string). If that is not |
4813 // the case we would rather go to the runtime system now to flatten | 4841 // the case we would rather go to the runtime system now to flatten |
4814 // the string. | 4842 // the string. |
4843 Label assure_seq_string; | |
4815 __ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); | 4844 __ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); |
4816 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); | 4845 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); |
4817 __ cmp(result_, Operand(ip)); | 4846 __ cmp(result_, Operand(ip)); |
4818 __ b(ne, &call_runtime_); | 4847 __ b(ne, &call_runtime_); |
4819 // Get the first of the two strings and load its instance type. | 4848 // Get the first of the two strings and load its instance type. |
4820 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); | 4849 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); |
4850 __ jmp(&assure_seq_string); | |
4851 | |
4852 // SlicedString, unpack and add offset. | |
4853 __ bind(&sliced_string); | |
4854 __ ldr(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset)); | |
4855 __ add(scratch_, scratch_, result_); | |
4856 __ ldr(object_, FieldMemOperand(object_, SlicedString::kParentOffset)); | |
4857 | |
4858 // Assure that we are dealing with a sequential string. Go to runtime if not. | |
4859 __ bind(&assure_seq_string); | |
4821 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4860 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
4822 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4861 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
4823 // If the first cons component is also non-flat, then go to runtime. | 4862 // Check that parent is not an external string. Go to runtime otherwise. |
4824 STATIC_ASSERT(kSeqStringTag == 0); | 4863 STATIC_ASSERT(kSeqStringTag == 0); |
4825 __ tst(result_, Operand(kStringRepresentationMask)); | 4864 __ tst(result_, Operand(kStringRepresentationMask)); |
4826 __ b(ne, &call_runtime_); | 4865 __ b(ne, &call_runtime_); |
4827 | 4866 |
4828 // Check for 1-byte or 2-byte string. | 4867 // Check for 1-byte or 2-byte string. |
4829 __ bind(&flat_string); | 4868 __ bind(&flat_string); |
4830 STATIC_ASSERT(kAsciiStringTag != 0); | 4869 STATIC_ASSERT(kAsciiStringTag != 0); |
4831 __ tst(result_, Operand(kStringEncodingMask)); | 4870 __ tst(result_, Operand(kStringEncodingMask)); |
4832 __ b(ne, &ascii_string); | 4871 __ b(ne, &ascii_string); |
4833 | 4872 |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5393 // 0 <= from <= to <= string.length. | 5432 // 0 <= from <= to <= string.length. |
5394 // If any of these assumptions fail, we call the runtime system. | 5433 // If any of these assumptions fail, we call the runtime system. |
5395 | 5434 |
5396 static const int kToOffset = 0 * kPointerSize; | 5435 static const int kToOffset = 0 * kPointerSize; |
5397 static const int kFromOffset = 1 * kPointerSize; | 5436 static const int kFromOffset = 1 * kPointerSize; |
5398 static const int kStringOffset = 2 * kPointerSize; | 5437 static const int kStringOffset = 2 * kPointerSize; |
5399 | 5438 |
5400 // Check bounds and smi-ness. | 5439 // Check bounds and smi-ness. |
5401 Register to = r6; | 5440 Register to = r6; |
5402 Register from = r7; | 5441 Register from = r7; |
5442 | |
5443 if (FLAG_string_slices) { | |
5444 __ nop(0); // Jumping as first instruction would crash the code generation. | |
Vitaly Repeshko
2011/08/26 22:29:05
Is this a bug?
| |
5445 __ jmp(&runtime); | |
5446 } | |
5447 | |
5403 __ Ldrd(to, from, MemOperand(sp, kToOffset)); | 5448 __ Ldrd(to, from, MemOperand(sp, kToOffset)); |
5404 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5449 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
5405 STATIC_ASSERT(kSmiTag == 0); | 5450 STATIC_ASSERT(kSmiTag == 0); |
5406 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5451 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5452 | |
5407 // I.e., arithmetic shift right by one un-smi-tags. | 5453 // I.e., arithmetic shift right by one un-smi-tags. |
5408 __ mov(r2, Operand(to, ASR, 1), SetCC); | 5454 __ mov(r2, Operand(to, ASR, 1), SetCC); |
5409 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); | 5455 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); |
5410 // If either to or from had the smi tag bit set, then carry is set now. | 5456 // If either to or from had the smi tag bit set, then carry is set now. |
5411 __ b(cs, &runtime); // Either "from" or "to" is not a smi. | 5457 __ b(cs, &runtime); // Either "from" or "to" is not a smi. |
5412 __ b(mi, &runtime); // From is negative. | 5458 __ b(mi, &runtime); // From is negative. |
5413 | 5459 |
5414 // Both to and from are smis. | 5460 // Both to and from are smis. |
5415 | |
5416 __ sub(r2, r2, Operand(r3), SetCC); | 5461 __ sub(r2, r2, Operand(r3), SetCC); |
5417 __ b(mi, &runtime); // Fail if from > to. | 5462 __ b(mi, &runtime); // Fail if from > to. |
5418 // Special handling of sub-strings of length 1 and 2. One character strings | 5463 // Special handling of sub-strings of length 1 and 2. One character strings |
5419 // are handled in the runtime system (looked up in the single character | 5464 // are handled in the runtime system (looked up in the single character |
5420 // cache). Two character strings are looked for in the symbol cache. | 5465 // cache). Two character strings are looked for in the symbol cache. |
5421 __ cmp(r2, Operand(2)); | 5466 __ cmp(r2, Operand(2)); |
5422 __ b(lt, &runtime); | 5467 __ b(lt, &runtime); |
5423 | 5468 |
5424 // r2: length | 5469 // r2: length |
5425 // r3: from index (untaged smi) | 5470 // r3: from index (untaged smi) |
(...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6535 __ mov(result, Operand(0)); | 6580 __ mov(result, Operand(0)); |
6536 __ Ret(); | 6581 __ Ret(); |
6537 } | 6582 } |
6538 | 6583 |
6539 | 6584 |
6540 #undef __ | 6585 #undef __ |
6541 | 6586 |
6542 } } // namespace v8::internal | 6587 } } // namespace v8::internal |
6543 | 6588 |
6544 #endif // V8_TARGET_ARCH_ARM | 6589 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |