Skip to content

Commit 8ae0c90

Browse files
committed
feat: interface to value
1 parent ee5234e commit 8ae0c90

File tree

13 files changed

+118
-70
lines changed

13 files changed

+118
-70
lines changed

runtime/collector.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,14 @@ static void scan_stack(n_processor_t *p, coroutine_t *co) {
350350
}
351351

352352

353-
if (co->error) {
354-
insert_gc_worklist(worklist, co->error);
353+
if (co->has_error) {
354+
if (co->error.value.ptr_value && span_of((addr_t) co->error.value.ptr_value)) {
355+
insert_gc_worklist(worklist, co->error.value.ptr_value);
356+
}
357+
358+
if (co->error.methods && span_of((addr_t) co->error.methods)) {
359+
insert_gc_worklist(worklist, co->error.methods);
360+
}
355361
}
356362

357363
if (co->traces.data && span_of((addr_t) co->traces.data)) {

runtime/nutils/errort.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ static inline n_string_t rti_error_msg(n_interface_t *error) {
2626
* @param has
2727
* @return
2828
*/
29-
static inline n_interface_t *n_error_new(n_string_t msg, uint8_t panic) {
29+
static inline n_interface_t n_error_new(n_string_t msg, uint8_t panic) {
3030
n_errort *errort = rti_gc_malloc(errort_rtype.gc_heap_size, &errort_rtype);
3131
errort->msg = msg;
3232
errort->panic = panic;
3333
DEBUGF("[runtime.n_error_new] errort=%p, msg=%p, panic=%d", errort, msg, panic);
3434

3535
// interface casting, error to interface union
3636
int64_t methods[1] = {(int64_t) errort_msg};
37-
n_interface_t *result = interface_casting(errort_rtype.hash, errort, 1, methods);
37+
n_interface_t result = {0};
38+
interface_casting(&result, errort_rtype.hash, errort, 1, methods);
3839

3940
return result;
4041
}

runtime/nutils/fs.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fs_context_t *rt_uv_fs_open(n_string_t path, int64_t flags, int64_t mode) {
125125

126126
global_waiting_send(uv_async_fs_open, ctx, rt_string_ref(&path), 0);
127127
if (co->has_error) {
128-
n_string_t msg = rti_error_msg(co->error);
128+
n_string_t msg = rti_error_msg(&co->error);
129129
DEBUGF("[fs_open] open file failed: %s", (char *) rt_string_ref(&msg));
130130
return NULL;
131131
} else {
@@ -165,7 +165,7 @@ n_int_t rt_uv_fs_read_at(fs_context_t *ctx, n_vec_t buf, int offset) {
165165
global_waiting_send(uv_async_fs_read_at, ctx, (void *) offset, 0);
166166

167167
if (co->has_error) {
168-
n_string_t msg = rti_error_msg(co->error);
168+
n_string_t msg = rti_error_msg(&co->error);
169169
DEBUGF("[rt_uv_fs_read] read file failed: %s", (char *) rt_string_ref(&msg));
170170
return 0;
171171
} else {
@@ -200,7 +200,7 @@ n_int_t rt_uv_fs_write_at(fs_context_t *ctx, n_vec_t buf, int offset) {
200200
global_waiting_send(uv_async_fs_write_at, ctx, &buf, (void *) (int64_t) offset);
201201

202202
if (co->has_error) {
203-
n_string_t msg = rti_error_msg(co->error);
203+
n_string_t msg = rti_error_msg(&co->error);
204204
DEBUGF("[fs_write_at] write file failed: %s", (char *) rt_string_ref(&msg));
205205
} else {
206206
DEBUGF("[fs_write_at] write file success");
@@ -288,7 +288,7 @@ uv_stat_t rt_uv_fs_stat(fs_context_t *ctx) {
288288
global_waiting_send(uv_async_fs_stat, ctx, co, 0);
289289

290290
if (co->has_error) {
291-
n_string_t msg = rti_error_msg(co->error);
291+
n_string_t msg = rti_error_msg(&co->error);
292292
DEBUGF("[rt_uv_fs_stat] stat file failed: %s", (char *) rt_string_ref(&msg));
293293
} else {
294294
DEBUGF("[rt_uv_fs_stat] stat file success");

runtime/nutils/nutils.c

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -126,61 +126,60 @@ bool interface_is(n_interface_t *mu, int64_t target_rtype_hash) {
126126
}
127127

128128
/**
129-
* union 参考 env 中的 upvalue 处理超过 8byte 的数据
129+
* interface 参考 any 处理 storage_ind 类型
130+
* @param out
130131
* @param input_rtype_hash
131-
* @param value
132-
* @return
132+
* @param value_ref
133+
* @param method_count
134+
* @param methods
133135
*/
134-
n_interface_t *interface_casting(uint64_t input_rtype_hash, void *value_ref, int64_t method_count, int64_t *methods) {
136+
void interface_casting(n_interface_t *out, uint64_t input_rtype_hash, void *value_ref, int64_t method_count, int64_t *methods) {
137+
assert(out && "interface_casting out is null");
135138
// - 根据 input_rtype_hash 找到对应的
136139
rtype_t *rtype = rt_find_rtype(input_rtype_hash);
137140
assert(rtype && "cannot find rtype by hash");
138141

139142
ASSERT_ADDR(value_ref);
140143

141-
TRACEF("[union_casting] input_kind=%s", type_kind_str[rtype->kind]);
142-
143-
144-
rtype_t interface_rtype = GC_RTYPE(TYPE_INTERFACE, 4, TYPE_GC_SCAN, TYPE_GC_SCAN, TYPE_GC_NOSCAN, TYPE_GC_NOSCAN);
145-
146-
// any_t 在 element_rtype list 中是可以预注册的,因为其 gc_bits 不会变来变去的,都是恒定不变的!
147-
n_interface_t *mu = rti_gc_malloc(sizeof(n_interface_t), &interface_rtype);
144+
TRACEF("[interface_casting] input_kind=%s", type_kind_str[rtype->kind]);
148145

149146
if (method_count > 0) {
150-
mu->method_count = method_count;
151-
mu->methods = (int64_t *) rti_array_new(&uint64_rtype, method_count);
147+
out->method_count = method_count;
148+
out->methods = (int64_t *) rti_array_new(&uint64_rtype, method_count);
152149
// 进行数据 copy TODO write barrier
153-
memmove(mu->methods, methods, method_count * POINTER_SIZE);
150+
memmove(out->methods, methods, method_count * POINTER_SIZE);
151+
} else {
152+
out->method_count = 0;
153+
out->methods = NULL;
154154
}
155155

156156
DEBUGF(
157157
"[interface_casting] union_base: %p, memmove value_ref(%p) -> any->value(%p), size=%lu, fetch_value_8byte=%p",
158-
mu, value_ref,
159-
&mu->value, rtype->stack_size, (void *) fetch_addr_value((addr_t) value_ref));
158+
out, value_ref,
159+
&out->value, rtype->storage_size, (void *) fetch_addr_value((addr_t) value_ref));
160160

161-
mu->rtype = rtype;
161+
out->rtype = rtype;
162162
uint64_t stack_size = rtype->storage_size;
163+
out->value.i64_value = 0;
163164

164165
if (rtype->storage_kind != STORAGE_KIND_PTR) {
165166
// TODO number 可以直接存储在 value 中
166167
// union 进行了数据的额外缓存,并进行值 copy,不需要担心 arr/struct 这样的大数据的丢失问题
167168
void *new_value = rti_gc_malloc(rtype->gc_heap_size, rtype);
168169
memmove(new_value, value_ref, stack_size);
169-
rti_write_barrier_ptr(&mu->value.ptr_value, new_value, false);
170+
out->value.ptr_value = new_value;
170171
} else {
171172
// 特殊类型参数处理,为了兼容 fn method 中的 self 自动化参数, self 如果是 int/struct 等类型,会自动转换为 ref<int>
172173
// 如果是 vec/string 等类型,self 的类型依旧是 vec/string 等,而不是 ref<vec>/ref<string> 这有点多余, 因为 vec/string
173174
// 本来就是在堆中分配的, 传递的是一个指针, 虽然后续可以能会进行统一处理,但是目前还是需要进行特殊处理,value 中直接存放可以作为
174175
// fn method 传递的参数
175-
memmove(&mu->value, value_ref, stack_size);
176+
memmove(&out->value, value_ref, stack_size);
176177
}
177178

178179
DEBUGF("[interface_casting] success, union_base: %p, union_rtype: %p, union_i64_value: %ld, union_ptr_value: %p",
179-
mu,
180-
mu->rtype,
181-
mu->value.i64_value, mu->value.ptr_value);
182-
183-
return mu;
180+
out,
181+
out->rtype,
182+
out->value.i64_value, out->value.ptr_value);
184183
}
185184

186185
/**
@@ -488,7 +487,7 @@ void co_throw_error(n_interface_t *error, char *path, char *fn_name, n_int_t lin
488487
};
489488
rt_vec_push(&co->traces, errort_trace_rtype.hash, &trace);
490489

491-
rti_write_barrier_ptr(&co->error, error, false);
490+
rti_write_barrier_rtype(&co->error, error, &throwable_rtype);
492491
co->has_error = true;
493492
}
494493

@@ -504,10 +503,10 @@ void throw_index_out_error(n_int_t *index, n_int_t *len, n_bool_t be_catch) {
504503
char *msg = tlsprintf("index out of range [%d] with length %d", index, len);
505504

506505
if (be_catch) {
507-
n_interface_t *error = n_error_new(string_new(msg, strlen(msg)), true);
508-
assert(error->method_count == 1);
506+
n_interface_t error = n_error_new(string_new(msg, strlen(msg)), true);
507+
assert(error.method_count == 1);
509508

510-
DEBUGF("[runtime.co_throw_error_msg] co=%p, error=%p, msg=%s", co, (void *) error, (char *) msg);
509+
DEBUGF("[runtime.co_throw_error_msg] co=%p, error=%p, msg=%s", co, (void *) &error, (char *) msg);
511510

512511
assert(co->traces.data == NULL);
513512

@@ -522,7 +521,7 @@ void throw_index_out_error(n_int_t *index, n_int_t *len, n_bool_t be_catch) {
522521
.column = caller->column,
523522
};
524523
rt_vec_push(&co->traces, errort_trace_rtype.hash, &trace);
525-
rti_write_barrier_ptr(&co->error, error, false);
524+
rti_write_barrier_rtype(&co->error, &error, &throwable_rtype);
526525
co->has_error = true;
527526
} else {
528527
char *copy_msg = strdup(msg);
@@ -531,15 +530,16 @@ void throw_index_out_error(n_int_t *index, n_int_t *len, n_bool_t be_catch) {
531530
}
532531
}
533532

534-
n_interface_t *co_remove_error() {
533+
n_interface_t co_remove_error() {
535534
coroutine_t *co = coroutine_get();
536535

537-
assert(co->error);
536+
assert(co->has_error);
538537
co->has_error = false;
539538

540-
n_interface_t *error = co->error;
539+
n_interface_t error = co->error;
541540

542-
rti_write_barrier_ptr(&co->error, NULL, false);
541+
n_interface_t empty = {0};
542+
rti_write_barrier_rtype(&co->error, &empty, &throwable_rtype);
543543
co->traces = (n_vec_t){0};
544544
return error;
545545
}
@@ -569,11 +569,11 @@ uint8_t co_has_panic(bool be_catch, char *path, char *fn_name, n_int_t line, n_i
569569
return 1;
570570
}
571571

572-
assert(co->error);
572+
assert(co->has_error);
573573

574574
// 在 runtime 调用 nature 代码, rti_error_msg 会让 gc scan_stack 异常,不过马上就要退出了,问题不大
575575
// 可以考虑增加 safepoint_lock, 避免进入 safepoint 状态
576-
n_string_t msg = rti_error_msg(co->error);
576+
n_string_t msg = rti_error_msg(&co->error);
577577

578578
char *dump_msg;
579579
if (co->main) {

runtime/nutils/nutils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void union_to_any(n_any_t *out, n_union_t *input);
3939

4040
void tagged_union_casting(n_tagged_union_t *out, int64_t id, int64_t value_rtype_hash, void *value_ref);
4141

42-
n_interface_t *interface_casting(uint64_t input_rtype_hash, void *value_ref, int64_t method_count, int64_t *methods);
42+
void interface_casting(n_interface_t *out, uint64_t input_rtype_hash, void *value_ref, int64_t method_count, int64_t *methods);
4343

4444
int64_t iterator_next_key(void *iterator, uint64_t rtype_hash, int64_t cursor, void *key_ref);
4545

@@ -51,7 +51,7 @@ void co_throw_error(n_interface_t *error, char *path, char *fn_name, n_int_t lin
5151

5252
void throw_index_out_error(n_int_t *index, n_int_t *len, n_bool_t be_catch);
5353

54-
n_interface_t *co_remove_error();
54+
n_interface_t co_remove_error();
5555

5656
uint8_t co_has_error(char *path, char *fn_name, n_int_t line, n_int_t column);
5757

runtime/nutils/process.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ typedef struct {
1919
n_string_t cwd;
2020
n_vec_t env;
2121

22-
n_interface_t *io_stdin;
23-
n_interface_t *io_stdout;
24-
n_interface_t *io_stderr;
22+
n_interface_t io_stdin;
23+
n_interface_t io_stdout;
24+
n_interface_t io_stderr;
2525
} command_t;
2626

2727
typedef struct {

runtime/processor.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,13 @@ NO_OPTIMIZE static void coroutine_wrapper() {
250250

251251

252252
DEBUGF(
253-
"[runtime.coroutine_wrapper] user fn completed, p_index=%d co=%p, main=%d, rt_fn=%d,err=%p",
253+
"[runtime.coroutine_wrapper] user fn completed, p_index=%d co=%p, main=%d, rt_fn=%d,has_error=%d",
254254
p->index, co,
255-
co->main, co->flag & FLAG(CO_FLAG_RTFN), co->error);
255+
co->main, co->flag & FLAG(CO_FLAG_RTFN), co->has_error);
256256

257257

258258
// coroutine 即将退出,避免被 gc 清理,所以将 error保存在 co->future 中?
259-
if (co->error && co->future) {
259+
if (co->has_error && co->future) {
260260
union_casting(&co->future->error, throwable_rtype.hash, &co->error); // 将 co error 赋值给 co->future 避免被 gc
261261
}
262262

@@ -616,30 +616,30 @@ coroutine_t *coroutine_get() {
616616
void rti_throw(char *msg, bool panic) {
617617
DEBUGF("[runtime.rti_throw] msg=%s", msg);
618618
coroutine_t *co = coroutine_get();
619-
n_interface_t *error = n_error_new(string_new(msg, strlen(msg)), panic);
619+
n_interface_t error = n_error_new(string_new(msg, strlen(msg)), panic);
620620

621621
co->has_error = true;
622622
if (co->traces.data == NULL) {
623623
n_vec_t traces = rti_vec_new(&errort_trace_rtype, 0, 0);
624624
co->traces = traces;
625625
}
626-
rti_write_barrier_ptr(&co->error, error, false);
626+
rti_write_barrier_rtype(&co->error, &error, &throwable_rtype);
627627
}
628628

629629
void rti_co_throw(coroutine_t *co, char *msg, bool panic) {
630-
n_interface_t *error = n_error_new(string_new(msg, strlen(msg)), panic);
630+
n_interface_t error = n_error_new(string_new(msg, strlen(msg)), panic);
631631
co->has_error = true;
632632
if (co->traces.data == NULL) {
633633
n_vec_t traces = rti_vec_new(&errort_trace_rtype, 0, 0);
634634
co->traces = traces;
635635
}
636-
rti_write_barrier_ptr(&co->error, error, false);
636+
rti_write_barrier_rtype(&co->error, &error, &throwable_rtype);
637637
}
638638

639639
void coroutine_dump_error(coroutine_t *co) {
640-
DEBUGF("[runtime.coroutine_dump_error] co=%p, errort base=%p", co, co->error);
640+
DEBUGF("[runtime.coroutine_dump_error] co=%p, errort base=%p", co, &co->error);
641641

642-
n_string_t msg = rti_error_msg(co->error);
642+
n_string_t msg = rti_error_msg(&co->error);
643643
DEBUGF("[runtime.coroutine_dump_error] memory_string len: %lu, base: %p", msg.length, msg.data);
644644

645645
assert(co->traces.length > 0);
@@ -726,6 +726,10 @@ coroutine_t *rt_coroutine_new(void *fn, int64_t flag, n_future_t *fu, void *arg)
726726
co->status = CO_STATUS_RUNNABLE;
727727
co->p = NULL;
728728
co->next = NULL;
729+
co->has_error = false;
730+
co->error = (n_interface_t){0};
731+
co->traces = (n_vec_t){0};
732+
co->await_co = NULL;
729733
co->aco.inited = 0; // 标记为为初始化
730734

731735
return co;

runtime/rtype.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ static inline void builtin_rtype_init() {
137137
TYPE_GC_NOSCAN, TYPE_GC_NOSCAN);
138138
sc_map_put_64v(&rt_rtype_map, errort_trace_rtype.hash, &errort_trace_rtype);
139139

140-
throwable_rtype = GC_RTYPE(TYPE_INTERFACE, 4, TYPE_GC_SCAN, TYPE_GC_NOSCAN, TYPE_GC_NOSCAN, TYPE_GC_SCAN);
140+
throwable_rtype = GC_RTYPE(TYPE_INTERFACE, 4, TYPE_GC_SCAN, TYPE_GC_SCAN, TYPE_GC_NOSCAN, TYPE_GC_NOSCAN);
141141
sc_map_put_64v(&rt_rtype_map, throwable_rtype.hash, &throwable_rtype);
142142

143143
// 初始化错误 rtype

runtime/runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ struct coroutine_t {
421421
// uint64_t scan_ret_addr;
422422

423423
bool has_error;
424-
n_interface_t *error; // throwable
424+
n_interface_t error; // throwable
425425
n_vec_t traces; // element is n_trace_t
426426

427427
ATOMIC int32_t select_done;

0 commit comments

Comments
 (0)