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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 3421009: Revision 2.4.4.... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 10 years, 3 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 | « src/api.cc ('k') | src/arm/codegen-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 // On entry lhs_ and rhs_ are the values to be compared. 923 // On entry lhs_ and rhs_ are the values to be compared.
924 // On exit r0 is 0, positive or negative to indicate the result of 924 // On exit r0 is 0, positive or negative to indicate the result of
925 // the comparison. 925 // the comparison.
926 void CompareStub::Generate(MacroAssembler* masm) { 926 void CompareStub::Generate(MacroAssembler* masm) {
927 ASSERT((lhs_.is(r0) && rhs_.is(r1)) || 927 ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
928 (lhs_.is(r1) && rhs_.is(r0))); 928 (lhs_.is(r1) && rhs_.is(r0)));
929 929
930 Label slow; // Call builtin. 930 Label slow; // Call builtin.
931 Label not_smis, both_loaded_as_doubles, lhs_not_nan; 931 Label not_smis, both_loaded_as_doubles, lhs_not_nan;
932 932
933 if (include_smi_compare_) {
934 Label not_two_smis, smi_done;
935 __ orr(r2, r1, r0);
936 __ tst(r2, Operand(kSmiTagMask));
937 __ b(ne, &not_two_smis);
938 __ sub(r0, r1, r0);
939 __ b(vc, &smi_done);
940 // Correct the sign in case of overflow.
941 __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
942 __ bind(&smi_done);
943 __ Ret();
944 __ bind(&not_two_smis);
945 } else if (FLAG_debug_code) {
946 __ orr(r2, r1, r0);
947 __ tst(r2, Operand(kSmiTagMask));
948 __ Assert(nz, "CompareStub: unexpected smi operands.");
949 }
950
933 // NOTICE! This code is only reached after a smi-fast-case check, so 951 // NOTICE! This code is only reached after a smi-fast-case check, so
934 // it is certain that at least one operand isn't a smi. 952 // it is certain that at least one operand isn't a smi.
935 953
936 // Handle the case where the objects are identical. Either returns the answer 954 // Handle the case where the objects are identical. Either returns the answer
937 // or goes to slow. Only falls through if the objects were not identical. 955 // or goes to slow. Only falls through if the objects were not identical.
938 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); 956 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
939 957
940 // If either is a Smi (we know that not both are), then they can only 958 // If either is a Smi (we know that not both are), then they can only
941 // be strictly equal if the other is a HeapNumber. 959 // be strictly equal if the other is a HeapNumber.
942 STATIC_ASSERT(kSmiTag == 0); 960 STATIC_ASSERT(kSmiTag == 0);
(...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after
2281 } 2299 }
2282 2300
2283 2301
2284 void StackCheckStub::Generate(MacroAssembler* masm) { 2302 void StackCheckStub::Generate(MacroAssembler* masm) {
2285 // Do tail-call to runtime routine. Runtime routines expect at least one 2303 // Do tail-call to runtime routine. Runtime routines expect at least one
2286 // argument, so give it a Smi. 2304 // argument, so give it a Smi.
2287 __ mov(r0, Operand(Smi::FromInt(0))); 2305 __ mov(r0, Operand(Smi::FromInt(0)));
2288 __ push(r0); 2306 __ push(r0);
2289 __ TailCallRuntime(Runtime::kStackGuard, 1, 1); 2307 __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
2290 2308
2291 __ StubReturn(1); 2309 __ Ret();
2292 } 2310 }
2293 2311
2294 2312
2295 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { 2313 void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
2296 Label slow, done; 2314 Label slow, done;
2297 2315
2298 Register heap_number_map = r6; 2316 Register heap_number_map = r6;
2299 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2317 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
2300 2318
2301 if (op_ == Token::SUB) { 2319 if (op_ == Token::SUB) {
2302 // Check whether the value is a smi. 2320 if (include_smi_code_) {
2303 Label try_float; 2321 // Check whether the value is a smi.
2304 __ tst(r0, Operand(kSmiTagMask)); 2322 Label try_float;
2305 __ b(ne, &try_float); 2323 __ tst(r0, Operand(kSmiTagMask));
2324 __ b(ne, &try_float);
2306 2325
2307 // Go slow case if the value of the expression is zero 2326 // Go slow case if the value of the expression is zero
2308 // to make sure that we switch between 0 and -0. 2327 // to make sure that we switch between 0 and -0.
2309 if (negative_zero_ == kStrictNegativeZero) { 2328 if (negative_zero_ == kStrictNegativeZero) {
2310 // If we have to check for zero, then we can check for the max negative 2329 // If we have to check for zero, then we can check for the max negative
2311 // smi while we are at it. 2330 // smi while we are at it.
2312 __ bic(ip, r0, Operand(0x80000000), SetCC); 2331 __ bic(ip, r0, Operand(0x80000000), SetCC);
2313 __ b(eq, &slow); 2332 __ b(eq, &slow);
2314 __ rsb(r0, r0, Operand(0, RelocInfo::NONE)); 2333 __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
2315 __ StubReturn(1); 2334 __ Ret();
2316 } else { 2335 } else {
2317 // The value of the expression is a smi and 0 is OK for -0. Try 2336 // The value of the expression is a smi and 0 is OK for -0. Try
2318 // optimistic subtraction '0 - value'. 2337 // optimistic subtraction '0 - value'.
2319 __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC); 2338 __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
2320 __ StubReturn(1, vc); 2339 __ Ret(vc);
2321 // We don't have to reverse the optimistic neg since the only case 2340 // We don't have to reverse the optimistic neg since the only case
2322 // where we fall through is the minimum negative Smi, which is the case 2341 // where we fall through is the minimum negative Smi, which is the case
2323 // where the neg leaves the register unchanged. 2342 // where the neg leaves the register unchanged.
2324 __ jmp(&slow); // Go slow on max negative Smi. 2343 __ jmp(&slow); // Go slow on max negative Smi.
2344 }
2345 __ bind(&try_float);
2346 } else if (FLAG_debug_code) {
2347 __ tst(r0, Operand(kSmiTagMask));
2348 __ Assert(ne, "Unexpected smi operand.");
2325 } 2349 }
2326 2350
2327 __ bind(&try_float);
2328 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2351 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2329 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2352 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
2330 __ cmp(r1, heap_number_map); 2353 __ cmp(r1, heap_number_map);
2331 __ b(ne, &slow); 2354 __ b(ne, &slow);
2332 // r0 is a heap number. Get a new heap number in r1. 2355 // r0 is a heap number. Get a new heap number in r1.
2333 if (overwrite_ == UNARY_OVERWRITE) { 2356 if (overwrite_ == UNARY_OVERWRITE) {
2334 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2357 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2335 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. 2358 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
2336 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2359 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2337 } else { 2360 } else {
2338 __ AllocateHeapNumber(r1, r2, r3, r6, &slow); 2361 __ AllocateHeapNumber(r1, r2, r3, r6, &slow);
2339 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2362 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2340 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2363 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2341 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); 2364 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset));
2342 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. 2365 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
2343 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); 2366 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset));
2344 __ mov(r0, Operand(r1)); 2367 __ mov(r0, Operand(r1));
2345 } 2368 }
2346 } else if (op_ == Token::BIT_NOT) { 2369 } else if (op_ == Token::BIT_NOT) {
2370 if (include_smi_code_) {
2371 Label non_smi;
2372 __ BranchOnNotSmi(r0, &non_smi);
2373 __ mvn(r0, Operand(r0));
2374 // Bit-clear inverted smi-tag.
2375 __ bic(r0, r0, Operand(kSmiTagMask));
2376 __ Ret();
2377 __ bind(&non_smi);
2378 } else if (FLAG_debug_code) {
2379 __ tst(r0, Operand(kSmiTagMask));
2380 __ Assert(ne, "Unexpected smi operand.");
2381 }
2382
2347 // Check if the operand is a heap number. 2383 // Check if the operand is a heap number.
2348 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2384 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2349 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2385 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
2350 __ cmp(r1, heap_number_map); 2386 __ cmp(r1, heap_number_map);
2351 __ b(ne, &slow); 2387 __ b(ne, &slow);
2352 2388
2353 // Convert the heap number is r0 to an untagged integer in r1. 2389 // Convert the heap number is r0 to an untagged integer in r1.
2354 __ ConvertToInt32(r0, r1, r2, r3, &slow); 2390 __ ConvertToInt32(r0, r1, r2, r3, &slow);
2355 2391
2356 // Do the bitwise operation (move negated) and check if the result 2392 // Do the bitwise operation (move negated) and check if the result
(...skipping 27 matching lines...) Expand all
2384 WriteInt32ToHeapNumberStub stub(r1, r0, r2); 2420 WriteInt32ToHeapNumberStub stub(r1, r0, r2);
2385 __ push(lr); 2421 __ push(lr);
2386 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); 2422 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
2387 __ pop(lr); 2423 __ pop(lr);
2388 } 2424 }
2389 } else { 2425 } else {
2390 UNIMPLEMENTED(); 2426 UNIMPLEMENTED();
2391 } 2427 }
2392 2428
2393 __ bind(&done); 2429 __ bind(&done);
2394 __ StubReturn(1); 2430 __ Ret();
2395 2431
2396 // Handle the slow case by jumping to the JavaScript builtin. 2432 // Handle the slow case by jumping to the JavaScript builtin.
2397 __ bind(&slow); 2433 __ bind(&slow);
2398 __ push(r0); 2434 __ push(r0);
2399 switch (op_) { 2435 switch (op_) {
2400 case Token::SUB: 2436 case Token::SUB:
2401 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); 2437 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS);
2402 break; 2438 break;
2403 case Token::BIT_NOT: 2439 case Token::BIT_NOT:
2404 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); 2440 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS);
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after
3492 const char* never_nan_nan_name = ""; 3528 const char* never_nan_nan_name = "";
3493 if (never_nan_nan_ && (cc_ == eq || cc_ == ne)) { 3529 if (never_nan_nan_ && (cc_ == eq || cc_ == ne)) {
3494 never_nan_nan_name = "_NO_NAN"; 3530 never_nan_nan_name = "_NO_NAN";
3495 } 3531 }
3496 3532
3497 const char* include_number_compare_name = ""; 3533 const char* include_number_compare_name = "";
3498 if (!include_number_compare_) { 3534 if (!include_number_compare_) {
3499 include_number_compare_name = "_NO_NUMBER"; 3535 include_number_compare_name = "_NO_NUMBER";
3500 } 3536 }
3501 3537
3538 const char* include_smi_compare_name = "";
3539 if (!include_smi_compare_) {
3540 include_smi_compare_name = "_NO_SMI";
3541 }
3542
3502 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 3543 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
3503 "CompareStub_%s%s%s%s%s%s", 3544 "CompareStub_%s%s%s%s%s%s",
3504 cc_name, 3545 cc_name,
3505 lhs_name, 3546 lhs_name,
3506 rhs_name, 3547 rhs_name,
3507 strict_name, 3548 strict_name,
3508 never_nan_nan_name, 3549 never_nan_nan_name,
3509 include_number_compare_name); 3550 include_number_compare_name,
3551 include_smi_compare_name);
3510 return name_; 3552 return name_;
3511 } 3553 }
3512 3554
3513 3555
3514 int CompareStub::MinorKey() { 3556 int CompareStub::MinorKey() {
3515 // Encode the three parameters in a unique 16 bit value. To avoid duplicate 3557 // Encode the three parameters in a unique 16 bit value. To avoid duplicate
3516 // stubs the never NaN NaN condition is only taken into account if the 3558 // stubs the never NaN NaN condition is only taken into account if the
3517 // condition is equals. 3559 // condition is equals.
3518 ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 12)); 3560 ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 12));
3519 ASSERT((lhs_.is(r0) && rhs_.is(r1)) || 3561 ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
3520 (lhs_.is(r1) && rhs_.is(r0))); 3562 (lhs_.is(r1) && rhs_.is(r0)));
3521 return ConditionField::encode(static_cast<unsigned>(cc_) >> 28) 3563 return ConditionField::encode(static_cast<unsigned>(cc_) >> 28)
3522 | RegisterField::encode(lhs_.is(r0)) 3564 | RegisterField::encode(lhs_.is(r0))
3523 | StrictField::encode(strict_) 3565 | StrictField::encode(strict_)
3524 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) 3566 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
3525 | IncludeNumberCompareField::encode(include_number_compare_); 3567 | IncludeNumberCompareField::encode(include_number_compare_)
3568 | IncludeSmiCompareField::encode(include_smi_compare_);
3526 } 3569 }
3527 3570
3528 3571
3529 // StringCharCodeAtGenerator 3572 // StringCharCodeAtGenerator
3530 3573
3531 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 3574 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
3532 Label flat_string; 3575 Label flat_string;
3533 Label ascii_string; 3576 Label ascii_string;
3534 Label got_char_code; 3577 Label got_char_code;
3535 3578
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after
4137 // both "from" and "to" are smis, and 4180 // both "from" and "to" are smis, and
4138 // 0 <= from <= to <= string.length. 4181 // 0 <= from <= to <= string.length.
4139 // If any of these assumptions fail, we call the runtime system. 4182 // If any of these assumptions fail, we call the runtime system.
4140 4183
4141 static const int kToOffset = 0 * kPointerSize; 4184 static const int kToOffset = 0 * kPointerSize;
4142 static const int kFromOffset = 1 * kPointerSize; 4185 static const int kFromOffset = 1 * kPointerSize;
4143 static const int kStringOffset = 2 * kPointerSize; 4186 static const int kStringOffset = 2 * kPointerSize;
4144 4187
4145 4188
4146 // Check bounds and smi-ness. 4189 // Check bounds and smi-ness.
4147 __ ldr(r7, MemOperand(sp, kToOffset)); 4190 Register to = r6;
4148 __ ldr(r6, MemOperand(sp, kFromOffset)); 4191 Register from = r7;
4192 __ Ldrd(to, from, MemOperand(sp, kToOffset));
4193 STATIC_ASSERT(kFromOffset == kToOffset + 4);
4149 STATIC_ASSERT(kSmiTag == 0); 4194 STATIC_ASSERT(kSmiTag == 0);
4150 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 4195 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4151 // I.e., arithmetic shift right by one un-smi-tags. 4196 // I.e., arithmetic shift right by one un-smi-tags.
4152 __ mov(r2, Operand(r7, ASR, 1), SetCC); 4197 __ mov(r2, Operand(to, ASR, 1), SetCC);
4153 __ mov(r3, Operand(r6, ASR, 1), SetCC, cc); 4198 __ 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. 4199 // 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. 4200 __ b(cs, &runtime); // Either "from" or "to" is not a smi.
4156 __ b(mi, &runtime); // From is negative. 4201 __ b(mi, &runtime); // From is negative.
4157 4202
4203 // Both to and from are smis.
4204
4158 __ sub(r2, r2, Operand(r3), SetCC); 4205 __ sub(r2, r2, Operand(r3), SetCC);
4159 __ b(mi, &runtime); // Fail if from > to. 4206 __ b(mi, &runtime); // Fail if from > to.
4160 // Special handling of sub-strings of length 1 and 2. One character strings 4207 // 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 4208 // are handled in the runtime system (looked up in the single character
4162 // cache). Two character strings are looked for in the symbol cache. 4209 // cache). Two character strings are looked for in the symbol cache.
4163 __ cmp(r2, Operand(2)); 4210 __ cmp(r2, Operand(2));
4164 __ b(lt, &runtime); 4211 __ b(lt, &runtime);
4165 4212
4166 // r2: length 4213 // r2: length
4167 // r3: from index (untaged smi) 4214 // r3: from index (untaged smi)
4168 // r6: from (smi) 4215 // r6 (a.k.a. to): to (smi)
4169 // r7: to (smi) 4216 // r7 (a.k.a. from): from offset (smi)
4170 4217
4171 // Make sure first argument is a sequential (or flat) string. 4218 // Make sure first argument is a sequential (or flat) string.
4172 __ ldr(r5, MemOperand(sp, kStringOffset)); 4219 __ ldr(r5, MemOperand(sp, kStringOffset));
4173 STATIC_ASSERT(kSmiTag == 0); 4220 STATIC_ASSERT(kSmiTag == 0);
4174 __ tst(r5, Operand(kSmiTagMask)); 4221 __ tst(r5, Operand(kSmiTagMask));
4175 __ b(eq, &runtime); 4222 __ b(eq, &runtime);
4176 Condition is_string = masm->IsObjectStringType(r5, r1); 4223 Condition is_string = masm->IsObjectStringType(r5, r1);
4177 __ b(NegateCondition(is_string), &runtime); 4224 __ b(NegateCondition(is_string), &runtime);
4178 4225
4179 // r1: instance type 4226 // r1: instance type
4180 // r2: length 4227 // r2: length
4181 // r3: from index (untaged smi) 4228 // r3: from index (untagged smi)
4182 // r5: string 4229 // r5: string
4183 // r6: from (smi) 4230 // r6 (a.k.a. to): to (smi)
4184 // r7: to (smi) 4231 // r7 (a.k.a. from): from offset (smi)
4185 Label seq_string; 4232 Label seq_string;
4186 __ and_(r4, r1, Operand(kStringRepresentationMask)); 4233 __ and_(r4, r1, Operand(kStringRepresentationMask));
4187 STATIC_ASSERT(kSeqStringTag < kConsStringTag); 4234 STATIC_ASSERT(kSeqStringTag < kConsStringTag);
4188 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 4235 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
4189 __ cmp(r4, Operand(kConsStringTag)); 4236 __ cmp(r4, Operand(kConsStringTag));
4190 __ b(gt, &runtime); // External strings go to runtime. 4237 __ b(gt, &runtime); // External strings go to runtime.
4191 __ b(lt, &seq_string); // Sequential strings are handled directly. 4238 __ b(lt, &seq_string); // Sequential strings are handled directly.
4192 4239
4193 // Cons string. Try to recurse (once) on the first substring. 4240 // Cons string. Try to recurse (once) on the first substring.
4194 // (This adds a little more generality than necessary to handle flattened 4241 // (This adds a little more generality than necessary to handle flattened
4195 // cons strings, but not much). 4242 // cons strings, but not much).
4196 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset)); 4243 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset));
4197 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); 4244 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
4198 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 4245 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset));
4199 __ tst(r1, Operand(kStringRepresentationMask)); 4246 __ tst(r1, Operand(kStringRepresentationMask));
4200 STATIC_ASSERT(kSeqStringTag == 0); 4247 STATIC_ASSERT(kSeqStringTag == 0);
4201 __ b(ne, &runtime); // Cons and External strings go to runtime. 4248 __ b(ne, &runtime); // Cons and External strings go to runtime.
4202 4249
4203 // Definitly a sequential string. 4250 // Definitly a sequential string.
4204 __ bind(&seq_string); 4251 __ bind(&seq_string);
4205 4252
4206 // r1: instance type. 4253 // r1: instance type.
4207 // r2: length 4254 // r2: length
4208 // r3: from index (untaged smi) 4255 // r3: from index (untaged smi)
4209 // r5: string 4256 // r5: string
4210 // r6: from (smi) 4257 // r6 (a.k.a. to): to (smi)
4211 // r7: to (smi) 4258 // r7 (a.k.a. from): from offset (smi)
4212 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); 4259 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset));
4213 __ cmp(r4, Operand(r7)); 4260 __ cmp(r4, Operand(to));
4214 __ b(lt, &runtime); // Fail if to > length. 4261 __ b(lt, &runtime); // Fail if to > length.
4262 to = no_reg;
4215 4263
4216 // r1: instance type. 4264 // r1: instance type.
4217 // r2: result string length. 4265 // r2: result string length.
4218 // r3: from index (untaged smi) 4266 // r3: from index (untaged smi)
4219 // r5: string. 4267 // r5: string.
4220 // r6: from offset (smi) 4268 // r7 (a.k.a. from): from offset (smi)
4221 // Check for flat ascii string. 4269 // Check for flat ascii string.
4222 Label non_ascii_flat; 4270 Label non_ascii_flat;
4223 __ tst(r1, Operand(kStringEncodingMask)); 4271 __ tst(r1, Operand(kStringEncodingMask));
4224 STATIC_ASSERT(kTwoByteStringTag == 0); 4272 STATIC_ASSERT(kTwoByteStringTag == 0);
4225 __ b(eq, &non_ascii_flat); 4273 __ b(eq, &non_ascii_flat);
4226 4274
4227 Label result_longer_than_two; 4275 Label result_longer_than_two;
4228 __ cmp(r2, Operand(2)); 4276 __ cmp(r2, Operand(2));
4229 __ b(gt, &result_longer_than_two); 4277 __ b(gt, &result_longer_than_two);
4230 4278
(...skipping 21 matching lines...) Expand all
4252 __ Ret(); 4300 __ Ret();
4253 4301
4254 __ bind(&result_longer_than_two); 4302 __ bind(&result_longer_than_two);
4255 4303
4256 // Allocate the result. 4304 // Allocate the result.
4257 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); 4305 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime);
4258 4306
4259 // r0: result string. 4307 // r0: result string.
4260 // r2: result string length. 4308 // r2: result string length.
4261 // r5: string. 4309 // r5: string.
4262 // r6: from offset (smi) 4310 // r7 (a.k.a. from): from offset (smi)
4263 // Locate first character of result. 4311 // Locate first character of result.
4264 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 4312 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
4265 // Locate 'from' character of string. 4313 // Locate 'from' character of string.
4266 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 4314 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
4267 __ add(r5, r5, Operand(r6, ASR, 1)); 4315 __ add(r5, r5, Operand(from, ASR, 1));
4268 4316
4269 // r0: result string. 4317 // r0: result string.
4270 // r1: first character of result string. 4318 // r1: first character of result string.
4271 // r2: result string length. 4319 // r2: result string length.
4272 // r5: first character of sub string to copy. 4320 // r5: first character of sub string to copy.
4273 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 4321 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
4274 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 4322 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
4275 COPY_ASCII | DEST_ALWAYS_ALIGNED); 4323 COPY_ASCII | DEST_ALWAYS_ALIGNED);
4276 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 4324 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
4277 __ add(sp, sp, Operand(3 * kPointerSize)); 4325 __ add(sp, sp, Operand(3 * kPointerSize));
4278 __ Ret(); 4326 __ Ret();
4279 4327
4280 __ bind(&non_ascii_flat); 4328 __ bind(&non_ascii_flat);
4281 // r2: result string length. 4329 // r2: result string length.
4282 // r5: string. 4330 // r5: string.
4283 // r6: from offset (smi) 4331 // r7 (a.k.a. from): from offset (smi)
4284 // Check for flat two byte string. 4332 // Check for flat two byte string.
4285 4333
4286 // Allocate the result. 4334 // Allocate the result.
4287 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime); 4335 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime);
4288 4336
4289 // r0: result string. 4337 // r0: result string.
4290 // r2: result string length. 4338 // r2: result string length.
4291 // r5: string. 4339 // r5: string.
4292 // Locate first character of result. 4340 // Locate first character of result.
4293 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 4341 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
4294 // Locate 'from' character of string. 4342 // Locate 'from' character of string.
4295 __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 4343 __ 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 4344 // As "from" is a smi it is 2 times the value which matches the size of a two
4297 // byte character. 4345 // byte character.
4298 __ add(r5, r5, Operand(r6)); 4346 __ add(r5, r5, Operand(from));
4347 from = no_reg;
4299 4348
4300 // r0: result string. 4349 // r0: result string.
4301 // r1: first character of result. 4350 // r1: first character of result.
4302 // r2: result length. 4351 // r2: result length.
4303 // r5: first character of string to copy. 4352 // r5: first character of string to copy.
4304 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 4353 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
4305 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 4354 StringHelper::GenerateCopyCharactersLong(
4306 DEST_ALWAYS_ALIGNED); 4355 masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
4307 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 4356 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
4308 __ add(sp, sp, Operand(3 * kPointerSize)); 4357 __ add(sp, sp, Operand(3 * kPointerSize));
4309 __ Ret(); 4358 __ Ret();
4310 4359
4311 // Just jump to runtime to create the sub string. 4360 // Just jump to runtime to create the sub string.
4312 __ bind(&runtime); 4361 __ bind(&runtime);
4313 __ TailCallRuntime(Runtime::kSubString, 3, 1); 4362 __ TailCallRuntime(Runtime::kSubString, 3, 1);
4314 } 4363 }
4315 4364
4316 4365
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
4372 __ Ret(); 4421 __ Ret();
4373 } 4422 }
4374 4423
4375 4424
4376 void StringCompareStub::Generate(MacroAssembler* masm) { 4425 void StringCompareStub::Generate(MacroAssembler* masm) {
4377 Label runtime; 4426 Label runtime;
4378 4427
4379 // Stack frame on entry. 4428 // Stack frame on entry.
4380 // sp[0]: right string 4429 // sp[0]: right string
4381 // sp[4]: left string 4430 // sp[4]: left string
4382 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // left 4431 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1.
4383 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // right
4384 4432
4385 Label not_same; 4433 Label not_same;
4386 __ cmp(r0, r1); 4434 __ cmp(r0, r1);
4387 __ b(ne, &not_same); 4435 __ b(ne, &not_same);
4388 STATIC_ASSERT(EQUAL == 0); 4436 STATIC_ASSERT(EQUAL == 0);
4389 STATIC_ASSERT(kSmiTag == 0); 4437 STATIC_ASSERT(kSmiTag == 0);
4390 __ mov(r0, Operand(Smi::FromInt(EQUAL))); 4438 __ mov(r0, Operand(Smi::FromInt(EQUAL)));
4391 __ IncrementCounter(&Counters::string_compare_native, 1, r1, r2); 4439 __ IncrementCounter(&Counters::string_compare_native, 1, r1, r2);
4392 __ add(sp, sp, Operand(2 * kPointerSize)); 4440 __ add(sp, sp, Operand(2 * kPointerSize));
4393 __ Ret(); 4441 __ Ret();
4394 4442
4395 __ bind(&not_same); 4443 __ bind(&not_same);
4396 4444
4397 // Check that both objects are sequential ascii strings. 4445 // Check that both objects are sequential ascii strings.
4398 __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime); 4446 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime);
4399 4447
4400 // Compare flat ascii strings natively. Remove arguments from stack first. 4448 // Compare flat ascii strings natively. Remove arguments from stack first.
4401 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3); 4449 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
4402 __ add(sp, sp, Operand(2 * kPointerSize)); 4450 __ add(sp, sp, Operand(2 * kPointerSize));
4403 GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5); 4451 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5);
4404 4452
4405 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 4453 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
4406 // tagged as a small integer. 4454 // tagged as a small integer.
4407 __ bind(&runtime); 4455 __ bind(&runtime);
4408 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 4456 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
4409 } 4457 }
4410 4458
4411 4459
4412 void StringAddStub::Generate(MacroAssembler* masm) { 4460 void StringAddStub::Generate(MacroAssembler* masm) {
4413 Label string_add_runtime; 4461 Label string_add_runtime;
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
4679 __ bind(&string_add_runtime); 4727 __ bind(&string_add_runtime);
4680 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 4728 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
4681 } 4729 }
4682 4730
4683 4731
4684 #undef __ 4732 #undef __
4685 4733
4686 } } // namespace v8::internal 4734 } } // namespace v8::internal
4687 4735
4688 #endif // V8_TARGET_ARCH_ARM 4736 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/api.cc ('k') | src/arm/codegen-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698