OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 4126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4137 // both "from" and "to" are smis, and | 4137 // both "from" and "to" are smis, and |
4138 // 0 <= from <= to <= string.length. | 4138 // 0 <= from <= to <= string.length. |
4139 // If any of these assumptions fail, we call the runtime system. | 4139 // If any of these assumptions fail, we call the runtime system. |
4140 | 4140 |
4141 static const int kToOffset = 0 * kPointerSize; | 4141 static const int kToOffset = 0 * kPointerSize; |
4142 static const int kFromOffset = 1 * kPointerSize; | 4142 static const int kFromOffset = 1 * kPointerSize; |
4143 static const int kStringOffset = 2 * kPointerSize; | 4143 static const int kStringOffset = 2 * kPointerSize; |
4144 | 4144 |
4145 | 4145 |
4146 // Check bounds and smi-ness. | 4146 // Check bounds and smi-ness. |
4147 __ ldr(r7, MemOperand(sp, kToOffset)); | 4147 // Both to and from are smis. |
Erik Corry
2010/09/15 10:23:53
We don't know that yet, so I moved this comment do
| |
4148 __ ldr(r6, MemOperand(sp, kFromOffset)); | 4148 Register to = r6; |
4149 Register from = r7; | |
4150 __ Ldrd(to, from, MemOperand(sp, kToOffset)); | |
4151 STATIC_ASSERT(kFromOffset == kToOffset + 4); | |
4149 STATIC_ASSERT(kSmiTag == 0); | 4152 STATIC_ASSERT(kSmiTag == 0); |
4150 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 4153 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
4151 // I.e., arithmetic shift right by one un-smi-tags. | 4154 // I.e., arithmetic shift right by one un-smi-tags. |
4152 __ mov(r2, Operand(r7, ASR, 1), SetCC); | 4155 __ mov(r2, Operand(to, ASR, 1), SetCC); |
4153 __ mov(r3, Operand(r6, ASR, 1), SetCC, cc); | 4156 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); |
4154 // If either r2 or r6 had the smi tag bit set, then carry is set now. | 4157 // If either to or from had the smi tag bit set, then carry is set now. |
4155 __ b(cs, &runtime); // Either "from" or "to" is not a smi. | 4158 __ b(cs, &runtime); // Either "from" or "to" is not a smi. |
4156 __ b(mi, &runtime); // From is negative. | 4159 __ b(mi, &runtime); // From is negative. |
4157 | 4160 |
4158 __ sub(r2, r2, Operand(r3), SetCC); | 4161 __ sub(r2, r2, Operand(r3), SetCC); |
4159 __ b(mi, &runtime); // Fail if from > to. | 4162 __ b(mi, &runtime); // Fail if from > to. |
4160 // Special handling of sub-strings of length 1 and 2. One character strings | 4163 // Special handling of sub-strings of length 1 and 2. One character strings |
4161 // are handled in the runtime system (looked up in the single character | 4164 // are handled in the runtime system (looked up in the single character |
4162 // cache). Two character strings are looked for in the symbol cache. | 4165 // cache). Two character strings are looked for in the symbol cache. |
4163 __ cmp(r2, Operand(2)); | 4166 __ cmp(r2, Operand(2)); |
4164 __ b(lt, &runtime); | 4167 __ b(lt, &runtime); |
4165 | 4168 |
4166 // r2: length | 4169 // r2: length |
4167 // r3: from index (untaged smi) | 4170 // r3: from index (untaged smi) |
4168 // r6: from (smi) | |
4169 // r7: to (smi) | |
Erik Corry
2010/09/15 10:23:53
I put these comments back.
| |
4170 | 4171 |
4171 // Make sure first argument is a sequential (or flat) string. | 4172 // Make sure first argument is a sequential (or flat) string. |
4172 __ ldr(r5, MemOperand(sp, kStringOffset)); | 4173 __ ldr(r5, MemOperand(sp, kStringOffset)); |
4173 STATIC_ASSERT(kSmiTag == 0); | 4174 STATIC_ASSERT(kSmiTag == 0); |
4174 __ tst(r5, Operand(kSmiTagMask)); | 4175 __ tst(r5, Operand(kSmiTagMask)); |
4175 __ b(eq, &runtime); | 4176 __ b(eq, &runtime); |
4176 Condition is_string = masm->IsObjectStringType(r5, r1); | 4177 Condition is_string = masm->IsObjectStringType(r5, r1); |
4177 __ b(NegateCondition(is_string), &runtime); | 4178 __ b(NegateCondition(is_string), &runtime); |
4178 | 4179 |
4179 // r1: instance type | 4180 // r1: instance type |
4180 // r2: length | 4181 // r2: length |
4181 // r3: from index (untaged smi) | 4182 // r3: from index (untaged smi) |
4182 // r5: string | 4183 // r5: string |
4183 // r6: from (smi) | |
Erik Corry
2010/09/15 10:23:53
And these
| |
4184 // r7: to (smi) | |
4185 Label seq_string; | 4184 Label seq_string; |
4186 __ and_(r4, r1, Operand(kStringRepresentationMask)); | 4185 __ and_(r4, r1, Operand(kStringRepresentationMask)); |
4187 STATIC_ASSERT(kSeqStringTag < kConsStringTag); | 4186 STATIC_ASSERT(kSeqStringTag < kConsStringTag); |
4188 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 4187 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
4189 __ cmp(r4, Operand(kConsStringTag)); | 4188 __ cmp(r4, Operand(kConsStringTag)); |
4190 __ b(gt, &runtime); // External strings go to runtime. | 4189 __ b(gt, &runtime); // External strings go to runtime. |
4191 __ b(lt, &seq_string); // Sequential strings are handled directly. | 4190 __ b(lt, &seq_string); // Sequential strings are handled directly. |
4192 | 4191 |
4193 // Cons string. Try to recurse (once) on the first substring. | 4192 // Cons string. Try to recurse (once) on the first substring. |
4194 // (This adds a little more generality than necessary to handle flattened | 4193 // (This adds a little more generality than necessary to handle flattened |
4195 // cons strings, but not much). | 4194 // cons strings, but not much). |
4196 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset)); | 4195 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset)); |
4197 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); | 4196 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); |
4198 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 4197 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
4199 __ tst(r1, Operand(kStringRepresentationMask)); | 4198 __ tst(r1, Operand(kStringRepresentationMask)); |
4200 STATIC_ASSERT(kSeqStringTag == 0); | 4199 STATIC_ASSERT(kSeqStringTag == 0); |
4201 __ b(ne, &runtime); // Cons and External strings go to runtime. | 4200 __ b(ne, &runtime); // Cons and External strings go to runtime. |
4202 | 4201 |
4203 // Definitly a sequential string. | 4202 // Definitly a sequential string. |
4204 __ bind(&seq_string); | 4203 __ bind(&seq_string); |
4205 | 4204 |
4206 // r1: instance type. | 4205 // r1: instance type. |
4207 // r2: length | 4206 // r2: length |
4208 // r3: from index (untaged smi) | 4207 // r3: from index (untaged smi) |
4209 // r5: string | 4208 // r5: string |
4210 // r6: from (smi) | 4209 // r6 (a.k.a. to): to (smi) |
4211 // r7: to (smi) | |
Erik Corry
2010/09/15 10:23:53
And I put 'to' back here.
| |
4212 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); | 4210 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); |
4213 __ cmp(r4, Operand(r7)); | 4211 __ cmp(r4, Operand(to)); |
4214 __ b(lt, &runtime); // Fail if to > length. | 4212 __ b(lt, &runtime); // Fail if to > length. |
4215 | 4213 |
4216 // r1: instance type. | 4214 // r1: instance type. |
4217 // r2: result string length. | 4215 // r2: result string length. |
4218 // r3: from index (untaged smi) | 4216 // r3: from index (untaged smi) |
4219 // r5: string. | 4217 // r5: string. |
4220 // r6: from offset (smi) | |
Erik Corry
2010/09/15 10:23:53
We use 'from' below so it is still live here, so I
| |
4221 // Check for flat ascii string. | 4218 // Check for flat ascii string. |
4222 Label non_ascii_flat; | 4219 Label non_ascii_flat; |
4223 __ tst(r1, Operand(kStringEncodingMask)); | 4220 __ tst(r1, Operand(kStringEncodingMask)); |
4224 STATIC_ASSERT(kTwoByteStringTag == 0); | 4221 STATIC_ASSERT(kTwoByteStringTag == 0); |
4225 __ b(eq, &non_ascii_flat); | 4222 __ b(eq, &non_ascii_flat); |
4226 | 4223 |
4227 Label result_longer_than_two; | 4224 Label result_longer_than_two; |
4228 __ cmp(r2, Operand(2)); | 4225 __ cmp(r2, Operand(2)); |
4229 __ b(gt, &result_longer_than_two); | 4226 __ b(gt, &result_longer_than_two); |
4230 | 4227 |
(...skipping 21 matching lines...) Expand all Loading... | |
4252 __ Ret(); | 4249 __ Ret(); |
4253 | 4250 |
4254 __ bind(&result_longer_than_two); | 4251 __ bind(&result_longer_than_two); |
4255 | 4252 |
4256 // Allocate the result. | 4253 // Allocate the result. |
4257 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); | 4254 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); |
4258 | 4255 |
4259 // r0: result string. | 4256 // r0: result string. |
4260 // r2: result string length. | 4257 // r2: result string length. |
4261 // r5: string. | 4258 // r5: string. |
4262 // r6: from offset (smi) | 4259 // r7 (a.k.a. from): from offset (smi) |
4263 // Locate first character of result. | 4260 // Locate first character of result. |
4264 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4261 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
4265 // Locate 'from' character of string. | 4262 // Locate 'from' character of string. |
4266 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4263 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
4267 __ add(r5, r5, Operand(r6, ASR, 1)); | 4264 __ add(r5, r5, Operand(from, ASR, 1)); |
4268 | 4265 |
4269 // r0: result string. | 4266 // r0: result string. |
4270 // r1: first character of result string. | 4267 // r1: first character of result string. |
4271 // r2: result string length. | 4268 // r2: result string length. |
4272 // r5: first character of sub string to copy. | 4269 // r5: first character of sub string to copy. |
4273 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); | 4270 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); |
4274 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, | 4271 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, |
4275 COPY_ASCII | DEST_ALWAYS_ALIGNED); | 4272 COPY_ASCII | DEST_ALWAYS_ALIGNED); |
4276 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); | 4273 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); |
4277 __ add(sp, sp, Operand(3 * kPointerSize)); | 4274 __ add(sp, sp, Operand(3 * kPointerSize)); |
4278 __ Ret(); | 4275 __ Ret(); |
4279 | 4276 |
4280 __ bind(&non_ascii_flat); | 4277 __ bind(&non_ascii_flat); |
4281 // r2: result string length. | 4278 // r2: result string length. |
4282 // r5: string. | 4279 // r5: string. |
4283 // r6: from offset (smi) | 4280 // r7 (a.k.a. from): from offset (smi) |
4284 // Check for flat two byte string. | 4281 // Check for flat two byte string. |
4285 | 4282 |
4286 // Allocate the result. | 4283 // Allocate the result. |
4287 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime); | 4284 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime); |
4288 | 4285 |
4289 // r0: result string. | 4286 // r0: result string. |
4290 // r2: result string length. | 4287 // r2: result string length. |
4291 // r5: string. | 4288 // r5: string. |
4292 // Locate first character of result. | 4289 // Locate first character of result. |
4293 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4290 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
4294 // Locate 'from' character of string. | 4291 // Locate 'from' character of string. |
4295 __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4292 __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
4296 // As "from" is a smi it is 2 times the value which matches the size of a two | 4293 // As "from" is a smi it is 2 times the value which matches the size of a two |
4297 // byte character. | 4294 // byte character. |
4298 __ add(r5, r5, Operand(r6)); | 4295 __ add(r5, r5, Operand(from)); |
4299 | 4296 |
4300 // r0: result string. | 4297 // r0: result string. |
4301 // r1: first character of result. | 4298 // r1: first character of result. |
4302 // r2: result length. | 4299 // r2: result length. |
4303 // r5: first character of string to copy. | 4300 // r5: first character of string to copy. |
4304 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 4301 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
4305 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, | 4302 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, |
4306 DEST_ALWAYS_ALIGNED); | 4303 r9, DEST_ALWAYS_ALIGNED); |
4307 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); | 4304 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); |
4308 __ add(sp, sp, Operand(3 * kPointerSize)); | 4305 __ add(sp, sp, Operand(3 * kPointerSize)); |
4309 __ Ret(); | 4306 __ Ret(); |
4310 | 4307 |
4311 // Just jump to runtime to create the sub string. | 4308 // Just jump to runtime to create the sub string. |
4312 __ bind(&runtime); | 4309 __ bind(&runtime); |
4313 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 4310 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
4314 } | 4311 } |
4315 | 4312 |
4316 | 4313 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4372 __ Ret(); | 4369 __ Ret(); |
4373 } | 4370 } |
4374 | 4371 |
4375 | 4372 |
4376 void StringCompareStub::Generate(MacroAssembler* masm) { | 4373 void StringCompareStub::Generate(MacroAssembler* masm) { |
4377 Label runtime; | 4374 Label runtime; |
4378 | 4375 |
4379 // Stack frame on entry. | 4376 // Stack frame on entry. |
4380 // sp[0]: right string | 4377 // sp[0]: right string |
4381 // sp[4]: left string | 4378 // sp[4]: left string |
4382 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // left | 4379 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1. |
4383 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // right | |
4384 | 4380 |
4385 Label not_same; | 4381 Label not_same; |
4386 __ cmp(r0, r1); | 4382 __ cmp(r0, r1); |
4387 __ b(ne, ¬_same); | 4383 __ b(ne, ¬_same); |
4388 STATIC_ASSERT(EQUAL == 0); | 4384 STATIC_ASSERT(EQUAL == 0); |
4389 STATIC_ASSERT(kSmiTag == 0); | 4385 STATIC_ASSERT(kSmiTag == 0); |
4390 __ mov(r0, Operand(Smi::FromInt(EQUAL))); | 4386 __ mov(r0, Operand(Smi::FromInt(EQUAL))); |
4391 __ IncrementCounter(&Counters::string_compare_native, 1, r1, r2); | 4387 __ IncrementCounter(&Counters::string_compare_native, 1, r1, r2); |
4392 __ add(sp, sp, Operand(2 * kPointerSize)); | 4388 __ add(sp, sp, Operand(2 * kPointerSize)); |
4393 __ Ret(); | 4389 __ Ret(); |
4394 | 4390 |
4395 __ bind(¬_same); | 4391 __ bind(¬_same); |
4396 | 4392 |
4397 // Check that both objects are sequential ascii strings. | 4393 // Check that both objects are sequential ascii strings. |
4398 __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime); | 4394 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); |
4399 | 4395 |
4400 // Compare flat ascii strings natively. Remove arguments from stack first. | 4396 // Compare flat ascii strings natively. Remove arguments from stack first. |
4401 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3); | 4397 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3); |
4402 __ add(sp, sp, Operand(2 * kPointerSize)); | 4398 __ add(sp, sp, Operand(2 * kPointerSize)); |
4403 GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5); | 4399 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); |
4404 | 4400 |
4405 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 4401 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
4406 // tagged as a small integer. | 4402 // tagged as a small integer. |
4407 __ bind(&runtime); | 4403 __ bind(&runtime); |
4408 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4404 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
4409 } | 4405 } |
4410 | 4406 |
4411 | 4407 |
4412 void StringAddStub::Generate(MacroAssembler* masm) { | 4408 void StringAddStub::Generate(MacroAssembler* masm) { |
4413 Label string_add_runtime; | 4409 Label string_add_runtime; |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4679 __ bind(&string_add_runtime); | 4675 __ bind(&string_add_runtime); |
4680 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 4676 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
4681 } | 4677 } |
4682 | 4678 |
4683 | 4679 |
4684 #undef __ | 4680 #undef __ |
4685 | 4681 |
4686 } } // namespace v8::internal | 4682 } } // namespace v8::internal |
4687 | 4683 |
4688 #endif // V8_TARGET_ARCH_ARM | 4684 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |