| OLD | NEW |
| 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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
| 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 13 matching lines...) Expand all Loading... |
| 24 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); | 24 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); |
| 25 DECLARE_FLAG(bool, inline_alloc); | 25 DECLARE_FLAG(bool, inline_alloc); |
| 26 | 26 |
| 27 | 27 |
| 28 Assembler::Assembler(bool use_far_branches) | 28 Assembler::Assembler(bool use_far_branches) |
| 29 : buffer_(), | 29 : buffer_(), |
| 30 prologue_offset_(-1), | 30 prologue_offset_(-1), |
| 31 use_far_branches_(use_far_branches), | 31 use_far_branches_(use_far_branches), |
| 32 comments_(), | 32 comments_(), |
| 33 allow_constant_pool_(true) { | 33 allow_constant_pool_(true) { |
| 34 if (Isolate::Current() != Dart::vm_isolate()) { | |
| 35 // These objects and labels need to be accessible through every pool-pointer | |
| 36 // at the same index. | |
| 37 intptr_t index = | |
| 38 object_pool_wrapper_.AddObject(Object::null_object()); | |
| 39 ASSERT(index == 0); | |
| 40 | |
| 41 index = object_pool_wrapper_.AddObject(Bool::True()); | |
| 42 ASSERT(index == 1); | |
| 43 | |
| 44 index = object_pool_wrapper_.AddObject(Bool::False()); | |
| 45 ASSERT(index == 2); | |
| 46 | |
| 47 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); | |
| 48 StubCode* stub_code = Isolate::Current()->stub_code(); | |
| 49 if (stub_code->UpdateStoreBuffer_entry() != NULL) { | |
| 50 object_pool_wrapper_.AddExternalLabel( | |
| 51 &stub_code->UpdateStoreBufferLabel(), kNotPatchable); | |
| 52 } else { | |
| 53 object_pool_wrapper_.AddObject(vacant); | |
| 54 } | |
| 55 } | |
| 56 } | 34 } |
| 57 | 35 |
| 58 | 36 |
| 59 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 37 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
| 60 ASSERT(Utils::IsAligned(data, 4)); | 38 ASSERT(Utils::IsAligned(data, 4)); |
| 61 ASSERT(Utils::IsAligned(length, 4)); | 39 ASSERT(Utils::IsAligned(length, 4)); |
| 62 const uword end = data + length; | 40 const uword end = data + length; |
| 63 while (data < end) { | 41 while (data < end) { |
| 64 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; | 42 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; |
| 65 data += 4; | 43 data += 4; |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 ldr(dst, Address(dst, lower12)); | 358 ldr(dst, Address(dst, lower12)); |
| 381 } | 359 } |
| 382 | 360 |
| 383 | 361 |
| 384 intptr_t Assembler::FindImmediate(int64_t imm) { | 362 intptr_t Assembler::FindImmediate(int64_t imm) { |
| 385 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 363 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 386 return object_pool_wrapper_.FindImmediate(imm); | 364 return object_pool_wrapper_.FindImmediate(imm); |
| 387 } | 365 } |
| 388 | 366 |
| 389 | 367 |
| 390 // A set of VM objects that are present in every constant pool. | 368 bool Assembler::CanLoadFromObjectPool(const Object& object) const { |
| 391 static bool IsAlwaysInConstantPool(const Object& object) { | 369 ASSERT(!Thread::CanLoadFromThread(object)); |
| 392 // TODO(zra): Evaluate putting all VM heap objects into the pool. | |
| 393 return (object.raw() == Object::null()) | |
| 394 || (object.raw() == Bool::True().raw()) | |
| 395 || (object.raw() == Bool::False().raw()); | |
| 396 } | |
| 397 | |
| 398 | |
| 399 bool Assembler::CanLoadObjectFromPool(const Object& object) { | |
| 400 if (!allow_constant_pool()) { | 370 if (!allow_constant_pool()) { |
| 401 return IsAlwaysInConstantPool(object); | 371 return false; |
| 402 } | 372 } |
| 403 | 373 |
| 404 // TODO(zra, kmillikin): Also load other large immediates from the object | 374 // TODO(zra, kmillikin): Also load other large immediates from the object |
| 405 // pool | 375 // pool |
| 406 if (object.IsSmi()) { | 376 if (object.IsSmi()) { |
| 407 // If the raw smi does not fit into a 32-bit signed int, then we'll keep | 377 // If the raw smi does not fit into a 32-bit signed int, then we'll keep |
| 408 // the raw value in the object pool. | 378 // the raw value in the object pool. |
| 409 return !Utils::IsInt(32, reinterpret_cast<int64_t>(object.raw())); | 379 return !Utils::IsInt(32, reinterpret_cast<int64_t>(object.raw())); |
| 410 } | 380 } |
| 411 ASSERT(object.IsNotTemporaryScopedHandle()); | 381 ASSERT(object.IsNotTemporaryScopedHandle()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 LoadWordFromPoolOffsetFixed(dst, pp, offset); | 421 LoadWordFromPoolOffsetFixed(dst, pp, offset); |
| 452 } | 422 } |
| 453 | 423 |
| 454 | 424 |
| 455 void Assembler::LoadIsolate(Register dst, Register pp) { | 425 void Assembler::LoadIsolate(Register dst, Register pp) { |
| 456 ldr(dst, Address(THR, Thread::isolate_offset())); | 426 ldr(dst, Address(THR, Thread::isolate_offset())); |
| 457 } | 427 } |
| 458 | 428 |
| 459 | 429 |
| 460 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { | 430 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { |
| 461 if (CanLoadObjectFromPool(object)) { | 431 if (Thread::CanLoadFromThread(object)) { |
| 432 ldr(dst, Address(THR, Thread::OffsetFromThread(object))); |
| 433 } else if (CanLoadFromObjectPool(object)) { |
| 462 const int32_t offset = | 434 const int32_t offset = |
| 463 ObjectPool::element_offset(object_pool_wrapper_.FindObject(object)); | 435 ObjectPool::element_offset(object_pool_wrapper_.FindObject(object)); |
| 464 LoadWordFromPoolOffset(dst, pp, offset); | 436 LoadWordFromPoolOffset(dst, pp, offset); |
| 465 } else { | 437 } else { |
| 466 ASSERT((Isolate::Current() == Dart::vm_isolate()) || | 438 ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
| 467 object.IsSmi() || | 439 object.IsSmi() || |
| 468 object.InVMHeap()); | 440 object.InVMHeap()); |
| 469 LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); | 441 LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); |
| 470 } | 442 } |
| 471 } | 443 } |
| 472 | 444 |
| 473 | 445 |
| 474 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { | 446 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { |
| 475 if (CanLoadObjectFromPool(object)) { | 447 if (Thread::CanLoadFromThread(object)) { |
| 448 ldr(TMP, Address(THR, Thread::OffsetFromThread(object))); |
| 449 CompareRegisters(reg, TMP); |
| 450 } else if (CanLoadFromObjectPool(object)) { |
| 476 LoadObject(TMP, object, pp); | 451 LoadObject(TMP, object, pp); |
| 477 CompareRegisters(reg, TMP); | 452 CompareRegisters(reg, TMP); |
| 478 } else { | 453 } else { |
| 479 CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()), pp); | 454 CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()), pp); |
| 480 } | 455 } |
| 481 } | 456 } |
| 482 | 457 |
| 483 | 458 |
| 484 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { | 459 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { |
| 485 if ((pp != kNoPP) && | 460 if ((pp != kNoPP) && |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 } | 883 } |
| 909 // A store buffer update is required. | 884 // A store buffer update is required. |
| 910 if (value != R0) { | 885 if (value != R0) { |
| 911 // Preserve R0. | 886 // Preserve R0. |
| 912 Push(R0); | 887 Push(R0); |
| 913 } | 888 } |
| 914 Push(LR); | 889 Push(LR); |
| 915 if (object != R0) { | 890 if (object != R0) { |
| 916 mov(R0, object); | 891 mov(R0, object); |
| 917 } | 892 } |
| 918 StubCode* stub_code = Isolate::Current()->stub_code(); | 893 ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset())); |
| 919 BranchLink(&stub_code->UpdateStoreBufferLabel(), PP); | 894 blr(TMP); |
| 920 Pop(LR); | 895 Pop(LR); |
| 921 if (value != R0) { | 896 if (value != R0) { |
| 922 // Restore R0. | 897 // Restore R0. |
| 923 Pop(R0); | 898 Pop(R0); |
| 924 } | 899 } |
| 925 Bind(&done); | 900 Bind(&done); |
| 926 } | 901 } |
| 927 | 902 |
| 928 | 903 |
| 929 void Assembler::StoreIntoObjectNoBarrier(Register object, | 904 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1457 add(base, array, Operand(index, LSL, shift)); | 1432 add(base, array, Operand(index, LSL, shift)); |
| 1458 } | 1433 } |
| 1459 const OperandSize size = Address::OperandSizeFor(cid); | 1434 const OperandSize size = Address::OperandSizeFor(cid); |
| 1460 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); | 1435 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); |
| 1461 return Address(base, offset, Address::Offset, size); | 1436 return Address(base, offset, Address::Offset, size); |
| 1462 } | 1437 } |
| 1463 | 1438 |
| 1464 } // namespace dart | 1439 } // namespace dart |
| 1465 | 1440 |
| 1466 #endif // defined TARGET_ARCH_ARM64 | 1441 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |