Граф коммитов

624 Коммитов

Автор SHA1 Сообщение Дата
Peter Zhu 51ffef2819 Fix memory leak in prism when syntax error in iseq compilation
If there's a syntax error during iseq compilation then prism would leak
memory because it would not free the pm_parse_result_t.

This commit changes pm_iseq_new_with_opt to have a rb_protect to catch
when an error is raised, and return NULL and set error_state to a value
that can be raised by calling rb_jump_tag after memory has been freed.

For example:

    10.times do
      10_000.times do
        eval("/[/=~s")
      rescue SyntaxError
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    39280
    68736
    99232
    128864
    158896
    188208
    217344
    246304
    275376
    304592

After:

    12192
    13200
    14256
    14848
    16000
    16000
    16000
    16064
    17232
    17952
2024-11-08 15:43:41 -05:00
Kevin Newton 4203c70dfa Allow eval to see top scope
Fixes [Bug #20856]

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
2024-11-05 17:08:35 -05:00
Alan Wu 11e7ab79de
Remove 1 allocation in Enumerable#each_with_index (#11868)
* Remove 1 allocation in Enumerable#each_with_index

Previously, each call to Enumerable#each_with_index allocates 2
objects, one for the counting index, the other an imemo_ifunc passed
to `self.each` as a block.

Use `struct vm_ifunc::data` to hold the counting index directly to
remove 1 allocation.

* [DOC] Brief summary for usages of `struct vm_ifunc`
2024-10-11 10:22:44 -04:00
Nobuyoshi Nakada 3e1021b144 Make default parser enum and define getter/setter 2024-10-02 20:43:40 +09:00
Peter Zhu 4f0fe97995 Free scope node in prism 2024-09-24 10:23:45 -04:00
Peter Zhu 4113dcc4ae Fix memory leak in constant ID list in prism 2024-09-24 10:23:45 -04:00
Kevin Newton f7b097dea0 [PRISM] Keep script lines option for eval iseqs as well 2024-09-03 12:12:08 -04:00
Kevin Newton 371432b2d7 [PRISM] Handle RubyVM.keep_script_lines 2024-08-29 20:27:01 -04:00
Alan Wu 68a419d749 Delete unused rb_check_funcall_with_hook() 2024-08-07 19:17:31 -04:00
Yusuke Endoh 114e32b357 Add rb_block_call2, a flexible variant of rb_block_call
This function accepts flags:

RB_NO_KEYWORDS, RB_PASS_KEYWORDS, RB_PASS_CALLED_KEYWORDS:
Works as the same as rb_block_call_kw.

RB_BLOCK_NO_USE_PACKED_ARGS:
The given block ("bl_proc") does not use "yielded_arg" of rb_block_call_func_t.
Instead, the block accesses the yielded arguments via "argc" and "argv".
This flag allows the called method to yield arguments without allocating an Array.
2024-07-10 13:00:47 +09:00
Aaron Patterson a25dd5b12c Set a fast path for forwardable iseqs 2024-06-18 09:28:25 -07:00
Kevin Newton a708b6aa65 [PRISM] Respect eval coverage setting 2024-05-20 12:28:47 -04:00
yui-knk 899d9f79dd Rename `vast` to `ast_value`
There is an English word "vast".
This commit changes the name to be more clear name to avoid confusion.
2024-05-03 12:40:35 +09:00
HASUMI Hitoshi 2244c58b00 [Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.

## Background

We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.

## Summary (file by file)

- `rubyparser.h`
  - Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
  - Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
    - You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
  - Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
  - rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
  - Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
  - This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
  - Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
  - Fix `node_memsize()`
    - Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
  - Follow-up due to the above changes
- `imemo.{c|h}`
  - If an object with `imemo_ast` appears, considers it a bug

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-26 11:21:08 +09:00
Aaron Patterson 73a7e51535 Pass a callinfo object to global call cache search
Global call cache can be used with only a CI
2024-04-24 11:21:18 -07:00
Aaron Patterson 2cc59c1b31 pass CI to gccct_method_search_slowpath
Also the slow path only needs to look up the method once: via
vm_search_method_slowpath0.  gccct just returns whatever cc normal
method lookup does.
2024-04-24 11:21:18 -07:00
Aaron Patterson 853c0b1a77 Reuse slow path method search for gccct
This way all code paths use the same search code for finding call caches
for a particular method.
2024-04-24 09:30:59 -07:00
HASUMI Hitoshi 9b1e97b211 [Universal parser] DeVALUE of p->debug_lines and ast->body.script_lines
This patch is part of universal parser work.

## Summary
- Decouple VALUE from members below:
  - `(struct parser_params *)->debug_lines`
  - `(rb_ast_t *)->body.script_lines`
- Instead, they are now `rb_parser_ary_t *`
  - They can also be a `(VALUE)FIXNUM` as before to hold line count
- `ISEQ_BODY(iseq)->variable.script_lines` remains VALUE
  - In order to do this,
  - Add `VALUE script_lines` param to `rb_iseq_new_with_opt()`
  - Introduce `rb_parser_build_script_lines_from()` to convert `rb_parser_ary_t *` into `VALUE`

## Other details
- Extend `rb_parser_ary_t *`. It previously could only store `rb_parser_ast_token *`, now can store script_lines, too
- Change tactics of building the top-level `SCRIPT_LINES__` in `yycompile0()`
  - Before: While parsing, each line of the script is added to `SCRIPT_LINES__[path]`
  - After: After `yyparse(p)`, `SCRIPT_LINES__[path]` will be built from `p->debug_lines`
- Remove the second parameter of `rb_parser_set_script_lines()` to make it simple
- Introduce `script_lines_free()` to be called from `rb_ast_free()` because the GC no longer takes care of the script_lines
- Introduce `rb_parser_string_deep_copy()` in parse.y to maintain script_lines when `rb_ruby_parser_free()` called
  - With regard to this, please see *Future tasks* below

## Future tasks
- Decouple IMEMO from `rb_ast_t *`
  - This lifts the five-members-restriction of Ruby object,
  - So we will be able to move the ownership of the `lex.string_buffer` from parser to AST
  - Then we remove `rb_parser_string_deep_copy()` to make the whole thing simple
2024-04-15 20:51:54 +09:00
Kevin Newton 48c2ffe980 [PRISM] Enable SCRIPT_COMPILED tracepoint event 2024-04-04 15:27:51 -04:00
Kevin Newton 42d1cd8f7f [PRISM] Pass --enable-frozen-string-literal through to evals 2024-03-27 08:34:42 -04:00
Takashi Kokubun cbcb2d46fc
[DOC] Unify Doxygen formats (#10285) 2024-03-19 10:59:25 -07:00
Étienne Barrié 12be40ae6b Implement chilled strings
[Feature #20205]

As a path toward enabling frozen string literals by default in the future,
this commit introduce "chilled strings". From a user perspective chilled
strings pretend to be frozen, but on the first attempt to mutate them,
they lose their frozen status and emit a warning rather than to raise a
`FrozenError`.

Implementation wise, `rb_compile_option_struct.frozen_string_literal` is
no longer a boolean but a tri-state of `enabled/disabled/unset`.

When code is compiled with frozen string literals neither explictly enabled
or disabled, string literals are compiled with a new `putchilledstring`
instruction. This instruction is identical to `putstring` except it marks
the String with the `STR_CHILLED (FL_USER3)` and `FL_FREEZE` flags.

Chilled strings have the `FL_FREEZE` flag as to minimize the need to check
for chilled strings across the codebase, and to improve compatibility with
C extensions.

Notes:
  - `String#freeze`: clears the chilled flag.
  - `String#-@`: acts as if the string was mutable.
  - `String#+@`: acts as if the string was mutable.
  - `String#clone`: copies the chilled flag.

Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2024-03-19 09:26:49 +01:00
Jean Boussier 91bf7eb274 Refactor frozen_string_literal check during compilation
In preparation for https://bugs.ruby-lang.org/issues/20205.

The `frozen_string_literal` compilation option will no longer
be a boolean but a tri-state: `on/off/default`.
2024-03-15 15:52:33 +01:00
Kevin Newton 00c32f606a [PRISM] Do not send numbered parameters into eval 2024-03-13 19:01:43 -04:00
Jean Boussier d4f3dcf4df Refactor VM root modules
This `st_table` is used to both mark and pin classes
defined from the C API. But `vm->mark_object_ary` already
does both much more efficiently.

Currently a Ruby process starts with 252 rooted classes,
which uses `7224B` in an `st_table` or `2016B` in an `RArray`.

So a baseline of 5kB saved, but since `mark_object_ary` is
preallocated with `1024` slots but only use `405` of them,
it's a net `7kB` save.

`vm->mark_object_ary` is also being refactored.

Prior to this changes, `mark_object_ary` was a regular `RArray`, but
since this allows for references to be moved, it was marked a second
time from `rb_vm_mark()` to pin these objects.

This has the detrimental effect of marking these references on every
minors even though it's a mostly append only list.

But using a custom TypedData we can save from having to mark
all the references on minor GC runs.

Addtionally, immediate values are now ignored and not appended
to `vm->mark_object_ary` as it's just wasted space.
2024-03-06 15:33:43 -05:00
Kevin Newton 80ffa3006c [PRISM] Eval frames should not have an absolute path 2024-02-21 17:25:55 -05:00
Yusuke Endoh 25d74b9527 Do not include a backtick in error messages and backtraces
[Feature #16495]
2024-02-15 18:42:31 +09:00
Kevin Newton 9933377c34 [PRISM] Correctly hook up line numbers for eval 2024-02-14 15:29:26 -05:00
Matt Valentine-House adb2fbf69a [PRISM] Prism/eval should handle file names provided 2024-02-13 21:19:12 -05:00
Matt Valentine-House c2af974e67 [PRISM] Build wrapper scopes for eval
- Don't use `build_options_scopes` We can inline the code here instead
  and avoid allocating all the extra arrays.

- Create `pm_scope_node_t` objects with the correct local table, for the
  scope node returned from the parser.

Co-Authored-By: Kevin Newton <kddnewton@gmail.com>
2024-02-13 21:19:12 -05:00
Matt Valentine-House fd3f776a05 [PRISM] Use Prism for `eval` if enabled 2024-02-13 21:19:12 -05:00
Matt Valentine-House 08b77dd682 Remove unused bind argument from eval_make_iseq 2024-02-09 12:28:26 +00:00
Xavier Noria aad246feba s/SafeStringValue/StringValue/
The macro SafeStringValue() became just StringValue() in c5c05460ac,
and it is deprecated nowadays.

This patch replaces remaining macro usage. Some occurrences are left in
ext/stringio and ext/win32ole, they should be fixed upstream.

The macro itself is not deleted, because it may be used in extensions.
2024-01-12 12:24:48 -08:00
Jeremy Evans 3081c83169 Support tracing of struct member accessor methods
This follows the same approach used for attr_reader/attr_writer in
2d98593bf5, skipping the checking for
tracing after the first call using the call cache, and clearing the
call cache when tracing is turned on/off.

Fixes [Bug #18886]
2023-12-07 10:29:33 -08:00
Nobuyoshi Nakada 1cfc853be6
Suppress nonnull warning from gcc 13 2023-11-07 23:19:51 +09:00
Peter Zhu 38e98cbb6a Fix typo in "refinements" 2023-09-19 19:34:50 -04:00
Nobuyoshi Nakada 6aa16f9ec1 Move SCRIPT_LINES__ away from parse.y 2023-08-25 18:23:05 +09:00
Koichi Sasada 280419d0e0 `calling->cd` instead of `calling->ci`
`struct rb_calling_info::cd` is introduced and `rb_calling_info::ci`
is replaced with it to manipulate the inline cache of iseq while
method invocation process. So that `ci` can be acessed with
`calling->cd->ci`. It adds one indirection but it can be justified
by the following points:

1) `vm_search_method_fastpath()` doesn't need `ci` and also
`vm_call_iseq_setup_normal()` doesn't need `ci`. It means
reducing `cd->ci` access in `vm_sendish()` can make it faster.

2) most of method types need to access `ci` once in theory
so that 1 additional indirection doesn't matter.
2023-07-31 17:13:43 +09:00
Koichi Sasada 36023d5cb7 mark `cc->cme_` if it is for `super`
`vm_search_super_method()` makes orphan CCs (they are not connected
from ccs) and `cc->cme_` can be collected before without marking.
2023-07-31 14:04:31 +09:00
Nobuyoshi Nakada 1780ad3748
Extract magic numbers 2023-07-24 23:41:01 +09:00
Jean Boussier 43a5c19135 Use the caller location as default filename for eval family of methods
[Feature #19755]

Before (in /tmp/test.rb):

```ruby
Object.class_eval("p __FILE__") # => "(eval)"
```

After:

```ruby
Object.class_eval("p __FILE__") # => "(eval at /tmp/test.rb:1)"
```

This makes it much easier to track down generated code in case
the author forgot to provide a filename argument.
2023-07-24 14:51:20 +02:00
Peter Zhu 3223181284 Remove RARRAY_CONST_PTR_TRANSIENT
RARRAY_CONST_PTR now does the same things as RARRAY_CONST_PTR_TRANSIENT.
2023-07-13 14:48:14 -04:00
Nobuyoshi Nakada 1b01140d8a
Remove unused fstring 2023-07-11 19:52:37 +09:00
yui-knk 19c62b400d Replace parser & node compile_option from Hash to bit field
This commit reduces dependency to CRuby object.
2023-06-17 16:41:08 +09:00
yui-knk ed7c7657ae Remove deleted function
`rb_parser_warn_location` was deleted by 0eeed5bcc5.
2023-05-23 08:21:34 +09:00
Jeremy Evans 99c6d19e50 Generalize cfunc large array splat fix to fix many additional cases raising SystemStackError
Originally, when 2e7bceb34e fixed cfuncs to no
longer use the VM stack for large array splats, it was thought to have fully
fixed Bug #4040, since the issue was fixed for methods defined in Ruby (iseqs)
back in Ruby 2.2.

After additional research, I determined that same issue affects almost all
types of method calls, not just iseq and cfunc calls.  There were two main
types of remaining issues, important cases (where large array splat should
work) and pedantic cases (where large array splat raised SystemStackError
instead of ArgumentError).

Important cases:

```ruby
define_method(:a){|*a|}
a(*1380888.times)

def b(*a); end
send(:b, *1380888.times)

:b.to_proc.call(self, *1380888.times)

def d; yield(*1380888.times) end
d(&method(:b))

def self.method_missing(*a); end
not_a_method(*1380888.times)

```

Pedantic cases:

```ruby
def a; end
a(*1380888.times)
def b(_); end
b(*1380888.times)
def c(_=nil); end
c(*1380888.times)

c = Class.new do
  attr_accessor :a
  alias b a=
end.new
c.a(*1380888.times)
c.b(*1380888.times)

c = Struct.new(:a) do
  alias b a=
end.new
c.a(*1380888.times)
c.b(*1380888.times)
```

This patch fixes all usage of CALLER_SETUP_ARG with splatting a large
number of arguments, and required similar fixes to use a temporary
hidden array in three other cases where the VM would use the VM stack
for handling a large number of arguments.  However, it is possible
there may be additional cases where splatting a large number
of arguments still causes a SystemStackError.

This has a measurable performance impact, as it requires additional
checks for a large number of arguments in many additional cases.

This change is fairly invasive, as there were many different VM
functions that needed to be modified to support this. To avoid
too much API change, I modified struct rb_calling_info to add a
heap_argv member for storing the array, so I would not have to
thread it through many functions.  This struct is always stack
allocated, which helps ensure sure GC doesn't collect it early.

Because of how invasive the changes are, and how rarely large
arrays are actually splatted in Ruby code, the existing test/spec
suites are not great at testing for correct behavior.  To try to
find and fix all issues, I tested this in CI with
VM_ARGC_STACK_MAX to -1, ensuring that a temporary array is used
for all array splat method calls.  This was very helpful in
finding breaking cases, especially ones involving flagged keyword
hashes.

Fixes [Bug #4040]

Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com>
2023-04-25 08:06:16 -07:00
Takashi Kokubun 868f03cce1 Remove unused jit_enable_p flag
This was used only by MJIT.
2023-03-14 14:01:53 -07:00
Takashi Kokubun 290e26c729 Remove obsoleted MJIT_HEADER macro 2023-03-06 22:29:35 -08:00
Takashi Kokubun 233ddfac54 Stop exporting symbols for MJIT 2023-03-06 21:59:23 -08:00
Yusuke Endoh e7b8d32e16 Stop using receiver#inspect for "undefined method" errors
```
42.time    #=> undefined method `time' for object Integer (NoMethodError)

class Foo
  privatee #=> undefined local variable or method 'privatee' for class Foo (NoMethodError)
end

s = ""
def s.foo = nil
s.bar      #=> undefined method `bar' for extended object String (NoMethodError)
```

[Feature #18285]
2023-02-20 10:33:06 +09:00