diff --git a/method.h b/method.h
index 3e424fbc02..9e0f5e7c47 100644
--- a/method.h
+++ b/method.h
@@ -218,4 +218,6 @@ void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src);
 
 void rb_scope_visibility_set(rb_method_visibility_t);
 
+VALUE rb_unnamed_parameters(int arity);
+
 #endif /* RUBY_METHOD_H */
diff --git a/proc.c b/proc.c
index b81d14ed46..276fc8737d 100644
--- a/proc.c
+++ b/proc.c
@@ -1156,8 +1156,8 @@ rb_proc_location(VALUE self)
     return iseq_location(rb_proc_get_iseq(self, 0));
 }
 
-static VALUE
-unnamed_parameters(int arity)
+VALUE
+rb_unnamed_parameters(int arity)
 {
     VALUE a, param = rb_ary_new2((arity < 0) ? -arity : arity);
     int n = (arity < 0) ? ~arity : arity;
@@ -1191,7 +1191,7 @@ rb_proc_parameters(VALUE self)
     int is_proc;
     const rb_iseq_t *iseq = rb_proc_get_iseq(self, &is_proc);
     if (!iseq) {
-	return unnamed_parameters(rb_proc_arity(self));
+	return rb_unnamed_parameters(rb_proc_arity(self));
     }
     return rb_iseq_parameters(iseq, is_proc);
 }
@@ -2575,7 +2575,7 @@ rb_method_parameters(VALUE method)
 {
     const rb_iseq_t *iseq = rb_method_iseq(method);
     if (!iseq) {
-	return unnamed_parameters(method_arity(method));
+	return rb_unnamed_parameters(method_arity(method));
     }
     return rb_iseq_parameters(iseq, 0);
 }
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index bff3b8c75b..db79a15149 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -703,6 +703,40 @@ def test_tracepoint_enabled
     assert_equal(false, trace.enabled?)
   end
 
+  def parameter_test(a, b, c)
+    yield
+  end
+
+  def test_tracepoint_parameters
+    trace = TracePoint.new(:line, :class, :end, :call, :return, :b_call, :b_return, :c_call, :c_return, :raise){|tp|
+      next if !target_thread?
+      next if tp.path != __FILE__
+      case tp.event
+      when :call, :return
+        assert_equal([[:req, :a], [:req, :b], [:req, :c]], tp.parameters)
+      when :b_call, :b_return
+        next if tp.parameters == []
+        assert_equal([[:req, :x], [:req, :y], [:req, :z]], tp.parameters)
+      when :c_call, :c_return
+        assert_equal([[:req]], tp.parameters) if tp.method_id == :getbyte
+      when :line, :class, :end, :raise
+        assert_raise(RuntimeError) { tp.parameters }
+      end
+    }
+    obj = Object.new
+    trace.enable{
+      parameter_test(1, 2, 3) {|x, y, z|
+      }
+      "".getbyte(0)
+      class << obj
+      end
+      begin
+        raise
+      rescue
+      end
+    }
+  end
+
   def method_test_tracepoint_return_value obj
     obj
   end
diff --git a/vm_trace.c b/vm_trace.c
index 3b4f2231dc..c344f3320c 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -804,6 +804,41 @@ fill_id_and_klass(rb_trace_arg_t *trace_arg)
     }
 }
 
+VALUE
+rb_tracearg_parameters(rb_trace_arg_t *trace_arg)
+{
+    switch(trace_arg->event) {
+      case RUBY_EVENT_CALL:
+      case RUBY_EVENT_RETURN:
+      case RUBY_EVENT_B_CALL:
+      case RUBY_EVENT_B_RETURN: {
+	const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->ec, trace_arg->cfp);
+	if (cfp) {
+	    return rb_iseq_parameters(cfp->iseq, 0);
+	}
+	break;
+      }
+      case RUBY_EVENT_C_CALL:
+      case RUBY_EVENT_C_RETURN: {
+	fill_id_and_klass(trace_arg);
+	if (trace_arg->klass && trace_arg->id) {
+	    const rb_method_entry_t *me;
+	    VALUE iclass = Qnil;
+	    me = rb_method_entry_without_refinements(trace_arg->klass, trace_arg->id, &iclass);
+	    return rb_unnamed_parameters(rb_method_entry_arity(me));
+	}
+	break;
+      }
+      case RUBY_EVENT_RAISE:
+      case RUBY_EVENT_LINE:
+      case RUBY_EVENT_CLASS:
+      case RUBY_EVENT_END:
+	rb_raise(rb_eRuntimeError, "not supported by this event");
+	break;
+    }
+    return Qnil;
+}
+
 VALUE
 rb_tracearg_method_id(rb_trace_arg_t *trace_arg)
 {
@@ -919,6 +954,15 @@ tracepoint_attr_path(VALUE tpval)
     return rb_tracearg_path(get_trace_arg());
 }
 
+/*
+ * Return the parameters of the method or block that the current hook belongs to
+ */
+static VALUE
+tracepoint_attr_parameters(VALUE tpval)
+{
+    return rb_tracearg_parameters(get_trace_arg());
+}
+
 /*
  * Return the name at the definition of the method being called
  */
@@ -1502,6 +1546,7 @@ Init_vm_trace(void)
     rb_define_method(rb_cTracePoint, "event", tracepoint_attr_event, 0);
     rb_define_method(rb_cTracePoint, "lineno", tracepoint_attr_lineno, 0);
     rb_define_method(rb_cTracePoint, "path", tracepoint_attr_path, 0);
+    rb_define_method(rb_cTracePoint, "parameters", tracepoint_attr_parameters, 0);
     rb_define_method(rb_cTracePoint, "method_id", tracepoint_attr_method_id, 0);
     rb_define_method(rb_cTracePoint, "callee_id", tracepoint_attr_callee_id, 0);
     rb_define_method(rb_cTracePoint, "defined_class", tracepoint_attr_defined_class, 0);
