Skip to content

Commit 75fabf7

Browse files
committed
Move profiling to prism module directly
1 parent 283938e commit 75fabf7

3 files changed

Lines changed: 113 additions & 90 deletions

File tree

ext/prism/extension.c

Lines changed: 105 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ VALUE rb_cPrismParseLexResult;
2525

2626
VALUE rb_cPrismDebugEncoding;
2727

28-
ID rb_option_id_command_line;
29-
ID rb_option_id_encoding;
30-
ID rb_option_id_filepath;
31-
ID rb_option_id_frozen_string_literal;
32-
ID rb_option_id_line;
33-
ID rb_option_id_scopes;
34-
ID rb_option_id_version;
35-
ID rb_prism_source_id_for;
28+
ID rb_id_option_command_line;
29+
ID rb_id_option_encoding;
30+
ID rb_id_option_filepath;
31+
ID rb_id_option_frozen_string_literal;
32+
ID rb_id_option_line;
33+
ID rb_id_option_scopes;
34+
ID rb_id_option_version;
35+
ID rb_id_source_for;
3636

3737
/******************************************************************************/
3838
/* IO of Ruby code */
@@ -135,25 +135,25 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
135135
pm_options_t *options = (pm_options_t *) argument;
136136
ID key_id = SYM2ID(key);
137137

138-
if (key_id == rb_option_id_filepath) {
138+
if (key_id == rb_id_option_filepath) {
139139
if (!NIL_P(value)) pm_options_filepath_set(options, check_string(value));
140-
} else if (key_id == rb_option_id_encoding) {
140+
} else if (key_id == rb_id_option_encoding) {
141141
if (!NIL_P(value)) pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
142-
} else if (key_id == rb_option_id_line) {
142+
} else if (key_id == rb_id_option_line) {
143143
if (!NIL_P(value)) pm_options_line_set(options, NUM2INT(value));
144-
} else if (key_id == rb_option_id_frozen_string_literal) {
144+
} else if (key_id == rb_id_option_frozen_string_literal) {
145145
if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, RTEST(value));
146-
} else if (key_id == rb_option_id_version) {
146+
} else if (key_id == rb_id_option_version) {
147147
if (!NIL_P(value)) {
148148
const char *version = check_string(value);
149149

150150
if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
151151
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
152152
}
153153
}
154-
} else if (key_id == rb_option_id_scopes) {
154+
} else if (key_id == rb_id_option_scopes) {
155155
if (!NIL_P(value)) build_options_scopes(options, value);
156-
} else if (key_id == rb_option_id_command_line) {
156+
} else if (key_id == rb_id_option_command_line) {
157157
if (!NIL_P(value)) {
158158
const char *string = check_string(value);
159159
uint8_t command_line = 0;
@@ -600,7 +600,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
600600

601601
VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input));
602602
VALUE offsets = rb_ary_new();
603-
VALUE source = rb_funcall(rb_cPrismSource, rb_prism_source_id_for, 3, source_string, LONG2NUM(parser.start_line), offsets);
603+
VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets);
604604

