Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -43542,12 +43542,44 @@ static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val,
static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int i, is_wide_char;
JSString *p, *q;
int64_t len;
uint32_t n;
JSValue r;
int i;

/* XXX: Use more efficient method */
/* XXX: This method is OK if r has a single refcount */
/* XXX: should use string_buffer? */
if (JS_TAG_STRING != JS_VALUE_GET_TAG(this_val))
goto slow_path;
if (!argc)
return js_dup(this_val);
p = JS_VALUE_GET_STRING(this_val);
len = p->len;
is_wide_char = p->is_wide_char;
for (i = 0; i < argc; i++) {
if (JS_TAG_STRING != JS_VALUE_GET_TAG(argv[i]))
goto slow_path;
p = JS_VALUE_GET_STRING(argv[i]);
if (p->is_wide_char != is_wide_char)
goto slow_path;
len += p->len;
}
if (len > INT_MAX)
return JS_ThrowOutOfMemory(ctx);
q = js_alloc_string(ctx, len, is_wide_char);
if (!q)
return JS_EXCEPTION;
p = JS_VALUE_GET_STRING(this_val);
n = p->len << is_wide_char;
memcpy(str8(q), str8(p), n);
len = n;
for (i = 0; i < argc; i++) {
p = JS_VALUE_GET_STRING(argv[i]);
n = p->len << is_wide_char;
memcpy(str8(q) + len, str8(p), n);
len += n;
}
return JS_MKPTR(JS_TAG_STRING, q);
slow_path:
r = JS_ToStringCheckObject(ctx, this_val);
for (i = 0; i < argc; i++) {
if (JS_IsException(r))
Expand Down
35 changes: 35 additions & 0 deletions tests/microbench.js
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,37 @@ function string_slice3(n)
return n * 1000;
}

function string_concat(n, r)
{
var i, f, xs;
// generate a function on the fly; splatting the arguments with
// "x".concat(...xs) spends too much time inside the splat itself
xs = "x".repeat(r).split("").map(_ => "'x'");
f = new Function("", `'x'.concat(${ xs.join(",") })`);
for (i = 0; i < n; i++)
f();
return n;
}

function string_concat0(n) {
return string_concat(n, 0);
}

function string_concat1(n)
{
return string_concat(n, 1);
}

function string_concat2(n)
{
return string_concat(n, 32);
}

function string_concat3(n)
{
return string_concat(n, 256);
}

/* sort bench */

function sort_bench(text) {
Expand Down Expand Up @@ -1147,6 +1178,10 @@ function main(argc, argv, g)
string_build2,
//string_build3,
//string_build4,
string_concat0,
string_concat1,
string_concat2,
string_concat3,
string_slice1,
string_slice2,
string_slice3,
Expand Down
Loading