| 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();
|
| }
|
|
|
|
|