ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:90375] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
@ 2018-12-08  0:42 ` tenderlove
  2018-12-08 13:58 ` [ruby-core:90379] " shevegen
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: tenderlove @ 2018-12-08  0:42 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been reported by tenderlovemaking (Aaron Patterson).

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90379] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
  2018-12-08  0:42 ` [ruby-core:90375] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals tenderlove
@ 2018-12-08 13:58 ` shevegen
  2018-12-08 17:58 ` [ruby-core:90380] " eregontp
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: shevegen @ 2018-12-08 13:58 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by shevegen (Robert A. Heiler).


About the name - some suggestions if only to show which variants may be
better than others. :)

   frozen: true # could say "ruby, freeze as much as you possibly can!"

In other words, that setting/flag could mean that strings, hashes and arrays
are frozen (if the above is approved).

Or:

    frozen_string_array_hash_literals: true
    frozen_string_hash_array_literals: true
    frozen_three_literals: true

I am not saying any of these names are good names. Just putting them down. :)

    frozen_literals: true

I think one advantage for frozen_literals is that it is short. People could
use that in .rb files too.

Another approach could of course also be to only allow strings to be frozen
(which will become the default in ruby 3.x if I remember correctly); and not
allow a change of hash and arrays in a .rb file, but to allow it for the
suggestion above, e. g. in RubyVM.

One could also split the above up into hash and array as separate calls,
so rather than:

    RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)

to have:

    RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_literal: true, frozen_array_literal: true)

I mention the last primarily because we already have frozen string literals; so for
consistency it may be useful to have it split up into hash and arrays too. If this
is too cumbersome to use three separate calls, then one could always use keys that
unify these, such as in the example given by Aaron:

    frozen_hash_and_array_literal: true

could also include Strings into it:

    frozen_string_and_hash_and_array_literal: true

It's a bit cumbersome though. Perhaps a simple variant may then be:

    frozen: true
    frozen_literal: true
    frozen_literals: true

This could then mean to "freeze all that can be frozen".

Anyway; I think the first step is to ask matz about the functionality
itself, and then see which API may be best if this is approved. 

Personally I think "frozen_literals" would be ok, even if the name
may not be 100% "perfect". Ruby is not necessarily perfect in all
names e. g. I remember a few folks thinking that the word constant 
implies "can not be changed", which may be the accurate meaning,
but from within ruby itself, I think it is perfectly fine to let 
people change constants if they want to (e. g. the philosophy of
ruby to be practical and useful).

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75489

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90380] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
  2018-12-08  0:42 ` [ruby-core:90375] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals tenderlove
  2018-12-08 13:58 ` [ruby-core:90379] " shevegen
@ 2018-12-08 17:58 ` eregontp
  2018-12-10  0:55 ` [ruby-core:90387] " shyouhei
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: eregontp @ 2018-12-08 17:58 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by Eregon (Benoit Daloze).


One alternative idea which would achieve a similar goal is having #deep_freeze on core types, and recognizing `{ 'a' => ['b', { 'c' => 'd' }] }.deep_freeze`.
This would be more general, since it would also work for freezing non-constant/non-literal data structures.

I would think many if not all `[]` and `{}` are meant to be mutated, so it seems frozen Array/Hash literals them would rather be the exception than the norm (which is less clear for Strings, so I think there the magic comment makes sense).

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75490

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90387] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2018-12-08 17:58 ` [ruby-core:90380] " eregontp
@ 2018-12-10  0:55 ` shyouhei
  2018-12-10 13:07   ` [ruby-core:90404] " Benoit Daloze
  2018-12-10 20:10 ` [ruby-core:90408] " tenderlove
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 13+ messages in thread
From: shyouhei @ 2018-12-10  0:55 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by shyouhei (Shyouhei Urabe).


Off topic:

Eregon (Benoit Daloze) wrote:
> One alternative idea which would achieve a similar goal is having #deep_freeze on core types, and recognizing `{ 'a' => ['b', { 'c' => 'd' }] }.deep_freeze`.
> This would be more general, since it would also work for freezing non-constant/non-literal data structures.

Object#deep_freeze can be written without any extensions right now, like this: https://github.com/shyouhei/optdown/blob/master/lib/optdown/deeply_frozen.rb
I heard this trick from @akr .

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75509

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90404] Re: [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
  2018-12-10  0:55 ` [ruby-core:90387] " shyouhei
