summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro Matsumoto <[email protected]>2012-08-13 21:03:08 +0900
committerYukihiro Matsumoto <[email protected]>2012-08-13 21:03:08 +0900
commitcda1709a35ad7d495ec1a08793cd88b78e20c444 (patch)
tree8934fa5e65c5be86f2adcbe5bf9f7282bb137204 /src
parent59bf47e7f887ee987477d3c926d46dde87c1e15f (diff)
downloadmruby-cda1709a35ad7d495ec1a08793cd88b78e20c444.tar.gz
mruby-cda1709a35ad7d495ec1a08793cd88b78e20c444.zip
setjmp in mrb_funcall_with_block if mrb->jmp is empty
Diffstat (limited to 'src')
-rw-r--r--src/class.c38
-rw-r--r--src/vm.c53
2 files changed, 53 insertions, 38 deletions
diff --git a/src/class.c b/src/class.c
index d6bb85a58..795527263 100644
--- a/src/class.c
+++ b/src/class.c
@@ -855,44 +855,6 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
return m;
}
-#ifndef MRB_FUNCALL_ARGC_MAX
-#define MRB_FUNCALL_ARGC_MAX 16
-#endif
-
-mrb_value
-mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
-{
- mrb_sym mid = mrb_intern(mrb, name);
- va_list ap;
- int i;
-
- if (argc == 0) {
- return mrb_funcall_argv(mrb, self, mid, 0, 0);
- }
- else if (argc == 1) {
- mrb_value v;
-
- va_start(ap, argc);
- v = va_arg(ap, mrb_value);
- va_end(ap);
- return mrb_funcall_argv(mrb, self, mid, 1, &v);
- }
- else {
- mrb_value argv[MRB_FUNCALL_ARGC_MAX];
-
- if (argc > MRB_FUNCALL_ARGC_MAX) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX);
- }
-
- va_start(ap, argc);
- for (i = 0; i < argc; i++) {
- argv[i] = va_arg(ap, mrb_value);
- }
- va_end(ap);
- return mrb_funcall_argv(mrb, self, mid, argc, argv);
- }
-}
-
void
mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv)
{
diff --git a/src/vm.c b/src/vm.c
index 6cb421642..c27fdfbab 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -21,6 +21,7 @@
#include <string.h>
#include <setjmp.h>
#include <stddef.h>
+#include <stdarg.h>
#define STACK_INIT_SIZE 128
#define CALLINFO_INIT_SIZE 32
@@ -179,6 +180,44 @@ ecall(mrb_state *mrb, int i)
if (!mrb->exc) mrb->exc = exc;
}
+#ifndef MRB_FUNCALL_ARGC_MAX
+#define MRB_FUNCALL_ARGC_MAX 16
+#endif
+
+mrb_value
+mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
+{
+ mrb_sym mid = mrb_intern(mrb, name);
+ va_list ap;
+ int i;
+
+ if (argc == 0) {
+ return mrb_funcall_argv(mrb, self, mid, 0, 0);
+ }
+ else if (argc == 1) {
+ mrb_value v;
+
+ va_start(ap, argc);
+ v = va_arg(ap, mrb_value);
+ va_end(ap);
+ return mrb_funcall_argv(mrb, self, mid, 1, &v);
+ }
+ else {
+ mrb_value argv[MRB_FUNCALL_ARGC_MAX];
+
+ if (argc > MRB_FUNCALL_ARGC_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX);
+ }
+
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++) {
+ argv[i] = va_arg(ap, mrb_value);
+ }
+ va_end(ap);
+ return mrb_funcall_argv(mrb, self, mid, argc, argv);
+ }
+}
+
mrb_value
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk)
{
@@ -189,6 +228,20 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
int n = mrb->ci->nregs;
mrb_value val;
+ if (!mrb->jmp) {
+ jmp_buf c_jmp;
+
+ if (setjmp(c_jmp) != 0) { /* error */
+ mrb->jmp = 0;
+ return mrb_nil_value();
+ }
+ mrb->jmp = &c_jmp;
+ /* recursive call */
+ val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
+ mrb->jmp = 0;
+ return val;
+ }
+
if (argc < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc);
}