Skip to content

Commit 0b6d52c

Browse files
committed
Add JIT implementation
1 parent 7e61e6c commit 0b6d52c

File tree

1 file changed

+84
-17
lines changed

1 file changed

+84
-17
lines changed

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,7 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
863863
{
864864
zend_string *old_str;
865865
zend_uchar c;
866+
char *string_value;
866867
size_t string_len;
867868
zend_long offset;
868869

@@ -888,11 +889,11 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
888889
}
889890

890891
string_len = ZSTR_LEN(tmp);
891-
c = (zend_uchar)ZSTR_VAL(tmp)[0];
892+
string_value = ZSTR_VAL(tmp);
892893
zend_string_release(tmp);
893894
} else {
894895
string_len = Z_STRLEN_P(value);
895-
c = (zend_uchar)Z_STRVAL_P(value)[0];
896+
string_value = Z_STRVAL_P(value);
896897
}
897898

898899
if (string_len == 0) {
@@ -904,32 +905,98 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
904905
return;
905906
}
906907

907-
if (offset < 0) { /* Handle negative offset */
908-
offset += (zend_long)Z_STRLEN_P(str);
908+
/* If it's a byte char replace byte directly */
909+
if (string_len == 1) {
910+
c = (zend_uchar)string_value[0];
911+
912+
if (offset < 0) { /* Handle negative offset */
913+
offset += (zend_long)
914+
Z_STRLEN_P(str);
915+
}
916+
917+
if ((size_t) offset >= Z_STRLEN_P(str)) {
918+
/* Extend string if needed */
919+
zend_long old_len = Z_STRLEN_P(str);
920+
Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
921+
Z_TYPE_INFO_P(str) = IS_STRING_EX;
922+
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
923+
Z_STRVAL_P(str)[offset + 1] = 0;
924+
} else if (!Z_REFCOUNTED_P(str)) {
925+
old_str = Z_STR_P(str);
926+
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
927+
Z_TYPE_INFO_P(str) = IS_STRING_EX;
928+
zend_string_release(old_str);
929+
} else {
930+
SEPARATE_STRING(str);
931+
zend_string_forget_hash_val(Z_STR_P(str));
932+
}
933+
934+
Z_STRVAL_P(str)[offset] = c;
935+
936+
if (result) {
937+
/* Return the new character */
938+
ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
939+
}
940+
return;
909941
}
910942

943+
944+
911945
if ((size_t)offset >= Z_STRLEN_P(str)) {
912-
/* Extend string if needed */
946+
/* Extend string */
913947
zend_long old_len = Z_STRLEN_P(str);
914-
Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
915-
Z_TYPE_INFO_P(str) = IS_STRING_EX;
916-
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
917-
Z_STRVAL_P(str)[offset+1] = 0;
948+
zend_string *tmp = zend_string_extend(Z_STR_P(str), offset + string_len, 0); // Leak
949+
memset(ZSTR_VAL(tmp) + old_len, ' ', offset - old_len);
950+
memcpy(ZSTR_VAL(tmp) + offset, string_value, string_len);
951+
if (result) {
952+
ZVAL_STR(result, zend_string_init(ZSTR_VAL(tmp), ZSTR_LEN(tmp), 0));
953+
}
954+
zend_string_release_ex(tmp, 0);
955+
return;
918956
} else if (!Z_REFCOUNTED_P(str)) {
919-
old_str = Z_STR_P(str);
920-
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
921-
Z_TYPE_INFO_P(str) = IS_STRING_EX;
922-
zend_string_release(old_str);
957+
ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
958+
} else if (Z_REFCOUNT_P(str) > 1) {
959+
Z_DELREF_P(str);
960+
ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
923961
} else {
924-
SEPARATE_STRING(str);
925962
zend_string_forget_hash_val(Z_STR_P(str));
926963
}
927964

928-
Z_STRVAL_P(str)[offset] = c;
965+
// Buffer offset
966+
int k = 0;
967+
// Source offset
968+
int i = 0;
969+
char *buffer = emalloc(Z_STRLEN_P(str) + string_len);
970+
char *source = Z_STRVAL_P(str);
971+
// Append bytes from the source string to the buffer until the offset is reached
972+
while (i < offset) {
973+
buffer[k] = source[i];
974+
i++;
975+
k++;
976+
}
977+
i++; // Skip byte being replaced
978+
// If not an empty string then append all the bytes from the value to the buffer
979+
if (string_len > 0) {
980+
int j = 0;
981+
while (string_value[j] != '\0') {
982+
buffer[k] = string_value[j];
983+
j++;
984+
k++;
985+
}
986+
}
987+
// Add remaining bytes from the source string.
988+
while (source[i] != '\0') {
989+
buffer[k] = source[i];
990+
i++;
991+
k++;
992+
}
993+
// Append NUL byte to make a valid C string.
994+
buffer[k] = '\0';
995+
ZVAL_NEW_STR(str, zend_string_init(buffer, Z_STRLEN_P(str) + string_len - 1, 0));
996+
efree(buffer);
929997

930998
if (result) {
931-
/* Return the new character */
932-
ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
999+
ZVAL_STR(result, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
9331000
}
9341001
}
9351002

0 commit comments

Comments
 (0)