Decode the Dart message into a Dart_CMessage structure before calling the native port callback
The native port callback is now passed the message as a decodes Dart_CMessage structure. The Dart_CMessage structure is allocated in a zone and the callback receiving it should expect the lifetime to be controlled by the caller. Added support for zones which do not require a current isolate. Changed the GrowableArray to support allocating in aprovided zone instead of the zone for the current isolate. R=turnidge@google.com, asiva@google.com BUG= TEST= Review URL: https://chromiumcodereview.appspot.com//9325022 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4068 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
+55
-50
@@ -535,16 +535,69 @@ DART_EXPORT bool Dart_HasLivePorts();
|
||||
*/
|
||||
DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle object);
|
||||
|
||||
// --- Message sending/receiving from native code ----
|
||||
|
||||
/**
|
||||
* A Dart_CObject is used for representing Dart objects as native C
|
||||
* data outside the Dart heap. These objects are totally detached from
|
||||
* the Dart heap. Only a subset of the Dart objects have a
|
||||
* representation as a Dart_CObject.
|
||||
*/
|
||||
struct Dart_CObject {
|
||||
enum Type {
|
||||
kNull = 0,
|
||||
kBool,
|
||||
kInt32,
|
||||
kDouble,
|
||||
kString,
|
||||
kArray,
|
||||
kNumberOfTypes
|
||||
};
|
||||
Type type;
|
||||
union {
|
||||
bool as_bool;
|
||||
int32_t as_int32;
|
||||
double as_double;
|
||||
char* as_string;
|
||||
struct {
|
||||
int length;
|
||||
Dart_CObject** values;
|
||||
} as_array;
|
||||
} value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Posts a message on some port. The message will contain the
|
||||
* Dart_CObject object graph rooted in 'message'.
|
||||
*
|
||||
* While the message is being sent the state of the graph of
|
||||
* Dart_CObject structures rooted in 'message' should not be accessed,
|
||||
* as the message generation will make temporary modifications to the
|
||||
* data. When the message has been sent the graph will be fully
|
||||
* restored.
|
||||
*
|
||||
* \param port_id The destination port.
|
||||
* \param message The message to send.
|
||||
*
|
||||
* \return True if the message was posted.
|
||||
*/
|
||||
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message);
|
||||
|
||||
/**
|
||||
* A native message handler.
|
||||
*
|
||||
* This handler is associated with a native port by calling
|
||||
* Dart_NewNativePort.
|
||||
*
|
||||
* The message received is decoded into the message structure. The
|
||||
* lifetime of the message data is controlled by the caller. All the
|
||||
* data references from the message are allocated by the caller and
|
||||
* will be reclaimed when returning to it.
|
||||
*/
|
||||
|
||||
typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
|
||||
Dart_Port reply_port_id,
|
||||
uint8_t* data);
|
||||
// TODO(turnidge): Make this function take more appropriate arguments.
|
||||
Dart_CObject* message);
|
||||
|
||||
/**
|
||||
* Creates a new native port. When messages are received on this
|
||||
@@ -1414,52 +1467,4 @@ DART_EXPORT Dart_Handle Dart_SetNativeResolver(
|
||||
DART_EXPORT void Dart_InitPprofSupport();
|
||||
DART_EXPORT void Dart_GetPprofSymbolInfo(void** buffer, int* buffer_size);
|
||||
|
||||
// --- Message sending/receiving from native code ----
|
||||
|
||||
/**
|
||||
* A Dart_CObject is used for representing Dart objects as native C
|
||||
* data outside the Dart heap. These objects are totally detached from
|
||||
* the Dart heap. Only a subset of the Dart objects have a
|
||||
* representation as a Dart_CObject.
|
||||
*/
|
||||
struct Dart_CObject {
|
||||
enum Type {
|
||||
kNull = 0,
|
||||
kBool,
|
||||
kInt32,
|
||||
kDouble,
|
||||
kString,
|
||||
kArray,
|
||||
kNumberOfTypes
|
||||
};
|
||||
Type type;
|
||||
union {
|
||||
bool as_bool;
|
||||
int32_t as_int32;
|
||||
double as_double;
|
||||
char* as_string;
|
||||
struct {
|
||||
int length;
|
||||
Dart_CObject** values;
|
||||
} as_array;
|
||||
} value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Posts a message on some port. The message will contain the
|
||||
* Dart_CObject object graph rooted in 'message'.
|
||||
*
|
||||
* While the message is being sent the state of the graph of
|
||||
* Dart_CObject structures rooted in 'message' should not be accessed,
|
||||
* as the message generation will make temporary modifications to the
|
||||
* data. When the message has been sent the graph will be fully
|
||||
* restored.
|
||||
*
|
||||
* \param port_id The destination port.
|
||||
* \param message The message to send.
|
||||
*
|
||||
* \return True if the message was posted.
|
||||
*/
|
||||
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message);
|
||||
|
||||
#endif // INCLUDE_DART_API_H_
|
||||
|
||||
+3
-1
@@ -1,10 +1,11 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "vm/dart.h"
|
||||
|
||||
#include "vm/code_index_table.h"
|
||||
#include "vm/dart_api_state.h"
|
||||
#include "vm/flags.h"
|
||||
#include "vm/freelist.h"
|
||||
#include "vm/handles.h"
|
||||
@@ -34,6 +35,7 @@ bool Dart::InitOnce(Dart_IsolateCreateCallback create,
|
||||
Isolate::InitOnce();
|
||||
PortMap::InitOnce();
|
||||
FreeListElement::InitOnce();
|
||||
Api::InitOnce();
|
||||
// Create the VM isolate and finish the VM initialization.
|
||||
{
|
||||
ASSERT(vm_isolate_ == NULL);
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey;
|
||||
|
||||
const char* CanonicalFunction(const char* func) {
|
||||
if (strncmp(func, "dart::", 6) == 0) {
|
||||
return func + 6;
|
||||
@@ -237,6 +239,13 @@ uword Api::Reallocate(uword ptr, intptr_t old_size, intptr_t new_size) {
|
||||
}
|
||||
|
||||
|
||||
void Api::InitOnce() {
|
||||
ASSERT(api_native_key_ == Thread::kUnsetThreadLocalKey);
|
||||
api_native_key_ = Thread::CreateThreadLocal();
|
||||
ASSERT(api_native_key_ != Thread::kUnsetThreadLocalKey);
|
||||
}
|
||||
|
||||
|
||||
// --- Handles ---
|
||||
|
||||
|
||||
@@ -2437,5 +2446,4 @@ DART_EXPORT void Dart_GetPprofSymbolInfo(void** buffer, int* buffer_size) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace dart
|
||||
|
||||
@@ -121,6 +121,16 @@ class Api : AllStatic {
|
||||
|
||||
// Reallocates space in the local zone.
|
||||
static uword Reallocate(uword ptr, intptr_t old_size, intptr_t new_size);
|
||||
|
||||
// Performs one-time initialization needed by the API.
|
||||
static void InitOnce();
|
||||
|
||||
private:
|
||||
// Thread local key used by the API. Currently holds the current
|
||||
// ApiNativeScope if any.
|
||||
static ThreadLocalKey api_native_key_;
|
||||
|
||||
friend class ApiNativeScope;
|
||||
};
|
||||
|
||||
class IsolateSaver {
|
||||
|
||||
@@ -2890,23 +2890,31 @@ TEST_CASE(ImportLibrary5) {
|
||||
|
||||
void NewNativePort_send123(Dart_Port dest_port_id,
|
||||
Dart_Port reply_port_id,
|
||||
uint8_t* data) {
|
||||
Dart_CObject *message) {
|
||||
// Gets a null message.
|
||||
EXPECT_NOTNULL(message);
|
||||
EXPECT_EQ(Dart_CObject::kNull, message->type);
|
||||
|
||||
// Post integer value.
|
||||
Dart_CObject object;
|
||||
object.type = Dart_CObject::kInt32;
|
||||
object.value.as_int32 = 123;
|
||||
Dart_PostCObject(reply_port_id, &object);
|
||||
Dart_CObject response;
|
||||
response.type = Dart_CObject::kInt32;
|
||||
response.value.as_int32 = 123;
|
||||
Dart_PostCObject(reply_port_id, &response);
|
||||
}
|
||||
|
||||
|
||||
void NewNativePort_send321(Dart_Port dest_port_id,
|
||||
Dart_Port reply_port_id,
|
||||
uint8_t* data) {
|
||||
Dart_CObject* message) {
|
||||
// Gets a null message.
|
||||
EXPECT_NOTNULL(message);
|
||||
EXPECT_EQ(Dart_CObject::kNull, message->type);
|
||||
|
||||
// Post integer value.
|
||||
Dart_CObject object;
|
||||
object.type = Dart_CObject::kInt32;
|
||||
object.value.as_int32 = 321;
|
||||
Dart_PostCObject(reply_port_id, &object);
|
||||
Dart_CObject response;
|
||||
response.type = Dart_CObject::kInt32;
|
||||
response.value.as_int32 = 321;
|
||||
Dart_PostCObject(reply_port_id, &response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "vm/dart_api_message.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/object_store.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
// TODO(sgjesse): When the external message format is done these
|
||||
// duplicate constants from snapshot.cc should be removed.
|
||||
enum {
|
||||
kInstanceId = ObjectStore::kMaxId,
|
||||
kMaxPredefinedObjectIds,
|
||||
};
|
||||
static const int kNumInitialReferences = 4;
|
||||
|
||||
ApiMessageReader::ApiMessageReader(const uint8_t* buffer,
|
||||
intptr_t length,
|
||||
ReAlloc alloc)
|
||||
: BaseReader(buffer, length),
|
||||
alloc_(alloc),
|
||||
backward_references_(kNumInitialReferences) {
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
void ApiMessageReader::Init() {
|
||||
// Initialize marker objects used to handle Lists.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated.
|
||||
memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
|
||||
memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
|
||||
type_arguments_marker.type =
|
||||
static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kTypeArguments);
|
||||
dynamic_type_marker.type =
|
||||
static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kDynamicType);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::ReadMessage() {
|
||||
// Read the object out of the message.
|
||||
return ReadObject();
|
||||
}
|
||||
|
||||
|
||||
intptr_t ApiMessageReader::LookupInternalClass(intptr_t class_header) {
|
||||
SerializedHeaderType header_type = SerializedHeaderTag::decode(class_header);
|
||||
ASSERT(header_type == kObjectId);
|
||||
intptr_t header_value = SerializedHeaderData::decode(class_header);
|
||||
return header_value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObject(Dart_CObject::Type type) {
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(alloc_(NULL, 0, sizeof(Dart_CObject)));
|
||||
value->type = type;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObjectNull() {
|
||||
return AllocateDartCObject(Dart_CObject::kNull);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObjectBool(bool val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kBool);
|
||||
value->value.as_bool = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObjectInt32(int32_t val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kInt32);
|
||||
value->value.as_int32 = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kDouble);
|
||||
value->value.as_double = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObjectString(intptr_t length) {
|
||||
// Allocate a Dart_CObject structure followed by an array of chars
|
||||
// for the string content. The pointer to the string content is set
|
||||
// up to this area.
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(
|
||||
alloc_(NULL, 0, sizeof(Dart_CObject) + length + 1));
|
||||
value->value.as_string = reinterpret_cast<char*>(value) + sizeof(*value);
|
||||
value->type = Dart_CObject::kString;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::AllocateDartCObjectArray(intptr_t length) {
|
||||
// Allocate a Dart_CObject structure followed by an array of
|
||||
// pointers to Dart_CObject structures. The pointer to the array
|
||||
// content is set up to this area.
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(
|
||||
alloc_(NULL, 0, sizeof(Dart_CObject) + length * sizeof(value)));
|
||||
value->type = Dart_CObject::kArray;
|
||||
value->value.as_array.length = length;
|
||||
if (length > 0) {
|
||||
value->value.as_array.values = reinterpret_cast<Dart_CObject**>(value + 1);
|
||||
} else {
|
||||
value->value.as_array.values = NULL;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
||||
// Read the class header information and lookup the class.
|
||||
intptr_t class_header = ReadIntptrValue();
|
||||
intptr_t tags = ReadIntptrValue();
|
||||
USE(tags);
|
||||
intptr_t class_id;
|
||||
|
||||
// Reading of regular dart instances is not supported.
|
||||
if (SerializedHeaderData::decode(class_header) == kInstanceId) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSERT((class_header & kSmiTagMask) != 0);
|
||||
class_id = LookupInternalClass(class_header);
|
||||
switch (class_id) {
|
||||
case Object::kClassClass: {
|
||||
return NULL;
|
||||
}
|
||||
case Object::kTypeArgumentsClass: {
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated (currently length is leaked).
|
||||
AddBackwardReference(object_id, NULL);
|
||||
Dart_CObject* length = ReadObject();
|
||||
ASSERT(length->type == Dart_CObject::kInt32);
|
||||
for (int i = 0; i < length->value.as_int32; i++) {
|
||||
Dart_CObject* type = ReadObject();
|
||||
if (type != &dynamic_type_marker) return NULL;
|
||||
}
|
||||
return &type_arguments_marker;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kArrayClass: {
|
||||
intptr_t len = ReadSmiValue();
|
||||
Dart_CObject* value = AllocateDartCObjectArray(len);
|
||||
AddBackwardReference(object_id, value);
|
||||
// Skip type arguments.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated (currently type_arguments is leaked).
|
||||
Dart_CObject* type_arguments = ReadObject();
|
||||
if (type_arguments != &type_arguments_marker &&
|
||||
type_arguments->type != Dart_CObject::kNull) {
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
value->value.as_array.values[i] = ReadObject();
|
||||
}
|
||||
return value;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kDoubleClass: {
|
||||
// Read the double value for the object.
|
||||
Dart_CObject* object = AllocateDartCObjectDouble(Read<double>());
|
||||
AddBackwardReference(object_id, object);
|
||||
return object;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kOneByteStringClass: {
|
||||
intptr_t len = ReadSmiValue();
|
||||
intptr_t hash = ReadSmiValue();
|
||||
USE(hash);
|
||||
Dart_CObject* object = AllocateDartCObjectString(len);
|
||||
AddBackwardReference(object_id, object);
|
||||
char* p = object->value.as_string;
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*p = Read<uint8_t>();
|
||||
p++;
|
||||
}
|
||||
*p = '\0';
|
||||
return object;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kTwoByteStringClass:
|
||||
// Two byte strings not supported.
|
||||
return NULL;
|
||||
break;
|
||||
case ObjectStore::kFourByteStringClass:
|
||||
// Four byte strings not supported.
|
||||
return NULL;
|
||||
break;
|
||||
default:
|
||||
// Everything else not supported.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::ReadIndexedObject(intptr_t object_id) {
|
||||
if (object_id == Object::kNullObject) {
|
||||
return AllocateDartCObjectNull();
|
||||
} else if (object_id == ObjectStore::kTrueValue) {
|
||||
return AllocateDartCObjectBool(true);
|
||||
} else if (object_id == ObjectStore::kFalseValue) {
|
||||
return AllocateDartCObjectBool(false);
|
||||
} else if (object_id == ObjectStore::kDynamicType ||
|
||||
object_id == ObjectStore::kDoubleInterface ||
|
||||
object_id == ObjectStore::kIntInterface ||
|
||||
object_id == ObjectStore::kBoolInterface ||
|
||||
object_id == ObjectStore::kStringInterface) {
|
||||
// Always return dynamic type (this is only a marker).
|
||||
return &dynamic_type_marker;
|
||||
} else {
|
||||
intptr_t index = object_id - kMaxPredefinedObjectIds;
|
||||
ASSERT(index < backward_references_.length());
|
||||
ASSERT(backward_references_[index] != NULL);
|
||||
return backward_references_[index];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::ReadObjectImpl(intptr_t header) {
|
||||
SerializedHeaderType header_type = SerializedHeaderTag::decode(header);
|
||||
intptr_t header_value = SerializedHeaderData::decode(header);
|
||||
|
||||
if (header_type == kObjectId) {
|
||||
return ReadIndexedObject(header_value);
|
||||
}
|
||||
ASSERT(header_type == kInlined);
|
||||
return ReadInlinedObject(header_value);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::ReadObject() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
Dart_CObject* dart_value = AllocateDartCObjectInt32(value >> kSmiTagShift);
|
||||
return dart_value;
|
||||
}
|
||||
ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
|
||||
return ReadObjectImpl(value);
|
||||
}
|
||||
|
||||
|
||||
void ApiMessageReader::AddBackwardReference(intptr_t id, Dart_CObject* obj) {
|
||||
ASSERT((id - kMaxPredefinedObjectIds) == backward_references_.length());
|
||||
backward_references_.Add(obj);
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef VM_DART_API_MESSAGE_H_
|
||||
#define VM_DART_API_MESSAGE_H_
|
||||
|
||||
#include "vm/dart_api_state.h"
|
||||
#include "vm/snapshot.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
// Use this C structure for reading internal objects in the serialized
|
||||
// data. These are objects that we need to process in order to
|
||||
// generate the Dart_CObject graph but that we don't want to expose in
|
||||
// that graph.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated.
|
||||
struct Dart_CObject_Internal : public Dart_CObject {
|
||||
enum Type {
|
||||
kTypeArguments = Dart_CObject::kNumberOfTypes,
|
||||
kDynamicType,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Reads a message snapshot into a C structure.
|
||||
class ApiMessageReader : public BaseReader {
|
||||
public:
|
||||
ApiMessageReader(const uint8_t* buffer, intptr_t length, ReAlloc alloc);
|
||||
~ApiMessageReader() { }
|
||||
|
||||
Dart_CObject* ReadMessage();
|
||||
|
||||
private:
|
||||
// Allocates a Dart_CObject object.
|
||||
Dart_CObject* AllocateDartCObject();
|
||||
// Allocates a Dart_CObject object with the specified type.
|
||||
Dart_CObject* AllocateDartCObject(Dart_CObject::Type type);
|
||||
// Allocates a Dart_CObject object for the null object.
|
||||
Dart_CObject* AllocateDartCObjectNull();
|
||||
// Allocates a Dart_CObject object for a boolean object.
|
||||
Dart_CObject* AllocateDartCObjectBool(bool value);
|
||||
// Allocates a Dart_CObject object for for a 32-bit integer.
|
||||
Dart_CObject* AllocateDartCObjectInt32(int32_t value);
|
||||
// Allocates a Dart_CObject object for a double.
|
||||
Dart_CObject* AllocateDartCObjectDouble(double value);
|
||||
// Allocates a Dart_CObject object for string data.
|
||||
Dart_CObject* AllocateDartCObjectString(intptr_t length);
|
||||
// Allocates a C array of Dart_CObject objects.
|
||||
Dart_CObject* AllocateDartCObjectArray(intptr_t length);
|
||||
|
||||
void Init();
|
||||
|
||||
intptr_t LookupInternalClass(intptr_t class_header);
|
||||
Dart_CObject* ReadInlinedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObjectImpl(intptr_t header);
|
||||
Dart_CObject* ReadIndexedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObject();
|
||||
|
||||
// Add object to backward references.
|
||||
void AddBackwardReference(intptr_t id, Dart_CObject* obj);
|
||||
|
||||
Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
|
||||
ASSERT(object->type >= Dart_CObject::kNumberOfTypes);
|
||||
return reinterpret_cast<Dart_CObject_Internal*>(object);
|
||||
}
|
||||
|
||||
// Allocation of the structures for the decoded message happens
|
||||
// either in the supplied zone or using the supplied allocation
|
||||
// function.
|
||||
ReAlloc alloc_;
|
||||
ApiGrowableArray<Dart_CObject*> backward_references_;
|
||||
|
||||
Dart_CObject type_arguments_marker;
|
||||
Dart_CObject dynamic_type_marker;
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // VM_DART_API_MESSAGE_H_
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
|
||||
#include "include/dart_api.h"
|
||||
|
||||
#include "platform/thread.h"
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "vm/flags.h"
|
||||
#include "vm/growable_array.h"
|
||||
#include "vm/handles.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/os.h"
|
||||
@@ -46,8 +48,11 @@ class ApiZone {
|
||||
intptr_t SizeInBytes() const { return zone_.SizeInBytes(); }
|
||||
|
||||
private:
|
||||
BaseZone* GetBaseZone() { return &zone_; }
|
||||
|
||||
BaseZone zone_;
|
||||
|
||||
template<typename T> friend class ApiGrowableArray;
|
||||
DISALLOW_COPY_AND_ASSIGN(ApiZone);
|
||||
};
|
||||
|
||||
@@ -507,6 +512,49 @@ class ApiState {
|
||||
DISALLOW_COPY_AND_ASSIGN(ApiState);
|
||||
};
|
||||
|
||||
|
||||
class ApiNativeScope {
|
||||
public:
|
||||
ApiNativeScope() {
|
||||
// Currently no support for nesting native scopes.
|
||||
ASSERT(Current() == NULL);
|
||||
Thread::SetThreadLocal(Api::api_native_key_, reinterpret_cast<uword>(this));
|
||||
}
|
||||
|
||||
~ApiNativeScope() {
|
||||
ASSERT(Current() == this);
|
||||
Thread::SetThreadLocal(Api::api_native_key_, NULL);
|
||||
}
|
||||
|
||||
static inline ApiNativeScope* Current() {
|
||||
return reinterpret_cast<ApiNativeScope*>(
|
||||
Thread::GetThreadLocal(Api::api_native_key_));
|
||||
}
|
||||
|
||||
ApiZone* zone() { return &zone_; }
|
||||
|
||||
private:
|
||||
ApiZone zone_;
|
||||
};
|
||||
|
||||
|
||||
// Api growable arrays use a zone for allocation. The constructor
|
||||
// picks the zone from the current isolate if in an isolate
|
||||
// environment. When outside an isolate environment it picks the zone
|
||||
// from the current native scope.
|
||||
template<typename T>
|
||||
class ApiGrowableArray : public BaseGrowableArray<T, ValueObject> {
|
||||
public:
|
||||
explicit ApiGrowableArray(int initial_capacity)
|
||||
: BaseGrowableArray<T, ValueObject>(
|
||||
initial_capacity,
|
||||
ApiNativeScope::Current()->zone()->GetBaseZone()) {}
|
||||
ApiGrowableArray()
|
||||
: BaseGrowableArray<T, ValueObject>(
|
||||
ApiNativeScope::Current()->zone()->GetBaseZone()) {}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // VM_DART_API_STATE_H_
|
||||
|
||||
+19
-15
@@ -18,15 +18,14 @@ namespace dart {
|
||||
template<typename T, typename B>
|
||||
class BaseGrowableArray : public B {
|
||||
public:
|
||||
BaseGrowableArray() : length_(0), capacity_(0), data_(NULL), zone_(NULL) {
|
||||
ASSERT(Isolate::Current() != NULL);
|
||||
zone_ = Isolate::Current()->current_zone();
|
||||
explicit BaseGrowableArray(BaseZone* zone)
|
||||
: length_(0), capacity_(0), data_(NULL), zone_(zone) {
|
||||
ASSERT(zone_ != NULL);
|
||||
}
|
||||
|
||||
explicit BaseGrowableArray(int initial_capacity)
|
||||
: length_(0), capacity_(0), data_(NULL), zone_(NULL) {
|
||||
ASSERT(Isolate::Current() != NULL);
|
||||
zone_ = Isolate::Current()->current_zone();
|
||||
BaseGrowableArray(int initial_capacity, BaseZone* zone)
|
||||
: length_(0), capacity_(0), data_(NULL), zone_(zone) {
|
||||
ASSERT(zone_ != NULL);
|
||||
if (initial_capacity > 0) {
|
||||
capacity_ = Utils::RoundUpToPowerOfTwo(initial_capacity);
|
||||
data_ = reinterpret_cast<T*>(zone_->Allocate(capacity_ * sizeof(T)));
|
||||
@@ -76,7 +75,7 @@ class BaseGrowableArray : public B {
|
||||
int length_;
|
||||
int capacity_;
|
||||
T* data_;
|
||||
Zone* zone_; // Zone in which we are allocating the array.
|
||||
BaseZone* zone_; // Zone in which we are allocating the array.
|
||||
|
||||
void Resize(int new_length);
|
||||
|
||||
@@ -95,9 +94,6 @@ inline void BaseGrowableArray<T, B>::Sort(
|
||||
template<typename T, typename B>
|
||||
void BaseGrowableArray<T, B>::Resize(int new_length) {
|
||||
if (new_length > capacity_) {
|
||||
ASSERT(Isolate::Current() != NULL);
|
||||
// Check that we allocating in the array's zone.
|
||||
ASSERT(zone_ == Isolate::Current()->current_zone());
|
||||
int new_capacity = Utils::RoundUpToPowerOfTwo(new_length);
|
||||
T* new_data = reinterpret_cast<T*>(
|
||||
zone_->Reallocate(reinterpret_cast<uword>(data_),
|
||||
@@ -115,8 +111,12 @@ template<typename T>
|
||||
class GrowableArray : public BaseGrowableArray<T, ValueObject> {
|
||||
public:
|
||||
explicit GrowableArray(int initial_capacity)
|
||||
: BaseGrowableArray<T, ValueObject>(initial_capacity) {}
|
||||
GrowableArray() : BaseGrowableArray<T, ValueObject>() {}
|
||||
: BaseGrowableArray<T, ValueObject>(
|
||||
initial_capacity,
|
||||
Isolate::Current()->current_zone()->GetBaseZone()) {}
|
||||
GrowableArray()
|
||||
: BaseGrowableArray<T, ValueObject>(
|
||||
Isolate::Current()->current_zone()->GetBaseZone()) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -124,8 +124,12 @@ template<typename T>
|
||||
class ZoneGrowableArray : public BaseGrowableArray<T, ZoneAllocated> {
|
||||
public:
|
||||
explicit ZoneGrowableArray(int initial_capacity)
|
||||
: BaseGrowableArray<T, ZoneAllocated>(initial_capacity) {}
|
||||
ZoneGrowableArray() : BaseGrowableArray<T, ZoneAllocated>() {}
|
||||
: BaseGrowableArray<T, ZoneAllocated>(
|
||||
initial_capacity,
|
||||
Isolate::Current()->current_zone()->GetBaseZone()) {}
|
||||
ZoneGrowableArray() :
|
||||
BaseGrowableArray<T, ZoneAllocated>(
|
||||
Isolate::Current()->current_zone()->GetBaseZone()) {}
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
#include "vm/native_message_handler.h"
|
||||
|
||||
#include "vm/dart_api_message.h"
|
||||
#include "vm/isolate.h"
|
||||
#include "vm/message.h"
|
||||
#include "vm/snapshot.h"
|
||||
#include "vm/thread.h"
|
||||
|
||||
namespace dart {
|
||||
@@ -31,6 +33,14 @@ void NativeMessageHandler::CheckAccess() {
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t* zone_allocator(
|
||||
uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
|
||||
ApiZone* zone = ApiNativeScope::Current()->zone();
|
||||
return reinterpret_cast<uint8_t*>(
|
||||
zone->Reallocate(reinterpret_cast<uword>(ptr), old_size, new_size));
|
||||
}
|
||||
|
||||
|
||||
static void RunWorker(uword parameter) {
|
||||
NativeMessageHandler* handler =
|
||||
reinterpret_cast<NativeMessageHandler*>(parameter);
|
||||
@@ -47,12 +57,19 @@ static void RunWorker(uword parameter) {
|
||||
// dispatched to special vm code. Implement.
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
// TODO(sgjesse): Once CMessageReader::ReadObject is committed,
|
||||
// use that here and pass the resulting data object to the
|
||||
// handler instead.
|
||||
// Enter a native scope for handling the message. This will create a
|
||||
// zone for allocating the objects for decoding the message.
|
||||
ApiNativeScope scope;
|
||||
|
||||
int32_t length = reinterpret_cast<int32_t*>(
|
||||
message->data())[Snapshot::kLengthIndex];
|
||||
ApiMessageReader reader(message->data() + Snapshot::kHeaderSize,
|
||||
length,
|
||||
zone_allocator);
|
||||
Dart_CObject* object = reader.ReadMessage();
|
||||
(*handler->func())(message->dest_port(),
|
||||
message->reply_port(),
|
||||
message->data());
|
||||
object);
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,242 +437,6 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
|
||||
}
|
||||
|
||||
|
||||
CMessageReader::CMessageReader(const uint8_t* buffer,
|
||||
intptr_t length,
|
||||
ReAlloc alloc)
|
||||
: BaseReader(buffer, length),
|
||||
alloc_(alloc),
|
||||
backward_references_(kNumInitialReferences) {
|
||||
// Initialize marker objects used to handle Lists.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated.
|
||||
memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
|
||||
memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
|
||||
type_arguments_marker.type =
|
||||
static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kTypeArguments);
|
||||
dynamic_type_marker.type =
|
||||
static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kDynamicType);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::ReadMessage() {
|
||||
// Read the object out of the message.
|
||||
return ReadObject();
|
||||
}
|
||||
|
||||
intptr_t CMessageReader::LookupInternalClass(intptr_t class_header) {
|
||||
SerializedHeaderType header_type = SerializedHeaderTag::decode(class_header);
|
||||
ASSERT(header_type == kObjectId);
|
||||
intptr_t header_value = SerializedHeaderData::decode(class_header);
|
||||
return header_value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObject(Dart_CObject::Type type) {
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(
|
||||
alloc_(NULL, 0, sizeof(Dart_CObject)));
|
||||
value->type = type;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectNull() {
|
||||
return AllocateDartCObject(Dart_CObject::kNull);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectBool(bool val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kBool);
|
||||
value->value.as_bool = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectInt32(int32_t val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kInt32);
|
||||
value->value.as_int32 = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectDouble(double val) {
|
||||
Dart_CObject* value = AllocateDartCObject(Dart_CObject::kDouble);
|
||||
value->value.as_double = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectString(intptr_t length) {
|
||||
// Allocate a Dart_CObject structure followed by an array of chars
|
||||
// for the string content. The pointer to the string content is set
|
||||
// up to this area.
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(
|
||||
alloc_(NULL, 0, sizeof(Dart_CObject) + length + 1));
|
||||
value->value.as_string = reinterpret_cast<char*>(value) + sizeof(*value);
|
||||
value->type = Dart_CObject::kString;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::AllocateDartCObjectArray(intptr_t length) {
|
||||
// Allocate a Dart_CObject structure followed by an array of
|
||||
// pointers to Dart_CObject structures. The pointer to the array
|
||||
// content is set up to this area.
|
||||
Dart_CObject* value =
|
||||
reinterpret_cast<Dart_CObject*>(
|
||||
alloc_(NULL, 0, sizeof(Dart_CObject) + length * sizeof(value)));
|
||||
value->type = Dart_CObject::kArray;
|
||||
value->value.as_array.length = length;
|
||||
if (length > 0) {
|
||||
value->value.as_array.values = reinterpret_cast<Dart_CObject**>(value + 1);
|
||||
} else {
|
||||
value->value.as_array.values = NULL;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::ReadInlinedObject(intptr_t object_id) {
|
||||
// Read the class header information and lookup the class.
|
||||
intptr_t class_header = ReadIntptrValue();
|
||||
intptr_t tags = ReadIntptrValue();
|
||||
USE(tags);
|
||||
intptr_t class_id;
|
||||
|
||||
// Reading of regular dart instances is not supported.
|
||||
if (SerializedHeaderData::decode(class_header) == kInstanceId) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSERT((class_header & kSmiTagMask) != 0);
|
||||
class_id = LookupInternalClass(class_header);
|
||||
switch (class_id) {
|
||||
case Object::kClassClass: {
|
||||
return NULL;
|
||||
}
|
||||
case Object::kTypeArgumentsClass: {
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated (currently length is leaked).
|
||||
AddBackwardReference(object_id, NULL);
|
||||
Dart_CObject* length = ReadObject();
|
||||
ASSERT(length->type == Dart_CObject::kInt32);
|
||||
for (int i = 0; i < length->value.as_int32; i++) {
|
||||
Dart_CObject* type = ReadObject();
|
||||
if (type != &dynamic_type_marker) return NULL;
|
||||
}
|
||||
return &type_arguments_marker;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kArrayClass: {
|
||||
intptr_t len = ReadSmiValue();
|
||||
Dart_CObject* value = AllocateDartCObjectArray(len);
|
||||
AddBackwardReference(object_id, value);
|
||||
// Skip type arguments.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated (currently type_arguments is leaked).
|
||||
Dart_CObject* type_arguments = ReadObject();
|
||||
if (type_arguments != &type_arguments_marker &&
|
||||
type_arguments->type != Dart_CObject::kNull) {
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
value->value.as_array.values[i] = ReadObject();
|
||||
}
|
||||
return value;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kDoubleClass: {
|
||||
// Read the double value for the object.
|
||||
Dart_CObject* object = AllocateDartCObjectDouble(Read<double>());
|
||||
AddBackwardReference(object_id, object);
|
||||
return object;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kOneByteStringClass: {
|
||||
intptr_t len = ReadSmiValue();
|
||||
intptr_t hash = ReadSmiValue();
|
||||
USE(hash);
|
||||
Dart_CObject* object = AllocateDartCObjectString(len);
|
||||
AddBackwardReference(object_id, object);
|
||||
char* p = object->value.as_string;
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*p = Read<uint8_t>();
|
||||
p++;
|
||||
}
|
||||
*p = '\0';
|
||||
return object;
|
||||
break;
|
||||
}
|
||||
case ObjectStore::kTwoByteStringClass:
|
||||
// Two byte strings not supported.
|
||||
return NULL;
|
||||
break;
|
||||
case ObjectStore::kFourByteStringClass:
|
||||
// Four byte strings not supported.
|
||||
return NULL;
|
||||
break;
|
||||
default:
|
||||
// Everything else not supported.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::ReadIndexedObject(intptr_t object_id) {
|
||||
if (object_id == Object::kNullObject) {
|
||||
return AllocateDartCObjectNull();
|
||||
} else if (object_id == ObjectStore::kTrueValue) {
|
||||
return AllocateDartCObjectBool(true);
|
||||
} else if (object_id == ObjectStore::kFalseValue) {
|
||||
return AllocateDartCObjectBool(false);
|
||||
} else if (object_id == ObjectStore::kDynamicType ||
|
||||
object_id == ObjectStore::kDoubleInterface ||
|
||||
object_id == ObjectStore::kIntInterface ||
|
||||
object_id == ObjectStore::kBoolInterface ||
|
||||
object_id == ObjectStore::kStringInterface) {
|
||||
// Always return dynamic type (this is only a marker).
|
||||
return &dynamic_type_marker;
|
||||
} else {
|
||||
intptr_t index = object_id - kMaxPredefinedObjectIds;
|
||||
ASSERT(index < backward_references_.length());
|
||||
ASSERT(backward_references_[index] != NULL);
|
||||
return backward_references_[index];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::ReadObjectImpl(intptr_t header) {
|
||||
SerializedHeaderType header_type = SerializedHeaderTag::decode(header);
|
||||
intptr_t header_value = SerializedHeaderData::decode(header);
|
||||
|
||||
if (header_type == kObjectId) {
|
||||
return ReadIndexedObject(header_value);
|
||||
}
|
||||
ASSERT(header_type == kInlined);
|
||||
return ReadInlinedObject(header_value);
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* CMessageReader::ReadObject() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
Dart_CObject* dart_value = AllocateDartCObjectInt32(value >> kSmiTagShift);
|
||||
return dart_value;
|
||||
}
|
||||
ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
|
||||
return ReadObjectImpl(value);
|
||||
}
|
||||
|
||||
|
||||
void CMessageReader::AddBackwardReference(intptr_t id, Dart_CObject* obj) {
|
||||
ASSERT((id - kMaxPredefinedObjectIds) == backward_references_.length());
|
||||
backward_references_.Add(obj);
|
||||
}
|
||||
|
||||
|
||||
void MessageWriter::WriteMessage(intptr_t field_count, intptr_t *data) {
|
||||
// Write out the serialization header value for this object.
|
||||
WriteSerializationMarker(kInlined, kMaxPredefinedObjectIds);
|
||||
|
||||
@@ -404,68 +404,6 @@ class SnapshotReader : public BaseReader {
|
||||
};
|
||||
|
||||
|
||||
// Use this C structure for reading internal objects in the serialized
|
||||
// data. These are objects that we need to process in order to
|
||||
// generate the Dart_CObject graph but that we don't want to expose in
|
||||
// that graph.
|
||||
// TODO(sjesse): Remove this when message serialization format is
|
||||
// updated.
|
||||
struct Dart_CObject_Internal : public Dart_CObject {
|
||||
enum Type {
|
||||
kTypeArguments = Dart_CObject::kNumberOfTypes,
|
||||
kDynamicType,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Reads a message snapshot into C structure.
|
||||
class CMessageReader : public BaseReader {
|
||||
public:
|
||||
CMessageReader(const uint8_t* buffer, intptr_t length, ReAlloc alloc);
|
||||
~CMessageReader() { }
|
||||
|
||||
Dart_CObject* ReadMessage();
|
||||
|
||||
private:
|
||||
// Allocates a Dart_CObject object on the C heap.
|
||||
Dart_CObject* AllocateDartCObject();
|
||||
// Allocates a Dart_CObject object with the specified type on the C heap.
|
||||
Dart_CObject* AllocateDartCObject(Dart_CObject::Type type);
|
||||
// Allocates a Dart_CObject object for the null object on the C heap.
|
||||
Dart_CObject* AllocateDartCObjectNull();
|
||||
// Allocates a Dart_CObject object for a boolean object on the C heap.
|
||||
Dart_CObject* AllocateDartCObjectBool(bool value);
|
||||
// Allocates a Dart_CObject object for for a 32-bit integer on the C heap.
|
||||
Dart_CObject* AllocateDartCObjectInt32(int32_t value);
|
||||
// Allocates a Dart_CObject object for a double on the C heap.
|
||||
Dart_CObject* AllocateDartCObjectDouble(double value);
|
||||
// Allocates a Dart_CObject object for string data on the C heap.
|
||||
Dart_CObject* AllocateDartCObjectString(intptr_t length);
|
||||
// Allocates a C array of Dart_CObject objects on the C heap.
|
||||
Dart_CObject* AllocateDartCObjectArray(intptr_t length);
|
||||
|
||||
intptr_t LookupInternalClass(intptr_t class_header);
|
||||
Dart_CObject* ReadInlinedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObjectImpl(intptr_t header);
|
||||
Dart_CObject* ReadIndexedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObject();
|
||||
|
||||
// Add object to backward references.
|
||||
void AddBackwardReference(intptr_t id, Dart_CObject* obj);
|
||||
|
||||
Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
|
||||
ASSERT(object->type >= Dart_CObject::kNumberOfTypes);
|
||||
return reinterpret_cast<Dart_CObject_Internal*>(object);
|
||||
}
|
||||
|
||||
ReAlloc alloc_;
|
||||
GrowableArray<Dart_CObject*> backward_references_;
|
||||
|
||||
Dart_CObject type_arguments_marker;
|
||||
Dart_CObject dynamic_type_marker;
|
||||
};
|
||||
|
||||
|
||||
class BaseWriter {
|
||||
public:
|
||||
// Size of the snapshot.
|
||||
|
||||
+23
-10
@@ -7,6 +7,7 @@
|
||||
#include "vm/bigint_operations.h"
|
||||
#include "vm/class_finalizer.h"
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "vm/dart_api_message.h"
|
||||
#include "vm/dart_api_state.h"
|
||||
#include "vm/snapshot.h"
|
||||
#include "vm/unit_test.h"
|
||||
@@ -55,7 +56,7 @@ static uint8_t* zone_allocator(
|
||||
static Dart_CObject* DecodeMessage(uint8_t* message,
|
||||
intptr_t length,
|
||||
ReAlloc allocator) {
|
||||
CMessageReader message_reader(message, length, allocator);
|
||||
ApiMessageReader message_reader(message, length, allocator);
|
||||
return message_reader.ReadMessage();
|
||||
}
|
||||
|
||||
@@ -107,7 +108,6 @@ static void CheckEncodeDecodeMessage(Dart_CObject* root) {
|
||||
MessageWriter writer(&buffer, &malloc_allocator);
|
||||
writer.WriteCMessage(root);
|
||||
|
||||
Zone zone(Isolate::Current());
|
||||
Dart_CObject* new_root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -135,6 +135,7 @@ TEST_CASE(SerializeNull) {
|
||||
EXPECT(Equals(null_object, serialized_object));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -163,6 +164,7 @@ TEST_CASE(SerializeSmi1) {
|
||||
EXPECT(Equals(smi, serialized_object));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -192,6 +194,7 @@ TEST_CASE(SerializeSmi2) {
|
||||
EXPECT(Equals(smi, serialized_object));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -221,6 +224,7 @@ TEST_CASE(SerializeDouble) {
|
||||
EXPECT(Equals(dbl, serialized_object));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -267,6 +271,7 @@ TEST_CASE(SerializeTrue) {
|
||||
Snapshot::SetupFromBuffer(buffer);
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -291,6 +296,7 @@ TEST_CASE(SerializeFalse) {
|
||||
Snapshot::SetupFromBuffer(buffer);
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -322,6 +328,7 @@ TEST_CASE(SerializeBigint) {
|
||||
EXPECT_EQ(BigintOperations::ToInt64(bigint), BigintOperations::ToInt64(obj));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -405,6 +412,7 @@ TEST_CASE(SerializeString) {
|
||||
EXPECT(str.Equals(serialized_str));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -440,6 +448,7 @@ TEST_CASE(SerializeArray) {
|
||||
EXPECT(array.Equals(serialized_array));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -475,6 +484,7 @@ TEST_CASE(SerializeEmptyArray) {
|
||||
EXPECT(array.Equals(serialized_array));
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -803,6 +813,7 @@ TEST_CASE(IntArrayMessage) {
|
||||
writer.WriteMessage(len, data);
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -892,6 +903,7 @@ UNIT_TEST_CASE(DartGeneratedMessages) {
|
||||
writer.FinalizeBuffer();
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -910,6 +922,7 @@ UNIT_TEST_CASE(DartGeneratedMessages) {
|
||||
writer.FinalizeBuffer();
|
||||
|
||||
// Read object back from the snapshot into a C structure.
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = DecodeMessage(buffer + Snapshot::kHeaderSize,
|
||||
writer.BytesWritten(),
|
||||
&zone_allocator);
|
||||
@@ -962,7 +975,7 @@ UNIT_TEST_CASE(DartGeneratedListMessages) {
|
||||
DARTSCOPE_NOCHECKS(isolate);
|
||||
{
|
||||
// Generate a list of nulls from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -974,7 +987,7 @@ UNIT_TEST_CASE(DartGeneratedListMessages) {
|
||||
}
|
||||
{
|
||||
// Generate a list of ints from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getIntList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -987,7 +1000,7 @@ UNIT_TEST_CASE(DartGeneratedListMessages) {
|
||||
}
|
||||
{
|
||||
// Generate a list of strings from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getStringList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -1001,7 +1014,7 @@ UNIT_TEST_CASE(DartGeneratedListMessages) {
|
||||
}
|
||||
{
|
||||
// Generate a list of objects of different types from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getMixedList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -1072,7 +1085,7 @@ UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
|
||||
|
||||
{
|
||||
// Generate a list of strings from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getStringList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -1086,7 +1099,7 @@ UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
|
||||
}
|
||||
{
|
||||
// Generate a list of doubles from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getDoubleList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -1100,7 +1113,7 @@ UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
|
||||
}
|
||||
{
|
||||
// Generate a list of objects of different types from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getMixedList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
@@ -1120,7 +1133,7 @@ UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
|
||||
}
|
||||
{
|
||||
// Generate a list of objects of different types from Dart code.
|
||||
Zone zone(Isolate::Current());
|
||||
ApiNativeScope scope;
|
||||
Dart_CObject* root = GetDeserializedDartMessage(lib, "getSelfRefList");
|
||||
EXPECT_NOTNULL(root);
|
||||
EXPECT_EQ(Dart_CObject::kArray, root->type);
|
||||
|
||||
@@ -81,6 +81,8 @@
|
||||
'dart_api_impl.h',
|
||||
'dart_api_state.h',
|
||||
'dart_api_impl_test.cc',
|
||||
'dart_api_message.cc',
|
||||
'dart_api_message.h',
|
||||
'dart_entry.cc',
|
||||
'dart_entry.h',
|
||||
'dart_entry_test.cc',
|
||||
|
||||
@@ -91,6 +91,7 @@ class BaseZone {
|
||||
|
||||
friend class Zone;
|
||||
friend class ApiZone;
|
||||
template<typename T, typename B> friend class BaseGrowableArray;
|
||||
DISALLOW_COPY_AND_ASSIGN(BaseZone);
|
||||
};
|
||||
|
||||
@@ -127,6 +128,8 @@ class Zone : public StackResource {
|
||||
void VisitObjectPointers(ObjectPointerVisitor* visitor);
|
||||
|
||||
private:
|
||||
BaseZone* GetBaseZone() { return &zone_; }
|
||||
|
||||
BaseZone zone_;
|
||||
|
||||
// Structure for managing handles allocation.
|
||||
@@ -134,6 +137,10 @@ class Zone : public StackResource {
|
||||
|
||||
// Used for chaining zones in order to allow unwinding of stacks.
|
||||
Zone* previous_;
|
||||
|
||||
template<typename T> friend class GrowableArray;
|
||||
template<typename T> friend class ZoneGrowableArray;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Zone);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user