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 
AssemblerBuffer(ArenaAllocator * arena)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 
~AssemblerBuffer()65 AssemblerBuffer::~AssemblerBuffer() {
66   if (arena_->IsRunningOnMemoryTool()) {
67     arena_->MakeInaccessible(contents_, Capacity());
68   }
69 }
70 
71 
ProcessFixups(const MemoryRegion & region)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 
FinalizeInstructions(const MemoryRegion & instructions)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 
ExtendCapacity(size_t min_capacity)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 
ImplicitlyAdvancePC()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