@@ -37973,29 +37973,64 @@ static int JS_CopySubArray(JSContext *ctx,
3797337973 JSValueConst obj, int64_t to_pos,
3797437974 int64_t from_pos, int64_t count, int dir)
3797537975{
37976- int64_t i, from, to;
37976+ JSObject *p;
37977+ int64_t i, from, to, len;
3797737978 JSValue val;
3797837979 int fromPresent;
3797937980
37980- /* XXX: should special case fast arrays */
37981- for (i = 0; i < count; i++) {
37981+ p = NULL;
37982+ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
37983+ p = JS_VALUE_GET_OBJ(obj);
37984+ if (p->class_id != JS_CLASS_ARRAY || !p->fast_array) {
37985+ p = NULL;
37986+ }
37987+ }
37988+
37989+ for (i = 0; i < count; ) {
3798237990 if (dir < 0) {
3798337991 from = from_pos + count - i - 1;
3798437992 to = to_pos + count - i - 1;
3798537993 } else {
3798637994 from = from_pos + i;
3798737995 to = to_pos + i;
3798837996 }
37989- fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val);
37990- if (fromPresent < 0)
37991- goto exception;
37992-
37993- if (fromPresent) {
37994- if (JS_SetPropertyInt64(ctx, obj, to, val) < 0)
37995- goto exception;
37997+ if (p && p->fast_array &&
37998+ from >= 0 && from < (len = p->u.array.count) &&
37999+ to >= 0 && to < len) {
38000+ int64_t l, j;
38001+ /* Fast path for fast arrays. Since we don't look at the
38002+ prototype chain, we can optimize only the cases where
38003+ all the elements are present in the array. */
38004+ l = count - i;
38005+ if (dir < 0) {
38006+ l = min_int64(l, from + 1);
38007+ l = min_int64(l, to + 1);
38008+ for(j = 0; j < l; j++) {
38009+ set_value(ctx, &p->u.array.u.values[to - j],
38010+ JS_DupValue(ctx, p->u.array.u.values[from - j]));
38011+ }
38012+ } else {
38013+ l = min_int64(l, len - from);
38014+ l = min_int64(l, len - to);
38015+ for(j = 0; j < l; j++) {
38016+ set_value(ctx, &p->u.array.u.values[to + j],
38017+ JS_DupValue(ctx, p->u.array.u.values[from + j]));
38018+ }
38019+ }
38020+ i += l;
3799638021 } else {
37997- if (JS_DeletePropertyInt64(ctx, obj, to, JS_PROP_THROW) < 0)
38022+ fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val);
38023+ if (fromPresent < 0)
3799838024 goto exception;
38025+
38026+ if (fromPresent) {
38027+ if (JS_SetPropertyInt64(ctx, obj, to, val) < 0)
38028+ goto exception;
38029+ } else {
38030+ if (JS_DeletePropertyInt64(ctx, obj, to, JS_PROP_THROW) < 0)
38031+ goto exception;
38032+ }
38033+ i++;
3799938034 }
3800038035 }
3800138036 return 0;
@@ -38957,64 +38992,27 @@ static JSValue js_array_push(JSContext *ctx, JSValueConst this_val,
3895738992 int64_t len, from, newLen;
3895838993
3895938994 obj = JS_ToObject(ctx, this_val);
38960-
38961- if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
38962- JSObject *p = JS_VALUE_GET_OBJ(obj);
38963- if (p->class_id != JS_CLASS_ARRAY ||
38964- !p->fast_array || !p->extensible)
38965- goto generic_case;
38966- /* length must be writable */
38967- if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE)))
38968- goto generic_case;
38969- /* check the length */
38970- if (unlikely(JS_VALUE_GET_TAG(p->prop[0].u.value) != JS_TAG_INT))
38971- goto generic_case;
38972- len = JS_VALUE_GET_INT(p->prop[0].u.value);
38973- /* we don't support holes */
38974- if (unlikely(len != p->u.array.count))
38975- goto generic_case;
38976- newLen = len + argc;
38977- if (unlikely(newLen > INT32_MAX))
38978- goto generic_case;
38979- if (newLen > p->u.array.u1.size) {
38980- if (expand_fast_array(ctx, p, newLen))
38981- goto exception;
38982- }
38983- if (unshift && argc > 0) {
38984- memmove(p->u.array.u.values + argc, p->u.array.u.values,
38985- len * sizeof(p->u.array.u.values[0]));
38986- from = 0;
38987- } else {
38988- from = len;
38989- }
38990- for(i = 0; i < argc; i++) {
38991- p->u.array.u.values[from + i] = JS_DupValue(ctx, argv[i]);
38992- }
38993- p->u.array.count = newLen;
38994- p->prop[0].u.value = JS_NewInt32(ctx, newLen);
38995- } else {
38996- generic_case:
38997- if (js_get_length64(ctx, &len, obj))
38998- goto exception;
38999- newLen = len + argc;
39000- if (newLen > MAX_SAFE_INTEGER) {
39001- JS_ThrowTypeError(ctx, "Array loo long");
38995+ if (js_get_length64(ctx, &len, obj))
38996+ goto exception;
38997+ newLen = len + argc;
38998+ if (newLen > MAX_SAFE_INTEGER) {
38999+ JS_ThrowTypeError(ctx, "Array loo long");
39000+ goto exception;
39001+ }
39002+ from = len;
39003+ if (unshift && argc > 0) {
39004+ if (JS_CopySubArray(ctx, obj, argc, 0, len, -1))
3900239005 goto exception;
39003- }
39004- from = len;
39005- if (unshift && argc > 0) {
39006- if (JS_CopySubArray(ctx, obj, argc, 0, len, -1))
39007- goto exception;
39008- from = 0;
39009- }
39010- for(i = 0; i < argc; i++) {
39011- if (JS_SetPropertyInt64(ctx, obj, from + i,
39012- JS_DupValue(ctx, argv[i])) < 0)
39013- goto exception;
39014- }
39015- if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)
39006+ from = 0;
39007+ }
39008+ for(i = 0; i < argc; i++) {
39009+ if (JS_SetPropertyInt64(ctx, obj, from + i,
39010+ JS_DupValue(ctx, argv[i])) < 0)
3901639011 goto exception;
3901739012 }
39013+ if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)
39014+ goto exception;
39015+
3901839016 JS_FreeValue(ctx, obj);
3901939017 return JS_NewInt64(ctx, newLen);
3902039018
0 commit comments