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

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

Issue 241573002: Code patching for 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"
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 const uint16_t offset_high = Utils::High16Bits(offset); 267 const uint16_t offset_high = Utils::High16Bits(offset);
268 movz(dst, offset_low, 0); 268 movz(dst, offset_low, 0);
269 if (offset_high != 0) { 269 if (offset_high != 0) {
270 movk(dst, offset_high, 1); 270 movk(dst, offset_high, 1);
271 } 271 }
272 ldr(dst, Address(pp, dst)); 272 ldr(dst, Address(pp, dst));
273 } 273 }
274 } 274 }
275 275
276 276
277 intptr_t Assembler::FindExternalLabel(const ExternalLabel* label,
278 Patchability patchable) {
279 // The object pool cannot be used in the vm isolate.
280 ASSERT(Isolate::Current() != Dart::vm_isolate());
281 ASSERT(!object_pool_.IsNull());
282 const uword address = label->address();
283 ASSERT(Utils::IsAligned(address, 4));
284 // The address is stored in the object array as a RawSmi.
285 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address));
286 if (patchable == kNotPatchable) {
287 // If the call site is not patchable, we can try to re-use an existing
288 // entry.
289 return FindObject(smi, kNotPatchable);
290 }
291 // If the call is patchable, do not reuse an existing entry since each
292 // reference may be patched independently.
293 object_pool_.Add(smi, Heap::kOld);
294 patchable_pool_entries_.Add(patchable);
295 return object_pool_.Length() - 1;
296 }
297
298
277 intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) { 299 intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) {
278 // The object pool cannot be used in the vm isolate. 300 // The object pool cannot be used in the vm isolate.
279 ASSERT(Isolate::Current() != Dart::vm_isolate()); 301 ASSERT(Isolate::Current() != Dart::vm_isolate());
280 ASSERT(!object_pool_.IsNull()); 302 ASSERT(!object_pool_.IsNull());
281 303
282 // If the object is not patchable, check if we've already got it in the 304 // If the object is not patchable, check if we've already got it in the
283 // object pool. 305 // object pool.
284 if (patchable == kNotPatchable) { 306 if (patchable == kNotPatchable) {
285 // Special case for Object::null(), which is always at object_pool_ index 0 307 // Special case for Object::null(), which is always at object_pool_ index 0
286 // because Lookup() below returns 0 when the object is not mapped in the 308 // because Lookup() below returns 0 when the object is not mapped in the
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 } 357 }
336 358
337 359
338 bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) { 360 bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) {
339 return !Utils::IsInt(32, imm) && 361 return !Utils::IsInt(32, imm) &&
340 (pp != kNoRegister) && 362 (pp != kNoRegister) &&
341 (Isolate::Current() != Dart::vm_isolate()); 363 (Isolate::Current() != Dart::vm_isolate());
342 } 364 }
343 365
344 366
367 void Assembler::LoadExternalLabel(Register dst,
368 const ExternalLabel* label,
369 Patchability patchable,
370 Register pp) {
371 const int32_t offset =
372 Array::element_offset(FindExternalLabel(label, patchable));
373 LoadWordFromPoolOffset(dst, pp, offset);
374 }
375
376
345 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { 377 void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
346 if (CanLoadObjectFromPool(object)) { 378 if (CanLoadObjectFromPool(object)) {
347 const int32_t offset = 379 const int32_t offset =
348 Array::element_offset(FindObject(object, kNotPatchable)); 380 Array::element_offset(FindObject(object, kNotPatchable));
349 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); 381 LoadWordFromPoolOffset(dst, pp, offset);
350 } else { 382 } else {
351 ASSERT((Isolate::Current() == Dart::vm_isolate()) || 383 ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
352 object.IsSmi() || 384 object.IsSmi() ||
353 object.InVMHeap()); 385 object.InVMHeap());
354 LoadImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); 386 LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
355 } 387 }
356 } 388 }
357 389
358 390
391 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) {
392 if ((pp != kNoRegister) && (Isolate::Current() != Dart::vm_isolate())) {
393 int64_t val_smi_tag = imm & kSmiTagMask;
394 imm &= ~kSmiTagMask; // Mask off the tag bits.
395 const int32_t offset = Array::element_offset(FindImmediate(imm));
396 LoadWordFromPoolOffset(reg, pp, offset);
397 if (val_smi_tag != 0) {
398 // Add back the tag bits.
399 orri(reg, reg, val_smi_tag);
400 }
401 } else {
402 // TODO(zra): Since this sequence only needs to be decodable, it can be
403 // of variable length.
404 LoadPatchableImmediate(reg, imm);
405 }
406 }
407
408
409 void Assembler::LoadPatchableImmediate(Register reg, int64_t imm) {
410 const uint32_t w0 = Utils::Low32Bits(imm);
411 const uint32_t w1 = Utils::High32Bits(imm);
412 const uint16_t h0 = Utils::Low16Bits(w0);
413 const uint16_t h1 = Utils::High16Bits(w0);
414 const uint16_t h2 = Utils::Low16Bits(w1);
415 const uint16_t h3 = Utils::High16Bits(w1);
416 movz(reg, h0, 0);
417 movk(reg, h1, 1);
418 movk(reg, h2, 2);
419 movk(reg, h3, 3);
420 }
421
422
359 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { 423 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) {
360 Comment("LoadImmediate"); 424 Comment("LoadImmediate");
361 if (CanLoadImmediateFromPool(imm, pp)) { 425 if (CanLoadImmediateFromPool(imm, pp)) {
362 // It's a 64-bit constant and we're not in the VM isolate, so load from 426 // It's a 64-bit constant and we're not in the VM isolate, so load from
363 // object pool. 427 // object pool.
364 // Save the bits that must be masked-off for the SmiTag 428 // Save the bits that must be masked-off for the SmiTag
365 int64_t val_smi_tag = imm & kSmiTagMask; 429 int64_t val_smi_tag = imm & kSmiTagMask;
366 imm &= ~kSmiTagMask; // Mask off the tag bits. 430 imm &= ~kSmiTagMask; // Mask off the tag bits.
367 const int32_t offset = Array::element_offset(FindImmediate(imm)); 431 const int32_t offset = Array::element_offset(FindImmediate(imm));
368 LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); 432 LoadWordFromPoolOffset(reg, pp, offset);
369 if (val_smi_tag != 0) { 433 if (val_smi_tag != 0) {
370 // Add back the tag bits. 434 // Add back the tag bits.
371 orri(reg, reg, val_smi_tag); 435 orri(reg, reg, val_smi_tag);
372 } 436 }
373 } else { 437 } else {
374 // 1. Can we use one orri operation? 438 // 1. Can we use one orri operation?
375 Operand op; 439 Operand op;
376 Operand::OperandType ot; 440 Operand::OperandType ot;
377 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); 441 ot = Operand::CanHold(imm, kXRegSizeInBits, &op);
378 if (ot == Operand::BitfieldImm) { 442 if (ot == Operand::BitfieldImm) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 } else { 503 } else {
440 movz(reg, h3, 3); 504 movz(reg, h3, 3);
441 } 505 }
442 } 506 }
443 } 507 }
444 } 508 }
445 509
446 } // namespace dart 510 } // namespace dart
447 511
448 #endif // defined TARGET_ARCH_ARM64 512 #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