diff --git a/src/code/amd64.c b/src/code/amd64.c
index c0afbcf68002ee5d1f610a1b31cd95802220884e..159fe5ad2eb3d27902ffaf5e24c11a39be4c035c 100644
--- a/src/code/amd64.c
+++ b/src/code/amd64.c
@@ -2082,12 +2082,12 @@ void ins_f_byte(unsigned int b)
       /* FIXME:
 
 	 Int.native_min / -1 -> exception.
-	 
+
 	 This checks for -<whatever> / -1.
 
 	 There is bound to be a better way.
 	 Somehow disable the exception?
-	 
+
 	 Some SSE alternative that does not throw?
 
 	 Perhaps a 64/64->64 instead of the current 128/64->64?
@@ -2274,19 +2274,6 @@ void ins_f_byte(unsigned int b)
     mov_mem128_reg( P_REG_RCX, 16, P_REG_XMM1 );
     mov_reg_mem128( P_REG_XMM1, P_REG_RCX, 0 );
     mov_reg_mem128( P_REG_XMM0, P_REG_RCX, 16 );
-#if 0
-    add_reg_imm_reg( sp_reg, -2*sizeof(struct svalue), P_REG_R10);
-    mov_mem_reg( P_REG_R10, 0, P_REG_RAX );
-    mov_mem_reg( P_REG_R10, 8, P_REG_RCX );
-    mov_mem_reg( P_REG_R10,16, P_REG_R8 );
-    mov_mem_reg( P_REG_R10,24, P_REG_R9 );
-    /* load done. */
-    mov_reg_mem(P_REG_R8,  P_REG_R10,0);
-    mov_reg_mem(P_REG_R9,  P_REG_R10,8);
-    mov_reg_mem(P_REG_RAX, P_REG_R10,sizeof(struct svalue));
-    mov_reg_mem(P_REG_RCX, P_REG_R10,8+sizeof(struct svalue));
-    /* save done. */
-#endif
     return;
 
   case F_INDEX:
@@ -2306,7 +2293,7 @@ void ins_f_byte(unsigned int b)
 
     /* Array and int index. */
     mov_mem32_reg( P_REG_RCX, OFFSETOF(array,size), P_REG_RDX );
-    cmp_reg32_imm( P_REG_RBX, 0 ); jge( &label_D );
+    cmp_reg_imm( P_REG_RBX, 0 ); jge( &label_D );
     /* less than 0, add size */
     add_reg_reg( P_REG_RBX, P_REG_RDX );
 
@@ -2344,6 +2331,34 @@ void ins_f_byte(unsigned int b)
     /* done */
     return;
 
+    case F_SIZEOF_STRING:
+      {
+      LABELS();
+      ins_debug_instr_prologue(b, 0, 0);
+      amd64_load_sp_reg();
+      mov_mem8_reg( sp_reg, SVAL(-1).type, P_REG_RAX );
+      cmp_reg32_imm( P_REG_RAX, PIKE_T_STRING );
+      jne( &label_A );
+      mov_mem_reg( sp_reg, SVAL(-1).value, P_REG_RAX);
+      mov_mem_reg( P_REG_RAX, OFFSETOF(pike_string,len), P_REG_RBX );
+      /* dec refs */
+      add_mem32_imm( P_REG_RAX, OFFSETOF(pike_string,refs),  -1);
+      jnz( &label_B );
+      /* no refs, call really_free_svalue */
+      add_reg_imm_reg( sp_reg, SVAL(-1).off, ARG1_REG );
+      amd64_call_c_function(really_free_svalue);
+      jmp(&label_B);
+     LABEL_A;
+        /* not a string. */
+       amd64_call_c_opcode( addr, flags );
+       jmp(&label_C);
+     LABEL_B;
+      /* save size on stack. */
+       mov_imm_mem( PIKE_T_INT, sp_reg, SVAL(-1).type );
+       mov_reg_mem( P_REG_RBX, sp_reg, SVAL(-1).value );
+     LABEL_C;
+      }
+      return;
   case F_SIZEOF:
     {
       LABELS();
@@ -3562,6 +3577,29 @@ void ins_f_byte_with_arg(unsigned int a, INT32 b)
     }
     return;
 
