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

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

Issue 10657012: Intrinsify fixed and growable array allocation on x64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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 | « runtime/vm/intrinsifier_ia32.cc ('k') | runtime/vm/stub_code_ia32.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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intrinsifier.h" 8 #include "vm/intrinsifier.h"
9 9
10 #include "vm/assembler.h" 10 #include "vm/assembler.h"
11 #include "vm/instructions.h" 11 #include "vm/instructions.h"
12 #include "vm/object_store.h"
12 13
13 namespace dart { 14 namespace dart {
14 15
15 DECLARE_FLAG(bool, enable_type_checks); 16 DECLARE_FLAG(bool, enable_type_checks);
16 17
17 // When entering intrinsics code: 18 // When entering intrinsics code:
18 // RBX: IC Data 19 // RBX: IC Data
19 // R10: Arguments descriptor 20 // R10: Arguments descriptor
20 // TOS: Return address 21 // TOS: Return address
21 // The RBX, R10 registers can be destroyed only if there is no slow-path (i.e., 22 // The RBX, R10 registers can be destroyed only if there is no slow-path (i.e.,
22 // the methods returns true). 23 // the methods returns true).
23 24
24 #define __ assembler-> 25 #define __ assembler->
25 26
27
26 bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { 28 bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
29 // This snippet of inlined code uses the following registers:
30 // RAX, RCX, RDI, R13
31 // and the newly allocated object is returned in RAX.
32 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
33 const intptr_t kArrayLengthOffset = 1 * kWordSize;
34 Label fall_through;
35
36 // Compute the size to be allocated, it is based on the array length
37 // and is computed as:
38 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
39 __ movq(RDI, Address(RSP, kArrayLengthOffset)); // Array Length.
40 // Assert that length is a Smi.
41 __ testq(RDI, Immediate(kSmiTagSize));
42 __ j(NOT_ZERO, &fall_through);
43 __ cmpq(RDI, Immediate(0));
44 __ j(LESS, &fall_through);
45 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
46 __ leaq(RDI, Address(RDI, TIMES_4, fixed_size)); // RDI is a Smi.
47 ASSERT(kSmiTagShift == 1);
48 __ andq(RDI, Immediate(-kObjectAlignment));
49
50 Isolate* isolate = Isolate::Current();
51 Heap* heap = isolate->heap();
52
53 // RDI: allocation size.
54 __ movq(RAX, Immediate(heap->TopAddress()));
55 __ movq(RAX, Address(RAX, 0));
56 __ leaq(RCX, Address(RAX, RDI, TIMES_1, 0));
57
58 // Check if the allocation fits into the remaining space.
59 // RAX: potential new object start.
60 // RCX: potential next object start.
61 // RDI: allocation size.
62 __ movq(R13, Immediate(heap->TopAddress()));
63 __ cmpq(RCX, Address(R13, 0));
64 __ j(ABOVE_EQUAL, &fall_through);
65
66 // Successfully allocated the object(s), now update top to point to
67 // next object start and initialize the object.
68 __ movq(Address(R13, 0), RCX);
69 __ addq(RAX, Immediate(kHeapObjectTag));
70
71 // Initialize the tags.
72 // RAX: new object start as a tagged pointer.
73 // RCX: new object end address.
74 // RDI: allocation size.
75 {
76 Label size_tag_overflow, done;
77 __ cmpl(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
78 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
79 __ shlq(RDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2));
80 __ jmp(&done, Assembler::kNearJump);
81
82 __ Bind(&size_tag_overflow);
83 __ movq(RDI, Immediate(0));
84 __ Bind(&done);
85
86 // Get the class index and insert it into the tags.
87 const Class& cls = Class::Handle(isolate->object_store()->array_class());
88 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cls.id())));
89 __ movq(FieldAddress(RAX, Array::tags_offset()), RDI); // Tags.
90 }
91
92 // RAX: new object start as a tagged pointer.
93 // RCX: new object end address.
94 // Store the type argument field.
95 __ movl(RDI, Address(RSP, kTypeArgumentsOffset)); // type argument.
96 __ StoreIntoObjectNoBarrier(RAX,
97 FieldAddress(RAX, Array::type_arguments_offset()),
98 RDI);
99
100 // Set the length field.
101 __ movq(RDI, Address(RSP, kArrayLengthOffset)); // Array Length.
102 __ StoreIntoObjectNoBarrier(RAX,
103 FieldAddress(RAX, Array::length_offset()),
104 RDI);
105
106 // Initialize all array elements to raw_null.
107 // RAX: new object start as a tagged pointer.
108 // RCX: new object end address.
109 // RDI: iterator which initially points to the start of the variable
110 // data area to be initialized.
111 const Immediate raw_null =
112 Immediate(reinterpret_cast<intptr_t>(Object::null()));
113 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray)));
114 Label done;
115 Label init_loop;
116 __ Bind(&init_loop);
117 __ cmpq(RDI, RCX);
118 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
119 __ movq(Address(RDI, 0), raw_null);
120 __ addq(RDI, Immediate(kWordSize));
121 __ jmp(&init_loop, Assembler::kNearJump);
122 __ Bind(&done);
123 __ ret(); // returns the newly allocated object in RAX.
124
125 __ Bind(&fall_through);
27 return false; 126 return false;
28 } 127 }
29 128
30 129
31 bool Intrinsifier::Array_getLength(Assembler* assembler) { 130 bool Intrinsifier::Array_getLength(Assembler* assembler) {
32 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 131 __ movq(RAX, Address(RSP, + 1 * kWordSize));
33 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); 132 __ movq(RAX, FieldAddress(RAX, Array::length_offset()));
34 __ ret(); 133 __ ret();
35 return true; 134 return true;
36 } 135 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 __ StoreIntoObject(RAX, 184 __ StoreIntoObject(RAX,
86 FieldAddress(RAX, RCX, TIMES_4, sizeof(RawArray)), 185 FieldAddress(RAX, RCX, TIMES_4, sizeof(RawArray)),
87 RDX); 186 RDX);
88 // Caller is responsible of preserving the value if necessary. 187 // Caller is responsible of preserving the value if necessary.
89 __ ret(); 188 __ ret();
90 __ Bind(&fall_through); 189 __ Bind(&fall_through);
91 return false; 190 return false;
92 } 191 }
93 192
94 193
194 // Allocate a GrowableObjectArray using the backing array specified.
195 // On stack: type argument (+2), data (+1), return-address (+0).
95 bool Intrinsifier::GArray_Allocate(Assembler* assembler) { 196 bool Intrinsifier::GArray_Allocate(Assembler* assembler) {
197 // This snippet of inlined code uses the following registers:
198 // RAX, RCX, R13
199 // and the newly allocated object is returned in RAX.
200 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
201 const intptr_t kArrayOffset = 1 * kWordSize;
202 Label fall_through;
203
204 // Compute the size to be allocated, it is based on the array length
205 // and is computed as:
206 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) +
207 intptr_t fixed_size = GrowableObjectArray::InstanceSize();
208
209 Isolate* isolate = Isolate::Current();
210 Heap* heap = isolate->heap();
211
212 __ movq(RAX, Immediate(heap->TopAddress()));
213 __ movq(RAX, Address(RAX, 0));
214 __ leaq(RCX, Address(RAX, fixed_size));
215
216 // Check if the allocation fits into the remaining space.
217 // RAX: potential new backing array object start.
218 // RCX: potential next object start.
219 __ movq(R13, Immediate(heap->EndAddress()));
220 __ cmpq(RCX, Address(R13, 0));
221 __ j(ABOVE_EQUAL, &fall_through);
222
223 // Successfully allocated the object(s), now update top to point to
224 // next object start and initialize the object.
225 __ movq(R13, Immediate(heap->TopAddress()));
226 __ movq(Address(R13, 0), RCX);
227 __ addq(RAX, Immediate(kHeapObjectTag));
228
229 // Initialize the tags.
230 // EAX: new growable array object start as a tagged pointer.
231 const Class& cls = Class::Handle(
232 isolate->object_store()->growable_object_array_class());
233 uword tags = 0;
234 tags = RawObject::SizeTag::update(fixed_size, tags);
235 tags = RawObject::ClassIdTag::update(cls.id(), tags);
236 __ movq(FieldAddress(RAX, GrowableObjectArray::tags_offset()),
237 Immediate(tags));
238
239 // Store backing array object in growable array object.
240 __ movq(RCX, Address(RSP, kArrayOffset)); // data argument.
241 __ StoreIntoObject(RAX,
242 FieldAddress(RAX, GrowableObjectArray::data_offset()),
243 RCX);
244
245 // RAX: new growable array object start as a tagged pointer.
246 // Store the type argument field in the growable array object.
247 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); // type argument.
248 __ StoreIntoObjectNoBarrier(
249 RAX,
250 FieldAddress(RAX, GrowableObjectArray::type_arguments_offset()),
251 RCX);
252
253 // Set the length field in the growable array object to 0.
254 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()),
255 Immediate(0));
256 __ ret(); // returns the newly allocated object in RAX.
257
258 __ Bind(&fall_through);
96 return false; 259 return false;
97 } 260 }
98 261
99 262
100 // Get length of growable object array. 263 // Get length of growable object array.
101 // On stack: growable array (+1), return-address (+0). 264 // On stack: growable array (+1), return-address (+0).
102 bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) { 265 bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
103 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 266 __ movq(RAX, Address(RSP, + 1 * kWordSize));
104 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset())); 267 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
105 __ ret(); 268 __ ret();
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 772
610 bool Intrinsifier::String_isEmpty(Assembler* assembler) { 773 bool Intrinsifier::String_isEmpty(Assembler* assembler) {
611 return false; 774 return false;
612 } 775 }
613 776
614 #undef __ 777 #undef __
615 778
616 } // namespace dart 779 } // namespace dart
617 780
618 #endif // defined TARGET_ARCH_X64 781 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_ia32.cc ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698