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 "arm/assembler_arm.h" 23 #include "mips/assembler_mips.h" 24 #include "x86/assembler_x86.h" 25 #include "globals.h" 26 #include "memory_region.h" 27 28 namespace art { 29 30 static byte* NewContents(size_t capacity) { 31 return new byte[capacity]; 32 } 33 34 35 AssemblerBuffer::AssemblerBuffer() { 36 static const size_t kInitialBufferCapacity = 4 * KB; 37 contents_ = NewContents(kInitialBufferCapacity); 38 cursor_ = contents_; 39 limit_ = ComputeLimit(contents_, kInitialBufferCapacity); 40 fixup_ = NULL; 41 slow_path_ = NULL; 42 #ifndef NDEBUG 43 has_ensured_capacity_ = false; 44 fixups_processed_ = false; 45 #endif 46 47 // Verify internal state. 48 CHECK_EQ(Capacity(), kInitialBufferCapacity); 49 CHECK_EQ(Size(), 0U); 50 } 51 52 53 AssemblerBuffer::~AssemblerBuffer() { 54 delete[] contents_; 55 } 56 57 58 void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) { 59 AssemblerFixup* fixup = fixup_; 60 while (fixup != NULL) { 61 fixup->Process(region, fixup->position()); 62 fixup = fixup->previous(); 63 } 64 } 65 66 67 void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) { 68 // Copy the instructions from the buffer. 69 MemoryRegion from(reinterpret_cast<void*>(contents()), Size()); 70 instructions.CopyFrom(0, from); 71 // Process fixups in the instructions. 72 ProcessFixups(instructions); 73 #ifndef NDEBUG 74 fixups_processed_ = true; 75 #endif 76 } 77 78 79 void AssemblerBuffer::ExtendCapacity() { 80 size_t old_size = Size(); 81 size_t old_capacity = Capacity(); 82 size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB); 83 84 // Allocate the new data area and copy contents of the old one to it. 85 byte* new_contents = NewContents(new_capacity); 86 memmove(reinterpret_cast<void*>(new_contents), 87 reinterpret_cast<void*>(contents_), 88 old_size); 89 90 // Compute the relocation delta and switch to the new contents area. 91 ptrdiff_t delta = new_contents - contents_; 92 contents_ = new_contents; 93 94 // Update the cursor and recompute the limit. 95 cursor_ += delta; 96 limit_ = ComputeLimit(new_contents, new_capacity); 97 98 // Verify internal state. 99 CHECK_EQ(Capacity(), new_capacity); 100 CHECK_EQ(Size(), old_size); 101 } 102 103 104 Assembler* Assembler::Create(InstructionSet instruction_set) { 105 switch (instruction_set) { 106 case kArm: 107 case kThumb2: 108 return new arm::ArmAssembler(); 109 case kMips: 110 return new mips::MipsAssembler(); 111 case kX86: 112 return new x86::X86Assembler(); 113 default: 114 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 115 return NULL; 116 } 117 } 118 119 } // namespace art 120