@ 2018-12-10 13:07   ` Benoit Daloze
  0 siblings, 0 replies; 13+ messages in thread
From: Benoit Daloze @ 2018-12-10 13:07 UTC (permalink / raw)
  To: ruby-core

Interesting code :)
But also inefficient of course, making extra copies (changing
identity) and allocations.
On Mon, Dec 10, 2018 at 1:55 AM <shyouhei@ruby-lang.org> wrote:
>
> Issue #15393 has been updated by shyouhei (Shyouhei Urabe).
>
>
> Off topic:
>
> Eregon (Benoit Daloze) wrote:
> > One alternative idea which would achieve a similar goal is having #deep_freeze on core types, and recognizing `{ 'a' => ['b', { 'c' => 'd' }] }.deep_freeze`.
> > This would be more general, since it would also work for freezing non-constant/non-literal data structures.
>
> Object#deep_freeze can be written without any extensions right now, like this: https://github.com/shyouhei/optdown/blob/master/lib/optdown/deeply_frozen.rb
> I heard this trick from @akr .
>
> ----------------------------------------
> Feature #15393: Add compilation flags to freeze Array and Hash literals
> https://bugs.ruby-lang.org/issues/15393#change-75509
>
> * Author: tenderlovemaking (Aaron Patterson)
> * Status: Open
> * Priority: Normal
> * Assignee:
> * Target version:
> ----------------------------------------
> Hi,
>
> I would like to add VM compilation options to freeze array and hash literals.  For example:
>
> ~~~ ruby
> frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
>   { 'a' => ['b', { 'c' => 'd' }] }
> eocode
> puts frozen.disasm
> ~~~
>
> Output is:
>
> ~~~
> $ ./ruby thing.rb
> == disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
> 0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
> 0002 leave
> ~~~
>
> Anything nested in the hash that can't be "frozen" will cause it to not be frozen.
>
> For example:
>
> ~~~ ruby
> not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
>   { 'a' => some_method }
> eocode
> puts not_frozen.disasm
> ~~~
>
> Output:
>
> ~~~
> $ ./ruby thing.rb
> == disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
> 0000 putobject                    "a"
> 0002 putself
> 0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
> 0006 newhash                      2
> 0008 leave
> ~~~
>
> Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.
>
> The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.
>
> I've attached a patch that implements the above.
>
> (Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)
>
> Thanks!
>
> ---Files--------------------------------
> 0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)
>
>
> --
> https://bugs.ruby-lang.org/
>
> Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90408] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2018-12-10  0:55 ` [ruby-core:90387] " shyouhei
@ 2018-12-10 20:10 ` tenderlove
  2018-12-12 21:35 ` [ruby-core:90457] " shannonskipper
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: tenderlove @ 2018-12-10 20:10 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by tenderlovemaking (Aaron Patterson).


Eregon (Benoit Daloze) wrote:
> One alternative idea which would achieve a similar goal is having #deep_freeze on core types, and recognizing `{ 'a' => ['b', { 'c' => 'd' }] }.deep_freeze`.
> This would be more general, since it would also work for freezing non-constant/non-literal data structures.

I thought about doing this with ".freeze", introducing a special instruction the same way we do for the `"string".freeze` optimization, but dealing with deoptization in the case someone monkey patches the method seems like a pain.

The reason I went this direction first is that it side steps the deoptimization problem, and if we want to support a ".deep_freeze" method later we can.  I imagine the implementation would be a branch where one of the branches is the same `putobject` instruction that I have in this patch.

Anyway, I think the advantages of this patch are:

