Handle<Value> CreateExternalArrayBuffer(int32_t length, uint8_t *data) { Handle<Object> buffer = Object::New(); buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True()); Persistent<Object> persistent_array = Persistent<Object>::New(buffer); persistent_array.MakeWeak(data, ExternalArrayWeakCallback); persistent_array.MarkIndependent(); buffer->SetIndexedPropertiesToExternalArrayData( data, v8::kExternalByteArray, length); buffer->Set(String::New("byteLength"), Int32::New(length), ReadOnly); buffer->Set(String::New("address"), Int32::New(reinterpret_cast<uint32_t>(data)), ReadOnly); return buffer; }
static gboolean gum_script_event_sink_drain (gpointer user_data) { GumScriptEventSink * self = GUM_SCRIPT_EVENT_SINK (user_data); gpointer buffer = NULL; guint len, size; if (self->core == NULL) return FALSE; len = self->queue->len; size = len * sizeof (GumEvent); if (len != 0) { buffer = g_memdup (self->queue->data, size); gum_spinlock_acquire (&self->lock); g_array_remove_range (self->queue, 0, len); gum_spinlock_release (&self->lock); } if (buffer != NULL) { GHashTable * frequencies = NULL; if (!self->on_call_summary.IsEmpty ()) { frequencies = g_hash_table_new (NULL, NULL); GumCallEvent * ev = static_cast<GumCallEvent *> (buffer); for (guint i = 0; i != len; i++) { if (ev->type == GUM_CALL) { gsize count = GPOINTER_TO_SIZE ( g_hash_table_lookup (frequencies, ev->target)); count++; g_hash_table_insert (frequencies, ev->target, GSIZE_TO_POINTER (count)); } ev++; } } ScriptScope scope (self->core->script); if (frequencies != NULL) { Handle<Object> summary = Object::New (); GHashTableIter iter; g_hash_table_iter_init (&iter, frequencies); gpointer target, count; while (g_hash_table_iter_next (&iter, &target, &count)) { summary->Set (_gum_script_pointer_new (self->core, target), Number::New (GPOINTER_TO_SIZE (count)), ReadOnly); } g_hash_table_unref (frequencies); Handle<Value> argv[] = { summary }; self->on_call_summary->Call (self->on_call_summary, 1, argv); } if (!self->on_receive.IsEmpty ()) { V8::AdjustAmountOfExternalAllocatedMemory (size); Handle<Object> data = Object::New (); data->Set (String::New ("length"), Int32::New (size), ReadOnly); data->SetIndexedPropertiesToExternalArrayData (buffer, kExternalUnsignedByteArray, size); Persistent<Object> persistent_data = Persistent<Object>::New (data); persistent_data.MakeWeak (buffer, gum_script_event_sink_data_free); persistent_data.MarkIndependent (); Handle<Value> argv[] = { data }; self->on_receive->Call (self->on_receive, 1, argv); } else { g_free (buffer); } } return TRUE; }
Handle<Value> CreateExternalArray(const Arguments& args, ExternalArrayType type, size_t element_size) { TryCatch try_catch; ASSERT_PIN(element_size == 1 || element_size == 2 || element_size == 4 || element_size == 8, "CreateExternalArray"); // Currently, only the following constructors are supported: // TypedArray(unsigned long length) // TypedArray(ArrayBuffer buffer, // optional unsigned long byteOffset, // optional unsigned long length) Handle<Object> buffer; int32_t length; int32_t byteLength; int32_t byteOffset; int32_t bufferLength; if (args.Length() == 0) { return ThrowException( String::New("Array constructor must have at least one parameter.")); } if (args[0]->IsObject() && (!args[0]->ToObject()->GetHiddenValue(String::New(kArrayBufferMarkerPropName)).IsEmpty()) || (IS_BINARY(args[0]))) { if (!args[0]->ToObject()->GetHiddenValue(String::New(kArrayBufferMarkerPropName)).IsEmpty()) { buffer = args[0]->ToObject(); bufferLength = convertToUint(buffer->Get(String::New("byteLength")), &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); } else { buffer = CreateExternalArrayBuffer(args[0])->ToObject(); bufferLength = convertToUint(buffer->Get(String::New("byteLength")), &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); } if (args.Length() < 2 || args[1]->IsUndefined()) { byteOffset = 0; } else { byteOffset = convertToUint(args[1], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); if (byteOffset > bufferLength) { return ThrowException(String::New("byteOffset out of bounds")); } if (byteOffset % element_size != 0) { return ThrowException( String::New("byteOffset must be multiple of element_size")); } } if (args.Length() < 3 || args[2]->IsUndefined()) { byteLength = bufferLength - byteOffset; length = byteLength / element_size; if (byteLength % element_size != 0) { return ThrowException( String::New("buffer size must be multiple of element_size")); } } else { length = convertToUint(args[2], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); byteLength = length * element_size; if (byteOffset + byteLength > bufferLength) { return ThrowException(String::New("length out of bounds")); } } } else { length = convertToUint(args[0], &try_catch); byteLength = length * element_size; byteOffset = 0; Handle<Value> result = CreateExternalArrayBuffer(byteLength); if (!result->IsObject()) return result; buffer = result->ToObject(); } void* data = buffer->GetIndexedPropertiesExternalArrayData(); ASSERT_PIN(data != NULL, "CreateExternalArray data != NULL"); Handle<Object> array = Object::New(); array->SetIndexedPropertiesToExternalArrayData( static_cast<uint8_t*>(data) + byteOffset, type, length); array->Set(String::New("byteLength"), Int32::New(byteLength), ReadOnly); array->Set(String::New("byteOffset"), Int32::New(byteOffset), ReadOnly); array->Set(String::New("length"), Int32::New(length), ReadOnly); array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size)); array->Set(String::New("buffer"), buffer, ReadOnly); return array; }