diff --git a/runtime/vm/instructions.cc b/runtime/vm/instructions.cc new file mode 100644 index 00000000000..b265420a148 --- /dev/null +++ b/runtime/vm/instructions.cc @@ -0,0 +1,41 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "vm/instructions.h" + +#include "vm/object.h" +#if defined(DART_PRECOMPILER) +#include "vm/compiler/aot/precompiler.h" +#endif + +namespace dart { + +bool ObjectAtPoolIndex(const Code& code, intptr_t index, Object* obj) { +#if defined(DART_PRECOMPILER) + if (FLAG_precompiled_mode) { + Precompiler* precompiler = Precompiler::Instance(); + if (precompiler != nullptr) { + compiler::ObjectPoolBuilder* pool = + precompiler->global_object_pool_builder(); + if (index < pool->CurrentLength()) { + compiler::ObjectPoolBuilderEntry& entry = pool->EntryAt(index); + if (entry.type() == compiler::ObjectPoolBuilderEntry::kTaggedObject) { + *obj = entry.obj_->ptr(); + return true; + } + } + } + return false; + } +#endif + const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); + if (!pool.IsNull() && (index < pool.Length()) && + (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { + *obj = pool.ObjectAt(index); + return true; + } + return false; +} + +} // namespace dart diff --git a/runtime/vm/instructions.h b/runtime/vm/instructions.h index 5dbe5d69841..3ddb87d115b 100644 --- a/runtime/vm/instructions.h +++ b/runtime/vm/instructions.h @@ -26,6 +26,7 @@ namespace dart { class Object; class Code; +bool ObjectAtPoolIndex(const Code& code, intptr_t index, Object* obj); bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj); #if !defined(TARGET_ARCH_IA32) diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc index ecacd45abd8..9a3f92fc94d 100644 --- a/runtime/vm/instructions_arm.cc +++ b/runtime/vm/instructions_arm.cc @@ -197,12 +197,7 @@ bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { Register dst; if (IsLoadWithOffset(instr, PP, &offset, &dst)) { intptr_t index = ObjectPool::IndexFromOffset(offset); - const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); - if (!pool.IsNull() && (index < pool.Length()) && - (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { - *obj = pool.ObjectAt(index); - return true; - } + return ObjectAtPoolIndex(code, index, obj); } else if (IsLoadWithOffset(instr, THR, &offset, &dst)) { return Thread::ObjectAtOffset(offset, obj); } diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc index 0c64963e703..d78c779fab3 100644 --- a/runtime/vm/instructions_arm64.cc +++ b/runtime/vm/instructions_arm64.cc @@ -304,17 +304,27 @@ bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { // PP is untagged on ARM64. ASSERT(Utils::IsAligned(offset, 8)); intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag); - const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); - if (!pool.IsNull() && (index < pool.Length()) && - (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { - *obj = pool.ObjectAt(index); - return true; - } + return ObjectAtPoolIndex(code, index, obj); } else if (instr->RnField() == THR) { return Thread::ObjectAtOffset(offset, obj); } + if (instr->RnField() == instr->RtField()) { + Instr* add = Instr::At(pc - Instr::kInstrSize); + if (add->IsAddSubImmOp() && add->SFField() && (instr->Bit(22) == 1) && + (add->RdField() == add->RtField())) { + offset = (add->Imm12Field() << 12) + offset; + if (add->RnField() == PP) { + // PP is untagged on ARM64. + ASSERT(Utils::IsAligned(offset, 8)); + intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag); + return ObjectAtPoolIndex(code, index, obj); + } else if (add->RnField() == THR) { + return Thread::ObjectAtOffset(offset, obj); + } + } + } + // TODO(rmacnak): Loads with offsets beyond 24 bits. } - // TODO(rmacnak): Loads with offsets beyond 12 bits. if (instr->IsAddSubImmOp() && instr->SFField() && (instr->RnField() == NULL_REG)) { diff --git a/runtime/vm/instructions_riscv.cc b/runtime/vm/instructions_riscv.cc index cabe480f5af..3a7d2a86508 100644 --- a/runtime/vm/instructions_riscv.cc +++ b/runtime/vm/instructions_riscv.cc @@ -231,12 +231,7 @@ bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { return false; // Being used as argument register A5. } intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag); - const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); - if (!pool.IsNull() && (index < pool.Length()) && - (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { - *obj = pool.ObjectAt(index); - return true; - } + return ObjectAtPoolIndex(code, index, obj); } else if (instr.rs1p() == THR) { return Thread::ObjectAtOffset(offset, obj); } @@ -255,12 +250,7 @@ bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { return false; // Being used as argument register A5. } intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag); - const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); - if (!pool.IsNull() && (index < pool.Length()) && - (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { - *obj = pool.ObjectAt(index); - return true; - } + return ObjectAtPoolIndex(code, index, obj); } else if (instr.rs1() == THR) { return Thread::ObjectAtOffset(offset, obj); } diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc index 30d7ed7a50c..e2a6403c0d1 100644 --- a/runtime/vm/instructions_x64.cc +++ b/runtime/vm/instructions_x64.cc @@ -59,21 +59,11 @@ bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) { // movq, cmpq if ((bytes[2] & 0xc7) == (0x80 | (PP & 7))) { // [r15+disp32] intptr_t index = IndexFromPPLoadDisp32(pc + 3); - const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); - if (!pool.IsNull() && (index < pool.Length()) && - (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { - *obj = pool.ObjectAt(index); - return true; - } + return ObjectAtPoolIndex(code, index, obj); } if ((bytes[2] & 0xc7) == (0x40 | (PP & 7))) { // [r15+disp8] intptr_t index = IndexFromPPLoadDisp8(pc + 3); - const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool()); - if (!pool.IsNull() && (index < pool.Length()) && - (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) { - *obj = pool.ObjectAt(index); - return true; - } + return ObjectAtPoolIndex(code, index, obj); } } } diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni index 0a2264ae127..b7a9c01a9ae 100644 --- a/runtime/vm/vm_sources.gni +++ b/runtime/vm/vm_sources.gni @@ -126,6 +126,7 @@ vm_sources = [ "hash_table.h", "image_snapshot.cc", "image_snapshot.h", + "instructions.cc", "instructions.h", "instructions_arm.cc", "instructions_arm.h",