assembler.cc revision 834b394ee759ed31c5371d8093d7cd8cd90014a8
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 28namespace art { 29 30static byte* NewContents(size_t capacity) { 31 return new byte[capacity]; 32} 33 34 35AssemblerBuffer::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 53AssemblerBuffer::~AssemblerBuffer() { 54 delete[] contents_; 55} 56 57 58void 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 67void 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 79void 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 104Assembler* 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