]> gitweb.factorcode.org Git - factor.git/blob - vm/errors.cpp
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / vm / errors.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Global variables used to pass fault handler state from signal handler to
7 user-space */
8 cell signal_number;
9 cell signal_fault_addr;
10 stack_frame *signal_callstack_top;
11
12 void out_of_memory()
13 {
14         print_string("Out of memory\n\n");
15         dump_generations();
16         exit(1);
17 }
18
19 void fatal_error(const char* msg, cell tagged)
20 {
21         print_string("fatal_error: "); print_string(msg);
22         print_string(": "); print_cell_hex(tagged); nl();
23         exit(1);
24 }
25
26 void critical_error(const char* msg, cell tagged)
27 {
28         print_string("You have triggered a bug in Factor. Please report.\n");
29         print_string("critical_error: "); print_string(msg);
30         print_string(": "); print_cell_hex(tagged); nl();
31         factorbug();
32 }
33
34 void throw_error(cell error, stack_frame *callstack_top)
35 {
36         /* If the error handler is set, we rewind any C stack frames and
37         pass the error to user-space. */
38         if(userenv[BREAK_ENV] != F)
39         {
40                 /* If error was thrown during heap scan, we re-enable the GC */
41                 gc_off = false;
42
43                 /* Reset local roots */
44                 gc_locals.clear();
45                 gc_bignums.clear();
46
47                 /* If we had an underflow or overflow, stack pointers might be
48                 out of bounds */
49                 fix_stacks();
50
51                 dpush(error);
52
53                 /* Errors thrown from C code pass NULL for this parameter.
54                 Errors thrown from Factor code, or signal handlers, pass the
55                 actual stack pointer at the time, since the saved pointer is
56                 not necessarily up to date at that point. */
57                 if(callstack_top)
58                 {
59                         callstack_top = fix_callstack_top(callstack_top,
60                                 stack_chain->callstack_bottom);
61                 }
62                 else
63                         callstack_top = stack_chain->callstack_top;
64
65                 throw_impl(userenv[BREAK_ENV],callstack_top);
66         }
67         /* Error was thrown in early startup before error handler is set, just
68         crash. */
69         else
70         {
71                 print_string("You have triggered a bug in Factor. Please report.\n");
72                 print_string("early_error: ");
73                 print_obj(error);
74                 nl();
75                 factorbug();
76         }
77 }
78
79 void general_error(vm_error_type error, cell arg1, cell arg2,
80         stack_frame *callstack_top)
81 {
82         throw_error(allot_array_4(userenv[ERROR_ENV],
83                 tag_fixnum(error),arg1,arg2),callstack_top);
84 }
85
86 void type_error(cell type, cell tagged)
87 {
88         general_error(ERROR_TYPE,tag_fixnum(type),tagged,NULL);
89 }
90
91 void not_implemented_error()
92 {
93         general_error(ERROR_NOT_IMPLEMENTED,F,F,NULL);
94 }
95
96 /* Test if 'fault' is in the guard page at the top or bottom (depending on
97 offset being 0 or -1) of area+area_size */
98 bool in_page(cell fault, cell area, cell area_size, int offset)
99 {
100         int pagesize = getpagesize();
101         area += area_size;
102         area += offset * pagesize;
103
104         return fault >= area && fault <= area + pagesize;
105 }
106
107 void memory_protection_error(cell addr, stack_frame *native_stack)
108 {
109         if(in_page(addr, ds_bot, 0, -1))
110                 general_error(ERROR_DS_UNDERFLOW,F,F,native_stack);
111         else if(in_page(addr, ds_bot, ds_size, 0))
112                 general_error(ERROR_DS_OVERFLOW,F,F,native_stack);
113         else if(in_page(addr, rs_bot, 0, -1))
114                 general_error(ERROR_RS_UNDERFLOW,F,F,native_stack);
115         else if(in_page(addr, rs_bot, rs_size, 0))
116                 general_error(ERROR_RS_OVERFLOW,F,F,native_stack);
117         else if(in_page(addr, nursery.end, 0, 0))
118                 critical_error("allot_object() missed GC check",0);
119         else
120                 general_error(ERROR_MEMORY,allot_cell(addr),F,native_stack);
121 }
122
123 void signal_error(int signal, stack_frame *native_stack)
124 {
125         general_error(ERROR_SIGNAL,tag_fixnum(signal),F,native_stack);
126 }
127
128 void divide_by_zero_error()
129 {
130         general_error(ERROR_DIVIDE_BY_ZERO,F,F,NULL);
131 }
132
133 void fp_trap_error()
134 {
135         general_error(ERROR_FP_TRAP,F,F,NULL);
136 }
137
138 PRIMITIVE(call_clear)
139 {
140         throw_impl(dpop(),stack_chain->callstack_bottom);
141 }
142
143 /* For testing purposes */
144 PRIMITIVE(unimplemented)
145 {
146         not_implemented_error();
147 }
148
149 void memory_signal_handler_impl()
150 {
151         memory_protection_error(signal_fault_addr,signal_callstack_top);
152 }
153
154 void misc_signal_handler_impl()
155 {
156         signal_error(signal_number,signal_callstack_top);
157 }
158
159 void fp_signal_handler_impl()
160 {
161     fp_trap_error();
162 }
163
164 }