File Coverage

lib/SPVM/Builder/src/spvm_api.c
Criterion Covered Total %
statement 1855 2152 86.2
branch 559 794 70.4
condition n/a
subroutine n/a
pod n/a
total 2414 2946 81.9


line stmt bran cond sub pod time code
1             // Copyright (c) 2023 Yuki Kimoto
2             // MIT License
3              
4             #include
5             #include
6             #include
7             #include
8              
9             #include "spvm_native.h"
10              
11             #include "spvm_api.h"
12             #include "spvm_vm.h"
13             #include "spvm_api_runtime.h"
14             #include "spvm_api_allocator.h"
15             #include "spvm_api_string_buffer.h"
16             #include "spvm_opcode.h"
17              
18             #include "spvm_strerror.h"
19             #include "spvm_object.h"
20             #include "spvm_allocator.h"
21             #include "spvm_weaken_backref.h"
22             #include "spvm_hash.h"
23             #include "spvm_string_buffer.h"
24              
25             #include "spvm_runtime.h"
26             #include "spvm_runtime_string.h"
27             #include "spvm_runtime_basic_type.h"
28             #include "spvm_runtime_class_var.h"
29             #include "spvm_runtime_field.h"
30             #include "spvm_runtime_method.h"
31              
32             #include "spvm_implement.h"
33              
34             #include "spvm_api_string_buffer.h"
35             #include "spvm_api_compiler.h"
36             #include "spvm_api_runtime.h"
37             #include "spvm_api_class_file.h"
38             #include "spvm_api_basic_type.h"
39             #include "spvm_api_class_var.h"
40             #include "spvm_api_field.h"
41             #include "spvm_api_method.h"
42             #include "spvm_api_arg.h"
43             #include "spvm_api_type.h"
44             #include "spvm_api_internal.h"
45              
46             #include "spvm_mutex.h"
47              
48             static const char* FILE_NAME = "spvm_api.c";
49              
50 119195           SPVM_ENV* SPVM_API_new_env(void) {
51              
52 119195           SPVM_API_ALLOCATOR* api_allocator = SPVM_API_ALLOCATOR_new_api();
53            
54 119195           SPVM_API_STRING_BUFFER* api_string_buffer = SPVM_API_STRING_BUFFER_new_api();
55            
56 119195           SPVM_API_COMPILER* api_compiler = SPVM_API_COMPILER_new_api();
57            
58 119195           SPVM_API_RUNTIME* api_runtime = SPVM_API_RUNTIME_new_api();
59            
60 119195           SPVM_API_CLASS_FILE* api_class_file = SPVM_API_CLASS_FILE_new_api();
61            
62 119195           SPVM_API_BASIC_TYPE* api_basic_type = SPVM_API_BASIC_TYPE_new_api();
63            
64 119195           SPVM_API_CLASS_VAR* api_class_var = SPVM_API_CLASS_VAR_new_api();
65            
66 119195           SPVM_API_FIELD* api_field = SPVM_API_FIELD_new_api();
67            
68 119195           SPVM_API_TYPE* api_type = SPVM_API_TYPE_new_api();
69            
70 119195           SPVM_API_METHOD* api_method = SPVM_API_METHOD_new_api();
71            
72 119195           SPVM_API_ARG* api_arg = SPVM_API_ARG_new_api();
73            
74 119195           SPVM_API_INTERNAL* api_internal = SPVM_API_INTERNAL_new_api();
75            
76 119195           void* env_api_init[] = {
77             api_allocator,
78             api_string_buffer,
79             api_compiler,
80             api_class_file,
81             api_runtime,
82             api_basic_type,
83             api_class_var,
84             api_field,
85             api_method,
86             api_arg,
87             api_type,
88             api_internal,
89             };
90 119195           SPVM_ENV_API* env_api = calloc(1, sizeof(env_api_init));
91 119195           memcpy(env_api, env_api_init, sizeof(env_api_init));
92              
93              
94              
95              
96              
97              
98             // Native APIs
99 119195           void* env_init[] = {
100             NULL, // compiler
101             NULL, // runtime
102             env_api, // api
103             SPVM_API_new_env,
104             SPVM_API_free_env,
105             SPVM_API_call_init_methods,
106             SPVM_API_set_command_info_program_name,
107             SPVM_API_set_command_info_argv,
108             SPVM_API_set_command_info_base_time,
109             SPVM_API_destroy_class_vars,
110             SPVM_API_args_width,
111             SPVM_API_get_object_basic_type,
112             SPVM_API_get_object_basic_type_id,
113             SPVM_API_get_object_basic_type_name,
114             SPVM_API_get_object_type_dimension,
115             SPVM_API_get_basic_type,
116             SPVM_API_get_basic_type_by_name,
117             SPVM_API_get_basic_type_by_id,
118             SPVM_API_get_basic_type_id,
119             SPVM_API_get_basic_type_id_by_name,
120             SPVM_API_get_class_var,
121             SPVM_API_get_class_var_byte,
122             SPVM_API_get_class_var_short,
123             SPVM_API_get_class_var_int,
124             SPVM_API_get_class_var_long,
125             SPVM_API_get_class_var_float,
126             SPVM_API_get_class_var_double,
127             SPVM_API_get_class_var_object,
128             SPVM_API_get_class_var_string,
129             SPVM_API_set_class_var_byte,
130             SPVM_API_set_class_var_short,
131             SPVM_API_set_class_var_int,
132             SPVM_API_set_class_var_long,
133             SPVM_API_set_class_var_float,
134             SPVM_API_set_class_var_double,
135             SPVM_API_set_class_var_object,
136             SPVM_API_set_class_var_string,
137             SPVM_API_get_class_var_object_ref,
138             SPVM_API_get_class_var_byte_by_name,
139             SPVM_API_get_class_var_short_by_name,
140             SPVM_API_get_class_var_int_by_name,
141             SPVM_API_get_class_var_long_by_name,
142             SPVM_API_get_class_var_float_by_name,
143             SPVM_API_get_class_var_double_by_name,
144             SPVM_API_get_class_var_object_by_name,
145             SPVM_API_get_class_var_string_by_name,
146             SPVM_API_set_class_var_byte_by_name,
147             SPVM_API_set_class_var_short_by_name,
148             SPVM_API_set_class_var_int_by_name,
149             SPVM_API_set_class_var_long_by_name,
150             SPVM_API_set_class_var_float_by_name,
151             SPVM_API_set_class_var_double_by_name,
152             SPVM_API_set_class_var_object_by_name,
153             SPVM_API_set_class_var_string_by_name,
154             SPVM_API_get_field,
155             SPVM_API_get_field_static,
156             SPVM_API_get_field_byte,
157             SPVM_API_get_field_short,
158             SPVM_API_get_field_int,
159             SPVM_API_get_field_long,
160             SPVM_API_get_field_float,
161             SPVM_API_get_field_double,
162             SPVM_API_get_field_object,
163             SPVM_API_get_field_string,
164             SPVM_API_set_field_byte,
165             SPVM_API_set_field_short,
166             SPVM_API_set_field_int,
167             SPVM_API_set_field_long,
168             SPVM_API_set_field_float,
169             SPVM_API_set_field_double,
170             SPVM_API_set_field_object,
171             SPVM_API_set_field_string,
172             SPVM_API_get_field_byte_by_name,
173             SPVM_API_get_field_short_by_name,
174             SPVM_API_get_field_int_by_name,
175             SPVM_API_get_field_long_by_name,
176             SPVM_API_get_field_float_by_name,
177             SPVM_API_get_field_double_by_name,
178             SPVM_API_get_field_object_by_name,
179             SPVM_API_get_field_string_by_name,
180             SPVM_API_set_field_byte_by_name,
181             SPVM_API_set_field_short_by_name,
182             SPVM_API_set_field_int_by_name,
183             SPVM_API_set_field_long_by_name,
184             SPVM_API_set_field_float_by_name,
185             SPVM_API_set_field_double_by_name,
186             SPVM_API_set_field_object_by_name,
187             SPVM_API_set_field_string_by_name,
188             SPVM_API_get_field_string_chars_by_name,
189             SPVM_API_get_method,
190             SPVM_API_get_class_method,
191             SPVM_API_get_instance_method_static,
192             SPVM_API_get_instance_method,
193             SPVM_API_call_method_no_mortal,
194             SPVM_API_call_method,
195             SPVM_API_call_class_method_by_name,
196             SPVM_API_call_instance_method_static_by_name,
197             SPVM_API_call_instance_method_by_name,
198             SPVM_API_new_object_no_mortal,
199             SPVM_API_new_object,
200             SPVM_API_new_object_by_name,
201             SPVM_API_new_pointer_object_no_mortal,
202             SPVM_API_new_pointer_object,
203             SPVM_API_new_pointer_object_by_name,
204             SPVM_API_get_pointer,
205             SPVM_API_set_pointer,
206             SPVM_API_new_string_nolen_no_mortal,
207             SPVM_API_new_string_nolen,
208             SPVM_API_new_string_no_mortal,
209             SPVM_API_new_string,
210             SPVM_API_new_byte_array_no_mortal,
211             SPVM_API_new_byte_array,
212             SPVM_API_new_short_array_no_mortal,
213             SPVM_API_new_short_array,
214             SPVM_API_new_int_array_no_mortal,
215             SPVM_API_new_int_array,
216             SPVM_API_new_long_array_no_mortal,
217             SPVM_API_new_long_array,
218             SPVM_API_new_float_array_no_mortal,
219             SPVM_API_new_float_array,
220             SPVM_API_new_double_array_no_mortal,
221             SPVM_API_new_double_array,
222             SPVM_API_new_object_array_no_mortal,
223             SPVM_API_new_object_array,
224             SPVM_API_new_object_array_by_name,
225             SPVM_API_new_string_array,
226             SPVM_API_new_muldim_array_no_mortal,
227             SPVM_API_new_muldim_array,
228             SPVM_API_new_muldim_array_by_name,
229             SPVM_API_new_mulnum_array_no_mortal,
230             SPVM_API_new_mulnum_array,
231             SPVM_API_new_mulnum_array_by_name,
232             SPVM_API_new_array_proto_no_mortal,
233             SPVM_API_new_array_proto,
234             SPVM_API_length,
235             SPVM_API_get_elems_byte,
236             SPVM_API_get_elems_short,
237             SPVM_API_get_elems_int,
238             SPVM_API_get_elems_long,
239             SPVM_API_get_elems_float,
240             SPVM_API_get_elems_double,
241             SPVM_API_get_elem_object,
242             SPVM_API_get_elem_string,
243             SPVM_API_set_elem_object,
244             SPVM_API_set_elem_string,
245             SPVM_API_get_chars,
246             SPVM_API_get_bool_object_value,
247             SPVM_API_concat_no_mortal,
248             SPVM_API_concat,
249             SPVM_API_shorten,
250             SPVM_API_make_read_only,
251             SPVM_API_is_read_only,
252             SPVM_API_print,
253             SPVM_API_print_stderr,
254             SPVM_API_dump_no_mortal,
255             SPVM_API_dump,
256             SPVM_API_dumpc,
257             SPVM_API_copy_no_mortal,
258             SPVM_API_copy,
259             SPVM_API_get_spvm_version_string,
260             SPVM_API_get_spvm_version_number,
261             SPVM_API_get_version_string,
262             SPVM_API_get_version_number,
263             SPVM_API_die,
264             SPVM_API_get_exception,
265             SPVM_API_set_exception,
266             SPVM_API_new_stack_trace_no_mortal,
267             SPVM_API_new_stack_trace,
268             SPVM_API_is_string,
269             SPVM_API_is_class,
270             SPVM_API_is_pointer_class,
271             SPVM_API_is_array,
272             SPVM_API_is_object_array,
273             SPVM_API_is_numeric_array,
274             SPVM_API_is_mulnum_array,
275             SPVM_API_isa,
276             SPVM_API_isa_by_name,
277             SPVM_API_is_type,
278             SPVM_API_is_type_by_name,
279             SPVM_API_elem_isa,
280             SPVM_API_get_elem_size,
281             SPVM_API_get_type_name_no_mortal,
282             SPVM_API_get_type_name,
283             SPVM_API_get_compile_type_name_no_mortal,
284             SPVM_API_get_compile_type_name,
285             SPVM_API_enter_scope,
286             SPVM_API_leave_scope,
287             SPVM_API_push_mortal,
288             NULL,
289             SPVM_API_weaken,
290             SPVM_API_isweak,
291             SPVM_API_unweaken,
292             SPVM_API_strerror_string,
293             SPVM_API_strerror_string_nolen,
294             SPVM_API_strerror,
295             SPVM_API_strerror_nolen,
296             NULL,
297             NULL,
298             NULL,
299             NULL,
300             SPVM_API_new_memory_stack,
301             SPVM_API_free_memory_stack,
302             SPVM_API_get_memory_blocks_count_stack,
303             SPVM_API_new_stack,
304             SPVM_API_free_stack,
305             SPVM_API_get_ref_count,
306             NULL,
307             NULL,
308             SPVM_API_get_field_object_defined_and_has_pointer_by_name,
309             SPVM_API_get_field_object_ref,
310             SPVM_API_get_field_object_ref_by_name,
311             SPVM_API_check_stack_env,
312             NULL,
313             NULL,
314             SPVM_API_assign_object,
315             SPVM_API_new_string_array_no_mortal,
316             SPVM_API_new_memory_block,
317             SPVM_API_free_memory_block,
318             SPVM_API_get_memory_blocks_count,
319             SPVM_API_say,
320             SPVM_API_warn,
321             };
322 119195           SPVM_ENV* env = calloc(1, sizeof(env_init));
323 119195 50         if (env == NULL) {
324 0           return NULL;
325             }
326 119195           memcpy(env, env_init, sizeof(env_init));
327            
328 119195           return env;
329             }
330              
331 119195           void SPVM_API_free_env(SPVM_ENV* env) {
332              
333             // Free env api
334 119195           SPVM_API_ALLOCATOR_free_api(env->api->allocator);
335 119195           SPVM_API_STRING_BUFFER_free_api(env->api->string_buffer);
336 119195           SPVM_API_COMPILER_free_api(env->api->compiler);
337 119195           SPVM_API_RUNTIME_free_api(env->api->runtime);
338 119195           SPVM_API_CLASS_FILE_free_api(env->api->class_file);
339 119195           SPVM_API_BASIC_TYPE_free_api(env->api->basic_type);
340 119195           SPVM_API_CLASS_VAR_free_api(env->api->class_var);
341 119195           SPVM_API_FIELD_free_api(env->api->field);
342 119195           SPVM_API_TYPE_free_api(env->api->type);
343 119195           SPVM_API_METHOD_free_api(env->api->method);
344 119195           SPVM_API_ARG_free_api(env->api->arg);
345 119195           SPVM_API_INTERNAL_free_api(env->api->internal);
346            
347 119195           free(env->api);
348            
349             // Free env
350 119195           free(env);
351 119195           env = NULL;
352 119195           }
353              
354 488           int32_t SPVM_API_call_init_methods(SPVM_ENV* env, SPVM_VALUE* stack) {
355            
356 488           int32_t error_id = 0;
357            
358             // Runtime
359 488           SPVM_RUNTIME* runtime = env->runtime;
360            
361             // Call INIT blocks
362 488           int32_t basic_types_length = runtime->basic_types_length;
363 25260 100         for (int32_t basic_type_id = 0; basic_type_id < basic_types_length; basic_type_id++) {
364 24772           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_RUNTIME_get_basic_type_by_id(env->runtime, basic_type_id);
365 24772 100         if (basic_type->init_method) {
366 15304           SPVM_RUNTIME_METHOD* init_method = SPVM_API_BASIC_TYPE_get_method_by_index(env->runtime, basic_type, basic_type->init_method->index);
367 15304           int32_t args_width = 0;
368 15304           error_id = SPVM_API_call_method_no_mortal(env, stack, init_method, args_width);
369 15304 50         if (error_id) { break; }
370             }
371             }
372            
373 488           return error_id;
374             }
375              
376 336           int32_t SPVM_API_set_command_info_program_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* obj_program_name) {
377            
378 336           int32_t error_id = 0;
379            
380 336 50         if (!obj_program_name) {
381 0           return SPVM_API_die(env, stack, "The obj_program_name must be defined", __func__, FILE_NAME, __LINE__);
382             }
383            
384 336           SPVM_RUNTIME_BASIC_TYPE* obj_program_name_basic_type = SPVM_API_get_object_basic_type(env, stack, obj_program_name);
385 336 50         if (!(obj_program_name_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_STRING && obj_program_name->type_dimension == 0)) {
    50          
386 0           return SPVM_API_die(env, stack, "The obj_program_name must be a string", __func__, FILE_NAME, __LINE__);
387             }
388            
389 336           SPVM_API_set_class_var_object_by_name(env, stack, "CommandInfo", "$PROGRAM_NAME", obj_program_name, &error_id, __func__, __FILE__, __LINE__);
390 336 50         if (error_id) { return error_id; }
391            
392 336           return 0;
393             }
394              
395 336           int32_t SPVM_API_set_command_info_argv(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* obj_argv) {
396            
397 336           int32_t error_id = 0;
398            
399 336 50         if (!obj_argv) {
400 0           return SPVM_API_die(env, stack, "The obj_argv must be defined", __func__, FILE_NAME, __LINE__);
401             }
402            
403 336           SPVM_RUNTIME_BASIC_TYPE* obj_argv_basic_type = SPVM_API_get_object_basic_type(env, stack, obj_argv);
404 336 50         if (!(obj_argv_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_STRING && obj_argv->type_dimension == 1)) {
    50          
405 0           return SPVM_API_die(env, stack, "The obj_argv must be a string array", __func__, FILE_NAME, __LINE__);
406             }
407            
408 336           SPVM_API_set_class_var_object_by_name(env, stack, "CommandInfo", "$ARGV", obj_argv, &error_id, __func__, __FILE__, __LINE__);
409 336 50         if (error_id) { return error_id; }
410            
411 336           return 0;
412             }
413              
414 336           int32_t SPVM_API_set_command_info_base_time(SPVM_ENV* env, SPVM_VALUE* stack, int64_t base_time) {
415            
416 336           int32_t error_id = 0;
417            
418 336           SPVM_API_set_class_var_long_by_name(env, stack, "CommandInfo", "$BASE_TIME", base_time, &error_id, __func__, __FILE__, __LINE__);
419 336 50         if (error_id) { return error_id; }
420            
421 336           return 0;
422             }
423              
424 336           void SPVM_API_destroy_class_vars(SPVM_ENV* env, SPVM_VALUE* stack){
425              
426             // Runtime
427 336           SPVM_RUNTIME* runtime = env->runtime;
428            
429             // Free objects of class variables
430 15619 100         for (int32_t basic_type_id = 0; basic_type_id < runtime->basic_types_length; basic_type_id++) {
431 15283           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_RUNTIME_get_basic_type_by_id(env->runtime, basic_type_id);
432            
433 17597 100         for (int32_t class_var_index = 0; class_var_index < basic_type->class_vars_length; class_var_index++) {
434            
435 2314           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_index(runtime, basic_type, class_var_index);
436            
437 2314           SPVM_RUNTIME_BASIC_TYPE* class_var_basic_type = class_var->basic_type;
438 2314           int32_t class_var_type_dimension = class_var->type_dimension;
439 2314           int32_t class_var_type_flag = class_var->type_flag;
440            
441 2314           int32_t class_var_type_is_object = SPVM_API_TYPE_is_object_type(runtime, class_var_basic_type, class_var_type_dimension, class_var_type_flag);
442 2314 100         if (class_var_type_is_object) {
443 1446           SPVM_OBJECT** object_ref = (SPVM_OBJECT**)&class_var->data;
444 1446           SPVM_API_assign_object(env, stack, object_ref, NULL);
445             }
446             }
447             }
448 336           }
449              
450 670139           int32_t SPVM_API_args_width(SPVM_ENV* env, SPVM_VALUE* stack) {
451 670139           int32_t args_length = stack[SPVM_API_C_STACK_INDEX_ARGS_WIDTH].ival;
452            
453 670139           return args_length;
454             }
455              
456 4           int32_t SPVM_API_get_basic_type_id(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name) {
457            
458              
459 4           SPVM_RUNTIME* runtime = env->runtime;
460              
461 4 50         if (basic_type_name == NULL) {
462 0           return -1;
463             }
464              
465 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_RUNTIME_get_basic_type_by_name(runtime, basic_type_name);
466 4 100         if (basic_type) {
467 2           int32_t basic_type_id = basic_type->id;
468 2           return basic_type_id;
469             }
470             else {
471 2           return -1;
472             }
473             }
474              
475 282407           SPVM_RUNTIME_BASIC_TYPE* SPVM_API_get_basic_type(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name) {
476            
477              
478 282407           SPVM_RUNTIME* runtime = env->runtime;
479              
480 282407 50         if (basic_type_name == NULL) {
481 0           return NULL;
482             }
483              
484 282407           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_RUNTIME_get_basic_type_by_name(runtime, basic_type_name);
485            
486 282407           return basic_type;
487             }
488              
489 16           void SPVM_API_call_class_method_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name, int32_t args_width, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
490            
491 16           *error_id = 0;
492            
493 16           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
494 16           SPVM_RUNTIME_METHOD* method = SPVM_API_BASIC_TYPE_get_method_by_name(env->runtime, basic_type, method_name);
495 16 100         if (!method) {
496 2           *error_id = SPVM_API_die(env, stack, "The %s class method in the %s class is not found", method_name, basic_type_name, func_name, file, line);
497 2           return;
498             }
499 14           *error_id = SPVM_API_call_method_no_mortal(env, stack, method, args_width);
500 14 50         if (*error_id) {
501 0           const char* message = SPVM_API_get_chars(env, stack, SPVM_API_get_exception(env, stack));
502 0           SPVM_API_die(env, stack, "%s", message, func_name, file, line);
503             }
504             }
505              
506 4           void SPVM_API_call_instance_method_static_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name, int32_t args_width, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
507            
508 4           *error_id = 0;
509            
510 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
511 4           SPVM_RUNTIME_METHOD* method = SPVM_API_BASIC_TYPE_get_method_by_name(env->runtime, basic_type, method_name);
512 4 100         if (!method) {
513 2           *error_id = SPVM_API_die(env, stack, "The %s instance method in the %s class is not found", method_name, basic_type_name, func_name, file, line);
514 2           return;
515             }
516 2           *error_id = SPVM_API_call_method_no_mortal(env, stack, method, args_width);
517 2 50         if (*error_id) {
518 0           const char* message = SPVM_API_get_chars(env, stack, SPVM_API_get_exception(env, stack));
519 0           SPVM_API_die(env, stack, "%s", message, func_name, file, line);
520             }
521             }
522              
523 348           void SPVM_API_call_instance_method_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* method_name, int32_t args_width, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
524            
525 348           *error_id = 0;
526            
527 348           SPVM_OBJECT* object = stack[0].oval;
528            
529 348 50         if (object == NULL) {
530 0           *error_id = SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
531 0           return;
532             };
533            
534 348 50         if (object->type_dimension > 0) {
535 0           *error_id = SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
536 0           return;
537             };
538            
539 348           SPVM_RUNTIME_METHOD* method = SPVM_API_get_instance_method(env, stack, object, method_name);
540 348 100         if (!method) {
541 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
542 2           *error_id = SPVM_API_die(env, stack, "The %s instance method is not found in the %s class or its super class", method_name, basic_type_name, func_name, file, line);
543 2           return;
544             };
545            
546 346           *error_id = SPVM_API_call_method_no_mortal(env, stack, method, args_width);
547            
548 346 100         if (*error_id) {
549 2           const char* message = SPVM_API_get_chars(env, stack, SPVM_API_get_exception(env, stack));
550 2           SPVM_API_die(env, stack, "%s", message, func_name, file, line);
551             }
552             }
553              
554 8           void* SPVM_API_new_object_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
555 8           *error_id = 0;
556            
557 8           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
558 8 100         if (!basic_type) {
559 2           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
560 2           *error_id = 1;
561 2           return NULL;
562             };
563            
564 6           void* object = SPVM_API_new_object(env, stack, basic_type);
565            
566 6           return object;
567             }
568              
569 233432           SPVM_OBJECT* SPVM_API_new_pointer_object_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, void* pointer, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
570 233432           *error_id = 0;
571            
572 233432           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
573 233432 100         if (!basic_type) {
574 2           *error_id = 1;
575 2           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
576 2           return NULL;
577             };
578 233430           SPVM_OBJECT* object = SPVM_API_new_pointer_object(env, stack, basic_type, pointer);
579            
580 233430           return object;
581             }
582              
583 0           SPVM_OBJECT* SPVM_API_new_object_array_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t length, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
584 0           *error_id = 0;
585            
586 0           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
587 0 0         if (!basic_type) {
588 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
589 0           *error_id = 1;
590 0           return NULL;
591             };
592            
593 0           void* object = SPVM_API_new_object_array(env, stack, basic_type, length);
594            
595 0           return object;
596             }
597              
598 0           SPVM_OBJECT* SPVM_API_new_muldim_array_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t length, int32_t* error_id, const char* func_name, const char* file, int32_t line) { *error_id = 0;
599            
600 0           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
601 0 0         if (!basic_type) {
602 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
603 0           *error_id = 1;
604 0           return NULL;
605             };
606            
607 0           void* object = SPVM_API_new_muldim_array(env, stack, basic_type, type_dimension, length);
608            
609 0           return object;
610             }
611              
612 0           SPVM_OBJECT* SPVM_API_new_mulnum_array_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t length, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
613 0           *error_id = 0;
614            
615 0           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
616 0 0         if (!basic_type) {
617 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
618 0           *error_id = 1;
619 0           return NULL;
620             };
621            
622 0           void* object = SPVM_API_new_mulnum_array(env, stack, basic_type, length);
623            
624 0           return object;
625             }
626              
627 28           int8_t SPVM_API_get_class_var_byte(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
628            
629 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
630            
631 28 50         assert(basic_type);
632            
633 28           int32_t class_vars_length = basic_type->class_vars_length;
634            
635 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
636            
637 28           int8_t value = class_var->data.bval;
638            
639 28           return value;
640             }
641              
642 28           int16_t SPVM_API_get_class_var_short(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
643            
644 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
645            
646 28 50         assert(basic_type);
647            
648 28           int32_t class_vars_length = basic_type->class_vars_length;
649            
650 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
651            
652 28           int16_t value = class_var->data.sval;
653            
654 28           return value;
655             }
656              
657 96           int32_t SPVM_API_get_class_var_int(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
658            
659 96           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
660            
661 96 50         assert(basic_type);
662            
663 96           int32_t class_vars_length = basic_type->class_vars_length;
664            
665 96 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
666            
667 96           int32_t value = class_var->data.ival;
668            
669 96           return value;
670             }
671              
672 36           int64_t SPVM_API_get_class_var_long(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
673            
674 36           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
675            
676            
677 36 50         assert(basic_type);
678            
679 36           int32_t class_vars_length = basic_type->class_vars_length;
680            
681 36 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
682            
683 36           int64_t value = class_var->data.lval;
684            
685 36           return value;
686             }
687              
688 28           float SPVM_API_get_class_var_float(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
689            
690 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
691            
692 28 50         assert(basic_type);
693            
694 28           int32_t class_vars_length = basic_type->class_vars_length;
695            
696 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
697            
698 28           float value = class_var->data.fval;
699            
700 28           return value;
701             }
702              
703 28           double SPVM_API_get_class_var_double(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
704            
705 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
706            
707 28 50         assert(basic_type);
708            
709 28           int32_t class_vars_length = basic_type->class_vars_length;
710            
711 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
712            
713 28           double value = class_var->data.dval;
714            
715 28           return value;
716             }
717              
718 754           SPVM_OBJECT* SPVM_API_get_class_var_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
719            
720 754           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
721            
722 754 50         assert(basic_type);
723            
724 754           int32_t class_vars_length = basic_type->class_vars_length;
725            
726 754 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
727            
728 754           SPVM_OBJECT* value_maybe_weaken = (SPVM_OBJECT*)class_var->data.oval;
729 754           SPVM_OBJECT* value = SPVM_API_get_object_no_weaken_address(env, stack, value_maybe_weaken);
730            
731 754           return value;
732             }
733              
734 678           SPVM_OBJECT** SPVM_API_get_class_var_object_ref(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
735            
736 678           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
737            
738 678 50         assert(basic_type);
739            
740 678           int32_t class_vars_length = basic_type->class_vars_length;
741            
742 678 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
743            
744 678           SPVM_OBJECT** object_ref = (SPVM_OBJECT**)&class_var->data.oval;
745            
746 678           return object_ref;
747             }
748              
749 0           SPVM_OBJECT* SPVM_API_get_class_var_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var) {
750            
751 0           return SPVM_API_get_class_var_object(env, stack, class_var);
752             }
753              
754 28           void SPVM_API_set_class_var_byte(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, int8_t value) {
755            
756 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
757            
758 28 50         assert(basic_type);
759            
760 28           int32_t class_vars_length = basic_type->class_vars_length;
761            
762 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
763            
764 28           class_var->data.bval = value;
765 28           }
766              
767 28           void SPVM_API_set_class_var_short(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, int16_t value) {
768            
769 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
770            
771 28 50         assert(basic_type);
772            
773 28           int32_t class_vars_length = basic_type->class_vars_length;
774            
775 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
776            
777 28           class_var->data.sval = value;
778 28           }
779              
780 92           void SPVM_API_set_class_var_int(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, int32_t value) {
781            
782 92           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
783            
784 92 50         assert(basic_type);
785            
786 92           int32_t class_vars_length = basic_type->class_vars_length;
787            
788 92 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
789            
790 92           class_var->data.ival = value;
791 92           }
792              
793 368           void SPVM_API_set_class_var_long(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, int64_t value) {
794            
795 368           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
796            
797 368 50         assert(basic_type);
798            
799 368           int32_t class_vars_length = basic_type->class_vars_length;
800            
801 368 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
802            
803 368           class_var->data.lval = value;
804 368           }
805              
806 28           void SPVM_API_set_class_var_float(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, float value) {
807            
808 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
809            
810 28 50         assert(basic_type);
811            
812 28           int32_t class_vars_length = basic_type->class_vars_length;
813            
814 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
815            
816 28           class_var->data.fval = value;
817 28           }
818              
819 28           void SPVM_API_set_class_var_double(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, double value) {
820            
821 28           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
822            
823 28 50         assert(basic_type);
824            
825 28           int32_t class_vars_length = basic_type->class_vars_length;
826            
827 28 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
828            
829 28           class_var->data.dval = value;
830 28           }
831              
832 674           void SPVM_API_set_class_var_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, SPVM_OBJECT* value) {
833            
834 674           SPVM_RUNTIME_BASIC_TYPE* basic_type = class_var->current_basic_type;
835            
836 674 50         assert(basic_type);
837            
838 674           int32_t class_vars_length = basic_type->class_vars_length;
839            
840 674 50         assert(class_var->index >= 0 && class_var->index < class_vars_length);
    50          
841            
842 674           void* object_ref = &class_var->data.oval;
843 674           SPVM_API_assign_object(env, stack, object_ref, value);
844 674           }
845              
846 0           void SPVM_API_set_class_var_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_CLASS_VAR* class_var, SPVM_OBJECT* value) {
847            
848 0           SPVM_API_set_class_var_object(env, stack, class_var, value);
849 0           }
850              
851 4           int8_t SPVM_API_get_class_var_byte_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
852 4           *error_id = 0;
853            
854 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
855 4 50         if (!basic_type) {
856 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
857 0           *error_id = 1;
858 0           return 0;
859             }
860            
861 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
862 4 100         if (!class_var) {
863 2           *error_id = 1;
864 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
865 2           return 0;
866             };
867            
868 2           int8_t value = SPVM_API_get_class_var_byte(env, stack, class_var);
869 2           return value;
870             }
871              
872 4           int16_t SPVM_API_get_class_var_short_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
873 4           *error_id = 0;
874            
875 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
876 4 50         if (!basic_type) {
877 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
878 0           *error_id = 1;
879 0           return 0;
880             }
881            
882 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
883 4 100         if (!class_var) {
884 2           *error_id = 1;
885 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
886 2           return 0;
887             };
888            
889 2           int16_t value = SPVM_API_get_class_var_short(env, stack, class_var);
890 2           return value;
891             }
892              
893 4           int32_t SPVM_API_get_class_var_int_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
894 4           *error_id = 0;
895            
896 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
897 4 50         if (!basic_type) {
898 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
899 0           *error_id = 1;
900 0           return 0;
901             }
902            
903 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
904 4 100         if (!class_var) {
905 2           *error_id = 1;
906 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
907 2           return 0;
908             };
909            
910 2           int32_t value = SPVM_API_get_class_var_int(env, stack, class_var);
911 2           return value;
912             }
913              
914 4           int64_t SPVM_API_get_class_var_long_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
915 4           *error_id = 0;
916            
917 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
918 4 50         if (!basic_type) {
919 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
920 0           *error_id = 1;
921 0           return 0;
922             }
923            
924 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
925 4 100         if (!class_var) {
926 2           *error_id = 1;
927 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
928 2           return 0;
929             };
930            
931 2           int64_t value = SPVM_API_get_class_var_long(env, stack, class_var);
932 2           return value;
933             }
934              
935 4           float SPVM_API_get_class_var_float_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
936 4           *error_id = 0;
937            
938 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
939 4 50         if (!basic_type) {
940 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
941 0           *error_id = 1;
942 0           return 0;
943             }
944            
945 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
946 4 100         if (!class_var) {
947 2           *error_id = 1;
948 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
949 2           return 0;
950             };
951            
952 2           float value = SPVM_API_get_class_var_float(env, stack, class_var);
953 2           return value;
954             }
955              
956 4           double SPVM_API_get_class_var_double_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
957 4           *error_id = 0;
958            
959 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
960 4 50         if (!basic_type) {
961 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
962 0           *error_id = 1;
963 0           return 0;
964             }
965            
966 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
967 4 100         if (!class_var) {
968 2           *error_id = 1;
969 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
970 2           return 0;
971             };
972            
973 2           double value = SPVM_API_get_class_var_double(env, stack, class_var);
974 2           return value;
975             }
976              
977 4           SPVM_OBJECT* SPVM_API_get_class_var_object_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
978 4           *error_id = 0;
979            
980 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
981 4 50         if (!basic_type) {
982 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
983 0           *error_id = 1;
984 0           return 0;
985             }
986            
987 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
988 4 100         if (!class_var) {
989 2           *error_id = 1;
990 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
991 2           return 0;
992             };
993            
994 2           SPVM_OBJECT* value = SPVM_API_get_class_var_object(env, stack, class_var);
995 2           return value;
996             }
997              
998 0           SPVM_OBJECT* SPVM_API_get_class_var_string_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
999 0           *error_id = 0;
1000            
1001 0           return SPVM_API_get_class_var_object_by_name(env, stack, basic_type_name, class_var_name, error_id, func_name, file, line);
1002             }
1003              
1004 4           void SPVM_API_set_class_var_byte_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int8_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1005 4           *error_id = 0;
1006            
1007 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1008 4 50         if (!basic_type) {
1009 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1010 0           *error_id = 1;
1011 0           return;
1012             }
1013            
1014 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1015 4 100         if (!class_var) {
1016 2           *error_id = 1;
1017 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1018 2           return;
1019             };
1020            
1021 2           SPVM_API_set_class_var_byte(env, stack, class_var, value);
1022             }
1023              
1024 4           void SPVM_API_set_class_var_short_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int16_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1025 4           *error_id = 0;
1026            
1027 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1028 4 50         if (!basic_type) {
1029 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1030 0           *error_id = 1;
1031 0           return;
1032             }
1033            
1034 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1035 4 100         if (!class_var) {
1036 2           *error_id = 1;
1037 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1038 2           return;
1039             };
1040            
1041 2           SPVM_API_set_class_var_short(env, stack, class_var, value);
1042             }
1043              
1044 4           void SPVM_API_set_class_var_int_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1045 4           *error_id = 0;
1046            
1047 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1048 4 50         if (!basic_type) {
1049 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1050 0           *error_id = 1;
1051 0           return;
1052             }
1053            
1054 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1055 4 100         if (!class_var) {
1056 2           *error_id = 1;
1057 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1058 2           return;
1059             };
1060            
1061 2           SPVM_API_set_class_var_int(env, stack, class_var, value);
1062             }
1063              
1064 340           void SPVM_API_set_class_var_long_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int64_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1065 340           *error_id = 0;
1066            
1067 340           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1068 340 50         if (!basic_type) {
1069 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1070 0           *error_id = 1;
1071 0           return;
1072             }
1073            
1074 340           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1075 340 100         if (!class_var) {
1076 2           *error_id = 1;
1077 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1078 2           return;
1079             };
1080            
1081 338           SPVM_API_set_class_var_long(env, stack, class_var, value);
1082             }
1083              
1084 4           void SPVM_API_set_class_var_float_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, float value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1085 4           *error_id = 0;
1086            
1087 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1088 4 50         if (!basic_type) {
1089 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1090 0           *error_id = 1;
1091 0           return;
1092             }
1093            
1094 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1095 4 100         if (!class_var) {
1096 2           *error_id = 1;
1097 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1098 2           return;
1099             };
1100            
1101 2           SPVM_API_set_class_var_float(env, stack, class_var, value);
1102             }
1103              
1104 4           void SPVM_API_set_class_var_double_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, double value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1105 4           *error_id = 0;
1106            
1107 4           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1108 4 50         if (!basic_type) {
1109 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1110 0           *error_id = 1;
1111 0           return;
1112             }
1113            
1114 4           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1115 4 100         if (!class_var) {
1116 2           *error_id = 1;
1117 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1118 2           return;
1119             };
1120            
1121 2           SPVM_API_set_class_var_double(env, stack, class_var, value);
1122             }
1123              
1124 676           void SPVM_API_set_class_var_object_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, SPVM_OBJECT* value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1125 676           *error_id = 0;
1126            
1127 676           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
1128 676 50         if (!basic_type) {
1129 0           SPVM_API_die(env, stack, "The %s class is not found", basic_type_name, func_name, file, line);
1130 0           *error_id = 1;
1131 0           return;
1132             }
1133            
1134 676           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
1135 676 100         if (!class_var) {
1136 2           *error_id = 1;
1137 2           SPVM_API_die(env, stack, "The %s class variable in the %s class is not found", class_var_name, basic_type_name, func_name, file, line);
1138 2           return;
1139             };
1140            
1141 674           SPVM_API_set_class_var_object(env, stack, class_var, value);
1142             }
1143              
1144 0           void SPVM_API_set_class_var_string_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, SPVM_OBJECT* value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1145 0           SPVM_API_set_class_var_object_by_name(env, stack, basic_type_name, class_var_name, value, error_id, func_name, file, line);
1146 0           }
1147              
1148 700           int8_t SPVM_API_get_field_byte(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1149              
1150 700           int8_t value = *(int8_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1151              
1152 700           return value;
1153             }
1154              
1155 10           int16_t SPVM_API_get_field_short(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1156              
1157 10           int16_t value = *(int16_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1158            
1159 10           return value;
1160             }
1161              
1162 20           int32_t SPVM_API_get_field_int(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1163              
1164 20           int32_t value = *(int32_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1165            
1166 20           return value;
1167             }
1168              
1169 10           int64_t SPVM_API_get_field_long(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1170              
1171 10           int64_t value = *(int64_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1172            
1173 10           return value;
1174             }
1175              
1176 10           float SPVM_API_get_field_float(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1177              
1178 10           float value = *(float*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1179            
1180 10           return value;
1181             }
1182              
1183 10           double SPVM_API_get_field_double(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1184              
1185 10           double value = *(double*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1186            
1187 10           return value;
1188             }
1189              
1190 516927           SPVM_OBJECT* SPVM_API_get_field_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1191              
1192 516927           SPVM_OBJECT* value_maybe_weaken = *(SPVM_OBJECT**)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1193 516927           SPVM_OBJECT* value = SPVM_API_get_object_no_weaken_address(env, stack, value_maybe_weaken);
1194            
1195 516927           return value;
1196             }
1197              
1198 346           SPVM_OBJECT** SPVM_API_get_field_object_ref(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1199              
1200 346           SPVM_OBJECT** object_ref = (SPVM_OBJECT**)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1201            
1202 346           return object_ref;
1203             }
1204              
1205 2           SPVM_OBJECT* SPVM_API_get_field_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field) {
1206            
1207 2           SPVM_OBJECT* value = SPVM_API_get_field_object(env, stack, object, field);
1208            
1209 2           return value;
1210             }
1211              
1212 14           void SPVM_API_set_field_byte(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, int8_t value) {
1213              
1214             // Get field value
1215 14           *(int8_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset) = value;
1216 14           }
1217              
1218 2           void SPVM_API_set_field_short(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, int16_t value) {
1219              
1220             // Get field value
1221 2           *(int16_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset) = value;
1222 2           }
1223              
1224 6           void SPVM_API_set_field_int(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, int32_t value) {
1225              
1226             // Get field value
1227 6           *(int32_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset) = value;
1228 6           }
1229              
1230 2           void SPVM_API_set_field_long(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, int64_t value) {
1231              
1232             // Get field value
1233 2           *(int64_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset) = value;
1234 2           }
1235              
1236 2           void SPVM_API_set_field_float(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, float value) {
1237              
1238             // Get field value
1239 2           *(float*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset) = value;
1240 2           }
1241              
1242 2           void SPVM_API_set_field_double(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, double value) {
1243              
1244             // Get field value
1245 2           *(double*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset) = value;
1246 2           }
1247              
1248 233692           void SPVM_API_set_field_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, SPVM_OBJECT* value) {
1249              
1250             // Get field value
1251 233692           void* object_ref = (void**)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
1252              
1253 233692           SPVM_API_assign_object(env, stack, object_ref, value);
1254 233692           }
1255              
1256 0           void SPVM_API_set_field_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_FIELD* field, SPVM_OBJECT* value) {
1257            
1258 0           SPVM_API_set_field_object(env, stack, object, field, value);
1259 0           }
1260              
1261 702           int8_t SPVM_API_get_field_byte_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1262 702           *error_id = 0;
1263            
1264 702 50         if (object == NULL) {
1265 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1266 0           return 0;
1267             };
1268            
1269 702 50         if (object->type_dimension > 0) {
1270 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1271 0           return 0;
1272             };
1273            
1274 702           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1275 702 100         if (!field) {
1276 2           *error_id = 1;
1277 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1278 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1279 2           return 0;
1280             };
1281 700           int8_t value = SPVM_API_get_field_byte(env, stack, object, field);
1282 700           return value;
1283             }
1284              
1285 12           int16_t SPVM_API_get_field_short_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1286 12           *error_id = 0;
1287            
1288 12 50         if (object == NULL) {
1289 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1290 0           return 0;
1291             };
1292            
1293 12 50         if (object->type_dimension > 0) {
1294 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1295 0           return 0;
1296             };
1297            
1298 12           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1299 12 100         if (!field) {
1300 2           *error_id = 1;
1301 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1302 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1303 2           return 0;
1304             };
1305 10           int16_t value = SPVM_API_get_field_short(env, stack, object, field);
1306 10           return value;
1307             }
1308              
1309 20           int32_t SPVM_API_get_field_int_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1310 20           *error_id = 0;
1311            
1312 20 50         if (object == NULL) {
1313 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1314 0           return 0;
1315             };
1316            
1317 20 50         if (object->type_dimension > 0) {
1318 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1319 0           return 0;
1320             };
1321            
1322 20           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1323 20 100         if (!field) {
1324 2           *error_id = 1;
1325 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1326 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1327 2           return 0;
1328             };
1329 18           int32_t value = SPVM_API_get_field_int(env, stack, object, field);
1330 18           return value;
1331             }
1332              
1333 12           int64_t SPVM_API_get_field_long_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1334 12           *error_id = 0;
1335            
1336 12 50         if (object == NULL) {
1337 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1338 0           return 0;
1339             };
1340            
1341 12 50         if (object->type_dimension > 0) {
1342 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1343 0           return 0;
1344             };
1345            
1346 12           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1347 12 100         if (!field) {
1348 2           *error_id = 1;
1349 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1350 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1351 2           return 0;
1352             };
1353 10           int64_t value = SPVM_API_get_field_long(env, stack, object, field);
1354 10           return value;
1355             }
1356              
1357 12           float SPVM_API_get_field_float_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1358 12           *error_id = 0;
1359            
1360 12 50         if (object == NULL) {
1361 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1362 0           return 0;
1363             };
1364            
1365 12 50         if (object->type_dimension > 0) {
1366 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1367 0           return 0;
1368             };
1369            
1370 12           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1371 12 100         if (!field) {
1372 2           *error_id = 1;
1373 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1374 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1375 2           return 0;
1376             };
1377 10           float value = SPVM_API_get_field_float(env, stack, object, field);
1378 10           return value;
1379             }
1380              
1381 12           double SPVM_API_get_field_double_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1382 12           *error_id = 0;
1383            
1384 12 50         if (object == NULL) {
1385 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1386 0           return 0;
1387             };
1388            
1389 12 50         if (object->type_dimension > 0) {
1390 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1391 0           return 0;
1392             };
1393            
1394 12           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1395 12 100         if (!field) {
1396 2           *error_id = 1;
1397 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1398 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1399 2           return 0;
1400             };
1401 10           double value = SPVM_API_get_field_double(env, stack, object, field);
1402 10           return value;
1403             }
1404              
1405 516927           SPVM_OBJECT* SPVM_API_get_field_object_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1406 516927           *error_id = 0;
1407            
1408 516927 50         if (object == NULL) {
1409 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1410 0           return NULL;
1411             };
1412            
1413 516927 50         if (object->type_dimension > 0) {
1414 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1415 0           return NULL;
1416             };
1417            
1418 516927           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1419 516927 100         if (!field) {
1420 2           *error_id = 1;
1421 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1422 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1423 2           return NULL;
1424             };
1425 516925           SPVM_OBJECT* value = SPVM_API_get_field_object(env, stack, object, field);
1426 516925           return value;
1427             }
1428              
1429 346           SPVM_OBJECT** SPVM_API_get_field_object_ref_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1430 346           *error_id = 0;
1431            
1432 346 50         if (object == NULL) {
1433 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1434 0           return NULL;
1435             };
1436            
1437 346 50         if (object->type_dimension > 0) {
1438 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1439 0           return NULL;
1440             };
1441            
1442 346           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1443 346 50         if (!field) {
1444 0           *error_id = 1;
1445 0           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1446 0           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1447 0           return NULL;
1448             };
1449 346           SPVM_OBJECT** object_ref = SPVM_API_get_field_object_ref(env, stack, object, field);
1450 346           return object_ref;
1451             }
1452              
1453 256439           SPVM_OBJECT* SPVM_API_get_field_object_defined_and_has_pointer_by_name(SPVM_ENV* env, SPVM_VALUE* stack, void* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file_name, int32_t line) {
1454            
1455 256439           *error_id = 0;
1456            
1457 256439           void* obj_runtime = env->get_field_object_by_name(env, stack, object, field_name, error_id, func_name, file_name, line);
1458            
1459 256439 50         if (*error_id) { return NULL; }
1460            
1461 256439 50         if (!obj_runtime) {
1462 0           *error_id = env->die(env, stack, "The %s field must be defined.", field_name, func_name, file_name, line);
1463 0           return NULL;
1464             }
1465            
1466 256439           void* runtime = env->get_pointer(env, stack, obj_runtime);
1467            
1468 256439 50         if (!runtime) {
1469 0           *error_id = env->die(env, stack, "The pointer of the %s field must be defined.", field_name, func_name, file_name, line);
1470 0           return NULL;
1471             }
1472            
1473 256439           return obj_runtime;
1474             }
1475              
1476 0           SPVM_OBJECT* SPVM_API_get_field_string_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1477            
1478 0           return SPVM_API_get_field_object_by_name(env, stack, object, field_name, error_id, func_name, file, line);
1479             }
1480              
1481 4           const char* SPVM_API_get_field_string_chars_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1482 4           *error_id = 0;
1483            
1484 4           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1485 4 100         if (!field) {
1486 2           *error_id = 1;
1487 2           SPVM_API_die(env, stack, "The %s field is not found", field_name, func_name, file, line);
1488 2           return NULL;
1489             };
1490 2           SPVM_OBJECT* value = SPVM_API_get_field_string(env, stack, object, field);
1491 2 50         if (value == NULL) {
1492 0           return NULL;
1493             }
1494             else {
1495 2           const char* chars = SPVM_API_get_chars(env, stack, value);
1496 2           return chars;
1497             }
1498             }
1499              
1500 16           void SPVM_API_set_field_byte_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int8_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1501 16           *error_id = 0;
1502            
1503 16 50         if (object == NULL) {
1504 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1505 0           return;
1506             };
1507            
1508 16 50         if (object->type_dimension > 0) {
1509 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1510 0           return;
1511             };
1512            
1513 16           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1514 16 100         if (!field) {
1515 2           *error_id = 1;
1516 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1517 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1518 2           return;
1519             }
1520 14           SPVM_API_set_field_byte(env, stack, object, field, value);
1521             }
1522              
1523 4           void SPVM_API_set_field_short_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int16_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1524 4           *error_id = 0;
1525            
1526 4 50         if (object == NULL) {
1527 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1528 0           return;
1529             };
1530            
1531 4 50         if (object->type_dimension > 0) {
1532 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1533 0           return;
1534             };
1535            
1536 4           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1537 4 100         if (!field) {
1538 2           *error_id = 1;
1539 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1540 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1541 2           return;
1542             };
1543 2           SPVM_API_set_field_short(env, stack, object, field, value);
1544             }
1545              
1546 4           void SPVM_API_set_field_int_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int32_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1547 4           *error_id = 0;
1548            
1549 4 50         if (object == NULL) {
1550 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1551 0           return;
1552             };
1553            
1554 4 50         if (object->type_dimension > 0) {
1555 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1556 0           return;
1557             };
1558            
1559 4           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1560 4 100         if (!field) {
1561 2           *error_id = 1;
1562 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1563 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1564 2           return;
1565             };
1566 2           SPVM_API_set_field_int(env, stack, object, field, value);
1567             }
1568              
1569 4           void SPVM_API_set_field_long_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, int64_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1570 4           *error_id = 0;
1571            
1572 4 50         if (object == NULL) {
1573 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1574 0           return;
1575             };
1576            
1577 4 50         if (object->type_dimension > 0) {
1578 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1579 0           return;
1580             };
1581            
1582 4           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1583 4 100         if (!field) {
1584 2           *error_id = 1;
1585 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1586 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1587 2           return;
1588             };
1589 2           SPVM_API_set_field_long(env, stack, object, field, value);
1590             }
1591              
1592 4           void SPVM_API_set_field_float_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, float value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1593 4           *error_id = 0;
1594 4 50         if (object == NULL) {
1595 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1596 0           return;
1597             };
1598            
1599 4 50         if (object->type_dimension > 0) {
1600 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1601 0           return;
1602             };
1603            
1604 4           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1605 4 100         if (!field) {
1606 2           *error_id = 1;
1607 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1608 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1609 2           return;
1610             };
1611 2           SPVM_API_set_field_float(env, stack, object, field, value);
1612             }
1613              
1614 4           void SPVM_API_set_field_double_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, double value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1615 4           *error_id = 0;
1616            
1617 4 50         if (object == NULL) {
1618 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1619 0           return;
1620             };
1621            
1622 4 50         if (object->type_dimension > 0) {
1623 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1624 0           return;
1625             };
1626            
1627 4           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1628 4 100         if (!field) {
1629 2           *error_id = 1;
1630 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1631 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1632 2           return;
1633             };
1634 2           SPVM_API_set_field_double(env, stack, object, field, value);
1635             }
1636              
1637 233694           void SPVM_API_set_field_object_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, SPVM_OBJECT* value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1638 233694           *error_id = 0;
1639            
1640 233694 50         if (object == NULL) {
1641 0           SPVM_API_die(env, stack, "The object must be defined", func_name, file, line);
1642 0           return;
1643             };
1644            
1645 233694 50         if (object->type_dimension > 0) {
1646 0           SPVM_API_die(env, stack, "The type dimension of the object must be equal to 0", func_name, file, line);
1647 0           return;
1648             };
1649            
1650 233694           SPVM_RUNTIME_FIELD* field = SPVM_API_get_field(env, stack, object, field_name);
1651 233694 100         if (!field) {
1652 2           *error_id = 1;
1653 2           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
1654 2           SPVM_API_die(env, stack, "The %s field is not found in the %s class or its super class", field_name, basic_type_name, func_name, file, line);
1655 2           return;
1656             };
1657 233692           SPVM_API_set_field_object(env, stack, object, field, value);
1658             }
1659              
1660 0           void SPVM_API_set_field_string_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name, SPVM_OBJECT* value, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
1661 0           SPVM_API_set_field_object_by_name(env, stack, object, field_name, value, error_id, func_name, file, line);
1662 0           }
1663              
1664 316           int32_t SPVM_API_die(SPVM_ENV* env, SPVM_VALUE* stack, const char* message, ...) {
1665            
1666             va_list args;
1667            
1668 316           char* message_with_line = (char*)SPVM_API_new_memory_block(env, stack, 512);
1669 316           int32_t message_length = strlen(message);
1670 316 50         if (message_length > 255) {
1671 0           message_length = 255;
1672             }
1673 316           memcpy(message_with_line, message, message_length);
1674 316           const char* place = "\n %s at %s line %d";
1675 316           memcpy(message_with_line + message_length, place, strlen(place));
1676              
1677 316           char* buffer = (char*)SPVM_API_new_memory_block(env, stack, 512);
1678 316           va_start(args, message);
1679 316           vsnprintf(buffer, 511, message_with_line, args);
1680 316           va_end(args);
1681            
1682 316           void* exception = SPVM_API_new_string_no_mortal(env, stack, buffer, strlen(buffer));
1683            
1684 316           SPVM_API_free_memory_block(env, stack, message_with_line);
1685 316           message_with_line = NULL;
1686            
1687 316           SPVM_API_free_memory_block(env, stack, buffer);
1688 316           buffer = NULL;
1689            
1690 316           SPVM_API_set_exception(env, stack, exception);
1691            
1692 316           return SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_CLASS;
1693             }
1694              
1695 682           SPVM_VALUE* SPVM_API_new_stack(SPVM_ENV* env) {
1696            
1697 682           SPVM_RUNTIME* runtime = env->runtime;
1698            
1699             // Arguments and return values : 0-255
1700             // Stack local varialbe : 256-511
1701             // Exception message 511
1702             // Mortal stack 510
1703             // Motal stack top 509
1704             // Motal stack capacity 508
1705            
1706 682           SPVM_VALUE* stack = SPVM_ALLOCATOR_alloc_memory_block_tmp(runtime->allocator, sizeof(SPVM_VALUE) * 512);
1707            
1708 682           int32_t native_mortal_stack_capacity = 1;
1709 682           void* native_mortal_stack = SPVM_API_new_memory_block(env, stack, sizeof(SPVM_OBJECT*) * native_mortal_stack_capacity);
1710 682 50         if (native_mortal_stack == NULL) {
1711 0           return NULL;
1712             }
1713 682           stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_CAPACITY].ival = native_mortal_stack_capacity;
1714 682           stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK].oval = native_mortal_stack;
1715 682           stack[SPVM_API_C_STACK_INDEX_ENV].oval = env;
1716            
1717 682           return stack;
1718             }
1719              
1720 682           void SPVM_API_free_stack(SPVM_ENV* env, SPVM_VALUE* stack) {
1721            
1722 682           SPVM_RUNTIME* runtime = env->runtime;
1723            
1724 682           SPVM_API_set_exception(env, stack, NULL);
1725            
1726 682           SPVM_OBJECT** mortal_stack = stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK].oval;
1727            
1728 682 50         if (mortal_stack != NULL) {
1729 682           SPVM_API_free_memory_block(env, stack, mortal_stack);
1730 682           mortal_stack = NULL;
1731             }
1732            
1733 682           SPVM_ALLOCATOR_free_memory_block_tmp(runtime->allocator, stack);
1734 682           stack = NULL;
1735 682           }
1736              
1737 2843425           int32_t SPVM_API_call_method_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_METHOD* method, int32_t args_width) {
1738            
1739 2843425           int32_t mortal = 0;
1740 2843425           int32_t error_id = SPVM_API_call_method_common(env, stack, method, args_width, mortal);
1741            
1742 2843425           return error_id;
1743             }
1744              
1745 62           int32_t SPVM_API_call_method(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_METHOD* method, int32_t args_width) {
1746            
1747 62           int32_t mortal = 1;
1748 62           int32_t error_id = SPVM_API_call_method_common(env, stack, method, args_width, mortal);
1749            
1750 62           return error_id;
1751             }
1752              
1753 8           int32_t SPVM_API_is_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1754            
1755             int32_t is_array;
1756 8 100         if (object) {
1757 6           is_array = object->type_dimension > 0;
1758             }
1759             else {
1760 2           is_array = 0;
1761             }
1762            
1763 8           return is_array;
1764             }
1765              
1766 14348           int32_t SPVM_API_is_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1767            
1768             int32_t is_string;
1769 14348 50         if (object) {
1770 14348           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
1771 14348 100         is_string = (object_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_STRING && object->type_dimension == 0);
    100          
1772             }
1773             else {
1774 0           is_string = 0;
1775             }
1776            
1777 14348           return is_string;
1778             }
1779              
1780 270           int32_t SPVM_API_is_numeric_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1781              
1782 270           SPVM_RUNTIME* runtime = env->runtime;
1783            
1784             int32_t is_numeric_array;
1785 270 100         if (object) {
1786 268           int32_t object_type_dimension = object->type_dimension;
1787 268 100         if (object_type_dimension == 0) {
1788 6           is_numeric_array = 0;
1789             }
1790 262 100         else if (object_type_dimension == 1) {
1791 254           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
1792 254           int32_t object_basic_type_category = object_basic_type->category;
1793 254 100         switch (object_basic_type_category) {
1794             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC:
1795             {
1796 170           is_numeric_array = 1;
1797 170           break;
1798             }
1799             default: {
1800 254           is_numeric_array = 0;
1801             }
1802             }
1803             }
1804 8 50         else if (object_type_dimension > 1) {
1805 8           is_numeric_array = 0;
1806             }
1807             else {
1808 268           assert(0);
1809             }
1810             }
1811             else {
1812 2           is_numeric_array = 0;
1813             }
1814              
1815 270           return is_numeric_array;
1816             }
1817              
1818              
1819 591690           int32_t SPVM_API_is_object_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1820            
1821 591690           SPVM_RUNTIME* runtime = env->runtime;
1822              
1823             int32_t is_object_array;
1824 591690 100         if (object) {
1825 591688           int32_t object_type_dimension = object->type_dimension;
1826 591688 100         if (object_type_dimension == 0) {
1827 460112           is_object_array = 0;
1828             }
1829 131576 100         else if (object_type_dimension == 1) {
1830 131482           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
1831 131482           int32_t element_type_dimension = 0;
1832 131482           int32_t type_flag = 0;
1833 131482           is_object_array = SPVM_API_TYPE_is_object_type(env->runtime, object_basic_type, element_type_dimension, type_flag);
1834             }
1835 94 50         else if (object_type_dimension > 1) {
1836 94           is_object_array = 1;
1837             }
1838             else {
1839 591688           assert(0);
1840             }
1841             }
1842             else {
1843 2           is_object_array = 0;
1844             }
1845            
1846 591690           return is_object_array;
1847             }
1848              
1849 21026           int32_t SPVM_API_is_mulnum_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1850              
1851 21026           SPVM_RUNTIME* runtime = env->runtime;
1852              
1853             int32_t is_mulnum_array;
1854 21026 100         if (object) {
1855 21024           int32_t object_type_dimension = object->type_dimension;
1856 21024 100         if (object_type_dimension == 0) {
1857 6           is_mulnum_array = 0;
1858             }
1859 21018 100         else if (object_type_dimension == 1) {
1860 20994           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
1861 20994           int32_t object_basic_type_category = object_basic_type->category;
1862 20994 100         switch (object_basic_type_category) {
1863             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM:
1864             {
1865 100           is_mulnum_array = 1;
1866 100           break;
1867             }
1868             default: {
1869 20994           is_mulnum_array = 0;
1870             }
1871             }
1872             }
1873 24 50         else if (object_type_dimension > 1) {
1874 24           is_mulnum_array = 0;
1875             }
1876             else {
1877 21024           assert(0);
1878             }
1879             }
1880             else {
1881 2           is_mulnum_array = 0;
1882             }
1883              
1884 21026           return is_mulnum_array;
1885             }
1886              
1887 10           int32_t SPVM_API_is_class(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1888            
1889 10           SPVM_RUNTIME* runtime = env->runtime;
1890              
1891             int32_t is_class;
1892 10 100         if (object) {
1893 8           int32_t object_type_dimension = object->type_dimension;
1894 8 100         if (object_type_dimension == 0) {
1895 6           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
1896 6           int32_t object_basic_type_category = object_basic_type->category;
1897            
1898 6 100         switch (object_basic_type_category) {
1899             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS: {
1900 4           is_class = 1;
1901 4           break;
1902             }
1903             default: {
1904 6           is_class = 0;
1905             }
1906             }
1907             }
1908             else {
1909 8           is_class = 0;
1910             }
1911             }
1912             else {
1913 2           is_class = 0;
1914             }
1915            
1916 10           return is_class;
1917             }
1918              
1919 12           int32_t SPVM_API_is_pointer_class(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
1920            
1921 12           SPVM_RUNTIME* runtime = env->runtime;
1922            
1923             int32_t is_pointer_class;
1924 12 100         if (object) {
1925 10           int32_t object_type_dimension = object->type_dimension;
1926 10 100         if (object_type_dimension == 0) {
1927 8           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
1928 8           int32_t object_basic_type_category = object_basic_type->category;
1929            
1930 8 100         switch (object_basic_type_category) {
1931             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS: {
1932 6           int32_t basic_type_is_pointer = object_basic_type->is_pointer;
1933            
1934 6 100         if (basic_type_is_pointer) {
1935 2           is_pointer_class = 1;
1936             }
1937             else {
1938 4           is_pointer_class = 0;
1939             }
1940 6           break;
1941             }
1942             default: {
1943 8           is_pointer_class = 0;
1944             }
1945             }
1946             }
1947             else {
1948 10           is_pointer_class = 0;
1949             }
1950             }
1951             else {
1952 2           is_pointer_class = 0;
1953             }
1954            
1955 12           return is_pointer_class;
1956             }
1957              
1958 6726           int32_t SPVM_API_get_elem_size(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array) {
1959            
1960 6726           SPVM_RUNTIME* runtime = env->runtime;
1961            
1962             int32_t elem_size;
1963 6726 50         if (array) {
1964 6726 100         if (SPVM_API_is_string(env, stack, array)) {
1965 6404           elem_size = 1;
1966             }
1967 322 100         else if (SPVM_API_is_object_array(env, stack, array)) {
1968 262           elem_size = sizeof(void*);
1969             }
1970 60 100         else if (SPVM_API_is_numeric_array(env, stack, array)) {
1971            
1972 48           SPVM_RUNTIME_BASIC_TYPE* array_basic_type = SPVM_API_get_object_basic_type(env, stack, array);
1973 48           int32_t type_dimension = array->type_dimension;
1974 48 50         assert(type_dimension == 1);
1975            
1976 48 100         if (array_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE) {
1977 28           elem_size = 1;
1978             }
1979 20 50         else if (array_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT) {
1980 0           elem_size = 2;
1981             }
1982 20 100         else if (array_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_INT || array_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT) {
    50          
1983 8           elem_size = 4;
1984             }
1985 12 50         else if (array_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_LONG || array_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE) {
    50          
1986 12           elem_size = 8;
1987             }
1988             else {
1989 48           assert(0);
1990             }
1991             }
1992 12 50         else if (SPVM_API_is_mulnum_array(env, stack, array)) {
1993 12           SPVM_RUNTIME_BASIC_TYPE* array_basic_type = SPVM_API_get_object_basic_type(env, stack, array);
1994 12           int32_t type_dimension = array->type_dimension;
1995 12 50         assert(type_dimension == 1);
1996            
1997 12           int32_t fields_length = array_basic_type->fields_length;
1998            
1999 12           SPVM_RUNTIME_FIELD* first_field = SPVM_API_BASIC_TYPE_get_field_by_index(runtime, array_basic_type, 0);
2000            
2001 12           int32_t field_basic_type_id = first_field->basic_type->id;
2002            
2003 12 50         if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE) {
2004 0           elem_size = 1 * fields_length;
2005             }
2006 12 50         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT) {
2007 0           elem_size = 2 * fields_length;
2008             }
2009 12 50         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_INT || field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT) {
    50          
2010 0           elem_size = 4 * fields_length;
2011             }
2012 12 50         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_LONG || field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE) {
    50          
2013 12           elem_size = 8 * fields_length;
2014             }
2015             else {
2016 6726           assert(0);
2017             }
2018             }
2019             }
2020             else {
2021 0           elem_size = 0;
2022             }
2023            
2024 6726           return elem_size;
2025             }
2026              
2027 1362921           int32_t SPVM_API_enter_scope(SPVM_ENV* env, SPVM_VALUE* stack){
2028            
2029              
2030 1362921           SPVM_OBJECT*** current_mortal_stack_ptr = (SPVM_OBJECT***)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK];
2031 1362921           int32_t* current_mortal_stack_top_ptr = (int32_t*)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_TOP];
2032 1362921           int32_t* current_mortal_stack_capacity_ptr = (int32_t*)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_CAPACITY];
2033            
2034 1362921           int32_t mortal_stack_top = *current_mortal_stack_top_ptr ;
2035            
2036 1362921           return mortal_stack_top;
2037             }
2038              
2039 108           SPVM_OBJECT* SPVM_API_get_type_name_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
2040            
2041            
2042 108 50         assert(object);
2043            
2044 108           SPVM_RUNTIME* runtime = env->runtime;
2045            
2046 108           const char* basic_type_name = SPVM_API_get_object_basic_type_name(env, stack, object);
2047 108           int32_t type_dimension = object->type_dimension;
2048            
2049 108           int32_t length = 0;
2050            
2051             // Basic type
2052 108           length += strlen(basic_type_name);
2053            
2054             //[]
2055 108           length += type_dimension * 2;
2056            
2057 108           void* obj_type_name = SPVM_API_new_string_no_mortal(env, stack, NULL, length);
2058            
2059 108           char* type_name = (char*)SPVM_API_get_chars(env, stack, obj_type_name);
2060            
2061 108           int32_t type_name_index = 0;
2062 108           sprintf((char*)type_name, "%s", basic_type_name);
2063 108           type_name_index += strlen(basic_type_name);
2064            
2065             int32_t dim_index;
2066 204 100         for (dim_index = 0; dim_index < type_dimension; dim_index++) {
2067 96           sprintf((char*)(type_name + type_name_index), "[]");
2068 96           type_name_index += 2;
2069             }
2070            
2071 108           return obj_type_name;
2072             }
2073              
2074 0           SPVM_OBJECT* SPVM_API_get_type_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
2075            
2076            
2077 0           SPVM_OBJECT* obj_type_name = SPVM_API_get_type_name_no_mortal(env, stack, object);
2078            
2079 0           SPVM_API_push_mortal(env, stack, obj_type_name);
2080            
2081 0           return obj_type_name;
2082             }
2083              
2084 8           int32_t SPVM_API_get_compile_type_name_length(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t type_flag) {
2085            
2086 8           int32_t compile_type_name_length = 0;
2087            
2088             // mutable
2089 8 100         if (type_flag & SPVM_NATIVE_C_TYPE_FLAG_MUTABLE) {
2090 2           compile_type_name_length += strlen("mutable ");
2091             }
2092            
2093             // Basic type
2094 8           compile_type_name_length += strlen(basic_type_name);
2095            
2096             // []
2097 8           compile_type_name_length += type_dimension * 2;
2098            
2099             // *
2100 8 100         if (type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF) {
2101 2           compile_type_name_length += 1;
2102             }
2103            
2104 8           return compile_type_name_length;
2105             }
2106              
2107 8           SPVM_OBJECT* SPVM_API_get_compile_type_name_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t type_flag) {
2108            
2109 8           int32_t compile_type_name_length = SPVM_API_get_compile_type_name_length(env, stack, basic_type_name, type_dimension, type_flag);
2110            
2111 8           void* obj_compile_type_name = SPVM_API_new_string_no_mortal(env, stack, NULL, compile_type_name_length);
2112            
2113 8           char* compile_type_name = (char*)SPVM_API_get_chars(env, stack, obj_compile_type_name);
2114            
2115 8 100         if (type_flag & SPVM_NATIVE_C_TYPE_FLAG_MUTABLE) {
2116 2           sprintf(compile_type_name, "mutable ");
2117 2           compile_type_name += strlen("mutable ");
2118             }
2119            
2120 8           sprintf(compile_type_name, "%s", basic_type_name);
2121 8           compile_type_name += strlen(basic_type_name);
2122            
2123 12 100         for (int32_t type_dimension_index = 0; type_dimension_index < type_dimension; type_dimension_index++) {
2124 4           sprintf(compile_type_name, "[]");
2125 4           compile_type_name += 2;
2126             }
2127            
2128             // Reference
2129 8 100         if (type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF) {
2130 2           sprintf(compile_type_name, "*");
2131 2           compile_type_name += 1;
2132             }
2133            
2134 8           *compile_type_name = '\0';
2135 8           compile_type_name++;
2136            
2137 8           return obj_compile_type_name;
2138             }
2139              
2140 8           SPVM_OBJECT* SPVM_API_get_compile_type_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t type_flag) {
2141            
2142 8           SPVM_OBJECT* obj_compile_type_name = SPVM_API_get_compile_type_name_no_mortal(env, stack, basic_type_name, type_dimension, type_flag);
2143            
2144 8           SPVM_API_push_mortal(env, stack, obj_compile_type_name);
2145            
2146 8           return obj_compile_type_name;
2147             }
2148              
2149 2056           SPVM_OBJECT* SPVM_API_new_stack_trace_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* exception, SPVM_RUNTIME_METHOD* method, int32_t line) {
2150              
2151 2056 50         if (stack[SPVM_API_C_STACK_INDEX_CALL_DEPTH].ival > 100) {
2152 0           return exception;
2153             }
2154              
2155 2056           SPVM_RUNTIME* runtime = env->runtime;
2156              
2157 2056           SPVM_RUNTIME_BASIC_TYPE* basic_type = method->current_basic_type;
2158 2056           const char* basic_type_name = basic_type->name;
2159 2056           const char* method_name = method->name;
2160              
2161 2056           const char* class_dir = basic_type->class_dir;
2162             const char* class_dir_sep;
2163 2056 50         if (class_dir) {
2164 2056           class_dir_sep = "/";
2165             }
2166             else {
2167 0           class_dir = "";
2168 0           class_dir_sep = "";
2169             }
2170            
2171 2056           const char* class_rel_file = basic_type->class_rel_file;
2172            
2173             // Basic type name and method name
2174 2056           const char* new_line_part = "\n ";
2175 2056           const char* arrow_part = "->";
2176 2056           const char* at_part = " at ";
2177              
2178             // Exception
2179 2056           const char* exception_bytes = SPVM_API_get_chars(env, stack, exception);
2180 2056           int32_t exception_length = SPVM_API_length(env, stack, exception);
2181            
2182             // Total string length
2183 2056           int32_t total_length = 0;
2184 2056           total_length += exception_length;
2185 2056           total_length += strlen(new_line_part);
2186 2056           total_length += strlen(basic_type_name);
2187 2056           total_length += strlen(arrow_part);
2188 2056           total_length += strlen(method_name);
2189 2056           total_length += strlen(at_part);
2190 2056           total_length += strlen(class_dir);
2191 2056           total_length += strlen(class_dir_sep);
2192 2056           total_length += strlen(class_rel_file);
2193              
2194 2056           const char* line_part = " line ";
2195             char line_str[20];
2196            
2197 2056           sprintf(line_str, "%" PRId32, line);
2198 2056           total_length += strlen(line_part);
2199 2056           total_length += strlen(line_str);
2200            
2201             // Create exception message
2202 2056           void* new_exception = SPVM_API_new_string_no_mortal(env, stack, NULL, total_length);
2203 2056           const char* new_exception_bytes = SPVM_API_get_chars(env, stack, new_exception);
2204            
2205 2056           memcpy(
2206             (void*)(new_exception_bytes),
2207             (void*)(exception_bytes),
2208             exception_length
2209             );
2210              
2211 2056           sprintf(
2212             (char*)new_exception_bytes + exception_length,
2213             "%s%s%s%s%s%s%s%s%s%" PRId32,
2214             new_line_part,
2215             basic_type_name,
2216             arrow_part,
2217             method_name,
2218             at_part,
2219             class_dir,
2220             class_dir_sep,
2221             class_rel_file,
2222             line_part,
2223             line
2224             );
2225            
2226 2056           return new_exception;
2227             }
2228              
2229 0           SPVM_OBJECT* SPVM_API_new_stack_trace(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* exception, SPVM_RUNTIME_METHOD* method, int32_t line) {
2230            
2231            
2232 0           SPVM_OBJECT* stack_trace = SPVM_API_new_stack_trace_no_mortal(env, stack, exception, method, line);
2233            
2234 0           SPVM_API_push_mortal(env, stack, stack_trace);
2235            
2236 0           return stack_trace;
2237             }
2238              
2239 24           void SPVM_API_fprint(SPVM_ENV* env, SPVM_VALUE* stack, FILE* fh, SPVM_OBJECT* string) {
2240            
2241 24 100         if (string) {
2242 20           const char* bytes = SPVM_API_get_chars(env, stack, string);
2243 20           int32_t string_length = SPVM_API_length(env, stack, string);
2244            
2245 20 100         if (string_length > 0) {
2246 16           FILE* spvm_stdout = SPVM_API_RUNTIME_get_spvm_stdout(env->runtime);
2247 16           fwrite(bytes, 1, string_length, spvm_stdout);
2248             }
2249             }
2250 24           }
2251              
2252 14           void SPVM_API_print(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string) {
2253            
2254 14           SPVM_RUNTIME* runtime = env->runtime;
2255            
2256 14           SPVM_API_fprint(env, stack, runtime->spvm_stdout, string);
2257 14           }
2258              
2259 10           void SPVM_API_say(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string) {
2260            
2261 10           SPVM_RUNTIME* runtime = env->runtime;
2262            
2263 10           SPVM_API_fprint(env, stack, runtime->spvm_stdout, string);
2264            
2265 10           fputc('\n', runtime->spvm_stdout);
2266 10           }
2267              
2268 20           void SPVM_API_warn(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string, const char* class_dir, const char* class_rel_file, int32_t line) {
2269             const char* class_dir_sep;
2270 20 50         if (class_dir) {
2271 20           class_dir_sep = "/";
2272             }
2273             else {
2274 0           class_dir_sep = "";
2275 0           class_dir = "";
2276             }
2277            
2278 20           FILE* spvm_stderr = SPVM_API_RUNTIME_get_spvm_stderr(env->runtime);
2279            
2280 20           int32_t empty_or_undef = 0;
2281 20 100         if (string) {
2282 18           const char* bytes =SPVM_API_get_chars(env, stack, string);
2283 18           int32_t string_length = SPVM_API_length(env, stack, string);
2284            
2285 18 100         if (string_length > 0) {
2286 16           size_t ret = fwrite(bytes, 1, string_length, spvm_stderr);
2287            
2288             // Add line and file information if last character is not '\n'
2289             int32_t add_line_file;
2290 16 100         if (bytes[string_length - 1] != '\n') {
2291 16           fprintf(spvm_stderr, "\n at %s%s%s line %d\n", class_dir, class_dir_sep, class_rel_file, line);
2292             }
2293             }
2294             else {
2295 18           empty_or_undef = 1;
2296             }
2297             }
2298             else {
2299 2           empty_or_undef = 1;
2300             }
2301            
2302 20 100         if (empty_or_undef) {
2303 4           fprintf(spvm_stderr, "Warning\n at %s%s%s line %d\n", class_dir, class_dir_sep, class_rel_file, line);
2304             }
2305 20           }
2306              
2307 0           void SPVM_API_print_stderr(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string) {
2308            
2309 0           SPVM_RUNTIME* runtime = env->runtime;
2310            
2311 0           SPVM_API_fprint(env, stack, runtime->spvm_stderr, string);
2312 0           }
2313              
2314 1102           SPVM_OBJECT* SPVM_API_concat_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string1, SPVM_OBJECT* string2) {
2315            
2316 1102           int32_t string1_length = SPVM_API_length(env, stack, string1);
2317 1102           int32_t string2_length = SPVM_API_length(env, stack, string2);
2318            
2319 1102           int32_t string3_length = string1_length + string2_length;
2320 1102           SPVM_OBJECT* string3 = SPVM_API_new_string_no_mortal(env, stack, NULL, string3_length);
2321            
2322 1102           const char* string1_bytes = SPVM_API_get_chars(env, stack, string1);
2323 1102           const char* string2_bytes = SPVM_API_get_chars(env, stack, string2);
2324 1102           char* string3_bytes = (char*)SPVM_API_get_chars(env, stack, string3);
2325            
2326 1102 100         if (string1_length > 0) {
2327 982           memcpy(string3_bytes, string1_bytes, string1_length);
2328             }
2329 1102 100         if (string2_length) {
2330 910           memcpy(string3_bytes + string1_length, string2_bytes, string2_length);
2331             }
2332            
2333 1102           return string3;
2334             }
2335              
2336 0           SPVM_OBJECT* SPVM_API_concat(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string1, SPVM_OBJECT* string2) {
2337            
2338            
2339 0           SPVM_OBJECT* str = SPVM_API_concat_no_mortal(env, stack, string1, string2);
2340            
2341 0           SPVM_API_push_mortal(env, stack, str);
2342            
2343 0           return str;
2344             }
2345              
2346 2           SPVM_OBJECT* SPVM_API_dump(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
2347            
2348            
2349 2           SPVM_OBJECT* str = SPVM_API_dump_no_mortal(env, stack, object);
2350            
2351 2           SPVM_API_push_mortal(env, stack, str);
2352            
2353 2           return str;
2354             }
2355              
2356 68           SPVM_OBJECT* SPVM_API_dump_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
2357            
2358 68           SPVM_RUNTIME* runtime = env->runtime;
2359            
2360 68           int32_t depth = 0;
2361 68           SPVM_STRING_BUFFER* string_buffer = SPVM_STRING_BUFFER_new(runtime->allocator, 255, SPVM_ALLOCATOR_C_ALLOC_TYPE_TMP);
2362 68           SPVM_HASH* address_symtable = SPVM_HASH_new(runtime->allocator, 255, SPVM_ALLOCATOR_C_ALLOC_TYPE_TMP);
2363            
2364 68           SPVM_API_dump_recursive(env, stack, object, &depth, string_buffer, address_symtable);
2365            
2366 68           int32_t string_buffer_length = string_buffer->length;
2367            
2368 68           SPVM_OBJECT* dump = SPVM_API_new_string_no_mortal(env, stack, string_buffer->string, string_buffer->length);
2369            
2370 68           SPVM_HASH_free(address_symtable);
2371 68           address_symtable = NULL;
2372            
2373 68           SPVM_STRING_BUFFER_free(string_buffer);
2374 68           string_buffer = NULL;
2375            
2376 68           return dump;
2377             }
2378              
2379 2           const char* SPVM_API_dumpc(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
2380            
2381            
2382 2           SPVM_OBJECT* obj_dump = SPVM_API_dump(env, stack, object);
2383            
2384 2           const char* dump_chars = SPVM_API_get_chars(env, stack, obj_dump);
2385            
2386 2           return dump_chars;
2387             }
2388              
2389 168           void SPVM_API_dump_recursive(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, int32_t* depth, SPVM_STRING_BUFFER* string_buffer, SPVM_HASH* address_symtable) {
2390            
2391 168           SPVM_RUNTIME* runtime = env->runtime;
2392            
2393             char tmp_buffer[256];
2394            
2395             SPVM_OBJECT* dump;
2396 168 100         if (object == NULL) {
2397 36           SPVM_STRING_BUFFER_add(string_buffer, "undef");
2398             }
2399             else {
2400 132           int32_t type_dimension = object->type_dimension;
2401            
2402 132 100         if (SPVM_API_is_string(env, stack, object)) {
2403 28           const char* chars = SPVM_API_get_chars(env, stack, object);
2404 28           int32_t chars_length = SPVM_API_length(env, stack, object);
2405 28           SPVM_STRING_BUFFER_add(string_buffer, "\"");
2406 28           SPVM_STRING_BUFFER_add_len(string_buffer, (char*)chars, chars_length);
2407 28           SPVM_STRING_BUFFER_add(string_buffer, "\"");
2408             }
2409 104 100         else if (type_dimension > 0) {
2410 66           int32_t array_length = SPVM_API_length(env, stack, object);
2411 66           int32_t element_type_dimension = type_dimension - 1;
2412            
2413 66           SPVM_STRING_BUFFER_add(string_buffer, "[\n");
2414            
2415 66           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
2416 66           const char* object_basic_type_name = object_basic_type->name;
2417            
2418 216 100         for (int32_t array_index = 0; array_index < array_length; array_index++) {
2419            
2420 326 100         for (int32_t depth_index = 0; depth_index < *depth + 1; depth_index++) {
2421 176           SPVM_STRING_BUFFER_add(string_buffer, " ");
2422             }
2423            
2424 150 100         if (SPVM_API_is_mulnum_array(env, stack, object)) {
2425            
2426 32           SPVM_STRING_BUFFER_add(string_buffer, "{\n");
2427            
2428 32           int32_t fields_length = object_basic_type->fields_length;
2429            
2430 128 100         for (int32_t field_index = 0; field_index < fields_length; field_index++) {
2431 288 100         for (int32_t depth_index = 0; depth_index < *depth + 2; depth_index++) {
2432 192           SPVM_STRING_BUFFER_add(string_buffer, " ");
2433             }
2434            
2435 96           SPVM_RUNTIME_FIELD* field = SPVM_API_BASIC_TYPE_get_field_by_index(runtime, object_basic_type, field_index);
2436            
2437 96           int32_t field_basic_type_id = field->basic_type->id;
2438            
2439 96           const char* field_name = field->name;
2440 96           SPVM_STRING_BUFFER_add(string_buffer, field_name);
2441 96           SPVM_STRING_BUFFER_add(string_buffer, " => ");
2442            
2443 96           switch (field_basic_type_id) {
2444             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
2445 24           int8_t* element = &((int8_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index * fields_length];
2446 24           sprintf(tmp_buffer, "%d", element[field_index]);
2447 24           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2448 24           break;
2449             }
2450             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
2451 24           int16_t* element = &((int16_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index * fields_length];
2452 24           sprintf(tmp_buffer, "%d", element[field_index]);
2453 24           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2454 24           break;
2455             }
2456             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
2457 24           int32_t* element = &((int32_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index * fields_length];
2458 24           sprintf(tmp_buffer, "%d", element[field_index]);
2459 24           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2460 24           break;
2461             }
2462             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
2463 24           int64_t* element = &((int64_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index * fields_length];
2464 24           sprintf(tmp_buffer, "%lld", (long long int)element[field_index]);
2465 24           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2466 24           break;
2467             }
2468             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
2469 0           float* element = &((float*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index * fields_length];
2470 0           sprintf(tmp_buffer, "%g", element[field_index]);
2471 0           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2472 0           break;
2473             }
2474             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
2475 0           double* element = &((double*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index * fields_length];
2476 0           sprintf(tmp_buffer, "%g", element[field_index]);
2477 0           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2478 0           break;
2479             }
2480             }
2481            
2482 96 100         if (field_index == fields_length - 1) {
2483 32           SPVM_STRING_BUFFER_add(string_buffer, "\n");
2484             }
2485             else {
2486 64           SPVM_STRING_BUFFER_add(string_buffer, ",\n");
2487             }
2488             }
2489            
2490 32           SPVM_STRING_BUFFER_add(string_buffer, " }");
2491             }
2492 118 100         else if (SPVM_API_is_numeric_array(env, stack, object)) {
2493 54           switch (object_basic_type->id) {
2494             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
2495 8           int8_t element = ((int8_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index];
2496 8           sprintf(tmp_buffer, "%d", element);
2497 8           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2498 8           break;
2499             }
2500             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
2501 8           int16_t element = ((int16_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index];
2502 8           sprintf(tmp_buffer, "%d", element);
2503 8           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2504 8           break;
2505             }
2506             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
2507 14           int32_t element = ((int32_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index];
2508 14           sprintf(tmp_buffer, "%d", element);
2509 14           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2510 14           break;
2511             }
2512             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
2513 8           int64_t element = ((int64_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index];
2514 8           sprintf(tmp_buffer, "%lld", (long long int)element);
2515 8           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2516 8           break;
2517             }
2518             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
2519 8           float element = ((float*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index];
2520 8           sprintf(tmp_buffer, "%g", element);
2521 8           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2522 8           break;
2523             }
2524             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
2525 8           double element = ((double*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index];
2526 8           sprintf(tmp_buffer, "%g", element);
2527 8           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2528 54           break;
2529             }
2530             }
2531             }
2532 64 50         else if (SPVM_API_is_object_array(env, stack, object)) {
2533 64           SPVM_OBJECT* element = (((SPVM_OBJECT**)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[array_index]);
2534 64           element = SPVM_API_get_object_no_weaken_address(env, stack, element);
2535 64           (*depth)++;
2536 64           SPVM_API_dump_recursive(env, stack, element, depth, string_buffer, address_symtable);
2537 64           (*depth)--;
2538             }
2539             else {
2540 0           assert(0);
2541             }
2542            
2543 150 100         if (array_index == array_length - 1) {
2544 66           SPVM_STRING_BUFFER_add(string_buffer, "\n");
2545             }
2546             else {
2547 84           SPVM_STRING_BUFFER_add(string_buffer, ",\n");
2548             }
2549             }
2550            
2551 76 100         for (int32_t depth_index = 0; depth_index < *depth; depth_index++) {
2552 10           SPVM_STRING_BUFFER_add(string_buffer, " ");
2553             }
2554 66           SPVM_STRING_BUFFER_add(string_buffer, "]");
2555            
2556 66           SPVM_STRING_BUFFER_add(string_buffer, " : ");
2557 66           SPVM_STRING_BUFFER_add(string_buffer, object_basic_type_name);
2558 136 100         for (int32_t type_dimension_index = 0; type_dimension_index < type_dimension; type_dimension_index++) {
2559 70           SPVM_STRING_BUFFER_add(string_buffer, "[]");
2560             }
2561            
2562             // If the object is weaken, this get the real address
2563 66           sprintf(tmp_buffer, "(%p)", SPVM_API_get_object_no_weaken_address(env, stack, object));
2564 66           SPVM_STRING_BUFFER_add(string_buffer, tmp_buffer);
2565             }
2566             else {
2567             // If the object is weaken, this get the real address
2568 38           sprintf(tmp_buffer, "%p", SPVM_API_get_object_no_weaken_address(env, stack, object));
2569 38           int32_t exists = (int32_t)(intptr_t)SPVM_HASH_get(address_symtable, tmp_buffer, strlen(tmp_buffer));
2570 38 100         if (exists) {
2571             // If the object is weaken, this get the real address
2572 24           sprintf(tmp_buffer, "REUSE_OBJECT(%p)", SPVM_API_get_object_no_weaken_address(env, stack, object));
2573 24           SPVM_STRING_BUFFER_add(string_buffer, tmp_buffer);
2574             }
2575             else {
2576 14           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
2577 14           const char* basic_type_name = object_basic_type->name;
2578            
2579 14           SPVM_HASH_set(address_symtable, tmp_buffer, strlen(tmp_buffer), (void*)(intptr_t)1);
2580            
2581 14           SPVM_STRING_BUFFER_add(string_buffer, basic_type_name);
2582 14           sprintf(tmp_buffer, " (%p) ", object);
2583 14           SPVM_STRING_BUFFER_add(string_buffer, tmp_buffer);
2584            
2585 14           SPVM_STRING_BUFFER_add(string_buffer, "{\n");
2586            
2587             // Free object fields
2588 14           int32_t fields_length = object_basic_type->fields_length;
2589 126 100         for (int32_t field_index = 0; field_index < fields_length; field_index++) {
2590 314 100         for (int32_t depth_index = 0; depth_index < *depth + 1; depth_index++) {
2591 202           SPVM_STRING_BUFFER_add(string_buffer, " ");
2592             }
2593            
2594 112           SPVM_RUNTIME_FIELD* field = SPVM_API_BASIC_TYPE_get_field_by_index(runtime, object_basic_type, field_index);
2595            
2596 112           int32_t field_basic_type_id = field->basic_type->id;
2597 112           int32_t field_type_dimension = field->type_dimension;
2598 112           int32_t field_offset = field->offset;
2599 112           const char* field_name = field->name;
2600            
2601 112           SPVM_STRING_BUFFER_add(string_buffer, field_name);
2602 112           SPVM_STRING_BUFFER_add(string_buffer, " => ");
2603 112 100         if (field_type_dimension == 0 && field_basic_type_id >= SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE && field_basic_type_id <= SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE) {
    50          
    100          
2604 76           switch (field_basic_type_id) {
2605             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
2606 12           int8_t field_value = *(int8_t*)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2607 12           sprintf(tmp_buffer, "%d", field_value);
2608 12           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2609 12           break;
2610             }
2611             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
2612 12           int16_t field_value = *(int16_t*)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2613 12           sprintf(tmp_buffer, "%d", field_value);
2614 12           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2615 12           break;
2616             }
2617             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
2618 16           int32_t field_value = *(int32_t*)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2619 16           sprintf(tmp_buffer, "%d", field_value);
2620 16           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2621 16           break;
2622             }
2623             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
2624 12           int64_t field_value = *(int64_t*)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2625 12           sprintf(tmp_buffer, "%lld", (long long int)field_value);
2626 12           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2627 12           break;
2628             }
2629             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
2630 12           float field_value = *(float*)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2631 12           sprintf(tmp_buffer, "%g", field_value);
2632 12           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2633 12           break;
2634             }
2635             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
2636 12           double field_value = *(double*)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2637 12           sprintf(tmp_buffer, "%g", field_value);
2638 12           SPVM_STRING_BUFFER_add(string_buffer, (const char*)tmp_buffer);
2639 12           break;
2640             }
2641             default : {
2642 0           assert(0);
2643             }
2644             }
2645 76           }
2646             else {
2647 36           SPVM_OBJECT* field_value = *(SPVM_OBJECT**)((intptr_t)object + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field_offset);
2648 36           field_value = SPVM_API_get_object_no_weaken_address(env, stack, field_value);
2649 36           (*depth)++;
2650 36           SPVM_API_dump_recursive(env, stack, field_value, depth, string_buffer, address_symtable);
2651 36           (*depth)--;
2652             }
2653            
2654 112 100         if (field_index == fields_length - 1) {
2655 14           SPVM_STRING_BUFFER_add(string_buffer, "\n");
2656             }
2657             else {
2658 98           SPVM_STRING_BUFFER_add(string_buffer, ",\n");
2659             }
2660             }
2661            
2662 24 100         for (int32_t depth_index = 0; depth_index < *depth; depth_index++) {
2663 10           SPVM_STRING_BUFFER_add(string_buffer, " ");
2664             }
2665 14           SPVM_STRING_BUFFER_add(string_buffer, "}");
2666             }
2667             }
2668             }
2669 168           }
2670              
2671 14000           void SPVM_API_make_read_only(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string) {
2672 14000           SPVM_RUNTIME_BASIC_TYPE* string_basic_type = SPVM_API_get_object_basic_type(env, stack, string);
2673 14000 50         if (string && string_basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_STRING && string->type_dimension == 0) {
    50          
    50          
2674 14000           string->flag |= SPVM_OBJECT_C_FLAG_IS_READ_ONLY;
2675             }
2676 14000           }
2677              
2678 6404           int32_t SPVM_API_is_read_only(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string) {
2679            
2680             int32_t is_read_only;
2681 6404 100         if (string) {
2682 6396 100         if (string->flag & SPVM_OBJECT_C_FLAG_IS_READ_ONLY) {
2683 268           is_read_only = 1;
2684             }
2685             else {
2686 6396           is_read_only = 0;
2687             }
2688             }
2689             else {
2690 8           is_read_only = 0;
2691             }
2692            
2693 6404           return is_read_only;
2694             }
2695              
2696 6410           int32_t SPVM_API_set_exception(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* exception) {
2697            
2698 6410           SPVM_OBJECT** current_exception_ptr = (SPVM_OBJECT**)&stack[SPVM_API_C_STACK_INDEX_EXCEPTION];
2699            
2700 6410           SPVM_API_assign_object(env, stack, current_exception_ptr, exception);
2701            
2702 6410           return 0;
2703             }
2704              
2705 4352           SPVM_OBJECT* SPVM_API_get_exception(SPVM_ENV* env, SPVM_VALUE* stack){
2706              
2707 4352           SPVM_OBJECT** current_exception_ptr = (SPVM_OBJECT**)&stack[SPVM_API_C_STACK_INDEX_EXCEPTION];
2708 4352           SPVM_OBJECT* current_exception = *current_exception_ptr;
2709            
2710 4352           return current_exception;
2711             }
2712              
2713 4           SPVM_OBJECT* SPVM_API_new_byte_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2714            
2715 4           SPVM_OBJECT* object = SPVM_API_new_byte_array_no_mortal(env, stack, length);
2716            
2717 4           SPVM_API_push_mortal(env, stack, object);
2718            
2719 4           return object;
2720             }
2721              
2722 4           SPVM_OBJECT* SPVM_API_new_short_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2723            
2724 4           SPVM_OBJECT* object = SPVM_API_new_short_array_no_mortal(env, stack, length);
2725            
2726 4           SPVM_API_push_mortal(env, stack, object);
2727            
2728 4           return object;
2729             }
2730              
2731 14           SPVM_OBJECT* SPVM_API_new_int_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2732            
2733 14           SPVM_OBJECT* object = SPVM_API_new_int_array_no_mortal(env, stack, length);
2734            
2735 14           SPVM_API_push_mortal(env, stack, object);
2736            
2737 14           return object;
2738             }
2739              
2740 6           SPVM_OBJECT* SPVM_API_new_long_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2741            
2742 6           SPVM_OBJECT* object = SPVM_API_new_long_array_no_mortal(env, stack, length);
2743            
2744 6           SPVM_API_push_mortal(env, stack, object);
2745            
2746 6           return object;
2747             }
2748              
2749 4           SPVM_OBJECT* SPVM_API_new_float_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2750            
2751 4           SPVM_OBJECT* object = SPVM_API_new_float_array_no_mortal(env, stack, length);
2752            
2753 4           SPVM_API_push_mortal(env, stack, object);
2754            
2755 4           return object;
2756             }
2757              
2758 2           SPVM_OBJECT* SPVM_API_new_double_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2759            
2760 2           SPVM_OBJECT* object = SPVM_API_new_double_array_no_mortal(env, stack, length);
2761            
2762 2           SPVM_API_push_mortal(env, stack, object);
2763            
2764 2           return object;
2765             }
2766              
2767 7           SPVM_OBJECT* SPVM_API_new_string_array(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2768            
2769 7           SPVM_OBJECT* string_array = SPVM_API_new_string_array_no_mortal(env, stack, length);
2770            
2771 7           SPVM_API_push_mortal(env, stack, string_array);
2772            
2773 7           return string_array;
2774             }
2775              
2776 367           SPVM_OBJECT* SPVM_API_new_string_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2777            
2778 367           SPVM_RUNTIME_BASIC_TYPE* string_basic_type = SPVM_API_RUNTIME_get_basic_type_by_id(env->runtime, SPVM_NATIVE_C_BASIC_TYPE_ID_STRING);
2779            
2780 367           SPVM_OBJECT* object = SPVM_API_new_object_array_no_mortal(env, stack, string_basic_type, length);
2781            
2782 367           return object;
2783             }
2784              
2785 12           SPVM_OBJECT* SPVM_API_new_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
2786            
2787 12           SPVM_OBJECT* object = SPVM_API_new_object_no_mortal(env, stack, basic_type);
2788            
2789 12           SPVM_API_push_mortal(env, stack, object);
2790            
2791 12           return object;
2792             }
2793              
2794 300969           SPVM_OBJECT* SPVM_API_new_object_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
2795            
2796 300969           SPVM_RUNTIME* runtime = env->runtime;
2797            
2798 300969 50         if (!basic_type) {
2799 0           return NULL;
2800             }
2801            
2802 300969 50         if (basic_type->category != SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS) {
2803 0           return NULL;
2804             }
2805            
2806             // Alloc body length + 1
2807 300969           int32_t fields_length = basic_type->fields_length;
2808            
2809 300969           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + basic_type->fields_size + 1;
2810            
2811 300969 50         if (!basic_type) {
2812 0           return NULL;
2813             }
2814 300969           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 0, fields_length, 0);
2815            
2816 300969           return object;
2817             }
2818              
2819 264404           SPVM_OBJECT* SPVM_API_new_pointer_object_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, void* pointer) {
2820            
2821 264404           void* obj_object = SPVM_API_new_object_no_mortal(env, stack, basic_type);
2822            
2823 264404           SPVM_API_set_pointer(env, stack, obj_object, pointer);
2824            
2825 264404           return obj_object;
2826             }
2827              
2828 233432           SPVM_OBJECT* SPVM_API_new_pointer_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, void* pointer) {
2829            
2830            
2831 233432           SPVM_OBJECT* object = SPVM_API_new_pointer_object_no_mortal(env, stack, basic_type, pointer);
2832            
2833 233432           SPVM_API_push_mortal(env, stack, object);
2834            
2835 233432           return object;
2836             }
2837              
2838 68831           SPVM_OBJECT* SPVM_API_new_string_nolen_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes) {
2839            
2840            
2841 68831           int32_t length = strlen((char*)bytes);
2842            
2843 68831           SPVM_OBJECT* object = SPVM_API_new_string_no_mortal(env, stack, NULL, length);
2844            
2845 68831 50         if (bytes != NULL && length > 0) {
    100          
2846 68690           memcpy((void*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)), (char*)bytes, length);
2847             }
2848            
2849 68831           return object;
2850             }
2851              
2852 68695           SPVM_OBJECT* SPVM_API_new_string_nolen(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes) {
2853            
2854            
2855 68695           SPVM_OBJECT* object = SPVM_API_new_string_nolen_no_mortal(env, stack, bytes);
2856            
2857 68695           SPVM_API_push_mortal(env, stack, object);
2858            
2859 68695           return object;
2860             }
2861              
2862 159811           SPVM_OBJECT* SPVM_API_new_string_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes, int32_t length) {
2863            
2864            
2865 159811 50         if (length < 0) {
2866 0           return NULL;
2867             }
2868            
2869 159811           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(char) * (length + 1);
2870            
2871 159811           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_STRING);
2872            
2873 159811           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 0, length, 0);
2874            
2875 159811 50         if (object) {
2876 159811 100         if (bytes != NULL && length > 0) {
    100          
2877 83601           memcpy((void*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)), (char*)bytes, length);
2878             }
2879             }
2880            
2881 159811           return object;
2882             }
2883              
2884 32           int32_t SPVM_API_get_bool_object_value(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* bool_object) {
2885            
2886 32           int32_t value = *(int32_t*)((intptr_t)bool_object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
2887            
2888 32           return value;
2889             }
2890              
2891 1319           SPVM_OBJECT* SPVM_API_new_string(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes, int32_t length) {
2892            
2893            
2894 1319           SPVM_OBJECT* object = SPVM_API_new_string_no_mortal(env, stack, bytes, length);
2895            
2896 1319           SPVM_API_push_mortal(env, stack, object);
2897            
2898 1319           return object;
2899             }
2900              
2901 836           SPVM_OBJECT* SPVM_API_new_byte_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2902            
2903 836 50         if (length < 0) {
2904 0           return NULL;
2905             }
2906            
2907 836           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(int8_t) * (length + 1);
2908            
2909 836           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE);
2910            
2911 836           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2912            
2913 836           return object;
2914             }
2915              
2916 714           SPVM_OBJECT* SPVM_API_new_short_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2917            
2918 714           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(int16_t) * (length + 1);
2919            
2920 714           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT);
2921            
2922 714           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2923            
2924 714           return object;
2925             }
2926              
2927 910           SPVM_OBJECT* SPVM_API_new_int_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2928            
2929 910           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(int32_t) * (length + 1);
2930            
2931 910           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_INT);
2932            
2933 910           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2934            
2935 910           return object;
2936             }
2937              
2938 706           SPVM_OBJECT* SPVM_API_new_long_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2939            
2940 706 50         if (length < 0) {
2941 0           return NULL;
2942             }
2943            
2944 706           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(int64_t) * (length + 1);
2945            
2946 706           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_LONG);
2947            
2948 706           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2949            
2950 706           return object;
2951             }
2952              
2953 706           SPVM_OBJECT* SPVM_API_new_float_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2954            
2955 706           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(float) * (length + 1);
2956            
2957 706           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT);
2958            
2959 706           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2960            
2961 706           return object;
2962             }
2963              
2964 714           SPVM_OBJECT* SPVM_API_new_double_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length) {
2965            
2966 714           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(double) * (length + 1);
2967            
2968 714           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type_by_id(env, stack, SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE);
2969            
2970 714           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2971            
2972 714           return object;
2973             }
2974              
2975 52598           SPVM_OBJECT* SPVM_API_new_object_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t length) {
2976            
2977 52598           SPVM_RUNTIME* runtime = env->runtime;
2978            
2979             SPVM_OBJECT object_for_type_check;
2980 52598           object_for_type_check.basic_type = basic_type;
2981 52598           object_for_type_check.type_dimension = 1;
2982            
2983 52598           int32_t is_object_array = SPVM_API_is_object_array(env, stack, &object_for_type_check);
2984            
2985 52598 50         if (!is_object_array) {
2986 0           return NULL;
2987             }
2988            
2989 52598 50         if (!basic_type) {
2990 0           return NULL;
2991             }
2992            
2993 52598           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(void*) * (length + 1);
2994            
2995 52598           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
2996            
2997 52598           return object;
2998             }
2999              
3000 4           SPVM_OBJECT* SPVM_API_new_object_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t length) {
3001            
3002 4           SPVM_OBJECT* object = SPVM_API_new_object_array_no_mortal(env, stack, basic_type, length);
3003            
3004 4           SPVM_API_push_mortal(env, stack, object);
3005            
3006 4           return object;
3007             }
3008              
3009 70           SPVM_OBJECT* SPVM_API_new_muldim_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t length) {
3010            
3011 70 50         if (type_dimension < 2) {
3012 0           return NULL;
3013             }
3014 70 50         else if (basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_ANY_OBJECT) {
3015 0           return NULL;
3016             }
3017            
3018 70           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + sizeof(void*) * (length + 1);
3019            
3020 70 50         if (!basic_type) {
3021 0           return NULL;
3022             }
3023 70           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, type_dimension, length, 0);
3024            
3025 70           return object;
3026             }
3027              
3028 0           SPVM_OBJECT* SPVM_API_new_muldim_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t length) {
3029            
3030 0           SPVM_OBJECT* object = SPVM_API_new_muldim_array_no_mortal(env, stack, basic_type, type_dimension, length);
3031            
3032 0           SPVM_API_push_mortal(env, stack, object);
3033            
3034 0           return object;
3035             }
3036              
3037 226           SPVM_OBJECT* SPVM_API_new_mulnum_array_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t length) {
3038            
3039 226           SPVM_RUNTIME* runtime = env->runtime;
3040            
3041             // valut_t array dimension must be 1
3042 226           const char* basic_type_name = basic_type->name;
3043            
3044 226           int32_t fields_length = basic_type->fields_length;
3045 226           SPVM_RUNTIME_FIELD* field_first = SPVM_API_BASIC_TYPE_get_field_by_index(runtime, basic_type, 0);
3046            
3047 226           int32_t field_basic_type_id = field_first->basic_type->id;
3048            
3049             int32_t unit_size;
3050 226 100         if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE) {
3051 42           unit_size = sizeof(int8_t);
3052             }
3053 184 100         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT) {
3054 32           unit_size = sizeof(int16_t);
3055             }
3056 152 100         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_INT) {
3057 44           unit_size = sizeof(int32_t);
3058             }
3059 108 100         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_LONG) {
3060 32           unit_size = sizeof(int64_t);
3061             }
3062 76 100         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT) {
3063 28           unit_size = sizeof(float);
3064             }
3065 48 50         else if (field_basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE) {
3066 48           unit_size = sizeof(double);
3067             }
3068             else {
3069 0           assert(0);
3070             }
3071            
3072 226           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + unit_size * fields_length * (length + 1);
3073            
3074 226           SPVM_OBJECT* object = SPVM_API_new_object_common(env, stack, alloc_size, basic_type, 1, length, 0);
3075            
3076 226           return object;
3077             }
3078              
3079 0           SPVM_OBJECT* SPVM_API_new_mulnum_array(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t length) {
3080            
3081 0           SPVM_OBJECT* object = SPVM_API_new_mulnum_array_no_mortal(env, stack, basic_type, length);
3082            
3083 0           SPVM_API_push_mortal(env, stack, object);
3084            
3085 0           return object;
3086             }
3087              
3088 268           SPVM_OBJECT* SPVM_API_new_array_proto_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, int32_t length) {
3089              
3090 268 50         if (array == NULL) {
3091 0           return NULL;
3092             }
3093            
3094 268 50         if (length < 0) {
3095 0           return NULL;
3096             }
3097            
3098 268           size_t element_size = SPVM_API_get_elem_size(env, stack, array);
3099            
3100 268           size_t alloc_size = (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + element_size * (length + 1);
3101            
3102 268           SPVM_RUNTIME_BASIC_TYPE* array_basic_type = SPVM_API_get_object_basic_type(env, stack, array);
3103 268           SPVM_OBJECT* new_array = SPVM_API_new_object_common(env, stack, alloc_size, array_basic_type, array->type_dimension, length, 0);
3104            
3105 268           return new_array;
3106             }
3107              
3108 262           SPVM_OBJECT* SPVM_API_new_array_proto(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, int32_t length) {
3109            
3110            
3111 262           SPVM_OBJECT* object = SPVM_API_new_array_proto_no_mortal(env, stack, array, length);
3112            
3113 262           SPVM_API_push_mortal(env, stack, object);
3114            
3115 262           return object;
3116             }
3117              
3118 0           int32_t SPVM_API_get_object_basic_type_id(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3119 0           return object->basic_type->id;
3120             }
3121              
3122 2699079           SPVM_RUNTIME_BASIC_TYPE* SPVM_API_get_object_basic_type(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3123            
3124 2699079           return object->basic_type;
3125             }
3126              
3127 190072           const char* SPVM_API_get_object_basic_type_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3128            
3129 190072           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
3130            
3131 190072           return object_basic_type->name;
3132             }
3133              
3134 21006           int32_t SPVM_API_get_object_type_dimension(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3135 21006           return object->type_dimension;
3136             }
3137              
3138 187742           int32_t SPVM_API_length(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3139            
3140 187742           int32_t length = object->length;
3141            
3142 187742           return length;
3143             }
3144              
3145 518562           void SPVM_API_set_length(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, int32_t length) {
3146            
3147 518562           object->length = length;
3148 518562           }
3149              
3150 1022           int8_t* SPVM_API_get_elems_byte(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3151            
3152 1022           return (int8_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3153             }
3154              
3155 180134           const char* SPVM_API_get_chars(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string) {
3156            
3157 180134           return (const char*)((intptr_t)string + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3158             }
3159              
3160 926           int16_t* SPVM_API_get_elems_short(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3161            
3162 926           return (int16_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3163             }
3164              
3165 1150           int32_t* SPVM_API_get_elems_int(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3166            
3167 1150           return (int32_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3168             }
3169              
3170 928           int64_t* SPVM_API_get_elems_long(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3171            
3172 928           return (int64_t*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3173             }
3174              
3175 922           float* SPVM_API_get_elems_float(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3176            
3177 922           return (float*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3178             }
3179              
3180 916           double* SPVM_API_get_elems_double(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3181            
3182 916           return (double*)((intptr_t)object + SPVM_API_RUNTIME_get_object_data_offset(env->runtime));
3183             }
3184              
3185 101691           SPVM_OBJECT* SPVM_API_get_elem_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, int32_t index) {
3186            
3187 101691           SPVM_OBJECT* object_maybe_weaken = ((SPVM_OBJECT**)((intptr_t)array + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[index];
3188 101691           SPVM_OBJECT* object = SPVM_API_get_object_no_weaken_address(env, stack, object_maybe_weaken);
3189            
3190 101691           return object;
3191             }
3192              
3193 30816           void SPVM_API_set_elem_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, int32_t index, SPVM_OBJECT* object) {
3194            
3195 30816           void* object_ref = &((void**)((intptr_t)array + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[index];
3196            
3197 30816           SPVM_API_assign_object(env, stack, object_ref, object);
3198 30816           }
3199              
3200 101479           SPVM_OBJECT* SPVM_API_get_elem_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, int32_t index) {
3201            
3202 101479           return SPVM_API_get_elem_object(env, stack, array, index);
3203             }
3204              
3205 119           void SPVM_API_set_elem_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, int32_t index, SPVM_OBJECT* string) {
3206            
3207 119           SPVM_API_set_elem_object(env, stack, array, index, string);
3208 119           }
3209              
3210 1722071           void* SPVM_API_get_pointer(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3211            
3212 1722071           return object->pointer;
3213             }
3214              
3215 264404           void SPVM_API_set_pointer(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, void* pointer) {
3216            
3217 264404           object->pointer = pointer;
3218 264404           }
3219              
3220 751783           SPVM_RUNTIME_FIELD* SPVM_API_get_field(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* field_name) {
3221            
3222 751783           SPVM_RUNTIME* runtime = env->runtime;
3223            
3224 751783 50         if (!object) {
3225 0           return NULL;
3226             }
3227            
3228 751783           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
3229            
3230 751783 50         if (object->type_dimension != 0) {
3231 0           return NULL;
3232             }
3233            
3234 751783           SPVM_RUNTIME_FIELD* field = SPVM_API_BASIC_TYPE_get_field_by_name(runtime, object_basic_type, field_name);
3235            
3236 751783           return field;
3237             }
3238              
3239 3026           SPVM_RUNTIME_FIELD* SPVM_API_get_field_static(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* field_name) {
3240            
3241 3026           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
3242            
3243 3026 50         if (!basic_type) {
3244 0           return NULL;
3245             }
3246            
3247 3026           SPVM_RUNTIME_FIELD* field = SPVM_API_BASIC_TYPE_get_field_by_name(env->runtime, basic_type, field_name);
3248            
3249 3026           return field;
3250             }
3251              
3252 108           SPVM_RUNTIME_CLASS_VAR* SPVM_API_get_class_var(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name) {
3253            
3254 108           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
3255            
3256 108 50         if (!basic_type) {
3257 0           return NULL;
3258             }
3259            
3260 108           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_name(env->runtime, basic_type, class_var_name);
3261            
3262 108           return class_var;
3263             }
3264              
3265 12957           SPVM_RUNTIME_METHOD* SPVM_API_get_method(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name) {
3266            
3267 12957           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
3268            
3269 12957 50         if (!basic_type) {
3270 0           return NULL;
3271             }
3272            
3273 12957           SPVM_RUNTIME_METHOD* method = SPVM_API_BASIC_TYPE_get_method_by_name(env->runtime, basic_type, method_name);
3274            
3275 12957           return method;
3276             }
3277              
3278 58           SPVM_RUNTIME_METHOD* SPVM_API_get_class_method(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name) {
3279            
3280 58           SPVM_RUNTIME_METHOD* method = SPVM_API_get_method(env, stack, basic_type_name, method_name);
3281            
3282 58 50         if (method) {
3283 58 50         if (!method->is_class_method) {
3284 0           return NULL;
3285             }
3286             }
3287            
3288 58           return method;
3289             }
3290              
3291 2           SPVM_RUNTIME_METHOD* SPVM_API_get_instance_method_static(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name) {
3292            
3293 2           SPVM_RUNTIME_METHOD* method = SPVM_API_get_method(env, stack, basic_type_name, method_name);
3294            
3295 2 50         if (method) {
3296 2 50         if (method->is_class_method) {
3297 0           return NULL;
3298             }
3299             }
3300            
3301 2           return method;
3302             }
3303              
3304 689100           SPVM_RUNTIME_METHOD* SPVM_API_get_instance_method(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* method_name) {
3305            
3306             // Method
3307 689100           SPVM_RUNTIME_METHOD* method = NULL;
3308            
3309             // Compiler
3310 689100           SPVM_RUNTIME* runtime = env->runtime;
3311            
3312 689100 50         if (!object) {
3313 0           return NULL;
3314             }
3315            
3316             // Basic type
3317 689100           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
3318 689100           SPVM_RUNTIME_BASIC_TYPE* parent_basic_type = object_basic_type;
3319            
3320             while (1) {
3321 689202 100         if (!parent_basic_type) {
3322 10           break;
3323             }
3324            
3325             // Method
3326 689192           method = SPVM_API_BASIC_TYPE_get_method_by_name(runtime, parent_basic_type, method_name);
3327 689192 100         if (method) {
3328             // Instance method
3329 689090 50         if (method->is_class_method) {
3330 0           method = NULL;
3331             }
3332 689090           break;
3333             }
3334            
3335 102           parent_basic_type = parent_basic_type->parent;
3336 102           }
3337            
3338 689100           return method;
3339             }
3340              
3341             // Deprecated
3342 1457633           void* SPVM_API_new_memory_stack(SPVM_ENV* env, SPVM_VALUE* stack, size_t size) {
3343            
3344 1457633           return SPVM_API_new_memory_block(env, stack, size);
3345             }
3346              
3347 1978222           void* SPVM_API_new_memory_block(SPVM_ENV* env, SPVM_VALUE* stack, size_t size) {
3348            
3349 1978222           SPVM_RUNTIME* runtime = env->runtime;
3350            
3351 1978222 50         assert(size > 0);
3352            
3353             if ((uint64_t)size > (uint64_t)SIZE_MAX) {
3354             return NULL;
3355             }
3356            
3357 1978222           void* block = SPVM_ALLOCATOR_alloc_memory_block_unmanaged((size_t)size);
3358            
3359 1978222           stack[SPVM_API_C_STACK_INDEX_MEMORY_BLOCKS_COUNT].ival++;
3360            
3361             #ifdef SPVM_DEBUG_MEMORY
3362             fprintf(runtime->spvm_stderr, "[Debug]Function : new_memory_block, Block Address: %p, Stack Address : %p, Memory Blocks Count : %d\n", block, stack, stack[SPVM_API_C_STACK_INDEX_MEMORY_BLOCKS_COUNT].ival);
3363             #endif
3364            
3365 1978222           return block;
3366             }
3367              
3368             // Deprecated
3369 1977552           void SPVM_API_free_memory_block(SPVM_ENV* env, SPVM_VALUE* stack, void* block) {
3370            
3371 1977552           SPVM_RUNTIME* runtime = env->runtime;
3372            
3373 1977552 100         if (block) {
3374 1977550           SPVM_ALLOCATOR_free_memory_block_unmanaged(block);
3375 1977550           stack[SPVM_API_C_STACK_INDEX_MEMORY_BLOCKS_COUNT].ival--;
3376             #ifdef SPVM_DEBUG_MEMORY
3377             fprintf(runtime->spvm_stderr, "[Debug]Function : free_memory_block, Block Address: %p, Stack Address : %p, Memory Blocks Count : %d\n", block, stack, stack[SPVM_API_C_STACK_INDEX_MEMORY_BLOCKS_COUNT].ival);
3378             #endif
3379             }
3380 1977552           }
3381              
3382 1457633           void SPVM_API_free_memory_stack(SPVM_ENV* env, SPVM_VALUE* stack, void* block) {
3383            
3384 1457633           SPVM_API_free_memory_block(env, stack, block);
3385            
3386 1457633           }
3387              
3388 548           int32_t SPVM_API_get_memory_blocks_count_stack(SPVM_ENV* env, SPVM_VALUE* stack) {
3389            
3390 548           return SPVM_API_get_memory_blocks_count(env, stack);
3391             }
3392              
3393 572           int32_t SPVM_API_get_memory_blocks_count(SPVM_ENV* env, SPVM_VALUE* stack) {
3394            
3395            
3396 572           int32_t memory_blocks_count = stack[SPVM_API_C_STACK_INDEX_MEMORY_BLOCKS_COUNT].ival;
3397            
3398 572           return memory_blocks_count;
3399             }
3400              
3401 222           SPVM_OBJECT* SPVM_API_copy_no_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3402 222 50         if (!object) {
3403 0           return NULL;
3404             }
3405            
3406             SPVM_OBJECT* new_object;
3407            
3408 222           int32_t length = SPVM_API_length(env, stack, object);
3409            
3410 222 100         if (SPVM_API_is_string(env, stack, object)) {
3411 216           new_object = SPVM_API_new_string_no_mortal(env, stack, NULL, length);
3412            
3413 216           const char* object_chars = SPVM_API_get_chars(env, stack, object);
3414 216           char* new_object_chars = (char*)SPVM_API_get_chars(env, stack, new_object);
3415            
3416 216           memcpy(new_object_chars, object_chars, length);
3417             }
3418 12 100         else if (SPVM_API_is_numeric_array(env, stack, object) || SPVM_API_is_mulnum_array(env, stack, object)) {
    50          
3419 6           new_object = SPVM_API_new_array_proto_no_mortal(env, stack, object, length);
3420            
3421 6           const char* object_bytes = (const char*)SPVM_API_get_elems_byte(env, stack, object);
3422 6           char* new_object_bytes = (char*)SPVM_API_get_elems_byte(env, stack, new_object);
3423            
3424 6           size_t element_size = SPVM_API_get_elem_size(env, stack, object);
3425            
3426 6           memcpy(new_object_bytes, object_bytes, element_size * length);
3427             }
3428             else {
3429 0           new_object = NULL;
3430             }
3431            
3432 222           return new_object;
3433             }
3434              
3435 0           SPVM_OBJECT* SPVM_API_copy(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3436            
3437            
3438 0           SPVM_OBJECT* new_object = SPVM_API_copy_no_mortal(env, stack, object);
3439            
3440 0           SPVM_API_push_mortal(env, stack, new_object);
3441            
3442 0           return new_object;
3443             }
3444              
3445 34           void SPVM_API_shorten(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* string, int32_t new_length) {
3446            
3447            
3448 34 50         if (string != NULL) {
3449 34 50         if (SPVM_API_is_string(env, stack, string)) {
3450 34 50         if (!SPVM_API_is_read_only(env, stack, string)) {
3451 34           int32_t length = SPVM_API_length(env, stack, string);
3452            
3453 34 100         if (new_length > length) {
3454 2           new_length = length;
3455             }
3456 32 50         else if (new_length < 0) {
3457 0           new_length = 0;
3458             }
3459            
3460 34           SPVM_API_set_length(env, stack, string, new_length);
3461 34           char* chars = (char*)SPVM_API_get_chars(env, stack, string);
3462 34 50         if (new_length > length) {
3463 0           memset(chars + new_length, 0, new_length - length);
3464             }
3465             }
3466             }
3467             }
3468 34           }
3469              
3470 107723           int32_t SPVM_API_elem_isa(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* array, SPVM_OBJECT* element) {
3471            
3472 107723           SPVM_RUNTIME* runtime = env->runtime;
3473            
3474 107723 50         assert(array);
3475            
3476 107723           SPVM_RUNTIME_BASIC_TYPE* array_basic_type = SPVM_API_get_object_basic_type(env, stack,array);
3477            
3478 107723           int32_t array_type_dimension = array->type_dimension;
3479            
3480 107723 50         assert(array_type_dimension > 0);
3481 107723           int32_t runtime_assignability = SPVM_API_isa(env, stack, element, array_basic_type, array_type_dimension - 1);
3482              
3483 107723           return runtime_assignability;
3484             }
3485              
3486 962           int32_t SPVM_API_is_type(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t type_dimension) {
3487            
3488             // Object must be not null
3489 962 50         assert(object);
3490            
3491 962           int32_t is_type = 0;
3492 962           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
3493 962 100         if (object_basic_type->id == basic_type->id && object->type_dimension == type_dimension) {
    100          
3494 956           is_type = 1;
3495             }
3496            
3497 962           return is_type;
3498             }
3499              
3500 820           int32_t SPVM_API_is_type_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* basic_type_name, int32_t type_dimension) {
3501            
3502 820           SPVM_RUNTIME_BASIC_TYPE* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
3503 820 50         if (!basic_type) {
3504 0           return 0;
3505             };
3506            
3507 820           int32_t is_type = SPVM_API_is_type(env, stack, object, basic_type, type_dimension);
3508            
3509 820           return is_type;
3510             }
3511              
3512 312559           int32_t SPVM_API_isa(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t type_dimension) {
3513            
3514 312559           SPVM_RUNTIME* runtime = env->runtime;
3515            
3516             int32_t isa;
3517 312559 100         if (object == NULL) {
3518 222           isa = 1;
3519             }
3520             else {
3521 312337           SPVM_RUNTIME_BASIC_TYPE* object_basic_type = SPVM_API_get_object_basic_type(env, stack, object);
3522 312337           int32_t object_type_dimension = object->type_dimension;
3523 312337 50         if (!basic_type) {
3524 0           isa = 0;
3525             }
3526             else {
3527 312337           isa = SPVM_API_TYPE_can_assign(env->runtime, basic_type, type_dimension, 0, object_basic_type, object_type_dimension, 0);
3528             }
3529             }
3530            
3531 312559           return isa;
3532             }
3533              
3534 0           int32_t SPVM_API_isa_by_name(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object, const char* basic_type_name, int32_t type_dimension) {
3535            
3536 0           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
3537 0 0         if (!basic_type) {
3538 0           return 0;
3539             };
3540            
3541 0           int32_t isa = SPVM_API_isa(env, stack, object, basic_type, type_dimension);
3542            
3543 0           return isa;
3544             }
3545              
3546 0           int32_t SPVM_API_get_basic_type_id_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
3547 0           *error_id = 0;
3548            
3549 0           int32_t basic_type_id = SPVM_API_get_basic_type_id(env, stack, basic_type_name);
3550 0 0         if (basic_type_id < 0) {
3551 0           *error_id = 1;
3552 0           SPVM_API_die(env, stack, "The %s basic type is not found", basic_type_name, func_name, file, line);
3553             };
3554 0           return basic_type_id;
3555             }
3556              
3557 0           SPVM_RUNTIME_BASIC_TYPE* SPVM_API_get_basic_type_by_name(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t* error_id, const char* func_name, const char* file, int32_t line) {
3558 0           *error_id = 0;
3559            
3560 0           void* basic_type = SPVM_API_get_basic_type(env, stack, basic_type_name);
3561 0 0         if (!basic_type) {
3562 0           *error_id = 1;
3563 0           SPVM_API_die(env, stack, "The %s basic type is not found", basic_type_name, func_name, file, line);
3564             };
3565            
3566 0           return basic_type;
3567             }
3568              
3569 164403           SPVM_RUNTIME_BASIC_TYPE* SPVM_API_get_basic_type_by_id(SPVM_ENV* env, SPVM_VALUE* stack, int32_t basic_type_id) {
3570            
3571 164403           void* basic_type = SPVM_API_RUNTIME_get_basic_type_by_id(env->runtime, basic_type_id);
3572            
3573 164403           return basic_type;
3574             }
3575              
3576 8           void* SPVM_API_strerror_string(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value, int32_t length) {
3577            
3578 8 50         if (length < 0) {
3579 0           return NULL;
3580             }
3581            
3582 8 50         if (length == 0) {
3583 8           length = 64;
3584             }
3585            
3586 8           void* obj_strerror_value = SPVM_API_new_string(env, stack, NULL, length);
3587 8           char* strerror_value = (char*)SPVM_API_get_chars(env, stack, obj_strerror_value);
3588            
3589 8           int32_t status = SPVM_STRERROR_strerror(errno_value, strerror_value, length);
3590            
3591 8 50         if (status == 0) {
3592 8           SPVM_API_shorten(env, stack, obj_strerror_value, strlen(strerror_value));
3593 8           return obj_strerror_value;
3594             }
3595             else {
3596 0           return NULL;
3597             }
3598             }
3599              
3600 4           const char* SPVM_API_strerror(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value, int32_t length) {
3601            
3602 4           void* obj_strerror_value = SPVM_API_strerror_string(env, stack, errno_value, length);
3603            
3604 4 50         if (obj_strerror_value) {
3605 4           char* strerror_value = (char*)SPVM_API_get_chars(env, stack, obj_strerror_value);
3606 4           return strerror_value;
3607             }
3608             else {
3609 0           return NULL;
3610             }
3611             }
3612              
3613 2           void* SPVM_API_strerror_string_nolen(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value) {
3614 2           return SPVM_API_strerror_string(env, stack, errno_value, 0);
3615             }
3616              
3617 2           const char* SPVM_API_strerror_nolen(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value) {
3618 2           return SPVM_API_strerror(env, stack, errno_value, 0);
3619             }
3620              
3621 1457633           int32_t SPVM_API_call_method_vm(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_METHOD* method, int32_t args_width) {
3622 1457633           return SPVM_VM_call_method(env, stack, method, args_width);
3623             }
3624              
3625 4           const char* SPVM_API_get_spvm_version_string(SPVM_ENV* env, SPVM_VALUE* stack) {
3626            
3627 4           const char* spvm_version_string = SPVM_NATIVE_VERSION_STRING;
3628            
3629 4           return spvm_version_string;
3630             }
3631              
3632 2           double SPVM_API_get_spvm_version_number(SPVM_ENV* env, SPVM_VALUE* stack) {
3633            
3634 2           const char* spvm_version_string = SPVM_API_get_spvm_version_string(env, stack);
3635            
3636 2 50         assert(spvm_version_string);
3637            
3638 2           int32_t spvm_version_string_length = strlen(spvm_version_string);
3639            
3640             char *end;
3641 2           errno = 0;
3642 2           double version_number = strtod(spvm_version_string, &end);
3643 2 50         assert(*end == '\0');
3644 2 50         assert(errno == 0);
3645            
3646 2           return version_number;
3647             }
3648              
3649 15           const char* SPVM_API_get_version_string(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type){
3650            
3651 15           return basic_type->version_string;
3652             }
3653              
3654 4           double SPVM_API_get_version_number(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
3655            
3656 4           const char* version_string = SPVM_API_get_version_string(env, stack, basic_type);
3657            
3658 4 50         if (!version_string) {
3659 0           return -1;
3660             }
3661            
3662 4           int32_t version_string_length = strlen(version_string);
3663            
3664 4           char version_string_without_hyphen[20] = {0};
3665 4           int32_t version_string_without_hyphen_length = 0;
3666 36 100         for (int32_t i = 0; i < version_string_length; i++) {
3667 32           char ch = version_string[i];
3668 32 50         if (!(ch == '_')) {
3669 32           version_string_without_hyphen[version_string_without_hyphen_length] = ch;
3670 32           version_string_without_hyphen_length++;
3671             }
3672             }
3673            
3674             char *end;
3675 4           errno = 0;
3676 4           double version_number = strtod(version_string_without_hyphen, &end);
3677 4 50         assert(*end == '\0');
3678 4 50         assert(errno == 0);
3679            
3680 4           return version_number;
3681             }
3682              
3683 518528           SPVM_OBJECT* SPVM_API_new_object_common(SPVM_ENV* env, SPVM_VALUE* stack, size_t alloc_size, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t length, int32_t flag) {
3684            
3685 518528           SPVM_OBJECT* object = SPVM_API_new_memory_block(env, stack, alloc_size);
3686            
3687 518528 50         if (object) {
3688 518528           object->basic_type = basic_type;
3689 518528           object->type_dimension = type_dimension;
3690 518528           object->flag = flag;
3691            
3692             // The length of string can be shorten.
3693 518528           SPVM_API_set_length(env, stack, object, length);
3694             }
3695            
3696 518528           SPVM_MUTEX* mutex = SPVM_API_get_object_mutex(env, stack, object);
3697            
3698 518528           SPVM_MUTEX_init(mutex);
3699            
3700 518528           return object;
3701             }
3702              
3703 20           int32_t SPVM_API_check_stack_env(SPVM_ENV* env, SPVM_VALUE* stack) {
3704            
3705 20           int32_t is_valid = 0;
3706 20 50         if (stack[SPVM_API_C_STACK_INDEX_ENV].oval == env) {
3707 20           is_valid = 1;
3708             }
3709            
3710 20           return is_valid;
3711             }
3712              
3713 2843487           int32_t SPVM_API_call_method_common(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_RUNTIME_METHOD* method, int32_t args_width, int32_t mortal) {
3714            
3715             // Runtime
3716 2843487           SPVM_RUNTIME* runtime = env->runtime;
3717            
3718 2843487           int32_t error_id = 0;
3719 2843487           stack[SPVM_API_C_STACK_INDEX_ARGS_WIDTH].ival = args_width;
3720 2843487           stack[SPVM_API_C_STACK_INDEX_CALL_DEPTH].ival++;
3721            
3722 2843487           int32_t max_call_depth = 10000;
3723 2843487 50         if (stack[SPVM_API_C_STACK_INDEX_CALL_DEPTH].ival > max_call_depth) {
3724 0           error_id = SPVM_API_die(env, stack, "Deep recursion occurs. The depth of a method call must be less than %d", max_call_depth, FILE_NAME, __LINE__);
3725             }
3726             else {
3727 2843487           void* method_return_basic_type = method->return_basic_type;
3728 2843487           int32_t method_return_type_dimension = method->return_type_dimension;
3729 2843487           int32_t method_return_type_flag = method->return_type_flag;
3730            
3731 2843487           SPVM_RUNTIME_BASIC_TYPE* current_basic_type = method->current_basic_type;
3732            
3733 2843487           int32_t method_return_type_is_object = SPVM_API_TYPE_is_object_type(runtime, method_return_basic_type, method_return_type_dimension, method_return_type_flag);
3734 2843487           int32_t no_need_call = 0;
3735 2843487 100         if (method->is_init) {
3736            
3737 21535 100         if (current_basic_type->initialized) {
3738 12198           no_need_call = 1;
3739             }
3740             else {
3741 9337           current_basic_type->initialized = 1;
3742             }
3743             }
3744            
3745 2843487 100         if (!no_need_call) {
3746             // Call native method
3747 2831289 100         if (method->is_native) {
3748             // Enter scope
3749 1362919           int32_t original_mortal_stack_top = SPVM_API_enter_scope(env, stack);
3750            
3751             // Set argument default values
3752 1362919           int32_t optional_args_length = method->args_length - method->required_args_length;
3753 1362919 100         if (optional_args_length > 0) {
3754            
3755             // Operation codes
3756 368           SPVM_OPCODE* opcodes = method->opcodes;
3757            
3758             // Execute operation codes
3759 368           int32_t opcode_rel_index = 0;
3760             while (1) {
3761            
3762 820           SPVM_OPCODE* opcode = &(opcodes[opcode_rel_index]);
3763            
3764 820 100         if (opcode->id == SPVM_OPCODE_C_ID_END_ARGS) {
3765 368           break;
3766             }
3767            
3768 452           switch (opcode->id) {
3769             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_BYTE: {
3770 4           int32_t stack_index = opcode->operand3 & 0xFF;
3771 4 100         if (stack_index >= args_width) {
3772 2           stack[stack_index].bval = (int8_t)(uint8_t)opcode->operand1;
3773             }
3774 4           break;
3775             }
3776             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_SHORT: {
3777 4           int32_t stack_index = opcode->operand3 & 0xFF;
3778 4 100         if (stack_index >= args_width) {
3779 2           stack[stack_index].sval = (int16_t)(uint16_t)opcode->operand1;
3780             }
3781 4           break;
3782             }
3783             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_INT: {
3784 16           int32_t stack_index = opcode->operand3 & 0xFF;
3785 16 100         if (stack_index >= args_width) {
3786 8           stack[stack_index].ival = (int32_t)opcode->operand1;
3787             }
3788 16           break;
3789             }
3790             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_LONG: {
3791 4           int32_t stack_index = opcode->operand3 & 0xFF;
3792 4 100         if (stack_index >= args_width) {
3793 2           stack[stack_index].lval = *(int64_t*)&opcode->operand1;
3794             }
3795 4           break;
3796             }
3797             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_FLOAT: {
3798 4           int32_t stack_index = opcode->operand3 & 0xFF;
3799 4 100         if (stack_index >= args_width) {
3800             SPVM_VALUE default_value;
3801 2           default_value.ival = (int32_t)opcode->operand1;
3802 2           stack[stack_index].fval = default_value.fval;
3803             }
3804 4           break;
3805             }
3806             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_DOUBLE: {
3807 4           int32_t stack_index = opcode->operand3 & 0xFF;
3808 4 100         if (stack_index >= args_width) {
3809 2           stack[stack_index].dval = *(double*)&opcode->operand1;
3810             }
3811 4           break;
3812             }
3813             case SPVM_OPCODE_C_ID_GET_STACK_OPTIONAL_OBJECT: {
3814 372           int32_t stack_index = opcode->operand3 & 0xFF;
3815 372 100         if (stack_index >= args_width) {
3816 16           stack[stack_index].oval = NULL;
3817             }
3818 372           break;
3819             }
3820             }
3821            
3822 452           opcode_rel_index++;
3823 452           }
3824             }
3825            
3826             // Call native subrotuine
3827 1362919           int32_t (*native_address)(SPVM_ENV*, SPVM_VALUE*) = method->native_address;
3828 1362919 50         assert(native_address != NULL);
3829 1362919           error_id = (*native_address)(env, stack);
3830            
3831             // Increment ref count of return value
3832 1362919 100         if (!error_id) {
3833 1362609 100         if (method_return_type_is_object) {
3834 306584           SPVM_OBJECT* return_object = *(void**)&stack[0];
3835 306584 100         if (return_object != NULL) {
3836 305998           SPVM_MUTEX* object_mutex = SPVM_API_get_object_mutex(env, stack, return_object);
3837            
3838 305998           SPVM_MUTEX_lock(object_mutex);
3839            
3840 305998           SPVM_API_inc_ref_count(env, stack, return_object);
3841            
3842 305998           SPVM_MUTEX_unlock(object_mutex);
3843             }
3844             }
3845             }
3846            
3847             // Leave scope
3848 1362919           SPVM_API_leave_scope(env, stack, original_mortal_stack_top);
3849            
3850             // Decrement ref count of return value
3851 1362919 100         if (!error_id) {
3852 1362609 100         if (method_return_type_is_object) {
3853 306584           SPVM_OBJECT* return_object = *(void**)&stack[0];
3854 306584 100         if (return_object != NULL) {
3855 305998           SPVM_MUTEX* object_mutex = SPVM_API_get_object_mutex(env, stack, return_object);
3856            
3857 305998           SPVM_MUTEX_lock(object_mutex);
3858            
3859 305998           SPVM_API_dec_ref_count(env, stack, return_object);
3860            
3861 305998           SPVM_MUTEX_unlock(object_mutex);
3862             }
3863             }
3864             }
3865            
3866             // Set default exception message
3867 1362919 100         if (error_id && SPVM_API_get_exception(env, stack) == NULL) {
    50          
3868 0           void* exception = SPVM_API_new_string_nolen_no_mortal(env, stack, "Error");
3869 1362919           SPVM_API_set_exception(env, stack, exception);
3870             }
3871             }
3872             else {
3873             // Call precompiled method
3874 1468370           void* method_precompile_address = method->precompile_address;
3875 1468370 100         if (method_precompile_address) {
3876 10737           int32_t (*precompile_address)(SPVM_ENV*, SPVM_VALUE*) = method_precompile_address;
3877 10737           error_id = (*precompile_address)(env, stack);
3878             }
3879             // Call sub virtual machine
3880             else {
3881 1457633           error_id = SPVM_API_call_method_vm(env, stack, method, args_width);
3882             }
3883             }
3884            
3885 2831289 100         if (mortal && method_return_type_is_object) {
    100          
3886 6           SPVM_API_push_mortal(env, stack, stack[0].oval);
3887             }
3888             }
3889             }
3890            
3891 2843487           stack[SPVM_API_C_STACK_INDEX_CALL_DEPTH].ival--;
3892            
3893 2843487           return error_id;
3894             }
3895              
3896 303785           int32_t SPVM_API_push_mortal(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3897            
3898            
3899 303785           SPVM_OBJECT*** current_mortal_stack_ptr = (SPVM_OBJECT***)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK];
3900 303785           int32_t* current_mortal_stack_top_ptr = (int32_t*)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_TOP];
3901 303785           int32_t* current_mortal_stack_capacity_ptr = (int32_t*)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_CAPACITY];
3902            
3903 303785 50         if (object != NULL) {
3904             // Extend mortal stack
3905 303785 100         if (*current_mortal_stack_top_ptr >= *current_mortal_stack_capacity_ptr) {
3906 359           int32_t new_mortal_stack_capacity = *current_mortal_stack_capacity_ptr * 2;
3907 359           SPVM_OBJECT** new_mortal_stack = SPVM_API_new_memory_block(env, stack, sizeof(void*) * new_mortal_stack_capacity);
3908 359 50         if (new_mortal_stack == NULL) {
3909 0           return SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_CLASS;
3910             }
3911 359           memcpy(new_mortal_stack, *current_mortal_stack_ptr, sizeof(void*) * *current_mortal_stack_capacity_ptr);
3912 359           *current_mortal_stack_capacity_ptr = new_mortal_stack_capacity;
3913 359           SPVM_API_free_memory_block(env, stack, *current_mortal_stack_ptr);
3914 359           *current_mortal_stack_ptr = NULL;
3915 359           *current_mortal_stack_ptr = new_mortal_stack;
3916             }
3917            
3918 303785           SPVM_API_assign_object(env, stack, &(*current_mortal_stack_ptr)[*current_mortal_stack_top_ptr], object);
3919            
3920 303785           *current_mortal_stack_top_ptr = *current_mortal_stack_top_ptr + 1;
3921             }
3922            
3923 303785           return 0;
3924             }
3925              
3926 1362921           void SPVM_API_leave_scope(SPVM_ENV* env, SPVM_VALUE* stack, int32_t original_mortal_stack_top) {
3927            
3928 1362921           SPVM_OBJECT*** current_mortal_stack_ptr = (SPVM_OBJECT***)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK];
3929 1362921           int32_t* current_mortal_stack_top_ptr = (int32_t*)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_TOP];
3930 1362921           int32_t* current_mortal_stack_capacity_ptr = (int32_t*)&stack[SPVM_API_C_STACK_INDEX_MORTAL_STACK_CAPACITY];
3931            
3932             int32_t mortal_stack_index;
3933 1666706 100         for (mortal_stack_index = original_mortal_stack_top; mortal_stack_index < *current_mortal_stack_top_ptr; mortal_stack_index++) {
3934            
3935 303785           SPVM_OBJECT** object_ref = &(*current_mortal_stack_ptr)[mortal_stack_index];
3936            
3937 303785           SPVM_API_assign_object(env, stack, object_ref, NULL);
3938            
3939             }
3940            
3941 1362921           *current_mortal_stack_top_ptr = original_mortal_stack_top;
3942 1362921           }
3943              
3944 1300815           void SPVM_API_leave_scope_local(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** object_vars, int32_t* mortal_stack, int32_t* mortal_stack_top_ptr, int32_t original_mortal_stack_top) {
3945            
3946 2131359 100         for (int32_t mortal_stack_index = original_mortal_stack_top; mortal_stack_index < *mortal_stack_top_ptr; mortal_stack_index++) {
3947 830544           int32_t var_index = mortal_stack[mortal_stack_index];
3948 830544           SPVM_OBJECT** object_ref = (SPVM_OBJECT**)&object_vars[var_index];
3949 830544 100         if (*object_ref != NULL) {
3950 810029           SPVM_API_assign_object(env, stack, object_ref, NULL);
3951             }
3952             }
3953 1300815           *mortal_stack_top_ptr = original_mortal_stack_top;
3954            
3955 1300815           }
3956              
3957 8304510           SPVM_OBJECT* SPVM_API_get_object_no_weaken_address(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
3958             // Dropping weaken flag
3959 8304510           void* object_no_weaken_address = (void*)((intptr_t)object & ~(intptr_t)1);
3960            
3961 8304510           return object_no_weaken_address;
3962             }
3963              
3964 1868562           int32_t SPVM_API_isweak_only_check_flag(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** ref) {
3965 1868562           int32_t isweak = (intptr_t)*ref & 1;
3966 1868562           return isweak;
3967             }
3968              
3969 4           int32_t SPVM_API_isweak(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** ref) {
3970 4           SPVM_RUNTIME* runtime = env->runtime;
3971            
3972 4 50         assert(ref);
3973            
3974 4 50         if (*ref == NULL) {
3975 0           return 0;
3976             }
3977            
3978 4           SPVM_OBJECT* object = SPVM_API_get_object_no_weaken_address(env, stack, *ref);
3979            
3980 4           SPVM_MUTEX* mutex_object = SPVM_API_get_object_mutex(env, stack, object);
3981            
3982 4           SPVM_MUTEX_lock(mutex_object);
3983            
3984 4           int32_t isweak = SPVM_API_isweak_only_check_flag(env, stack, ref);
3985            
3986 4           SPVM_MUTEX_unlock(mutex_object);
3987            
3988 4           return isweak;
3989             }
3990              
3991 384           int32_t SPVM_API_weaken(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** ref) {
3992            
3993 384 50         assert(ref);
3994            
3995 384 100         if (*ref == NULL) {
3996 2           return 0;
3997             }
3998            
3999 382           SPVM_OBJECT* object = SPVM_API_get_object_no_weaken_address(env, stack, *ref);
4000            
4001 382           SPVM_MUTEX* mutex_object = SPVM_API_get_object_mutex(env, stack, object);
4002            
4003 382           SPVM_MUTEX_lock(mutex_object);
4004            
4005 382           int32_t isweak = SPVM_API_isweak_only_check_flag(env, stack, ref);
4006            
4007 382           SPVM_OBJECT* destroied_referent = NULL;
4008 382 100         if (!isweak) {
4009            
4010 380           int32_t ref_count = SPVM_API_get_ref_count(env, stack, object);
4011            
4012 380 50         assert(ref_count > 0);
4013            
4014             // If reference count is 1, the object is destroied
4015 380 100         if (ref_count == 1) {
4016 2           destroied_referent = object;
4017 2           *ref = NULL;
4018             }
4019             else {
4020             // Weaken is implemented by tag pointer.
4021             // If pointer most right bit is 1, object is weaken.
4022 378           *ref = (SPVM_OBJECT*)((intptr_t)*ref | 1);
4023            
4024 378           SPVM_API_dec_ref_count(env, stack, object);
4025            
4026 378           SPVM_WEAKEN_BACKREF* new_weaken_backref = SPVM_API_new_memory_block(env, stack, sizeof(SPVM_WEAKEN_BACKREF));
4027 378           new_weaken_backref->ref = ref;
4028            
4029             // Create a new weaken back refference
4030 378 50         if (object->weaken_backref_head == NULL) {
4031 378           object->weaken_backref_head = new_weaken_backref;
4032             }
4033             // Add weaken back refference
4034             else {
4035 0           SPVM_WEAKEN_BACKREF* weaken_backref_next = object->weaken_backref_head;
4036            
4037 0 0         while (weaken_backref_next->next != NULL){
4038 0           weaken_backref_next = weaken_backref_next->next;
4039             }
4040 0           weaken_backref_next->next = new_weaken_backref;
4041             }
4042             }
4043             }
4044            
4045 382           SPVM_MUTEX_unlock(mutex_object);
4046            
4047 382 100         if (destroied_referent) {
4048 2           SPVM_API_assign_object(env, stack, &destroied_referent, NULL);
4049             }
4050            
4051 384           return 0;
4052             }
4053              
4054 5816348           void SPVM_API_unweaken_thread_unsafe(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** ref) {
4055            
4056 5816348 50         assert(ref);
4057            
4058 5816348 100         if (*ref == NULL) {
4059 3948172           return;
4060             }
4061            
4062 1868176           SPVM_OBJECT* object = SPVM_API_get_object_no_weaken_address(env, stack, *ref);
4063            
4064 1868176           int32_t isweak = SPVM_API_isweak_only_check_flag(env, stack, ref);
4065            
4066 1868176 100         if (isweak) {
4067            
4068 362 50         assert(object->weaken_backref_head);
4069            
4070             // Drop weaken flag
4071 362           *ref = (SPVM_OBJECT*)((intptr_t)*ref & ~(intptr_t)1);
4072            
4073 362           SPVM_API_inc_ref_count(env, stack, object);
4074            
4075             // Remove a weaken back reference
4076 362 50         assert(object->weaken_backref_head);
4077 362           SPVM_WEAKEN_BACKREF** weaken_backref_next_ptr = &object->weaken_backref_head;
4078 362 50         while (*weaken_backref_next_ptr != NULL){
4079 362 50         if ((*weaken_backref_next_ptr)->ref == ref) {
4080 362           SPVM_WEAKEN_BACKREF* tmp = (*weaken_backref_next_ptr)->next;
4081            
4082 362           SPVM_WEAKEN_BACKREF* weaken_backref_next = *weaken_backref_next_ptr;
4083            
4084 362           SPVM_API_free_memory_block(env, stack, weaken_backref_next);
4085 362           weaken_backref_next = NULL;
4086            
4087 362           *weaken_backref_next_ptr = tmp;
4088 362           break;
4089             }
4090 0           *weaken_backref_next_ptr = (*weaken_backref_next_ptr)->next;
4091             }
4092             }
4093            
4094             }
4095              
4096 0           void SPVM_API_unweaken(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** ref) {
4097            
4098 0 0         assert(ref);
4099            
4100 0 0         if (*ref == NULL) {
4101 0           return;
4102             }
4103            
4104 0           SPVM_OBJECT* object = SPVM_API_get_object_no_weaken_address(env, stack, *ref);
4105            
4106 0           SPVM_MUTEX* mutex_object = SPVM_API_get_object_mutex(env, stack, object);
4107            
4108 0           SPVM_MUTEX_lock(mutex_object);
4109            
4110 0           SPVM_API_unweaken_thread_unsafe(env, stack, ref);
4111            
4112 0           SPVM_MUTEX_unlock(mutex_object);
4113             }
4114              
4115 16           void SPVM_API_free_weaken_backrefs(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_WEAKEN_BACKREF* weaken_backref_head) {
4116            
4117 16           SPVM_WEAKEN_BACKREF* weaken_backref_head_cur = weaken_backref_head;
4118 16           SPVM_WEAKEN_BACKREF* weaken_backref_head_next = NULL;
4119 32 100         while (weaken_backref_head_cur != NULL){
4120 16           *(weaken_backref_head_cur->ref) = NULL;
4121 16           weaken_backref_head_next = weaken_backref_head_cur->next;
4122            
4123 16           SPVM_API_free_memory_block(env, stack, weaken_backref_head_cur);
4124 16           weaken_backref_head_cur = NULL;
4125 16           weaken_backref_head_cur = weaken_backref_head_next;
4126             }
4127 16           }
4128              
4129 5816348           void SPVM_API_assign_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT** ref, SPVM_OBJECT* object) {
4130            
4131 5816348           SPVM_RUNTIME* runtime = env->runtime;
4132            
4133 5816348           SPVM_MUTEX* runtime_mutex_update_object = runtime->mutex_update_object;
4134            
4135 5816348           SPVM_MUTEX_lock(runtime_mutex_update_object);
4136            
4137 5816348           SPVM_OBJECT* object_assign_off = SPVM_API_get_object_no_weaken_address(env, stack, *ref);
4138 5816348 100         if (object_assign_off) {
4139            
4140 1868176           SPVM_MUTEX* mutex_object_assign_off = SPVM_API_get_object_mutex(env, stack, object_assign_off);
4141            
4142 1868176           SPVM_MUTEX_lock(mutex_object_assign_off);
4143             }
4144            
4145 5816348 50         assert(!((intptr_t)object & 1));
4146            
4147 5816348           int32_t lock_object_mutex = 0;
4148 5816348 100         if (object && (object != object_assign_off)) {
    100          
4149 1868296           SPVM_MUTEX* object_mutex = SPVM_API_get_object_mutex(env, stack, object);
4150            
4151 1868296           SPVM_MUTEX_lock(object_mutex);
4152 1868296           lock_object_mutex = 1;
4153             }
4154            
4155 5816348           SPVM_MUTEX_unlock(runtime_mutex_update_object);
4156            
4157 5816348           SPVM_API_unweaken_thread_unsafe(env, stack, ref);
4158            
4159 5816348 100         if (object) {
4160 1868864           SPVM_API_inc_ref_count(env, stack, object);
4161             }
4162            
4163 5816348           *ref = object;
4164            
4165 5816348 100         if (object) {
4166 1868864           SPVM_MUTEX* object_mutex = SPVM_API_get_object_mutex(env, stack, object);
4167 1868864 100         if (lock_object_mutex) {
4168 1868296           SPVM_MUTEX_unlock(object_mutex);
4169             }
4170             }
4171            
4172 5816348 100         if (!object_assign_off) {
4173 3948172           return;
4174             }
4175            
4176 1868176           int32_t object_assign_off_ref_count = SPVM_API_get_ref_count(env, stack, object_assign_off);
4177            
4178 1868176 50         assert(object_assign_off_ref_count > 0);
4179            
4180 1868176           SPVM_MUTEX* mutex_object_assign_off = SPVM_API_get_object_mutex(env, stack, object_assign_off);
4181 1868176 100         if (object_assign_off_ref_count > 1) {
4182            
4183 1350320           SPVM_API_dec_ref_count(env, stack, object_assign_off);
4184 1350320           SPVM_MUTEX_unlock(mutex_object_assign_off);
4185            
4186 1350320           return;
4187             }
4188            
4189 517856           SPVM_MUTEX_unlock(mutex_object_assign_off);
4190            
4191             // Free object_assign_off array
4192 517856 100         if (SPVM_API_is_object_array(env, stack, object_assign_off)) {
4193 52930           int32_t length = SPVM_API_length(env, stack, object_assign_off);
4194 2256671 100         for (int32_t index = 0; index < length; index++) {
4195 2203741           SPVM_OBJECT** ref = &(((SPVM_OBJECT**)((intptr_t)object_assign_off + SPVM_API_RUNTIME_get_object_data_offset(env->runtime)))[index]);
4196 2203741           SPVM_API_assign_object(env, stack, ref, NULL);
4197             }
4198             }
4199             // Free object_assign_off
4200             else {
4201 464926           SPVM_RUNTIME_BASIC_TYPE* object_assign_off_basic_type = SPVM_API_get_object_basic_type(env, stack, object_assign_off);
4202 464926           int32_t object_assign_off_basic_type_category = object_assign_off_basic_type->category;
4203 464926 100         if (object_assign_off_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS) {
4204             // Class
4205 300297           SPVM_RUNTIME* runtime = env->runtime;
4206            
4207             // Call destructor
4208 300297 100         if (object_assign_off_basic_type->destructor_method) {
4209            
4210 706           SPVM_VALUE save_stack0 = stack[0];
4211 706           SPVM_OBJECT* save_exception = SPVM_API_get_exception(env, stack);
4212 706           SPVM_OBJECT* save_exception_referent = NULL;
4213 706           SPVM_API_assign_object(env, stack, &save_exception_referent, save_exception);
4214            
4215 706           SPVM_RUNTIME_METHOD* destructor_method = SPVM_API_BASIC_TYPE_get_method_by_index(env->runtime, object_assign_off_basic_type, object_assign_off_basic_type->destructor_method->index);
4216            
4217 706           stack[0].oval = object_assign_off;
4218 706           int32_t args_width = 1;
4219 706           int32_t error_id = SPVM_API_call_method_no_mortal(env, stack, destructor_method, args_width);
4220            
4221             // Exception in destructor is changed to warning
4222 706 100         if (error_id) {
4223 2           void* exception = SPVM_API_get_exception(env, stack);
4224 2           const char* exception_chars = SPVM_API_get_chars(env, stack, exception);
4225 2           fprintf(runtime->spvm_stderr, "[The following exception is coverted to a warning because it is thrown in the DESTROY method]\n%s\n", exception_chars);
4226             }
4227            
4228             // Restore stack and exception
4229 706           stack[0] = save_stack0;
4230 706           SPVM_API_set_exception(env, stack, save_exception);
4231 706           SPVM_API_assign_object(env, stack, &save_exception_referent, NULL);
4232             }
4233            
4234             // Free object_assign_off fields
4235 300297           int32_t object_assign_off_fields_length = object_assign_off_basic_type->fields_length;
4236 608482 100         for (int32_t field_index = 0; field_index < object_assign_off_fields_length; field_index++) {
4237 308185           SPVM_RUNTIME_FIELD* field = SPVM_API_BASIC_TYPE_get_field_by_index(runtime, object_assign_off_basic_type, field_index);
4238            
4239 308185           void* field_basic_type = field->basic_type;
4240 308185           int32_t field_type_dimension = field->type_dimension;
4241 308185           int32_t field_type_flag = field->type_flag;
4242 308185           int32_t field_type_is_object_assign_off = SPVM_API_TYPE_is_object_type(runtime, field_basic_type, field_type_dimension, field_type_flag);
4243            
4244 308185 100         if (field_type_is_object_assign_off) {
4245 252297           SPVM_OBJECT** ref = (SPVM_OBJECT**)((intptr_t)object_assign_off + (size_t)SPVM_API_RUNTIME_get_object_data_offset(env->runtime) + field->offset);
4246 252297           SPVM_API_assign_object(env, stack, ref, NULL);
4247             }
4248             }
4249             }
4250            
4251             }
4252            
4253 517856           SPVM_MUTEX_lock(mutex_object_assign_off);
4254            
4255 517856           SPVM_API_dec_ref_count(env, stack, object_assign_off);
4256            
4257 517856           object_assign_off_ref_count = SPVM_API_get_ref_count(env, stack, object_assign_off);
4258            
4259 517856 50         if (object_assign_off_ref_count > 0) {
4260 0           SPVM_MUTEX_unlock(mutex_object_assign_off);
4261             }
4262 517856 50         else if (object_assign_off_ref_count == 0) {
4263            
4264             // Free weak back refenreces
4265 517856 100         if (object_assign_off->weaken_backref_head != NULL) {
4266 16           SPVM_API_free_weaken_backrefs(env, stack, object_assign_off->weaken_backref_head);
4267 16           object_assign_off->weaken_backref_head = NULL;
4268             }
4269            
4270 517856           SPVM_MUTEX_unlock(mutex_object_assign_off);
4271 517856           SPVM_MUTEX_destroy(mutex_object_assign_off);
4272            
4273             // Free object_assign_off
4274 517856           SPVM_API_free_memory_block(env, stack, object_assign_off);
4275 517856           object_assign_off = NULL;
4276             }
4277             else {
4278 0           assert(0);
4279             }
4280             }
4281              
4282 2264607           void SPVM_API_inc_ref_count(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
4283            
4284 2264607 50         if (object != NULL) {
4285 2264607           int32_t ref_count = SPVM_API_get_ref_count(env, stack, object);
4286 2264607 50         assert(ref_count >= 0);
4287            
4288 2264607           object->ref_count++;
4289             }
4290            
4291 2264607           }
4292              
4293 2263935           void SPVM_API_dec_ref_count(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
4294            
4295 2263935           SPVM_RUNTIME* runtime = env->runtime;
4296            
4297 2263935 50         if (object != NULL) {
4298 2263935           int32_t ref_count = SPVM_API_get_ref_count(env, stack, object);
4299 2263935 50         assert(ref_count > 0);
4300            
4301 2263935           object->ref_count--;
4302             }
4303            
4304 2263935           }
4305              
4306 6914980           int32_t SPVM_API_get_ref_count(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
4307            
4308 6914980           int32_t ref_count = object->ref_count;
4309            
4310 6914980           return ref_count;
4311             }
4312              
4313 8961954           SPVM_MUTEX* SPVM_API_get_object_mutex(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
4314            
4315 8961954           SPVM_MUTEX* object_mutex = (SPVM_MUTEX*)((intptr_t)object + sizeof(SPVM_OBJECT));
4316            
4317 8961954           return object_mutex;
4318             }
4319              
4320 178766           void SPVM_API_lock_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
4321            
4322 178766           SPVM_MUTEX* object_mutex = SPVM_API_get_object_mutex(env, stack, object);
4323            
4324 178766           SPVM_MUTEX_lock(object_mutex);
4325 178766           }
4326              
4327 178766           void SPVM_API_unlock_object(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJECT* object) {
4328            
4329 178766           SPVM_MUTEX* object_mutex = SPVM_API_get_object_mutex(env, stack, object);
4330            
4331 178766           SPVM_MUTEX_unlock(object_mutex);
4332 178766           }
4333