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

Support testing static vm functions in intrinsic tests #4868

Merged
merged 6 commits into from Nov 17, 2021

Conversation

elliottt
Copy link
Contributor

@elliottt elliottt commented Nov 17, 2021

14cd06c - Extend IREmitterHelpers::receiverFastPathTestWithCache to support calling another function to get the address of a static vm function when emitting a comparison. This result is stored in a global variable and cached at module load time to avoid jumping back and forth between the loaded module and the vm.

a10204e - As an example, this PR adds an implementation of String#to_each, which is defined by testing the results of method search against the static symbol rb_str_to_s.

c356135 - Add benchmarks for different uses of String#to_s.

# this branch
ruby vm startup time: .090
source                                          interpreted     compiled
stripe/while_10_000_000.rb                      .239            .116
stripe/string_subclass_to_s.rb                  .806            .556
stripe/string_subclass_to_s.rb - baseline       .567            .440
stripe/string_to_s.rb                           .454            .217
stripe/string_to_s.rb - baseline                .215            .101


# master
source                                          interpreted     compiled
stripe/while_10_000_000.rb                      .238            .115
stripe/string_subclass_to_s.rb                  .811            .675
stripe/string_subclass_to_s.rb - baseline       .573            .560
stripe/string_to_s.rb                           .447            .313
stripe/string_to_s.rb - baseline                .209            .198

Motivation

More flexible symbol based intrinsics, and a faster implementation of String#to_s.

Test plan

See included automated tests.

@elliottt elliottt marked this pull request as ready for review November 17, 2021 21:04
@elliottt elliottt requested a review from a team as a code owner November 17, 2021 21:04
Copy link
Contributor

@froydnj froydnj left a comment

Choose a reason for hiding this comment

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

I think this makes sense, though I am not totally sure why we need the KnownFunction bits for this particular function (I think we need it for other methods, if they're implemented with Ruby-internal functions?).

Comment on lines +12 to +18
VALUE (*sorbet_rb_str_to_s_func(void))(VALUE) {
return rb_str_to_s;
}

VALUE sorbet_rb_str_to_s(VALUE str) {
return rb_str_to_s(str);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we have both of these? Can't we just say in the intrinsic that we expect the cached function to be rb_str_to_s?

(And then if we have that, I suppose we don't need the KnownFunction bits? At least not for this particular method...)

Copy link
Contributor Author

@elliottt elliottt Nov 17, 2021

Choose a reason for hiding this comment

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

rb_str_to_s is static in string.c, which is what led to all of this. The entry in the inline cache will be rb_str_to_s, not sorbet_rb_str_to_s, so there are some hoops to jump through.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, of course. Sorry, I thought these were in the codegen payload; this makes more sense now.

Comment on lines 48 to 52

sig {params(x: String).returns(String)}
def self.string_to_s(x)
x.to_s
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we have some filecheck tests for this function?

Comment on lines +66 to +67
class StringSubclass < String
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this class be defining its own to_s method to ensure that our intrinsic implementation isn't just calling rb_str_to_s directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should test both. The default implementation of String#to_s will do something different for subclasses of String, which is what this case is testing.

// Implicit constructor from a string for backwards compability
KnownFunction(std::string name) : KnownFunction(Type::Symbol, std::move(name)) {}

KnownFunction(Type type, std::string name) : type{type}, name{std::move(name)} {}
Copy link
Contributor

Choose a reason for hiding this comment

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

WDYT about making this function private?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Works for me!

@elliottt
Copy link
Contributor Author

We have a policy of testing changes to Sorbet against Stripe's codebase before
merging them. I've kicked off a test run for the current PR. When the build
finishes, I'll share with you whether or how it failed. Thanks!

Stripe employees can see the build results here:

https://go/builds/bui_KcBOCpZjy0WhiI
https://go/builds/bui_KcBO09kyjXI72i

@elliottt elliottt merged commit 9fb0a34 into master Nov 17, 2021
@elliottt elliottt deleted the trevor/string-to_s-intrinsic branch November 17, 2021 23:23
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.

None yet

2 participants