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

Side by Side Diff: runtime/vm/stub_code_arm.cc

Issue 746623002: Dedupe code for array/object initialization on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 1 month 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 | « runtime/vm/intermediate_language_arm.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 // R3: allocation stats address. 692 // R3: allocation stats address.
693 // R4, R5: null 693 // R4, R5: null
694 // R6: iterator which initially points to the start of the variable 694 // R6: iterator which initially points to the start of the variable
695 // data area to be initialized. 695 // data area to be initialized.
696 // R7: new object end address. 696 // R7: new object end address.
697 // R8: allocation size. 697 // R8: allocation size.
698 698
699 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); 699 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
700 __ mov(R5, Operand(R4)); 700 __ mov(R5, Operand(R4));
701 __ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag); 701 __ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag);
702 702 __ InitializeFieldsNoBarrier(R0, R6, R7, R4, R5);
703 Label init_loop;
704 __ Bind(&init_loop);
705 __ AddImmediate(R6, 2 * kWordSize);
706 __ cmp(R6, Operand(R7));
707 __ strd(R4, Address(R6, -2 * kWordSize), LS);
708 __ b(&init_loop, CC);
709 __ str(R4, Address(R6, -2 * kWordSize), HI);
710
711 __ IncrementAllocationStatsWithSize(R3, R8, cid, space); 703 __ IncrementAllocationStatsWithSize(R3, R8, cid, space);
712 __ Ret(); // Returns the newly allocated object in R0. 704 __ Ret(); // Returns the newly allocated object in R0.
713 // Unable to allocate the array using the fast inline code, just call 705 // Unable to allocate the array using the fast inline code, just call
714 // into the runtime. 706 // into the runtime.
715 __ Bind(&slow_case); 707 __ Bind(&slow_case);
716 708
717 // Create a stub frame as we are pushing some objects on the stack before 709 // Create a stub frame as we are pushing some objects on the stack before
718 // calling into the runtime. 710 // calling into the runtime.
719 __ EnterStubFrame(); 711 __ EnterStubFrame();
720 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 712 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 __ ldr(IP, Address(IP, 0)); 867 __ ldr(IP, Address(IP, 0));
876 __ cmp(R3, Operand(IP)); 868 __ cmp(R3, Operand(IP));
877 if (FLAG_use_slow_path) { 869 if (FLAG_use_slow_path) {
878 __ b(&slow_case); 870 __ b(&slow_case);
879 } else { 871 } else {
880 __ b(&slow_case, CS); // Branch if unsigned higher or equal. 872 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
881 } 873 }
882 874
883 // Successfully allocated the object, now update top to point to 875 // Successfully allocated the object, now update top to point to
884 // next object start and initialize the object. 876 // next object start and initialize the object.
885 // R0: new object. 877 // R0: new object start (untagged).
886 // R1: number of context variables. 878 // R1: number of context variables.
887 // R2: object size. 879 // R2: object size.
888 // R3: next object start. 880 // R3: next object start.
889 // R5: top address. 881 // R5: top address.
890 __ LoadAllocationStatsAddress(R4, cid, space); 882 __ LoadAllocationStatsAddress(R6, cid, space);
891 __ str(R3, Address(R5, 0)); 883 __ str(R3, Address(R5, 0));
892 __ add(R0, R0, Operand(kHeapObjectTag)); 884 __ add(R0, R0, Operand(kHeapObjectTag));
893 885
894 // Calculate the size tag. 886 // Calculate the size tag.
895 // R0: new object. 887 // R0: new object (tagged).
896 // R1: number of context variables. 888 // R1: number of context variables.
897 // R2: object size. 889 // R2: object size.
898 // R4: allocation stats address. 890 // R3: next object start.
891 // R6: allocation stats address.
899 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 892 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
900 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); 893 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
901 // If no size tag overflow, shift R2 left, else set R2 to zero. 894 // If no size tag overflow, shift R2 left, else set R2 to zero.
902 __ mov(R3, Operand(R2, LSL, shift), LS); 895 __ mov(R5, Operand(R2, LSL, shift), LS);
903 __ mov(R3, Operand(0), HI); 896 __ mov(R5, Operand(0), HI);
904 897
905 // Get the class index and insert it into the tags. 898 // Get the class index and insert it into the tags.
906 // R3: size and bit tags. 899 // R5: size and bit tags.
907 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(cid)); 900 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(cid));
908 __ orr(R3, R3, Operand(IP)); 901 __ orr(R5, R5, Operand(IP));
909 __ str(R3, FieldAddress(R0, Context::tags_offset())); 902 __ str(R5, FieldAddress(R0, Context::tags_offset()));
910 903
911 // Setup up number of context variables field. 904 // Setup up number of context variables field.
912 // R0: new object. 905 // R0: new object.
913 // R1: number of context variables as integer value (not object). 906 // R1: number of context variables as integer value (not object).
914 // R2: object size. 907 // R2: object size.
915 // R4: allocation stats address. 908 // R3: next object start.
909 // R6: allocation stats address.
916 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); 910 __ str(R1, FieldAddress(R0, Context::num_variables_offset()));
917 911
918 // Setup the parent field. 912 // Setup the parent field.
919 // R0: new object. 913 // R0: new object.
920 // R1: number of context variables. 914 // R1: number of context variables.
921 // R2: object size. 915 // R2: object size.
922 // R4: allocation stats address. 916 // R3: next object start.
923 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); 917 // R6: allocation stats address.
924 __ str(R3, FieldAddress(R0, Context::parent_offset())); 918 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
919 __ str(R4, FieldAddress(R0, Context::parent_offset()));
925 920
926 // Initialize the context variables. 921 // Initialize the context variables.
927 // R0: new object. 922 // R0: new object.
928 // R1: number of context variables. 923 // R1: number of context variables.
929 // R2: object size. 924 // R2: object size.
930 // R3: raw null. 925 // R3: next object start.
931 // R4: allocation stats address. 926 // R4, R5: raw null.
927 // R6: allocation stats address.
932 Label loop; 928 Label loop;
933 __ AddImmediate(R5, R0, Context::variable_offset(0) - kHeapObjectTag); 929 __ AddImmediate(R7, R0, Context::variable_offset(0) - kHeapObjectTag);
934 __ Bind(&loop); 930 __ InitializeFieldsNoBarrier(R0, R7, R3, R4, R5);
zra 2014/11/20 21:43:10 Keep an eye on benchmark numbers for any differenc
935 __ subs(R1, R1, Operand(1)); 931 __ IncrementAllocationStatsWithSize(R6, R2, cid, space);
936 __ str(R3, Address(R5, R1, LSL, 2), PL); // Store if R1 positive or zero.
937 __ b(&loop, NE); // Loop if R1 not zero.
938
939 __ IncrementAllocationStatsWithSize(R4, R2, cid, space);
940 932
941 // Done allocating and initializing the context. 933 // Done allocating and initializing the context.
942 // R0: new object. 934 // R0: new object.
943 __ Ret(); 935 __ Ret();
944 936
945 __ Bind(&slow_case); 937 __ Bind(&slow_case);
946 } 938 }
947 // Create a stub frame as we are pushing some objects on the stack before 939 // Create a stub frame as we are pushing some objects on the stack before
948 // calling into the runtime. 940 // calling into the runtime.
949 __ EnterStubFrame(); 941 __ EnterStubFrame();
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 const int kInlineInstanceSize = 12; 1052 const int kInlineInstanceSize = 12;
1061 const intptr_t instance_size = cls.instance_size(); 1053 const intptr_t instance_size = cls.instance_size();
1062 ASSERT(instance_size > 0); 1054 ASSERT(instance_size > 0);
1063 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { 1055 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
1064 Label slow_case; 1056 Label slow_case;
1065 // Allocate the object and update top to point to 1057 // Allocate the object and update top to point to
1066 // next object start and initialize the allocated object. 1058 // next object start and initialize the allocated object.
1067 Heap* heap = Isolate::Current()->heap(); 1059 Heap* heap = Isolate::Current()->heap();
1068 Heap::Space space = heap->SpaceForAllocation(cls.id()); 1060 Heap::Space space = heap->SpaceForAllocation(cls.id());
1069 __ LoadImmediate(R5, heap->TopAddress(space)); 1061 __ LoadImmediate(R5, heap->TopAddress(space));
1070 __ ldr(R2, Address(R5, 0)); 1062 __ ldr(R0, Address(R5, 0));
1071 __ AddImmediate(R3, R2, instance_size); 1063 __ AddImmediate(R1, R0, instance_size);
1072 // Check if the allocation fits into the remaining space. 1064 // Check if the allocation fits into the remaining space.
1073 // R2: potential new object start. 1065 // R0: potential new object start.
1074 // R3: potential next object start. 1066 // R1: potential next object start.
1075 __ LoadImmediate(IP, heap->EndAddress(space)); 1067 __ LoadImmediate(IP, heap->EndAddress(space));
1076 __ ldr(IP, Address(IP, 0)); 1068 __ ldr(IP, Address(IP, 0));
1077 __ cmp(R3, Operand(IP)); 1069 __ cmp(R1, Operand(IP));
1078 if (FLAG_use_slow_path) { 1070 if (FLAG_use_slow_path) {
1079 __ b(&slow_case); 1071 __ b(&slow_case);
1080 } else { 1072 } else {
1081 __ b(&slow_case, CS); // Unsigned higher or equal. 1073 __ b(&slow_case, CS); // Unsigned higher or equal.
1082 } 1074 }
1083 __ str(R3, Address(R5, 0)); 1075 __ str(R1, Address(R5, 0));
1084 1076
1085 // Load the address of the allocation stats table. We split up the load 1077 // Load the address of the allocation stats table. We split up the load
1086 // and the increment so that the dependent load is not too nearby. 1078 // and the increment so that the dependent load is not too nearby.
1087 __ LoadAllocationStatsAddress(R5, cls.id(), space); 1079 __ LoadAllocationStatsAddress(R5, cls.id(), space);
1088 1080
1089 // R2: new object start. 1081 // R0: new object start.
1090 // R3: next object start. 1082 // R1: next object start.
1091 // R5: allocation stats table. 1083 // R5: allocation stats table.
1092 // Set the tags. 1084 // Set the tags.
1093 uword tags = 0; 1085 uword tags = 0;
1094 tags = RawObject::SizeTag::update(instance_size, tags); 1086 tags = RawObject::SizeTag::update(instance_size, tags);
1095 ASSERT(cls.id() != kIllegalCid); 1087 ASSERT(cls.id() != kIllegalCid);
1096 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1088 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1097 __ LoadImmediate(R0, tags); 1089 __ LoadImmediate(R2, tags);
1098 __ str(R0, Address(R2, Instance::tags_offset())); 1090 __ str(R2, Address(R0, Instance::tags_offset()));
1091 __ add(R0, R0, Operand(kHeapObjectTag));
1099 1092
1100 // Initialize the remaining words of the object. 1093 // Initialize the remaining words of the object.
1101 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); 1094 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
1102 1095
1103 // R0: raw null. 1096 // R2: raw null.
1104 // R2: new object start. 1097 // R0: new object (tagged).
1105 // R3: next object start. 1098 // R1: next object start.
1106 // R5: allocation stats table. 1099 // R5: allocation stats table.
1107 // First try inlining the initialization without a loop. 1100 // First try inlining the initialization without a loop.
1108 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1101 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1109 // Check if the object contains any non-header fields. 1102 // Check if the object contains any non-header fields.
1110 // Small objects are initialized using a consecutive set of writes. 1103 // Small objects are initialized using a consecutive set of writes.
1111 intptr_t current_offset = Instance::NextFieldOffset(); 1104 intptr_t current_offset = Instance::NextFieldOffset();
1112 // Write two nulls at a time. 1105 // Write two nulls at a time.
1113 if (instance_size >= 2 * kWordSize) { 1106 if (instance_size >= 2 * kWordSize) {
1114 __ mov(R1, Operand(R0)); 1107 __ mov(R3, Operand(R2));
1115 while (current_offset + kWordSize < instance_size) { 1108 while (current_offset + kWordSize < instance_size) {
1116 __ StoreToOffset(kWordPair, R0, R2, current_offset); 1109 __ StoreToOffset(kWordPair, R2, R0, current_offset - kHeapObjectTag);
1117 current_offset += 2 * kWordSize; 1110 current_offset += 2 * kWordSize;
1118 } 1111 }
1119 } 1112 }
1120 // Write remainder. 1113 // Write remainder.
1121 while (current_offset < instance_size) { 1114 while (current_offset < instance_size) {
1122 __ StoreToOffset(kWord, R0, R2, current_offset); 1115 __ StoreToOffset(kWord, R2, R0, current_offset - kHeapObjectTag);
1123 current_offset += kWordSize; 1116 current_offset += kWordSize;
1124 } 1117 }
1125 } else { 1118 } else {
1126 // There are more than kInlineInstanceSize(12) fields 1119 // There are more than kInlineInstanceSize(12) fields
1127 __ add(R4, R2, Operand(Instance::NextFieldOffset())); 1120 __ add(R4, R0, Operand(Instance::NextFieldOffset() - kHeapObjectTag));
1128 __ mov(R1, Operand(R0)); 1121 __ mov(R3, Operand(R2));
1129 // Loop until the whole object is initialized. 1122 // Loop until the whole object is initialized.
1130 // R0: raw null. 1123 // R2: raw null.
1131 // R1: raw null. 1124 // R3: raw null.
1132 // R2: new object. 1125 // R0: new object (tagged).
1133 // R3: next object start. 1126 // R1: next object start.
1134 // R4: next word to be initialized. 1127 // R4: next word to be initialized.
1135 // R5: allocation stats table. 1128 // R5: allocation stats table.
1136 Label init_loop; 1129 __ InitializeFieldsNoBarrier(R0, R4, R1, R2, R3);
1137 __ Bind(&init_loop);
1138 __ AddImmediate(R4, 2 * kWordSize);
1139 __ cmp(R4, Operand(R3));
1140 __ strd(R0, Address(R4, -2 * kWordSize), LS);
1141 __ b(&init_loop, CC);
1142 __ str(R0, Address(R4, -2 * kWordSize), HI);
1143 } 1130 }
1144 if (is_cls_parameterized) { 1131 if (is_cls_parameterized) {
1145 // Set the type arguments in the new object. 1132 // Set the type arguments in the new object.
1146 __ ldr(R4, Address(SP, 0)); 1133 __ ldr(R4, Address(SP, 0));
1147 __ StoreToOffset(kWord, R4, R2, cls.type_arguments_field_offset()); 1134 __ StoreToOffset(kWord, R4,
1135 R0, cls.type_arguments_field_offset() - kHeapObjectTag);
1148 } 1136 }
1149 1137
1150 // Done allocating and initializing the instance. 1138 // Done allocating and initializing the instance.
1151 // R2: new object still missing its heap tag. 1139 // R0: new object (tagged).
1152 // R5: allocation stats table. 1140 // R5: allocation stats table.
1153 __ add(R0, R2, Operand(kHeapObjectTag));
1154 1141
1155 // Update allocation stats. 1142 // Update allocation stats.
1156 __ IncrementAllocationStats(R5, cls.id(), space); 1143 __ IncrementAllocationStats(R5, cls.id(), space);
1157 1144
1158 // R0: new object. 1145 // R0: new object (tagged).
1159 __ Ret(); 1146 __ Ret();
1160 1147
1161 __ Bind(&slow_case); 1148 __ Bind(&slow_case);
1162 } 1149 }
1163 if (is_cls_parameterized) { 1150 if (is_cls_parameterized) {
1164 // Load the type arguments. 1151 // Load the type arguments.
1165 __ ldr(R4, Address(SP, 0)); 1152 __ ldr(R4, Address(SP, 0));
1166 } 1153 }
1167 // If is_cls_parameterized: 1154 // If is_cls_parameterized:
1168 // R4: new object type arguments. 1155 // R4: new object type arguments.
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 const Register right = R0; 1976 const Register right = R0;
1990 __ ldr(left, Address(SP, 1 * kWordSize)); 1977 __ ldr(left, Address(SP, 1 * kWordSize));
1991 __ ldr(right, Address(SP, 0 * kWordSize)); 1978 __ ldr(right, Address(SP, 0 * kWordSize));
1992 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 1979 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
1993 __ Ret(); 1980 __ Ret();
1994 } 1981 }
1995 1982
1996 } // namespace dart 1983 } // namespace dart
1997 1984
1998 #endif // defined TARGET_ARCH_ARM 1985 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698