1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "assembler.h" 18 19 #include <algorithm> 20 #include <vector> 21 22 #include "base/casts.h" 23 #include "base/globals.h" 24 #include "base/memory_region.h" 25 26 namespace art { 27 28 AssemblerBuffer::AssemblerBuffer(ArenaAllocator* allocator) 29 : allocator_(allocator) { 30 static const size_t kInitialBufferCapacity = 4 * KB; 31 contents_ = allocator_->AllocArray<uint8_t>(kInitialBufferCapacity, kArenaAllocAssembler); 32 cursor_ = contents_; 33 limit_ = ComputeLimit(contents_, kInitialBufferCapacity); 34 fixup_ = nullptr; 35 slow_path_ = nullptr; 36 #ifndef NDEBUG 37 has_ensured_capacity_ = false; 38 fixups_processed_ = false; 39 #endif 40 41 // Verify internal state. 42 CHECK_EQ(Capacity(), kInitialBufferCapacity); 43 CHECK_EQ(Size(), 0U); 44 } 45 46 47 AssemblerBuffer::~AssemblerBuffer() { 48 if (allocator_->IsRunningOnMemoryTool()) { 49 allocator_->MakeInaccessible(contents_, Capacity()); 50 } 51 } 52 53 54 void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) { 55 AssemblerFixup* fixup = fixup_; 56 while (fixup != nullptr) { 57 fixup->Process(region, fixup->position()); 58 fixup = fixup->previous(); 59 } 60 } 61 62 63 void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) { 64 // Copy the instructions from the buffer. 65 MemoryRegion from(reinterpret_cast<void*>(contents()), Size()); 66 instructions.CopyFrom(0, from); 67 // Process fixups in the instructions. 68 ProcessFixups(instructions); 69 #ifndef NDEBUG 70 fixups_processed_ = true; 71 #endif 72 } 73 74 75 void AssemblerBuffer::ExtendCapacity(size_t min_capacity) { 76 size_t old_size = Size(); 77 size_t old_capacity = Capacity(); 78 DCHECK_GT(min_capacity, old_capacity); 79 size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB); 80 new_capacity = std::max(new_capacity, min_capacity); 81 82 // Allocate the new data area and copy contents of the old one to it. 83 contents_ = reinterpret_cast<uint8_t*>( 84 allocator_->Realloc(contents_, old_capacity, new_capacity, kArenaAllocAssembler)); 85 86 // Update the cursor and recompute the limit. 87 cursor_ = contents_ + old_size; 88 limit_ = ComputeLimit(contents_, new_capacity); 89 90 // Verify internal state. 91 CHECK_EQ(Capacity(), new_capacity); 92 CHECK_EQ(Size(), old_size); 93 } 94 95 void DebugFrameOpCodeWriterForAssembler::ImplicitlyAdvancePC() { 96 uint32_t pc = dchecked_integral_cast<uint32_t>(assembler_->CodeSize()); 97 if (delay_emitting_advance_pc_) { 98 uint32_t stream_pos = dchecked_integral_cast<uint32_t>(opcodes_.size()); 99 delayed_advance_pcs_.push_back(DelayedAdvancePC {stream_pos, pc}); 100 } else { 101 AdvancePC(pc); 102 } 103 } 104 105 } // namespace art 106