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 #ifdef ART_ENABLE_CODEGEN_arm 23 #include "arm/assembler_thumb2.h" 24 #endif 25 #ifdef ART_ENABLE_CODEGEN_arm64 26 #include "arm64/assembler_arm64.h" 27 #endif 28 #ifdef ART_ENABLE_CODEGEN_mips 29 #include "mips/assembler_mips.h" 30 #endif 31 #ifdef ART_ENABLE_CODEGEN_mips64 32 #include "mips64/assembler_mips64.h" 33 #endif 34 #ifdef ART_ENABLE_CODEGEN_x86 35 #include "x86/assembler_x86.h" 36 #endif 37 #ifdef ART_ENABLE_CODEGEN_x86_64 38 #include "x86_64/assembler_x86_64.h" 39 #endif 40 #include "base/casts.h" 41 #include "globals.h" 42 #include "memory_region.h" 43 44 namespace art { 45 46 AssemblerBuffer::AssemblerBuffer(ArenaAllocator* arena) 47 : arena_(arena) { 48 static const size_t kInitialBufferCapacity = 4 * KB; 49 contents_ = arena_->AllocArray<uint8_t>(kInitialBufferCapacity, kArenaAllocAssembler); 50 cursor_ = contents_; 51 limit_ = ComputeLimit(contents_, kInitialBufferCapacity); 52 fixup_ = nullptr; 53 slow_path_ = nullptr; 54 #ifndef NDEBUG 55 has_ensured_capacity_ = false; 56 fixups_processed_ = false; 57 #endif 58 59 // Verify internal state. 60 CHECK_EQ(Capacity(), kInitialBufferCapacity); 61 CHECK_EQ(Size(), 0U); 62 } 63 64 65 AssemblerBuffer::~AssemblerBuffer() { 66 if (arena_->IsRunningOnMemoryTool()) { 67 arena_->MakeInaccessible(contents_, Capacity()); 68 } 69 } 70 71 72 void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) { 73 AssemblerFixup* fixup = fixup_; 74 while (fixup != nullptr) { 75 fixup->Process(region, fixup->position()); 76 fixup = fixup->previous(); 77 } 78 } 79 80 81 void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) { 82 // Copy the instructions from the buffer. 83 MemoryRegion from(reinterpret_cast<void*>(contents()), Size()); 84 instructions.CopyFrom(0, from); 85 // Process fixups in the instructions. 86 ProcessFixups(instructions); 87 #ifndef NDEBUG 88 fixups_processed_ = true; 89 #endif 90 } 91 92 93 void AssemblerBuffer::ExtendCapacity(size_t min_capacity) { 94 size_t old_size = Size(); 95 size_t old_capacity = Capacity(); 96 DCHECK_GT(min_capacity, old_capacity); 97 size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB); 98 new_capacity = std::max(new_capacity, min_capacity); 99 100 // Allocate the new data area and copy contents of the old one to it. 101 contents_ = reinterpret_cast<uint8_t*>( 102 arena_->Realloc(contents_, old_capacity, new_capacity, kArenaAllocAssembler)); 103 104 // Update the cursor and recompute the limit. 105 cursor_ = contents_ + old_size; 106 limit_ = ComputeLimit(contents_, new_capacity); 107 108 // Verify internal state. 109 CHECK_EQ(Capacity(), new_capacity); 110 CHECK_EQ(Size(), old_size); 111 } 112 113 void DebugFrameOpCodeWriterForAssembler::ImplicitlyAdvancePC() { 114 uint32_t pc = dchecked_integral_cast<uint32_t>(assembler_->CodeSize()); 115 if (delay_emitting_advance_pc_) { 116 uint32_t stream_pos = dchecked_integral_cast<uint32_t>(opcodes_.size()); 117 delayed_advance_pcs_.push_back(DelayedAdvancePC {stream_pos, pc}); 118 } else { 119 AdvancePC(pc); 120 } 121 } 122 123 } // namespace art 124