Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start implementing internal V8 APIs #12821

Merged
merged 101 commits into from
Aug 15, 2024
Merged

Start implementing internal V8 APIs #12821

merged 101 commits into from
Aug 15, 2024

Conversation

190n
Copy link
Contributor

@190n 190n commented Jul 25, 2024

What does this PR do?

  • Documentation or TypeScript types (it's okay to leave the rest blank in this case)
  • Code changes

Implements some of the V8 APIs that native modules written especially for Node.js use. Some have real implementations while some have stubs that just crash, but even those will let us see which APIs are missing because it will print which method failed instead of the generic dyld: missing symbol called on macOS.

Most Node.js modules still won't fully load because node_module_register isn't fully implemented.

TODOs before we can reasonably expect some modules to work (at least based on cpu-features's usage):

  • Implement module lifecycle properly
  • Stub HandleScope and EscapableHandleScope without aborting
  • Implement ObjectTemplate and FunctionTemplate
  • Implement internal fields on objects

How did you verify your code works?

I wrote automated tests

Copy link
Contributor

github-actions bot commented Jul 25, 2024

@190n, your commit has failing tests :(

🪟💻 3 failing tests Windows x64 baseline

  • test/cli/install/registry/bun-install-registry.test.ts 1 failing
  • test/js/node/child_process/child_process.test.ts 1 failing
  • test/js/node/http/node-http.test.ts 2 failing

🪟💻 3 failing tests Windows x64

  • test/cli/install/registry/bun-install-registry.test.ts 2 failing
  • test/js/node/child_process/child_process.test.ts 1 failing
  • test/js/node/http/node-http.test.ts 1 failing

View logs

@@ -341,6 +342,7 @@ class NAPIFunction : public JSC::JSFunction {
NAPICallFrame frame(JSC::ArgList(args), function->m_dataPtr);

auto scope = DECLARE_THROW_SCOPE(vm);
v8::HandleScope handleScope(v8::Isolate::fromGlobalObject(static_cast<Zig::GlobalObject*>(globalObject)));
Copy link
Collaborator

@Jarred-Sumner Jarred-Sumner Aug 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can technically be a node:vm global object but I don't think we handle this correctly elsewhere either

return globalObject()->vm();
}

const Zig::GlobalObject* globalObject() const
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use Bun::GlobalScope for these, honestly

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it's not a blocker

void* raw_ptr = root.getPtr<void>();
// check if this pointer is identical to the fixed locations where these primitive
// values are stored
if (raw_ptr == globalInternals->undefinedSlot()->getPtr<void>()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting that literally everything is a pointer


namespace v8 {

Local<External> External::New(Isolate* isolate, void* value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol v8 external wraps napi external

backwards

vm,
globalObject,
globalObject->functionPrototype(),
JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to be a constructor? I think InternalFunctionType is fine. But if we can use JSFunction it is generally faster than InternalFunction (i am semi-mindlessly repeating something I saw in a PR review on webkit's github)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be a constructor but I don't support that yet.

}
};

using FunctionCallback = void (*)(const FunctionCallbackInfo<Value>&);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need a specified calling convention?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. It's only called by native code (inside FunctionTemplate::functionCall) not JS, and V8's definition doesn't specify a calling convention. On windows, the compiler should adapt from SysV to MSVC calling convention for us inside FunctionTemplate::functionCall.


// An array used by HandleScope to store the items. Must keep pointer stability when resized, since
// v8::Locals point inside this array.
class HandleScopeBuffer : public JSC::JSNonFinalObject {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a JSC::JSCell instead?

// the layout is correct.
struct Roots {
// v8-internal.h:775
static const int kUndefinedValueRootIndex = 4;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could use constexpr for these?

}
// TODO(@190n) span.data() is latin1 not utf8, but this is okay as long as the only way to make
// a v8 string is NewFromUtf8. that's because NewFromUtf8 will use either all ASCII or all UTF-16.
memcpy(buffer, span.data(), to_copy);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can to_copy be zero?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I'm working on UTF-16 right now in this function so this path is probably gonna change a bit

ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);

for (int i = 0; i < thisObject->size; i++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be unsigned or size_t

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and we should copy the size into a local variable to avoid the extra pointer lookup

Handle& HandleScopeBuffer::createUninitializedHandle()
{
RELEASE_ASSERT(size < capacity - 1);
int index = size;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int index = size;
unsigned index = size;


Handle& HandleScopeBuffer::createUninitializedHandle()
{
RELEASE_ASSERT(size < capacity - 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RELEASE_ASSERT(size < capacity - 1);
ASSERT(size <= capacity);

static constexpr int capacity = 64;

Handle storage[capacity];
int size = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int size = 0;
unsigned size = 0;

@Jarred-Sumner Jarred-Sumner merged commit dc2929d into main Aug 15, 2024
26 of 32 checks passed
@Jarred-Sumner Jarred-Sumner deleted the ben/v8-internal-apis branch August 15, 2024 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants