home *** CD-ROM | disk | FTP | other *** search
-
- /* Copyright (C) 1988, 1989 Herve' Touati, Aquarius Project, UC Berkeley */
-
- /* Copyright Herve' Touati, Aquarius Project, UC Berkeley */
-
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <stream.h>
- #include "hash_table.h"
- #include "string_table.h"
- #include "tags.h"
- #include "instr.h"
- #include "scan.h"
- #include "memory.h"
- #include "inst_args.h"
- #include "inst_table.h"
- #include "assembler.h"
- #include "main.h"
- #include "top_level.h"
- #include "basics.h"
- #include "control.h"
- #include "compile.h"
- #include "arg_types.h"
- #ifdef WITH_GC
- #include "gc.h"
- #endif
-
- Command commands[] = {
- #define NAMES
- #define use(String,ID,Function,ARGTYPE)\
- {String, ID, &Function, ARGTYPE},
- #include "commands.h"
- #undef use
- #undef NAMES
- };
-
- static Scan command_scanner;
- static HashTable command_ID;
- typedef int (*IPF)();
- extern PF set_new_handler(PF);
- extern void out_of_store();
- void init_commands()
- {
- IPF signal(...);
-
- for (int i = 0; i < LAST_COMMAND; i++)
- command_ID.bind(command_scanner.intern(commands[i].name), commands[i].ID);
- signal(SIGINT, &service_interrupt);
- signal(SIGILL, &service_illegal_instruction);
- signal(SIGBUS, &service_bus_error);
- signal(SIGSEGV, &service_segmentation_fault);
- set_new_handler(&out_of_store);
- }
-
- void execute_command()
- {
- int ID = command_ID.get(command_scanner.intern_p0);
- Command* C = &commands[ID];
- int arg = instr_args[C->arg_type]->fill(command_scanner.p[1]);
- (*(C->exec))(arg);
- }
-
- char* prompt = "> ";
-
- void DisplayMemSize(int)
- {
- #define use(Name,ID,Coeff,Reg,Type)\
- cout << Name << " = " << memory_sizes[ID] << " words\n";
- #include "memory_sizes.h"
- #undef use
- }
-
- extern void write_term(Cell);
-
- int BREADTH_LIMIT = 8;
- void SetBreadth(int breadth)
- {
- BREADTH_LIMIT = breadth;
- }
-
- int DEPTH_LIMIT = 8;
- void SetDepth(int depth)
- {
- DEPTH_LIMIT = depth;
- }
-
- void PrintYReg(int index)
- {
- write_term(E[index]);
- cout << "\n";
- }
-
- /* in cells */
- int window_size = 1024;
- static int instr_trace_flag;
- static int call_trace_flag;
- static int print_xreg_flag;
- static int print_xreg_last;
- static int break_point_flag;
- static int profile_flag;
- static int arg_type_flag;
- int trace_heap_flag;
- static int trace_stack_flag;
- static int trace_gc_calls_flag;
- static ArgTypes ArgData;
- static Instr* break_point;
- static int last_xreg;
- static CellPtr H_window;
- static int count_reset_window;
- #define COUNT_SIZE 1024
- static int gc_calls_count[COUNT_SIZE];
-
- void PrintXReg(int index)
- {
- last_xreg = index;
- write_term(X[index]);
- cout << "\n";
- }
-
- void DisplayToggles(int)
- {
- if (instr_trace_flag) cerr << "instr trace on\n";
- if (call_trace_flag) cerr << "call trace on\n";
- if (print_xreg_flag) cerr << "xreg trace on\n";
- if (profile_flag) cerr << "profiling on\n";
- if (arg_type_flag) cerr << "arg types monitored\n";
- if (trace_heap_flag) cerr << "Heap Max Traced\n";
- if (trace_stack_flag) cerr << "Control Stack Max Traced\n";
- #ifdef WITH_GC
- if (DISPLAY_GC) cerr << "GC Activity Traced\n";
- if (CHECK_GC_LIMIT) cerr << "GC activations limited\n";
- #endif
- if (break_point_flag)
- cerr << "break point at " << (break_point - P0) << "\n";
- if (trace_gc_calls_flag) {
- cerr << "GC Calls Traced\n";
- cerr << "Window Size is " << window_size / 256 << " KB\n";
- }
- }
-
- void ToggleTraceFlag(int atom)
- {
- char* mode = (char*) atom;
- switch (*mode) {
- case 'g':
- trace_gc_calls_flag = 1 - trace_gc_calls_flag;
- break;
- case 'i':
- instr_trace_flag = 1 - instr_trace_flag;
- break;
- case 'c':
- call_trace_flag = 1 - call_trace_flag;
- break;
- case 'x':
- print_xreg_flag = 1 - print_xreg_flag;
- print_xreg_last = last_xreg;
- break;
- case 'h':
- trace_heap_flag = 1 - trace_heap_flag;
- break;
- case 's':
- trace_stack_flag = 1 - trace_stack_flag;
- break;
- default:
- cerr << "[gicxhs]: gc, instr, call, xregs, heap, control stacks\n";
- break;
- }
- }
-
- void ToggleProfile(int)
- {
- profile_flag = 1 - profile_flag;
- }
-
- void RecordArgTypes(int)
- {
- arg_type_flag = 1 - arg_type_flag;
- if (arg_type_flag) {
- ArgData.init();
- }
- }
-
- void ListProc(int)
- {
- if (arg_type_flag) {
- ArgData.print();
- } else {
- instr_args[ARG_PROC]->print_proc_table();
- }
- }
-
- void print_xregs(int last_xreg)
- {
- for (int i = 0; i <= last_xreg; i++) {
- cout << "X" << i << "->";
- write_term(X[i]);
- cout << "; ";
- }
- cout << "\n";
- }
-
- void instr_trace(int xregs)
- {
- cout << P - P0 << ": ";
- instr_types[P->ID].print(*P);
- (*P->exec)();
- if (print_xreg_flag) print_xregs(xregs);
- }
-
- void call_trace()
- {
- switch (P->ID) {
- case EXECUTE_PROC:
- case CALL:
- int arity = instr_args[ARG_PROC]->get_arity(P->arg1);
- instr_trace(arity - 1);
- break;
- default:
- (*P->exec)();
- break;
- }
- }
-
- HeapData heap_usage;
- static StackData stack_usage;
-
- void init_gather_data()
- {
- heap_usage.clear();
- stack_usage.clear();
- }
-
- void HeapUsage(int)
- {
- if (! trace_heap_flag) {
- cerr << "execute with trace h first\n";
- return;
- }
- if (! heap_usage.end) {
- heap_usage.end = 1;
- heap_usage.enter(cellp(B[H_CP_OFFSET]), H);
- }
- heap_usage.print();
- }
-
- void StackUsage(int)
- {
- if (! trace_stack_flag) {
- cerr << "execute with trace s first\n";
- return;
- }
- stack_usage.print();
- }
-
- inline void step()
- {
- if (profile_flag) {
- P->count++;
- }
- if (arg_type_flag) {
- if (P->ID == CALL || P->ID == EXECUTE_PROC) {
- ArgData.fill(P->arg1);
- }
- }
- if (trace_heap_flag) {
- if (P->ID == FAIL) {
- heap_usage.enter(cellp(B[H_CP_OFFSET]),H);
- }
- }
- if (trace_stack_flag) {
- if (P->ID == CALL || P->ID == EXECUTE_PROC) {
- stack_usage.enter(E, B);
- }
- }
- if (instr_trace_flag) {
- instr_trace(print_xreg_last);
- } else if (call_trace_flag) {
- call_trace();
- } else {
- (*P->exec)();
- }
- if (trace_gc_calls_flag) {
- if (P->ID == CALL || P->ID == EXECUTE_PROC) {
- if (H > H_window + window_size) {
- CellPtr b = B;
- int count = 0;
- cout << (int) H << " " << (int) H_window;
- while (cellp(b[H_CP_OFFSET]) > H_window) {
- cout << " " << b[H_CP_OFFSET];
- b = b + FIXED_CP_SIZE + b[SIZE_CP_OFFSET];
- count++;
- }
- cout << "\n";
- if (count >= COUNT_SIZE) {
- cerr << "Overflow in gc call buckets\n";
- count = COUNT_SIZE - 1;
- }
- gc_calls_count[count]++;
- H_window = H;
- }
- } else if (P->ID == FAIL) {
- if (H < H_window) {
- count_reset_window++;
- H_window = H;
- }
- }
- }
- P++;
- }
-
- void Step(int)
- {
- step();
- }
-
- void Next(int)
- {
- for (; P != break_point; P++) {
- if (instr_trace_flag) instr_trace(print_xreg_last);
- if (call_trace_flag) call_trace();
- if (P->ID == CALL || P->ID == EXECUTE_PROC)
- break;
- (*P->exec)();
- }
- }
-
- void SetBreakPoint(int instr_number)
- {
- break_point_flag = 1 - break_point_flag;
- if (break_point_flag)
- break_point = P0 + instr_number;
- else
- break_point = 0;
- }
-
- void execute()
- {
- for (; P != break_point; )
- step();
- }
-
- void Continue(int iter)
- {
- iter = (iter < 1) ? 1 : iter;
- for (int i = 0; i < iter; i++) {
- step();
- execute();
- }
- }
-
- void Reset(int)
- {
- init_gather_data();
- init_control_registers();
- for (int i = 0; i < COUNT_SIZE; i++)
- gc_calls_count[i] = 0;
- count_reset_window = 0;
- heap_usage.clear();
- }
-
- extern void init_gather_data();
-
- void Run(int)
- {
- if(instr_args[ARG_PROC]->status == UNRESOLVED_ADDRESSES)
- top_level_error("unknown procedure: can't execute");
- init_control_registers();
- init_gather_data();
- execute();
- }
-
- void Fast(int)
- {
- extern void fast_execute();
- if(instr_args[ARG_PROC]->status == UNRESOLVED_ADDRESSES)
- top_level_error("unknown procedure: can't execute");
- init_control_registers();
- fast_execute();
- }
-
- void PrintInstr(int)
- {
- instr_types[P->ID].print(*P);
- }
-
- void ListCode(int from)
- {
- assembly_print(from, profile_flag);
- }
-
- void assemble_file(char* filename, int mode)
- {
- istream* new_cinp = get_loadable_file(filename, mode);
- if (new_cinp == 0) {
- cerr << filename << ".w ";
- top_level_error("can't be found or made");
- }
- istream old_cin = cin;
- cin = *new_cinp;
- assembly();
- cin = old_cin;
- }
-
- void AssembleFile(int atom)
- {
- assemble_file((char*) atom, LOAD_MODE);
- init_control_registers();
- }
-
- void CompileAndLoad(int atom)
- {
- assemble_file((char*) atom, COMPILE_MODE);
- init_control_registers();
- }
-
- void Usage(int)
- {
- #define NAMES
- #define use(String,ID,Function,ArgID)\
- cerr << String << ": " << instr_args[ArgID]->name << "\n";
- #include "commands.h"
- #undef use
- #undef NAMES
- }
-
- #define use(Function,Type,sign,ORIGIN)\
- void Function(Type ptr)\
- {\
- cerr << sign(ptr - ORIGIN);\
- }
- use(print_e,Cell*,,E0)
- use(print_b,Cell*,-,B0)
- use(print_h,Cell*,,H0)
- use(print_tr,Cell*,-,TR0)
- use(print_p,Instr*,,P0)
- use(print_r,Cell*,,R0)
- #undef use
-
- void print_reg(char* reg_name)
- {
- switch (reg_name[0]) {
- #define use(ch,Function,PTR)\
- case 'ch':\
- Function(PTR);\
- break;
- use(e,print_e,E)
- use(b,print_b,B)
- use(p,print_p,P)
- use(h,print_h,H)
- use(t,print_tr,TR)
- use(r,print_r,R)
- #undef use
- }
- }
-
- void PrintReg(int atom)
- {
- print_reg((char*) atom); cout << "\n";
- }
-
- void print_env(Cell* E)
- {
- cerr << "(" << (E - E0) << ") ";
- cerr << "B: "; print_b(cellp(E[B_ENV_OFFSET])); cerr << "\t";
- cerr << "E: ("; print_e(cellp(E[E_ENV_OFFSET])); cerr << ",";
- cerr << instrp(E[P_ENV_OFFSET])->arg2; cerr << ")\t";
- cerr << "P: "; print_p(instrp(E[P_ENV_OFFSET])); cerr << "\n";
- }
-
- struct E_chain {
- CellPtr e;
- CellPtr b;
- E_chain(CellPtr E, CellPtr B);
- CellPtr next();
- void next_be();
- };
-
- E_chain::E_chain(CellPtr E, CellPtr B)
- {
- e = E;
- b = B;
- }
-
- CellPtr E_chain::next()
- {
- CellPtr result = e;
- e = cellp(e[E_ENV_OFFSET]);
- if (e < cellp(b[E_CP_OFFSET])) {
- e = cellp(b[E_CP_OFFSET]);
- b += FIXED_CP_SIZE + b[SIZE_CP_OFFSET];
- }
- return result;
- }
-
- void print_env_variables(CellPtr from, CellPtr to)
- {
- CellPtr Y = from;
- if (from < to) {
- cerr << "\t";
- for (; from < to; from++) {
- cerr << "Y" << (from - Y) << "->";
- write_term(*from); cerr << "; ";
- }
- cerr << "\n";
- }
- }
-
- void PrintEnv(int n = 1)
- {
- E_chain chain(E, B);
- CellPtr Y, Y0;
- Y = chain.next();
- Y0 = chain.next();
- for (int i = 0; i < n; i++) {
- print_env(Y);
- if (print_xreg_flag)
- print_env_variables(Y0,Y - E_TOP_OFFSET);
- Y = Y0;
- Y0 = chain.next();
- }
- }
-
- void print_cp(Cell* B)
- {
- cerr << "(" << (B0 - B) << ") ";
- cerr << "E: "; print_e(cellp(B[E_CP_OFFSET])); cerr << "\t";
- cerr << "H: "; print_h(cellp(B[H_CP_OFFSET])); cerr << "\t";
- cerr << "TR: "; print_tr(cellp(B[TR_CP_OFFSET])); cerr << "\t";
- cerr << "P: "; print_p(instrp(B[P_CP_OFFSET])); cerr << "\t";
- cerr << "size: " << B[SIZE_CP_OFFSET] << "\n\t";
- int i0 = B[SIZE_CP_OFFSET];
- if (print_xreg_flag) {
- for (int i = 0; i < i0; i++) {
- cerr << "X" << i << "->";
- write_term(B[X1_CP_OFFSET + i]);
- cerr << "; ";
- }
- cerr << "\n";
- }
- }
-
- struct B_chain {
- CellPtr b;
- B_chain(CellPtr B) {b = B;}
- void next() {
- b += FIXED_CP_SIZE + b[SIZE_CP_OFFSET];
- }
- };
-
- void PrintCp(int n=0)
- {
- B_chain chain(B);
- for (int i = 0; i < n; i++) {
- print_cp(chain.b);
- chain.next();
- }
- }
-
- void print_records(char* name)
- {
- switch (name[0]) {
- case 'e':
- print_env(E);
- break;
- case 'b':
- print_cp(B);
- break;
- }
- }
-
- void PrintRecords(int atom)
- {
- print_records((char*) atom);
- }
-
- /* CONTROL */
-
- static jmp_buf top_level_env;
-
- void top_level()
- {
- setjmp(top_level_env);
- for (;;) {
- cerr << prompt;
- command_scanner.next_line();
- if (command_scanner.status == SCAN_EOF) {
- cerr << "Bye bye\n";
- exit(0);
- }
- execute_command();
- }
- }
-
- void service_interrupt()
- {
- static int interrupt_counter = 0;
- interrupt_counter++;
- cerr << "\t\t\t *** Interrupt ***\n";
- if (interrupt_counter > 8) exit(1);
- top_level_normal_termination();
- }
-
- void service_illegal_instruction()
- {
- cerr << "\t\t\t *** Illegal Instruction ***\n";
- top_level_normal_termination();
- }
-
- void service_bus_error()
- {
- cerr << "\t\t\t *** Bus Error ***\n";
- top_level_normal_termination();
- }
-
- void service_segmentation_fault()
- {
- cerr << "\t\t\t *** Segmentation Fault ***\n";
- top_level_normal_termination();
- }
-
- void top_level_error(char* s)
- {
- if (s == 0)
- s = "Error has occurred";
- cerr << s << "\n";
- top_level_normal_termination();
- }
-
- void top_level_failure()
- {
- cerr << "\t\t\t*** FAIL *** \n";
- top_level_normal_termination();
- }
-
- void top_level_success()
- {
- cerr << "\t\t\t*** SUCCESS *** \n";
- top_level_normal_termination();
- }
-
- void top_level_normal_termination()
- {
- longjmp(top_level_env, 0);
- }
-
- void out_of_store()
- {
- cerr << "memory exhausted\n";
- exit(1);
- }
-
- void AccessDataBase(Cell cnst)
- {
- extern void access(Cell, Cell);
- Cell var = make_ptr(TAGREF, H++);
- access(cnst, var);
- write_term(var);
- }
-
- void print_heap_cell(Cell c, CellPtr Base)
- {
- switch(get_tag(c)) {
- case TAGREF:
- cout << "REF @" << addr(c) - Base << "\n";
- break;
- case TAGSTRUCT:
- cout << "STRUCT @" << addr(c) - Base << "\n";
- break;
- case TAGLIST:
- cout << "LIST @" << addr(c) - Base << "\n";
- break;
- case TAGCONST:
- if (is_int(c))
- cout << "INT " << (c >> 3) << "\n";
- else
- cout << "ATOM " << ((char*) c) << "\n";
- break;
- }
- }
-
- void PrintHeap(int from)
- {
- for (int i = 0; i < BREADTH_LIMIT; i++) {
- printf("%5d: ", i + from);
- print_heap_cell(H0[i + from], H0);
- }
- }
-
- void PrintAssert(Cell cst)
- {
- extern Cell assert_address_and_size(Cell, int&);
- int size;
- Cell value = assert_address_and_size(cst, size);
- print_heap_cell(value, R0);
- if (get_tag(value) != TAGCONST) {
- CellPtr from = addr(value);
- for (int i = 0; i < size; i++) {
- printf("%5d: ", i + from - R0);
- print_heap_cell(from[i], R0);
- }
- }
- }
-
- void Echo(Cell atom)
- {
- cout << get_string(atom) << "\n";
- }
-
- void PrintStringTable(int)
- {
- SCAN.print();
- }
-
- void SelectGc(Cell atom)
- {
- #ifdef WITH_GC
- char* gc = (char*) atom;
- switch (*gc) {
- case 's':
- WHICH_GC = MARK_COMPACT;
- break;
- case 'c':
- WHICH_GC = MARK_COPY;
- break;
- case 't':
- WHICH_GC = MARK_THRESHOLD;
- break;
- case 'v':
- WHICH_GC = MARK_COPY_FAST_COPY;
- break;
- case 'f':
- WHICH_GC = MARK_COMPACT_FAST_COPY;
- break;
- case '?':
- case 'h':
- cerr << "[sct]: mark and compact (sweep), mark and copy, threshold\n";
- cerr << "[vf]: mark-copy and fast copy; mark-compact and fast copy\n";
- break;
- default:
- switch (WHICH_GC) {
- case MARK_COPY:
- cerr << "mark and copy [c], window=" << window_size / 256 << "\n";
- break;
- case MARK_COMPACT:
- cerr << "mark and compact [s], window=" << window_size / 256 << "\n";
- break;
- case MARK_THRESHOLD:
- cerr << "select copy or sweep, threshold [t], window="
- << window_size / 256 << "\n";
- break;
- case MARK_COPY_FAST_COPY:
- cerr << "mark-copy, and fast copy [v], window="
- << window_size / 256 << "\n";
- break;
- case MARK_COMPACT_FAST_COPY:
- cerr << "mark-compact, and fast copy [f], window="
- << window_size / 256 << "\n";
- break;
- default:
- cerr << "[sct]: mark and compact (sweep), mark and copy, threshold\n";
- cerr << "[vf]: mark-copy and fast copy; mark-compact and fast copy\n";
- break;
- }
- }
- #endif
- }
-
- void TraceGc(int)
- {
- #ifdef WITH_GC
- DISPLAY_GC = 1 - DISPLAY_GC;
- #endif
- }
-
- void SetWindowSize(int size)
- {
- #ifdef WITH_GC
- window_size = size * 256;
- #endif
- }
-
- void SetGcLimit(int limit)
- {
- #ifdef WITH_GC
- CHECK_GC_LIMIT = 1 - CHECK_GC_LIMIT;
- GC_COUNT_LIMIT = limit;
- #endif
- }
-
- void get_os_data()
- {
- extern void getrusage(...);
- struct rusage os_data;
- struct timeval from = os_data.ru_utime;
- getrusage(RUSAGE_SELF, &os_data);
- struct timeval os_time = os_data.ru_utime;
- float mstime = (float) os_time.tv_usec / 1000000 + os_time.tv_sec;
- printf("%.1fu ", mstime);
- os_time = os_data.ru_stime;
- mstime = (float) os_time.tv_usec / 1000000 + os_time.tv_sec;
- printf("%.1fs ", mstime);
- printf("%dpr ", os_data.ru_minflt);
- printf("%dpf ", os_data.ru_majflt);
- printf("%dirss ", os_data.ru_idrss);
- printf("%dmrss \n", os_data.ru_maxrss);
- }
-
- void GetGcData(int)
- {
- #ifdef WITH_GC
- /* scanned, scanned by copy, fraction, survivors, fraction */
- /* trail scanned, survivors, fraction */
- if (gc_scanned == 0) {
- top_level_error("Run a program with GC first");
- }
- printf("time in gc: %.3f mem recovered: %d\n",
- gc_time, gc_scanned - gc_survivors);
- switch (WHICH_GC) {
- case MARK_COPY:
- case MARK_THRESHOLD:
- case MARK_COPY_FAST_COPY:
- case MARK_COMPACT_FAST_COPY:
- printf("%d & %d & %d & %2.1f & %d & %2.1f & %d & %d & %2.1f\n",
- window_size / 256,
- gc_scanned,
- gc_copy_scanned,
- (float) gc_copy_scanned * 100 / gc_scanned,
- gc_survivors,
- (float) gc_survivors * 100 / gc_scanned,
- tr_scanned,
- tr_survivors,
- (float) tr_survivors * 100 / tr_scanned);
- break;
- case MARK_COMPACT:
- printf("%d & %d & %d & %2.1f & %d & %d & %2.1f\n",
- window_size / 256,
- gc_scanned,
- gc_survivors,
- (float) gc_survivors * 100 / gc_scanned,
- tr_scanned,
- tr_survivors,
- (float) tr_survivors * 100 / tr_scanned);
- break;
- default:
- cerr << "[sc]: mark and compact (sweep), mark and copy\n";
- break;
- }
- #endif
- get_os_data();
- }
-