1. No new methods like "deep_freeze", so you can try this with existing code
2. Any code you write that works with these flags enabled will also work with them disabled (vs deep_freeze that isn't on existing Rubys)
3. This patch should be forward compatible when we figure out what "deep_freeze" solution we're going to have in the future

> I would think many `[]` and `{}` are meant to be mutated, so it seems frozen Array/Hash literals them would rather be the exception than the norm (which is less clear for Strings, so I think there the magic comment makes sense).

I thought the same thing, but I'm not 100% convinced.  Lots of code in Rails (as well as our application at work) is merging some kind of "default hash" like:

~~~ ruby
def method(some_hash)
  some_hash = { :defaults => 'thing' }.merge(some_hash)
end
~~~

I'll try to get some numbers on this though.  :D



----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75557

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90457] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2018-12-10 20:10 ` [ruby-core:90408] " tenderlove
@ 2018-12-12 21:35 ` shannonskipper
  2018-12-13  8:47 ` [ruby-core:90500] " janfri26
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: shannonskipper @ 2018-12-12 21:35 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by shan (Shannon Skipper).


I had the same thought as shevy, that it'd be nice to have a:

~~~ ruby
# frozen_literals: true
~~~

It might also be worth considering a separate `frozen_array_literal` and `frozen_hash_literal`. I have files where I'd initially only want to enable one of the above.

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75617

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90500] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2018-12-12 21:35 ` [ruby-core:90457] " shannonskipper
@ 2018-12-13  8:47 ` janfri26
  2018-12-14 19:51 ` [ruby-core:90530] " nardonykolyszyn
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: janfri26 @ 2018-12-13  8:47 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by janfri (Jan Friedrich).


shan (Shannon Skipper) wrote:
> I had the same thought as shevy, that it'd be nice to have a:
> 
> ~~~ ruby
> # frozen_literals: true
> ~~~
> 
> It might also be worth considering a separate `frozen_array_literal` and `frozen_hash_literal`. I have files where I'd initially only want to enable one of the above.

+1


----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75657

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90530] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2018-12-13  8:47 ` [ruby-core:90500] " janfri26
@ 2018-12-14 19:51 ` nardonykolyszyn
  2018-12-15 13:27 ` [ruby-core:90549] " eregontp
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: nardonykolyszyn @ 2018-12-14 19:51 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by devpolish (Nardo Nykolyszyn).


I've been waiting this for a while. I'm completely agree.

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75684

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90549] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (7 preceding siblings ...)
  2018-12-14 19:51 ` [ruby-core:90530] " nardonykolyszyn
@ 2018-12-15 13:27 ` eregontp
  2018-12-18 17:08 ` [ruby-core:90605] " 223-322-223-322
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: eregontp @ 2018-12-15 13:27 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by Eregon (Benoit Daloze).


tenderlovemaking (Aaron Patterson) wrote:
> I thought about doing this with ".freeze", introducing a special instruction the same way we do for the `"string".freeze` optimization, but dealing with deoptization in the case someone monkey patches the method seems like a pain.

I think it might semantically make some sense to ignore monkey-patching of `.freeze` (and `.deep_freeze`) for calls on literals, which would then avoid needing deoptimization for this (although deoptimization would be a flag check + the current logic as fallback, it doesn't seem so bad).
It's somewhat similar to String literals not calling String#initialize for instance (same for Array, Hash).
And it's probably a bad idea to override #freeze in the hope it would be used on frozen literals anyway, as of course this would only work if the monkey-patch is reliably loaded before everything else.

Another issue is it's quite ugly to opt out of frozen array/hash literals, if a mutable copy is wanted:

```ruby
# frozen_hash_and_array_literal: true
my_mutable_data = { 'a' => ['b', { 'c' => 'd' }.dup].dup }.dup
```

That's why I think `deep_freeze` would better express the intent in some cases, and be finer-grained:

```ruby
MY_CONSTANT = { 'a' => ['b', { 'c' => 'd' }] }.deep_freeze
my_mutable_data = { 'a' => ['b', { 'c' => 'd' }] }

{ :defaults => 'thing' }.deep_freeze.merge(some_hash)
```

and this would work regardless of what is the value to freeze (but only avoid allocations if it's all literals, otherwise a constant must be used).

Furthermore, frozen literals don't allow composition or extraction in different constants:
```ruby
# frozen_hash_and_array_literal: true
MY_KEY = 'a'
MY_CONSTANT = { MY_KEY => ['b', { 'c' => 'd' }] } # Not frozen, and breaks referential transparency

MY_CONSTANT = { MY_KEY => ['b', { 'c' => 'd' }] }.deep_freeze # Works
```

OTOH, "string".freeze has shown the magic comment is much nicer in many cases than adding "string".freeze in many places (at the price of making a mutable String not so nice, but those seem rarer).
It would be interesting to get an idea of what's a typical ratio of immutable/mutable Array and Hash literals, and what converting a codebase to use frozen Array/Hash literals would look like.

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75698

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90605] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (8 preceding siblings ...)
  2018-12-15 13:27 ` [ruby-core:90549] " eregontp
@ 2018-12-18 17:08 ` 223-322-223-322
  2018-12-18 17:15 ` [ruby-core:90606] " 223-322-223-322
  2019-01-15  0:15 ` [ruby-core:91092] " tenderlove
  11 siblings, 0 replies; 13+ messages in thread
From: 223-322-223-322 @ 2018-12-18 17:08 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by sergey-posokhov (Sergey Posokhov).

File frequency-1.rb added
File frequency-2.rb added

> I would like to add VM compilation options to freeze array and hash literals.  For example:

My two samples:

----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75763

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
0001-Add-compile-options-for-freezing-hash-and-array-lite.patch (6.14 KB)
frequency-1.rb (1.04 KB)
frequency-2.rb (775 Bytes)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:90606] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (9 preceding siblings ...)
  2018-12-18 17:08 ` [ruby-core:90605] " 223-322-223-322
@ 2018-12-18 17:15 ` 223-322-223-322
  2019-01-15  0:15 ` [ruby-core:91092] " tenderlove
  11 siblings, 0 replies; 13+ messages in thread
From: 223-322-223-322 @ 2018-12-18 17:15 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by sergey-posokhov (Sergey Posokhov).

File frequency-1.rb added
File frequency-2.rb added

> I would like to add VM compilation options to freeze array and hash literals.  For example:

My two samples:

~~~ ruby
#!/usr/local/bin/ruby -w

def frequency(text)
  def prepare_string(text)
    text.gsub!(",", "")                            
        .split(" ")                              #
  end                                            # <-- freeze the result and return it
                                                 #
  def sort_frequency_report(fq)	
    fq.to_h
      .sort_by{|k, v| v }
      .reverse
      .to_h                                      #
  end                                            # <-- freeze the result and return it
                                                 #
  word_list = prepare_string(text)
  
  fq = Hash.new()
  
  for word in word_list
    if fq.has_key?(word)
      fq[word] += 1
    else
      fq[word] = 1
    end  
  end
                                                 #  
  sort_frequency_report(fq)                      # <-- freeze the result and return it
end                                              #

p frequency("text text text text
             text txet text text
             text text text")
~~~

And:

~~~ ruby
#!/usr/local/bin/ruby -w

def frequency(text)
  def prepare_string(text)
    text.gsub!(",", "")                            
        .split(" ")
  end

  def sort_frequency_report(fq)	
    #                                            #
    # fq = Hash.new()                            # Why?!.. is it correct?..
    #                                            #

    fq.to_h
      .sort_by{|k, v| v }
      .reverse
      .to_h
  end

  word_list = prepare_string(text)
  
  fq = Hash.new()
  
  for word in word_list
    if fq.has_key?(word)
      fq[word] += 1
    else
      fq[word] = 1
    end  
  end

  sort_frequency_report(fq)
end

p frequency("text text text text
             text txet text text
             text text text")
~~~


----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-75765

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!

---Files--------------------------------
frequency-1.rb (1.06 KB)
frequency-2.rb (775 Bytes)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:91092] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals
       [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
                   ` (10 preceding siblings ...)
  2018-12-18 17:15 ` [ruby-core:90606] " 223-322-223-322
@ 2019-01-15  0:15 ` tenderlove
  11 siblings, 0 replies; 13+ messages in thread
From: tenderlove @ 2019-01-15  0:15 UTC (permalink / raw)
  To: ruby-core

Issue #15393 has been updated by tenderlovemaking (Aaron Patterson).


