| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "include/dart_api.h" | 5 #include "include/dart_api.h" |
| 6 #include "include/dart_mirrors_api.h" | 6 #include "include/dart_mirrors_api.h" |
| 7 #include "include/dart_native_api.h" | 7 #include "include/dart_native_api.h" |
| 8 | 8 |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 3380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3391 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(typed_data)); | 3391 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(typed_data)); |
| 3392 args.SetAt(1, obj); | 3392 args.SetAt(1, obj); |
| 3393 | 3393 |
| 3394 // Invoke the factory constructor and return the new object. | 3394 // Invoke the factory constructor and return the new object. |
| 3395 result = DartEntry::InvokeFunction(factory, args); | 3395 result = DartEntry::InvokeFunction(factory, args); |
| 3396 ASSERT(result.IsInstance() || result.IsNull() || result.IsError()); | 3396 ASSERT(result.IsInstance() || result.IsNull() || result.IsError()); |
| 3397 return Api::NewHandle(isolate, result.raw()); | 3397 return Api::NewHandle(isolate, result.raw()); |
| 3398 } | 3398 } |
| 3399 | 3399 |
| 3400 | 3400 |
| 3401 // Structure to record acquired typed data for verification purposes. |
| 3402 class AcquiredData { |
| 3403 public: |
| 3404 AcquiredData(void* data, intptr_t size_in_bytes, bool copy) |
| 3405 : size_in_bytes_(size_in_bytes), data_(data), data_copy_(NULL) { |
| 3406 if (copy) { |
| 3407 data_copy_ = malloc(size_in_bytes_); |
| 3408 memmove(data_copy_, data_, size_in_bytes_); |
| 3409 } |
| 3410 } |
| 3411 |
| 3412 // The pointer to hand out via the API. |
| 3413 void* GetData() const { return data_copy_ != NULL ? data_copy_ : data_; } |
| 3414 |
| 3415 // Writes back and deletes/zaps, if a copy was made. |
| 3416 ~AcquiredData() { |
| 3417 if (data_copy_ != NULL) { |
| 3418 memmove(data_, data_copy_, size_in_bytes_); |
| 3419 memset(data_copy_, kZapReleasedByte, size_in_bytes_); |
| 3420 free(data_copy_); |
| 3421 } |
| 3422 } |
| 3423 |
| 3424 private: |
| 3425 static const uint8_t kZapReleasedByte = 0xda; |
| 3426 intptr_t size_in_bytes_; |
| 3427 void* data_; |
| 3428 void* data_copy_; |
| 3429 |
| 3430 DISALLOW_COPY_AND_ASSIGN(AcquiredData); |
| 3431 }; |
| 3432 |
| 3433 |
| 3401 DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, | 3434 DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, |
| 3402 Dart_TypedData_Type* type, | 3435 Dart_TypedData_Type* type, |
| 3403 void** data, | 3436 void** data, |
| 3404 intptr_t* len) { | 3437 intptr_t* len) { |
| 3405 Isolate* isolate = Isolate::Current(); | 3438 Isolate* isolate = Isolate::Current(); |
| 3406 DARTSCOPE(isolate); | 3439 DARTSCOPE(isolate); |
| 3407 intptr_t class_id = Api::ClassId(object); | 3440 intptr_t class_id = Api::ClassId(object); |
| 3408 if (!RawObject::IsExternalTypedDataClassId(class_id) && | 3441 if (!RawObject::IsExternalTypedDataClassId(class_id) && |
| 3409 !RawObject::IsTypedDataViewClassId(class_id) && | 3442 !RawObject::IsTypedDataViewClassId(class_id) && |
| 3410 !RawObject::IsTypedDataClassId(class_id)) { | 3443 !RawObject::IsTypedDataClassId(class_id)) { |
| 3411 RETURN_TYPE_ERROR(isolate, object, 'TypedData'); | 3444 RETURN_TYPE_ERROR(isolate, object, 'TypedData'); |
| 3412 } | 3445 } |
| 3413 if (type == NULL) { | 3446 if (type == NULL) { |
| 3414 RETURN_NULL_ERROR(type); | 3447 RETURN_NULL_ERROR(type); |
| 3415 } | 3448 } |
| 3416 if (data == NULL) { | 3449 if (data == NULL) { |
| 3417 RETURN_NULL_ERROR(data); | 3450 RETURN_NULL_ERROR(data); |
| 3418 } | 3451 } |
| 3419 if (len == NULL) { | 3452 if (len == NULL) { |
| 3420 RETURN_NULL_ERROR(len); | 3453 RETURN_NULL_ERROR(len); |
| 3421 } | 3454 } |
| 3422 // Get the type of typed data object. | 3455 // Get the type of typed data object. |
| 3423 *type = GetType(class_id); | 3456 *type = GetType(class_id); |
| 3457 intptr_t length = 0; |
| 3458 intptr_t size_in_bytes = 0; |
| 3459 void* data_tmp = NULL; |
| 3460 bool external = false; |
| 3424 // If it is an external typed data object just return the data field. | 3461 // If it is an external typed data object just return the data field. |
| 3425 if (RawObject::IsExternalTypedDataClassId(class_id)) { | 3462 if (RawObject::IsExternalTypedDataClassId(class_id)) { |
| 3426 const ExternalTypedData& obj = | 3463 const ExternalTypedData& obj = |
| 3427 Api::UnwrapExternalTypedDataHandle(isolate, object); | 3464 Api::UnwrapExternalTypedDataHandle(isolate, object); |
| 3428 ASSERT(!obj.IsNull()); | 3465 ASSERT(!obj.IsNull()); |
| 3429 *len = obj.Length(); | 3466 length = obj.Length(); |
| 3430 *data = obj.DataAddr(0); | 3467 size_in_bytes = length * ExternalTypedData::ElementSizeInBytes(class_id); |
| 3468 data_tmp = obj.DataAddr(0); |
| 3469 external = true; |
| 3431 } else if (RawObject::IsTypedDataClassId(class_id)) { | 3470 } else if (RawObject::IsTypedDataClassId(class_id)) { |
| 3432 // Regular typed data object, set up some GC and API callback guards. | 3471 // Regular typed data object, set up some GC and API callback guards. |
| 3433 const TypedData& obj = Api::UnwrapTypedDataHandle(isolate, object); | 3472 const TypedData& obj = Api::UnwrapTypedDataHandle(isolate, object); |
| 3434 ASSERT(!obj.IsNull()); | 3473 ASSERT(!obj.IsNull()); |
| 3435 *len = obj.Length(); | 3474 length = obj.Length(); |
| 3475 size_in_bytes = length * TypedData::ElementSizeInBytes(class_id); |
| 3436 isolate->IncrementNoGCScopeDepth(); | 3476 isolate->IncrementNoGCScopeDepth(); |
| 3437 START_NO_CALLBACK_SCOPE(isolate); | 3477 START_NO_CALLBACK_SCOPE(isolate); |
| 3438 *data = obj.DataAddr(0); | 3478 data_tmp = obj.DataAddr(0); |
| 3439 } else { | 3479 } else { |
| 3440 ASSERT(RawObject::IsTypedDataViewClassId(class_id)); | 3480 ASSERT(RawObject::IsTypedDataViewClassId(class_id)); |
| 3441 const Instance& view_obj = Api::UnwrapInstanceHandle(isolate, object); | 3481 const Instance& view_obj = Api::UnwrapInstanceHandle(isolate, object); |
| 3442 ASSERT(!view_obj.IsNull()); | 3482 ASSERT(!view_obj.IsNull()); |
| 3443 Smi& val = Smi::Handle(); | 3483 Smi& val = Smi::Handle(); |
| 3444 val ^= TypedDataView::Length(view_obj); | 3484 val ^= TypedDataView::Length(view_obj); |
| 3445 *len = val.Value(); | 3485 length = val.Value(); |
| 3486 size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id); |
| 3446 val ^= TypedDataView::OffsetInBytes(view_obj); | 3487 val ^= TypedDataView::OffsetInBytes(view_obj); |
| 3447 intptr_t offset_in_bytes = val.Value(); | 3488 intptr_t offset_in_bytes = val.Value(); |
| 3448 const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj)); | 3489 const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj)); |
| 3449 isolate->IncrementNoGCScopeDepth(); | 3490 isolate->IncrementNoGCScopeDepth(); |
| 3450 START_NO_CALLBACK_SCOPE(isolate); | 3491 START_NO_CALLBACK_SCOPE(isolate); |
| 3451 if (TypedData::IsTypedData(obj)) { | 3492 if (TypedData::IsTypedData(obj)) { |
| 3452 const TypedData& data_obj = TypedData::Cast(obj); | 3493 const TypedData& data_obj = TypedData::Cast(obj); |
| 3453 *data = data_obj.DataAddr(offset_in_bytes); | 3494 data_tmp = data_obj.DataAddr(offset_in_bytes); |
| 3454 } else { | 3495 } else { |
| 3455 ASSERT(ExternalTypedData::IsExternalTypedData(obj)); | 3496 ASSERT(ExternalTypedData::IsExternalTypedData(obj)); |
| 3456 const ExternalTypedData& data_obj = ExternalTypedData::Cast(obj); | 3497 const ExternalTypedData& data_obj = ExternalTypedData::Cast(obj); |
| 3457 *data = data_obj.DataAddr(offset_in_bytes); | 3498 data_tmp = data_obj.DataAddr(offset_in_bytes); |
| 3499 external = true; |
| 3458 } | 3500 } |
| 3459 } | 3501 } |
| 3460 if (FLAG_verify_acquired_data) { | 3502 if (FLAG_verify_acquired_data) { |
| 3461 // For now, we just verify that acquire/release are properly matched | |
| 3462 // per object. | |
| 3463 // TODO(koda): Copy internal data to/from a side buffer which is unmapped | |
| 3464 // on release to catch use-after-release bugs. | |
| 3465 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); | 3503 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); |
| 3466 WeakTable* table = isolate->api_state()->acquired_table(); | 3504 WeakTable* table = isolate->api_state()->acquired_table(); |
| 3467 intptr_t current = table->GetValue(obj.raw()); | 3505 intptr_t current = table->GetValue(obj.raw()); |
| 3468 if (current != 0) { | 3506 if (current != 0) { |
| 3469 ASSERT(current == 1); | |
| 3470 return Api::NewError("Data was already acquired for this object."); | 3507 return Api::NewError("Data was already acquired for this object."); |
| 3471 } | 3508 } |
| 3472 table->SetValue(obj.raw(), 1); | 3509 // Do not make a copy if the data is external. Some callers expect external |
| 3510 // data to remain in place, even though the API spec doesn't guarantee it. |
| 3511 // TODO(koda/asiva): Make final decision and document it. |
| 3512 AcquiredData* ad = new AcquiredData(data_tmp, size_in_bytes, !external); |
| 3513 table->SetValue(obj.raw(), reinterpret_cast<intptr_t>(ad)); |
| 3514 data_tmp = ad->GetData(); |
| 3473 } | 3515 } |
| 3516 *data = data_tmp; |
| 3517 *len = length; |
| 3474 return Api::Success(); | 3518 return Api::Success(); |
| 3475 } | 3519 } |
| 3476 | 3520 |
| 3477 | 3521 |
| 3478 DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) { | 3522 DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) { |
| 3479 Isolate* isolate = Isolate::Current(); | 3523 Isolate* isolate = Isolate::Current(); |
| 3480 DARTSCOPE(isolate); | 3524 DARTSCOPE(isolate); |
| 3481 intptr_t class_id = Api::ClassId(object); | 3525 intptr_t class_id = Api::ClassId(object); |
| 3482 if (!RawObject::IsExternalTypedDataClassId(class_id) && | 3526 if (!RawObject::IsExternalTypedDataClassId(class_id) && |
| 3483 !RawObject::IsTypedDataViewClassId(class_id) && | 3527 !RawObject::IsTypedDataViewClassId(class_id) && |
| 3484 !RawObject::IsTypedDataClassId(class_id)) { | 3528 !RawObject::IsTypedDataClassId(class_id)) { |
| 3485 RETURN_TYPE_ERROR(isolate, object, 'TypedData'); | 3529 RETURN_TYPE_ERROR(isolate, object, 'TypedData'); |
| 3486 } | 3530 } |
| 3487 if (!RawObject::IsExternalTypedDataClassId(class_id)) { | 3531 if (!RawObject::IsExternalTypedDataClassId(class_id)) { |
| 3488 isolate->DecrementNoGCScopeDepth(); | 3532 isolate->DecrementNoGCScopeDepth(); |
| 3489 END_NO_CALLBACK_SCOPE(isolate); | 3533 END_NO_CALLBACK_SCOPE(isolate); |
| 3490 } | 3534 } |
| 3491 if (FLAG_verify_acquired_data) { | 3535 if (FLAG_verify_acquired_data) { |
| 3492 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); | 3536 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); |
| 3493 WeakTable* table = isolate->api_state()->acquired_table(); | 3537 WeakTable* table = isolate->api_state()->acquired_table(); |
| 3494 intptr_t current = table->GetValue(obj.raw()); | 3538 intptr_t current = table->GetValue(obj.raw()); |
| 3495 if (current != 1) { | 3539 if (current == 0) { |
| 3496 ASSERT(current == 0); | |
| 3497 return Api::NewError("Data was not acquired for this object."); | 3540 return Api::NewError("Data was not acquired for this object."); |
| 3498 } | 3541 } |
| 3499 // Delete entry from table. | 3542 AcquiredData* ad = reinterpret_cast<AcquiredData*>(current); |
| 3500 table->SetValue(obj.raw(), 0); | 3543 table->SetValue(obj.raw(), 0); // Delete entry from table. |
| 3544 delete ad; |
| 3501 } | 3545 } |
| 3502 return Api::Success(); | 3546 return Api::Success(); |
| 3503 } | 3547 } |
| 3504 | 3548 |
| 3505 | 3549 |
| 3506 DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object) { | 3550 DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object) { |
| 3507 Isolate* isolate = Isolate::Current(); | 3551 Isolate* isolate = Isolate::Current(); |
| 3508 CHECK_ISOLATE(isolate); | 3552 CHECK_ISOLATE(isolate); |
| 3509 intptr_t class_id = Api::ClassId(object); | 3553 intptr_t class_id = Api::ClassId(object); |
| 3510 if (class_id != kByteBufferCid) { | 3554 if (class_id != kByteBufferCid) { |
| (...skipping 1965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5476 | 5520 |
| 5477 | 5521 |
| 5478 DART_EXPORT void Dart_RegisterRootServiceRequestCallback( | 5522 DART_EXPORT void Dart_RegisterRootServiceRequestCallback( |
| 5479 const char* name, | 5523 const char* name, |
| 5480 Dart_ServiceRequestCallback callback, | 5524 Dart_ServiceRequestCallback callback, |
| 5481 void* user_data) { | 5525 void* user_data) { |
| 5482 Service::RegisterRootEmbedderCallback(name, callback, user_data); | 5526 Service::RegisterRootEmbedderCallback(name, callback, user_data); |
| 5483 } | 5527 } |
| 5484 | 5528 |
| 5485 } // namespace dart | 5529 } // namespace dart |
| OLD | NEW |