summaryrefslogtreecommitdiff
path: root/compiler/utils/assembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/assembler.h')
-rw-r--r--compiler/utils/assembler.h64
1 files changed, 43 insertions, 21 deletions
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index 1dbc142391..80aa630424 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -21,17 +21,20 @@
#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
+#include "arm/constants_arm.h"
+#include "base/arena_allocator.h"
+#include "base/arena_object.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "arm/constants_arm.h"
+#include "debug/dwarf/debug_frame_opcode_writer.h"
#include "label.h"
#include "managed_register.h"
#include "memory_region.h"
#include "mips/constants_mips.h"
#include "offsets.h"
+#include "utils/array_ref.h"
#include "x86/constants_x86.h"
#include "x86_64/constants_x86_64.h"
-#include "dwarf/debug_frame_opcode_writer.h"
namespace art {
@@ -60,7 +63,7 @@ class AssemblerFixup {
};
// Parent of all queued slow paths, emitted during finalization
-class SlowPath {
+class SlowPath : public DeletableArenaObject<kArenaAllocAssembler> {
public:
SlowPath() : next_(nullptr) {}
virtual ~SlowPath() {}
@@ -85,9 +88,13 @@ class SlowPath {
class AssemblerBuffer {
public:
- AssemblerBuffer();
+ explicit AssemblerBuffer(ArenaAllocator* arena);
~AssemblerBuffer();
+ ArenaAllocator* GetArena() {
+ return arena_;
+ }
+
// Basic support for emitting, loading, and storing.
template<typename T> void Emit(T value) {
CHECK(HasEnsuredCapacity());
@@ -172,8 +179,8 @@ class AssemblerBuffer {
class EnsureCapacity {
public:
explicit EnsureCapacity(AssemblerBuffer* buffer) {
- if (buffer->cursor() >= buffer->limit()) {
- buffer->ExtendCapacity();
+ if (buffer->cursor() > buffer->limit()) {
+ buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
}
// In debug mode, we save the assembler buffer along with the gap
// size before we start emitting to the buffer. This allows us to
@@ -213,7 +220,9 @@ class AssemblerBuffer {
class EnsureCapacity {
public:
explicit EnsureCapacity(AssemblerBuffer* buffer) {
- if (buffer->cursor() >= buffer->limit()) buffer->ExtendCapacity();
+ if (buffer->cursor() > buffer->limit()) {
+ buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
+ }
}
};
@@ -227,7 +236,14 @@ class AssemblerBuffer {
// Returns the position in the instruction stream.
int GetPosition() { return cursor_ - contents_; }
- void ExtendCapacity(size_t min_capacity = 0u);
+ size_t Capacity() const {
+ CHECK_GE(limit_, contents_);
+ return (limit_ - contents_) + kMinimumGap;
+ }
+
+ // Unconditionally increase the capacity.
+ // The provided `min_capacity` must be higher than current `Capacity()`.
+ void ExtendCapacity(size_t min_capacity);
private:
// The limit is set to kMinimumGap bytes before the end of the data area.
@@ -235,6 +251,7 @@ class AssemblerBuffer {
// for a single, fast space check per instruction.
static const int kMinimumGap = 32;
+ ArenaAllocator* arena_;
uint8_t* contents_;
uint8_t* cursor_;
uint8_t* limit_;
@@ -248,10 +265,6 @@ class AssemblerBuffer {
uint8_t* cursor() const { return cursor_; }
uint8_t* limit() const { return limit_; }
- size_t Capacity() const {
- CHECK_GE(limit_, contents_);
- return (limit_ - contents_) + kMinimumGap;
- }
// Process the fixup chain starting at the given fixup. The offset is
// non-zero for fixups in the body if the preamble is non-empty.
@@ -299,8 +312,10 @@ class DebugFrameOpCodeWriterForAssembler FINAL
// Override the last delayed PC. The new PC can be out of order.
void OverrideDelayedPC(size_t pc) {
DCHECK(delay_emitting_advance_pc_);
- DCHECK(!delayed_advance_pcs_.empty());
- delayed_advance_pcs_.back().pc = pc;
+ if (enabled_) {
+ DCHECK(!delayed_advance_pcs_.empty());
+ delayed_advance_pcs_.back().pc = pc;
+ }
}
// Return the number of delayed advance PC entries.
@@ -338,10 +353,12 @@ class DebugFrameOpCodeWriterForAssembler FINAL
std::vector<DelayedAdvancePC> delayed_advance_pcs_;
};
-class Assembler {
+class Assembler : public DeletableArenaObject<kArenaAllocAssembler> {
public:
- static Assembler* Create(InstructionSet instruction_set,
- const InstructionSetFeatures* instruction_set_features = nullptr);
+ static std::unique_ptr<Assembler> Create(
+ ArenaAllocator* arena,
+ InstructionSet instruction_set,
+ const InstructionSetFeatures* instruction_set_features = nullptr);
// Finalize the code; emit slow paths, fixup branches, add literal pool, etc.
virtual void FinalizeCode() { buffer_.EmitSlowPaths(this); }
@@ -359,13 +376,14 @@ class Assembler {
virtual void Comment(const char* format ATTRIBUTE_UNUSED, ...) {}
// Emit code that will create an activation on the stack
- virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ virtual void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) = 0;
// Emit code that will remove an activation from the stack
virtual void RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) = 0;
+ ArrayRef<const ManagedRegister> callee_save_regs) = 0;
virtual void IncreaseFrameSize(size_t adjust) = 0;
virtual void DecreaseFrameSize(size_t adjust) = 0;
@@ -504,7 +522,11 @@ class Assembler {
DebugFrameOpCodeWriterForAssembler& cfi() { return cfi_; }
protected:
- Assembler() : buffer_(), cfi_(this) {}
+ explicit Assembler(ArenaAllocator* arena) : buffer_(arena), cfi_(this) {}
+
+ ArenaAllocator* GetArena() {
+ return buffer_.GetArena();
+ }
AssemblerBuffer buffer_;