| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "regexp-macro-assembler.h" | 34 #include "regexp-macro-assembler.h" |
| 35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
| 36 | 36 |
| 37 namespace v8 { | 37 namespace v8 { |
| 38 namespace internal { | 38 namespace internal { |
| 39 | 39 |
| 40 | 40 |
| 41 void ToNumberStub::InitializeInterfaceDescriptor( |
| 42 Isolate* isolate, |
| 43 CodeStubInterfaceDescriptor* descriptor) { |
| 44 // x0: value |
| 45 static Register registers[] = { x0 }; |
| 46 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 47 descriptor->register_params_ = registers; |
| 48 descriptor->deoptimization_handler_ = NULL; |
| 49 } |
| 50 |
| 51 |
| 41 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( | 52 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( |
| 42 Isolate* isolate, | 53 Isolate* isolate, |
| 43 CodeStubInterfaceDescriptor* descriptor) { | 54 CodeStubInterfaceDescriptor* descriptor) { |
| 44 // x3: array literals array | 55 // x3: array literals array |
| 45 // x2: array literal index | 56 // x2: array literal index |
| 46 // x1: constant elements | 57 // x1: constant elements |
| 47 static Register registers[] = { x3, x2, x1 }; | 58 static Register registers[] = { x3, x2, x1 }; |
| 48 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 59 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 49 descriptor->register_params_ = registers; | 60 descriptor->register_params_ = registers; |
| 50 descriptor->deoptimization_handler_ = | 61 descriptor->deoptimization_handler_ = |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 // x2: key (unused) | 280 // x2: key (unused) |
| 270 // x0: value | 281 // x0: value |
| 271 static Register registers[] = { x1, x2, x0 }; | 282 static Register registers[] = { x1, x2, x0 }; |
| 272 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 283 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 273 descriptor->register_params_ = registers; | 284 descriptor->register_params_ = registers; |
| 274 descriptor->deoptimization_handler_ = | 285 descriptor->deoptimization_handler_ = |
| 275 FUNCTION_ADDR(StoreIC_MissFromStubFailure); | 286 FUNCTION_ADDR(StoreIC_MissFromStubFailure); |
| 276 } | 287 } |
| 277 | 288 |
| 278 | 289 |
| 279 #if 0 | |
| 280 // TODO(jbramley): This was added in r15635, then reverted in r15674, but it | |
| 281 // will come back again in r15713. | |
| 282 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor( | 290 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor( |
| 283 Isolate* isolate, | 291 Isolate* isolate, |
| 284 CodeStubInterfaceDescriptor* descriptor) { | 292 CodeStubInterfaceDescriptor* descriptor) { |
| 285 // x0: value | 293 // x0: value |
| 286 // x3: target map | 294 // x3: target map |
| 287 // x1: key | 295 // x1: key |
| 288 // x2: receiver | 296 // x2: receiver |
| 289 static Register registers[] = { x0, x3, x1, x2 }; | 297 static Register registers[] = { x0, x3, x1, x2 }; |
| 290 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 298 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 291 descriptor->register_params_ = registers; | 299 descriptor->register_params_ = registers; |
| 292 descriptor->deoptimization_handler_ = | 300 descriptor->deoptimization_handler_ = |
| 293 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); | 301 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); |
| 294 } | 302 } |
| 295 #endif | |
| 296 | 303 |
| 297 | 304 |
| 298 #define __ ACCESS_MASM(masm) | 305 #define __ ACCESS_MASM(masm) |
| 299 | 306 |
| 300 | 307 |
| 301 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 308 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
| 302 // Update the static counter each time a new code stub is generated. | 309 // Update the static counter each time a new code stub is generated. |
| 303 Isolate* isolate = masm->isolate(); | 310 Isolate* isolate = masm->isolate(); |
| 304 isolate->counters()->code_stubs()->Increment(); | 311 isolate->counters()->code_stubs()->Increment(); |
| 305 | 312 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 316 __ Push(descriptor->register_params_[i]); | 323 __ Push(descriptor->register_params_[i]); |
| 317 } | 324 } |
| 318 ExternalReference miss = descriptor->miss_handler(); | 325 ExternalReference miss = descriptor->miss_handler(); |
| 319 __ CallExternalReference(miss, descriptor->register_param_count_); | 326 __ CallExternalReference(miss, descriptor->register_param_count_); |
| 320 } | 327 } |
| 321 | 328 |
| 322 __ Ret(); | 329 __ Ret(); |
| 323 } | 330 } |
| 324 | 331 |
| 325 | 332 |
| 326 // Input: | |
| 327 // x0: object to convert. | |
| 328 // Output: | |
| 329 // x0: result number. | |
| 330 void ToNumberStub::Generate(MacroAssembler* masm) { | |
| 331 // See ECMA-262 section 9.3. | |
| 332 | |
| 333 // If it is a Smi or a HeapNumber, just return the value. | |
| 334 Label done; | |
| 335 __ JumpIfSmi(x0, &done); | |
| 336 __ JumpIfHeapNumber(x0, &done); | |
| 337 | |
| 338 // Inline checks for specific values that we can easily convert. | |
| 339 Label return_zero, return_one; | |
| 340 | |
| 341 // Check for 'true', 'false', and 'null'. | |
| 342 __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, &return_one); | |
| 343 __ JumpIfRoot(x0, Heap::kFalseValueRootIndex, &return_zero); | |
| 344 __ JumpIfRoot(x0, Heap::kNullValueRootIndex, &return_zero); | |
| 345 | |
| 346 // Call a builtin to do the job. | |
| 347 __ Push(x0); | |
| 348 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); | |
| 349 | |
| 350 // We never fall through here. | |
| 351 if (FLAG_debug_code) { | |
| 352 __ Abort("We should never reach this code."); | |
| 353 } | |
| 354 | |
| 355 __ Bind(&return_zero); | |
| 356 __ Mov(x0, Operand(Smi::FromInt(0))); | |
| 357 __ Ret(); | |
| 358 | |
| 359 __ Bind(&return_one); | |
| 360 __ Mov(x0, Operand(Smi::FromInt(1))); | |
| 361 __ Bind(&done); | |
| 362 __ Ret(); | |
| 363 } | |
| 364 | |
| 365 | |
| 366 void FastNewClosureStub::Generate(MacroAssembler* masm) { | 333 void FastNewClosureStub::Generate(MacroAssembler* masm) { |
| 367 // Create a new closure from the given function info in new space. Set the | 334 // Create a new closure from the given function info in new space. Set the |
| 368 // context to the current context in cp. | 335 // context to the current context in cp. |
| 369 Register new_fn = x0; | 336 Register new_fn = x0; |
| 370 Register function = x1; | 337 Register function = x1; |
| 371 | 338 |
| 372 Counters* counters = masm->isolate()->counters(); | 339 Counters* counters = masm->isolate()->counters(); |
| 373 | 340 |
| 374 Label gc; | 341 Label gc; |
| 375 | 342 |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 | 742 |
| 776 // If right or left is not ODDBALL, test left >= FIRST_SPEC_OBJECT_TYPE. | 743 // If right or left is not ODDBALL, test left >= FIRST_SPEC_OBJECT_TYPE. |
| 777 // Otherwise, right or left is ODDBALL, so set a ge condition. | 744 // Otherwise, right or left is ODDBALL, so set a ge condition. |
| 778 __ Ccmp(left_type, FIRST_SPEC_OBJECT_TYPE, NVFlag, ne); | 745 __ Ccmp(left_type, FIRST_SPEC_OBJECT_TYPE, NVFlag, ne); |
| 779 | 746 |
| 780 __ B(ge, &return_not_equal); | 747 __ B(ge, &return_not_equal); |
| 781 | 748 |
| 782 // Internalized strings are unique, so they can only be equal if they are the | 749 // Internalized strings are unique, so they can only be equal if they are the |
| 783 // same object. We have already tested that case, so if left and right are | 750 // same object. We have already tested that case, so if left and right are |
| 784 // both internalized strings, they cannot be equal. | 751 // both internalized strings, they cannot be equal. |
| 785 __ And(scratch, right_type, kIsNotStringMask | kIsInternalizedMask); | 752 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
| 786 __ Cmp(scratch, kInternalizedTag | kStringTag); | 753 __ Orr(scratch, left_type, right_type); |
| 787 __ And(scratch, left_type, kIsNotStringMask | kIsInternalizedMask); | 754 __ TestAndBranchIfAllClear( |
| 788 __ Ccmp(scratch, kInternalizedTag | kStringTag, NoFlag, eq); | 755 scratch, kIsNotStringMask | kIsNotInternalizedMask, &return_not_equal); |
| 789 __ B(eq, &return_not_equal); | |
| 790 } | 756 } |
| 791 | 757 |
| 792 | 758 |
| 793 // See call site for description. | 759 // See call site for description. |
| 794 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 760 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
| 795 Register left, | 761 Register left, |
| 796 Register right, | 762 Register right, |
| 797 FPRegister left_d, | 763 FPRegister left_d, |
| 798 FPRegister right_d, | 764 FPRegister right_d, |
| 799 Register scratch, | 765 Register scratch, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 Register left_map, | 837 Register left_map, |
| 872 Register right_map, | 838 Register right_map, |
| 873 Register left_type, | 839 Register left_type, |
| 874 Register right_type, | 840 Register right_type, |
| 875 Label* possible_strings, | 841 Label* possible_strings, |
| 876 Label* not_both_strings) { | 842 Label* not_both_strings) { |
| 877 ASSERT(!AreAliased(left, right, left_map, right_map, left_type, right_type)); | 843 ASSERT(!AreAliased(left, right, left_map, right_map, left_type, right_type)); |
| 878 Register result = x0; | 844 Register result = x0; |
| 879 | 845 |
| 880 Label object_test; | 846 Label object_test; |
| 881 STATIC_ASSERT(kStringTag == 0); | 847 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
| 882 STATIC_ASSERT(kInternalizedTag != 0); | |
| 883 // TODO(all): reexamine this branch sequence for optimisation wrt branch | 848 // TODO(all): reexamine this branch sequence for optimisation wrt branch |
| 884 // prediction. | 849 // prediction. |
| 885 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); | 850 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); |
| 886 __ Tbz(right_type, MaskToBit(kIsInternalizedMask), possible_strings); | 851 __ Tbnz(right_type, MaskToBit(kIsNotInternalizedMask), possible_strings); |
| 887 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), not_both_strings); | 852 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), not_both_strings); |
| 888 __ Tbz(left_type, MaskToBit(kIsInternalizedMask), possible_strings); | 853 __ Tbnz(left_type, MaskToBit(kIsNotInternalizedMask), possible_strings); |
| 889 | 854 |
| 890 // Both are internalized. We already checked that they weren't the same | 855 // Both are internalized. We already checked that they weren't the same |
| 891 // pointer, so they are not equal. | 856 // pointer, so they are not equal. |
| 892 __ Mov(result, NOT_EQUAL); | 857 __ Mov(result, NOT_EQUAL); |
| 893 __ Ret(); | 858 __ Ret(); |
| 894 | 859 |
| 895 __ Bind(&object_test); | 860 __ Bind(&object_test); |
| 896 | 861 |
| 897 __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE); | 862 __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE); |
| 898 | 863 |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1644 // Test if left operand is a smi or string. | 1609 // Test if left operand is a smi or string. |
| 1645 __ JumpIfSmi(left, &call_transition); | 1610 __ JumpIfSmi(left, &call_transition); |
| 1646 __ JumpIfObjectType(left, x2, x2, FIRST_NONSTRING_TYPE, &call_transition, ge); | 1611 __ JumpIfObjectType(left, x2, x2, FIRST_NONSTRING_TYPE, &call_transition, ge); |
| 1647 | 1612 |
| 1648 // Test if right operand is a smi or string. | 1613 // Test if right operand is a smi or string. |
| 1649 __ JumpIfSmi(right, &call_transition); | 1614 __ JumpIfSmi(right, &call_transition); |
| 1650 __ JumpIfObjectType(right, x2, x2, FIRST_NONSTRING_TYPE, &call_transition, | 1615 __ JumpIfObjectType(right, x2, x2, FIRST_NONSTRING_TYPE, &call_transition, |
| 1651 ge); | 1616 ge); |
| 1652 | 1617 |
| 1653 StringAddStub string_add_stub( | 1618 StringAddStub string_add_stub( |
| 1654 static_cast<StringAddFlags>(ERECT_FRAME | NO_STRING_CHECK_IN_STUB)); | 1619 static_cast<StringAddFlags>(STRING_ADD_CHECK_NONE | |
| 1620 STRING_ADD_ERECT_FRAME)); |
| 1655 GenerateRegisterArgsPush(masm); | 1621 GenerateRegisterArgsPush(masm); |
| 1656 __ TailCallStub(&string_add_stub); | 1622 __ TailCallStub(&string_add_stub); |
| 1657 | 1623 |
| 1658 __ Bind(&call_transition); | 1624 __ Bind(&call_transition); |
| 1659 GenerateTypeTransition(masm); | 1625 GenerateTypeTransition(masm); |
| 1660 } | 1626 } |
| 1661 | 1627 |
| 1662 | 1628 |
| 1663 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 1629 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
| 1664 // On a64 the smis are 32 bits, so we should never see the INT32 type. | 1630 // On a64 the smis are 32 bits, so we should never see the INT32 type. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1757 Label left_not_string, call_runtime; | 1723 Label left_not_string, call_runtime; |
| 1758 | 1724 |
| 1759 Register left = x1; | 1725 Register left = x1; |
| 1760 Register right = x0; | 1726 Register right = x0; |
| 1761 | 1727 |
| 1762 // Check if left argument is a string. | 1728 // Check if left argument is a string. |
| 1763 __ JumpIfSmi(left, &left_not_string); | 1729 __ JumpIfSmi(left, &left_not_string); |
| 1764 __ JumpIfObjectType(left, x2, x2, FIRST_NONSTRING_TYPE, &left_not_string, ge); | 1730 __ JumpIfObjectType(left, x2, x2, FIRST_NONSTRING_TYPE, &left_not_string, ge); |
| 1765 | 1731 |
| 1766 StringAddStub string_add_left_stub( | 1732 StringAddStub string_add_left_stub( |
| 1767 static_cast<StringAddFlags>(ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB)); | 1733 static_cast<StringAddFlags>(STRING_ADD_CHECK_RIGHT | |
| 1734 STRING_ADD_ERECT_FRAME)); |
| 1768 GenerateRegisterArgsPush(masm); | 1735 GenerateRegisterArgsPush(masm); |
| 1769 __ TailCallStub(&string_add_left_stub); | 1736 __ TailCallStub(&string_add_left_stub); |
| 1770 | 1737 |
| 1771 // Left operand is not a string, test right. | 1738 // Left operand is not a string, test right. |
| 1772 __ Bind(&left_not_string); | 1739 __ Bind(&left_not_string); |
| 1773 __ JumpIfSmi(right, &call_runtime); | 1740 __ JumpIfSmi(right, &call_runtime); |
| 1774 __ JumpIfObjectType(right, x2, x2, FIRST_NONSTRING_TYPE, &call_runtime, ge); | 1741 __ JumpIfObjectType(right, x2, x2, FIRST_NONSTRING_TYPE, &call_runtime, ge); |
| 1775 | 1742 |
| 1776 StringAddStub string_add_right_stub( | 1743 StringAddStub string_add_right_stub( |
| 1777 static_cast<StringAddFlags>(ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB)); | 1744 static_cast<StringAddFlags>(STRING_ADD_CHECK_LEFT | |
| 1745 STRING_ADD_ERECT_FRAME)); |
| 1778 GenerateRegisterArgsPush(masm); | 1746 GenerateRegisterArgsPush(masm); |
| 1779 __ TailCallStub(&string_add_right_stub); | 1747 __ TailCallStub(&string_add_right_stub); |
| 1780 | 1748 |
| 1781 // Neither argument is a string. | 1749 // Neither argument is a string. |
| 1782 __ Bind(&call_runtime); | 1750 __ Bind(&call_runtime); |
| 1783 } | 1751 } |
| 1784 | 1752 |
| 1785 | 1753 |
| 1786 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 1754 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
| 1787 Register result, | 1755 Register result, |
| (...skipping 2936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4724 // Check that both operands are internalized strings. | 4692 // Check that both operands are internalized strings. |
| 4725 Register rhs_map = x10; | 4693 Register rhs_map = x10; |
| 4726 Register lhs_map = x11; | 4694 Register lhs_map = x11; |
| 4727 Register rhs_type = x10; | 4695 Register rhs_type = x10; |
| 4728 Register lhs_type = x11; | 4696 Register lhs_type = x11; |
| 4729 __ Ldr(lhs_map, FieldMemOperand(lhs, HeapObject::kMapOffset)); | 4697 __ Ldr(lhs_map, FieldMemOperand(lhs, HeapObject::kMapOffset)); |
| 4730 __ Ldr(rhs_map, FieldMemOperand(rhs, HeapObject::kMapOffset)); | 4698 __ Ldr(rhs_map, FieldMemOperand(rhs, HeapObject::kMapOffset)); |
| 4731 __ Ldrb(lhs_type, FieldMemOperand(lhs_map, Map::kInstanceTypeOffset)); | 4699 __ Ldrb(lhs_type, FieldMemOperand(lhs_map, Map::kInstanceTypeOffset)); |
| 4732 __ Ldrb(rhs_type, FieldMemOperand(rhs_map, Map::kInstanceTypeOffset)); | 4700 __ Ldrb(rhs_type, FieldMemOperand(rhs_map, Map::kInstanceTypeOffset)); |
| 4733 | 4701 |
| 4734 __ And(x12, rhs_type, kIsNotStringMask | kIsInternalizedMask); | 4702 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
| 4735 __ And(x13, lhs_type, kIsNotStringMask | kIsInternalizedMask); | 4703 __ Orr(x12, lhs_type, rhs_type); |
| 4736 __ Cmp(x12, kInternalizedTag | kStringTag); | 4704 __ TestAndBranchIfAnySet( |
| 4737 __ Ccmp(x13, kInternalizedTag | kStringTag, NoFlag, eq); | 4705 x12, kIsNotStringMask | kIsNotInternalizedMask, &miss); |
| 4738 __ B(ne, &miss); | |
| 4739 | 4706 |
| 4740 // Internalized strings are compared by identity. | 4707 // Internalized strings are compared by identity. |
| 4741 STATIC_ASSERT(EQUAL == 0); | 4708 STATIC_ASSERT(EQUAL == 0); |
| 4742 __ Cmp(lhs, rhs); | 4709 __ Cmp(lhs, rhs); |
| 4743 __ Cset(result, ne); | 4710 __ Cset(result, ne); |
| 4744 __ Ret(); | 4711 __ Ret(); |
| 4745 | 4712 |
| 4746 __ Bind(&miss); | 4713 __ Bind(&miss); |
| 4747 GenerateMiss(masm); | 4714 GenerateMiss(masm); |
| 4748 } | 4715 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4823 __ Ret(); | 4790 __ Ret(); |
| 4824 | 4791 |
| 4825 __ Bind(¬_equal); | 4792 __ Bind(¬_equal); |
| 4826 // Handle not identical strings | 4793 // Handle not identical strings |
| 4827 | 4794 |
| 4828 // Check that both strings are internalized strings. If they are, we're done | 4795 // Check that both strings are internalized strings. If they are, we're done |
| 4829 // because we already know they are not identical. We know they are both | 4796 // because we already know they are not identical. We know they are both |
| 4830 // strings. | 4797 // strings. |
| 4831 if (equality) { | 4798 if (equality) { |
| 4832 ASSERT(GetCondition() == eq); | 4799 ASSERT(GetCondition() == eq); |
| 4833 STATIC_ASSERT(kInternalizedTag != 0); | 4800 STATIC_ASSERT(kInternalizedTag == 0); |
| 4834 Label not_internalized_strings; | 4801 Label not_internalized_strings; |
| 4835 __ And(x12, lhs_type, rhs_type); | 4802 __ Orr(x12, lhs_type, rhs_type); |
| 4836 __ Tbz(x12, MaskToBit(kIsInternalizedMask), ¬_internalized_strings); | 4803 __ TestAndBranchIfAnySet( |
| 4804 x12, kIsNotInternalizedMask, ¬_internalized_strings); |
| 4837 // Result is in rhs (x0), and not EQUAL, as rhs is not a smi. | 4805 // Result is in rhs (x0), and not EQUAL, as rhs is not a smi. |
| 4838 __ Ret(); | 4806 __ Ret(); |
| 4839 __ Bind(¬_internalized_strings); | 4807 __ Bind(¬_internalized_strings); |
| 4840 } | 4808 } |
| 4841 | 4809 |
| 4842 // Check that both strings are sequential ASCII. | 4810 // Check that both strings are sequential ASCII. |
| 4843 Label runtime; | 4811 Label runtime; |
| 4844 __ JumpIfBothInstanceTypesAreNotSequentialAscii( | 4812 __ JumpIfBothInstanceTypesAreNotSequentialAscii( |
| 4845 lhs_type, rhs_type, x12, x13, &runtime); | 4813 lhs_type, rhs_type, x12, x13, &runtime); |
| 4846 | 4814 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4954 __ Jump(stub_entry); | 4922 __ Jump(stub_entry); |
| 4955 } | 4923 } |
| 4956 | 4924 |
| 4957 | 4925 |
| 4958 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, | 4926 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, |
| 4959 Register object, | 4927 Register object, |
| 4960 Register result, | 4928 Register result, |
| 4961 Register scratch1, | 4929 Register scratch1, |
| 4962 Register scratch2, | 4930 Register scratch2, |
| 4963 Register scratch3, | 4931 Register scratch3, |
| 4964 ObjectType object_type, | |
| 4965 Label* not_found) { | 4932 Label* not_found) { |
| 4966 ASSERT(!AreAliased(object, result, scratch1, scratch2, scratch3)); | 4933 ASSERT(!AreAliased(object, result, scratch1, scratch2, scratch3)); |
| 4967 | 4934 |
| 4968 // Use of registers. Register result is used as a temporary. | 4935 // Use of registers. Register result is used as a temporary. |
| 4969 Register number_string_cache = result; | 4936 Register number_string_cache = result; |
| 4970 Register mask = scratch3; | 4937 Register mask = scratch3; |
| 4971 | 4938 |
| 4972 // Load the number string cache. | 4939 // Load the number string cache. |
| 4973 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); | 4940 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 4974 | 4941 |
| 4975 // Make the hash mask from the length of the number string cache. It | 4942 // Make the hash mask from the length of the number string cache. It |
| 4976 // contains two elements (number and string) for each cache entry. | 4943 // contains two elements (number and string) for each cache entry. |
| 4977 __ Ldrsw(mask, UntagSmiFieldMemOperand(number_string_cache, | 4944 __ Ldrsw(mask, UntagSmiFieldMemOperand(number_string_cache, |
| 4978 FixedArray::kLengthOffset)); | 4945 FixedArray::kLengthOffset)); |
| 4979 __ Asr(mask, mask, 1); // Divide length by two. | 4946 __ Asr(mask, mask, 1); // Divide length by two. |
| 4980 __ Sub(mask, mask, 1); // Make mask. | 4947 __ Sub(mask, mask, 1); // Make mask. |
| 4981 | 4948 |
| 4982 // Calculate the entry in the number string cache. The hash value in the | 4949 // Calculate the entry in the number string cache. The hash value in the |
| 4983 // number string cache for smis is just the smi value, and the hash for | 4950 // number string cache for smis is just the smi value, and the hash for |
| 4984 // doubles is the xor of the upper and lower words. See | 4951 // doubles is the xor of the upper and lower words. See |
| 4985 // Heap::GetNumberStringCache. | 4952 // Heap::GetNumberStringCache. |
| 4986 Isolate* isolate = masm->isolate(); | 4953 Isolate* isolate = masm->isolate(); |
| 4987 Label is_smi; | 4954 Label is_smi; |
| 4988 Label load_result_from_cache; | 4955 Label load_result_from_cache; |
| 4989 if (object_type == OBJECT_IS_NOT_SMI) { | |
| 4990 __ JumpIfSmi(object, &is_smi); | |
| 4991 __ CheckMap(object, scratch1, Heap::kHeapNumberMapRootIndex, not_found, | |
| 4992 DONT_DO_SMI_CHECK); | |
| 4993 | 4956 |
| 4994 STATIC_ASSERT(kDoubleSize == (kWRegSizeInBytes * 2)); | 4957 __ JumpIfSmi(object, &is_smi); |
| 4995 __ Add(scratch1, object, HeapNumber::kValueOffset - kHeapObjectTag); | 4958 __ CheckMap(object, scratch1, Heap::kHeapNumberMapRootIndex, not_found, |
| 4996 __ Ldp(scratch1.W(), scratch2.W(), MemOperand(scratch1)); | 4959 DONT_DO_SMI_CHECK); |
| 4997 __ Eor(scratch1, scratch1, scratch2); | |
| 4998 __ And(scratch1, scratch1, mask); | |
| 4999 | 4960 |
| 5000 // Calculate address of entry in string cache: each entry consists of two | 4961 STATIC_ASSERT(kDoubleSize == (kWRegSizeInBytes * 2)); |
| 5001 // pointer sized fields. | 4962 __ Add(scratch1, object, HeapNumber::kValueOffset - kHeapObjectTag); |
| 5002 __ Add(scratch1, number_string_cache, | 4963 __ Ldp(scratch1.W(), scratch2.W(), MemOperand(scratch1)); |
| 5003 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); | 4964 __ Eor(scratch1, scratch1, scratch2); |
| 4965 __ And(scratch1, scratch1, mask); |
| 5004 | 4966 |
| 5005 Register probe = mask; | 4967 // Calculate address of entry in string cache: each entry consists of two |
| 5006 __ Ldr(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); | 4968 // pointer sized fields. |
| 5007 __ JumpIfSmi(probe, not_found); | 4969 __ Add(scratch1, number_string_cache, |
| 5008 __ Ldr(d0, FieldMemOperand(object, HeapNumber::kValueOffset)); | 4970 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); |
| 5009 __ Ldr(d1, FieldMemOperand(probe, HeapNumber::kValueOffset)); | 4971 |
| 5010 __ Fcmp(d0, d1); | 4972 Register probe = mask; |
| 5011 __ B(ne, not_found); | 4973 __ Ldr(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
| 5012 __ B(&load_result_from_cache); | 4974 __ JumpIfSmi(probe, not_found); |
| 5013 } | 4975 __ Ldr(d0, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 4976 __ Ldr(d1, FieldMemOperand(probe, HeapNumber::kValueOffset)); |
| 4977 __ Fcmp(d0, d1); |
| 4978 __ B(ne, not_found); |
| 4979 __ B(&load_result_from_cache); |
| 5014 | 4980 |
| 5015 __ Bind(&is_smi); | 4981 __ Bind(&is_smi); |
| 5016 Register scratch = scratch1; | 4982 Register scratch = scratch1; |
| 5017 __ And(scratch, mask, Operand::UntagSmi(object)); | 4983 __ And(scratch, mask, Operand::UntagSmi(object)); |
| 5018 // Calculate address of entry in string cache: each entry consists | 4984 // Calculate address of entry in string cache: each entry consists |
| 5019 // of two pointer sized fields. | 4985 // of two pointer sized fields. |
| 5020 __ Add(scratch, | 4986 __ Add(scratch, |
| 5021 number_string_cache, | 4987 number_string_cache, |
| 5022 Operand(scratch, LSL, kPointerSizeLog2 + 1)); | 4988 Operand(scratch, LSL, kPointerSizeLog2 + 1)); |
| 5023 | 4989 |
| 5024 // Check if the entry is the smi we are looking for. | 4990 // Check if the entry is the smi we are looking for. |
| 5025 Register probe = mask; | |
| 5026 __ Ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 4991 __ Ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
| 5027 __ Cmp(object, probe); | 4992 __ Cmp(object, probe); |
| 5028 __ B(ne, not_found); | 4993 __ B(ne, not_found); |
| 5029 | 4994 |
| 5030 // Get the result from the cache. | 4995 // Get the result from the cache. |
| 5031 __ Bind(&load_result_from_cache); | 4996 __ Bind(&load_result_from_cache); |
| 5032 __ Ldr(result, | 4997 __ Ldr(result, |
| 5033 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); | 4998 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); |
| 5034 __ IncrementCounter(isolate->counters()->number_to_string_native(), 1, | 4999 __ IncrementCounter(isolate->counters()->number_to_string_native(), 1, |
| 5035 scratch1, scratch2); | 5000 scratch1, scratch2); |
| 5036 } | 5001 } |
| 5037 | 5002 |
| 5038 | 5003 |
| 5039 void NumberToStringStub::Generate(MacroAssembler* masm) { | 5004 void NumberToStringStub::Generate(MacroAssembler* masm) { |
| 5040 Register result = x0; | 5005 Register result = x0; |
| 5041 Register object = x1; | 5006 Register object = x1; |
| 5042 Label runtime; | 5007 Label runtime; |
| 5043 | 5008 |
| 5044 __ Pop(object); | 5009 __ Pop(object); |
| 5045 | 5010 |
| 5046 // Generate code to lookup number in the number string cache. | 5011 // Generate code to lookup number in the number string cache. |
| 5047 GenerateLookupNumberStringCache(masm, object, result, x2, x3, x4, | 5012 GenerateLookupNumberStringCache(masm, object, result, x2, x3, x4, &runtime); |
| 5048 NumberToStringStub::OBJECT_IS_NOT_SMI, | |
| 5049 &runtime); | |
| 5050 __ Ret(); | 5013 __ Ret(); |
| 5051 | 5014 |
| 5052 // Handle number to string in the runtime system if not found in the cache. | 5015 // Handle number to string in the runtime system if not found in the cache. |
| 5053 __ Bind(&runtime); | 5016 __ Bind(&runtime); |
| 5054 __ Push(object); | 5017 __ Push(object); |
| 5055 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); | 5018 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); |
| 5056 } | 5019 } |
| 5057 | 5020 |
| 5058 | 5021 |
| 5059 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, | 5022 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, |
| (...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5692 Register result = x0; | 5655 Register result = x0; |
| 5693 Register left = x10; | 5656 Register left = x10; |
| 5694 Register right = x11; | 5657 Register right = x11; |
| 5695 Register left_type = x12; | 5658 Register left_type = x12; |
| 5696 Register right_type = x13; | 5659 Register right_type = x13; |
| 5697 | 5660 |
| 5698 // Pop the two arguments from the stack. | 5661 // Pop the two arguments from the stack. |
| 5699 __ Pop(right, left); | 5662 __ Pop(right, left); |
| 5700 | 5663 |
| 5701 // Make sure that both arguments are strings if not known in advance. | 5664 // Make sure that both arguments are strings if not known in advance. |
| 5702 if ((flags_ & NO_STRING_ADD_FLAGS) != 0) { | 5665 // Otherwise, at least one of the arguments is definitely a string, |
| 5666 // and we convert the one that is not known to be a string. |
| 5667 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { |
| 5668 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT); |
| 5669 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT); |
| 5703 __ JumpIfEitherSmi(right, left, &call_runtime); | 5670 __ JumpIfEitherSmi(right, left, &call_runtime); |
| 5704 // Load instance types. | 5671 // Load instance types. |
| 5705 StringHelper::LoadPairInstanceTypes(masm, left_type, right_type, left, | 5672 StringHelper::LoadPairInstanceTypes(masm, left_type, right_type, left, |
| 5706 right); | 5673 right); |
| 5707 STATIC_ASSERT(kStringTag == 0); | 5674 STATIC_ASSERT(kStringTag == 0); |
| 5708 // If either is not a string, go to runtime. | 5675 // If either is not a string, go to runtime. |
| 5709 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), &call_runtime); | 5676 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), &call_runtime); |
| 5710 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &call_runtime); | 5677 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &call_runtime); |
| 5711 } else { | 5678 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { |
| 5712 // Here at least one of the arguments is definitely a string. | 5679 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0); |
| 5713 // We convert the one that is not known to be a string. | 5680 GenerateConvertArgument(masm, left, x12, x13, x14, x15, &call_builtin); |
| 5714 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { | 5681 builtin_id = Builtins::STRING_ADD_RIGHT; |
| 5715 // NO_STRING_CHECK_LEFT flag is clear: convert the left string. | 5682 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { |
| 5716 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); | 5683 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0); |
| 5717 GenerateConvertArgument(masm, left, x12, x13, x14, x15, &call_builtin); | 5684 GenerateConvertArgument(masm, right, x12, x13, x14, x15, &call_builtin); |
| 5718 builtin_id = Builtins::STRING_ADD_RIGHT; | 5685 builtin_id = Builtins::STRING_ADD_LEFT; |
| 5719 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { | |
| 5720 // NO_STRING_CHECK_RIGHT flag is clear: convert the right string. | |
| 5721 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); | |
| 5722 GenerateConvertArgument(masm, right, x12, x13, x14, x15, &call_builtin); | |
| 5723 builtin_id = Builtins::STRING_ADD_LEFT; | |
| 5724 } | |
| 5725 } | 5686 } |
| 5726 | 5687 |
| 5727 // Both arguments are strings. | 5688 // Both arguments are strings. |
| 5728 // x0 result pointer to result string object (uninit) | 5689 // x0 result pointer to result string object (uninit) |
| 5729 // x10 left pointer to first string object | 5690 // x10 left pointer to first string object |
| 5730 // x11 right pointer to second string object | 5691 // x11 right pointer to second string object |
| 5731 // if (flags_ == NO_STRING_ADD_FLAGS) { | 5692 // x12 left_type first string instance type (if STRING_ADD_CHECK_BOTH) |
| 5732 // x12 left_type first string instance type | 5693 // x13 right_type second string instance type (if STRING_ADD_CHECK_BOTH) |
| 5733 // x13 right_type second string instance type | |
| 5734 // } | |
| 5735 Register left_len = x14; | 5694 Register left_len = x14; |
| 5736 Register right_len = x15; | 5695 Register right_len = x15; |
| 5737 { | 5696 { |
| 5738 Label strings_not_empty; | 5697 Label strings_not_empty; |
| 5739 // Speculatively move pointer to left string into the result register. | 5698 // Speculatively move pointer to left string into the result register. |
| 5740 __ Mov(result, left); | 5699 __ Mov(result, left); |
| 5741 // Check if either of the strings are empty. In that case return the other. | 5700 // Check if either of the strings are empty. In that case return the other. |
| 5742 __ Ldrsw(left_len, UntagSmiFieldMemOperand(left, String::kLengthOffset)); | 5701 __ Ldrsw(left_len, UntagSmiFieldMemOperand(left, String::kLengthOffset)); |
| 5743 __ Ldrsw(right_len, UntagSmiFieldMemOperand(right, String::kLengthOffset)); | 5702 __ Ldrsw(right_len, UntagSmiFieldMemOperand(right, String::kLengthOffset)); |
| 5744 // Test if first string is empty. | 5703 // Test if first string is empty. |
| 5745 __ Cmp(left_len, 0); | 5704 __ Cmp(left_len, 0); |
| 5746 // If first is empty, return second. | 5705 // If first is empty, return second. |
| 5747 __ CmovX(result, right, eq); | 5706 __ CmovX(result, right, eq); |
| 5748 // Else test if second string is empty. | 5707 // Else test if second string is empty. |
| 5749 __ Ccmp(right_len, 0, ZFlag, ne); | 5708 __ Ccmp(right_len, 0, ZFlag, ne); |
| 5750 // If either string was empty, return result. | 5709 // If either string was empty, return result. |
| 5751 __ B(ne, &strings_not_empty); | 5710 __ B(ne, &strings_not_empty); |
| 5752 | 5711 |
| 5753 __ IncrementCounter(counters->string_add_native(), 1, x3, x4); | 5712 __ IncrementCounter(counters->string_add_native(), 1, x3, x4); |
| 5754 __ Ret(); | 5713 __ Ret(); |
| 5755 | 5714 |
| 5756 __ Bind(&strings_not_empty); | 5715 __ Bind(&strings_not_empty); |
| 5757 } | 5716 } |
| 5758 | 5717 |
| 5759 // Load string instance types. | 5718 // Load string instance types. |
| 5760 if (flags_ != NO_STRING_ADD_FLAGS) { | 5719 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { |
| 5761 StringHelper::LoadPairInstanceTypes(masm, left_type, right_type, left, | 5720 StringHelper::LoadPairInstanceTypes(masm, left_type, right_type, left, |
| 5762 right); | 5721 right); |
| 5763 } | 5722 } |
| 5764 | 5723 |
| 5765 // Both strings are non-empty. | 5724 // Both strings are non-empty. |
| 5766 // x10 left first string | 5725 // x10 left first string |
| 5767 // x11 right second string | 5726 // x11 right second string |
| 5768 // x12 left_type first string instance type | 5727 // x12 left_type first string instance type |
| 5769 // x13 right_type second string instance type | 5728 // x13 right_type second string instance type |
| 5770 // x14 left_len length of first string | 5729 // x14 left_len length of first string |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6008 __ Add(right_len, right_len, right_len); | 5967 __ Add(right_len, right_len, right_len); |
| 6009 __ CopyBytes(result_char, right_char, right_len, temp, kCopyShort); | 5968 __ CopyBytes(result_char, right_char, right_len, temp, kCopyShort); |
| 6010 __ IncrementCounter(counters->string_add_native(), 1, x3, x4); | 5969 __ IncrementCounter(counters->string_add_native(), 1, x3, x4); |
| 6011 __ Ret(); | 5970 __ Ret(); |
| 6012 | 5971 |
| 6013 | 5972 |
| 6014 // Just jump to runtime to add the two strings. | 5973 // Just jump to runtime to add the two strings. |
| 6015 __ Bind(&call_runtime); | 5974 __ Bind(&call_runtime); |
| 6016 // Restore stack arguments. | 5975 // Restore stack arguments. |
| 6017 __ Push(left, right); | 5976 __ Push(left, right); |
| 6018 if ((flags_ & ERECT_FRAME) != 0) { | 5977 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { |
| 6019 GenerateRegisterArgsPop(masm); | 5978 GenerateRegisterArgsPop(masm); |
| 6020 // Build a frame | 5979 // Build a frame |
| 6021 { | 5980 { |
| 6022 FrameScope scope(masm, StackFrame::INTERNAL); | 5981 FrameScope scope(masm, StackFrame::INTERNAL); |
| 6023 GenerateRegisterArgsPush(masm); | 5982 GenerateRegisterArgsPush(masm); |
| 6024 __ CallRuntime(Runtime::kStringAdd, 2); | 5983 __ CallRuntime(Runtime::kStringAdd, 2); |
| 6025 } | 5984 } |
| 6026 __ Ret(); | 5985 __ Ret(); |
| 6027 } else { | 5986 } else { |
| 6028 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 5987 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 6029 } | 5988 } |
| 6030 | 5989 |
| 6031 if (call_builtin.is_linked()) { | 5990 if (call_builtin.is_linked()) { |
| 6032 __ Bind(&call_builtin); | 5991 __ Bind(&call_builtin); |
| 6033 // Restore stack arguments. | 5992 // Restore stack arguments. |
| 6034 __ Push(left, right); | 5993 __ Push(left, right); |
| 6035 if ((flags_ & ERECT_FRAME) != 0) { | 5994 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { |
| 6036 GenerateRegisterArgsPop(masm); | 5995 GenerateRegisterArgsPop(masm); |
| 6037 // Build a frame | 5996 // Build a frame |
| 6038 { | 5997 { |
| 6039 FrameScope scope(masm, StackFrame::INTERNAL); | 5998 FrameScope scope(masm, StackFrame::INTERNAL); |
| 6040 GenerateRegisterArgsPush(masm); | 5999 GenerateRegisterArgsPush(masm); |
| 6041 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); | 6000 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); |
| 6042 } | 6001 } |
| 6043 __ Ret(); | 6002 __ Ret(); |
| 6044 } else { | 6003 } else { |
| 6045 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); | 6004 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6066 Label not_cached; | 6025 Label not_cached; |
| 6067 __ Bind(¬_string); | 6026 __ Bind(¬_string); |
| 6068 // Puts the cache result into scratch1. | 6027 // Puts the cache result into scratch1. |
| 6069 NumberToStringStub::GenerateLookupNumberStringCache( | 6028 NumberToStringStub::GenerateLookupNumberStringCache( |
| 6070 masm, | 6029 masm, |
| 6071 arg, | 6030 arg, |
| 6072 scratch1, | 6031 scratch1, |
| 6073 scratch2, | 6032 scratch2, |
| 6074 scratch3, | 6033 scratch3, |
| 6075 scratch4, | 6034 scratch4, |
| 6076 NumberToStringStub::OBJECT_IS_NOT_SMI, | |
| 6077 ¬_cached); | 6035 ¬_cached); |
| 6078 __ Mov(arg, scratch1); | 6036 __ Mov(arg, scratch1); |
| 6079 __ B(&done); | 6037 __ B(&done); |
| 6080 | 6038 |
| 6081 // Check if the argument is a safe string wrapper. | 6039 // Check if the argument is a safe string wrapper. |
| 6082 __ Bind(¬_cached); | 6040 __ Bind(¬_cached); |
| 6083 __ JumpIfSmi(arg, slow); | 6041 __ JumpIfSmi(arg, slow); |
| 6084 Register map = scratch1; | 6042 Register map = scratch1; |
| 6085 __ JumpIfNotObjectType(arg, map, scratch2, JS_VALUE_TYPE, slow); | 6043 __ JumpIfNotObjectType(arg, map, scratch2, JS_VALUE_TYPE, slow); |
| 6086 __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitField2Offset)); | 6044 __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitField2Offset)); |
| (...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7082 __ Bind(&fast_elements_case); | 7040 __ Bind(&fast_elements_case); |
| 7083 GenerateCase(masm, FAST_ELEMENTS); | 7041 GenerateCase(masm, FAST_ELEMENTS); |
| 7084 } | 7042 } |
| 7085 | 7043 |
| 7086 | 7044 |
| 7087 #undef __ | 7045 #undef __ |
| 7088 | 7046 |
| 7089 } } // namespace v8::internal | 7047 } } // namespace v8::internal |
| 7090 | 7048 |
| 7091 #endif // V8_TARGET_ARCH_A64 | 7049 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |