Skip to content

Instantly share code, notes, and snippets.

@billywhizz
Last active October 18, 2020 00:09
Show Gist options
  • Save billywhizz/ff4c83c37142198d2e70992e438bf045 to your computer and use it in GitHub Desktop.
Save billywhizz/ff4c83c37142198d2e70992e438bf045 to your computer and use it in GitHub Desktop.
v8 backingstore mutexes on access

v8 version

8.5.210.27

platform

linux, Ubuntu 18.06

arch

x86_64

v8 build flags

https://github.com/just-js/libv8/blob/main/Dockerfile#L13

Problem

using

  Local<ArrayBuffer> buf = args[1].As<ArrayBuffer>();
  std::shared_ptr<BackingStore> backing = buf->GetBackingStore();
  const char* source = (const char*)backing->Data() + off;

we see this, with a mutex lock and unlock for buf->GetBackingStore();

<... epoll_wait resumed> )                                                                                         = 1
pthread_mutex_lock(0x55e5eaa619c8, 0xec692cf0, 0x55e5ec695e00, 0x55e5ec695810)                                     = 0
pthread_mutex_unlock(0x55e5eaa619c8, 0, 0, 0)                                                                      = 0
write(0, "omg\n", 4 <unfinished ...>
SYS_write(0, "omg\n", 4omg)
<... write resumed> )                                                                                              = 6
pthread_mutex_lock(0x55e5eaa619c8, 0xec695900, 0x55e5ec6957f0, 0x55e5ec695950)                                     = 0
pthread_mutex_unlock(0x55e5eaa619c8, 0, 0, 0)                                                                      = 0
read(7 <unfinished ...>
SYS_read(7, "\001", 8)                                                                                             = 8
<... read resumed> , "\001", 8)                                                                                    = 8
pthread_mutex_lock(0x55e5eaa619c8, 0xec692cc0, 0x55e5ec707ab0, 0x55e5ec6957b0)                                     = 0
pthread_mutex_unlock(0x55e5eaa619c8, 0, 0, 0)                                                                      = 0
epoll_wait(6, 0x55e5ec695e20, 1024, 0xffffffff <unfinished ...>
SYS_epoll_wait(6, 0x55e5ec695e20, 1024, 0xffffffff

using

  Local<ArrayBuffer> buf = args[1].As<ArrayBuffer>();
  const char* source = (char*)buf->GetAlignedPointerFromInternalField(1);

we see this, no mutexes involved

<... epoll_wait resumed> )                              = 1
write(0, "omg\n", 4 <unfinished ...>
SYS_write(0, "omg\n", 4omg)
<... write resumed> )                                   = 4
read(7 <unfinished ...>
SYS_read(7, "\001", 8)                                  = 8
<... read resumed> , "\001", 8)                         = 8
epoll_wait(6, 0x55ebc89fd690, 1024, 0xffffffff <unfinished ...>
SYS_epoll_wait(6, 0x55ebc89fd690, 1024, 0xffffffff

this ends up in src/heap/array-buffer-tracker-inl.h

l. 75: https://github.com/v8/v8/blob/8.5.210/src/heap/array-buffer-tracker-inl.h#L75

std::shared_ptr<BackingStore> ArrayBufferTracker::Lookup(Heap* heap,
                                                         JSArrayBuffer buffer) {
  if (buffer.backing_store() == nullptr) return {};

  Page* page = Page::FromHeapObject(buffer);
  base::MutexGuard guard(page->mutex());
  LocalArrayBufferTracker* tracker = page->local_tracker();
  DCHECK_NOT_NULL(tracker);
  return tracker->Lookup(buffer);
}

this commit

https://github.com/v8/v8/commit/b6b7de0d60b1dc4b72e953828e1d8d7333d1f6ce

void DoSomething(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
HandleScope handleScope(isolate);
Local<ArrayBuffer> ab = args[0].As<ArrayBuffer>();
// check if we have an internal pointer to the backing data
void* data = ab->GetAlignedPointerFromInternalField(1);
if (!data) {
std::shared_ptr<BackingStore> backing = ab->GetBackingStore();
data = backing->Data();
// set the internal pointer so we don't have to call GetBackingStore() every time
cb->SetAlignedPointerInInternalField(1, data);
}
// do something with data
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment