Creating and returning a new v8::internal::Object within a runtime function

46 views
Skip to first unread message

Pradyumna Shome

unread,
Feb 14, 2023, 2:19:33 PM2/14/23
to v8-users
Hi all

I'm trying to add a new runtime function to return the Data Pointer of an array as a v8::NumberObject, so I can operate upon memory addresses in other JavaScript commands. I'm having trouble constructing and returning an object of type v8::internal::Object, since it seems like every operation always returns a Local/Handle.

I reached out to one of the developers (Jakob) separately, and they pointed me to the definition of v8::NumberObject::New. However, I'm unable to figure out the plumbing required to satisfy the compiler that what I'm returning from the runtime function is indeed a v8::internal::Object. I've shared what I've tried doing to troubleshoot, the error log (bolding the actual errors) and code snippet below.

Best
Pradyumna

What I've Tried
  1. Constructing v8::StringObjects, v8::NumberObjects, and v8::internal::Numbers,by plumbing together APIs from https://v8docs.nodesource.com/node-0.8/da/d56/classv8_1_1_number_object.html and other sites.
  2. Reading the relevant pieces of https://v8.dev/docs/embed to understand what Local/Handle/Persistents are.
  3. Searched for call sites of the NumberObject/StringObject/Number APIs on the GitHub, Google, and You search engines to see if others have tried to do something similar. It turns out not a lot of people outside of the v8 developers are editing v8 (at least publicly).
  4. Read through numbers StackOverflow questions about construction v8::internal::objects, and manipulating Locals.
  5. Searching for related keywords on this forum.

Error Log (for one of the attempts)