Eregon (Benoit Daloze) wrote:
> tenderlovemaking (Aaron Patterson) wrote:
> > I thought about doing this with ".freeze", introducing a special instruction the same way we do for the `"string".freeze` optimization, but dealing with deoptization in the case someone monkey patches the method seems like a pain.
> 
> I think it might semantically make some sense to ignore monkey-patching of `.freeze` (and `.deep_freeze`) for calls on literals, which would then avoid needing deoptimization for this (although deoptimization would be a flag check + the current logic as fallback, it doesn't seem so bad).
> It's somewhat similar to String literals not calling String#initialize for instance (same for Array, Hash).
> And it's probably a bad idea to override #freeze in the hope it would be used on frozen literals anyway, as of course this would only work if the monkey-patch is reliably loaded before everything else.
> 
> Another issue is it's quite ugly to opt out of frozen array/hash literals, if a mutable copy is wanted:
> 
> ```ruby
> # frozen_hash_and_array_literal: true
> my_mutable_data = { 'a' => ['b', { 'c' => 'd' }.dup].dup }.dup
> ```
> 
> That's why I think `deep_freeze` would better express the intent in some cases, and be finer-grained:
> 
> ```ruby
> MY_CONSTANT = { 'a' => ['b', { 'c' => 'd' }] }.deep_freeze
> my_mutable_data = { 'a' => ['b', { 'c' => 'd' }] }
> 
> { :defaults => 'thing' }.deep_freeze.merge(some_hash)
> ```

Yes, I totally agree.  I think `deep_freeze` is going to be necessary for adoption of Guilds, and the code I'm proposing in this patch would be an optimization of the `deep_freeze` call on a literal.

> and this would work regardless of what is the value to freeze (but only avoid allocations if it's all literals, otherwise a constant must be used).
> 
> Furthermore, frozen literals don't allow composition or extraction in different constants:
> ```ruby
> # frozen_hash_and_array_literal: true
> MY_KEY = 'a'
> MY_CONSTANT = { MY_KEY => ['b', { 'c' => 'd' }] } # Not frozen, and breaks referential transparency
> 
> MY_CONSTANT = { MY_KEY => ['b', { 'c' => 'd' }] }.deep_freeze # Works
> ```
> 
> OTOH, "string".freeze has shown the magic comment is much nicer in many cases than adding "string".freeze in many places (at the price of making a mutable String not so nice, but those seem rarer).
> It would be interesting to get an idea of what's a typical ratio of immutable/mutable Array and Hash literals, and what converting a codebase to use frozen Array/Hash literals would look like.

Right.  I'm not proposing adding the magic comment at all, just adding a parameter to the ISeq constructor that will allow you to "deep freeze" literals in the code passed to ISeq#new.


----------------------------------------
Feature #15393: Add compilation flags to freeze Array and Hash literals
https://bugs.ruby-lang.org/issues/15393#change-76323

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi,

I would like to add VM compilation options to freeze array and hash literals.  For example:

~~~ ruby
frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => ['b', { 'c' => 'd' }] }
eocode
puts frozen.disasm
~~~

Output is:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject                    {"a"=>["b", {"c"=>"d"}]}
0002 leave
~~~

Anything nested in the hash that can't be "frozen" will cause it to not be frozen.

For example:

~~~ ruby
not_frozen = RubyVM::InstructionSequence.compile(<<-eocode, __FILE__, nil, 0, frozen_string_literal: true, frozen_hash_and_array_literal: true)
  { 'a' => some_method }
eocode
puts not_frozen.disasm
~~~

Output:

~~~
$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject                    "a"
0002 putself
0003 opt_send_without_block       <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash                      2
0008 leave
~~~

Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.

The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.

I've attached a patch that implements the above.

(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)

Thanks!



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-01-15  0:16 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-15393.20181208004237@ruby-lang.org>
2018-12-08  0:42 ` [ruby-core:90375] [Ruby trunk Feature#15393] Add compilation flags to freeze Array and Hash literals tenderlove
2018-12-08 13:58 ` [ruby-core:90379] " shevegen
2018-12-08 17:58 ` [ruby-core:90380] " eregontp
2018-12-10  0:55 ` [ruby-core:90387] " shyouhei
2018-12-10 13:07   ` [ruby-core:90404] " Benoit Daloze
2018-12-10 20:10 ` [ruby-core:90408] " tenderlove
2018-12-12 21:35 ` [ruby-core:90457] " shannonskipper
2018-12-13  8:47 ` [ruby-core:90500] " janfri26
2018-12-14 19:51 ` [ruby-core:90530] " nardonykolyszyn
2018-12-15 13:27 ` [ruby-core:90549] " eregontp
2018-12-18 17:08 ` [ruby-core:90605] " 223-322-223-322
2018-12-18 17:15 ` [ruby-core:90606] " 223-322-223-322
2019-01-15  0:15 ` [ruby-core:91092] " tenderlove

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).