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