/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "lazy_debug_frame_opcode_writer.h" #include "mir_to_lir.h" namespace art { namespace dwarf { const ArenaVector<uint8_t>* LazyDebugFrameOpCodeWriter::Patch(size_t code_size) { if (!this->enabled_) { DCHECK(this->data()->empty()); return this->data(); } if (!patched_) { patched_ = true; // Move our data buffer to temporary variable. ArenaVector<uint8_t> old_opcodes(this->opcodes_.get_allocator()); old_opcodes.swap(this->opcodes_); // Refill our data buffer with patched opcodes. this->opcodes_.reserve(old_opcodes.size() + advances_.size() + 4); size_t pos = 0; for (auto advance : advances_) { DCHECK_GE(advance.pos, pos); // Copy old data up to the point when advance was issued. this->opcodes_.insert(this->opcodes_.end(), old_opcodes.begin() + pos, old_opcodes.begin() + advance.pos); pos = advance.pos; // This may be null if there is no slow-path code after return. LIR* next_lir = NEXT_LIR(advance.last_lir_insn); // Insert the advance command with its final offset. Base::AdvancePC(next_lir != nullptr ? next_lir->offset : code_size); } // Copy the final segment. this->opcodes_.insert(this->opcodes_.end(), old_opcodes.begin() + pos, old_opcodes.end()); Base::AdvancePC(code_size); } return this->data(); } } // namespace dwarf } // namespace art