@@ -797,6 +797,97 @@ get_int_operand(codegen_scope *s, struct mrb_insn_data *data, mrb_int *n)
797797 }
798798}
799799800+static int new_lit_str2(codegen_scope *s, const char *str1, mrb_int len1, const char *str2, mrb_int len2);
801+802+static void
803+realloc_pool_str(codegen_scope *s, mrb_irep_pool *p, mrb_int len)
804+{
805+char *str;
806+if ((p->tt & 3) == IREP_TT_SSTR) {
807+str = codegen_realloc(s, NULL, len+1);
808+ }
809+else {
810+str = (char*)p->u.str;
811+str = codegen_realloc(s, str, len+1);
812+ }
813+p->tt = len<<2 | IREP_TT_STR;
814+str[len] = '\0';
815+p->u.str = (const char*)str;
816+}
817+818+static void
819+free_pool_str(codegen_scope *s, mrb_irep_pool *p)
820+{
821+if ((p->tt & 3) != IREP_TT_SSTR) {
822+codegen_realloc(s, (char*)p->u.str, 0);
823+ }
824+p->u.str = NULL;
825+s->irep->plen--;
826+}
827+828+static void
829+merge_op_string(codegen_scope *s, uint16_t dst, uint16_t b1, uint16_t b2, const mrb_code *pc)
830+{
831+int used = 0;
832+const mrb_code *i = s->iseq;
833+834+/* scan OP_STRING that refers b1 or b2 */
835+mrb_assert(pc < s->iseq + s->icapa);
836+while (i<pc) {
837+struct mrb_insn_data data = mrb_decode_insn(i);
838+if (data.insn == OP_STRING) {
839+if (data.b == b1) used |= 1;
840+else if (data.b == b2) used |= 2;
841+ }
842+switch (i[0]) {
843+case OP_EXT1:
844+i += mrb_insn_size1[i[1]] + 1;
845+break;
846+case OP_EXT2:
847+i += mrb_insn_size2[i[1]] + 1;
848+break;
849+case OP_EXT3:
850+i += mrb_insn_size3[i[1]] + 1;
851+break;
852+default:
853+i += mrb_insn_size[i[0]];
854+break;
855+ }
856+ }
857+858+mrb_irep_pool *p1 = &s->pool[b1];
859+mrb_irep_pool *p2 = &s->pool[b2];
860+mrb_int len1 = p1->tt>>2;
861+mrb_int len2 = p2->tt>>2;
862+int off;
863+864+switch (used) {
865+case 0: /* both pools are free */
866+case 2: /* b2 is referenced */
867+/* overwrite p1; free b2 if possible */
868+off = b1;
869+realloc_pool_str(s, p1, len1+len2);
870+memcpy((void*)p1->u.str+len1, (void*)p2->u.str, len2);
871+if (used == 0 && b2+1 == s->irep->plen) {
872+free_pool_str(s, p2);
873+ }
874+break;
875+case 1: /* b1 is referenced */
876+/* overwrite p2 */
877+off = b2;
878+realloc_pool_str(s, p2, len1+len2);
879+memmove((void*)p2->u.str+len1, (void*)p2->u.str, len2);
880+memcpy((void*)p2->u.str, p1->u.str, len1);
881+break;
882+case 3: /* both b1&b2 are referenced */
883+/* create new pool */
884+off = new_lit_str2(s, p1->u.str, len1, p2->u.str, len2);
885+break;
886+ }
887+s->pc = addr_pc(s, pc);
888+genop_2(s, OP_STRING, dst, off);
889+}
890+800891static void
801892gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
802893{
@@ -811,6 +902,13 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
811902812903if (!get_int_operand(s, &data, &n)) {
813904/* not integer immediate */
905+if (op == OP_ADD && data.insn == OP_STRING) {
906+struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
907+if (data0.insn == OP_STRING) {
908+merge_op_string(s, dst, data0.b, data.b, data0.addr);
909+return;
910+ }
911+ }
814912 goto normal;
815913 }
816914struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
@@ -2269,26 +2367,6 @@ gen_blkmove(codegen_scope *s, uint16_t ainfo, int lv)
22692367push();
22702368}
227123692272-static int
2273-opt_str_add(codegen_scope *s, node *tree)
2274-{
2275-/* optimize */
2276-if (no_optimize(s)) return 0;
2277-/* receiver is a string */
2278-if (!tree->car || nint(tree->car->car) != NODE_STR) return 0;
2279-/* + call */
2280-if (!tree->cdr || nsym(tree->cdr->car) != MRB_OPSYM_2(s->mrb, add)) return 0;
2281-/* valid arguments */
2282-if (!tree->cdr->cdr || tree->cdr->cdr->cdr) return FALSE;
2283-/* takes 1 argument */
2284-if (!tree->cdr->cdr->car->car && tree->cdr->cdr->car->car->cdr) return 0;
2285-/* valid 1st arguments */
2286-if (!tree->cdr->cdr->car->car->car) return 0;
2287-if (nint(tree->cdr->cdr->car->car->car->car) == NODE_STR) return 1;
2288-// if (nint(tree->cdr->cdr->car->car->car->car) == NODE_CALL) return 2;
2289-return 0;
2290-}
2291-22922370static void
22932371codegen(codegen_scope *s, node *tree, int val)
22942372{
@@ -2701,17 +2779,6 @@ codegen(codegen_scope *s, node *tree, int val)
27012779break;
2702278027032781case NODE_CALL:
2704-if (opt_str_add(s, tree)) {
2705-if (val) {
2706-node *n1 = tree->car->cdr;
2707-node *n2 = tree->cdr->cdr->car->car->car->cdr;
2708-int off = new_lit_str2(s, (char*)n1->car, nint(n1->cdr), (char*)n2->car, nint(n2->cdr));
2709-genop_2(s, OP_STRING, cursp(), off);
2710-push();
2711- }
2712-break;
2713- }
2714-/* fall through */
27152782case NODE_FCALL:
27162783gen_call(s, tree, val, 0);
27172784break;