oat_quick_method_header.h revision 524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02
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"
24524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
25524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffraynamespace art {
26524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
27524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayclass ArtMethod;
28524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
29524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray// OatQuickMethodHeader precedes the raw code chunk generated by the compiler.
30524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffrayclass PACKED(4) OatQuickMethodHeader {
31524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray public:
32524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  OatQuickMethodHeader(uint32_t mapping_table_offset = 0U,
33524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                       uint32_t vmap_table_offset = 0U,
34524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                       uint32_t gc_map_offset = 0U,
35524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                       uint32_t frame_size_in_bytes = 0U,
36524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                       uint32_t core_spill_mask = 0U,
37524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                       uint32_t fp_spill_mask = 0U,
38524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                       uint32_t code_size = 0U);
39524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
40524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  ~OatQuickMethodHeader();
41524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
42524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  OatQuickMethodHeader& operator=(const OatQuickMethodHeader&) = default;
43524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
44524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uintptr_t NativeQuickPcOffset(const uintptr_t pc) const {
45524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return pc - reinterpret_cast<uintptr_t>(GetEntryPoint());
46524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
47524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
48524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  bool IsOptimized() const {
49524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return gc_map_offset_ == 0 && vmap_table_offset_ != 0;
50524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
51524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
52524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  CodeInfo GetOptimizedCodeInfo() const {
53524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    DCHECK(IsOptimized());
54524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    const void* data = reinterpret_cast<const void*>(code_ - vmap_table_offset_);
55524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return CodeInfo(data);
56524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
57524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
58524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetCode() const {
59524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return code_;
60524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
61524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
62524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetNativeGcMap() const {
63524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (gc_map_offset_ == 0) ? nullptr : code_ - gc_map_offset_;
64524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
65524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
66524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetMappingTable() const {
67524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (mapping_table_offset_ == 0) ? nullptr : code_ - mapping_table_offset_;
68524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
69524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
70524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetVmapTable() const {
71524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
72524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
73524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
74524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
75524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  bool Contains(uintptr_t pc) const {
76524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    uintptr_t code_start = reinterpret_cast<uintptr_t>(code_);
77524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return code_start <= pc && pc <= (code_start + code_size_);
78524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
79524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
80524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetEntryPoint() const {
81524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // When the runtime architecture is ARM, `kRuntimeISA` is set to `kArm`
82524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // (not `kThumb2`), *but* we always generate code for the Thumb-2
83524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // instruction set anyway. Thumb-2 requires the entrypoint to be of
84524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // offset 1.
85524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
86524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (kRuntimeISA == kArm)
87524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray        ? reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(code_) | 1)
88524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray        : code_;
89524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
90524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
91524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  template <bool kCheckFrameSize = true>
92524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t GetFrameSizeInBytes() {
93524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    uint32_t result = frame_info_.FrameSizeInBytes();
94524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    if (kCheckFrameSize) {
95524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray      DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
96524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    }
97524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return result;
98524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
99524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
100524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  QuickMethodFrameInfo GetFrameInfo() const {
101524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return frame_info_;
102524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
103524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
104524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uintptr_t ToNativeQuickPc(ArtMethod* method,
105524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            const uint32_t dex_pc,
106524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            bool is_for_catch_handler,
107524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            bool abort_on_failure = true) const;
108524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
109524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t ToDexPc(ArtMethod* method, const uintptr_t pc, bool abort_on_failure = true) const;
110524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
111524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the mapping table to the end of the header.
112524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t mapping_table_offset_;
113524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the vmap table to the end of the header.
114524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t vmap_table_offset_;
115524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the gc map to the end of the header.
116524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t gc_map_offset_;
117524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The stack frame information.
118524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  QuickMethodFrameInfo frame_info_;
119524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The code size in bytes.
120524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t code_size_;
121524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The actual code.
122524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint8_t code_[0];
123524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray};
124524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
125524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray}  // namespace art
126524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
127524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#endif  // ART_RUNTIME_OAT_QUICK_METHOD_HEADER_H_
128