oat_quick_method_header.h revision dcdc85bbd569f0ee66c331b4219c19304a616214
1524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray/* 2524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * Copyright (C) 2011 The Android Open Source Project 3524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * 4524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * you may not use this file except in compliance with the License. 6524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * You may obtain a copy of the License at 7524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * 8524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * 10524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * See the License for the specific language governing permissions and 14524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray * limitations under the License. 15524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray */ 16524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 17524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#ifndef ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_ 18524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#define ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_ 19524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 20524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "arch/instruction_set.h" 21524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "base/macros.h" 22524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "quick/quick_method_frame_info.h" 23524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "stack_map.h" 241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "utils.h" 25524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 26524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffraynamespace art { 27524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 28524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayclass ArtMethod; 29524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 30524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray// OatQuickMethodHeader precedes the raw code chunk generated by the compiler. 31524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayclass PACKED(4) OatQuickMethodHeader { 32524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray public: 33524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray OatQuickMethodHeader(uint32_t mapping_table_offset = 0U, 34524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t vmap_table_offset = 0U, 35524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t gc_map_offset = 0U, 36524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t frame_size_in_bytes = 0U, 37524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t core_spill_mask = 0U, 38524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t fp_spill_mask = 0U, 39524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t code_size = 0U); 40524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 41524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray ~OatQuickMethodHeader(); 42524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 431dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray static OatQuickMethodHeader* FromCodePointer(const void* code_ptr) { 441dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray uintptr_t code = reinterpret_cast<uintptr_t>(code_ptr); 451dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray uintptr_t header = code - OFFSETOF_MEMBER(OatQuickMethodHeader, code_); 46562ff44698fc75f82e1f6cb0b71ce21df4328959Vladimir Marko DCHECK(IsAlignedParam(code, GetInstructionSetAlignment(kRuntimeISA)) || 47dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao IsAlignedParam(header, GetInstructionSetAlignment(kRuntimeISA))) 48dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao << std::hex << code << " " << std::hex << header; 491dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return reinterpret_cast<OatQuickMethodHeader*>(header); 501dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 511dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray static OatQuickMethodHeader* FromEntryPoint(const void* entry_point) { 531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray return FromCodePointer(EntryPointToCodePointer(entry_point)); 541dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 551dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray 56524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray OatQuickMethodHeader& operator=(const OatQuickMethodHeader&) = default; 57524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 58524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uintptr_t NativeQuickPcOffset(const uintptr_t pc) const { 59524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return pc - reinterpret_cast<uintptr_t>(GetEntryPoint()); 60524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 61524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 62524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool IsOptimized() const { 63524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return gc_map_offset_ == 0 && vmap_table_offset_ != 0; 64524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 65524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 66524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CodeInfo GetOptimizedCodeInfo() const { 67524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray DCHECK(IsOptimized()); 68524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const void* data = reinterpret_cast<const void*>(code_ - vmap_table_offset_); 69524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return CodeInfo(data); 70524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 71524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 72524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint8_t* GetCode() const { 73524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return code_; 74524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 75524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 76524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint8_t* GetNativeGcMap() const { 77524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return (gc_map_offset_ == 0) ? nullptr : code_ - gc_map_offset_; 78524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 79524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 80524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint8_t* GetMappingTable() const { 81524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return (mapping_table_offset_ == 0) ? nullptr : code_ - mapping_table_offset_; 82524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 83524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 84524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint8_t* GetVmapTable() const { 85524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler"; 86524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_; 87524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 88524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 89524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool Contains(uintptr_t pc) const { 90524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uintptr_t code_start = reinterpret_cast<uintptr_t>(code_); 911dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA"); 921dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray if (kRuntimeISA == kArm) { 931dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray // On Thumb-2, the pc is offset by one. 941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray code_start++; 951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray } 96524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return code_start <= pc && pc <= (code_start + code_size_); 97524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 98524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 99524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint8_t* GetEntryPoint() const { 100524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // When the runtime architecture is ARM, `kRuntimeISA` is set to `kArm` 101524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // (not `kThumb2`), *but* we always generate code for the Thumb-2 102524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // instruction set anyway. Thumb-2 requires the entrypoint to be of 103524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // offset 1. 104524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA"); 105524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return (kRuntimeISA == kArm) 106524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray ? reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(code_) | 1) 107524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray : code_; 108524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 109524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 110524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray template <bool kCheckFrameSize = true> 111524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t GetFrameSizeInBytes() { 112524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t result = frame_info_.FrameSizeInBytes(); 113524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray if (kCheckFrameSize) { 114524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray DCHECK_LE(static_cast<size_t>(kStackAlignment), result); 115524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 116524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return result; 117524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 118524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 119524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray QuickMethodFrameInfo GetFrameInfo() const { 120524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return frame_info_; 121524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray } 122524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 123524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uintptr_t ToNativeQuickPc(ArtMethod* method, 124524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const uint32_t dex_pc, 125524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool is_for_catch_handler, 126524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray bool abort_on_failure = true) const; 127524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 128524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t ToDexPc(ArtMethod* method, const uintptr_t pc, bool abort_on_failure = true) const; 129524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 130524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // The offset in bytes from the start of the mapping table to the end of the header. 131524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t mapping_table_offset_; 132524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // The offset in bytes from the start of the vmap table to the end of the header. 133524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t vmap_table_offset_; 134524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // The offset in bytes from the start of the gc map to the end of the header. 135524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t gc_map_offset_; 136524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // The stack frame information. 137524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray QuickMethodFrameInfo frame_info_; 138524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // The code size in bytes. 139524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint32_t code_size_; 140524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray // The actual code. 141524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uint8_t code_[0]; 142524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray}; 143524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 144524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray} // namespace art 145524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray 146524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#endif // ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_ 147