oat_quick_method_header.h revision 1dad3f68b7f5a4a4cb2b281413357adc2309a8fd
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_);
461dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    DCHECK(IsAlignedParam(code, GetInstructionSetAlignment(kRuntimeISA)) ||
471dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray           IsAlignedParam(header, GetInstructionSetAlignment(kRuntimeISA)));
481dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return reinterpret_cast<OatQuickMethodHeader*>(header);
491dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
501dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
511dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  static OatQuickMethodHeader* FromEntryPoint(const void* entry_point) {
521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return FromCodePointer(EntryPointToCodePointer(entry_point));
531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
541dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
55524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  OatQuickMethodHeader& operator=(const OatQuickMethodHeader&) = default;
56524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
57524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uintptr_t NativeQuickPcOffset(const uintptr_t pc) const {
58524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return pc - reinterpret_cast<uintptr_t>(GetEntryPoint());
59524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
60524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
61524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  bool IsOptimized() const {
62524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return gc_map_offset_ == 0 && vmap_table_offset_ != 0;
63524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
64524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
65524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  CodeInfo GetOptimizedCodeInfo() const {
66524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    DCHECK(IsOptimized());
67524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    const void* data = reinterpret_cast<const void*>(code_ - vmap_table_offset_);
68524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return CodeInfo(data);
69524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
70524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
71524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetCode() const {
72524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return code_;
73524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
74524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
75524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetNativeGcMap() const {
76524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (gc_map_offset_ == 0) ? nullptr : code_ - gc_map_offset_;
77524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
78524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
79524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetMappingTable() const {
80524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (mapping_table_offset_ == 0) ? nullptr : code_ - mapping_table_offset_;
81524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
82524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
83524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetVmapTable() const {
84524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
85524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
86524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
87524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
88524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  bool Contains(uintptr_t pc) const {
89524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    uintptr_t code_start = reinterpret_cast<uintptr_t>(code_);
901dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
911dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    if (kRuntimeISA == kArm) {
921dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      // On Thumb-2, the pc is offset by one.
931dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      code_start++;
941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    }
95524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return code_start <= pc && pc <= (code_start + code_size_);
96524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
97524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
98524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetEntryPoint() const {
99524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // When the runtime architecture is ARM, `kRuntimeISA` is set to `kArm`
100524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // (not `kThumb2`), *but* we always generate code for the Thumb-2
101524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // instruction set anyway. Thumb-2 requires the entrypoint to be of
102524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // offset 1.
103524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
104524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (kRuntimeISA == kArm)
105524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray        ? reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(code_) | 1)
106524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray        : code_;
107524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
108524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
109524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  template <bool kCheckFrameSize = true>
110524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t GetFrameSizeInBytes() {
111524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    uint32_t result = frame_info_.FrameSizeInBytes();
112524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    if (kCheckFrameSize) {
113524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray      DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
114524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    }
115524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return result;
116524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
117524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
118524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  QuickMethodFrameInfo GetFrameInfo() const {
119524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return frame_info_;
120524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
121524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
122524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uintptr_t ToNativeQuickPc(ArtMethod* method,
123524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            const uint32_t dex_pc,
124524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            bool is_for_catch_handler,
125524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            bool abort_on_failure = true) const;
126524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
127524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t ToDexPc(ArtMethod* method, const uintptr_t pc, bool abort_on_failure = true) const;
128524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
129524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the mapping table to the end of the header.
130524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t mapping_table_offset_;
131524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the vmap table to the end of the header.
132524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t vmap_table_offset_;
133524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the gc map to the end of the header.
134524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t gc_map_offset_;
135524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The stack frame information.
136524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  QuickMethodFrameInfo frame_info_;
137524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The code size in bytes.
138524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t code_size_;
139524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The actual code.
140524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint8_t code_[0];
141524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray};
142524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
143524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray}  // namespace art
144524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
145524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#endif  // ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_
146