diff --git a/src/arobject.h b/src/arobject.h index 6b7d89a..497bc3e 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -98,12 +98,19 @@ struct argon_function_struct { uint64_t column; }; +struct built_in_slot { + built_in_fields field; + ArgonObject*value; +}; + // full definition of ArgonObject (no typedef again!) struct ArgonObject { ArgonType type; ArgonType child_type; struct hashmap_GC *dict; - ArgonObject* Builtin_slots[BUILT_IN_FIELDS_COUNT]; + struct built_in_slot* built_in_slot; + size_t built_in_slot_size; + size_t built_in_slot_length; bool as_bool; union { struct as_number { diff --git a/src/runtime/objects/number/number.c b/src/runtime/objects/number/number.c index 2d6c687..d773bd4 100644 --- a/src/runtime/objects/number/number.c +++ b/src/runtime/objects/number/number.c @@ -498,7 +498,6 @@ void init_small_ints() { small_ints[i].type = TYPE_NUMBER; small_ints[i].dict = createHashmap_GC(); add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE); - add_builtin_field(&small_ints[i], __base__, BASE_CLASS); small_ints[i].value.as_number.is_int64 = true; small_ints[i].value.as_number.n.i64 = n; small_ints[i].as_bool = n; diff --git a/src/runtime/objects/object.c b/src/runtime/objects/object.c index 0e2df97..e1e9410 100644 --- a/src/runtime/objects/object.c +++ b/src/runtime/objects/object.c @@ -12,6 +12,20 @@ #include #include +int strcmp_len(const char *s1, size_t len, const char *s2) { + size_t s2len = strlen(s2); // length of null-terminated string + size_t n = (len < s2len) ? len : s2len; + + int cmp = memcmp(s1, s2, n); + if (cmp != 0) + return cmp; + + // If prefixes match, decide based on length + if (len == s2len) + return 0; + return (len < s2len) ? -1 : 1; +} + ArgonObject *BASE_CLASS = NULL; const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = { @@ -21,10 +35,11 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = { "__binding__", "__function__", "address", "__call__", "__number__", "log", "length", "__getattribute__"}; - ArgonObject *new_object() { ArgonObject *object = ar_alloc(sizeof(ArgonObject)); - memset(object->Builtin_slots, 0, sizeof(object->Builtin_slots)); + object->built_in_slot = NULL; + object->built_in_slot_size = 0; + object->built_in_slot_length = 0; object->type = TYPE_OBJECT; object->dict = NULL; object->as_bool = true; @@ -46,16 +61,31 @@ ArgonObject *new_instance(ArgonObject *of) { inline void add_builtin_field(ArgonObject *target, built_in_fields field, ArgonObject *object) { - target->Builtin_slots[field] = object; + for (size_t i = 0; i < target->built_in_slot_length; i++) { + if (target->built_in_slot[i].field == field) { + target->built_in_slot[i].value = object; + return; + } + } + size_t position = target->built_in_slot_length++; + if (target->built_in_slot_length > target->built_in_slot_size) { + target->built_in_slot_size *= 2; + if (target->built_in_slot_size == 0) target->built_in_slot_size = 2; + else if (target->built_in_slot_size>BUILT_IN_FIELDS_COUNT) target->built_in_slot_size = BUILT_IN_FIELDS_COUNT; + target->built_in_slot = + ar_realloc(target->built_in_slot, target->built_in_slot_size * + sizeof(struct built_in_slot)); + } + target->built_in_slot[position] = (struct built_in_slot){field, object}; // hashmap_insert_GC(target->dict, built_in_field_hashes[field], // (char *)built_in_field_names[field], object, 0); } -void add_field(ArgonObject *target, char *name, uint64_t hash, - ArgonObject *object) { +void add_field_l(ArgonObject *target, char *name, uint64_t hash, size_t length, + ArgonObject *object) { for (size_t i = 0; i < BUILT_IN_FIELDS_COUNT; i++) { - if (strcmp(name, built_in_field_names[i])) { - target->Builtin_slots[i] = object; + if (strcmp_len(name, length, built_in_field_names[i]) == 0) { + add_builtin_field(target, i, object); return; } } @@ -71,8 +101,7 @@ ArgonObject *bind_object_to_function(ArgonObject *object, add_builtin_field(bound_method_wrapper, __class__, ARGON_METHOD_TYPE); add_builtin_field(bound_method_wrapper, __binding__, object); add_builtin_field(bound_method_wrapper, __function__, function); - ArgonObject *function_name = - get_builtin_field(function, __name__); + ArgonObject *function_name = get_builtin_field(function, __name__); if (function_name) add_builtin_field(bound_method_wrapper, __name__, function_name); return bound_method_wrapper; @@ -100,8 +129,8 @@ ArgonObject *get_field_l(ArgonObject *target, char *name, uint64_t hash, size_t length, bool recursive, bool disable_method_wrapper) { for (size_t i = 0; i < BUILT_IN_FIELDS_COUNT; i++) { - if (strcmp(name, built_in_field_names[i])) { - return target->Builtin_slots[i]; + if (strcmp_len(name, length, built_in_field_names[i]) == 0) { + return get_builtin_field(target, i); } } if (!target->dict) @@ -112,28 +141,35 @@ ArgonObject *get_field_l(ArgonObject *target, char *name, uint64_t hash, ArgonObject *binding = target; if (disable_method_wrapper) binding = NULL; - return get_field_for_class_l( - get_builtin_field(target, __class__), name, - hash, length, binding); + return get_field_for_class_l(get_builtin_field(target, __class__), name, hash, + length, binding); } ArgonObject *get_builtin_field_for_class(ArgonObject *target, built_in_fields field, ArgonObject *binding_object) { - ArgonObject *object = get_builtin_field(target, field); - if (object) { - if ((object->type == TYPE_FUNCTION || - object->type == TYPE_NATIVE_FUNCTION) && - binding_object) { - object = bind_object_to_function(binding_object, object); + while (target) { + ArgonObject *object = get_builtin_field(target, field); + if (object) { + if ((object->type == TYPE_FUNCTION || + object->type == TYPE_NATIVE_FUNCTION) && + binding_object) { + object = bind_object_to_function(binding_object, object); + } + return object; } - return object; + target = get_builtin_field(target, __base__); } return NULL; } ArgonObject *get_builtin_field(ArgonObject *target, built_in_fields field) { - return target->Builtin_slots[field]; + for (size_t i = 0; i < target->built_in_slot_length; i++) { + if (target->built_in_slot[i].field == field) { + return target->built_in_slot[i].value; + } + } + return NULL; // ArgonObject *object = // hashmap_lookup_GC(target->dict, built_in_field_hashes[field]); // if (!recursive || object) diff --git a/src/runtime/objects/object.h b/src/runtime/objects/object.h index 2dfe02b..ffd13c9 100644 --- a/src/runtime/objects/object.h +++ b/src/runtime/objects/object.h @@ -21,8 +21,8 @@ ArgonObject *new_instance(ArgonObject * of); void add_builtin_field(ArgonObject *target, built_in_fields field, ArgonObject *object); -void add_field(ArgonObject *target, char *name, uint64_t hash, - ArgonObject *object); +void add_field_l(ArgonObject *target, char *name, uint64_t hash, size_t length, + ArgonObject *object); ArgonObject *bind_object_to_function(ArgonObject *object, ArgonObject *function); diff --git a/tests/iteration-test.ar b/tests/iteration-test.ar index 0f7853b..2c929db 100644 --- a/tests/iteration-test.ar +++ b/tests/iteration-test.ar @@ -1,3 +1,3 @@ -let i = 1e6 +let i = 1e7 while (i) do i=i-1 \ No newline at end of file