]> gitweb.factorcode.org Git - factor.git/blob - vm/callstack.cpp
VM: removing the get_datastack/retainstack/callstack primitives
[factor.git] / vm / callstack.cpp
1 #include "master.hpp"
2
3 namespace factor {
4
5 /* Allocates memory (allot) */
6 callstack* factor_vm::allot_callstack(cell size) {
7   callstack* stack = allot<callstack>(callstack_object_size(size));
8   stack->length = tag_fixnum(size);
9   return stack;
10 }
11
12 /* We ignore the two topmost frames, the 'callstack' primitive
13 frame itself, and the frame calling the 'callstack' primitive,
14 so that set-callstack doesn't get stuck in an infinite loop.
15
16 This means that if 'callstack' is called in tail position, we
17 will have popped a necessary frame... however this word is only
18 called by continuation implementation, and user code shouldn't
19 be calling it at all, so we leave it as it is for now. */
20 cell factor_vm::second_from_top_stack_frame(context* ctx) {
21   cell frame_top = ctx->callstack_top;
22   for (cell i = 0; i < 2; ++i) {
23     cell pred = code->frame_predecessor(frame_top);
24     if (pred >= ctx->callstack_bottom)
25       return frame_top;
26     frame_top = pred;
27   }
28   return frame_top;
29 }
30
31 /* Allocates memory (allot_callstack) */
32 cell factor_vm::capture_callstack(context* ctx) {
33   cell top = second_from_top_stack_frame(ctx);
34   cell bottom = ctx->callstack_bottom;
35
36   fixnum size = std::max((cell)0, bottom - top);
37
38   callstack* stack = allot_callstack(size);
39   memcpy(stack->top(), (void *)top, size);
40   return tag<callstack>(stack);
41 }
42
43 /* Allocates memory (capture_callstack) */
44 void factor_vm::primitive_callstack_for() {
45   context* other_ctx = (context*)pinned_alien_offset(ctx->peek());
46   ctx->replace(capture_callstack(other_ctx));
47 }
48
49 struct stack_frame_in_array {
50   cell cells[3];
51 };
52
53 /* Allocates memory (frames.trim()), iterate_callstack_object() */
54 void factor_vm::primitive_callstack_to_array() {
55   data_root<callstack> callstack(ctx->peek(), this);
56   /* Allocates memory here. */
57   growable_array frames(this);
58
59   auto stack_frame_accumulator = [&](cell frame_top,
60                                      cell size,
61                                      code_block* owner,
62                                      cell addr) {
63     data_root<object> executing_quot(owner->owner_quot(), this);
64     data_root<object> executing(owner->owner, this);
65     data_root<object> scan(owner->scan(this, addr), this);
66
67     frames.add(executing.value());
68     frames.add(executing_quot.value());
69     frames.add(scan.value());
70   };
71   iterate_callstack_object(callstack.untagged(), stack_frame_accumulator);
72
73   /* The callstack iterator visits frames in reverse order (top to bottom) */
74   std::reverse((stack_frame_in_array*)frames.elements->data(),
75                (stack_frame_in_array*)(frames.elements->data() +
76                                        frames.count));
77   frames.trim();
78
79   ctx->replace(frames.elements.value());
80 }
81
82 /* Some primitives implementing a limited form of callstack mutation.
83 Used by the single stepper. */
84 void factor_vm::primitive_innermost_stack_frame_executing() {
85   callstack* stack = untag_check<callstack>(ctx->peek());
86   void* frame = stack->top();
87   cell addr = *(cell*)frame;
88   ctx->replace(code->code_block_for_address(addr)->owner_quot());
89 }
90
91 void factor_vm::primitive_innermost_stack_frame_scan() {
92   callstack* stack = untag_check<callstack>(ctx->peek());
93   void* frame = stack->top();
94   cell addr = *(cell*)frame;
95   ctx->replace(code->code_block_for_address(addr)->scan(this, addr));
96 }
97
98 /* Allocates memory (jit_compile_quotation) */
99 void factor_vm::primitive_set_innermost_stack_frame_quotation() {
100   data_root<callstack> stack(ctx->pop(), this);
101   data_root<quotation> quot(ctx->pop(), this);
102
103   stack.untag_check(this);
104   quot.untag_check(this);
105
106   jit_compile_quotation(quot.value(), true);
107
108   void* inner = stack->top();
109   cell addr = *(cell*)inner;
110   code_block* block = code->code_block_for_address(addr);
111   cell offset = block->offset(addr);
112   *(cell*)inner = quot->entry_point + offset;
113 }
114
115 /* Allocates memory (allot_alien) */
116 void factor_vm::primitive_callstack_bounds() {
117   ctx->push(allot_alien((void*)ctx->callstack_seg->start));
118   ctx->push(allot_alien((void*)ctx->callstack_seg->end));
119 }
120
121 }