You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

namespace.c 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "vm/vm.h"
  2. static const l2_word tombstone = ~(l2_word)0;
  3. static struct l2_vm_namespace *set(struct l2_vm_namespace *ns, l2_word key, l2_word val);
  4. static struct l2_vm_namespace *alloc(size_t size, l2_word mask) {
  5. struct l2_vm_namespace *ns = calloc(
  6. 1, sizeof(struct l2_vm_namespace) + sizeof(l2_word) * size * 2);
  7. ns->size = size;
  8. ns->mask = mask;
  9. return ns;
  10. }
  11. static struct l2_vm_namespace *grow(struct l2_vm_namespace *ns) {
  12. struct l2_vm_namespace *newns = alloc(ns->size * 2, (ns->mask << 1) | ns->mask);
  13. for (size_t i = 0; i < ns->size; ++i) {
  14. l2_word key = ns->data[i];
  15. if (key == 0 || key == tombstone) {
  16. continue;
  17. }
  18. l2_word val = ns->data[ns->size + i];
  19. for (l2_word i = 0; ; ++i) {
  20. l2_word hash = (key + i) & newns->mask;
  21. if (newns->data[hash] == 0) {
  22. newns->data[hash] = key;
  23. newns->data[newns->size + hash] = val;
  24. newns->len += 1;
  25. break;
  26. }
  27. }
  28. }
  29. free(ns);
  30. return newns;
  31. }
  32. static void del(struct l2_vm_namespace *ns, l2_word key) {
  33. if (ns == NULL) {
  34. return;
  35. }
  36. for (l2_word i = 0; ; ++i) {
  37. l2_word hash = (key + i) & ns->mask;
  38. l2_word k = ns->data[hash];
  39. if (k == 0) {
  40. return;
  41. } else if (k == key) {
  42. ns->data[hash] = tombstone;
  43. return;
  44. }
  45. }
  46. }
  47. static struct l2_vm_namespace *set(struct l2_vm_namespace *ns, l2_word key, l2_word val) {
  48. if (ns == NULL) {
  49. ns = alloc(16, 0x0f);
  50. } else if (ns->len >= ns->size / 2) {
  51. ns = grow(ns);
  52. }
  53. for (l2_word i = 0; ; ++i) {
  54. l2_word hash = (key + i) & ns->mask;
  55. l2_word k = ns->data[hash];
  56. if (k == tombstone) {
  57. ns->data[hash] = key;
  58. ns->data[ns->size + hash] = val;
  59. break;
  60. } else if (k == key) {
  61. ns->data[ns->size + hash] = val;
  62. break;
  63. } else if (k == 0) {
  64. ns->len += 1;
  65. ns->data[hash] = key;
  66. ns->data[ns->size + hash] = val;
  67. break;
  68. }
  69. }
  70. return ns;
  71. }
  72. static l2_word get(struct l2_vm_namespace *ns, l2_word key) {
  73. if (ns == NULL) {
  74. return 0;
  75. }
  76. for (l2_word i = 0; ; ++i) {
  77. l2_word hash = (key + i) & ns->mask;
  78. l2_word k = ns->data[hash];
  79. if (k == 0 || k == tombstone) {
  80. return 0;
  81. } else if (k == key) {
  82. return ns->data[ns->size + hash];
  83. }
  84. }
  85. }
  86. l2_word l2_vm_namespace_get(struct l2_vm *vm, struct l2_vm_value *v, l2_word key) {
  87. l2_word ret = get(v->ns, key);
  88. if (ret == 0 && v->extra.ns_parent != 0) {
  89. return l2_vm_namespace_get(vm, &vm->values[v->extra.ns_parent], key);
  90. }
  91. return ret;
  92. }
  93. void l2_vm_namespace_set(struct l2_vm_value *v, l2_word key, l2_word val) {
  94. if (val == 0) {
  95. del(v->ns, key);
  96. } else {
  97. v->ns = set(v->ns, key, val);
  98. }
  99. }
  100. int l2_vm_namespace_replace(struct l2_vm *vm, struct l2_vm_value *v, l2_word key, l2_word val) {
  101. if (val == 0) {
  102. del(v->ns, key);
  103. return 0;
  104. } else {
  105. l2_word ret = get(v->ns, key);
  106. if (ret != 0) {
  107. v->ns = set(v->ns, key, val);
  108. return 0;
  109. }
  110. if (v->extra.ns_parent == 0) {
  111. return -1;
  112. }
  113. return l2_vm_namespace_replace(vm, &vm->values[v->extra.ns_parent], key, val);
  114. }
  115. }