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

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

Issue 139973004: A64: Synchronize with r15814. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/a64/code-stubs-a64.h ('k') | src/a64/codegen-a64.cc » ('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 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
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
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
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
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
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
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
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
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
4823 __ Ret(); 4790 __ Ret();
4824 4791
4825 __ Bind(&not_equal); 4792 __ Bind(&not_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), &not_internalized_strings); 4803 __ TestAndBranchIfAnySet(
4804 x12, kIsNotInternalizedMask, &not_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(&not_internalized_strings); 4807 __ Bind(&not_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
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
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
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
6066 Label not_cached; 6025 Label not_cached;
6067 __ Bind(&not_string); 6026 __ Bind(&not_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 &not_cached); 6035 &not_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(&not_cached); 6040 __ Bind(&not_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
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
OLDNEW
« no previous file with comments | « src/a64/code-stubs-a64.h ('k') | src/a64/codegen-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698