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

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

Issue 239303008: Adds object pool, LoadImmediate, and LoadObject to ARM64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 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/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
11 #include "vm/runtime_entry.h" 11 #include "vm/runtime_entry.h"
12 #include "vm/simulator.h" 12 #include "vm/simulator.h"
13 #include "vm/stack_frame.h" 13 #include "vm/stack_frame.h"
14 #include "vm/stub_code.h" 14 #include "vm/stub_code.h"
15 15
16 // An extra check since we are assuming the existence of /proc/cpuinfo below. 16 // An extra check since we are assuming the existence of /proc/cpuinfo below.
17 #if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID) 17 #if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID)
18 #error ARM64 cross-compile only supported on Linux 18 #error ARM64 cross-compile only supported on Linux
19 #endif 19 #endif
20 20
21 namespace dart { 21 namespace dart {
22 22
23 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); 23 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
24 DECLARE_FLAG(bool, inline_alloc); 24 DECLARE_FLAG(bool, inline_alloc);
25 25
26 26
27 Assembler::Assembler(bool use_far_branches)
28 : buffer_(),
29 object_pool_(GrowableObjectArray::Handle()),
30 patchable_pool_entries_(),
31 prologue_offset_(-1),
32 use_far_branches_(use_far_branches),
33 comments_() {
34 if (Isolate::Current() != Dart::vm_isolate()) {
35 object_pool_ = GrowableObjectArray::New(Heap::kOld);
36
37 // These objects and labels need to be accessible through every pool-pointer
38 // at the same index.
39 object_pool_.Add(Object::null_object(), Heap::kOld);
40 patchable_pool_entries_.Add(kNotPatchable);
41 // Not adding Object::null() to the index table. It is at index 0 in the
42 // object pool, but the HashMap uses 0 to indicate not found.
43
44 object_pool_.Add(Bool::True(), Heap::kOld);
45 patchable_pool_entries_.Add(kNotPatchable);
46 object_pool_index_table_.Insert(ObjIndexPair(Bool::True().raw(), 1));
47
48 object_pool_.Add(Bool::False(), Heap::kOld);
49 patchable_pool_entries_.Add(kNotPatchable);
50 object_pool_index_table_.Insert(ObjIndexPair(Bool::False().raw(), 2));
51 }
52 }
53
54
27 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { 55 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
28 ASSERT(Utils::IsAligned(data, 4)); 56 ASSERT(Utils::IsAligned(data, 4));
29 ASSERT(Utils::IsAligned(length, 4)); 57 ASSERT(Utils::IsAligned(length, 4));
30 const uword end = data + length; 58 const uword end = data + length;
31 while (data < end) { 59 while (data < end) {
32 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; 60 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction;
33 data += 4; 61 data += 4;
34 } 62 }
35 } 63 }
36 64
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 } 147 }
120 148
121 149
122 // Test if a given value can be encoded in the immediate field of a logical 150 // Test if a given value can be encoded in the immediate field of a logical
123 // instruction. 151 // instruction.
124 // If it can be encoded, the function returns true, and values pointed to by n, 152 // If it can be encoded, the function returns true, and values pointed to by n,
125 // imm_s and imm_r are updated with immediates encoded in the format required 153 // imm_s and imm_r are updated with immediates encoded in the format required
126 // by the corresponding fields in the logical instruction. 154 // by the corresponding fields in the logical instruction.
127 // If it can't be encoded, the function returns false, and the operand is 155 // If it can't be encoded, the function returns false, and the operand is
128 // undefined. 156 // undefined.
129 bool Assembler::IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op) { 157 bool Operand::IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op) {
130 ASSERT(imm_op != NULL); 158 ASSERT(imm_op != NULL);
131 ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits)); 159 ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits));
132 ASSERT((width == kXRegSizeInBits) || (value <= 0xffffffffUL)); 160 ASSERT((width == kXRegSizeInBits) || (value <= 0xffffffffUL));
133 uint8_t n = 0; 161 uint8_t n = 0;
134 uint8_t imm_s = 0; 162 uint8_t imm_s = 0;
135 uint8_t imm_r = 0; 163 uint8_t imm_r = 0;
136 164
137 // Logical immediates are encoded using parameters n, imm_s and imm_r using 165 // Logical immediates are encoded using parameters n, imm_s and imm_r using
138 // the following table: 166 // the following table:
139 // 167 //
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 set_bits >>= 1; 241 set_bits >>= 1;
214 imm_s_fixed >>= 1; 242 imm_s_fixed >>= 1;
215 continue; 243 continue;
216 } 244 }
217 245
218 // 6. Otherwise, the value can't be encoded. 246 // 6. Otherwise, the value can't be encoded.
219 return false; 247 return false;
220 } 248 }
221 } 249 }
222 250
251
252 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
253 uint32_t offset) {
254 ASSERT(dst != pp);
255 if (Address::CanHoldOffset(offset)) {
256 ldr(dst, Address(pp, offset));
257 } else {
258 const uint16_t offset_low = Utils::Low16Bits(offset);
259 const uint16_t offset_high = Utils::High16Bits(offset);
260 movz(dst, offset_low, 0);
261 if (offset_high != 0) {
262 movk(dst, offset_high, 1);
263 }
264 ldr(dst, Address(pp, dst));
265 }
266 }
267
268
269 intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) {
270 // The object pool cannot be used in the vm isolate.
271 ASSERT(Isolate::Current() != Dart::vm_isolate());
272 ASSERT(!object_pool_.IsNull());
273
274 // If the object is not patchable, check if we've already got it in the
275 // object pool.
276 if (patchable == kNotPatchable) {
277 // Special case for Object::null(), which is always at object_pool_ index 0
278 // because Lookup() below returns 0 when the object is not mapped in the
279 // table.
280 if (obj.raw() == Object::null()) {
281 return 0;
282 }
283
284 intptr_t idx = object_pool_index_table_.Lookup(obj.raw());
285 if (idx != 0) {
286 ASSERT(patchable_pool_entries_[idx] == kNotPatchable);
287 return idx;
288 }
289 }
290
291 object_pool_.Add(obj, Heap::kOld);
292 patchable_pool_entries_.Add(patchable);
293 if (patchable == kNotPatchable) {
294 // The object isn't patchable. Record the index for fast lookup.
295 object_pool_index_table_.Insert(
296 ObjIndexPair(obj.raw(), object_pool_.Length() - 1));
297 }
298 return object_pool_.Length() - 1;
299 }
300
301
302 intptr_t Assembler::FindImmediate(int64_t imm) {
303 ASSERT(Isolate::Current() != Dart::vm_isolate());
304 ASSERT(!object_pool_.IsNull());
305 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm));
306 return FindObject(smi, kNotPatchable);
307 }
308
309
310 bool Assembler::CanLoadObjectFromPool(const Object& object) {
311 // TODO(zra, kmillikin): Also load other large immediates from the object
312 // pool
313 if (object.IsSmi()) {
314 // If the raw smi does not fit into a 32-bit signed int, then we'll keep
315 // the raw value in the object pool.
316 return !Utils::IsInt(32, reinterpret_cast<int64_t>(object.raw()));
317 }
318 ASSERT(object.IsNotTemporaryScopedHandle());
319 ASSERT(object.IsOld());
320 return (Isolate::Current() != Dart::vm_isolate()) &&
321 // Not in the VMHeap, OR is one of the VMHeap objects we put in every
322 // object pool.
323 // TODO(zra): Evaluate putting all VM heap objects into the pool.
324 (!object.InVMHeap() || (object.raw() == Object::null()) ||
325 (object.raw() == Bool::True().raw()) ||
326 (object.raw() == Bool::False().raw()));
327 }
328
329
330 bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) {
331 return !Utils::IsInt(32, imm) &&
332 (pp != kNoRegister) &&
333 (Isolate::Current() != Dart::vm_isolate());
334 }
335
336
337 void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
338 if (CanLoadObjectFromPool(object)) {
339 const int32_t offset =
340 Array::element_offset(FindObject(object, kNotPatchable));
341 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
342 } else {
343 ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
344 object.IsSmi() ||
345 object.InVMHeap());
346 LoadImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
347 }
348 }
349
350
351 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) {
352 Comment("LoadImmediate");
353 if (CanLoadImmediateFromPool(imm, pp)) {
354 // It's a 64-bit constant and we're not in the VM isolate, so load from
355 // object pool.
356 // Save the bits that must be masked-off for the SmiTag
357 int64_t val_smi_tag = imm & kSmiTagMask;
358 imm &= ~kSmiTagMask; // Mask off the tag bits.
359 const int32_t offset = Array::element_offset(FindImmediate(imm));
360 LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag);
361 if (val_smi_tag != 0) {
362 // Add back the tag bits.
363 orri(reg, reg, val_smi_tag);
364 }
365 } else {
366 // 1. Can we use one orri operation?
367 Operand op;
368 Operand::OperandType ot;
369 ot = Operand::CanHold(imm, kXRegSizeInBits, &op);
370 if (ot == Operand::BitfieldImm) {
371 orri(reg, ZR, imm);
372 return;
373 }
374
375 // 2. Fall back on movz, movk, movn.
376 const uint32_t w0 = Utils::Low32Bits(imm);
377 const uint32_t w1 = Utils::High32Bits(imm);
378 const uint16_t h0 = Utils::Low16Bits(w0);
379 const uint16_t h1 = Utils::High16Bits(w0);
380 const uint16_t h2 = Utils::Low16Bits(w1);
381 const uint16_t h3 = Utils::High16Bits(w1);
382
383 // Special case for w1 == 0xffffffff
384 if (w1 == 0xffffffff) {
385 if (h1 == 0xffff) {
386 movn(reg, ~h0, 0);
387 } else {
388 movn(reg, ~h1, 1);
389 movk(reg, h0, 0);
390 }
391 return;
392 }
393
394 // Special case for h3 == 0xffff
395 if (h3 == 0xffff) {
396 // We know h2 != 0xffff.
397 movn(reg, ~h2, 2);
398 if (h1 != 0xffff) {
399 movk(reg, h1, 1);
400 }
401 if (h0 != 0xffff) {
402 movk(reg, h0, 0);
403 }
404 return;
405 }
406
407 bool initialized = false;
408 if (h0 != 0) {
409 movz(reg, h0, 0);
410 initialized = true;
411 }
412 if (h1 != 0) {
413 if (initialized) {
414 movk(reg, h1, 1);
415 } else {
416 movz(reg, h1, 1);
417 initialized = true;
418 }
419 }
420 if (h2 != 0) {
421 if (initialized) {
422 movk(reg, h2, 2);
423 } else {
424 movz(reg, h2, 2);
425 initialized = true;
426 }
427 }
428 if (h3 != 0) {
429 if (initialized) {
430 movk(reg, h3, 3);
431 } else {
432 movz(reg, h3, 3);
433 }
434 }
435 }
436 }
437
223 } // namespace dart 438 } // namespace dart
224 439
225 #endif // defined TARGET_ARCH_ARM64 440 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698