605605
parse_lex_data_t parse_lex_data = {
606606
.source = source,
@@ -761,6 +761,82 @@ parse(int argc, VALUE *argv, VALUE self) {
761761
return value;
762762
}
763763

764+
/**
765+
* call-seq:
766+
* Prism::parse_file(filepath, **options) -> ParseResult
767+
*
768+
* Parse the given file and return a ParseResult instance. For supported
769+
* options, see Prism::parse.
770+
*/
771+
static VALUE
772+
parse_file(int argc, VALUE *argv, VALUE self) {
773+
pm_string_t input;
774+
pm_options_t options = { 0 };
775+
776+
file_options(argc, argv, &input, &options);
777+
778+
VALUE value = parse_input(&input, &options);
779+
pm_string_free(&input);
780+
pm_options_free(&options);
781+
782+
return value;
783+
}
784+
785+
/**
786+
* Parse the given input and return nothing.
787+
*/
788+
static void
789+
profile_input(pm_string_t *input, const pm_options_t *options) {
790+
pm_parser_t parser;
791+
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
792+
793+
pm_node_t *node = pm_parse(&parser);
794+
pm_node_destroy(&parser, node);
795+
pm_parser_free(&parser);
796+
}
797+
798+
/**
799+
* call-seq:
800+
* Prism::profile(source, **options) -> nil
801+
*
802+
* Parse the given string and return nothing. This method is meant to allow
803+
* profilers to avoid the overhead of reifying the AST to Ruby. For supported
804+
* options, see Prism::parse.
805+
*/
806+
static VALUE
807+
profile(int argc, VALUE *argv, VALUE self) {
808+
pm_string_t input;
809+
pm_options_t options = { 0 };
810+
811+
string_options(argc, argv, &input, &options);
812+
profile_input(&input, &options);
813+
pm_string_free(&input);
814+
pm_options_free(&options);
815+
816+
return Qnil;
817+
}
818+
819+
/**
820+
* call-seq:
821+
* Prism::profile_file(filepath, **options) -> nil
822+
*
823+
* Parse the given file and return nothing. This method is meant to allow
824+
* profilers to avoid the overhead of reifying the AST to Ruby. For supported
825+
* options, see Prism::parse.
826+
*/
827+
static VALUE
828+
profile_file(int argc, VALUE *argv, VALUE self) {
829+
pm_string_t input;
830+
pm_options_t options = { 0 };
831+
832+
file_options(argc, argv, &input, &options);
833+
profile_input(&input, &options);
834+
pm_string_free(&input);
835+
pm_options_free(&options);
836+
837+
return Qnil;
838+
}
839+
764840
/**
765841
* An implementation of fgets that is suitable for use with Ruby IO objects.
766842
*/
@@ -815,27 +891,6 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
815891
return result;
816892
}
817893

818-
/**
819-
* call-seq:
820-
* Prism::parse_file(filepath, **options) -> ParseResult
821-
*
822-
* Parse the given file and return a ParseResult instance. For supported
823-
* options, see Prism::parse.
824-
*/
825-
static VALUE
826-
parse_file(int argc, VALUE *argv, VALUE self) {
827-
pm_string_t input;
828-
pm_options_t options = { 0 };
829-
830-
file_options(argc, argv, &input, &options);
831-
832-
VALUE value = parse_input(&input, &options);
833-
pm_string_free(&input);
834-
pm_options_free(&options);
835-
836-
return value;
837-
}
838-
839894
/**
840895
* Parse the given input and return an array of Comment objects.
841896
*/
@@ -1065,45 +1120,6 @@ named_captures(VALUE self, VALUE source) {
10651120
return names;
10661121
}
10671122

1068-
/**
1069-
* call-seq:
1070-
* Debug::profile_file(filepath) -> nil
1071-
*
1072-
* Parse the file, but do nothing with the result. This is used to profile the
1073-
* parser for memory and speed.
1074-
*/
1075-
static VALUE
1076-
profile_file(VALUE self, VALUE filepath) {
1077-
pm_string_t input;
1078-
1079-
const char *checked = check_string(filepath);
1080-
Check_Type(filepath, T_STRING);
1081-
1082-
if (!pm_string_mapped_init(&input, checked)) {
1083-
#ifdef _WIN32
1084-
int e = rb_w32_map_errno(GetLastError());
1085-
#else
1086-
int e = errno;
1087-
#endif
1088-
1089-
rb_syserr_fail(e, checked);
1090-
}
1091-
1092-
pm_options_t options = { 0 };
1093-
pm_options_filepath_set(&options, checked);
1094-
1095-
pm_parser_t parser;
1096-
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
1097-
1098-
pm_node_t *node = pm_parse(&parser);
1099-
pm_node_destroy(&parser, node);
1100-
pm_parser_free(&parser);
1101-
pm_options_free(&options);
1102-
pm_string_free(&input);
1103-
1104-
return Qnil;
1105-
}
1106-
11071123
#ifndef PRISM_EXCLUDE_PRETTYPRINT
11081124

