1// Copyright (c) 2012, 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_DART_API_MESSAGE_H_
6#define RUNTIME_VM_DART_API_MESSAGE_H_
7
8#include "include/dart_native_api.h"
9#include "platform/utils.h"
10#include "vm/allocation.h"
11#include "vm/dart_api_state.h"
12#include "vm/message.h"
13#include "vm/raw_object.h"
14#include "vm/snapshot.h"
15
16namespace dart {
17
18// Use this C structure for reading internal objects in the serialized
19// data. These are objects that we need to process in order to
20// generate the Dart_CObject graph but that we don't want to expose in
21// that graph.
22struct Dart_CObject_Internal : public Dart_CObject {
23 enum Type {
24 kTypeArguments = Dart_CObject_kNumberOfTypes,
25 kDynamicType,
26 kClass,
27 kView,
28 kUninitialized,
29 };
30 struct Dart_CObject_Internal* cls;
31 union {
32 struct {
33 struct _Dart_CObject* library_url;
34 struct _Dart_CObject* class_name;
35 } as_class;
36 struct {
37 struct _Dart_CObject* buffer;
38 int offset_in_bytes;
39 int length;
40 } as_view;
41 } internal;
42};
43
44// Reads a message snapshot into a C structure.
45class ApiMessageReader : public BaseReader {
46 public:
47 // The ApiMessageReader object must be enclosed by an ApiNativeScope.
48 // Allocation of all C Heap objects is done in the zone associated with
49 // the enclosing ApiNativeScope.
50 explicit ApiMessageReader(Message* message);
51 ~ApiMessageReader();
52
53 Dart_CObject* ReadMessage();
54
55 private:
56 class BackRefNode {
57 public:
58 BackRefNode(Dart_CObject* reference, DeserializeState state)
59 : reference_(reference), state_(state) {}
60 Dart_CObject* reference() const { return reference_; }
61 void set_reference(Dart_CObject* reference) { reference_ = reference; }
62 bool is_deserialized() const { return state_ == kIsDeserialized; }
63 void set_state(DeserializeState value) { state_ = value; }
64
65 private:
66 Dart_CObject* reference_;
67 DeserializeState state_;
68
69 DISALLOW_COPY_AND_ASSIGN(BackRefNode);
70 };
71
72 // Allocates a Dart_CObject object.
73 Dart_CObject* AllocateDartCObject();
74 // Allocates a Dart_CObject object with the specified type.
75 Dart_CObject* AllocateDartCObject(Dart_CObject_Type type);
76 // Allocates a Dart_CObject object representing an unsupported
77 // object in the API message.
78 Dart_CObject* AllocateDartCObjectUnsupported();
79 // Allocates a Dart_CObject object for the null object.
80 Dart_CObject* AllocateDartCObjectNull();
81 // Allocates a Dart_CObject object for a boolean object.
82 Dart_CObject* AllocateDartCObjectBool(bool value);
83 // Allocates a Dart_CObject object for for a 32-bit integer.
84 Dart_CObject* AllocateDartCObjectInt32(int32_t value);
85 // Allocates a Dart_CObject object for for a 64-bit integer.
86 Dart_CObject* AllocateDartCObjectInt64(int64_t value);
87 // Allocates a Dart_CObject object for a double.
88 Dart_CObject* AllocateDartCObjectDouble(double value);
89 // Allocates a Dart_CObject object for string data.
90 Dart_CObject* AllocateDartCObjectString(intptr_t length);
91 // Allocates a C Dart_CObject object for a typed data.
92 Dart_CObject* AllocateDartCObjectTypedData(Dart_TypedData_Type type,
93 intptr_t length);
94 // Allocates a C array of Dart_CObject objects.
95 Dart_CObject* AllocateDartCObjectArray(intptr_t length);
96 // Allocate a C Dart_CObject object for a VM isolate object.
97 Dart_CObject* AllocateDartCObjectVmIsolateObj(intptr_t id);
98 // Allocates a Dart_CObject_Internal object with the specified type.
99 Dart_CObject_Internal* AllocateDartCObjectInternal(
100 Dart_CObject_Internal::Type type);
101 // Allocates a Dart_CObject_Internal object for a class object.
102 Dart_CObject_Internal* AllocateDartCObjectClass();
103 // Allocates a backwards reference node.
104 BackRefNode* AllocateBackRefNode(Dart_CObject* ref, DeserializeState state);
105
106 void Init();
107
108 intptr_t LookupInternalClass(intptr_t class_header);
109 Dart_CObject* ReadVMIsolateObject(intptr_t value);
110 Dart_CObject* ReadInternalVMObject(intptr_t class_id, intptr_t object_id);
111 Dart_CObject* ReadInlinedObject(intptr_t object_id);
112 Dart_CObject* ReadObjectImpl();
113 Dart_CObject* ReadIndexedObject(intptr_t object_id);
114 Dart_CObject* ReadPredefinedSymbol(intptr_t object_id);
115 Dart_CObject* ReadObjectRef();
116 Dart_CObject* ReadObject();
117
118 // Add object to backward references.
119 void AddBackRef(intptr_t id, Dart_CObject* obj, DeserializeState state);
120
121 // Get an object from the backward references list.
122 Dart_CObject* GetBackRef(intptr_t id);
123
124 intptr_t NextAvailableObjectId() const;
125
126 Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
127 ASSERT(object->type >= Dart_CObject_kNumberOfTypes);
128 return reinterpret_cast<Dart_CObject_Internal*>(object);
129 }
130
131 ObjectPtr VmIsolateSnapshotObject(intptr_t index) const {
132 return Object::vm_isolate_snapshot_object_table().At(index);
133 }
134
135 Dart_CObject* CreateDartCObjectString(ObjectPtr raw);
136 Dart_CObject* GetCanonicalMintObject(Dart_CObject_Type type, int64_t value64);
137
138 uint8_t* allocator(intptr_t size) {
139 return zone_->Realloc<uint8_t>(NULL, 0, size);
140 }
141
142 Zone* zone_; // Zone in which C heap objects are allocated.
143 ApiGrowableArray<BackRefNode*> backward_references_;
144 ApiGrowableArray<Dart_CObject*> vm_isolate_references_;
145 Dart_CObject** vm_symbol_references_;
146
147 Dart_CObject type_arguments_marker;
148 Dart_CObject dynamic_type_marker;
149
150 MessageFinalizableData* finalizable_data_;
151};
152
153class ApiMessageWriter : public BaseWriter {
154 public:
155 static const intptr_t kInitialSize = 512;
156 ApiMessageWriter();
157 ~ApiMessageWriter();
158
159 // Writes a message with a single object.
160 std::unique_ptr<Message> WriteCMessage(Dart_CObject* object,
161 Dart_Port dest_port,
162 Message::Priority priority);
163
164 private:
165 static const intptr_t kDartCObjectTypeBits = 4;
166 static const intptr_t kDartCObjectTypeMask = (1 << kDartCObjectTypeBits) - 1;
167 static const intptr_t kDartCObjectMarkMask = ~kDartCObjectTypeMask;
168 static const intptr_t kDartCObjectMarkOffset = 1;
169
170 void MarkCObject(Dart_CObject* object, intptr_t object_id);
171 void UnmarkCObject(Dart_CObject* object);
172 bool IsCObjectMarked(Dart_CObject* object);
173 intptr_t GetMarkedCObjectMark(Dart_CObject* object);
174 void UnmarkAllCObjects(Dart_CObject* object);
175 void AddToForwardList(Dart_CObject* object);
176
177 void WriteSmi(int64_t value);
178 void WriteNullObject();
179 void WriteMint(Dart_CObject* object, int64_t value);
180 void WriteInt32(Dart_CObject* object);
181 void WriteInt64(Dart_CObject* object);
182 void WriteInlinedHeader(Dart_CObject* object);
183 bool WriteCObject(Dart_CObject* object);
184 bool WriteCObjectRef(Dart_CObject* object);
185 bool WriteForwardedCObject(Dart_CObject* object);
186 bool WriteCObjectInlined(Dart_CObject* object, Dart_CObject_Type type);
187
188 intptr_t object_id_;
189 Dart_CObject** forward_list_;
190 intptr_t forward_list_length_;
191 intptr_t forward_id_;
192 MessageFinalizableData* finalizable_data_;
193
194 DISALLOW_COPY_AND_ASSIGN(ApiMessageWriter);
195};
196
197// This class handles translation of certain RawObjects to CObjects for
198// NativeMessageHandlers.
199//
200// TODO(zra): Expand to support not only null, but also other VM heap objects
201// as well.
202class ApiObjectConverter : public AllStatic {
203 public:
204 static bool CanConvert(const ObjectPtr raw_obj) {
205 return !raw_obj->IsHeapObject() || (raw_obj == Object::null());
206 }
207
208 static bool Convert(const ObjectPtr raw_obj, Dart_CObject* c_obj) {
209 if (!raw_obj->IsHeapObject()) {
210 ConvertSmi(static_cast<const SmiPtr>(raw_obj), c_obj);
211 } else if (raw_obj == Object::null()) {
212 ConvertNull(c_obj);
213 } else {
214 return false;
215 }
216 return true;
217 }
218
219 private:
220 static void ConvertSmi(const SmiPtr raw_smi, Dart_CObject* c_obj) {
221 ASSERT(!raw_smi->IsHeapObject());
222 intptr_t value = Smi::Value(raw_smi);
223 if (Utils::IsInt(31, value)) {
224 c_obj->type = Dart_CObject_kInt32;
225 c_obj->value.as_int32 = static_cast<int32_t>(value);
226 } else {
227 c_obj->type = Dart_CObject_kInt64;
228 c_obj->value.as_int64 = static_cast<int64_t>(value);
229 }
230 }
231
232 static void ConvertNull(Dart_CObject* c_obj) {
233 c_obj->type = Dart_CObject_kNull;
234 c_obj->value.as_int64 = 0;
235 }
236};
237
238} // namespace dart
239
240#endif // RUNTIME_VM_DART_API_MESSAGE_H_
241