OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 // Test if left operand is a string. | 1901 // Test if left operand is a string. |
1902 __ JumpIfSmi(left, &call_runtime); | 1902 __ JumpIfSmi(left, &call_runtime); |
1903 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); | 1903 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); |
1904 __ b(ge, &call_runtime); | 1904 __ b(ge, &call_runtime); |
1905 | 1905 |
1906 // Test if right operand is a string. | 1906 // Test if right operand is a string. |
1907 __ JumpIfSmi(right, &call_runtime); | 1907 __ JumpIfSmi(right, &call_runtime); |
1908 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); | 1908 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); |
1909 __ b(ge, &call_runtime); | 1909 __ b(ge, &call_runtime); |
1910 | 1910 |
1911 StringAddStub string_add_stub((StringAddFlags) | 1911 StringAddStub string_add_stub( |
1912 (ERECT_FRAME | NO_STRING_CHECK_IN_STUB)); | 1912 (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME)); |
1913 GenerateRegisterArgsPush(masm); | 1913 GenerateRegisterArgsPush(masm); |
1914 __ TailCallStub(&string_add_stub); | 1914 __ TailCallStub(&string_add_stub); |
1915 | 1915 |
1916 __ bind(&call_runtime); | 1916 __ bind(&call_runtime); |
1917 GenerateTypeTransition(masm); | 1917 GenerateTypeTransition(masm); |
1918 } | 1918 } |
1919 | 1919 |
1920 | 1920 |
1921 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 1921 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
1922 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); | 1922 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2260 Label left_not_string, call_runtime; | 2260 Label left_not_string, call_runtime; |
2261 | 2261 |
2262 Register left = r1; | 2262 Register left = r1; |
2263 Register right = r0; | 2263 Register right = r0; |
2264 | 2264 |
2265 // Check if left argument is a string. | 2265 // Check if left argument is a string. |
2266 __ JumpIfSmi(left, &left_not_string); | 2266 __ JumpIfSmi(left, &left_not_string); |
2267 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); | 2267 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); |
2268 __ b(ge, &left_not_string); | 2268 __ b(ge, &left_not_string); |
2269 | 2269 |
2270 StringAddStub string_add_left_stub((StringAddFlags) | 2270 StringAddStub string_add_left_stub( |
2271 (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB)); | 2271 (StringAddFlags)(STRING_ADD_CHECK_RIGHT | STRING_ADD_ERECT_FRAME)); |
2272 GenerateRegisterArgsPush(masm); | 2272 GenerateRegisterArgsPush(masm); |
2273 __ TailCallStub(&string_add_left_stub); | 2273 __ TailCallStub(&string_add_left_stub); |
2274 | 2274 |
2275 // Left operand is not a string, test right. | 2275 // Left operand is not a string, test right. |
2276 __ bind(&left_not_string); | 2276 __ bind(&left_not_string); |
2277 __ JumpIfSmi(right, &call_runtime); | 2277 __ JumpIfSmi(right, &call_runtime); |
2278 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); | 2278 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); |
2279 __ b(ge, &call_runtime); | 2279 __ b(ge, &call_runtime); |
2280 | 2280 |
2281 StringAddStub string_add_right_stub((StringAddFlags) | 2281 StringAddStub string_add_right_stub( |
2282 (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB)); | 2282 (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME)); |
2283 GenerateRegisterArgsPush(masm); | 2283 GenerateRegisterArgsPush(masm); |
2284 __ TailCallStub(&string_add_right_stub); | 2284 __ TailCallStub(&string_add_right_stub); |
2285 | 2285 |
2286 // At least one argument is not a string. | 2286 // At least one argument is not a string. |
2287 __ bind(&call_runtime); | 2287 __ bind(&call_runtime); |
2288 } | 2288 } |
2289 | 2289 |
2290 | 2290 |
2291 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 2291 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
2292 Register result, | 2292 Register result, |
(...skipping 3205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5498 | 5498 |
5499 // Stack on entry: | 5499 // Stack on entry: |
5500 // sp[0]: second argument (right). | 5500 // sp[0]: second argument (right). |
5501 // sp[4]: first argument (left). | 5501 // sp[4]: first argument (left). |
5502 | 5502 |
5503 // Load the two arguments. | 5503 // Load the two arguments. |
5504 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. | 5504 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. |
5505 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. | 5505 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. |
5506 | 5506 |
5507 // Make sure that both arguments are strings if not known in advance. | 5507 // Make sure that both arguments are strings if not known in advance. |
5508 if ((flags_ & NO_STRING_ADD_FLAGS) != 0) { | 5508 // Otherwise, at least one of the arguments is definitely a string, |
| 5509 // and we convert the one that is not known to be a string. |
| 5510 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { |
5509 __ JumpIfEitherSmi(r0, r1, &call_runtime); | 5511 __ JumpIfEitherSmi(r0, r1, &call_runtime); |
5510 // Load instance types. | 5512 // Load instance types. |
5511 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5513 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5512 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5514 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5513 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5515 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5514 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5516 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5515 STATIC_ASSERT(kStringTag == 0); | 5517 STATIC_ASSERT(kStringTag == 0); |
5516 // If either is not a string, go to runtime. | 5518 // If either is not a string, go to runtime. |
5517 __ tst(r4, Operand(kIsNotStringMask)); | 5519 __ tst(r4, Operand(kIsNotStringMask)); |
5518 __ tst(r5, Operand(kIsNotStringMask), eq); | 5520 __ tst(r5, Operand(kIsNotStringMask), eq); |
5519 __ b(ne, &call_runtime); | 5521 __ b(ne, &call_runtime); |
5520 } else { | 5522 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { |
5521 // Here at least one of the arguments is definitely a string. | 5523 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0); |
5522 // We convert the one that is not known to be a string. | 5524 GenerateConvertArgument( |
5523 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { | 5525 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); |
5524 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); | 5526 builtin_id = Builtins::STRING_ADD_RIGHT; |
5525 GenerateConvertArgument( | 5527 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { |
5526 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); | 5528 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0); |
5527 builtin_id = Builtins::STRING_ADD_RIGHT; | 5529 GenerateConvertArgument( |
5528 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { | 5530 masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin); |
5529 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); | 5531 builtin_id = Builtins::STRING_ADD_LEFT; |
5530 GenerateConvertArgument( | |
5531 masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin); | |
5532 builtin_id = Builtins::STRING_ADD_LEFT; | |
5533 } | |
5534 } | 5532 } |
5535 | 5533 |
5536 // Both arguments are strings. | 5534 // Both arguments are strings. |
5537 // r0: first string | 5535 // r0: first string |
5538 // r1: second string | 5536 // r1: second string |
5539 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 5537 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5540 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 5538 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5541 { | 5539 { |
5542 Label strings_not_empty; | 5540 Label strings_not_empty; |
5543 // Check if either of the strings are empty. In that case return the other. | 5541 // Check if either of the strings are empty. In that case return the other. |
(...skipping 27 matching lines...) Expand all Loading... |
5571 Label string_add_flat_result, longer_than_two; | 5569 Label string_add_flat_result, longer_than_two; |
5572 // Adding two lengths can't overflow. | 5570 // Adding two lengths can't overflow. |
5573 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); | 5571 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); |
5574 __ add(r6, r2, Operand(r3)); | 5572 __ add(r6, r2, Operand(r3)); |
5575 // Use the string table when adding two one character strings, as it | 5573 // Use the string table when adding two one character strings, as it |
5576 // helps later optimizations to return a string here. | 5574 // helps later optimizations to return a string here. |
5577 __ cmp(r6, Operand(2)); | 5575 __ cmp(r6, Operand(2)); |
5578 __ b(ne, &longer_than_two); | 5576 __ b(ne, &longer_than_two); |
5579 | 5577 |
5580 // Check that both strings are non-external ASCII strings. | 5578 // Check that both strings are non-external ASCII strings. |
5581 if (flags_ != NO_STRING_ADD_FLAGS) { | 5579 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { |
5582 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5580 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5583 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5581 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5584 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5582 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5585 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5583 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5586 } | 5584 } |
5587 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, | 5585 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, |
5588 &call_runtime); | 5586 &call_runtime); |
5589 | 5587 |
5590 // Get the two characters forming the sub string. | 5588 // Get the two characters forming the sub string. |
5591 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); | 5589 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); |
(...skipping 27 matching lines...) Expand all Loading... |
5619 __ b(lt, &string_add_flat_result); | 5617 __ b(lt, &string_add_flat_result); |
5620 // Handle exceptionally long strings in the runtime system. | 5618 // Handle exceptionally long strings in the runtime system. |
5621 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 5619 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
5622 ASSERT(IsPowerOf2(String::kMaxLength + 1)); | 5620 ASSERT(IsPowerOf2(String::kMaxLength + 1)); |
5623 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. | 5621 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. |
5624 __ cmp(r6, Operand(String::kMaxLength + 1)); | 5622 __ cmp(r6, Operand(String::kMaxLength + 1)); |
5625 __ b(hs, &call_runtime); | 5623 __ b(hs, &call_runtime); |
5626 | 5624 |
5627 // If result is not supposed to be flat, allocate a cons string object. | 5625 // If result is not supposed to be flat, allocate a cons string object. |
5628 // If both strings are ASCII the result is an ASCII cons string. | 5626 // If both strings are ASCII the result is an ASCII cons string. |
5629 if (flags_ != NO_STRING_ADD_FLAGS) { | 5627 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { |
5630 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5628 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5631 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5629 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5632 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5630 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5633 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5631 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5634 } | 5632 } |
5635 Label non_ascii, allocated, ascii_data; | 5633 Label non_ascii, allocated, ascii_data; |
5636 STATIC_ASSERT(kTwoByteStringTag == 0); | 5634 STATIC_ASSERT(kTwoByteStringTag == 0); |
5637 __ tst(r4, Operand(kStringEncodingMask)); | 5635 __ tst(r4, Operand(kStringEncodingMask)); |
5638 __ tst(r5, Operand(kStringEncodingMask), ne); | 5636 __ tst(r5, Operand(kStringEncodingMask), ne); |
5639 __ b(eq, &non_ascii); | 5637 __ b(eq, &non_ascii); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5702 // Locate the first characters' locations. | 5700 // Locate the first characters' locations. |
5703 // r0: first string | 5701 // r0: first string |
5704 // r1: second string | 5702 // r1: second string |
5705 // r2: length of first string | 5703 // r2: length of first string |
5706 // r3: length of second string | 5704 // r3: length of second string |
5707 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 5705 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5708 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 5706 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
5709 // r6: sum of lengths. | 5707 // r6: sum of lengths. |
5710 Label first_prepared, second_prepared; | 5708 Label first_prepared, second_prepared; |
5711 __ bind(&string_add_flat_result); | 5709 __ bind(&string_add_flat_result); |
5712 if (flags_ != NO_STRING_ADD_FLAGS) { | 5710 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { |
5713 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5711 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5714 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 5712 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
5715 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 5713 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
5716 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 5714 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
5717 } | 5715 } |
5718 | 5716 |
5719 // Check whether both strings have same encoding | 5717 // Check whether both strings have same encoding |
5720 __ eor(r7, r4, Operand(r5)); | 5718 __ eor(r7, r4, Operand(r5)); |
5721 __ tst(r7, Operand(kStringEncodingMask)); | 5719 __ tst(r7, Operand(kStringEncodingMask)); |
5722 __ b(ne, &call_runtime); | 5720 __ b(ne, &call_runtime); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5790 // r6: first character of result. | 5788 // r6: first character of result. |
5791 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); | 5789 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); |
5792 // r6: next character of result. | 5790 // r6: next character of result. |
5793 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); | 5791 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); |
5794 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 5792 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
5795 __ add(sp, sp, Operand(2 * kPointerSize)); | 5793 __ add(sp, sp, Operand(2 * kPointerSize)); |
5796 __ Ret(); | 5794 __ Ret(); |
5797 | 5795 |
5798 // Just jump to runtime to add the two strings. | 5796 // Just jump to runtime to add the two strings. |
5799 __ bind(&call_runtime); | 5797 __ bind(&call_runtime); |
5800 if ((flags_ & ERECT_FRAME) != 0) { | 5798 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { |
5801 GenerateRegisterArgsPop(masm); | 5799 GenerateRegisterArgsPop(masm); |
5802 // Build a frame | 5800 // Build a frame |
5803 { | 5801 { |
5804 FrameScope scope(masm, StackFrame::INTERNAL); | 5802 FrameScope scope(masm, StackFrame::INTERNAL); |
5805 GenerateRegisterArgsPush(masm); | 5803 GenerateRegisterArgsPush(masm); |
5806 __ CallRuntime(Runtime::kStringAdd, 2); | 5804 __ CallRuntime(Runtime::kStringAdd, 2); |
5807 } | 5805 } |
5808 __ Ret(); | 5806 __ Ret(); |
5809 } else { | 5807 } else { |
5810 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 5808 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
5811 } | 5809 } |
5812 | 5810 |
5813 if (call_builtin.is_linked()) { | 5811 if (call_builtin.is_linked()) { |
5814 __ bind(&call_builtin); | 5812 __ bind(&call_builtin); |
5815 if ((flags_ & ERECT_FRAME) != 0) { | 5813 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { |
5816 GenerateRegisterArgsPop(masm); | 5814 GenerateRegisterArgsPop(masm); |
5817 // Build a frame | 5815 // Build a frame |
5818 { | 5816 { |
5819 FrameScope scope(masm, StackFrame::INTERNAL); | 5817 FrameScope scope(masm, StackFrame::INTERNAL); |
5820 GenerateRegisterArgsPush(masm); | 5818 GenerateRegisterArgsPush(masm); |
5821 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); | 5819 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); |
5822 } | 5820 } |
5823 __ Ret(); | 5821 __ Ret(); |
5824 } else { | 5822 } else { |
5825 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); | 5823 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7210 __ bind(&fast_elements_case); | 7208 __ bind(&fast_elements_case); |
7211 GenerateCase(masm, FAST_ELEMENTS); | 7209 GenerateCase(masm, FAST_ELEMENTS); |
7212 } | 7210 } |
7213 | 7211 |
7214 | 7212 |
7215 #undef __ | 7213 #undef __ |
7216 | 7214 |
7217 } } // namespace v8::internal | 7215 } } // namespace v8::internal |
7218 | 7216 |
7219 #endif // V8_TARGET_ARCH_ARM | 7217 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |