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

Side by Side Diff: src/arm/code-stubs-arm.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: Patched RegExp for string slices. 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
« no previous file with comments | « no previous file | src/arm/lithium-arm.cc » ('j') | src/arm/lithium-arm.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4328 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 // subject: Subject string 4342 // subject: Subject string
4343 // regexp_data: RegExp data (FixedArray) 4343 // regexp_data: RegExp data (FixedArray)
4344 // Check the representation and encoding of the subject string. 4344 // Check the representation and encoding of the subject string.
4345 Label seq_string; 4345 Label seq_string;
4346 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 4346 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
4347 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 4347 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
4348 // First check for flat string. 4348 // First check for flat string.
4349 __ tst(r0, Operand(kIsNotStringMask | kStringRepresentationMask)); 4349 __ and_(r1, r0, Operand(kIsNotStringMask | kStringRepresentationMask), SetCC);
4350 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 4350 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
4351 __ b(eq, &seq_string); 4351 __ b(eq, &seq_string);
4352 4352
4353 // subject: Subject string 4353 // subject: Subject string
4354 // regexp_data: RegExp data (FixedArray) 4354 // regexp_data: RegExp data (FixedArray)
4355 // Check for flat cons string. 4355 // Check for flat cons string or truncated sliced string.
4356 // A flat cons string is a cons string where the second part is the empty 4356 // 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 4357 // 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 4358 // string. Also in this case the first part of the cons string is known to be
4359 // a sequential string or an external string. 4359 // a sequential string or an external string.
4360 STATIC_ASSERT(kExternalStringTag !=0); 4360 // A truncated sliced string has the offset 0 and the same length as the
4361 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); 4361 // parent string.
4362 __ tst(r0, Operand(kIsNotStringMask | kExternalStringTag)); 4362 Label cons_string, encoding;
4363 __ cmp(r1, Operand(kConsStringTag));
4364 __ b(eq, &cons_string);
4365 __ cmp(r1, Operand(kSlicedStringTag));
4366 // If subject is not a sliced string, it can only be a non-string or an
4367 // external string.
4363 __ b(ne, &runtime); 4368 __ b(ne, &runtime);
4369 // String is sliced, check whether it is truncated.
4370 __ ldr(r0, FieldMemOperand(subject, SlicedString::kLengthOffset));
4371 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
4372 __ ldr(r1, FieldMemOperand(subject, String::kLengthOffset));
4373 __ cmp(r0, r1);
4374 __ b(ne, &runtime);
4375 __ jmp(&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(&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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
4768 | IncludeNumberCompareField::encode(include_number_compare_) 4782 | IncludeNumberCompareField::encode(include_number_compare_)
4769 | IncludeSmiCompareField::encode(include_smi_compare_); 4783 | IncludeSmiCompareField::encode(include_smi_compare_);
4770 } 4784 }
4771 4785
4772 4786
4773 // StringCharCodeAtGenerator 4787 // StringCharCodeAtGenerator
4774 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 4788 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
4775 Label flat_string; 4789 Label flat_string;
4776 Label ascii_string; 4790 Label ascii_string;
4777 Label got_char_code; 4791 Label got_char_code;
4792 Label sliced_string;
4778 4793
4779 // If the receiver is a smi trigger the non-string case. 4794 // If the receiver is a smi trigger the non-string case.
4780 __ JumpIfSmi(object_, receiver_not_string_); 4795 __ JumpIfSmi(object_, receiver_not_string_);
4781 4796
4782 // Fetch the instance type of the receiver into result register. 4797 // Fetch the instance type of the receiver into result register.
4783 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 4798 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
4784 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 4799 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
4785 // If the receiver is not a string trigger the non-string case. 4800 // If the receiver is not a string trigger the non-string case.
4786 __ tst(result_, Operand(kIsNotStringMask)); 4801 __ tst(result_, Operand(kIsNotStringMask));
4787 __ b(ne, receiver_not_string_); 4802 __ b(ne, receiver_not_string_);
4788 4803
4789 // If the index is non-smi trigger the non-smi case. 4804 // If the index is non-smi trigger the non-smi case.
4790 __ JumpIfNotSmi(index_, &index_not_smi_); 4805 __ JumpIfNotSmi(index_, &index_not_smi_);
4791 4806
4792 // Put smi-tagged index into scratch register. 4807 // Put smi-tagged index into scratch register.
4793 __ mov(scratch_, index_); 4808 __ mov(scratch_, index_);
4794 __ bind(&got_smi_index_); 4809 __ bind(&got_smi_index_);
4795 4810
4796 // Check for index out of range. 4811 // Check for index out of range.
4797 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); 4812 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset));
4798 __ cmp(ip, Operand(scratch_)); 4813 __ cmp(ip, Operand(scratch_));
4799 __ b(ls, index_out_of_range_); 4814 __ b(ls, index_out_of_range_);
4800 4815
4801 // We need special handling for non-flat strings. 4816 // We need special handling for non-flat strings.
4802 STATIC_ASSERT(kSeqStringTag == 0); 4817 STATIC_ASSERT(kSeqStringTag == 0);
4803 __ tst(result_, Operand(kStringRepresentationMask)); 4818 __ tst(result_, Operand(kStringRepresentationMask));
4804 __ b(eq, &flat_string); 4819 __ b(eq, &flat_string);
4805 4820
4806 // Handle non-flat strings. 4821 // Handle non-flat strings.
4807 __ tst(result_, Operand(kIsConsStringMask)); 4822 __ and_(result_, result_, Operand(kStringRepresentationMask));
4823 __ cmp(result_, Operand(kSlicedStringTag));
4824 __ b(eq, &sliced_string);
4825 __ cmp(result_, Operand(kExternalStringTag));
4808 __ b(eq, &call_runtime_); 4826 __ b(eq, &call_runtime_);
4809 4827
4810 // ConsString. 4828 // ConsString.
4811 // Check whether the right hand side is the empty string (i.e. if 4829 // 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 4830 // 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 4831 // the case we would rather go to the runtime system now to flatten
4814 // the string. 4832 // the string.
4815 __ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); 4833 __ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset));
4816 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); 4834 __ LoadRoot(ip, Heap::kEmptyStringRootIndex);
4817 __ cmp(result_, Operand(ip)); 4835 __ cmp(result_, Operand(ip));
4818 __ b(ne, &call_runtime_); 4836 __ b(ne, &call_runtime_);
4819 // Get the first of the two strings and load its instance type. 4837 // Get the first of the two strings and load its instance type.
4820 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); 4838 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset));
4821 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 4839 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
4822 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 4840 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
4823 // If the first cons component is also non-flat, then go to runtime. 4841 // If the first cons component is also non-flat, then go to runtime.
4824 STATIC_ASSERT(kSeqStringTag == 0); 4842 STATIC_ASSERT(kSeqStringTag == 0);
4825 __ tst(result_, Operand(kStringRepresentationMask)); 4843 __ tst(result_, Operand(kStringRepresentationMask));
4826 __ b(ne, &call_runtime_); 4844 __ b(ne, &call_runtime_);
4845 __ jmp(&flat_string);
4846
4847 // SlicedString, unpack and add offset.
4848 __ bind(&sliced_string);
4849 __ ldr(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset));
4850 __ add(scratch_, scratch_, result_);
4851 __ ldr(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
4852 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
4853 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
4827 4854
4828 // Check for 1-byte or 2-byte string. 4855 // Check for 1-byte or 2-byte string.
4829 __ bind(&flat_string); 4856 __ bind(&flat_string);
4830 STATIC_ASSERT(kAsciiStringTag != 0); 4857 STATIC_ASSERT(kAsciiStringTag != 0);
4831 __ tst(result_, Operand(kStringEncodingMask)); 4858 __ tst(result_, Operand(kStringEncodingMask));
4832 __ b(ne, &ascii_string); 4859 __ b(ne, &ascii_string);
4833 4860
4834 // 2-byte string. 4861 // 2-byte string.
4835 // Load the 2-byte character code into the result register. We can 4862 // 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 4863 // 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
5393 // 0 <= from <= to <= string.length. 5420 // 0 <= from <= to <= string.length.
5394 // If any of these assumptions fail, we call the runtime system. 5421 // If any of these assumptions fail, we call the runtime system.
5395 5422
5396 static const int kToOffset = 0 * kPointerSize; 5423 static const int kToOffset = 0 * kPointerSize;
5397 static const int kFromOffset = 1 * kPointerSize; 5424 static const int kFromOffset = 1 * kPointerSize;
5398 static const int kStringOffset = 2 * kPointerSize; 5425 static const int kStringOffset = 2 * kPointerSize;
5399 5426
5400 // Check bounds and smi-ness. 5427 // Check bounds and smi-ness.
5401 Register to = r6; 5428 Register to = r6;
5402 Register from = r7; 5429 Register from = r7;
5430
5431 __ nop(0); // Jumping as first instruction would crash the code generation.
antonm 2011/08/04 12:18:48 nit: shouldn't nop go under if as well?
5432 if (FLAG_string_slices) {
5433 __ jmp(&runtime);
5434 }
5435
5403 __ Ldrd(to, from, MemOperand(sp, kToOffset)); 5436 __ Ldrd(to, from, MemOperand(sp, kToOffset));
5404 STATIC_ASSERT(kFromOffset == kToOffset + 4); 5437 STATIC_ASSERT(kFromOffset == kToOffset + 4);
5405 STATIC_ASSERT(kSmiTag == 0); 5438 STATIC_ASSERT(kSmiTag == 0);
5406 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 5439 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
5440
5407 // I.e., arithmetic shift right by one un-smi-tags. 5441 // I.e., arithmetic shift right by one un-smi-tags.
5408 __ mov(r2, Operand(to, ASR, 1), SetCC); 5442 __ mov(r2, Operand(to, ASR, 1), SetCC);
5409 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); 5443 __ 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. 5444 // 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. 5445 __ b(cs, &runtime); // Either "from" or "to" is not a smi.
5412 __ b(mi, &runtime); // From is negative. 5446 __ b(mi, &runtime); // From is negative.
5413 5447
5414 // Both to and from are smis. 5448 // Both to and from are smis.
5415
5416 __ sub(r2, r2, Operand(r3), SetCC); 5449 __ sub(r2, r2, Operand(r3), SetCC);
5417 __ b(mi, &runtime); // Fail if from > to. 5450 __ b(mi, &runtime); // Fail if from > to.
5418 // Special handling of sub-strings of length 1 and 2. One character strings 5451 // 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 5452 // are handled in the runtime system (looked up in the single character
5420 // cache). Two character strings are looked for in the symbol cache. 5453 // cache). Two character strings are looked for in the symbol cache.
5421 __ cmp(r2, Operand(2)); 5454 __ cmp(r2, Operand(2));
5422 __ b(lt, &runtime); 5455 __ b(lt, &runtime);
5423 5456
5424 // r2: length 5457 // r2: length
5425 // r3: from index (untaged smi) 5458 // r3: from index (untaged smi)
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
5911 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5944 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5912 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5945 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5913 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5946 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5914 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5947 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5915 } 5948 }
5916 // Check that both strings are sequential. 5949 // Check that both strings are sequential.
5917 STATIC_ASSERT(kSeqStringTag == 0); 5950 STATIC_ASSERT(kSeqStringTag == 0);
5918 __ tst(r4, Operand(kStringRepresentationMask)); 5951 __ tst(r4, Operand(kStringRepresentationMask));
5919 __ tst(r5, Operand(kStringRepresentationMask), eq); 5952 __ tst(r5, Operand(kStringRepresentationMask), eq);
5920 __ b(ne, &string_add_runtime); 5953 __ b(ne, &string_add_runtime);
5954 // We cannot encounter sliced strings here since:
5955 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
5921 // Now check if both strings have the same encoding (ASCII/Two-byte). 5956 // Now check if both strings have the same encoding (ASCII/Two-byte).
5922 // r0: first string. 5957 // r0: first string.
5923 // r1: second string. 5958 // r1: second string.
5924 // r2: length of first string. 5959 // r2: length of first string.
5925 // r3: length of second string. 5960 // r3: length of second string.
5926 // r6: sum of lengths.. 5961 // r6: sum of lengths..
5927 Label non_ascii_string_add_flat_result; 5962 Label non_ascii_string_add_flat_result;
5928 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. 5963 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test.
5929 __ eor(r7, r4, Operand(r5)); 5964 __ eor(r7, r4, Operand(r5));
5930 __ tst(r7, Operand(kStringEncodingMask)); 5965 __ tst(r7, Operand(kStringEncodingMask));
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after
6535 __ mov(result, Operand(0)); 6570 __ mov(result, Operand(0));
6536 __ Ret(); 6571 __ Ret();
6537 } 6572 }
6538 6573
6539 6574
6540 #undef __ 6575 #undef __
6541 6576
6542 } } // namespace v8::internal 6577 } } // namespace v8::internal
6543 6578
6544 #endif // V8_TARGET_ARCH_ARM 6579 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/lithium-arm.cc » ('j') | src/arm/lithium-arm.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698