11091125
/**
@@ -1275,22 +1291,20 @@ Init_prism(void) {
12751291
rb_cPrismMagicComment = rb_define_class_under(rb_cPrism, "MagicComment", rb_cObject);
12761292
rb_cPrismParseError = rb_define_class_under(rb_cPrism, "ParseError", rb_cObject);
12771293
rb_cPrismParseWarning = rb_define_class_under(rb_cPrism, "ParseWarning", rb_cObject);
1278-
12791294
rb_cPrismResult = rb_define_class_under(rb_cPrism, "Result", rb_cObject);
12801295
rb_cPrismParseResult = rb_define_class_under(rb_cPrism, "ParseResult", rb_cPrismResult);
12811296
rb_cPrismParseLexResult = rb_define_class_under(rb_cPrism, "ParseLexResult", rb_cPrismResult);
12821297

1283-
// Intern all of the options that we support so that we don't have to do it
1284-
// every time we parse.
1285-
rb_option_id_command_line = rb_intern_const("command_line");
1286-
rb_option_id_encoding = rb_intern_const("encoding");
1287-
rb_option_id_filepath = rb_intern_const("filepath");
1288-
rb_option_id_frozen_string_literal = rb_intern_const("frozen_string_literal");
1289-
rb_option_id_line = rb_intern_const("line");
1290-
rb_option_id_scopes = rb_intern_const("scopes");
1291-
rb_option_id_version = rb_intern_const("version");
1292-
1293-
rb_prism_source_id_for = rb_intern("for");
1298+
// Intern all of the IDs eagerly that we support so that we don't have to do
1299+
// it every time we parse.
1300+
rb_id_option_command_line = rb_intern_const("command_line");
1301+
rb_id_option_encoding = rb_intern_const("encoding");
1302+
rb_id_option_filepath = rb_intern_const("filepath");
1303+
rb_id_option_frozen_string_literal = rb_intern_const("frozen_string_literal");
1304+
rb_id_option_line = rb_intern_const("line");
1305+
rb_id_option_scopes = rb_intern_const("scopes");
1306+
rb_id_option_version = rb_intern_const("version");
1307+
rb_id_source_for = rb_intern("for");
12941308

12951309
/**
12961310
* The version of the prism library.
@@ -1301,8 +1315,10 @@ Init_prism(void) {
13011315
rb_define_singleton_method(rb_cPrism, "lex", lex, -1);
13021316
rb_define_singleton_method(rb_cPrism, "lex_file", lex_file, -1);
13031317
rb_define_singleton_method(rb_cPrism, "parse", parse, -1);
1304-
rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1);
13051318
rb_define_singleton_method(rb_cPrism, "parse_file", parse_file, -1);
1319+
rb_define_singleton_method(rb_cPrism, "profile", profile, -1);
1320+
rb_define_singleton_method(rb_cPrism, "profile_file", profile_file, -1);
1321+
rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1);
13061322
rb_define_singleton_method(rb_cPrism, "parse_comments", parse_comments, -1);
13071323
rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, -1);
13081324
rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
@@ -1321,7 +1337,6 @@ Init_prism(void) {
13211337
// internal tasks. We expose these to make them easier to test.
13221338
VALUE rb_cPrismDebug = rb_define_module_under(rb_cPrism, "Debug");
13231339
rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1);
1324-
rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
13251340
rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2);
13261341

13271342
#ifndef PRISM_EXCLUDE_PRETTYPRINT

rbi/prism.rbi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ module Prism
2828
sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) }
2929
def self.parse_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end
3030

31+
sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).void }
32+
def self.profile(source, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end
33+
34+
sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).void }
35+
def self.profile_file(filepath, command_line: nil, encoding: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end
36+
3137
sig { params(stream: T.any(IO, StringIO), command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) }
3238
def self.parse_stream(stream, command_line: nil, encoding: nil, filepath: nil, frozen_string_literal: nil, line: nil, scopes: nil, version: nil); end
3339

templates/sig/prism.rbs.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Prism
66
<%-
77
{
88
parse: "ParseResult",
9+
profile: "nil",
910
lex: "LexResult",
1011
lex_compat: "LexCompat::Result",
1112
parse_lex: "ParseLexResult",
@@ -41,6 +42,7 @@ module Prism
4142
<%-
4243
{
4344
parse_file: "ParseResult",
45+
profile_file: "nil",
4446
lex_file: "LexResult",
4547
parse_lex_file: "ParseLexResult",
4648
dump_file: "String",

0 commit comments

Comments
 (0)