summaryrefslogtreecommitdiff
path: root/safe.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-24 11:13:49 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-24 11:13:49 +0000
commit5ee9513a7104078d9d2f51aecc354ae67f1ba002 (patch)
tree52e299b3ec089f27e306012ee11d4e70d82ff848 /safe.c
parentd0d32ba1e8e30443cadc0580e3f1e534af547f07 (diff)
Lazy Proc allocation for block parameters
[Feature #14045] * insns.def (getblockparam, setblockparam): add special access instructions for block parameters. getblockparam checks VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM and if it is not set this instruction creates a Proc object from a given blcok and set VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM. setblockparam is similar to setlocal, but set VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM. * compile.c: use get/setblockparm instead get/setlocal instructions. Note that they are used for method local block parameters (def m(&b)), not for block local method parameters (iter{|&b|). * proc.c (get_local_variable_ptr): creates Proc object for Binding#local_variable_get/set. * safe.c (safe_setter): we need to create Proc objects for postponed block parameters when $SAFE is changed. * vm_args.c (args_setup_block_parameter): used only for block local blcok parameters. * vm_args.c (vm_caller_setup_arg_block): if called with VM_CALL_ARGS_BLOCKARG_BLOCKPARAM flag then passed block values should be a block handler. * test/ruby/test_optimization.rb: add tests. * benchmark/bm_vm1_blockparam*: added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60397 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'safe.c')
-rw-r--r--safe.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/safe.c b/safe.c
index d938082d64..2e1ac8b529 100644
--- a/safe.c
+++ b/safe.c
@@ -65,17 +65,25 @@ safe_getter(void)
static void
safe_setter(VALUE val)
{
- int level = NUM2INT(val);
rb_thread_t *th = GET_THREAD();
+ int current_level = th->ec.safe_level;
+ int level = NUM2INT(val);
- if (level < th->ec.safe_level) {
+ if (level == current_level) {
+ return;
+ }
+ else if (level < current_level) {
rb_raise(rb_eSecurityError,
"tried to downgrade safe level from %d to %d",
- th->ec.safe_level, level);
+ current_level, level);
}
- if (level > SAFE_LEVEL_MAX) {
+ else if (level > SAFE_LEVEL_MAX) {
rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
}
+
+ /* block parameters */
+ rb_vm_stack_to_heap(th);
+
th->ec.safe_level = level;
}