Thumb2: Fix EmitJumpTables() to extend buffer only if needed.
Bug: 28256882
Change-Id: I15227535c0fcb73c04b0b05160852c4b1bebee49
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 26f7d0d..2c73fb8 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -256,7 +256,10 @@
for (JumpTable& table : jump_tables_) {
// Bulk ensure capacity, as this may be large.
size_t orig_size = buffer_.Size();
- buffer_.ExtendCapacity(orig_size + table.GetSize());
+ size_t required_capacity = orig_size + table.GetSize();
+ if (required_capacity > buffer_.Capacity()) {
+ buffer_.ExtendCapacity(required_capacity);
+ }
#ifndef NDEBUG
buffer_.has_ensured_capacity_ = true;
#endif
diff --git a/compiler/utils/assembler.cc b/compiler/utils/assembler.cc
index c2aa574..e6c3a18 100644
--- a/compiler/utils/assembler.cc
+++ b/compiler/utils/assembler.cc
@@ -47,7 +47,7 @@
AssemblerBuffer::AssemblerBuffer(ArenaAllocator* arena)
: arena_(arena) {
static const size_t kInitialBufferCapacity = 4 * KB;
- contents_ = arena_->AllocArray<uint8_t>(kInitialBufferCapacity);
+ contents_ = arena_->AllocArray<uint8_t>(kInitialBufferCapacity, kArenaAllocAssembler);
cursor_ = contents_;
limit_ = ComputeLimit(contents_, kInitialBufferCapacity);
fixup_ = nullptr;
@@ -94,6 +94,7 @@
void AssemblerBuffer::ExtendCapacity(size_t min_capacity) {
size_t old_size = Size();
size_t old_capacity = Capacity();
+ DCHECK_GT(min_capacity, old_capacity);
size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB);
new_capacity = std::max(new_capacity, min_capacity);
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index f70fe04..5267dc3 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -178,8 +178,8 @@
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
@@ -219,7 +219,9 @@
class EnsureCapacity {
public:
explicit EnsureCapacity(AssemblerBuffer* buffer) {
- if (buffer->cursor() >= buffer->limit()) buffer->ExtendCapacity();
+ if (buffer->cursor() > buffer->limit()) {
+ buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
+ }
}
};
@@ -233,7 +235,14 @@
// 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.
@@ -255,10 +264,6 @@
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.