| 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. This also serves as indicator |
| 4343 // whether the subject string is a sliced string. 0 is not suitable for this |
| 4344 // purpose because a slice can start at offset 0 but have a shorter length. |
| 4345 const int32_t kNotAStringSlice = -1; |
| 4346 __ mov(r9, Operand(kNotAStringSlice)); |
| 4342 // subject: Subject string | 4347 // subject: Subject string |
| 4343 // regexp_data: RegExp data (FixedArray) | 4348 // regexp_data: RegExp data (FixedArray) |
| 4344 // Check the representation and encoding of the subject string. | 4349 // Check the representation and encoding of the subject string. |
| 4345 Label seq_string; | 4350 Label seq_string; |
| 4346 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4351 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 4347 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 4352 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 4348 // First check for flat string. | 4353 // First check for flat string. |
| 4349 __ tst(r0, Operand(kIsNotStringMask | kStringRepresentationMask)); | 4354 __ and_(r1, r0, Operand(kIsNotStringMask | kStringRepresentationMask), SetCC); |
| 4350 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | 4355 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); |
| 4351 __ b(eq, &seq_string); | 4356 __ b(eq, &seq_string); |
| 4352 | 4357 |
| 4353 // subject: Subject string | 4358 // subject: Subject string |
| 4354 // regexp_data: RegExp data (FixedArray) | 4359 // regexp_data: RegExp data (FixedArray) |
| 4355 // Check for flat cons string. | 4360 // Check for flat cons string or sliced string. |
| 4356 // A flat cons string is a cons string where the second part is the empty | 4361 // 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 | 4362 // 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 | 4363 // string. Also in this case the first part of the cons string is known to be |
| 4359 // a sequential string or an external string. | 4364 // a sequential string or an external string. |
| 4360 STATIC_ASSERT(kExternalStringTag !=0); | 4365 // In the case of a sliced string its offset has to be taken into account. |
| 4361 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 4366 Label cons_string, check_encoding; |
| 4362 __ tst(r0, Operand(kIsNotStringMask | kExternalStringTag)); | 4367 __ cmp(r1, Operand(kConsStringTag)); |
| 4368 __ b(eq, &cons_string); |
| 4369 __ cmp(r1, Operand(kSlicedStringTag)); |
| 4370 // If subject is not a sliced string, it can only be a non-string or an |
| 4371 // external string. |
| 4363 __ b(ne, &runtime); | 4372 __ b(ne, &runtime); |
| 4373 // String is sliced. |
| 4374 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 4375 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); |
| 4376 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 4377 // r9: offset of sliced string, smi-tagged. |
| 4378 __ jmp(&check_encoding); |
| 4379 // String is a cons string, check whether it is flat. |
| 4380 __ bind(&cons_string); |
| 4364 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 4381 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 4365 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); | 4382 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); |
| 4366 __ cmp(r0, r1); | 4383 __ cmp(r0, r1); |
| 4367 __ b(ne, &runtime); | 4384 __ b(ne, &runtime); |
| 4368 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 4385 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 4386 // Is first part of cons or parent of slice a flat string? |
| 4387 __ bind(&check_encoding); |
| 4369 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4388 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 4370 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 4389 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 4371 // Is first part a flat string? | |
| 4372 STATIC_ASSERT(kSeqStringTag == 0); | 4390 STATIC_ASSERT(kSeqStringTag == 0); |
| 4373 __ tst(r0, Operand(kStringRepresentationMask)); | 4391 __ tst(r0, Operand(kStringRepresentationMask)); |
| 4374 __ b(ne, &runtime); | 4392 __ b(ne, &runtime); |
| 4375 | |
| 4376 __ bind(&seq_string); | 4393 __ bind(&seq_string); |
| 4377 // subject: Subject string | 4394 // subject: Subject string |
| 4378 // regexp_data: RegExp data (FixedArray) | 4395 // regexp_data: RegExp data (FixedArray) |
| 4379 // r0: Instance type of subject string | 4396 // r0: Instance type of subject string |
| 4380 STATIC_ASSERT(4 == kAsciiStringTag); | 4397 STATIC_ASSERT(4 == kAsciiStringTag); |
| 4381 STATIC_ASSERT(kTwoByteStringTag == 0); | 4398 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 4382 // Find the code object based on the assumptions above. | 4399 // Find the code object based on the assumptions above. |
| 4383 __ and_(r0, r0, Operand(kStringEncodingMask)); | 4400 __ and_(r0, r0, Operand(kStringEncodingMask)); |
| 4384 __ mov(r3, Operand(r0, ASR, 2), SetCC); | 4401 __ mov(r3, Operand(r0, ASR, 2), SetCC); |
| 4385 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); | 4402 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4429 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); | 4446 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); |
| 4430 __ ldr(r2, MemOperand(r2, 0)); | 4447 __ ldr(r2, MemOperand(r2, 0)); |
| 4431 __ add(r0, r0, Operand(r2)); | 4448 __ add(r0, r0, Operand(r2)); |
| 4432 __ str(r0, MemOperand(sp, 2 * kPointerSize)); | 4449 __ str(r0, MemOperand(sp, 2 * kPointerSize)); |
| 4433 | 4450 |
| 4434 // Argument 5 (sp[4]): static offsets vector buffer. | 4451 // Argument 5 (sp[4]): static offsets vector buffer. |
| 4435 __ mov(r0, | 4452 __ mov(r0, |
| 4436 Operand(ExternalReference::address_of_static_offsets_vector(isolate))); | 4453 Operand(ExternalReference::address_of_static_offsets_vector(isolate))); |
| 4437 __ str(r0, MemOperand(sp, 1 * kPointerSize)); | 4454 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
| 4438 | 4455 |
| 4456 Label got_string_index, not_sliced; |
| 4439 // For arguments 4 and 3 get string length, calculate start of string data and | 4457 // 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). | 4458 // 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); | 4459 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
| 4444 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4460 __ add(r8, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 4445 __ eor(r3, r3, Operand(1)); | 4461 __ eor(r3, r3, Operand(1)); |
| 4446 // Argument 4 (r3): End of string data | 4462 // Load the length from the original subject string from the previous stack |
| 4447 // Argument 3 (r2): Start of string data | 4463 // frame. Therefore we have to use fp, which points exactly to two pointer |
| 4448 __ add(r2, r9, Operand(r1, LSL, r3)); | 4464 // sizes below the previous sp. (Because creating a new stack frame pushes |
| 4449 __ add(r3, r9, Operand(r0, LSL, r3)); | 4465 // the previous fp onto the stack and thereby moves up sp by 2*kPointerSize.) |
| 4466 __ ldr(r0, MemOperand(fp, kSubjectOffset + 2*kPointerSize)); |
| 4467 // If slice offset is not 0, load the length from the original sliced string. |
| 4468 // Argument 4, r3: End of string data |
| 4469 // Argument 3, r2: Start of string data |
| 4470 __ cmp(r9, Operand(kNotAStringSlice)); |
| 4471 __ b(eq, ¬_sliced); |
| 4472 // Prepare start and end index of the input. |
| 4473 __ add(r2, r8, Operand(r9, LSL, r3)); |
| 4474 __ add(r2, r2, Operand(r1, LSL, r3)); |
| 4475 |
| 4476 __ add(r8, r8, Operand(r9, LSL, r3)); |
| 4477 __ ldr(r9, FieldMemOperand(r0, String::kLengthOffset)); |
| 4478 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); |
| 4479 __ add(r3, r8, Operand(r9, LSL, r3)); |
| 4480 __ jmp(&got_string_index); |
| 4481 |
| 4482 __ bind(¬_sliced); |
| 4483 __ ldr(r9, FieldMemOperand(subject, String::kLengthOffset)); |
| 4484 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); |
| 4485 __ add(r2, r8, Operand(r1, LSL, r3)); |
| 4486 __ add(r3, r8, Operand(r9, LSL, r3)); |
| 4487 __ bind(&got_string_index); |
| 4450 | 4488 |
| 4451 // Argument 2 (r1): Previous index. | 4489 // Argument 2 (r1): Previous index. |
| 4452 // Already there | 4490 // Already there |
| 4453 | 4491 |
| 4454 // Argument 1 (r0): Subject string. | 4492 // Argument 1 (r0): Subject string. |
| 4455 __ mov(r0, subject); | 4493 // Already there |
| 4456 | 4494 |
| 4457 // Locate the code entry and call it. | 4495 // Locate the code entry and call it. |
| 4458 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4496 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 4459 DirectCEntryStub stub; | 4497 DirectCEntryStub stub; |
| 4460 stub.GenerateCall(masm, r7); | 4498 stub.GenerateCall(masm, r7); |
| 4461 | 4499 |
| 4462 __ LeaveExitFrame(false, no_reg); | 4500 __ LeaveExitFrame(false, no_reg); |
| 4463 | 4501 |
| 4464 // r0: result | 4502 // r0: result |
| 4465 // subject: subject string (callee saved) | 4503 // subject: subject string (callee saved) |
| 4466 // regexp_data: RegExp data (callee saved) | 4504 // regexp_data: RegExp data (callee saved) |
| 4467 // last_match_info_elements: Last match info elements (callee saved) | 4505 // last_match_info_elements: Last match info elements (callee saved) |
| 4468 | 4506 |
| 4469 // Check the result. | 4507 // Check the result. |
| 4470 Label success; | 4508 Label success; |
| 4471 | 4509 |
| 4472 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); | 4510 __ cmp(subject, Operand(NativeRegExpMacroAssembler::SUCCESS)); |
| 4473 __ b(eq, &success); | 4511 __ b(eq, &success); |
| 4474 Label failure; | 4512 Label failure; |
| 4475 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 4513 __ cmp(subject, Operand(NativeRegExpMacroAssembler::FAILURE)); |
| 4476 __ b(eq, &failure); | 4514 __ b(eq, &failure); |
| 4477 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 4515 __ cmp(subject, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
| 4478 // If not exception it can only be retry. Handle that in the runtime system. | 4516 // If not exception it can only be retry. Handle that in the runtime system. |
| 4479 __ b(ne, &runtime); | 4517 __ b(ne, &runtime); |
| 4480 // Result must now be exception. If there is no pending exception already a | 4518 // 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 | 4519 // 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. | 4520 // haven't created the exception yet. Handle that in the runtime system. |
| 4483 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 4521 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 4484 __ mov(r1, Operand(ExternalReference::the_hole_value_location(isolate))); | 4522 __ mov(r1, Operand(ExternalReference::the_hole_value_location(isolate))); |
| 4485 __ ldr(r1, MemOperand(r1, 0)); | 4523 __ ldr(r1, MemOperand(r1, 0)); |
| 4486 __ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address, | 4524 __ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address, |
| 4487 isolate))); | 4525 isolate))); |
| 4488 __ ldr(r0, MemOperand(r2, 0)); | 4526 __ ldr(r0, MemOperand(r2, 0)); |
| 4489 __ cmp(r0, r1); | 4527 __ cmp(subject, r1); |
| 4490 __ b(eq, &runtime); | 4528 __ b(eq, &runtime); |
| 4491 | 4529 |
| 4492 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. | 4530 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. |
| 4493 | 4531 |
| 4494 // Check if the exception is a termination. If so, throw as uncatchable. | 4532 // Check if the exception is a termination. If so, throw as uncatchable. |
| 4495 __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex); | 4533 __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex); |
| 4496 __ cmp(r0, ip); | 4534 __ cmp(subject, ip); |
| 4497 Label termination_exception; | 4535 Label termination_exception; |
| 4498 __ b(eq, &termination_exception); | 4536 __ b(eq, &termination_exception); |
| 4499 | 4537 |
| 4500 __ Throw(r0); // Expects thrown value in r0. | 4538 __ Throw(subject); // Expects thrown value in r0. |
| 4501 | 4539 |
| 4502 __ bind(&termination_exception); | 4540 __ bind(&termination_exception); |
| 4503 __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0. | 4541 __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0. |
| 4504 | 4542 |
| 4505 __ bind(&failure); | 4543 __ bind(&failure); |
| 4506 // For failure and exception return null. | 4544 // For failure and exception return null. |
| 4507 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); | 4545 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); |
| 4508 __ add(sp, sp, Operand(4 * kPointerSize)); | 4546 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 4509 __ Ret(); | 4547 __ Ret(); |
| 4510 | 4548 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4768 | IncludeNumberCompareField::encode(include_number_compare_) | 4806 | IncludeNumberCompareField::encode(include_number_compare_) |
| 4769 | IncludeSmiCompareField::encode(include_smi_compare_); | 4807 | IncludeSmiCompareField::encode(include_smi_compare_); |
| 4770 } | 4808 } |
| 4771 | 4809 |
| 4772 | 4810 |
| 4773 // StringCharCodeAtGenerator | 4811 // StringCharCodeAtGenerator |
| 4774 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 4812 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
| 4775 Label flat_string; | 4813 Label flat_string; |
| 4776 Label ascii_string; | 4814 Label ascii_string; |
| 4777 Label got_char_code; | 4815 Label got_char_code; |
| 4816 Label sliced_string; |
| 4778 | 4817 |
| 4779 // If the receiver is a smi trigger the non-string case. | 4818 // If the receiver is a smi trigger the non-string case. |
| 4780 __ JumpIfSmi(object_, receiver_not_string_); | 4819 __ JumpIfSmi(object_, receiver_not_string_); |
| 4781 | 4820 |
| 4782 // Fetch the instance type of the receiver into result register. | 4821 // Fetch the instance type of the receiver into result register. |
| 4783 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4822 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 4784 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4823 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
| 4785 // If the receiver is not a string trigger the non-string case. | 4824 // If the receiver is not a string trigger the non-string case. |
| 4786 __ tst(result_, Operand(kIsNotStringMask)); | 4825 __ tst(result_, Operand(kIsNotStringMask)); |
| 4787 __ b(ne, receiver_not_string_); | 4826 __ b(ne, receiver_not_string_); |
| 4788 | 4827 |
| 4789 // If the index is non-smi trigger the non-smi case. | 4828 // If the index is non-smi trigger the non-smi case. |
| 4790 __ JumpIfNotSmi(index_, &index_not_smi_); | 4829 __ JumpIfNotSmi(index_, &index_not_smi_); |
| 4791 | 4830 |
| 4792 // Put smi-tagged index into scratch register. | 4831 // Put smi-tagged index into scratch register. |
| 4793 __ mov(scratch_, index_); | 4832 __ mov(scratch_, index_); |
| 4794 __ bind(&got_smi_index_); | 4833 __ bind(&got_smi_index_); |
| 4795 | 4834 |
| 4796 // Check for index out of range. | 4835 // Check for index out of range. |
| 4797 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); | 4836 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); |
| 4798 __ cmp(ip, Operand(scratch_)); | 4837 __ cmp(ip, Operand(scratch_)); |
| 4799 __ b(ls, index_out_of_range_); | 4838 __ b(ls, index_out_of_range_); |
| 4800 | 4839 |
| 4801 // We need special handling for non-flat strings. | 4840 // We need special handling for non-flat strings. |
| 4802 STATIC_ASSERT(kSeqStringTag == 0); | 4841 STATIC_ASSERT(kSeqStringTag == 0); |
| 4803 __ tst(result_, Operand(kStringRepresentationMask)); | 4842 __ tst(result_, Operand(kStringRepresentationMask)); |
| 4804 __ b(eq, &flat_string); | 4843 __ b(eq, &flat_string); |
| 4805 | 4844 |
| 4806 // Handle non-flat strings. | 4845 // Handle non-flat strings. |
| 4807 __ tst(result_, Operand(kIsConsStringMask)); | 4846 __ and_(result_, result_, Operand(kStringRepresentationMask)); |
| 4847 __ cmp(result_, Operand(kSlicedStringTag)); |
| 4848 __ b(eq, &sliced_string); |
| 4849 __ cmp(result_, Operand(kExternalStringTag)); |
| 4808 __ b(eq, &call_runtime_); | 4850 __ b(eq, &call_runtime_); |
| 4809 | 4851 |
| 4810 // ConsString. | 4852 // ConsString. |
| 4811 // Check whether the right hand side is the empty string (i.e. if | 4853 // 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 | 4854 // 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 | 4855 // the case we would rather go to the runtime system now to flatten |
| 4814 // the string. | 4856 // the string. |
| 4815 __ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); | 4857 __ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); |
| 4816 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); | 4858 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); |
| 4817 __ cmp(result_, Operand(ip)); | 4859 __ cmp(result_, Operand(ip)); |
| 4818 __ b(ne, &call_runtime_); | 4860 __ b(ne, &call_runtime_); |
| 4819 // Get the first of the two strings and load its instance type. | 4861 // Get the first of the two strings and load its instance type. |
| 4820 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); | 4862 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); |
| 4821 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4863 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 4822 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4864 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
| 4823 // If the first cons component is also non-flat, then go to runtime. | 4865 // If the first cons component is also non-flat, then go to runtime. |
| 4824 STATIC_ASSERT(kSeqStringTag == 0); | 4866 STATIC_ASSERT(kSeqStringTag == 0); |
| 4825 __ tst(result_, Operand(kStringRepresentationMask)); | 4867 __ tst(result_, Operand(kStringRepresentationMask)); |
| 4826 __ b(ne, &call_runtime_); | 4868 __ b(ne, &call_runtime_); |
| 4869 __ jmp(&flat_string); |
| 4870 |
| 4871 // SlicedString, unpack and add offset. |
| 4872 __ bind(&sliced_string); |
| 4873 __ ldr(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset)); |
| 4874 __ add(scratch_, scratch_, result_); |
| 4875 __ ldr(object_, FieldMemOperand(object_, SlicedString::kParentOffset)); |
| 4876 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 4877 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
| 4827 | 4878 |
| 4828 // Check for 1-byte or 2-byte string. | 4879 // Check for 1-byte or 2-byte string. |
| 4829 __ bind(&flat_string); | 4880 __ bind(&flat_string); |
| 4830 STATIC_ASSERT(kAsciiStringTag != 0); | 4881 STATIC_ASSERT(kAsciiStringTag != 0); |
| 4831 __ tst(result_, Operand(kStringEncodingMask)); | 4882 __ tst(result_, Operand(kStringEncodingMask)); |
| 4832 __ b(ne, &ascii_string); | 4883 __ b(ne, &ascii_string); |
| 4833 | 4884 |
| 4834 // 2-byte string. | 4885 // 2-byte string. |
| 4835 // Load the 2-byte character code into the result register. We can | 4886 // Load the 2-byte character code into the result register. We can |
| 4836 // add without shifting since the smi tag size is the log2 of the | 4887 // add without shifting since the smi tag size is the log2 of the |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5393 // 0 <= from <= to <= string.length. | 5444 // 0 <= from <= to <= string.length. |
| 5394 // If any of these assumptions fail, we call the runtime system. | 5445 // If any of these assumptions fail, we call the runtime system. |
| 5395 | 5446 |
| 5396 static const int kToOffset = 0 * kPointerSize; | 5447 static const int kToOffset = 0 * kPointerSize; |
| 5397 static const int kFromOffset = 1 * kPointerSize; | 5448 static const int kFromOffset = 1 * kPointerSize; |
| 5398 static const int kStringOffset = 2 * kPointerSize; | 5449 static const int kStringOffset = 2 * kPointerSize; |
| 5399 | 5450 |
| 5400 // Check bounds and smi-ness. | 5451 // Check bounds and smi-ness. |
| 5401 Register to = r6; | 5452 Register to = r6; |
| 5402 Register from = r7; | 5453 Register from = r7; |
| 5454 |
| 5455 if (FLAG_string_slices) { |
| 5456 __ nop(0); // Jumping as first instruction would crash the code generation. |
| 5457 __ jmp(&runtime); |
| 5458 } |
| 5459 |
| 5403 __ Ldrd(to, from, MemOperand(sp, kToOffset)); | 5460 __ Ldrd(to, from, MemOperand(sp, kToOffset)); |
| 5404 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5461 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
| 5405 STATIC_ASSERT(kSmiTag == 0); | 5462 STATIC_ASSERT(kSmiTag == 0); |
| 5406 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5463 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 5464 |
| 5407 // I.e., arithmetic shift right by one un-smi-tags. | 5465 // I.e., arithmetic shift right by one un-smi-tags. |
| 5408 __ mov(r2, Operand(to, ASR, 1), SetCC); | 5466 __ mov(r2, Operand(to, ASR, 1), SetCC); |
| 5409 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); | 5467 __ 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. | 5468 // 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. | 5469 __ b(cs, &runtime); // Either "from" or "to" is not a smi. |
| 5412 __ b(mi, &runtime); // From is negative. | 5470 __ b(mi, &runtime); // From is negative. |
| 5413 | 5471 |
| 5414 // Both to and from are smis. | 5472 // Both to and from are smis. |
| 5415 | |
| 5416 __ sub(r2, r2, Operand(r3), SetCC); | 5473 __ sub(r2, r2, Operand(r3), SetCC); |
| 5417 __ b(mi, &runtime); // Fail if from > to. | 5474 __ b(mi, &runtime); // Fail if from > to. |
| 5418 // Special handling of sub-strings of length 1 and 2. One character strings | 5475 // 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 | 5476 // are handled in the runtime system (looked up in the single character |
| 5420 // cache). Two character strings are looked for in the symbol cache. | 5477 // cache). Two character strings are looked for in the symbol cache. |
| 5421 __ cmp(r2, Operand(2)); | 5478 __ cmp(r2, Operand(2)); |
| 5422 __ b(lt, &runtime); | 5479 __ b(lt, &runtime); |
| 5423 | 5480 |
| 5424 // r2: length | 5481 // r2: length |
| 5425 // r3: from index (untaged smi) | 5482 // r3: from index (untaged smi) |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5911 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5968 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 5912 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5969 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 5913 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5970 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 5914 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5971 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 5915 } | 5972 } |
| 5916 // Check that both strings are sequential. | 5973 // Check that both strings are sequential. |
| 5917 STATIC_ASSERT(kSeqStringTag == 0); | 5974 STATIC_ASSERT(kSeqStringTag == 0); |
| 5918 __ tst(r4, Operand(kStringRepresentationMask)); | 5975 __ tst(r4, Operand(kStringRepresentationMask)); |
| 5919 __ tst(r5, Operand(kStringRepresentationMask), eq); | 5976 __ tst(r5, Operand(kStringRepresentationMask), eq); |
| 5920 __ b(ne, &string_add_runtime); | 5977 __ b(ne, &string_add_runtime); |
| 5978 // We cannot encounter sliced strings here since: |
| 5979 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); |
| 5921 // Now check if both strings have the same encoding (ASCII/Two-byte). | 5980 // Now check if both strings have the same encoding (ASCII/Two-byte). |
| 5922 // r0: first string. | 5981 // r0: first string. |
| 5923 // r1: second string. | 5982 // r1: second string. |
| 5924 // r2: length of first string. | 5983 // r2: length of first string. |
| 5925 // r3: length of second string. | 5984 // r3: length of second string. |
| 5926 // r6: sum of lengths.. | 5985 // r6: sum of lengths.. |
| 5927 Label non_ascii_string_add_flat_result; | 5986 Label non_ascii_string_add_flat_result; |
| 5928 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. | 5987 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. |
| 5929 __ eor(r7, r4, Operand(r5)); | 5988 __ eor(r7, r4, Operand(r5)); |
| 5930 __ tst(r7, Operand(kStringEncodingMask)); | 5989 __ tst(r7, Operand(kStringEncodingMask)); |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6535 __ mov(result, Operand(0)); | 6594 __ mov(result, Operand(0)); |
| 6536 __ Ret(); | 6595 __ Ret(); |
| 6537 } | 6596 } |
| 6538 | 6597 |
| 6539 | 6598 |
| 6540 #undef __ | 6599 #undef __ |
| 6541 | 6600 |
| 6542 } } // namespace v8::internal | 6601 } } // namespace v8::internal |
| 6543 | 6602 |
| 6544 #endif // V8_TARGET_ARCH_ARM | 6603 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |