[1135] in Coldmud discussion meeting
[COLD] Performance patch
daemon@ATHENA.MIT.EDU (Fri Nov 22 14:11:14 1996
)
Date: Fri, 22 Nov 1996 19:54:14 +0100 (MET)
From: Miroslav.Silovic@public.srce.hr (Miroslav Silovic)
To: coldstuff@cold.org
Cc: brandon@cold.org
Apply this patch to execute.c. It speeds up the expressions like
(| foo |), when foo causes the exception. The speedup in the
commonly used cases (mainly (| something[foo] |) || default and
(| object.method_that_may_not_exist() |) is *substantial*.
(the reason is that it won't allocate, then discard the backtrace).
Note that (| foo.method() |) will still construct the backtrace
if method explicitly calls throw() ColdC function, or expression
inside (| |)'s propagates the exception.
----------------------------------------------------------------
*** ../../Genesis-1.0p19/src/execute.c Wed Nov 13 06:28:05 1996
--- execute.c Fri Nov 22 19:29:15 1996
***************
*** 1319,1380 ****
(num_args == 1) ? "" : "s", required);
}
void func_type_error(char *which, cData *wrong, char *required)
{
cthrow(type_id, "The %s argument (%D) is not %s.", which, wrong, required);
}
void cthrow(Ident error, char *fmt, ...)
{
cStr *str;
va_list arg;
! va_start(arg, fmt);
! str = vformat(fmt, arg);
! va_end(arg);
interp_error(error, str);
! string_discard(str);
}
void interp_error(Ident error, cStr *explanation)
{
cList * location;
Ident location_type;
cData *d;
char *opname;
! /* Get the opcode name and decide whether it's a function or not. */
! opname = op_table[cur_frame->last_opcode].name;
! location_type = (islower(*opname)) ? function_id : opcode_id;
! /* Construct a two-element list giving the location. */
! location = list_new(2);
! d = list_empty_spaces(location, 2);
! /* The first element is 'function or 'opcode. */
! d->type = SYMBOL;
! d->u.symbol = ident_dup(location_type);
! d++;
! /* The second element is the symbol for the opcode. */
! d->type = SYMBOL;
! d->u.symbol = ident_dup(op_table[cur_frame->last_opcode].symbol);
start_error(error, explanation, NULL, location);
! list_discard(location);
}
void user_error(Ident error, cStr *explanation, cData *arg)
{
cList * location;
cData *d;
/* Construct a list giving the location. */
location = list_new(5);
d = list_empty_spaces(location, 5);
/* The first element is 'method. */
d->type = SYMBOL;
d->u.symbol = ident_dup(method_id);
d++;
--- 1319,1400 ----
(num_args == 1) ? "" : "s", required);
}
void func_type_error(char *which, cData *wrong, char *required)
{
cthrow(type_id, "The %s argument (%D) is not %s.", which, wrong, required);
}
+ INTERNAL Bool is_critical (void) {
+ if (cur_frame
+ && cur_frame->specifiers
+ && cur_frame->specifiers->type==CRITICAL)
+ return TRUE;
+ return FALSE;
+ }
+
void cthrow(Ident error, char *fmt, ...)
{
cStr *str;
va_list arg;
! if (!is_critical()) {
! va_start(arg, fmt);
! str = vformat(fmt, arg);
! va_end(arg);
! }
! else
! str=NULL;
!
interp_error(error, str);
! if (str)
! string_discard(str);
}
void interp_error(Ident error, cStr *explanation)
{
cList * location;
Ident location_type;
cData *d;
char *opname;
! if (explanation) {
! /* Get the opcode name and decide whether it's a function or not. */
! opname = op_table[cur_frame->last_opcode].name;
! location_type = (islower(*opname)) ? function_id : opcode_id;
! /* Construct a two-element list giving the location. */
! location = list_new(2);
! d = list_empty_spaces(location, 2);
! /* The first element is 'function or 'opcode. */
! d->type = SYMBOL;
! d->u.symbol = ident_dup(location_type);
! d++;
! /* The second element is the symbol for the opcode. */
! d->type = SYMBOL;
! d->u.symbol = ident_dup(op_table[cur_frame->last_opcode].symbol);
! }
! else
! location = NULL;
start_error(error, explanation, NULL, location);
! if (location)
! list_discard(location);
}
void user_error(Ident error, cStr *explanation, cData *arg)
{
cList * location;
cData *d;
+
/* Construct a list giving the location. */
location = list_new(5);
d = list_empty_spaces(location, 5);
/* The first element is 'method. */
d->type = SYMBOL;
d->u.symbol = ident_dup(method_id);
d++;
***************
*** 1416,1465 ****
}
INTERNAL void start_error(Ident error, cStr *explanation, cData *arg,
cList * location)
{
cList * error_condition, *traceback;
cData *d;
! /* Construct a three-element list for the error condition. */
! error_condition = list_new(3);
! d = list_empty_spaces(error_condition, 3);
! /* The first element is the error code. */
! d->type = T_ERROR;
! d->u.error = ident_dup(error);
! d++;
! /* The second element is the explanation string. */
! d->type = STRING;
! d->u.str = string_dup(explanation);
! d++;
! /* The third element is the error arg, or 0 if there is none. */
! if (arg) {
! data_dup(d, arg);
! } else {
! d->type = INTEGER;
! d->u.val = 0;
! }
! /* Now construct a traceback, starting as a two-element list. */
! traceback = list_new(2);
! d = list_empty_spaces(traceback, 2);
! /* The first element is the error condition. */
! d->type = LIST;
! d->u.list = error_condition;
! d++;
! /* The second argument is the location. */
! d->type = LIST;
! d->u.list = list_dup(location);
/* Start the error propagating. This consumes traceback. */
propagate_error(traceback, error);
}
/* Requires: traceback is a list of lists containing the traceback
* information to date. THIS FUNCTION CONSUMES THE INFORMATION.
* id is an error id. This function accounts for an error id
--- 1436,1489 ----
}
INTERNAL void start_error(Ident error, cStr *explanation, cData *arg,
cList * location)
{
cList * error_condition, *traceback;
cData *d;
! if (location) {
! /* Construct a three-element list for the error condition. */
! error_condition = list_new(3);
! d = list_empty_spaces(error_condition, 3);
! /* The first element is the error code. */
! d->type = T_ERROR;
! d->u.error = ident_dup(error);
! d++;
! /* The second element is the explanation string. */
! d->type = STRING;
! d->u.str = string_dup(explanation);
! d++;
! /* The third element is the error arg, or 0 if there is none. */
! if (arg) {
! data_dup(d, arg);
! } else {
! d->type = INTEGER;
! d->u.val = 0;
! }
! /* Now construct a traceback, starting as a two-element list. */
! traceback = list_new(2);
! d = list_empty_spaces(traceback, 2);
! /* The first element is the error condition. */
! d->type = LIST;
! d->u.list = error_condition;
! d++;
! /* The second argument is the location. */
! d->type = LIST;
! d->u.list = list_dup(location);
! }
! else
! traceback=NULL;
/* Start the error propagating. This consumes traceback. */
propagate_error(traceback, error);
}
/* Requires: traceback is a list of lists containing the traceback
* information to date. THIS FUNCTION CONSUMES THE INFORMATION.
* id is an error id. This function accounts for an error id
***************
*** 1475,1491 ****
/* If there's no current frame, drop all this on the floor. */
if (!cur_frame) {
list_discard(traceback);
return;
}
/* Add message to traceback. */
! traceback = traceback_add(traceback, error);
/* Look for an appropriate specifier in this frame. */
for (; cur_frame->specifiers; pop_error_action_specifier()) {
spec = cur_frame->specifiers;
switch (spec->type) {
case CRITICAL:
--- 1499,1516 ----
/* If there's no current frame, drop all this on the floor. */
if (!cur_frame) {
list_discard(traceback);
return;
}
/* Add message to traceback. */
! if (traceback)
! traceback = traceback_add(traceback, error);
/* Look for an appropriate specifier in this frame. */
for (; cur_frame->specifiers; pop_error_action_specifier()) {
spec = cur_frame->specifiers;
switch (spec->type) {
case CRITICAL:
***************
*** 1507,1523 ****
/* Push the error on the stack, and discard our copy of it. */
push_error(error);
ident_discard(error);
/* Pop this error spec, discard the traceback, and continue
* processing. */
pop_error_action_specifier();
! list_discard(traceback);
return;
case PROPAGATE:
/* We're in a propagate expression. Set the propagate flag and
* keep going. */
propagate = 1;
break;
--- 1532,1549 ----
/* Push the error on the stack, and discard our copy of it. */
push_error(error);
ident_discard(error);
/* Pop this error spec, discard the traceback, and continue
* processing. */
pop_error_action_specifier();
! if (traceback)
! list_discard(traceback);
return;
case PROPAGATE:
/* We're in a propagate expression. Set the propagate flag and
* keep going. */
propagate = 1;
break;