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