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
11namespace dart {
12
13// Forward declarations.
14class Object;
15class 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.
21class 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
39class 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
54class 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
69class 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
84class 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
99class 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.
117class 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
132class 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
151class 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
166class 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.
185class 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