Index: runtime/vm/dart_api_impl.cc |
=================================================================== |
--- runtime/vm/dart_api_impl.cc (revision 43108) |
+++ runtime/vm/dart_api_impl.cc (working copy) |
@@ -47,6 +47,8 @@ |
"Check function fingerprints"); |
DEFINE_FLAG(bool, trace_api, false, |
"Trace invocation of API calls (debug mode only)"); |
+DEFINE_FLAG(bool, verify_acquired_data, false, |
+ "Verify correct API acquire/release of typed data."); |
ThreadLocalKey Api::api_native_key_ = OSThread::kUnsetThreadLocalKey; |
Dart_Handle Api::true_handle_ = NULL; |
@@ -3434,6 +3436,20 @@ |
*data = data_obj.DataAddr(offset_in_bytes); |
} |
} |
+ if (FLAG_verify_acquired_data) { |
+ // For now, we just verify that acquire/release are properly matched |
+ // per object. |
+ // TODO(koda): Copy internal data to/from a side buffer which is unmapped |
+ // on release to catch use-after-release bugs. |
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); |
+ WeakTable* table = isolate->api_state()->acquired_table(); |
+ intptr_t current = table->GetValue(obj.raw()); |
+ if (current != 0) { |
+ ASSERT(current == 1); |
+ return Api::NewError("Data was already acquired for this object."); |
+ } |
+ table->SetValue(obj.raw(), 1); |
+ } |
return Api::Success(); |
} |
@@ -3451,6 +3467,17 @@ |
isolate->DecrementNoGCScopeDepth(); |
END_NO_CALLBACK_SCOPE(isolate); |
} |
+ if (FLAG_verify_acquired_data) { |
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); |
+ WeakTable* table = isolate->api_state()->acquired_table(); |
+ intptr_t current = table->GetValue(obj.raw()); |
+ if (current != 1) { |
+ ASSERT(current == 0); |
+ return Api::NewError("Data was not acquired for this object."); |
+ } |
+ // Delete entry from table. |
+ table->SetValue(obj.raw(), 0); |
+ } |
return Api::Success(); |
} |