1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_DEFERRED_OBJECTS_H_ |
6 | #define RUNTIME_VM_DEFERRED_OBJECTS_H_ |
7 | |
8 | #include "platform/globals.h" |
9 | #include "vm/tagged_pointer.h" |
10 | |
11 | namespace dart { |
12 | |
13 | // Forward declarations. |
14 | class Object; |
15 | class DeoptContext; |
16 | |
17 | // Used by the deoptimization infrastructure to defer allocation of |
18 | // unboxed objects until frame is fully rewritten and GC is safe. |
19 | // Describes a stack slot that should be populated with a reference to |
20 | // the materialized object. |
21 | class DeferredSlot { |
22 | public: |
23 | DeferredSlot(ObjectPtr* slot, DeferredSlot* next) |
24 | : slot_(slot), next_(next) {} |
25 | virtual ~DeferredSlot() {} |
26 | |
27 | ObjectPtr* slot() const { return slot_; } |
28 | DeferredSlot* next() const { return next_; } |
29 | |
30 | virtual void Materialize(DeoptContext* deopt_context) = 0; |
31 | |
32 | private: |
33 | ObjectPtr* const slot_; |
34 | DeferredSlot* const next_; |
35 | |
36 | DISALLOW_COPY_AND_ASSIGN(DeferredSlot); |
37 | }; |
38 | |
39 | class DeferredDouble : public DeferredSlot { |
40 | public: |
41 | DeferredDouble(double value, ObjectPtr* slot, DeferredSlot* next) |
42 | : DeferredSlot(slot, next), value_(value) {} |
43 | |
44 | virtual void Materialize(DeoptContext* deopt_context); |
45 | |
46 | double value() const { return value_; } |
47 | |
48 | private: |
49 | const double value_; |
50 | |
51 | DISALLOW_COPY_AND_ASSIGN(DeferredDouble); |
52 | }; |
53 | |
54 | class DeferredMint : public DeferredSlot { |
55 | public: |
56 | DeferredMint(int64_t value, ObjectPtr* slot, DeferredSlot* next) |
57 | : DeferredSlot(slot, next), value_(value) {} |
58 | |
59 | virtual void Materialize(DeoptContext* deopt_context); |
60 | |
61 | int64_t value() const { return value_; } |
62 | |
63 | private: |
64 | const int64_t value_; |
65 | |
66 | DISALLOW_COPY_AND_ASSIGN(DeferredMint); |
67 | }; |
68 | |
69 | class DeferredFloat32x4 : public DeferredSlot { |
70 | public: |
71 | DeferredFloat32x4(simd128_value_t value, ObjectPtr* slot, DeferredSlot* next) |
72 | : DeferredSlot(slot, next), value_(value) {} |
73 | |
74 | virtual void Materialize(DeoptContext* deopt_context); |
75 | |
76 | simd128_value_t value() const { return value_; } |
77 | |
78 | private: |
79 | const simd128_value_t value_; |
80 | |
81 | DISALLOW_COPY_AND_ASSIGN(DeferredFloat32x4); |
82 | }; |
83 | |
84 | class DeferredFloat64x2 : public DeferredSlot { |
85 | public: |
86 | DeferredFloat64x2(simd128_value_t value, ObjectPtr* slot, DeferredSlot* next) |
87 | : DeferredSlot(slot, next), value_(value) {} |
88 | |
89 | virtual void Materialize(DeoptContext* deopt_context); |
90 | |
91 | simd128_value_t value() const { return value_; } |
92 | |
93 | private: |
94 | const simd128_value_t value_; |
95 | |
96 | DISALLOW_COPY_AND_ASSIGN(DeferredFloat64x2); |
97 | }; |
98 | |
99 | class DeferredInt32x4 : public DeferredSlot { |
100 | public: |
101 | DeferredInt32x4(simd128_value_t value, ObjectPtr* slot, DeferredSlot* next) |
102 | : DeferredSlot(slot, next), value_(value) {} |
103 | |
104 | virtual void Materialize(DeoptContext* deopt_context); |
105 | |
106 | simd128_value_t value() const { return value_; } |
107 | |
108 | private: |
109 | const simd128_value_t value_; |
110 | |
111 | DISALLOW_COPY_AND_ASSIGN(DeferredInt32x4); |
112 | }; |
113 | |
114 | // Describes a slot that contains a reference to an object that had its |
115 | // allocation removed by AllocationSinking pass. |
116 | // Object itself is described and materialized by DeferredObject. |
117 | class DeferredObjectRef : public DeferredSlot { |
118 | public: |
119 | DeferredObjectRef(intptr_t index, ObjectPtr* slot, DeferredSlot* next) |
120 | : DeferredSlot(slot, next), index_(index) {} |
121 | |
122 | virtual void Materialize(DeoptContext* deopt_context); |
123 | |
124 | intptr_t index() const { return index_; } |
125 | |
126 | private: |
127 | const intptr_t index_; |
128 | |
129 | DISALLOW_COPY_AND_ASSIGN(DeferredObjectRef); |
130 | }; |
131 | |
132 | class DeferredRetAddr : public DeferredSlot { |
133 | public: |
134 | DeferredRetAddr(intptr_t index, |
135 | intptr_t deopt_id, |
136 | ObjectPtr* slot, |
137 | DeferredSlot* next) |
138 | : DeferredSlot(slot, next), index_(index), deopt_id_(deopt_id) {} |
139 | |
140 | virtual void Materialize(DeoptContext* deopt_context); |
141 | |
142 | intptr_t index() const { return index_; } |
143 | |
144 | private: |
145 | const intptr_t index_; |
146 | const intptr_t deopt_id_; |
147 | |
148 | DISALLOW_COPY_AND_ASSIGN(DeferredRetAddr); |
149 | }; |
150 | |
151 | class DeferredPcMarker : public DeferredSlot { |
152 | public: |
153 | DeferredPcMarker(intptr_t index, ObjectPtr* slot, DeferredSlot* next) |
154 | : DeferredSlot(slot, next), index_(index) {} |
155 | |
156 | virtual void Materialize(DeoptContext* deopt_context); |
157 | |
158 | intptr_t index() const { return index_; } |
159 | |
160 | private: |
161 | const intptr_t index_; |
162 | |
163 | DISALLOW_COPY_AND_ASSIGN(DeferredPcMarker); |
164 | }; |
165 | |
166 | class DeferredPp : public DeferredSlot { |
167 | public: |
168 | DeferredPp(intptr_t index, ObjectPtr* slot, DeferredSlot* next) |
169 | : DeferredSlot(slot, next), index_(index) {} |
170 | |
171 | virtual void Materialize(DeoptContext* deopt_context); |
172 | |
173 | intptr_t index() const { return index_; } |
174 | |
175 | private: |
176 | const intptr_t index_; |
177 | |
178 | DISALLOW_COPY_AND_ASSIGN(DeferredPp); |
179 | }; |
180 | |
181 | // Describes an object which allocation was removed by AllocationSinking pass. |
182 | // Arguments for materialization are stored as a part of expression stack |
183 | // for the bottommost deoptimized frame so that GC could discover them. |
184 | // They will be removed from the stack at the very end of deoptimization. |
185 | class DeferredObject { |
186 | public: |
187 | DeferredObject(intptr_t field_count, intptr_t* args) |
188 | : field_count_(field_count), |
189 | args_(reinterpret_cast<ObjectPtr*>(args)), |
190 | object_(NULL) {} |
191 | |
192 | intptr_t ArgumentCount() const { |
193 | return kFieldsStartIndex + kFieldEntrySize * field_count_; |
194 | } |
195 | |
196 | ObjectPtr object(); |
197 | |
198 | // Fill object with actual field values. |
199 | void Fill(); |
200 | |
201 | private: |
202 | enum { |
203 | kClassIndex = 0, |
204 | kLengthIndex, // Number of context variables for contexts, -1 otherwise. |
205 | kFieldsStartIndex |
206 | }; |
207 | |
208 | enum { |
209 | kOffsetIndex = 0, |
210 | kValueIndex, |
211 | kFieldEntrySize, |
212 | }; |
213 | |
214 | // Allocate the object but keep its fields null-initialized. Actual field |
215 | // values will be filled later by the Fill method. This separation between |
216 | // allocation and filling is needed because dematerialized objects form |
217 | // a graph which can contain cycles. |
218 | void Create(); |
219 | |
220 | ObjectPtr GetArg(intptr_t index) const { return args_[index]; } |
221 | |
222 | ObjectPtr GetClass() const { return GetArg(kClassIndex); } |
223 | |
224 | ObjectPtr GetLength() const { return GetArg(kLengthIndex); } |
225 | |
226 | ObjectPtr GetFieldOffset(intptr_t index) const { |
227 | return GetArg(kFieldsStartIndex + kFieldEntrySize * index + kOffsetIndex); |
228 | } |
229 | |
230 | ObjectPtr GetValue(intptr_t index) const { |
231 | return GetArg(kFieldsStartIndex + kFieldEntrySize * index + kValueIndex); |
232 | } |
233 | |
234 | // Amount of fields that have to be initialized. |
235 | const intptr_t field_count_; |
236 | |
237 | // Pointer to the first materialization argument on the stack. |
238 | // The first argument is Class of the instance to materialize followed by |
239 | // Field, value pairs. |
240 | ObjectPtr* args_; |
241 | |
242 | // Object materialized from this description. |
243 | const Object* object_; |
244 | |
245 | DISALLOW_COPY_AND_ASSIGN(DeferredObject); |
246 | }; |
247 | |
248 | } // namespace dart |
249 | |
250 | #endif // RUNTIME_VM_DEFERRED_OBJECTS_H_ |
251 | |