1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATION_DATA_H_
18 #define ART_COMPILER_OPTIMIZING_CODE_GENERATION_DATA_H_
19 
20 #include <memory>
21 
22 #include "arch/instruction_set.h"
23 #include "base/scoped_arena_allocator.h"
24 #include "base/scoped_arena_containers.h"
25 #include "code_generator.h"
26 #include "dex/string_reference.h"
27 #include "dex/type_reference.h"
28 #include "handle.h"
29 #include "mirror/class.h"
30 #include "mirror/object.h"
31 #include "mirror/string.h"
32 #include "stack_map_stream.h"
33 
34 namespace art HIDDEN {
35 
36 class CodeGenerationData : public DeletableArenaObject<kArenaAllocCodeGenerator> {
37  public:
Create(ArenaStack * arena_stack,InstructionSet instruction_set)38   static std::unique_ptr<CodeGenerationData> Create(ArenaStack* arena_stack,
39                                                     InstructionSet instruction_set) {
40     ScopedArenaAllocator allocator(arena_stack);
41     void* memory = allocator.Alloc<CodeGenerationData>(kArenaAllocCodeGenerator);
42     return std::unique_ptr<CodeGenerationData>(
43         ::new (memory) CodeGenerationData(std::move(allocator), instruction_set));
44   }
45 
GetScopedAllocator()46   ScopedArenaAllocator* GetScopedAllocator() {
47     return &allocator_;
48   }
49 
AddSlowPath(SlowPathCode * slow_path)50   void AddSlowPath(SlowPathCode* slow_path) {
51     slow_paths_.emplace_back(std::unique_ptr<SlowPathCode>(slow_path));
52   }
53 
GetSlowPaths()54   ArrayRef<const std::unique_ptr<SlowPathCode>> GetSlowPaths() const {
55     return ArrayRef<const std::unique_ptr<SlowPathCode>>(slow_paths_);
56   }
57 
GetStackMapStream()58   StackMapStream* GetStackMapStream() { return &stack_map_stream_; }
59 
ReserveJitStringRoot(StringReference string_reference,Handle<mirror::String> string)60   void ReserveJitStringRoot(StringReference string_reference, Handle<mirror::String> string) {
61     jit_string_roots_.Overwrite(string_reference,
62                                 reinterpret_cast64<uint64_t>(string.GetReference()));
63   }
64 
GetJitStringRootIndex(StringReference string_reference)65   uint64_t GetJitStringRootIndex(StringReference string_reference) const {
66     return jit_string_roots_.Get(string_reference);
67   }
68 
GetNumberOfJitStringRoots()69   size_t GetNumberOfJitStringRoots() const {
70     return jit_string_roots_.size();
71   }
72 
ReserveJitClassRoot(TypeReference type_reference,Handle<mirror::Class> klass)73   void ReserveJitClassRoot(TypeReference type_reference, Handle<mirror::Class> klass) {
74     jit_class_roots_.Overwrite(type_reference, reinterpret_cast64<uint64_t>(klass.GetReference()));
75   }
76 
GetJitClassRootIndex(TypeReference type_reference)77   uint64_t GetJitClassRootIndex(TypeReference type_reference) const {
78     return jit_class_roots_.Get(type_reference);
79   }
80 
GetNumberOfJitClassRoots()81   size_t GetNumberOfJitClassRoots() const {
82     return jit_class_roots_.size();
83   }
84 
GetNumberOfJitRoots()85   size_t GetNumberOfJitRoots() const {
86     return GetNumberOfJitStringRoots() + GetNumberOfJitClassRoots();
87   }
88 
89   void EmitJitRoots(/*out*/std::vector<Handle<mirror::Object>>* roots)
90       REQUIRES_SHARED(Locks::mutator_lock_);
91 
92  private:
CodeGenerationData(ScopedArenaAllocator && allocator,InstructionSet instruction_set)93   CodeGenerationData(ScopedArenaAllocator&& allocator, InstructionSet instruction_set)
94       : allocator_(std::move(allocator)),
95         stack_map_stream_(&allocator_, instruction_set),
96         slow_paths_(allocator_.Adapter(kArenaAllocCodeGenerator)),
97         jit_string_roots_(StringReferenceValueComparator(),
98                           allocator_.Adapter(kArenaAllocCodeGenerator)),
99         jit_class_roots_(TypeReferenceValueComparator(),
100                          allocator_.Adapter(kArenaAllocCodeGenerator)) {
101     slow_paths_.reserve(kDefaultSlowPathsCapacity);
102   }
103 
104   static constexpr size_t kDefaultSlowPathsCapacity = 8;
105 
106   ScopedArenaAllocator allocator_;
107   StackMapStream stack_map_stream_;
108   ScopedArenaVector<std::unique_ptr<SlowPathCode>> slow_paths_;
109 
110   // Maps a StringReference (dex_file, string_index) to the index in the literal table.
111   // Entries are initially added with a pointer in the handle zone, and `EmitJitRoots`
112   // will compute all the indices.
113   ScopedArenaSafeMap<StringReference, uint64_t, StringReferenceValueComparator> jit_string_roots_;
114 
115   // Maps a ClassReference (dex_file, type_index) to the index in the literal table.
116   // Entries are initially added with a pointer in the handle zone, and `EmitJitRoots`
117   // will compute all the indices.
118   ScopedArenaSafeMap<TypeReference, uint64_t, TypeReferenceValueComparator> jit_class_roots_;
119 };
120 
121 }  // namespace art
122 
123 #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATION_DATA_H_
124