oat_quick_method_header.h revision 132d8363bf8cb043d910836672192ec8c36649b6
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:
33a5931185c97c7b17981a9fc5016834a0bdd9480bChih-Hung Hsieh  explicit OatQuickMethodHeader(uint32_t vmap_table_offset = 0U,
34a5931185c97c7b17981a9fc5016834a0bdd9480bChih-Hung Hsieh                                uint32_t frame_size_in_bytes = 0U,
35a5931185c97c7b17981a9fc5016834a0bdd9480bChih-Hung Hsieh                                uint32_t core_spill_mask = 0U,
36a5931185c97c7b17981a9fc5016834a0bdd9480bChih-Hung Hsieh                                uint32_t fp_spill_mask = 0U,
37a5931185c97c7b17981a9fc5016834a0bdd9480bChih-Hung Hsieh                                uint32_t code_size = 0U);
38524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
39524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  ~OatQuickMethodHeader();
40524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
411dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  static OatQuickMethodHeader* FromCodePointer(const void* code_ptr) {
421dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    uintptr_t code = reinterpret_cast<uintptr_t>(code_ptr);
431dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    uintptr_t header = code - OFFSETOF_MEMBER(OatQuickMethodHeader, code_);
44562ff44698fc75f82e1f6cb0b71ce21df4328959Vladimir Marko    DCHECK(IsAlignedParam(code, GetInstructionSetAlignment(kRuntimeISA)) ||
45dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao           IsAlignedParam(header, GetInstructionSetAlignment(kRuntimeISA)))
46dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao        << std::hex << code << " " << std::hex << header;
471dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return reinterpret_cast<OatQuickMethodHeader*>(header);
481dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
491dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
501dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  static OatQuickMethodHeader* FromEntryPoint(const void* entry_point) {
511dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return FromCodePointer(EntryPointToCodePointer(entry_point));
521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
54524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  OatQuickMethodHeader& operator=(const OatQuickMethodHeader&) = default;
55524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
56524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uintptr_t NativeQuickPcOffset(const uintptr_t pc) const {
57524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return pc - reinterpret_cast<uintptr_t>(GetEntryPoint());
58524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
59524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
60524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  bool IsOptimized() const {
619d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko    return code_size_ != 0 && vmap_table_offset_ != 0;
62524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
63524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
645d950769b607b4f76413212db640a32d796911deDavid Srbecky  const void* GetOptimizedCodeInfoPtr() const {
65524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    DCHECK(IsOptimized());
66524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    const void* data = reinterpret_cast<const void*>(code_ - vmap_table_offset_);
675d950769b607b4f76413212db640a32d796911deDavid Srbecky    return data;
685d950769b607b4f76413212db640a32d796911deDavid Srbecky  }
695d950769b607b4f76413212db640a32d796911deDavid Srbecky
70132d8363bf8cb043d910836672192ec8c36649b6Nicolas Geoffray  uint8_t* GetOptimizedCodeInfoPtr() {
71132d8363bf8cb043d910836672192ec8c36649b6Nicolas Geoffray    DCHECK(IsOptimized());
72132d8363bf8cb043d910836672192ec8c36649b6Nicolas Geoffray    return code_ - vmap_table_offset_;
73132d8363bf8cb043d910836672192ec8c36649b6Nicolas Geoffray  }
74132d8363bf8cb043d910836672192ec8c36649b6Nicolas Geoffray
755d950769b607b4f76413212db640a32d796911deDavid Srbecky  CodeInfo GetOptimizedCodeInfo() const {
765d950769b607b4f76413212db640a32d796911deDavid Srbecky    return CodeInfo(GetOptimizedCodeInfoPtr());
77524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
78524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
79524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetCode() const {
80524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return code_;
81524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
82524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
835d950769b607b4f76413212db640a32d796911deDavid Srbecky  uint32_t GetCodeSize() const {
845d950769b607b4f76413212db640a32d796911deDavid Srbecky    return code_size_;
855d950769b607b4f76413212db640a32d796911deDavid Srbecky  }
865d950769b607b4f76413212db640a32d796911deDavid Srbecky
87524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetVmapTable() const {
88524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
89524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
90524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
91524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
92524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  bool Contains(uintptr_t pc) const {
93524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    uintptr_t code_start = reinterpret_cast<uintptr_t>(code_);
941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    if (kRuntimeISA == kArm) {
961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      // On Thumb-2, the pc is offset by one.
971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      code_start++;
981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    }
99524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return code_start <= pc && pc <= (code_start + code_size_);
100524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
101524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
102524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  const uint8_t* GetEntryPoint() const {
103524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // When the runtime architecture is ARM, `kRuntimeISA` is set to `kArm`
104524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // (not `kThumb2`), *but* we always generate code for the Thumb-2
105524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // instruction set anyway. Thumb-2 requires the entrypoint to be of
106524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    // offset 1.
107524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
108524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return (kRuntimeISA == kArm)
109524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray        ? reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(code_) | 1)
110524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray        : code_;
111524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
112524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
113524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  template <bool kCheckFrameSize = true>
114b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  uint32_t GetFrameSizeInBytes() const {
115524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    uint32_t result = frame_info_.FrameSizeInBytes();
116524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    if (kCheckFrameSize) {
1176832fbe366dd4fc79daa8976f8edbe78d4591649David Srbecky      DCHECK_ALIGNED(result, kStackAlignment);
118524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    }
119524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return result;
120524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
121524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
122524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  QuickMethodFrameInfo GetFrameInfo() const {
123524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    return frame_info_;
124524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  }
125524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
126524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uintptr_t ToNativeQuickPc(ArtMethod* method,
127524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            const uint32_t dex_pc,
128524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            bool is_for_catch_handler,
129524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray                            bool abort_on_failure = true) const;
130524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
131524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t ToDexPc(ArtMethod* method, const uintptr_t pc, bool abort_on_failure = true) const;
132524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray
133524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  // The offset in bytes from the start of the vmap table to the end of the header.
134524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray  uint32_t vmap_table_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