# autoninja -C out/arm64.optdebug d8
ninja: Entering directory `out/arm64.optdebug'
[1/11] CXX obj/v8_base_without_compiler/runtime-test.o
FAILED: obj/v8_base_without_compiler/runtime-test.o
../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF obj/v8_base_without_compiler/runtime-test.o.d -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -DCR_XCODE_VERSION=1420 -DCR_CLANG_REVISION=\"llvmorg-16-init-17653-g39da55e8-2\" -DCOMPONENT_BUILD -DCR_LIBCXX_REVISION=59bae40d835ae4eabaddbef781f5e3b778dd7907 -D_LIBCPP_ENABLE_ASSERTIONS=1 -D_DEBUG -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DCPPGC_VERIFY_HEAP -DENABLE_DISASSEMBLER -DV8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -DOBJECT_PRINT -DVERIFY_HEAP -DV8_TRACE_MAPS -DV8_ENABLE_ALLOCATION_TIMEOUT -DV8_ENABLE_FORCE_SLOW_PATH -DV8_ENABLE_DOUBLE_CONST_STORE_CHECK -DV8_INTL_SUPPORT -DENABLE_HANDLE_ZAPPING -DV8_CODE_COMMENTS -DV8_ENABLE_DEBUG_CODE -DV8_ENABLE_HEAP_SNAPSHOT_VERIFY -DV8_SNAPSHOT_NATIVE_CODE_COUNTERS -DV8_USE_EXTERNAL_STARTUP_DATA -DV8_ATOMIC_OBJECT_FIELD_WRITES -DV8_ENABLE_LAZY_SOURCE_POSITIONS -DV8_SHARED_RO_HEAP -DV8_WIN64_UNWINDING_INFO -DV8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -DV8_SHORT_BUILTIN_CALLS -DV8_EXTERNAL_CODE_SPACE -DV8_ENABLE_MAGLEV -DV8_ENABLE_TURBOFAN -DV8_ENABLE_SYSTEM_INSTRUMENTATION -DV8_ENABLE_WEBASSEMBLY -DV8_ALLOCATION_FOLDING -DV8_ALLOCATION_SITE_TRACKING -DV8_ADVANCED_BIGINT_ALGORITHMS -DV8_STATIC_ROOTS -DV8_USE_ZLIB -DV8_USE_LIBM_TRIG_FUNCTIONS -DV8_ENABLE_CHECKS -DV8_COMPRESS_POINTERS -DV8_COMPRESS_POINTERS_IN_SHARED_CAGE -DV8_31BIT_SMIS_ON_64BIT_ARCH -DV8_ENABLE_SANDBOX -DV8_DEPRECATION_WARNINGS -DV8_IMMINENT_DEPRECATION_WARNINGS -DCPPGC_CAGED_HEAP -DCPPGC_YOUNG_GENERATION -DCPPGC_POINTER_COMPRESSION -DCPPGC_SLIM_WRITE_BARRIER -DV8_TARGET_ARCH_ARM64 -DV8_HAVE_TARGET_OS -DV8_TARGET_OS_MACOS -DDEBUG -DV8_RUNTIME_CALL_STATS -DBUILDING_V8_SHARED -DUSING_V8_BASE_SHARED -DUSING_V8_PLATFORM_SHARED -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DUSE_CHROMIUM_ICU=1 -DU_ENABLE_TRACING=1 -DU_ENABLE_RESOURCE_TRACING=0 -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE -I../.. -Igen -I../../buildtools/third_party/libc++ -I../../include -Igen/include -I../../third_party/icu/source/common -I../../third_party/icu/source/i18n -I../../third_party/zlib -Wall -Werror -Wextra -Wimplicit-fallthrough -Wextra-semi -Wunreachable-code-aggressive -Wthread-safety -Wunguarded-availability -Wno-missing-field-initializers -Wno-unused-parameter -Wno-psabi -Wloop-analysis -Wno-unneeded-internal-declaration -Wenum-compare-conditional -Wno-ignored-pragma-optimize -Wno-deprecated-builtins -Wno-bitfield-constant-conversion -Wshadow -fno-delete-null-pointer-checks -fno-ident -fno-strict-aliasing -fstack-protector-strong -fcolor-diagnostics -fmerge-all-constants -fcrash-diagnostics-dir=../../tools/clang/crashreports -mllvm -instcombine-lower-dbg-declare=0 -ffp-contract=off -fcomplete-member-pointers -arch arm64 -fno-global-isel -mno-outline -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -ffile-compilation-dir=. -no-canonical-prefixes -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -g2 -gdwarf-aranges -Xclang -debug-info-kind=limited -isysroot ../../../../../../Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk -mmacos-version-min=10.13 -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -Wmissing-field-initializers -Wunreachable-code -Wctad-maybe-unsupported -Wno-shadow -Wshorten-64-to-32 -O0 -fvisibility=default -Wexit-time-destructors -Wno-undefined-bool-conversion -Wno-tautological-undefined-compare -std=c++20 -Wno-trigraphs -fno-exceptions -fno-rtti -nostdinc++ -isystem../../buildtools/third_party/libc++/trunk/include -isystem../../buildtools/third_party/libc++abi/trunk/include -c ../../src/runtime/runtime-test.cc -o obj/v8_base_without_compiler/runtime-test.o
../../src/runtime/runtime-test.cc:1160:57: error: cannot initialize a parameter of type 'Value *' with an rvalue of type 'Local<NumberObject> *'
  return *(v8::internal::Object*)v8::NumberObject::Cast(&numberObjectLocal);
                                                        ^~~~~~~~~~~~~~~~~~
../../include/v8-primitive-object.h:25:46: note: passing argument to parameter 'value' here
  V8_INLINE static NumberObject* Cast(Value* value) {
                                             ^
In file included from ../../src/runtime/runtime-test.cc:10:
In file included from ../../include/v8-function.h:11:
In file included from ../../include/v8-function-callback.h:8:
../../include/v8-local-handle.h:166:5: error: static assertion failed due to requirement 'std::is_base_of<v8::NumberObject, v8::Value>::value': type check
    static_assert(std::is_base_of<T, S>::value, "type check");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../src/runtime/runtime-test.cc:1159:43: note: in instantiation of function template specialization 'v8::Local<v8::NumberObject>::Local<v8::Value>' requested here
  Local<NumberObject> numberObjectLocal = v8::NumberObject::New((v8::Isolate*)isolate, number);
                                          ^
2 errors generated.
ninja: build stopped: subcommand failed.
Error! - V8 compilation finished with errors.

Code Snippet
RUNTIME_FUNCTION(Runtime_AddressOfArray) {
  SealHandleScope shs(isolate);
  StdoutStream os;

  MaybeObject maybe_object(*args.address_of_arg_at(0));
  Object object = maybe_object.GetHeapObjectOrSmi();

  void* data_pointer = JSTypedArray::cast(object).DataPtr();
  os << "Data Pointer: " << data_pointer << std::endl;

  std::string data_pointer_string;
  std::ostringstream stream;
  stream << data_pointer_string;
  data_pointer_string = stream.str();
  int number = stoi(data_pointer_string);
  Local<NumberObject> numberObjectLocal = v8::NumberObject::New((v8::Isolate*)isolate, number);
  return *(v8::internal::Object*)v8::NumberObject::Cast(&numberObjectLocal);

}

Jakob Gruber

unread,
Feb 15, 2023, 12:34:48 AM2/15/23
to v8-u...@googlegroups.com
Hi, something like this should work:

RUNTIME_FUNCTION(...) {
 ...
 return *isolate->factory()->NewNumber(number);
}

--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/c75f9ea7-2940-4baa-b77f-35aa77ac0fban%40googlegroups.com.

Pradyumna Shome

unread,
Feb 16, 2023, 4:55:22 PM2/16/23
to v8-users
That got me to the stage of being able to compile v8. However, in runtime, it crashes with the following error:

#
# Fatal error in v8::HandleScope::CreateHandle()
# Cannot create a handle without a HandleScope
#

zsh: trace trap  ~/coding/v8/out/arm64.optdebug/d8 --allow-natives-syntax

I read some more and realized the SealScope wasn't appropriate since the factory method creates a new Handle. I switched to an EscapableHandleScope. However, that requires an object of type Local and not Handle.

Am I on the right path? I'm not sure how to get from a Local to Handle or if I picked the right scope.

RUNTIME_FUNCTION(Runtime_AddressOfArray) {
    v8::EscapableHandleScope ehs((v8::Isolate*)isolate);
    StdoutStream os;
    MaybeObject maybe_object(*args.address_of_arg_at(0));
    Object object = maybe_object.GetHeapObjectOrSmi();
    void* data_pointer = JSTypedArray::cast(object).DataPtr();
    
    std::ostringstream stream;
    stream << data_pointer;
    std::string data_pointer_string = stream.str();

    data_pointer_string = data_pointer_string.substr(2, data_pointer_string.size() - 2);

    long number = stol(data_pointer_string, nullptr, 16);

    Handle<v8::internal::Object> number_handle = isolate->factory()->NewNumber(number);
    return ehs.Escape(number_handle);
}

Pradyumna Shome

unread,
Feb 20, 2023, 6:37:57 PM2/20/23
to v8-u...@googlegroups.com
I figured out my problem, although I don't know enough of the V8 system architecture to explain why. You can return the handle from the factory method directly if you use HandleScope instead of EscapableHandleScope.

Thanks for all the help!

Full code for posterity:

RUNTIME_FUNCTION(Runtime_AddressOfArray) {
   HandleScope hs(isolate);
   StdoutStream os;

   MaybeObject maybe_object(*args.address_of_arg_at(0));
   Object object = maybe_object.GetHeapObjectOrSmi();
   void* data_pointer = JSTypedArray::cast(object).DataPtr();

   std::ostringstream stream;
   stream << data_pointer;
   std::string data_pointer_string = stream.str();

   data_pointer_string = data_pointer_string.substr(2, data_pointer_string.size() - 2);

   long number = stol(data_pointer_string, nullptr, 16);

   Handle<v8::internal::Object> number_handle = isolate->factory()->NewNumber(number);

    return *number_handle;
}



v8-users@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to a topic in the Google Groups "v8-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/v8-users/hiTECGVar-I/unsubscribe.
To unsubscribe from this group and all its topics, send an email to v8-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/8ba8b406-d953-4d2e-8544-5ccd6e74a8f7n%40googlegroups.com.

Reply all
Reply to author
Forward
0 new messages