dataStack.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * This file is part of the PikaPython project.
  3. * http://github.com/pikastech/pikapython
  4. *
  5. * MIT License
  6. *
  7. * Copyright (c) 2021 lyon liang6516@outlook.com
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. */
  27. #include "dataStack.h"
  28. #include "PikaObj.h"
  29. #include "dataQueue.h"
  30. void _stack_overflow_handler(Stack* stack, size_t stack_require) {
  31. pika_platform_printf(
  32. "OverflowError: pika VM stack overflow, please use bigger "
  33. "PIKA_STACK_BUFF_SIZE\r\n");
  34. pika_platform_printf("Info: stack size request: %d\r\n",
  35. (int)stack_require);
  36. pika_platform_printf("Info: stack size now: %d\r\n",
  37. (int)stack->stack_totle_size);
  38. while (1) {
  39. }
  40. }
  41. uint8_t* stack_popPyload(Stack* stack, int32_t size);
  42. uint8_t* stack_getSpStart(Stack* stack) {
  43. return (uint8_t*)arg_getContent(stack->stack_pyload);
  44. }
  45. int32_t* stack_getSpSizeStart(Stack* stack) {
  46. return (int32_t*)arg_getContent(stack->stack_size_array);
  47. }
  48. uint32_t stack_spFree(Stack* stack) {
  49. return stack->stack_totle_size -
  50. ((uintptr_t)stack->sp - (uintptr_t)stack_getSpStart(stack));
  51. }
  52. uint32_t stack_spSizeFree(Stack* stack) {
  53. return stack->stack_totle_size / 4 -
  54. ((uintptr_t)stack->sp_size - (uintptr_t)stack_getSpSizeStart(stack));
  55. }
  56. void stack_reset(Stack* stack) {
  57. stack->sp = stack_getSpStart(stack);
  58. stack->sp_size = stack_getSpSizeStart(stack);
  59. stack->top = 0;
  60. }
  61. int32_t _stack_init(Stack* stack, size_t stack_size) {
  62. stack->stack_pyload = arg_setContent(NULL, NULL, stack_size);
  63. stack->stack_size_array = arg_setContent(NULL, NULL, stack_size / 4);
  64. stack_reset(stack);
  65. stack->stack_totle_size = stack_size;
  66. return 0;
  67. }
  68. int32_t stack_init(Stack* stack) {
  69. return _stack_init(stack, PIKA_STACK_BUFF_SIZE);
  70. };
  71. void stack_pushSize(Stack* stack, int32_t size) {
  72. *(stack->sp_size) = size;
  73. stack->sp_size++;
  74. if (stack_spSizeFree(stack) < sizeof(int32_t)) {
  75. _stack_overflow_handler(stack,
  76. stack->stack_totle_size + sizeof(int32_t) * 4);
  77. }
  78. }
  79. int32_t stack_popSize(Stack* stack) {
  80. stack->sp_size--;
  81. return *(stack->sp_size);
  82. }
  83. Arg* stack_checkArg(Stack* stack, int index) {
  84. if (stack->top - index <= 0) {
  85. return NULL;
  86. }
  87. int sp_offset = 0;
  88. int32_t size = 0;
  89. for (int i = 1; i <= index + 1; i++) {
  90. size = stack->sp_size[-i];
  91. if (size == -1) {
  92. sp_offset -= sizeof(Arg*);
  93. } else {
  94. sp_offset -= size;
  95. }
  96. }
  97. if (size == -1) {
  98. return *(Arg**)(stack->sp + sp_offset);
  99. }
  100. return (Arg*)(stack->sp + sp_offset);
  101. }
  102. int32_t stack_deinit(Stack* stack) {
  103. while (stack->top > 0) {
  104. int32_t size = stack_popSize(stack);
  105. uint8_t* pyload = stack_popPyload(stack, size);
  106. stack->top--;
  107. if (size == -1) {
  108. arg_deinit(*(Arg**)pyload);
  109. }
  110. }
  111. arg_deinit(stack->stack_pyload);
  112. arg_deinit(stack->stack_size_array);
  113. return 0;
  114. }
  115. void stack_pushPyload(Stack* stack,
  116. uint8_t* in,
  117. size_t size,
  118. pika_bool is_sample_copy) {
  119. size_t stack_require = size + (stack->sp - stack_getSpStart(stack));
  120. if (stack_require > stack->stack_totle_size) {
  121. _stack_overflow_handler(stack, stack_require);
  122. }
  123. Arg* top = (Arg*)stack->sp;
  124. if (is_sample_copy) {
  125. pika_platform_memcpy(top, in, size);
  126. } else {
  127. pika_platform_memcpy(top, in, sizeof(Arg));
  128. pika_platform_memcpy(top->content, ((Arg*)in)->_.buffer,
  129. size - sizeof(Arg));
  130. /* transfer to serialized form */
  131. arg_setSerialized(top, pika_true);
  132. }
  133. stack->sp += size;
  134. }
  135. uint8_t* stack_popPyload(Stack* stack, int32_t size) {
  136. if (size == -1) {
  137. size = sizeof(void*);
  138. }
  139. stack->sp -= size;
  140. return stack->sp;
  141. }
  142. static int32_t _stack_pushArg(Stack* stack, Arg* arg, pika_bool is_alloc) {
  143. pika_bool is_big_arg = pika_false;
  144. stack->top++;
  145. size_t size = arg_getTotleSize(arg);
  146. //! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment
  147. #if PIKA_ARG_ALIGN_ENABLE
  148. /* force alignment to avoid unaligned access */
  149. size = (size + 4 - 1) & ~(4 - 1);
  150. #endif
  151. /* add ref_cnt to keep object in stack */
  152. arg_refcntInc(arg);
  153. if (arg_isSerialized(arg)) {
  154. is_big_arg = pika_true;
  155. }
  156. if (is_big_arg) {
  157. /* push a pointer to this arg */
  158. stack_pushSize(stack, -1);
  159. stack_pushPyload(stack, (uint8_t*)&arg, sizeof(Arg*), pika_true);
  160. } else {
  161. stack_pushSize(stack, size);
  162. stack_pushPyload(stack, (uint8_t*)arg, size,
  163. (pika_bool)arg_isSerialized(arg));
  164. }
  165. if (is_big_arg) {
  166. return 0;
  167. }
  168. if (is_alloc) {
  169. arg_deinit(arg);
  170. return 0;
  171. }
  172. arg_deinitHeap(arg);
  173. return 0;
  174. }
  175. int32_t stack_pushArg(Stack* stack, Arg* arg) {
  176. pika_assert(arg != NULL);
  177. if (arg_isObject(arg)) {
  178. pika_assert(obj_checkAlive(arg_getPtr(arg)));
  179. }
  180. if (arg_isSerialized(arg)) {
  181. return _stack_pushArg(stack, arg, pika_true);
  182. }
  183. return _stack_pushArg(stack, arg, pika_false);
  184. }
  185. int32_t stack_pushStr(Stack* stack, char* str) {
  186. Arg* newArg = arg_newStr(str);
  187. return stack_pushArg(stack, newArg);
  188. }
  189. Arg* _stack_popArg(Stack* stack, Arg* arg_dict, pika_bool is_alloc) {
  190. pika_bool is_big_arg = pika_false;
  191. if (stack->top == 0) {
  192. return NULL;
  193. }
  194. stack->top--;
  195. int32_t size = stack_popSize(stack);
  196. if (size == -1) {
  197. is_big_arg = pika_true;
  198. size = sizeof(Arg*);
  199. }
  200. Arg* arg = NULL;
  201. if (is_big_arg) {
  202. arg = *(Arg**)stack_popPyload(stack, size);
  203. } else {
  204. arg = (Arg*)stack_popPyload(stack, size);
  205. if (is_alloc) {
  206. arg = arg_copy(arg);
  207. } else {
  208. arg = arg_copy_noalloc(arg, arg_dict);
  209. }
  210. }
  211. /* decrase ref_cnt */
  212. arg_refcntDec(arg);
  213. pika_assert(arg->flag < ARG_FLAG_MAX);
  214. return arg;
  215. }
  216. Arg* stack_popArg_alloc(Stack* stack) {
  217. return _stack_popArg(stack, NULL, pika_true);
  218. }
  219. Arg* stack_popArg(Stack* stack, Arg* arg_dict) {
  220. return _stack_popArg(stack, arg_dict, pika_false);
  221. }
  222. char* stack_popStr(Stack* stack, char* outBuff) {
  223. Arg* arg = stack_popArg_alloc(stack);
  224. strcpy(outBuff, arg_getStr(arg));
  225. arg_deinit(arg);
  226. return outBuff;
  227. }
  228. int32_t stack_getTop(Stack* stack) {
  229. return stack->top;
  230. }