Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: ruby/ruby
...
head fork: charliesome/ruby
Checking mergeability… Don't worry, you can still create the pull request.
  • 4 commits
  • 8 files changed
  • 0 commit comments
  • 1 contributor
View
3  gc.c
@@ -2813,6 +2813,9 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
goto again;
}
break;
+ case VM_METHOD_TYPE_CONSTVAL:
+ gc_mark(objspace, def->body.value);
+ break;
default:
break; /* ignore */
}
View
30 iseq.c
@@ -2193,6 +2193,36 @@ line_trace_specify(int line, rb_event_flag_t *events_ptr, void *ptr)
}
}
+/* analyzes the ISeq to determine if it returns a constant value.
+ if so, this value is returned. otherwise, Qundef is returned. */
+VALUE
+rb_iseq_const_value(VALUE iseqval)
+{
+ rb_iseq_t *iseq = iseq_check(iseqval);
+ VALUE val;
+ VALUE *seq = iseq->iseq;
+
+ while (*seq == BIN(trace)) seq += insn_len(BIN(trace));
+
+ if (*seq == BIN(putobject)) {
+ seq++;
+ val = *seq++;
+ } else if (*seq == BIN(putnil)) {
+ seq++;
+ val = Qnil;
+ } else {
+ return Qundef;
+ }
+
+ while (*seq == BIN(trace)) seq += insn_len(BIN(trace));
+
+ if (*seq == BIN(leave)) {
+ return val;
+ } else {
+ return Qundef;
+ }
+}
+
/*
* <b>Experimental MRI specific feature, only available as C level api.</b>
*
View
2  iseq.h
@@ -129,6 +129,8 @@ enum defined_type {
VALUE rb_iseq_defined_string(enum defined_type type);
+VALUE rb_iseq_const_value(VALUE iseqval);
+
#define DEFAULT_SPECIAL_VAR_COUNT 2
RUBY_SYMBOL_EXPORT_END
View
6 method.h
@@ -53,6 +53,7 @@ typedef enum {
VM_METHOD_TYPE_NOTIMPLEMENTED,
VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
VM_METHOD_TYPE_MISSING, /* wrapper for method_missing(id) */
+ VM_METHOD_TYPE_CONSTVAL, /* ie. def foo; 123; end */
VM_METHOD_TYPE_REFINED,
END_OF_ENUMERATION(VM_METHOD_TYPE)
@@ -77,10 +78,11 @@ typedef struct rb_method_definition_struct {
rb_method_type_t type; /* method type */
ID original_id;
union {
- rb_iseq_t * const iseq; /* should be mark */
+ rb_iseq_t * const iseq; /* should be marked */
rb_method_cfunc_t cfunc;
rb_method_attr_t attr;
- const VALUE proc; /* should be mark */
+ const VALUE proc; /* should be marked */
+ VALUE value; /* should be marked */
enum method_optimized_type {
OPTIMIZED_METHOD_TYPE_SEND,
OPTIMIZED_METHOD_TYPE_CALL,
View
4 proc.c
@@ -1806,6 +1806,10 @@ rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max)
}
break;
}
+ case VM_METHOD_TYPE_CONSTVAL: {
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
+ }
case VM_METHOD_TYPE_REFINED:
*max = UNLIMITED_ARGUMENTS;
return 0;
View
2  vm_eval.c
@@ -228,6 +228,8 @@ vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
rb_bug("vm_call0: unsupported optimized method type (%d)", ci->me->def->body.optimize_type);
}
break;
+ case VM_METHOD_TYPE_CONSTVAL:
+ return ci->me->def->body.value;
case VM_METHOD_TYPE_UNDEF:
break;
}
View
11 vm_insnhelper.c
@@ -1592,6 +1592,13 @@ vm_call_ivar(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
}
static VALUE
+vm_call_constval(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
+ cfp->sp -= ci->argc + 1;
+ return ci->me->def->body.value;
+}
+
+static VALUE
vm_call_attrset(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
{
VALUE val = vm_setivar(ci->recv, ci->me->def->body.attr.id, *(cfp->sp - 1), 0, ci, 1);
@@ -1824,6 +1831,10 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
}
break;
}
+ case VM_METHOD_TYPE_CONSTVAL:{
+ CI_SET_FASTPATH(ci, vm_call_constval, enable_fastpath);
+ return vm_call_constval(th, cfp, ci);
+ }
case VM_METHOD_TYPE_UNDEF:
break;
case VM_METHOD_TYPE_REFINED:{
View
11 vm_method.c
@@ -430,8 +430,15 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
switch (type) {
case VM_METHOD_TYPE_ISEQ: {
rb_iseq_t *iseq = (rb_iseq_t *)opts;
- *(rb_iseq_t **)&def->body.iseq = iseq;
- OBJ_WRITTEN(klass, Qundef, iseq->self);
+ VALUE const_val = rb_iseq_const_value(iseq->self);
+ if (const_val == Qundef) {
+ *(rb_iseq_t **)&def->body.iseq = iseq;
+ OBJ_WRITTEN(klass, Qundef, iseq->self);
+ } else {
+ def->type = VM_METHOD_TYPE_CONSTVAL;
+ def->body.value = const_val;
+ OBJ_WRITTEN(klass, Qundef, const_val);
+ }
break;
}
case VM_METHOD_TYPE_CFUNC:

No commit comments for this range

Something went wrong with that request. Please try again.