My working unpac space for OCaml projects in development
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

- optimized Regexp.prototype.exec - optimized String.prototype.replace - optimized 'arguments' object creation - optimized access to non strict 'arguments' elements

+568 -312
+1 -1
vendor/git/quickjs-c/Changelog
··· 1 - - micro optimizations (15% faster on bench-v8) 1 + - micro optimizations (30% faster on bench-v8) 2 2 - added resizable array buffers 3 3 - added ArrayBuffer.prototype.transfer 4 4 - added the Iterator object and methods
+515 -311
vendor/git/quickjs-c/quickjs.c
··· 127 127 JS_CLASS_BOOLEAN, /* u.object_data */ 128 128 JS_CLASS_SYMBOL, /* u.object_data */ 129 129 JS_CLASS_ARGUMENTS, /* u.array | length */ 130 - JS_CLASS_MAPPED_ARGUMENTS, /* | length */ 130 + JS_CLASS_MAPPED_ARGUMENTS, /* u.array | length */ 131 131 JS_CLASS_DATE, /* u.object_data */ 132 132 JS_CLASS_MODULE_NS, 133 133 JS_CLASS_C_FUNCTION, /* u.cfunc */ ··· 460 460 uint8_t std_array_prototype; 461 461 462 462 JSShape *array_shape; /* initial shape for Array objects */ 463 + JSShape *arguments_shape; /* shape for arguments objects */ 464 + JSShape *mapped_arguments_shape; /* shape for mapped arguments objects */ 465 + JSShape *regexp_shape; /* shape for regexp objects */ 466 + JSShape *regexp_result_shape; /* shape for regexp result objects */ 463 467 464 468 JSValue *class_proto; 465 469 JSValue function_proto; ··· 937 941 uint8_t extensible : 1; 938 942 uint8_t free_mark : 1; /* only used when freeing objects with cycles */ 939 943 uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */ 940 - uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */ 944 + uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_MAPPED_ARGUMENTS and typed arrays) */ 941 945 uint8_t is_constructor : 1; /* TRUE if object is a constructor function */ 942 946 uint8_t has_immutable_prototype : 1; /* cannot modify the prototype */ 943 947 uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ ··· 986 990 int16_t magic; 987 991 } cfunc; 988 992 /* array part for fast arrays and typed arrays */ 989 - struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ 993 + struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_MAPPED_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ 990 994 union { 991 - uint32_t size; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ 995 + uint32_t size; /* JS_CLASS_ARRAY */ 992 996 struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ 993 997 } u1; 994 998 union { 995 999 JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ 1000 + JSVarRef **var_refs; /* JS_CLASS_MAPPED_ARGUMENTS */ 996 1001 void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ 997 1002 int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ 998 1003 uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ ··· 1122 1127 int argc, JSValueConst *argv, int magic); 1123 1128 static void js_array_finalizer(JSRuntime *rt, JSValue val); 1124 1129 static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); 1130 + static void js_mapped_arguments_finalizer(JSRuntime *rt, JSValue val); 1131 + static void js_mapped_arguments_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); 1125 1132 static void js_object_data_finalizer(JSRuntime *rt, JSValue val); 1126 1133 static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); 1127 1134 static void js_c_function_finalizer(JSRuntime *rt, JSValue val); ··· 1190 1197 static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len); 1191 1198 static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, 1192 1199 JSValueConst flags); 1193 - static JSValue js_regexp_set_internal(JSContext *ctx, JSValue obj, 1194 - JSValue pattern, JSValue bc); 1200 + static JSValue JS_NewRegexp(JSContext *ctx, JSValue pattern, JSValue bc); 1195 1201 static void gc_decref(JSRuntime *rt); 1196 1202 static int JS_NewClass1(JSRuntime *rt, JSClassID class_id, 1197 1203 const JSClassDef *class_def, JSAtom name); ··· 1211 1217 static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val); 1212 1218 static JSProperty *add_property(JSContext *ctx, 1213 1219 JSObject *p, JSAtom prop, int prop_flags); 1220 + static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags); 1214 1221 static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); 1215 1222 JSValue JS_ThrowOutOfMemory(JSContext *ctx); 1216 1223 static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); ··· 1550 1557 { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */ 1551 1558 { JS_ATOM_Symbol, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_SYMBOL */ 1552 1559 { JS_ATOM_Arguments, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARGUMENTS */ 1553 - { JS_ATOM_Arguments, NULL, NULL }, /* JS_CLASS_MAPPED_ARGUMENTS */ 1560 + { JS_ATOM_Arguments, js_mapped_arguments_finalizer, js_mapped_arguments_mark }, /* JS_CLASS_MAPPED_ARGUMENTS */ 1554 1561 { JS_ATOM_Date, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_DATE */ 1555 1562 { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_MODULE_NS */ 1556 1563 { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */ ··· 1676 1683 countof(js_std_class_def)) < 0) 1677 1684 goto fail; 1678 1685 rt->class_array[JS_CLASS_ARGUMENTS].exotic = &js_arguments_exotic_methods; 1686 + rt->class_array[JS_CLASS_MAPPED_ARGUMENTS].exotic = &js_arguments_exotic_methods; 1679 1687 rt->class_array[JS_CLASS_STRING].exotic = &js_string_exotic_methods; 1680 1688 rt->class_array[JS_CLASS_MODULE_NS].exotic = &js_module_ns_exotic_methods; 1681 1689 ··· 2313 2321 2314 2322 if (ctx->array_shape) 2315 2323 mark_func(rt, &ctx->array_shape->header); 2324 + 2325 + if (ctx->arguments_shape) 2326 + mark_func(rt, &ctx->arguments_shape->header); 2327 + 2328 + if (ctx->mapped_arguments_shape) 2329 + mark_func(rt, &ctx->mapped_arguments_shape->header); 2330 + 2331 + if (ctx->regexp_shape) 2332 + mark_func(rt, &ctx->regexp_shape->header); 2333 + 2334 + if (ctx->regexp_result_shape) 2335 + mark_func(rt, &ctx->regexp_result_shape->header); 2316 2336 } 2317 2337 2318 2338 void JS_FreeContext(JSContext *ctx) ··· 2376 2396 JS_FreeValue(ctx, ctx->function_proto); 2377 2397 2378 2398 js_free_shape_null(ctx->rt, ctx->array_shape); 2399 + js_free_shape_null(ctx->rt, ctx->arguments_shape); 2400 + js_free_shape_null(ctx->rt, ctx->mapped_arguments_shape); 2401 + js_free_shape_null(ctx->rt, ctx->regexp_shape); 2402 + js_free_shape_null(ctx->rt, ctx->regexp_result_shape); 2379 2403 2380 2404 list_del(&ctx->link); 2381 2405 remove_gc_object(&ctx->header); ··· 5169 5193 printf("}\n"); 5170 5194 } 5171 5195 5172 - static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id) 5196 + /* 'props[]' is used to initialized the object properties. The number 5197 + of elements depends on the shape. */ 5198 + static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id, 5199 + JSProperty *props) 5173 5200 { 5174 5201 JSObject *p; 5175 - 5202 + int i; 5203 + 5176 5204 js_trigger_gc(ctx->rt, sizeof(JSObject)); 5177 5205 p = js_malloc(ctx, sizeof(JSObject)); 5178 5206 if (unlikely(!p)) ··· 5194 5222 if (unlikely(!p->prop)) { 5195 5223 js_free(ctx, p); 5196 5224 fail: 5225 + if (props) { 5226 + JSShapeProperty *prs = get_shape_prop(sh); 5227 + for(i = 0; i < sh->prop_count; i++) { 5228 + free_property(ctx->rt, &props[i], prs->flags); 5229 + prs++; 5230 + } 5231 + } 5197 5232 js_free_shape(ctx->rt, sh); 5198 5233 return JS_EXCEPTION; 5199 5234 } ··· 5209 5244 p->u.array.u.values = NULL; 5210 5245 p->u.array.count = 0; 5211 5246 p->u.array.u1.size = 0; 5212 - /* the length property is always the first one */ 5213 - if (likely(sh == ctx->array_shape)) { 5214 - pr = &p->prop[0]; 5215 - } else { 5216 - /* only used for the first array */ 5217 - /* cannot fail */ 5218 - pr = add_property(ctx, p, JS_ATOM_length, 5219 - JS_PROP_WRITABLE | JS_PROP_LENGTH); 5247 + if (!props) { 5248 + /* XXX: remove */ 5249 + /* the length property is always the first one */ 5250 + if (likely(sh == ctx->array_shape)) { 5251 + pr = &p->prop[0]; 5252 + } else { 5253 + /* only used for the first array */ 5254 + /* cannot fail */ 5255 + pr = add_property(ctx, p, JS_ATOM_length, 5256 + JS_PROP_WRITABLE | JS_PROP_LENGTH); 5257 + } 5258 + pr->u.value = JS_NewInt32(ctx, 0); 5220 5259 } 5221 - pr->u.value = JS_NewInt32(ctx, 0); 5222 5260 } 5223 5261 break; 5224 5262 case JS_CLASS_C_FUNCTION: 5225 5263 p->prop[0].u.value = JS_UNDEFINED; 5226 5264 break; 5227 5265 case JS_CLASS_ARGUMENTS: 5266 + case JS_CLASS_MAPPED_ARGUMENTS: 5228 5267 case JS_CLASS_UINT8C_ARRAY: 5229 5268 case JS_CLASS_INT8_ARRAY: 5230 5269 case JS_CLASS_UINT8_ARRAY: ··· 5270 5309 } 5271 5310 p->header.ref_count = 1; 5272 5311 add_gc_object(ctx->rt, &p->header, JS_GC_OBJ_TYPE_JS_OBJECT); 5312 + if (props) { 5313 + for(i = 0; i < sh->prop_count; i++) 5314 + p->prop[i] = props[i]; 5315 + } 5273 5316 return JS_MKPTR(JS_TAG_OBJECT, p); 5274 5317 } 5275 5318 ··· 5297 5340 if (!sh) 5298 5341 return JS_EXCEPTION; 5299 5342 } 5300 - return JS_NewObjectFromShape(ctx, sh, class_id); 5343 + return JS_NewObjectFromShape(ctx, sh, class_id, NULL); 5301 5344 } 5302 5345 5303 5346 /* WARNING: the shape is not hashed. It is used for objects where ··· 5320 5363 sh = js_new_shape_nohash(ctx, proto, hash_size, n_alloc_props); 5321 5364 if (!sh) 5322 5365 return JS_EXCEPTION; 5323 - return JS_NewObjectFromShape(ctx, sh, class_id); 5366 + return JS_NewObjectFromShape(ctx, sh, class_id, NULL); 5324 5367 } 5325 5368 5326 5369 #if 0 ··· 5383 5426 JSValue JS_NewArray(JSContext *ctx) 5384 5427 { 5385 5428 return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape), 5386 - JS_CLASS_ARRAY); 5429 + JS_CLASS_ARRAY, NULL); 5387 5430 } 5388 5431 5389 5432 JSValue JS_NewObject(JSContext *ctx) ··· 6578 6621 s->fast_array_elements += p->u.array.count; 6579 6622 for (i = 0; i < p->u.array.count; i++) { 6580 6623 compute_value_size(p->u.array.u.values[i], hp); 6624 + } 6625 + } 6626 + } 6627 + break; 6628 + case JS_CLASS_MAPPED_ARGUMENTS: /* u.array | length */ 6629 + if (p->fast_array) { 6630 + s->fast_array_count++; 6631 + if (p->u.array.u.values) { 6632 + s->memory_used_count++; 6633 + s->memory_used_size += p->u.array.count * 6634 + sizeof(*p->u.array.u.var_refs); 6635 + s->fast_array_elements += p->u.array.count; 6636 + for (i = 0; i < p->u.array.count; i++) { 6637 + compute_value_size(*p->u.array.u.var_refs[i]->pvalue, hp); 6581 6638 } 6582 6639 } 6583 6640 } ··· 8579 8636 case JS_CLASS_ARGUMENTS: 8580 8637 if (unlikely(idx >= p->u.array.count)) goto slow_path; 8581 8638 return JS_DupValue(ctx, p->u.array.u.values[idx]); 8639 + case JS_CLASS_MAPPED_ARGUMENTS: 8640 + if (unlikely(idx >= p->u.array.count)) goto slow_path; 8641 + return JS_DupValue(ctx, *p->u.array.u.var_refs[idx]->pvalue); 8582 8642 case JS_CLASS_INT8_ARRAY: 8583 8643 if (unlikely(idx >= p->u.array.count)) goto slow_path; 8584 8644 return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]); ··· 8757 8817 return &p->prop[p->shape->prop_count - 1]; 8758 8818 } 8759 8819 8760 - /* can be called on Array or Arguments objects. return < 0 if 8761 - memory alloc error. */ 8820 + /* can be called on JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS or 8821 + JS_CLASS_MAPPED_ARGUMENTS objects. return < 0 if memory alloc 8822 + error. */ 8762 8823 static no_inline __exception int convert_fast_array_to_array(JSContext *ctx, 8763 8824 JSObject *p) 8764 8825 { 8765 8826 JSProperty *pr; 8766 8827 JSShape *sh; 8767 - JSValue *tab; 8768 8828 uint32_t i, len, new_count; 8769 8829 8770 8830 if (js_shape_prepare_update(ctx, p, NULL)) ··· 8778 8838 return -1; 8779 8839 } 8780 8840 8781 - tab = p->u.array.u.values; 8782 - for(i = 0; i < len; i++) { 8783 - /* add_property cannot fail here but 8784 - __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ 8785 - pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E); 8786 - pr->u.value = *tab++; 8841 + if (p->class_id == JS_CLASS_MAPPED_ARGUMENTS) { 8842 + JSVarRef **tab = p->u.array.u.var_refs; 8843 + for(i = 0; i < len; i++) { 8844 + /* add_property cannot fail here but 8845 + __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ 8846 + pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF); 8847 + pr->u.var_ref = *tab++; 8848 + } 8849 + } else { 8850 + JSValue *tab = p->u.array.u.values; 8851 + for(i = 0; i < len; i++) { 8852 + /* add_property cannot fail here but 8853 + __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ 8854 + pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E); 8855 + pr->u.value = *tab++; 8856 + } 8787 8857 } 8788 8858 js_free(ctx, p->u.array.u.values); 8789 8859 p->u.array.count = 0; ··· 8887 8957 if (JS_AtomIsArrayIndex(ctx, &idx, atom) && 8888 8958 idx < p->u.array.count) { 8889 8959 if (p->class_id == JS_CLASS_ARRAY || 8890 - p->class_id == JS_CLASS_ARGUMENTS) { 8960 + p->class_id == JS_CLASS_ARGUMENTS || 8961 + p->class_id == JS_CLASS_MAPPED_ARGUMENTS) { 8891 8962 /* Special case deleting the last element of a fast Array */ 8892 8963 if (idx == p->u.array.count - 1) { 8893 - JS_FreeValue(ctx, p->u.array.u.values[idx]); 8964 + if (p->class_id == JS_CLASS_MAPPED_ARGUMENTS) { 8965 + free_var_ref(ctx->rt, p->u.array.u.var_refs[idx]); 8966 + } else { 8967 + JS_FreeValue(ctx, p->u.array.u.values[idx]); 8968 + } 8894 8969 p->u.array.count = idx; 8895 8970 return TRUE; 8896 8971 } ··· 9468 9543 if (unlikely(idx >= (uint32_t)p->u.array.count)) 9469 9544 goto slow_path; 9470 9545 set_value(ctx, &p->u.array.u.values[idx], val); 9546 + break; 9547 + case JS_CLASS_MAPPED_ARGUMENTS: 9548 + if (unlikely(idx >= (uint32_t)p->u.array.count)) 9549 + goto slow_path; 9550 + set_value(ctx, p->u.array.u.var_refs[idx]->pvalue, val); 9471 9551 break; 9472 9552 case JS_CLASS_UINT8C_ARRAY: 9473 9553 if (JS_ToUint8ClampFree(ctx, &v, val)) ··· 15666 15746 static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) 15667 15747 { 15668 15748 JSValue val, *tab; 15669 - JSProperty *pr; 15749 + JSProperty props[3]; 15670 15750 JSObject *p; 15671 15751 int i; 15672 15752 15673 - val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], 15674 - JS_CLASS_ARGUMENTS); 15753 + props[0].u.value = JS_NewInt32(ctx, argc); /* length */ 15754 + props[1].u.value = JS_DupValue(ctx, ctx->array_proto_values); /* Symbol.iterator */ 15755 + props[2].u.getset.getter = JS_VALUE_GET_OBJ(JS_DupValue(ctx, ctx->throw_type_error)); /* callee */ 15756 + props[2].u.getset.setter = JS_VALUE_GET_OBJ(JS_DupValue(ctx, ctx->throw_type_error)); /* callee */ 15757 + 15758 + val = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->arguments_shape), 15759 + JS_CLASS_ARGUMENTS, props); 15675 15760 if (JS_IsException(val)) 15676 15761 return val; 15677 15762 p = JS_VALUE_GET_OBJ(val); 15678 15763 15679 - /* add the length field (cannot fail) */ 15680 - pr = add_property(ctx, p, JS_ATOM_length, 15681 - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); 15682 - if (unlikely(!pr)) 15683 - goto fail; 15684 - pr->u.value = JS_NewInt32(ctx, argc); 15685 - 15686 15764 /* initialize the fast array part */ 15687 15765 tab = NULL; 15688 15766 if (argc > 0) { ··· 15695 15773 } 15696 15774 p->u.array.u.values = tab; 15697 15775 p->u.array.count = argc; 15698 - 15699 - JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, 15700 - JS_DupValue(ctx, ctx->array_proto_values), 15701 - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); 15702 - /* add callee property to throw a TypeError in strict mode */ 15703 - JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED, 15704 - ctx->throw_type_error, ctx->throw_type_error, 15705 - JS_PROP_HAS_GET | JS_PROP_HAS_SET); 15706 15776 return val; 15707 15777 fail: 15708 15778 JS_FreeValue(ctx, val); ··· 15712 15782 #define GLOBAL_VAR_OFFSET 0x40000000 15713 15783 #define ARGUMENT_VAR_OFFSET 0x20000000 15714 15784 15785 + static void js_mapped_arguments_finalizer(JSRuntime *rt, JSValue val) 15786 + { 15787 + JSObject *p = JS_VALUE_GET_OBJ(val); 15788 + JSVarRef **var_refs = p->u.array.u.var_refs; 15789 + int i; 15790 + for(i = 0; i < p->u.array.count; i++) 15791 + free_var_ref(rt, var_refs[i]); 15792 + js_free_rt(rt, var_refs); 15793 + } 15794 + 15795 + static void js_mapped_arguments_mark(JSRuntime *rt, JSValueConst val, 15796 + JS_MarkFunc *mark_func) 15797 + { 15798 + JSObject *p = JS_VALUE_GET_OBJ(val); 15799 + JSVarRef **var_refs = p->u.array.u.var_refs; 15800 + int i; 15801 + 15802 + for(i = 0; i < p->u.array.count; i++) 15803 + mark_func(rt, &var_refs[i]->header); 15804 + } 15805 + 15715 15806 /* legacy arguments object: add references to the function arguments */ 15716 15807 static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, 15717 15808 JSValueConst *argv, 15718 15809 JSStackFrame *sf, int arg_count) 15719 15810 { 15720 15811 JSValue val; 15721 - JSProperty *pr; 15812 + JSProperty props[3]; 15813 + JSVarRef **tab, *var_ref; 15722 15814 JSObject *p; 15723 - int i; 15815 + int i, j; 15724 15816 15725 - val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], 15726 - JS_CLASS_MAPPED_ARGUMENTS); 15817 + props[0].u.value = JS_NewInt32(ctx, argc); /* length */ 15818 + props[1].u.value = JS_DupValue(ctx, ctx->array_proto_values); /* Symbol.iterator */ 15819 + props[2].u.value = JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func); /* callee */ 15820 + 15821 + val = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->mapped_arguments_shape), 15822 + JS_CLASS_MAPPED_ARGUMENTS, props); 15727 15823 if (JS_IsException(val)) 15728 15824 return val; 15729 15825 p = JS_VALUE_GET_OBJ(val); 15730 15826 15731 - /* add the length field (cannot fail) */ 15732 - pr = add_property(ctx, p, JS_ATOM_length, 15733 - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); 15734 - if (unlikely(!pr)) 15735 - goto fail; 15736 - pr->u.value = JS_NewInt32(ctx, argc); 15737 - 15738 - for(i = 0; i < arg_count; i++) { 15739 - JSVarRef *var_ref; 15740 - var_ref = get_var_ref(ctx, sf, i, TRUE); 15741 - if (!var_ref) 15827 + /* initialize the fast array part */ 15828 + tab = NULL; 15829 + if (argc > 0) { 15830 + tab = js_malloc(ctx, sizeof(tab[0]) * argc); 15831 + if (!tab) 15742 15832 goto fail; 15743 - pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF); 15744 - if (!pr) { 15745 - free_var_ref(ctx->rt, var_ref); 15746 - goto fail; 15833 + for(i = 0; i < arg_count; i++) { 15834 + var_ref = get_var_ref(ctx, sf, i, TRUE); 15835 + if (!var_ref) 15836 + goto fail1; 15837 + tab[i] = var_ref; 15747 15838 } 15748 - pr->u.var_ref = var_ref; 15749 - } 15750 - 15751 - /* the arguments not mapped to the arguments of the function can 15752 - be normal properties */ 15753 - for(i = arg_count; i < argc; i++) { 15754 - if (JS_DefinePropertyValueUint32(ctx, val, i, 15755 - JS_DupValue(ctx, argv[i]), 15756 - JS_PROP_C_W_E) < 0) 15757 - goto fail; 15839 + for(i = arg_count; i < argc; i++) { 15840 + var_ref = js_create_var_ref(ctx, FALSE); 15841 + if (!var_ref) { 15842 + fail1: 15843 + for(j = 0; j < i; j++) 15844 + free_var_ref(ctx->rt, tab[j]); 15845 + js_free(ctx, tab); 15846 + goto fail; 15847 + } 15848 + var_ref->value = JS_DupValue(ctx, argv[i]); 15849 + tab[i] = var_ref; 15850 + } 15758 15851 } 15759 - 15760 - JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, 15761 - JS_DupValue(ctx, ctx->array_proto_values), 15762 - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); 15763 - /* callee returns this function in non strict mode */ 15764 - JS_DefinePropertyValue(ctx, val, JS_ATOM_callee, 15765 - JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func), 15766 - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); 15852 + p->u.array.u.var_refs = tab; 15853 + p->u.array.count = argc; 15767 15854 return val; 15768 15855 fail: 15769 15856 JS_FreeValue(ctx, val); ··· 17933 18020 17934 18021 CASE(OP_regexp): 17935 18022 { 17936 - JSValue obj; 17937 - obj = JS_NewObjectClass(ctx, JS_CLASS_REGEXP); 17938 - if (JS_IsException(obj)) 17939 - goto exception; 17940 - sp[-2] = js_regexp_set_internal(ctx, obj, sp[-2], sp[-1]); 18023 + sp[-2] = JS_NewRegexp(ctx, sp[-2], sp[-1]); 18024 + sp--; 17941 18025 if (JS_IsException(sp[-2])) 17942 18026 goto exception; 17943 - sp--; 17944 18027 } 17945 18028 BREAK; 17946 18029 ··· 40470 40553 if (!tab) 40471 40554 return NULL; 40472 40555 p = JS_VALUE_GET_OBJ(array_arg); 40473 - if ((p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS) && 40556 + if ((p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS || p->class_id == JS_CLASS_MAPPED_ARGUMENTS) && 40474 40557 p->fast_array && 40475 40558 len == p->u.array.count) { 40476 - for(i = 0; i < len; i++) { 40477 - tab[i] = JS_DupValue(ctx, p->u.array.u.values[i]); 40559 + if (p->class_id == JS_CLASS_MAPPED_ARGUMENTS) { 40560 + for(i = 0; i < len; i++) { 40561 + tab[i] = JS_DupValue(ctx, *p->u.array.u.var_refs[i]->pvalue); 40562 + } 40563 + } else { 40564 + for(i = 0; i < len; i++) { 40565 + tab[i] = JS_DupValue(ctx, p->u.array.u.values[i]); 40566 + } 40478 40567 } 40479 40568 } else { 40480 40569 for(i = 0; i < len; i++) { ··· 45082 45171 return result; 45083 45172 } 45084 45173 45085 - static JSValue js_string___GetSubstitution(JSContext *ctx, JSValueConst this_val, 45086 - int argc, JSValueConst *argv) 45174 + /* if captures != NULL, captures_val and matched are ignored. Otherwise, 45175 + captures_len is ignored */ 45176 + static int js_string_GetSubstitution(JSContext *ctx, 45177 + StringBuffer *b, 45178 + JSValueConst matched, 45179 + JSString *sp, 45180 + uint32_t position, 45181 + JSValueConst captures_val, 45182 + JSValueConst namedCaptures, 45183 + JSValueConst rep, 45184 + uint8_t **captures, 45185 + uint32_t captures_len) 45087 45186 { 45088 - // GetSubstitution(matched, str, position, captures, namedCaptures, rep) 45089 - JSValueConst matched, str, captures, namedCaptures, rep; 45090 45187 JSValue capture, name, s; 45091 - uint32_t position, len, matched_len, captures_len; 45092 - int i, j, j0, k, k1; 45188 + uint32_t len, matched_len; 45189 + int i, j, j0, k, k1, shift; 45093 45190 int c, c1; 45094 - StringBuffer b_s, *b = &b_s; 45095 - JSString *sp, *rp; 45096 - 45097 - matched = argv[0]; 45098 - str = argv[1]; 45099 - captures = argv[3]; 45100 - namedCaptures = argv[4]; 45101 - rep = argv[5]; 45191 + JSString *rp; 45102 45192 45103 - if (!JS_IsString(rep) || !JS_IsString(str)) 45104 - return JS_ThrowTypeError(ctx, "not a string"); 45105 - 45106 - sp = JS_VALUE_GET_STRING(str); 45193 + if (JS_VALUE_GET_TAG(rep) != JS_TAG_STRING) { 45194 + JS_ThrowTypeError(ctx, "not a string"); 45195 + goto exception; 45196 + } 45197 + shift = sp->is_wide_char; 45107 45198 rp = JS_VALUE_GET_STRING(rep); 45108 45199 45109 - string_buffer_init(ctx, b, 0); 45110 - 45111 - captures_len = 0; 45112 - if (!JS_IsUndefined(captures)) { 45113 - if (js_get_length32(ctx, &captures_len, captures)) 45200 + if (captures) { 45201 + matched_len = (captures[1] - captures[0]) >> shift; 45202 + } else { 45203 + captures_len = 0; 45204 + if (!JS_IsUndefined(captures_val)) { 45205 + if (js_get_length32(ctx, &captures_len, captures_val)) 45206 + goto exception; 45207 + } 45208 + if (js_get_length32(ctx, &matched_len, matched)) 45114 45209 goto exception; 45115 45210 } 45116 - if (js_get_length32(ctx, &matched_len, matched)) 45117 - goto exception; 45118 - if (JS_ToUint32(ctx, &position, argv[2]) < 0) 45119 - goto exception; 45120 45211 45121 45212 len = rp->len; 45122 45213 i = 0; ··· 45130 45221 if (c == '$') { 45131 45222 string_buffer_putc8(b, '$'); 45132 45223 } else if (c == '&') { 45133 - if (string_buffer_concat_value(b, matched)) 45134 - goto exception; 45224 + if (captures) { 45225 + string_buffer_concat(b, sp, position, position + matched_len); 45226 + } else { 45227 + if (string_buffer_concat_value(b, matched)) 45228 + goto exception; 45229 + } 45135 45230 } else if (c == '`') { 45136 45231 string_buffer_concat(b, sp, 0, position); 45137 45232 } else if (c == '\'') { ··· 45152 45247 } 45153 45248 } 45154 45249 if (k >= 1 && k < captures_len) { 45155 - s = JS_GetPropertyInt64(ctx, captures, k); 45156 - if (JS_IsException(s)) 45157 - goto exception; 45158 - if (!JS_IsUndefined(s)) { 45159 - if (string_buffer_concat_value_free(b, s)) 45250 + if (captures) { 45251 + int start, end; 45252 + if (captures[2 * k] && captures[2 * k + 1]) { 45253 + start = (captures[2 * k] - sp->u.str8) >> shift; 45254 + end = (captures[2 * k + 1] - sp->u.str8) >> shift; 45255 + string_buffer_concat(b, sp, start, end); 45256 + } 45257 + } else { 45258 + s = JS_GetPropertyInt64(ctx, captures_val, k); 45259 + if (JS_IsException(s)) 45160 45260 goto exception; 45261 + if (!JS_IsUndefined(s)) { 45262 + if (string_buffer_concat_value_free(b, s)) 45263 + goto exception; 45264 + } 45161 45265 } 45162 45266 } else { 45163 45267 goto norep; ··· 45184 45288 i = j; 45185 45289 } 45186 45290 string_buffer_concat(b, rp, i, rp->len); 45187 - return string_buffer_end(b); 45291 + return 0; 45188 45292 exception: 45189 - string_buffer_free(b); 45190 - return JS_EXCEPTION; 45293 + return -1; 45191 45294 } 45192 45295 45193 45296 static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, ··· 45196 45299 { 45197 45300 // replace(rx, rep) 45198 45301 JSValueConst O = this_val, searchValue = argv[0], replaceValue = argv[1]; 45199 - JSValueConst args[6]; 45302 + JSValueConst args[3]; 45200 45303 JSValue str, search_str, replaceValue_str, repl_str; 45201 45304 JSString *sp, *searchp; 45202 45305 StringBuffer b_s, *b = &b_s; ··· 45265 45368 break; 45266 45369 } 45267 45370 } 45371 + 45372 + string_buffer_concat(b, sp, endOfLastMatch, pos); 45373 + 45268 45374 if (functionalReplace) { 45269 45375 args[0] = search_str; 45270 45376 args[1] = JS_NewInt32(ctx, pos); 45271 45377 args[2] = str; 45272 45378 repl_str = JS_ToStringFree(ctx, JS_Call(ctx, replaceValue, JS_UNDEFINED, 3, args)); 45379 + if (JS_IsException(repl_str)) 45380 + goto exception; 45381 + string_buffer_concat_value_free(b, repl_str); 45273 45382 } else { 45274 - args[0] = search_str; 45275 - args[1] = str; 45276 - args[2] = JS_NewInt32(ctx, pos); 45277 - args[3] = JS_UNDEFINED; 45278 - args[4] = JS_UNDEFINED; 45279 - args[5] = replaceValue_str; 45280 - repl_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args); 45383 + if (js_string_GetSubstitution(ctx, b, search_str, sp, pos, 45384 + JS_UNDEFINED, JS_UNDEFINED, replaceValue_str, 45385 + NULL, 0)) { 45386 + goto exception; 45387 + } 45281 45388 } 45282 - if (JS_IsException(repl_str)) 45283 - goto exception; 45284 45389 45285 - string_buffer_concat(b, sp, endOfLastMatch, pos); 45286 - string_buffer_concat_value_free(b, repl_str); 45287 45390 endOfLastMatch = pos + searchp->len; 45288 45391 is_first = FALSE; 45289 45392 if (!is_replaceAll) ··· 45918 46021 return js_thisStringValue(ctx, this_val); 45919 46022 } 45920 46023 45921 - #if 0 45922 - static JSValue js_string___toStringCheckObject(JSContext *ctx, JSValueConst this_val, 45923 - int argc, JSValueConst *argv) 45924 - { 45925 - return JS_ToStringCheckObject(ctx, argv[0]); 45926 - } 45927 - 45928 - static JSValue js_string___toString(JSContext *ctx, JSValueConst this_val, 45929 - int argc, JSValueConst *argv) 45930 - { 45931 - return JS_ToString(ctx, argv[0]); 45932 - } 45933 - 45934 - static JSValue js_string___advanceStringIndex(JSContext *ctx, JSValueConst 45935 - this_val, 45936 - int argc, JSValueConst *argv) 45937 - { 45938 - JSValue str; 45939 - int idx; 45940 - BOOL is_unicode; 45941 - JSString *p; 45942 - 45943 - str = JS_ToString(ctx, argv[0]); 45944 - if (JS_IsException(str)) 45945 - return str; 45946 - if (JS_ToInt32Sat(ctx, &idx, argv[1])) { 45947 - JS_FreeValue(ctx, str); 45948 - return JS_EXCEPTION; 45949 - } 45950 - is_unicode = JS_ToBool(ctx, argv[2]); 45951 - p = JS_VALUE_GET_STRING(str); 45952 - if (!is_unicode || (unsigned)idx >= p->len || !p->is_wide_char) { 45953 - idx++; 45954 - } else { 45955 - string_getc(p, &idx); 45956 - } 45957 - JS_FreeValue(ctx, str); 45958 - return JS_NewInt32(ctx, idx); 45959 - } 45960 - #endif 45961 - 45962 46024 /* String Iterator */ 45963 46025 45964 46026 static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val, ··· 46072 46134 JS_CFUNC_DEF("fromCharCode", 1, js_string_fromCharCode ), 46073 46135 JS_CFUNC_DEF("fromCodePoint", 1, js_string_fromCodePoint ), 46074 46136 JS_CFUNC_DEF("raw", 1, js_string_raw ), 46075 - //JS_CFUNC_DEF("__toString", 1, js_string___toString ), 46076 - //JS_CFUNC_DEF("__isSpace", 1, js_string___isSpace ), 46077 - //JS_CFUNC_DEF("__toStringCheckObject", 1, js_string___toStringCheckObject ), 46078 - //JS_CFUNC_DEF("__advanceStringIndex", 3, js_string___advanceStringIndex ), 46079 - //JS_CFUNC_DEF("__GetSubstitution", 6, js_string___GetSubstitution ), 46080 46137 }; 46081 46138 46082 46139 static const JSCFunctionListEntry js_string_proto_funcs[] = { ··· 46872 46929 return ret; 46873 46930 } 46874 46931 46932 + /* fast regexp creation */ 46933 + static JSValue JS_NewRegexp(JSContext *ctx, JSValue pattern, JSValue bc) 46934 + { 46935 + JSValue obj; 46936 + JSProperty props[1]; 46937 + JSObject *p; 46938 + JSRegExp *re; 46939 + 46940 + /* sanity check */ 46941 + if (unlikely(JS_VALUE_GET_TAG(bc) != JS_TAG_STRING || 46942 + JS_VALUE_GET_TAG(pattern) != JS_TAG_STRING)) { 46943 + JS_ThrowTypeError(ctx, "string expected"); 46944 + goto fail; 46945 + } 46946 + props[0].u.value = JS_NewInt32(ctx, 0); /* lastIndex */ 46947 + obj = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->regexp_shape), JS_CLASS_REGEXP, props); 46948 + if (JS_IsException(obj)) 46949 + goto fail; 46950 + p = JS_VALUE_GET_OBJ(obj); 46951 + re = &p->u.regexp; 46952 + re->pattern = JS_VALUE_GET_STRING(pattern); 46953 + re->bytecode = JS_VALUE_GET_STRING(bc); 46954 + return obj; 46955 + fail: 46956 + JS_FreeValue(ctx, bc); 46957 + JS_FreeValue(ctx, pattern); 46958 + return JS_EXCEPTION; 46959 + } 46960 + 46875 46961 /* set the RegExp fields */ 46876 46962 static JSValue js_regexp_set_internal(JSContext *ctx, 46877 46963 JSValue obj, ··· 47055 47141 return JS_EXCEPTION; 47056 47142 } 47057 47143 47058 - #if 0 47059 - static JSValue js_regexp_get___source(JSContext *ctx, JSValueConst this_val) 47060 - { 47061 - JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); 47062 - if (!re) 47063 - return JS_EXCEPTION; 47064 - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern)); 47065 - } 47066 - 47067 - static JSValue js_regexp_get___flags(JSContext *ctx, JSValueConst this_val) 47068 - { 47069 - JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); 47070 - int flags; 47071 - 47072 - if (!re) 47073 - return JS_EXCEPTION; 47074 - flags = lre_get_flags(re->bytecode->u.str8); 47075 - return JS_NewInt32(ctx, flags); 47076 - } 47077 - #endif 47078 - 47079 47144 static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val) 47080 47145 { 47081 47146 JSRegExp *re; ··· 47294 47359 return string_buffer_end(b); 47295 47360 } 47296 47361 47362 + /* this_val must be of JS_CLASS_REGEXP */ 47363 + static force_inline int js_regexp_get_lastIndex(JSContext *ctx, int64_t *plast_index, 47364 + JSValueConst this_val) 47365 + { 47366 + JSObject *p = JS_VALUE_GET_OBJ(this_val); 47367 + 47368 + /* lastIndex is always the first property (it is not configurable) */ 47369 + if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) { 47370 + *plast_index = max_int(JS_VALUE_GET_INT(p->prop[0].u.value), 0); 47371 + return 0; 47372 + } else { 47373 + return JS_ToLengthFree(ctx, plast_index, JS_DupValue(ctx, p->prop[0].u.value)); 47374 + } 47375 + } 47376 + 47377 + /* this_val must be of JS_CLASS_REGEXP */ 47378 + static force_inline int js_regexp_set_lastIndex(JSContext *ctx, JSValueConst this_val, 47379 + int last_index) 47380 + { 47381 + JSObject *p = JS_VALUE_GET_OBJ(this_val); 47382 + 47383 + /* lastIndex is always the first property (it is not configurable) */ 47384 + if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT && 47385 + (get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) { 47386 + set_value(ctx, &p->prop[0].u.value, JS_NewInt32(ctx, last_index)); 47387 + } else { 47388 + if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, 47389 + JS_NewInt32(ctx, last_index)) < 0) 47390 + return -1; 47391 + } 47392 + return 0; 47393 + } 47394 + 47297 47395 static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, 47298 47396 int argc, JSValueConst *argv) 47299 47397 { 47300 47398 JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); 47301 47399 JSString *str; 47302 - JSValue t, ret, str_val, obj, val, groups; 47400 + JSValue t, ret, str_val, obj, groups; 47303 47401 JSValue indices, indices_groups; 47304 47402 uint8_t *re_bytecode; 47305 47403 uint8_t **capture, *str_buf; 47306 47404 int rc, capture_count, shift, i, re_flags; 47307 47405 int64_t last_index; 47308 47406 const char *group_name_ptr; 47407 + JSObject *p_obj; 47309 47408 47310 47409 if (!re) 47311 47410 return JS_EXCEPTION; ··· 47321 47420 indices_groups = JS_UNDEFINED; 47322 47421 capture = NULL; 47323 47422 47324 - val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex); 47325 - if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val)) 47423 + if (js_regexp_get_lastIndex(ctx, &last_index, this_val)) 47326 47424 goto fail; 47327 47425 47328 47426 re_bytecode = re->bytecode->u.str8; ··· 47349 47447 if (rc != 1) { 47350 47448 if (rc >= 0) { 47351 47449 if (rc == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) { 47352 - if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, 47353 - JS_NewInt32(ctx, 0)) < 0) 47450 + if (js_regexp_set_lastIndex(ctx, this_val, 0) < 0) 47354 47451 goto fail; 47355 47452 } 47356 47453 } else { ··· 47363 47460 } 47364 47461 } else { 47365 47462 int prop_flags; 47463 + JSProperty props[4]; 47464 + 47366 47465 if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) { 47367 - if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, 47368 - JS_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0) 47466 + if (js_regexp_set_lastIndex(ctx, this_val, 47467 + (capture[1] - str_buf) >> shift) < 0) 47369 47468 goto fail; 47370 47469 } 47371 - obj = JS_NewArray(ctx); 47372 - if (JS_IsException(obj)) 47373 - goto fail; 47374 47470 prop_flags = JS_PROP_C_W_E | JS_PROP_THROW; 47375 47471 group_name_ptr = lre_get_groupnames(re_bytecode); 47376 47472 if (group_name_ptr) { ··· 47389 47485 } 47390 47486 } 47391 47487 47488 + props[0].u.value = JS_NewInt32(ctx, capture_count); /* length */ 47489 + props[1].u.value = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift); /* index */ 47490 + props[2].u.value = str_val; /* input */ 47491 + props[3].u.value = JS_DupValue(ctx, groups); /* groups */ 47492 + 47493 + str_val = JS_UNDEFINED; 47494 + obj = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->regexp_result_shape), 47495 + JS_CLASS_ARRAY, props); 47496 + if (JS_IsException(obj)) 47497 + goto fail; 47498 + 47499 + p_obj = JS_VALUE_GET_OBJ(obj); 47500 + if (expand_fast_array(ctx, p_obj, capture_count)) 47501 + goto fail; 47502 + 47392 47503 for(i = 0; i < capture_count; i++) { 47393 47504 const char *name = NULL; 47394 47505 uint8_t **match = &capture[2 * i]; ··· 47454 47565 goto fail; 47455 47566 } 47456 47567 } 47457 - 47458 - if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0) 47459 - goto fail; 47460 - } 47461 - 47462 - t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift); 47463 - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0) 47464 - goto fail; 47465 - 47466 - t = str_val, str_val = JS_UNDEFINED; 47467 - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, t, prop_flags) < 0) 47468 - goto fail; 47469 - 47470 - t = groups, groups = JS_UNDEFINED; 47471 - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups, 47472 - t, prop_flags) < 0) { 47473 - goto fail; 47568 + p_obj->u.array.u.values[p_obj->u.array.count++] = val; 47474 47569 } 47475 47570 47476 47571 if (!JS_IsUndefined(indices)) { ··· 47498 47593 return ret; 47499 47594 } 47500 47595 47501 - /* delete portions of a string that match a given regex */ 47502 - static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg) 47596 + /* XXX: add group names support */ 47597 + static JSValue js_regexp_replace(JSContext *ctx, JSValueConst this_val, JSValueConst arg, 47598 + JSValueConst rep_val) 47503 47599 { 47504 47600 JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); 47505 47601 JSString *str; 47506 - JSValue str_val, val; 47602 + JSValue str_val; 47507 47603 uint8_t *re_bytecode; 47508 47604 int ret; 47509 47605 uint8_t **capture, *str_buf; ··· 47511 47607 int next_src_pos, start, end; 47512 47608 int64_t last_index; 47513 47609 StringBuffer b_s, *b = &b_s; 47514 - 47610 + JSString *rp = JS_VALUE_GET_STRING(rep_val); 47611 + const char *group_name_ptr; 47612 + BOOL fullUnicode; 47613 + 47515 47614 if (!re) 47516 47615 return JS_EXCEPTION; 47517 - 47616 + re_bytecode = re->bytecode->u.str8; 47617 + group_name_ptr = lre_get_groupnames(re_bytecode); 47618 + if (group_name_ptr) 47619 + return JS_UNDEFINED; /* group names are not supported yet */ 47620 + 47518 47621 string_buffer_init(ctx, b, 0); 47519 47622 47520 47623 capture = NULL; ··· 47522 47625 if (JS_IsException(str_val)) 47523 47626 goto fail; 47524 47627 str = JS_VALUE_GET_STRING(str_val); 47525 - re_bytecode = re->bytecode->u.str8; 47526 47628 re_flags = lre_get_flags(re_bytecode); 47629 + 47630 + if (re_flags & LRE_FLAG_GLOBAL) { 47631 + if (js_regexp_set_lastIndex(ctx, this_val, 0)) 47632 + goto fail; 47633 + } 47527 47634 if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) { 47528 47635 last_index = 0; 47529 47636 } else { 47530 - val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex); 47531 - if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val)) 47637 + if (js_regexp_get_lastIndex(ctx, &last_index, this_val)) 47532 47638 goto fail; 47533 47639 } 47534 47640 capture_count = lre_get_capture_count(re_bytecode); ··· 47537 47643 if (!capture) 47538 47644 goto fail; 47539 47645 } 47646 + fullUnicode = ((re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0); 47540 47647 shift = str->is_wide_char; 47541 47648 str_buf = str->u.str8; 47542 47649 next_src_pos = 0; 47543 47650 for (;;) { 47544 - if (last_index > str->len) 47545 - break; 47546 - 47547 - ret = lre_exec(capture, re_bytecode, 47548 - str_buf, last_index, str->len, shift, ctx); 47651 + if (last_index > str->len) { 47652 + ret = 0; 47653 + } else { 47654 + ret = lre_exec(capture, re_bytecode, 47655 + str_buf, last_index, str->len, shift, ctx); 47656 + } 47549 47657 if (ret != 1) { 47550 47658 if (ret >= 0) { 47551 47659 if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) { 47552 - if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, 47553 - JS_NewInt32(ctx, 0)) < 0) 47660 + if (js_regexp_set_lastIndex(ctx, this_val, 0) < 0) 47554 47661 goto fail; 47555 47662 } 47556 47663 } else { ··· 47570 47677 if (string_buffer_concat(b, str, next_src_pos, start)) 47571 47678 goto fail; 47572 47679 } 47680 + if (rp->len != 0) { 47681 + if (js_string_GetSubstitution(ctx, b, JS_UNDEFINED, str, start, 47682 + JS_UNDEFINED, JS_UNDEFINED, rep_val, 47683 + capture, capture_count)) { 47684 + goto fail; 47685 + } 47686 + } 47573 47687 next_src_pos = end; 47574 47688 if (!(re_flags & LRE_FLAG_GLOBAL)) { 47575 - if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, 47576 - JS_NewInt32(ctx, end)) < 0) 47577 - goto fail; 47689 + if (re_flags & LRE_FLAG_STICKY) { 47690 + if (js_regexp_set_lastIndex(ctx, this_val, end) < 0) 47691 + goto fail; 47692 + } 47578 47693 break; 47579 47694 } 47580 47695 if (end == start) { 47581 - if (!(re_flags & LRE_FLAG_UNICODE) || (unsigned)end >= str->len || !str->is_wide_char) { 47582 - end++; 47583 - } else { 47584 - string_getc(str, &end); 47585 - } 47696 + end = string_advance_index(str, end, fullUnicode); 47586 47697 } 47587 47698 last_index = end; 47588 47699 } ··· 47618 47729 JS_FreeValue(ctx, method); 47619 47730 return js_regexp_exec(ctx, r, 1, &s); 47620 47731 } 47621 - 47622 - #if 0 47623 - static JSValue js_regexp___RegExpExec(JSContext *ctx, JSValueConst this_val, 47624 - int argc, JSValueConst *argv) 47625 - { 47626 - return JS_RegExpExec(ctx, argv[0], argv[1]); 47627 - } 47628 - static JSValue js_regexp___RegExpDelete(JSContext *ctx, JSValueConst this_val, 47629 - int argc, JSValueConst *argv) 47630 - { 47631 - return JS_RegExpDelete(ctx, argv[0], argv[1]); 47632 - } 47633 - #endif 47634 47732 47635 47733 static JSValue js_regexp_test(JSContext *ctx, JSValueConst this_val, 47636 47734 int argc, JSValueConst *argv) ··· 47940 48038 return 0; 47941 48039 } 47942 48040 47943 - static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx) 48041 + /* find in 'p' or its prototypes */ 48042 + static JSShapeProperty *find_property_regexp(JSProperty **ppr, 48043 + JSObject *p, JSAtom atom) 47944 48044 { 47945 - JSValue val; 47946 - int res; 48045 + JSShapeProperty *prs; 47947 48046 47948 - val = JS_GetProperty(ctx, rx, JS_ATOM_constructor); 47949 - if (JS_IsException(val)) 47950 - return -1; 47951 - // rx.constructor === RegExp 47952 - res = js_same_value(ctx, val, ctx->regexp_ctor); 47953 - JS_FreeValue(ctx, val); 47954 - if (res) { 47955 - val = JS_GetProperty(ctx, rx, JS_ATOM_exec); 47956 - if (JS_IsException(val)) 47957 - return -1; 47958 - // rx.exec === RE_exec 47959 - res = JS_IsCFunction(ctx, val, js_regexp_exec, 0); 47960 - JS_FreeValue(ctx, val); 48047 + for(;;) { 48048 + prs = find_own_property(ppr, p, atom); 48049 + if (prs) 48050 + return prs; 48051 + p = p->shape->proto; 48052 + if (!p) 48053 + return NULL; 48054 + if (p->is_exotic) 48055 + return NULL; 47961 48056 } 47962 - return res; 48057 + } 48058 + 48059 + static BOOL check_regexp_getter(JSContext *ctx, 48060 + JSObject *p, JSAtom atom, 48061 + JSCFunction *func, int magic) 48062 + { 48063 + JSProperty *pr; 48064 + JSShapeProperty *prs; 48065 + 48066 + prs = find_property_regexp(&pr, p, atom); 48067 + if (!prs) 48068 + return FALSE; 48069 + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_GETSET) 48070 + return FALSE; 48071 + return JS_IsCFunction(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter), 48072 + func, magic); 48073 + } 48074 + 48075 + static BOOL js_is_standard_regexp(JSContext *ctx, JSValueConst obj) 48076 + { 48077 + JSObject *p; 48078 + JSProperty *pr; 48079 + JSShapeProperty *prs; 48080 + JSCFunctionType ft; 48081 + 48082 + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) 48083 + return FALSE; 48084 + p = JS_VALUE_GET_OBJ(obj); 48085 + if (p->class_id != JS_CLASS_REGEXP) 48086 + return FALSE; 48087 + /* check that the lastIndex is a number (no side effect while getting it) */ 48088 + prs = find_own_property(&pr, p, JS_ATOM_lastIndex); 48089 + if (!prs) 48090 + return FALSE; 48091 + if (!JS_IsNumber(pr->u.value)) 48092 + return FALSE; 48093 + 48094 + /* check the 'exec' method. */ 48095 + prs = find_property_regexp(&pr, p, JS_ATOM_exec); 48096 + if (!prs) 48097 + return FALSE; 48098 + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) 48099 + return FALSE; 48100 + if (!JS_IsCFunction(ctx, pr->u.value, js_regexp_exec, 0)) 48101 + return FALSE; 48102 + /* check the flag getters */ 48103 + ft.getter = js_regexp_get_flags; 48104 + if (!check_regexp_getter(ctx, p, JS_ATOM_flags, ft.generic, 0)) 48105 + return FALSE; 48106 + ft.getter_magic = js_regexp_get_flag; 48107 + if (!check_regexp_getter(ctx, p, JS_ATOM_global, ft.generic, LRE_FLAG_GLOBAL)) 48108 + return FALSE; 48109 + if (!check_regexp_getter(ctx, p, JS_ATOM_unicode, ft.generic, LRE_FLAG_UNICODE)) 48110 + return FALSE; 48111 + /* XXX: need to check all accessors, need a faster way. */ 48112 + return TRUE; 47963 48113 } 47964 48114 47965 48115 static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, ··· 47969 48119 JSValueConst rx = this_val, rep = argv[1]; 47970 48120 JSValueConst args[6]; 47971 48121 JSValue flags, str, rep_val, matched, tab, rep_str, namedCaptures, res; 47972 - JSString *p, *sp, *rp; 48122 + JSString *p, *sp; 47973 48123 StringBuffer b_s, *b = &b_s; 47974 48124 ValueBuffer v_b, *results = &v_b; 47975 48125 int nextSourcePosition, n, j, functionalReplace, is_global, fullUnicode; ··· 47994 48144 goto exception; 47995 48145 47996 48146 sp = JS_VALUE_GET_STRING(str); 47997 - rp = NULL; 47998 48147 functionalReplace = JS_IsFunction(ctx, rep); 47999 48148 if (!functionalReplace) { 48000 48149 rep_val = JS_ToString(ctx, rep); 48001 48150 if (JS_IsException(rep_val)) 48002 48151 goto exception; 48003 - rp = JS_VALUE_GET_STRING(rep_val); 48004 48152 } 48005 48153 48154 + if (!functionalReplace && js_is_standard_regexp(ctx, rx)) { 48155 + /* use faster version for simple cases */ 48156 + res = js_regexp_replace(ctx, rx, str, rep_val); 48157 + if (!JS_IsUndefined(res)) 48158 + goto done; 48159 + } 48160 + 48006 48161 flags = JS_GetProperty(ctx, rx, JS_ATOM_flags); 48007 48162 if (JS_IsException(flags)) 48008 48163 goto exception; ··· 48020 48175 goto exception; 48021 48176 } 48022 48177 48023 - if (rp && rp->len == 0 && is_global && js_is_standard_regexp(ctx, rx)) { 48024 - /* use faster version for simple cases */ 48025 - res = JS_RegExpDelete(ctx, rx, str); 48026 - goto done; 48027 - } 48028 48178 for(;;) { 48029 48179 JSValue result; 48030 48180 result = JS_RegExpExec(ctx, rx, str); ··· 48108 48258 rep_str = JS_ToStringFree(ctx, js_function_apply(ctx, rep, 2, args, 0)); 48109 48259 } else { 48110 48260 JSValue namedCaptures1; 48261 + StringBuffer b1_s, *b1 = &b1_s; 48262 + int ret; 48263 + 48111 48264 if (!JS_IsUndefined(namedCaptures)) { 48112 48265 namedCaptures1 = JS_ToObject(ctx, namedCaptures); 48113 48266 if (JS_IsException(namedCaptures1)) ··· 48115 48268 } else { 48116 48269 namedCaptures1 = JS_UNDEFINED; 48117 48270 } 48118 - args[0] = matched; 48119 - args[1] = str; 48120 - args[2] = JS_NewInt32(ctx, position); 48121 - args[3] = tab; 48122 - args[4] = namedCaptures1; 48123 - args[5] = rep_val; 48124 48271 JS_FreeValue(ctx, rep_str); 48125 - rep_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args); 48272 + 48273 + string_buffer_init(ctx, b1, 0); 48274 + ret = js_string_GetSubstitution(ctx, b1, matched, sp, position, 48275 + tab, namedCaptures1, rep_val, 48276 + NULL, 0); 48277 + rep_str = string_buffer_end(b1); 48126 48278 JS_FreeValue(ctx, namedCaptures1); 48279 + if (ret) 48280 + goto exception; 48127 48281 } 48128 48282 if (JS_IsException(rep_str)) 48129 48283 goto exception; ··· 48341 48495 static const JSCFunctionListEntry js_regexp_funcs[] = { 48342 48496 JS_CFUNC_DEF("escape", 1, js_regexp_escape ), 48343 48497 JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), 48344 - //JS_CFUNC_DEF("__RegExpExec", 2, js_regexp___RegExpExec ), 48345 - //JS_CFUNC_DEF("__RegExpDelete", 2, js_regexp___RegExpDelete ), 48346 48498 }; 48347 48499 48348 48500 static const JSCFunctionListEntry js_regexp_proto_funcs[] = { ··· 48365 48517 JS_CFUNC_DEF("[Symbol.matchAll]", 1, js_regexp_Symbol_matchAll ), 48366 48518 JS_CFUNC_DEF("[Symbol.search]", 1, js_regexp_Symbol_search ), 48367 48519 JS_CFUNC_DEF("[Symbol.split]", 2, js_regexp_Symbol_split ), 48368 - //JS_CGETSET_DEF("__source", js_regexp_get___source, NULL ), 48369 - //JS_CGETSET_DEF("__flags", js_regexp_get___flags, NULL ), 48370 48520 }; 48371 48521 48372 48522 static const JSCFunctionListEntry js_regexp_string_iterator_proto_funcs[] = { ··· 48401 48551 countof(js_regexp_string_iterator_proto_funcs)); 48402 48552 if (JS_IsException(ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR])) 48403 48553 return -1; 48554 + 48555 + ctx->regexp_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_REGEXP]), 48556 + JS_PROP_INITIAL_HASH_SIZE, 1); 48557 + if (!ctx->regexp_shape) 48558 + return -1; 48559 + if (add_shape_property(ctx, &ctx->regexp_shape, NULL, 48560 + JS_ATOM_lastIndex, JS_PROP_WRITABLE)) 48561 + return -1; 48562 + 48563 + ctx->regexp_result_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_ARRAY]), 48564 + JS_PROP_INITIAL_HASH_SIZE, 4); 48565 + if (!ctx->regexp_result_shape) 48566 + return -1; 48567 + if (add_shape_property(ctx, &ctx->regexp_result_shape, NULL, 48568 + JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH)) 48569 + return -1; 48570 + if (add_shape_property(ctx, &ctx->regexp_result_shape, NULL, 48571 + JS_ATOM_index, JS_PROP_C_W_E)) 48572 + return -1; 48573 + if (add_shape_property(ctx, &ctx->regexp_result_shape, NULL, 48574 + JS_ATOM_input, JS_PROP_C_W_E)) 48575 + return -1; 48576 + if (add_shape_property(ctx, &ctx->regexp_result_shape, NULL, 48577 + JS_ATOM_groups, JS_PROP_C_W_E)) 48578 + return -1; 48579 + 48404 48580 return 0; 48405 48581 } 48406 48582 ··· 55223 55399 JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH)) 55224 55400 return -1; 55225 55401 ctx->std_array_prototype = TRUE; 55402 + 55403 + ctx->arguments_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_OBJECT]), 55404 + JS_PROP_INITIAL_HASH_SIZE, 3); 55405 + if (!ctx->arguments_shape) 55406 + return -1; 55407 + if (add_shape_property(ctx, &ctx->arguments_shape, NULL, 55408 + JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) 55409 + return -1; 55410 + if (add_shape_property(ctx, &ctx->arguments_shape, NULL, 55411 + JS_ATOM_Symbol_iterator, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) 55412 + return -1; 55413 + if (add_shape_property(ctx, &ctx->arguments_shape, NULL, 55414 + JS_ATOM_callee, JS_PROP_GETSET)) 55415 + return -1; 55416 + 55417 + ctx->mapped_arguments_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_OBJECT]), 55418 + JS_PROP_INITIAL_HASH_SIZE, 3); 55419 + if (!ctx->mapped_arguments_shape) 55420 + return -1; 55421 + if (add_shape_property(ctx, &ctx->mapped_arguments_shape, NULL, 55422 + JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) 55423 + return -1; 55424 + if (add_shape_property(ctx, &ctx->mapped_arguments_shape, NULL, 55425 + JS_ATOM_Symbol_iterator, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) 55426 + return -1; 55427 + if (add_shape_property(ctx, &ctx->mapped_arguments_shape, NULL, 55428 + JS_ATOM_callee, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) 55429 + return -1; 55226 55430 55227 55431 return 0; 55228 55432 }
+52
vendor/git/quickjs-c/tests/microbench.js
··· 547 547 return len * n; 548 548 } 549 549 550 + function arguments_test() 551 + { 552 + return arguments[0] + arguments[1] + arguments[2]; 553 + } 554 + 555 + function arguments_read(n) 556 + { 557 + sum = 0; 558 + for(j = 0; j < n; j++) { 559 + sum += arguments_test(j, j, j); 560 + sum += arguments_test(j, j, j); 561 + sum += arguments_test(j, j, j); 562 + sum += arguments_test(j, j, j); 563 + } 564 + global_res = sum; 565 + return n * 4; 566 + } 567 + 568 + function arguments_strict_test() 569 + { 570 + "use strict"; 571 + return arguments[0] + arguments[1] + arguments[2]; 572 + } 573 + 574 + function arguments_strict_read(n) 575 + { 576 + sum = 0; 577 + for(j = 0; j < n; j++) { 578 + sum += arguments_strict_test(j, j, j); 579 + sum += arguments_strict_test(j, j, j); 580 + sum += arguments_strict_test(j, j, j); 581 + sum += arguments_strict_test(j, j, j); 582 + } 583 + global_res = sum; 584 + return n * 4; 585 + } 586 + 550 587 var global_var0; 551 588 552 589 function global_read(n) ··· 939 976 for(j = 0; j < n; j++) { 940 977 for(i = 0; i < 1000; i++) 941 978 r = /the quick brown ᶠᵒˣ/.exec(s) 979 + global_res = r; 980 + } 981 + return n * 1000; 982 + } 983 + 984 + function regexp_replace(n) 985 + { 986 + var i, j, r, s; 987 + s = "the quick abc brown fox jumped abc over the lazy dog" 988 + for(j = 0; j < n; j++) { 989 + for(i = 0; i < 1000; i++) 990 + r = s.replace(/abc /g, "-"); 942 991 global_res = r; 943 992 } 944 993 return n * 1000; ··· 1408 1457 array_pop, 1409 1458 typed_array_read, 1410 1459 typed_array_write, 1460 + arguments_read, 1461 + arguments_strict_read, 1411 1462 global_read, 1412 1463 global_write, 1413 1464 global_write_strict, ··· 1431 1482 math_min, 1432 1483 regexp_ascii, 1433 1484 regexp_utf16, 1485 + regexp_replace, 1434 1486 string_length, 1435 1487 string_build1, 1436 1488 string_build1x,