+  case F_SIZEOF_LOCAL_STRING:
+    {
+      LABELS();
+      ins_debug_instr_prologue(a-F_OFFSET, b, 0);
+      amd64_load_fp_reg();
+      amd64_load_sp_reg();
+
+      mov_mem_reg( fp_reg, OFFSETOF(pike_frame,locals), ARG1_REG);
+      add_reg_imm( ARG1_REG, b*sizeof(struct svalue));
+      mov_sval_type( ARG1_REG, P_REG_RAX );
+      mov_mem_reg( ARG1_REG, OFFSETOF(svalue, u.string ), P_REG_RBX);
+      /* type in RAX, svalue in ARG1 */
+      cmp_reg32_imm( P_REG_RAX, PIKE_T_STRING );
+      je( &label_B );
+      /* It's something else, svalue already in ARG1. */
+      amd64_call_c_function( pike_sizeof );
+      LABEL_B;
+      mov_mem32_reg( P_REG_RBX,OFFSETOF(pike_string, len ), P_REG_RAX );
+      /* Store result on stack */
+      amd64_push_int_reg( P_REG_RAX );
+    }
+    return;
+
   case F_PRIVATE_GLOBAL:
 /*
   This is a private (or final) global which is not a 'short' one.
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index 135030ea622e5bb7bee27d4bd5dd867160e93958..e67e12c7ac5544ca06b2d231ee0ffbece85d214e 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -2179,10 +2179,20 @@ OPCODE0(F_SIZEOF, "sizeof", 0, {
   push_int(val);
 });
 
+OPCODE0(F_SIZEOF_STRING, "sizeof(string)", 0, {
+  INT_TYPE val = pike_sizeof(Pike_sp-1);
+  pop_stack();
+  push_int(val);
+});
+
 OPCODE1(F_SIZEOF_LOCAL, "sizeof local", I_UPDATE_SP, {
   push_int(pike_sizeof(Pike_fp->locals+arg1));
 });
 
+OPCODE1(F_SIZEOF_LOCAL_STRING, "sizeof local string", I_UPDATE_SP, {
+  push_int(pike_sizeof(Pike_fp->locals+arg1));
+});
+
 OPCODE2_ALIAS(F_SSCANF, "sscanf", I_UPDATE_SP, o_sscanf);
 
 #define MKAPPLY(OP,OPCODE,NAME,TYPE,  ARG2, ARG3)			   \
diff --git a/src/operators.c b/src/operators.c
index a24c78a9385d61770beb57a19968e274a6112782..99e33652eaa31c0b7e99443795d4a56ce0b8055b 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5506,7 +5506,12 @@ static int generate_sizeof(node *n)
   if(count_args(CDR(n)) != 1) return 0;
   if(do_docode(CDR(n),DO_NOT_COPY) != 1)
     Pike_fatal("Count args was wrong in sizeof().\n");
-  emit0(F_SIZEOF);
+  if( pike_types_le( my_get_arg(&CDR(n), 0)[0]->type, string_type_string ) )
+      emit0(F_SIZEOF_STRING);
+  /* else if( pike_types_le( my_get_arg(&CDR(n), 0)[0]->type, array_type_string ) ) */
+  /*     emit0(F_SIZEOF_ARRAY); */
+  else
+      emit0(F_SIZEOF);
   return 1;
 }
 
diff --git a/src/peep.in b/src/peep.in
index d12f93b9cf5cc066ec200dfbcba7cdf2f29631ff..6f81998fb804cce6d9dddd555af79f916b947e6f 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -242,6 +242,7 @@ MARK EXTERNAL : MARK_AND_EXTERNAL($2a,$2b)
 MARK CONST0 : MARK_AND_CONST0
 MARK CONST1 : MARK_AND_CONST1
 LOCAL SIZEOF: SIZEOF_LOCAL ($1a)
+LOCAL SIZEOF_STRING: SIZEOF_LOCAL_STRING ($1a)
 MARK_AND_LOCAL SIZEOF: MARK SIZEOF_LOCAL ($1a)
 2_LOCALS SIZEOF: LOCAL($1a) SIZEOF_LOCAL ($1b)
 STRING INDEX: STRING_INDEX ($1a)