зеркало из https://github.com/github/ruby.git
* vm_opts.h, iseq.c, iseq.h: add compile option to force frozen
string literals. [Feature #11473] This addition is not specification change, but to try frozen string literal world discussed on [Feature #11473]. You can try frozen string literal world using this magical line: RubyVM::InstructionSequence.compile_option = {frozen_string_literal: true} Note that this is a global compilation option, so that you need to compile another script like that: p 'foo'.frozen? #=> false RubyVM::InstructionSequence.compile_option = {frozen_string_literal: true} p 'foo'.frozen? #=> false, because this line is already compiled. p eval("'foo'.frozen?") #=> true Details: * String literals are deduped by rb_fstring(). * Dynamic string literals ("...#{xyz}...") is now only frozen, not deduped. Maybe you have other ideas. Now, please do not use this option on your productions :) Of course, current specification can be changed. * compile.c: ditto. * test/ruby/test_iseq.rb: add a test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
42c3a67748
Коммит
7cf523c7db
35
ChangeLog
35
ChangeLog
|
@ -1,3 +1,38 @@
|
|||
Sat Aug 22 05:31:37 2015 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* vm_opts.h, iseq.c, iseq.h: add compile option to force frozen
|
||||
string literals.
|
||||
[Feature #11473]
|
||||
|
||||
This addition is not specification change, but to try frozen
|
||||
string literal world discussed on [Feature #11473].
|
||||
|
||||
You can try frozen string literal world using this magical line:
|
||||
|
||||
RubyVM::InstructionSequence.compile_option =
|
||||
{frozen_string_literal: true}
|
||||
|
||||
Note that this is a global compilation option, so that you need to
|
||||
compile another script like that:
|
||||
|
||||
p 'foo'.frozen? #=> false
|
||||
RubyVM::InstructionSequence.compile_option =
|
||||
{frozen_string_literal: true}
|
||||
p 'foo'.frozen? #=> false, because this line is already compiled.
|
||||
p eval("'foo'.frozen?") #=> true
|
||||
|
||||
Details:
|
||||
* String literals are deduped by rb_fstring().
|
||||
* Dynamic string literals ("...#{xyz}...") is now only frozen,
|
||||
not deduped. Maybe you have other ideas.
|
||||
|
||||
Now, please do not use this option on your productions :)
|
||||
Of course, current specification can be changed.
|
||||
|
||||
* compile.c: ditto.
|
||||
|
||||
* test/ruby/test_iseq.rb: add a test.
|
||||
|
||||
Sat Aug 22 02:53:12 2015 Aaron Patterson <tenderlove@ruby-lang.org>
|
||||
|
||||
* ext/psych/*: update to Psych 2.0.14
|
||||
|
|
14
compile.c
14
compile.c
|
@ -5002,10 +5002,15 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
break;
|
||||
}
|
||||
case NODE_STR:{
|
||||
node->nd_lit = rb_fstring(node->nd_lit);
|
||||
debugp_param("nd_lit", node->nd_lit);
|
||||
if (!poped) {
|
||||
ADD_INSN1(ret, line, putstring, node->nd_lit);
|
||||
node->nd_lit = rb_fstring(node->nd_lit);
|
||||
if (iseq->compile_data->option->frozen_string_literal) {
|
||||
ADD_INSN1(ret, line, putobject, node->nd_lit); /* already frozen */
|
||||
}
|
||||
else {
|
||||
ADD_INSN1(ret, line, putstring, node->nd_lit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -5015,6 +5020,11 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
if (poped) {
|
||||
ADD_INSN(ret, line, pop);
|
||||
}
|
||||
else {
|
||||
if (iseq->compile_data->option->frozen_string_literal) {
|
||||
ADD_SEND (ret, line, idFreeze, INT2FIX(0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_XSTR:{
|
||||
|
|
3
iseq.c
3
iseq.c
|
@ -338,7 +338,9 @@ static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
|
|||
OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
|
||||
OPT_STACK_CACHING, /* int stack_caching; */
|
||||
OPT_TRACE_INSTRUCTION, /* int trace_instruction */
|
||||
OPT_FROZEN_STRING_LITERAL
|
||||
};
|
||||
|
||||
static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
|
||||
|
||||
static void
|
||||
|
@ -375,6 +377,7 @@ make_compile_option(rb_compile_option_t *option, VALUE opt)
|
|||
SET_COMPILE_OPTION(option, opt, instructions_unification);
|
||||
SET_COMPILE_OPTION(option, opt, stack_caching);
|
||||
SET_COMPILE_OPTION(option, opt, trace_instruction);
|
||||
SET_COMPILE_OPTION(option, opt, frozen_string_literal);
|
||||
SET_COMPILE_OPTION_NUM(option, opt, debug_level);
|
||||
#undef SET_COMPILE_OPTION
|
||||
#undef SET_COMPILE_OPTION_NUM
|
||||
|
|
1
iseq.h
1
iseq.h
|
@ -61,6 +61,7 @@ struct rb_compile_option_struct {
|
|||
int instructions_unification;
|
||||
int stack_caching;
|
||||
int trace_instruction;
|
||||
int frozen_string_literal;
|
||||
int debug_level;
|
||||
};
|
||||
|
||||
|
|
|
@ -141,4 +141,17 @@ class TestISeq < Test::Unit::TestCase
|
|||
assert_raise(TypeError, bug11159) {ISeq.compile(:foo)}
|
||||
assert_raise(TypeError, bug11159) {ISeq.compile(1)}
|
||||
end
|
||||
|
||||
def test_frozen_string_literal_compile_option
|
||||
$f = 'f'
|
||||
line = __LINE__ + 2
|
||||
code = <<-'EOS'
|
||||
['foo', 'foo', "#{$f}foo"]
|
||||
EOS
|
||||
s1, s2, s3 = RubyVM::InstructionSequence.compile(code, __FILE__, __FILE__, line, {frozen_string_literal: true}).eval
|
||||
assert(s1.frozen?)
|
||||
assert(s2.frozen?)
|
||||
assert(s3.frozen?)
|
||||
assert(s1.object_id == s2.object_id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define OPT_PEEPHOLE_OPTIMIZATION 1
|
||||
#define OPT_SPECIALISED_INSTRUCTION 1
|
||||
#define OPT_INLINE_CONST_CACHE 1
|
||||
|
||||
#define OPT_FROZEN_STRING_LITERAL 0
|
||||
|
||||
/* Build Options.
|
||||
* You can't change these options at runtime.
|
||||
|
|
Загрузка…
Ссылка в новой задаче