summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h10
-rw-r--r--include/mruby/array.h6
-rw-r--r--include/mruby/irep.h4
-rw-r--r--include/mruby/string.h14
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c2
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c2
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c4
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h2
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c36
-rw-r--r--mrbgems/mruby-eval/src/eval.c71
-rw-r--r--mrbgems/mruby-io/test/file.rb2
-rw-r--r--mrbgems/mruby-io/test/mruby_io_test.c16
-rw-r--r--mrblib/array.rb18
-rw-r--r--src/array.c53
-rw-r--r--src/backtrace.c4
-rw-r--r--src/class.c16
-rw-r--r--src/codedump.c2
-rw-r--r--src/error.c4
-rw-r--r--src/load.c5
-rw-r--r--src/proc.c4
-rw-r--r--src/state.c2
-rw-r--r--src/string.c128
-rw-r--r--src/vm.c4
-rw-r--r--test/t/string.rb14
24 files changed, 281 insertions, 142 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 6ac15715e..87ccd8c05 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -134,8 +134,8 @@ typedef struct {
uint16_t ridx;
uint16_t epos;
struct REnv *env;
- mrb_code *pc; /* return address */
- mrb_code *err; /* error position */
+ const mrb_code *pc; /* return address */
+ const mrb_code *err; /* error position */
int argc;
int acc;
struct RClass *target_class;
@@ -250,8 +250,8 @@ typedef struct mrb_state {
#endif
#ifdef MRB_ENABLE_DEBUG_HOOK
- void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
- void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
+ void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, const mrb_code *pc, mrb_value *regs);
+ void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, const mrb_code *pc, mrb_value *regs);
#endif
#ifdef MRB_BYTECODE_DECODE_OPTION
@@ -1064,7 +1064,7 @@ MRB_API mrb_value mrb_top_self(mrb_state *);
MRB_API mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value);
MRB_API mrb_value mrb_top_run(mrb_state*, struct RProc*, mrb_value, unsigned int);
MRB_API mrb_value mrb_vm_run(mrb_state*, struct RProc*, mrb_value, unsigned int);
-MRB_API mrb_value mrb_vm_exec(mrb_state*, struct RProc*, mrb_code*);
+MRB_API mrb_value mrb_vm_exec(mrb_state*, struct RProc*, const mrb_code*);
/* compatibility macros */
#define mrb_toplevel_run_keep(m,p,k) mrb_top_run((m),(p),mrb_top_self(m),(k))
#define mrb_toplevel_run(m,p) mrb_toplevel_run_keep((m),(p),0)
diff --git a/include/mruby/array.h b/include/mruby/array.h
index c280df3ee..dde9f80cb 100644
--- a/include/mruby/array.h
+++ b/include/mruby/array.h
@@ -33,7 +33,9 @@ struct RArray {
} aux;
mrb_value *ptr;
} heap;
+#if defined(__cplusplus)
mrb_value ary[MRB_ARY_EMBED_LEN_MAX];
+#endif
} as;
};
@@ -46,7 +48,11 @@ struct RArray {
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
+#if defined(__cplusplus)
#define ARY_EMBED_PTR(a) (a)->as.ary
+#else
+#define ARY_EMBED_PTR(a) ((mrb_value*)(&(a)->as))
+#endif
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
diff --git a/include/mruby/irep.h b/include/mruby/irep.h
index fe518e713..4393129c7 100644
--- a/include/mruby/irep.h
+++ b/include/mruby/irep.h
@@ -32,7 +32,7 @@ typedef struct mrb_irep {
uint16_t nregs; /* Number of register variables */
uint8_t flags;
- mrb_code *iseq;
+ const mrb_code *iseq;
mrb_value *pool;
mrb_sym *syms;
struct mrb_irep **reps;
@@ -80,7 +80,7 @@ struct mrb_insn_data {
uint8_t c;
};
-struct mrb_insn_data mrb_decode_insn(mrb_code *pc);
+struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
MRB_END_DECL
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 6748446f9..ab29be421 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -34,6 +34,9 @@ struct RString {
} as;
};
+#define RSTR_SET_TYPE_FLAG(s, type) (RSTR_UNSET_TYPE_FLAG(s), (s)->flags |= MRB_STR_##type)
+#define RSTR_UNSET_TYPE_FLAG(s) ((s)->flags &= ~(MRB_STR_TYPE_MASK|MRB_STR_EMBED_LEN_MASK))
+
#define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED)
#define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED)
#define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK))
@@ -103,11 +106,14 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define MRB_STR_SHARED 1
#define MRB_STR_FSHARED 2
#define MRB_STR_NOFREE 4
-#define MRB_STR_POOL 8
-#define MRB_STR_ASCII 16
-#define MRB_STR_EMBED 32
-#define MRB_STR_EMBED_LEN_MASK 0x7c0
+#define MRB_STR_EMBED 8 /* type flags up to here */
+#define MRB_STR_POOL 16 /* status flags from here */
+#define MRB_STR_ASCII 32
#define MRB_STR_EMBED_LEN_SHIFT 6
+#define MRB_STR_EMBED_LEN_BITSIZE 5
+#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BITSIZE) - 1) << MRB_STR_EMBED_LEN_SHIFT)
+#define MRB_STR_TYPE_MASK (MRB_STR_POOL - 1)
+
void mrb_gc_free_str(mrb_state*, struct RString*);
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
index 513db4ded..530d824eb 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
@@ -428,7 +428,7 @@ mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
}
static mrb_bool
-check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, uint16_t line)
+check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, uint16_t line)
{
if (pc > irep->iseq) {
if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) {
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
index f888d1430..cdd7b6fa6 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
@@ -33,7 +33,7 @@ mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size
mrb_value
mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc, int direct_eval)
{
- void (*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *);
+ void (*tmp)(struct mrb_state *, struct mrb_irep *, const mrb_code *, mrb_value *);
mrb_value ruby_code;
mrb_value s;
mrb_value v;
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
index 003406172..d2fa4c856 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
@@ -505,7 +505,7 @@ get_and_parse_command(mrb_state *mrb, mrdb_state *mrdb)
}
static int32_t
-check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
+check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
{
struct RClass* c;
mrb_sym sym;
@@ -546,7 +546,7 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
}
static void
-mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
+mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
{
const char *file;
int32_t line;
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
index 7b14a899f..7c21de317 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
@@ -105,7 +105,7 @@ typedef struct mrb_debug_breakpoint {
typedef struct mrb_debug_context {
struct mrb_irep *root_irep;
struct mrb_irep *irep;
- mrb_code *pc;
+ const mrb_code *pc;
mrb_value *regs;
const char *prvfile;
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index d4031f6fd..36367f656 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -291,7 +291,7 @@ on_eval(codegen_scope *s)
}
struct mrb_insn_data
-mrb_decode_insn(mrb_code *pc)
+mrb_decode_insn(const mrb_code *pc)
{
struct mrb_insn_data data = { 0 };
mrb_code insn = READ_B();
@@ -1578,18 +1578,17 @@ codegen(codegen_scope *s, node *tree, int val)
}
codegen(s, tree->car, VAL);
pop();
- pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
-
- codegen(s, tree->cdr->car, val);
- if (elsepart) {
- if (val) pop();
- pos2 = genjmp(s, OP_JMP, 0);
- dispatch(s, pos1);
- codegen(s, elsepart, val);
- dispatch(s, pos2);
- }
- else {
- if (val) {
+ if (tree->cdr->car) {
+ pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
+ codegen(s, tree->cdr->car, val);
+ if (elsepart) {
+ if (val) pop();
+ pos2 = genjmp(s, OP_JMP, 0);
+ dispatch(s, pos1);
+ codegen(s, elsepart, val);
+ dispatch(s, pos2);
+ }
+ else if (val) {
pop();
pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
@@ -1601,6 +1600,17 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, pos1);
}
}
+ else { /* empty then-part */
+ if (elsepart) {
+ pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
+ codegen(s, elsepart, val);
+ dispatch(s, pos1);
+ }
+ else if (val) {
+ genop_1(s, OP_LOADNIL, cursp());
+ push();
+ }
+ }
}
break;
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
index e8f1d3e95..e2388f026 100644
--- a/mrbgems/mruby-eval/src/eval.c
+++ b/mrbgems/mruby-eval/src/eval.c
@@ -102,25 +102,28 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
uint8_t c;
mrb_code insn;
int argc = irep_argc(irep);
+ mrb_code *iseq = (mrb_code *)irep->iseq;
+
+ mrb_assert((irep->flags & MRB_ISEQ_NO_FREE) == 0);
for (i = 0; i < irep->ilen; ) {
- insn = irep->iseq[i];
+ insn = iseq[i];
switch(insn){
case OP_EPUSH:
- b = PEEK_S(irep->iseq+i+1);
+ b = PEEK_S(iseq+i+1);
patch_irep(mrb, irep->reps[b], bnest + 1, top);
break;
case OP_LAMBDA:
case OP_BLOCK:
- a = PEEK_B(irep->iseq+i+1);
- b = PEEK_B(irep->iseq+i+2);
+ a = PEEK_B(iseq+i+1);
+ b = PEEK_B(iseq+i+2);
patch_irep(mrb, irep->reps[b], bnest + 1, top);
break;
case OP_SEND:
- b = PEEK_B(irep->iseq+i+2);
- c = PEEK_B(irep->iseq+i+3);
+ b = PEEK_B(iseq+i+2);
+ c = PEEK_B(iseq+i+3);
if (c != 0) {
break;
}
@@ -128,24 +131,24 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
if (arg != 0) {
/* must replace */
- irep->iseq[i] = OP_GETUPVAR;
- irep->iseq[i+2] = arg >> 8;
- irep->iseq[i+3] = arg & 0xff;
+ iseq[i] = OP_GETUPVAR;
+ iseq[i+2] = arg >> 8;
+ iseq[i+3] = arg & 0xff;
}
}
break;
case OP_MOVE:
- a = PEEK_B(irep->iseq+i+1);
- b = PEEK_B(irep->iseq+i+2);
+ a = PEEK_B(iseq+i+1);
+ b = PEEK_B(iseq+i+2);
/* src part */
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
if (arg != 0) {
/* must replace */
- irep->iseq[i] = insn = OP_GETUPVAR;
- irep->iseq[i+2] = arg >> 8;
- irep->iseq[i+3] = arg & 0xff;
+ iseq[i] = insn = OP_GETUPVAR;
+ iseq[i+2] = arg >> 8;
+ iseq[i+3] = arg & 0xff;
}
}
/* dst part */
@@ -153,18 +156,18 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
if (arg != 0) {
/* must replace */
- irep->iseq[i] = insn = OP_SETUPVAR;
- irep->iseq[i+1] = (mrb_code)b;
- irep->iseq[i+2] = arg >> 8;
- irep->iseq[i+3] = arg & 0xff;
+ iseq[i] = insn = OP_SETUPVAR;
+ iseq[i+1] = (mrb_code)b;
+ iseq[i+2] = arg >> 8;
+ iseq[i+3] = arg & 0xff;
}
}
break;
case OP_GETUPVAR:
- a = PEEK_B(irep->iseq+i+1);
- b = PEEK_B(irep->iseq+i+2);
- c = PEEK_B(irep->iseq+i+3);
+ a = PEEK_B(iseq+i+1);
+ b = PEEK_B(iseq+i+2);
+ c = PEEK_B(iseq+i+3);
{
int lev = c+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
@@ -172,18 +175,18 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
if (arg != 0) {
/* must replace */
- irep->iseq[i] = OP_GETUPVAR;
- irep->iseq[i+2] = arg >> 8;
- irep->iseq[i+3] = arg & 0xff;
+ iseq[i] = OP_GETUPVAR;
+ iseq[i+2] = arg >> 8;
+ iseq[i+3] = arg & 0xff;
}
}
}
break;
case OP_SETUPVAR:
- a = PEEK_B(irep->iseq+i+1);
- b = PEEK_B(irep->iseq+i+2);
- c = PEEK_B(irep->iseq+i+3);
+ a = PEEK_B(iseq+i+1);
+ b = PEEK_B(iseq+i+2);
+ c = PEEK_B(iseq+i+3);
{
int lev = c+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
@@ -191,25 +194,25 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
if (arg != 0) {
/* must replace */
- irep->iseq[i] = OP_SETUPVAR;
- irep->iseq[i+1] = a;
- irep->iseq[i+2] = arg >> 8;
- irep->iseq[i+3] = arg & 0xff;
+ iseq[i] = OP_SETUPVAR;
+ iseq[i+1] = a;
+ iseq[i+2] = arg >> 8;
+ iseq[i+3] = arg & 0xff;
}
}
}
break;
case OP_EXT1:
- insn = PEEK_B(irep->iseq+i+1);
+ insn = PEEK_B(iseq+i+1);
i += mrb_insn_size1[insn]+1;
continue;
case OP_EXT2:
- insn = PEEK_B(irep->iseq+i+1);
+ insn = PEEK_B(iseq+i+1);
i += mrb_insn_size2[insn]+1;
continue;
case OP_EXT3:
- insn = PEEK_B(irep->iseq+i+1);
+ insn = PEEK_B(iseq+i+1);
i += mrb_insn_size3[insn]+1;
continue;
}
diff --git a/mrbgems/mruby-io/test/file.rb b/mrbgems/mruby-io/test/file.rb
index 1535ebb44..5f88bcee8 100644
--- a/mrbgems/mruby-io/test/file.rb
+++ b/mrbgems/mruby-io/test/file.rb
@@ -179,7 +179,7 @@ end
assert('File.symlink') do
target_name = "/usr/bin"
- symlink_name = "test-bin-dummy"
+ symlink_name = MRubyIOTestUtil.mktemp("test-bin-dummy-XXXXXXXX")
if !File.exist?(target_name)
skip("target directory of File.symlink is not found")
else
diff --git a/mrbgems/mruby-io/test/mruby_io_test.c b/mrbgems/mruby-io/test/mruby_io_test.c
index 2c8a75fc9..6d2941e41 100644
--- a/mrbgems/mruby-io/test/mruby_io_test.c
+++ b/mrbgems/mruby-io/test/mruby_io_test.c
@@ -44,6 +44,7 @@ mkdtemp(char *temp)
return path;
}
+#define mktemp(path) _mktemp(path)
#define umask(mode) _umask(mode)
#define rmdir(path) _rmdir(path)
#else
@@ -199,6 +200,20 @@ mrb_io_test_file_cleanup(mrb_state *mrb, mrb_value self)
}
static mrb_value
+mrb_io_test_mktemp(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value str;
+ char *cp;
+
+ mrb_get_args(mrb, "S", &str);
+ cp = mrb_str_to_cstr(mrb, str);
+ if (mktemp(cp) == NULL) {
+ mrb_sys_fail(mrb, "mktemp");
+ }
+ return mrb_str_new_cstr(mrb, cp);
+}
+
+static mrb_value
mrb_io_test_mkdtemp(mrb_state *mrb, mrb_value klass)
{
mrb_value str;
@@ -248,6 +263,7 @@ mrb_mruby_io_gem_test(mrb_state* mrb)
mrb_define_class_method(mrb, io_test, "file_test_setup", mrb_io_test_file_setup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "file_test_cleanup", mrb_io_test_file_cleanup, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, io_test, "mktemp", mrb_io_test_mktemp, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "mkdtemp", mrb_io_test_mkdtemp, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "rmdir", mrb_io_test_rmdir, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "win?", mrb_io_win_p, MRB_ARGS_NONE());
diff --git a/mrblib/array.rb b/mrblib/array.rb
index 2b080564c..6535d6d83 100644
--- a/mrblib/array.rb
+++ b/mrblib/array.rb
@@ -10,16 +10,16 @@ class Array
# and pass the respective element.
#
# ISO 15.2.12.5.10
- def each(&block)
- return to_enum :each unless block
+ # def each(&block)
+ # return to_enum :each unless block
- idx = 0
- while idx < length
- block.call(self[idx])
- idx += 1
- end
- self
- end
+ # idx = 0
+ # while idx < length
+ # block.call(self[idx])
+ # idx += 1
+ # end
+ # self
+ # end
##
# Calls the given block for each element of +self+
diff --git a/src/array.c b/src/array.c
index 06c23dcd3..33baceb9c 100644
--- a/src/array.c
+++ b/src/array.c
@@ -9,6 +9,8 @@
#include <mruby/class.h>
#include <mruby/string.h>
#include <mruby/range.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
#include "value_array.h"
#define ARY_DEFAULT_LEN 4
@@ -1257,6 +1259,55 @@ mrb_ary_svalue(mrb_state *mrb, mrb_value ary)
}
}
+static const mrb_code each_iseq[] = {
+ OP_ENTER, 0x0, 0x00, 0x1, /* OP_ENTER 0:0:0:0:0:0:1 */
+ OP_JMPIF, 0x1, 0x0, 19, /* OP_JMPIF R1 19 */
+ OP_LOADSELF, 0x3, /* OP_LOADSELF R3 */
+ OP_LOADSYM, 0x4, 0x0, /* OP_LOADSYM R4 :each*/
+ OP_SEND, 0x3, 0x1, 0x1, /* OP_SEND R3 :to_enum 1 */
+ OP_RETURN, 0x3, /* OP_RETURN R3 */
+ OP_LOADI_0, 0x2, /* OP_LOADI_0 R2 */
+ OP_JMP, 0x0, 43, /* OP_JMP 49 */
+ OP_MOVE, 0x3, 0x1, /* OP_MOVE R3 R1 */
+ OP_LOADSELF, 0x4, /* OP_LOADSELF R4 */
+ OP_MOVE, 0x5, 0x2, /* OP_MOVE R5 R2 */
+ OP_SEND, 0x4, 0x2, 0x1, /* OP_SEND R4 :[] 1 */
+ OP_SEND, 0x3, 0x3, 0x1, /* OP_SEND R3 :call 1 */
+ OP_ADDI, 0x2, 1, /* OP_ADDI R3 1 */
+ OP_MOVE, 0x3, 0x2, /* OP_MOVE R3 R2 */
+ OP_LOADSELF, 0x4, /* OP_LOADSELF R4 */
+ OP_SEND, 0x4, 0x4, 0x0, /* OP_SEND R4 :length 0 */
+ OP_LT, 0x3, /* OP_LT R3 */
+ OP_JMPIF, 0x3, 0x0, 24, /* OP_JMPIF R3 24 */
+ OP_RETURN, 0x0 /* OP_RETURN R3 */
+};
+
+static void
+init_ary_each(mrb_state *mrb, struct RClass *ary)
+{
+ struct RProc *p;
+ mrb_method_t m;
+ mrb_irep *each_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
+ static const mrb_irep mrb_irep_zero = { 0 };
+
+ *each_irep = mrb_irep_zero;
+ each_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*5);
+ each_irep->syms[0] = mrb_intern_lit(mrb, "each");
+ each_irep->syms[1] = mrb_intern_lit(mrb, "to_enum");
+ each_irep->syms[2] = mrb_intern_lit(mrb, "[]");
+ each_irep->syms[3] = mrb_intern_lit(mrb, "call");
+ each_irep->syms[4] = mrb_intern_lit(mrb, "length");
+ each_irep->slen = 5;
+ each_irep->flags = MRB_ISEQ_NO_FREE;
+ each_irep->iseq = each_iseq;
+ each_irep->ilen = sizeof(each_iseq);
+ each_irep->nregs = 7;
+ each_irep->nlocals = 3;
+ p = mrb_proc_new(mrb, each_irep);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, ary, mrb_intern_lit(mrb, "each"), m);
+}
+
void
mrb_init_array(mrb_state *mrb)
{
@@ -1297,4 +1348,6 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
mrb_define_method(mrb, a, "__svalue", mrb_ary_svalue, MRB_ARGS_NONE());
+
+ init_ary_each(mrb, a);
}
diff --git a/src/backtrace.c b/src/backtrace.c
index c9a223e07..8001849bc 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -26,7 +26,7 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
static void
-each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, mrb_code *pc0, each_backtrace_func func, void *data)
+each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data)
{
ptrdiff_t i;
@@ -37,7 +37,7 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, mrb_code *pc0, each_backtrace_fu
struct backtrace_location loc;
mrb_callinfo *ci;
mrb_irep *irep;
- mrb_code *pc;
+ const mrb_code *pc;
ci = &mrb->c->cibase[i];
diff --git a/src/class.c b/src/class.c
index e4fda18fc..43540dc3b 100644
--- a/src/class.c
+++ b/src/class.c
@@ -674,7 +674,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
if (i < argc) {
- *p = mrb_to_str(mrb, ARGV[arg_i++]);
+ *p = ARGV[arg_i++];
+ mrb_to_str(mrb, *p);
i++;
}
}
@@ -735,7 +736,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
if (i < argc) {
- ss = mrb_to_str(mrb, ARGV[arg_i++]);
+ ss = ARGV[arg_i++];
+ mrb_to_str(mrb, ss);
*ps = RSTRING_PTR(ss);
*pl = RSTRING_LEN(ss);
i++;
@@ -757,7 +759,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
if (i < argc) {
- ss = mrb_to_str(mrb, ARGV[arg_i++]);
+ ss = ARGV[arg_i++];
+ mrb_to_str(mrb, ss);
*ps = RSTRING_CSTR(mrb, ss);
i++;
}
@@ -1537,7 +1540,10 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv)
}
new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
mid = mrb_intern_lit(mrb, "initialize");
- if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) {
+ if (mrb_func_basic_p(mrb, new_class, mid, mrb_class_initialize)) {
+ mrb_class_initialize(mrb, new_class);
+ }
+ else {
mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
}
mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
@@ -2117,7 +2123,7 @@ inspect_main(mrb_state *mrb, mrb_value mod)
return mrb_str_new_lit(mrb, "main");
}
-static mrb_code new_iseq[] = {
+static const mrb_code new_iseq[] = {
OP_ENTER, 0x0, 0x10, 0x1, /* OP_ENTER 0:0:1:0:0:0:1 */
OP_LOADSELF, 0x3, /* OP_LOADSELF R3 */
OP_SEND, 0x3, 0x0, 0x0, /* OP_SEND R3 :allocate 0 */
diff --git a/src/codedump.c b/src/codedump.c
index 12d609075..b77a8adb4 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -69,7 +69,7 @@ static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
int ai;
- mrb_code *pc, *pcend;
+ const mrb_code *pc, *pcend;
mrb_code ins;
const char *file = NULL, *next_file;
diff --git a/src/error.c b/src/error.c
index 664da3fd6..bb8a0ba98 100644
--- a/src/error.c
+++ b/src/error.c
@@ -198,11 +198,11 @@ static void
exc_debug_info(mrb_state *mrb, struct RObject *exc)
{
mrb_callinfo *ci = mrb->c->ci;
- mrb_code *pc = ci->pc;
+ const mrb_code *pc = ci->pc;
if (mrb_obj_iv_defined(mrb, exc, mrb_intern_lit(mrb, "file"))) return;
while (ci >= mrb->c->cibase) {
- mrb_code *err = ci->err;
+ const mrb_code *err = ci->err;
if (!err && pc) err = pc - 1;
if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
diff --git a/src/load.c b/src/load.c
index 97eafdbb5..2aa2c576f 100644
--- a/src/load.c
+++ b/src/load.c
@@ -102,8 +102,9 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
}
else {
size_t data_len = sizeof(mrb_code) * irep->ilen;
- irep->iseq = (mrb_code *)mrb_malloc(mrb, data_len);
- memcpy(irep->iseq, src, data_len);
+ void *buf = mrb_malloc(mrb, data_len);
+ irep->iseq = (mrb_code *)buf;
+ memcpy(buf, src, data_len);
src += data_len;
}
}
diff --git a/src/proc.c b/src/proc.c
index a0edf22bc..ca398384f 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -9,7 +9,7 @@
#include <mruby/proc.h>
#include <mruby/opcode.h>
-static mrb_code call_iseq[] = {
+static const mrb_code call_iseq[] = {
OP_CALL,
};
@@ -256,7 +256,7 @@ mrb_int
mrb_proc_arity(const struct RProc *p)
{
struct mrb_irep *irep;
- mrb_code *pc;
+ const mrb_code *pc;
mrb_aspec aspec;
int ma, op, ra, pa, arity;
diff --git a/src/state.c b/src/state.c
index 69b069304..010a8d68a 100644
--- a/src/state.c
+++ b/src/state.c
@@ -117,7 +117,7 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
int i;
if (!(irep->flags & MRB_ISEQ_NO_FREE))
- mrb_free(mrb, irep->iseq);
+ mrb_free(mrb, (void*)irep->iseq);
if (irep->pool) for (i=0; i<irep->plen; i++) {
if (mrb_type(irep->pool[i]) == MRB_TT_STRING) {
mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
diff --git a/src/string.c b/src/string.c
index 2b9a5cfde..1edbff802 100644
--- a/src/string.c
+++ b/src/string.c
@@ -24,7 +24,7 @@
typedef struct mrb_shared_string {
int refcnt;
- mrb_int len;
+ mrb_int capa;
char *ptr;
} mrb_shared_string;
@@ -42,6 +42,7 @@ str_init_normal_capa(mrb_state *mrb, struct RString *s,
s->as.heap.ptr = dst;
s->as.heap.len = (mrb_int)len;
s->as.heap.aux.capa = (mrb_int)capa;
+ RSTR_UNSET_TYPE_FLAG(s);
}
static void
@@ -55,7 +56,7 @@ str_init_embed(struct RString *s, const char *p, size_t len)
{
if (p) memcpy(s->as.ary, p, len);
s->as.ary[len] = '\0';
- RSTR_SET_EMBED_FLAG(s);
+ RSTR_SET_TYPE_FLAG(s, EMBED);
RSTR_SET_EMBED_LEN(s, len);
}
@@ -65,7 +66,7 @@ str_init_nofree(struct RString *s, const char *p, size_t len)
s->as.heap.ptr = (char *)p;
s->as.heap.len = (mrb_int)len;
s->as.heap.aux.capa = 0; /* nofree */
- RSTR_SET_NOFREE_FLAG(s);
+ RSTR_SET_TYPE_FLAG(s, NOFREE);
}
static void
@@ -76,14 +77,14 @@ str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, m
}
else {
shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
- shared->refcnt = 2;
+ shared->refcnt = 1;
shared->ptr = orig->as.heap.ptr;
- shared->len = orig->as.heap.len;
+ shared->capa = orig->as.heap.aux.capa;
}
s->as.heap.ptr = orig->as.heap.ptr;
s->as.heap.len = orig->as.heap.len;
s->as.heap.aux.shared = shared;
- RSTR_SET_SHARED_FLAG(s);
+ RSTR_SET_TYPE_FLAG(s, SHARED);
}
static void
@@ -92,7 +93,7 @@ str_init_fshared(const struct RString *orig, struct RString *s, struct RString *
s->as.heap.ptr = orig->as.heap.ptr;
s->as.heap.len = orig->as.heap.len;
s->as.heap.aux.fshared = fshared;
- RSTR_SET_FSHARED_FLAG(s);
+ RSTR_SET_TYPE_FLAG(s, FSHARED);
}
static void
@@ -188,7 +189,6 @@ resize_capa(mrb_state *mrb, struct RString *s, size_t capacity)
if (RSTR_EMBED_P(s)) {
if (!RSTR_EMBEDDABLE_P(capacity)) {
str_init_normal_capa(mrb, s, s->as.ary, RSTR_EMBED_LEN(s), capacity);
- RSTR_UNSET_EMBED_FLAG(s);
}
}
else {
@@ -337,19 +337,69 @@ chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
/* map byte offset to character index */
static mrb_int
-bytes2chars(char *p, mrb_int bi)
+bytes2chars(char *p, mrb_int len, mrb_int bi)
{
- mrb_int i, b, n;
+ const char *e = p + (size_t)len;
+ const char *pivot = p + bi;
+ mrb_int i;
- for (b=i=0; b<bi; i++) {
- n = utf8len_codepage[(unsigned char)*p];
- b += n;
- p += n;
+ for (i = 0; p < pivot; i ++) {
+ p += utf8len(p, e);
}
- if (b != bi) return -1;
+ if (p != pivot) return -1;
return i;
}
+static const char *
+char_adjust(const char *beg, const char *end, const char *ptr)
+{
+ if ((ptr > beg || ptr < end) && (*ptr & 0xc0) == 0x80) {
+ const int utf8_adjust_max = 3;
+ const char *p;
+
+ if (ptr - beg > utf8_adjust_max) {
+ beg = ptr - utf8_adjust_max;
+ }
+
+ p = ptr;
+ while (p > beg) {
+ p --;
+ if ((*p & 0xc0) != 0x80) {
+ int clen = utf8len(p, end);
+ if (clen > ptr - p) return p;
+ break;
+ }
+ }
+ }
+
+ return ptr;
+}
+
+static const char *
+char_backtrack(const char *ptr, const char *end)
+{
+ if (ptr < end) {
+ const int utf8_bytelen_max = 4;
+ const char *p;
+
+ if (end - ptr > utf8_bytelen_max) {
+ ptr = end - utf8_bytelen_max;
+ }
+
+ p = end;
+ while (p > ptr) {
+ p --;
+ if ((*p & 0xc0) != 0x80) {
+ int clen = utf8len_codepage[(unsigned char)*p];
+ if (clen == end - p) { return p; }
+ break;
+ }
+ }
+ }
+
+ return end - 1;
+}
+
static mrb_int
str_index_str_by_char_search(mrb_state *mrb, const char *p, const char *pend, const char *s, const mrb_int slen, mrb_int off)
{
@@ -412,7 +462,9 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
#else
#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
#define chars2bytes(p, off, ci) (ci)
-#define bytes2chars(p, bi) (bi)
+#define bytes2chars(p, end, bi) (bi)
+#define char_adjust(beg, end, ptr) (ptr)
+#define char_backtrack(ptr, end) ((end) - 1)
#define BYTES_ALIGN_CHECK(pos)
#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
#endif
@@ -464,34 +516,28 @@ mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n)
static void
str_make_shared(mrb_state *mrb, struct RString *orig, struct RString *s)
{
- mrb_int len = RSTR_LEN(orig);
+ size_t len = (size_t)orig->as.heap.len;
mrb_assert(!RSTR_EMBED_P(orig));
if (RSTR_NOFREE_P(orig)) {
str_init_nofree(s, orig->as.heap.ptr, len);
- RSTR_UNSET_EMBED_FLAG(s);
}
else if (RSTR_SHARED_P(orig)) {
str_init_shared(mrb, orig, s, orig->as.heap.aux.shared);
- RSTR_UNSET_EMBED_FLAG(s);
}
else if (RSTR_FSHARED_P(orig)) {
str_init_fshared(orig, s, orig->as.heap.aux.fshared);
- RSTR_UNSET_EMBED_FLAG(s);
}
else if (MRB_FROZEN_P(orig) && !RSTR_POOL_P(orig)) {
str_init_fshared(orig, s, orig);
- RSTR_UNSET_EMBED_FLAG(s);
}
else {
if (orig->as.heap.aux.capa > orig->as.heap.len) {
orig->as.heap.ptr = (char *)mrb_realloc(mrb, orig->as.heap.ptr, len+1);
+ orig->as.heap.aux.capa = len;
}
str_init_shared(mrb, orig, s, NULL);
- RSTR_UNSET_EMBED_FLAG(s);
- orig->as.heap.aux.shared = s->as.heap.aux.shared;
- RSTR_SET_SHARED_FLAG(orig);
- RSTR_UNSET_EMBED_FLAG(s);
+ str_init_shared(mrb, orig, orig, s->as.heap.aux.shared);
}
}
@@ -601,7 +647,6 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
RSTR_COPY_ASCII_FLAG(s1, s2);
if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared);
- RSTR_UNSET_SHARED_FLAG(s1);
}
else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1) && !RSTR_FSHARED_P(s1)
&& s1->as.heap.ptr) {
@@ -609,8 +654,6 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
}
len = (size_t)RSTR_LEN(s2);
- RSTR_UNSET_FSHARED_FLAG(s1);
- RSTR_UNSET_NOFREE_FLAG(s1);
if (RSTR_EMBEDDABLE_P(len)) {
str_init_embed(s1, RSTR_PTR(s2), len);
}
@@ -624,7 +667,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
static mrb_int
str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
{
- char *s, *sbeg, *t;
+ const char *s, *sbeg, *t;
struct RString *ps = mrb_str_ptr(str);
mrb_int len = RSTRING_LEN(sub);
@@ -637,11 +680,12 @@ str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
s = RSTR_PTR(ps) + pos;
t = RSTRING_PTR(sub);
if (len) {
+ s = char_adjust(sbeg, sbeg + RSTR_LEN(ps), s);
while (sbeg <= s) {
if (memcmp(s, t, len) == 0) {
return (mrb_int)(s - RSTR_PTR(ps));
}
- s--;
+ s = char_backtrack(sbeg, s);
}
return -1;
}
@@ -736,29 +780,17 @@ mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
mrb_shared_string *shared = s->as.heap.aux.shared;
if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
- s->as.heap.ptr = shared->ptr;
- s->as.heap.aux.capa = shared->len;
- RSTR_PTR(s)[s->as.heap.len] = '\0';
+ s->as.heap.aux.capa = shared->capa;
+ s->as.heap.ptr[s->as.heap.len] = '\0';
mrb_free(mrb, shared);
}
else {
- char *p = RSTR_PTR(s);
- size_t len = (size_t)s->as.heap.len;
-
- str_init(mrb, s, p, len);
+ str_init(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
str_decref(mrb, shared);
}
- RSTR_UNSET_SHARED_FLAG(s);
- return;
}
- if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
- char *p = s->as.heap.ptr;
- size_t len = (size_t)s->as.heap.len;
-
- RSTR_UNSET_NOFREE_FLAG(s);
- RSTR_UNSET_FSHARED_FLAG(s);
- str_init(mrb, s, p, len);
- return;
+ else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
+ str_init(mrb, s, s->as.heap.ptr, (size_t)s->as.heap.len);
}
}
@@ -2016,7 +2048,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str)
case MRB_TT_STRING:
pos = str_rindex(mrb, str, sub, pos);
if (pos >= 0) {
- pos = bytes2chars(RSTRING_PTR(str), pos);
+ pos = bytes2chars(RSTRING_PTR(str), RSTRING_LEN(str), pos);
BYTES_ALIGN_CHECK(pos);
return mrb_fixnum_value(pos);
}
diff --git a/src/vm.c b/src/vm.c
index 458b9249e..7ba49a32d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -971,10 +971,10 @@ check_target_class(mrb_state *mrb)
void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
MRB_API mrb_value
-mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
+mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *pc)
{
/* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
- mrb_code *pc0 = pc;
+ const mrb_code *pc0 = pc;
mrb_irep *irep = proc->body.irep;
mrb_value *pool = irep->pool;
mrb_sym *syms = irep->syms;
diff --git a/test/t/string.rb b/test/t/string.rb
index 46cbe6e2a..7e3c327b1 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -557,10 +557,16 @@ end
assert('String#rindex(UTF-8)', '15.2.10.5.31') do
str = "こんにちは世界!\nこんにちは世界!"
- assert_nil str.index('さ')
- assert_equal 3, str.index('ち')
- assert_equal 12, str.index('ち', 10)
- assert_equal nil, str.index("さ")
+ assert_nil str.rindex('さ')
+ assert_equal 12, str.rindex('ち')
+ assert_equal 3, str.rindex('ち', 10)
+
+ broken = "\xf0☀\xf1☁\xf2☂\xf3☃\xf0☀\xf1☁\xf2☂\xf3☃"
+ assert_nil broken.rindex("\x81") # "\x81" is a part of "☁" ("\xe2\x98\x81")
+ assert_equal 11, broken.rindex("☁")
+ assert_equal 11, broken.rindex("☁", 12)
+ assert_equal 11, broken.rindex("☁", 11)
+ assert_equal 3, broken.rindex("☁", 10)
end if UTF8STRING
# assert('String#scan', '15.2.10.5.32') do