-/* srcontainsc/vm/optimizing/escape.c
+/* src/vm/jit/optimizing/escape.c
Copyright (C) 2008
CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+
*/
-#include "vm/jit/jit.h"
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
+
+#include "config.h"
+
+#include "vm/class.hpp"
+#include "vm/classcache.hpp"
+
+#include "vm/jit/jit.hpp"
#include "vm/jit/optimizing/escape.h"
+#include <stdarg.h>
+
+#if defined(ENABLE_ESCAPE_REASON)
+#define ENABLE_REASON
+#endif
+
+#if defined(ENABLE_REASON)
+#define I2(why, tov, es) escape_analysis_record_reason(e, why, iptr, tov, es);
+#else
+#define I2(why, tov, es)
+#endif
+#define I(why, to, from) I2(why, instruction_ ## to (iptr), escape_analysis_get_state(e, instruction_ ## from (iptr)))
+#define E2(why, var) I2(why, var, ESCAPE_GLOBAL)
+#define E(why, which) E2(why, instruction_ ## which (iptr))
+
+typedef enum {
+ RED = 31,
+ GREEN,
+ YELLOW,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ WHITE,
+ COLOR_END
+} color_t;
+
+#define ENABLE_COLOR
+
+static void color_start(color_t color) {
+#if defined(ENABLE_COLOR)
+ if (RED <= color && color < COLOR_END) {
+ printf("\033[%dm", color);
+ }
+#endif
+}
+
+static void color_end() {
+#if defined(ENABLE_COLOR)
+ printf("\033[m");
+ fflush(stdout);
+#endif
+}
+
+static void color_printf(color_t color, const char *fmt, ...) {
+ va_list ap;
+ color_start(color);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ color_end();
+}
+
+
/*** escape_state *************************************************************/
const char *escape_state_to_string(escape_state_t escape_state) {
/*** var_extra ***************************************************************/
+#if defined(ENABLE_REASON)
+typedef struct reason {
+ const char *why;
+ instruction *iptr;
+ struct reason *next;
+} reason_t;
+#endif
+
typedef struct var_extra {
instruction *allocation;
escape_state_t escape_state;
unsigned contains_arg:1;
unsigned contains_only_args:1;
/*signed adr_arg_num:30;*/
+#if defined(ENABLE_REASON)
+ reason_t *reasons;
+#endif
} var_extra_t;
static void var_extra_init(var_extra_t *ve) {
ve->contains_arg = false;
ve->contains_only_args = false;
/*ve->adr_arg_num = -1;*/
+#if defined(ENABLE_REASON)
+ ve->reasons = NULL;
+#endif
}
static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
e->adr_args_count = 0;
- e->verbose = (
- strcmp(e->jd->m->clazz->name->text, "gnu/java/util/regex/RESyntax") == 0
- && strcmp(e->jd->m->name->text, "<clinit>") == 0
- );
e->verbose = 1;
+ e->verbose = strcmp(jd->m->name->text, "<init>") == 0;
+ e->verbose = getenv("EV") != NULL;
+}
+
+#if defined(ENABLE_REASON)
+static void escape_analysis_record_reason(escape_analysis_t *e, const char *why, instruction *iptr, s4 var, escape_state_t es) {
+ var_extra_t *ve;
+ reason_t *re;
+ if (es == ESCAPE_GLOBAL || es == ESCAPE_METHOD_RETURN) {
+ var = var_extra_get_representant(e, var);
+ ve = var_extra_get(e, var);
+ re = NEW(reason_t);
+ re->why = why;
+ re->iptr= iptr;
+ re->next = ve->reasons;
+ ve->reasons = re;
+ if (e->verbose) {
+ printf("%d escapes because %s\n", var, why);
+ }
+ }
}
+#endif
static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr) {
var_extra_get(e, var)->allocation = iptr;
}
static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
var_extra_get(e, var)->contains_arg = true;
}
static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
return var_extra_get(e, var)->contains_arg;
}
static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
var_extra_get(e, var)->contains_only_args = true;
}
static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
return var_extra_get(e, var)->contains_only_args;
}
dependency_list_item_get_dependency(it),
escape_state
);
+ {
+ instruction *iptr = NULL;
+ I2("propagated by dependency", dependency_list_item_get_dependency(it), escape_state);
+ }
}
}
}
return;
}
+ if (e->verbose) printf("Merging (%d,%d)\n", var1, var2);
+
ve1 = var_extra_get(e, var1);
ve2 = var_extra_get(e, var2);
dependency_list_item_get_dependency(itd),
ESCAPE_GLOBAL
);
+ {
+ instruction *iptr = NULL;
+ E2("has become arg", dependency_list_item_get_dependency(itd));
+ }
}
}
ve1->adr_arg_num = -1;
}
*/
+#if defined(ENABLE_REASON)
+ if (ve1->reasons) {
+ reason_t *re = ve1->reasons;
+ while (re->next != NULL) {
+ re = re->next;
+ }
+ re->next = ve2->reasons;
+ } else {
+ ve1->reasons = ve2->reasons;
+ }
+#endif
}
static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
dependency_list_add(dl, store);
if (e->verbose) {
- printf("dependency_list_add\n");
+ printf("dependency_list_add: %d.dependency_list.add( { ", obj);
+ show_icmd(e->jd, store, 0, 3);
+ printf(" } )\n");
}
}
instruction **iarg;
methodinfo *mi;
escape_state_t es;
+ const char *why;
if (e->verbose) {
- printf("processing %s@%d\n", icmd_table[iptr->opc].name, iptr->line);
+ color_start(CYAN);
+ printf("%d: ", iptr->line);
+ show_icmd(e->jd, iptr, 0, 3);
+ color_end();
+ printf("\n");
}
switch (instruction_get_opcode(iptr)) {
if (c == NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("unresolved class", dst)
} else if (c->finalizer != NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("finalizer", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
instruction_list_add(e->allocations, iptr);
-
+ E("untracked array", dst)
break;
case ICMD_PUTSTATIC:
if (instruction_field_type(iptr) == TYPE_ADR) {
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("putstatic", s1)
}
break;
/* If s1 is currently not an argument, but can contain one later because
of a phi function, the merge function takes care to make all
dependencies escape globally. */
+ E("putfield into argument", s2)
} else {
+ I("putfield inherit", s2, s1);
escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
escape_analysis_add_dependency(e, iptr);
}
case ICMD_AASTORE:
if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
+ if (e->verbose) printf("Contains argument.\n");
escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
+ E("aastore into argument", s3)
} else {
+ if (e->verbose) printf("Contains no argument.\n");
+ I("aastore", s3, s1)
escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
escape_analysis_add_dependency(e, iptr);
}
case ICMD_GETSTATIC:
if (instruction_field_type(iptr) == TYPE_ADR) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("loaded from static var", dst)
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
}
break;
x.bar = y;
=> y escapes globally. */
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("loaded from arg", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
break;
case ICMD_ARRAYLENGTH:
- /* TODO */
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
break;
case ICMD_AALOAD:
if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
/* If store into argument, escapes globally. See ICMD_GETFIELD. */
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("aaload from argument", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
case ICMD_IFNULL:
case ICMD_IFNONNULL:
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+ break;
+
case ICMD_CHECKNULL:
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+ escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
break;
case ICMD_CHECKCAST:
count = instruction_arg_count(iptr);
mi = instruction_local_methodinfo(iptr);
paramescape = NULL;
+ why = "???";
if (mi != NULL) {
/* If the method could be resolved, it already is. */
paramescape = mi->paramescape;
+ if (e->verbose) {
+ if (paramescape) {
+ printf("Paramescape for callee available.\n");
+ }
+ }
+
+ if (paramescape) why = "Available param escape";
+
if (paramescape == NULL) {
if (e->verbose) {
- printf("BC escape analyzing callee %s/%s.\n", mi->clazz->name->text, mi->name->text);
+ printf("BC escape analyzing callee.\n");
}
+ why = "BC param escape";
bc_escape_analysis_perform(mi);
paramescape = mi->paramescape;
}
if (e->verbose) {
printf("Unresolved callee.\n");
}
+ why = "Unresolved callee";
}
if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
- if (mi != NULL && !method_profile_is_monomorphic(mi)) {
+ if (mi != NULL && !escape_is_monomorphic(e->jd->m, mi)) {
+ if (e->verbose) {
+ printf("Not monomorphic.\n");
+ }
+ why = "Polymorphic";
paramescape = NULL;
}
}
if (instruction_return_type(iptr) == TYPE_ADR) {
if (paramescape == NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E(why, dst);
} else {
es = escape_state_from_u1(paramescape[-1]);
+ I2(why, instruction_dst(iptr), es)
escape_analysis_ensure_state(e, instruction_dst(iptr), es);
}
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
}
-
+
for (i = 0; i < count; ++i) {
if (instruction_arg_type(iptr, i) == TYPE_ADR) {
instruction_arg(iptr, i),
ESCAPE_GLOBAL
);
- } else if (escape_state_from_u1(*paramescape) < ESCAPE_METHOD) {
+ E2(why, instruction_arg(iptr, i));
+ } else if (escape_state_from_u1(*paramescape) <= ESCAPE_METHOD) {
es = escape_state_from_u1(*paramescape);
if (es < ESCAPE_METHOD) {
es = ESCAPE_METHOD;
}
+ I2(why, instruction_arg(iptr, i), es);
escape_analysis_ensure_state(e, instruction_arg(iptr, i), es);
if (*paramescape & 0x80) {
If the return value escapes, the ES of the parameter needs
to be adjusted. */
escape_analysis_merge(e, instruction_arg(iptr, i), instruction_dst(iptr));
+ I2("return alias", instruction_arg(iptr, i), instruction_dst(iptr));
}
+ } else {
+ escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_GLOBAL);
+ E2(why, instruction_arg(iptr, i));
}
if (paramescape != NULL) {
case ICMD_ATHROW:
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("throw", s1)
break;
case ICMD_ARETURN:
ESCAPE_METHOD for now, and check later, if a different value than an
argument is possibly returned. */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD_RETURN);
+ E("return", s1)
instruction_list_add(e->returns, iptr);
break;
FOR_EACH_BASICBLOCK(e->jd, bptr) {
+ if (e->verbose) {
+ color_printf(CYAN, "=== BB %d ===\n", bptr->nr);
+ }
+
for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
escape_analysis_process_instruction(e, iptr);
}
instruction_list_item_t *iti;
instruction *iptr;
+ if (e->verbose) printf("Post processing returns:\n");
+
FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
iptr = iti->instr;
if (! escape_analysis_get_contains_only_arguments(e, instruction_s1(iptr))) {
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("return of not argument", s1)
}
}
}
instruction *iptr;
dependency_list_t *dl;
+ if (e->verbose) printf("Post processing getfields:\n");
+
FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
iptr = iti->instr;
dependency_list_item_get_dependency(itd),
escape_analysis_get_state(e, instruction_dst(iptr))
);
+ I2("post process getfield", dependency_list_item_get_dependency(itd), escape_analysis_get_state(e, instruction_dst(iptr)));
}
}
}
/* TODO if argument does not escape, mark. */
if (escape_analysis_get_state(e, instruction_arg(iptr, 0)) != ESCAPE_GLOBAL) {
- printf("Monitor on thread local object!\n");
- }
- }
-}
-
-static void display_allocation(escape_analysis_t *e, const char *prefix, const instruction *iptr, escape_state_t es) {
- const char *cl = "WTF";
- classinfo *c;
-
- if (instruction_get_opcode(iptr) == ICMD_NEW) {
- c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
- if (c) {
- cl = c->name->text;
+ if (e->verbose) {
+ printf("Monitor on thread local object!\n");
+ }
}
}
-
-
- printf(
- " %s %s %s: %s %s @%d %s\n",
- prefix,
- e->jd->m->clazz->name->text,
- e->jd->m->name->text,
- icmd_table[iptr->opc].name,
- cl,
- iptr->line,
- escape_state_to_string(es)
- );
}
static void escape_analysis_mark_allocations(escape_analysis_t *e) {
instruction_list_item_t *iti;
+ instruction *iptr;
escape_state_t es;
-/*
FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
- es = escape_analysis_get_state(e, instruction_dst(iti->instr));
- if (es < ESCAPE_GLOBAL_THROUGH_METHOD) {
- display_allocation(e, "****", iti->instr, es);
+ iptr = iti->instr;
+ es = escape_analysis_get_state(e, instruction_dst(iptr));
+
+#if defined(ENABLE_REASON)
+ if (instruction_get_opcode(iptr) == ICMD_NEW) {
+ var_extra_t *ve;
+ iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_escape_reason_new);
+ ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+ iptr->escape_reasons = ve->reasons;
+ if (es < ESCAPE_METHOD_RETURN) {
+ assert(!ve->reasons);
+ reason_t *r = NEW(reason_t);
+ r->why = "No escape\n";
+ r->iptr = NULL;
+ r->next = NULL;
+ iptr->escape_reasons = r;
+ } else {
+ assert(iptr->escape_reasons);
+ }
}
- if (es == ESCAPE_GLOBAL_THROUGH_METHOD) {
- display_allocation(e, "!!!!", iti->instr, es);
+#endif
+
+/*
+ if (instruction_get_opcode(iptr) == ICMD_NEW) {
+ es = escape_analysis_get_state(e, instruction_dst(iptr));
+ if (es < ESCAPE_METHOD_RETURN) {
+ iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_tlh_new);
+ e->jd->code->flags |= CODE_FLAG_TLH;
+ }
}
- }
*/
+ }
}
static void escape_analysis_process_arguments(escape_analysis_t *e) {
}
}
+#if defined(ENABLE_REASON)
+void print_escape_reasons() {
+ reason_t *re = THREADOBJECT->escape_reasons;
+
+ fprintf(stderr, "DYN_REASON");
+
+ for (; re; re = re->next) {
+ fprintf(stderr,":%s", re->why);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void set_escape_reasons(void *vp) {
+ THREADOBJECT->escape_reasons = vp;
+}
+#endif
+
static void escape_analysis_display(escape_analysis_t *e) {
instruction_list_item_t *iti;
var_extra_t *ve;
FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
iptr = iti->instr;
- ve = var_extra_get(e, instruction_dst(iptr));
+ ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+ show_icmd(e->jd, iptr-1, 0, 3);
+ printf("\n");
+ show_icmd(e->jd, iptr, 0, 3);
+ printf("\n");
printf(
- "%s@%d: %s\n",
+ "%s@%d: --%s-- %d\n\n",
icmd_table[iptr->opc].name,
iptr->line,
- escape_state_to_string(ve->escape_state)
+ escape_state_to_string(ve->escape_state),
+ ve->representant
);
+#if defined(ENABLE_REASON)
+ {
+ reason_t *re;
+ for (re = ve->reasons; re; re = re->next) {
+ printf("ESCAPE_REASON: %s\n", re->why);
+ }
+ }
+#endif
}
}
escape_analysis_init(e, jd);
if (e->verbose)
- printf("==== %s/%s ====\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
+ color_printf(RED, "\n\n==== %s/%s ====\n\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
escape_analysis_process_arguments(e);
escape_analysis_process_instructions(e);
escape_analysis_export_arguments(e);
if (e->verbose) escape_analysis_display(e);
+ if (e->verbose) {
+ int i, j, r;
+ for (i = 0; i < jd->vartop; ++i) {
+ r = var_extra_get_representant(e, i);
+ if (i == r) {
+ printf("EES of %d: ", i);
+ for (j = 0; j < jd->vartop; ++j) {
+ if (var_extra_get_representant(e, j) == r) {
+ printf("%d, ", j);
+ }
+ }
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+
escape_analysis_mark_allocations(e);
escape_analysis_mark_monitors(e);
/*** monomorphic *************************************************************/
-monomorphic_t monomorphic_get(methodinfo *caller, methodinfo *callee) {
- monomorphic_t res = { 0, 0 };
-}
-
-bool method_profile_is_monomorphic(methodinfo *m) {
-return 0;
-}
-
-#if 0
-
-/*** HACK to store method monomorphy information upon shutdown ****************/
-
-#include <sqlite3.h>
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee) {
-bool method_profile_is_monomorphic(methodinfo *m) {
- static sqlite3 *db = NULL;
- static sqlite3_stmt *stmt = NULL;
- int ret;
+ /* Non-speculative case */
- if (db == NULL) {
- assert(sqlite3_open("/home/peter/cacao-dev/profile.sqlite", &db) == SQLITE_OK);
- assert(sqlite3_prepare(db, "SELECT count(*) FROM monomorphic where class=? and method=? and descriptor=?", -1, &stmt, 0) == SQLITE_OK);
- }
-
- assert(sqlite3_bind_text(stmt, 1, m->clazz->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
- assert(sqlite3_bind_text(stmt, 2, m->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
- assert(sqlite3_bind_text(stmt, 3, m->descriptor->text, -1, SQLITE_STATIC) == SQLITE_OK);
-
- assert(sqlite3_step(stmt) == SQLITE_ROW);
- ret = sqlite3_column_int(stmt, 0);
- assert(sqlite3_reset(stmt) == SQLITE_OK);
-
- return ret;
-}
-void func(classinfo *c, void *arg) {
- methodinfo *it;
- sqlite3_stmt *stmt = (sqlite3_stmt *)arg;
- s4 flags;
- for (it = c->methods; it != c->methods + c->methodscount; ++it) {
- flags = it->flags;
- if (flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
- continue;
- }
- if ((flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED | ACC_ABSTRACT)) ==
- (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)) {
- assert(sqlite3_bind_text(stmt, 1, c->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
- assert(sqlite3_bind_text(stmt, 2, it->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
- assert(sqlite3_bind_text(stmt, 3, it->descriptor->text, -1, SQLITE_STATIC) == SQLITE_OK);
-
- assert(sqlite3_step(stmt) == SQLITE_DONE);
- assert(sqlite3_reset(stmt) == SQLITE_OK);
- }
+ if (callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
+ return true;
}
-}
+ if (
+ (callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED| ACC_ABSTRACT))
+ == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)
+ ) {
-void method_profile_store() {
- sqlite3 *db = NULL;
- sqlite3_stmt *stmt;
- assert(sqlite3_open("/home/peter/cacao-dev/profile.sqlite", &db) == SQLITE_OK);
- assert(sqlite3_exec(db, "DELETE FROM monomorphic", NULL, NULL, NULL) == SQLITE_OK);
- assert(sqlite3_prepare(db, "INSERT INTO monomorphic (class, method, descriptor) VALUES (?,?,?)", -1, &stmt, 0) == SQLITE_OK);
- classcache_foreach_loaded_class(func, stmt);
- assert(sqlite3_finalize(stmt) == SQLITE_OK);
- assert(sqlite3_close(db) == SQLITE_OK);
-}
+ /* Mark that we have used the information about monomorphy. */
-void iterate_classes() {
- return;
- method_profile_store();
+ callee->flags |= ACC_METHOD_MONOMORPHY_USED;
-}
+ /* We assume the callee is monomorphic. */
-#endif
+ method_add_assumption_monomorphic(caller, callee);
-#if defined(ENABLE_TLH)
-/*** TLH (Thread local heap) hack ********************************************/
-
-#include <sys/mman.h>
-#include "threads/thread.h"
-
-#define TLH_MAX_SIZE (20 * 1024 * 1024)
-
-void tlh_init(threadobject *t) {
- uint8_t *heap = (uint8_t *)mmap(
- NULL,
- TLH_MAX_SIZE,
- PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE,
- -1,
- 0
- );
- uint8_t *red = (uint8_t *)mmap(
- heap + TLH_MAX_SIZE - getpagesize(),
- getpagesize(),
- PROT_NONE,
- MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED,
- -1,
- 0
- );
- assert(heap);
- assert(red);
- t->tlhstart = heap;
- t->tlhtop = heap;
- t->tlhbase = heap;
-}
-
-void tlh_reset(threadobject *t) {
- t->tlhtop = t->tlhstart;
- t->tlhbase = t->tlhstart;
-}
-
-void tlh_destroy(threadobject *t) {
- int res = munmap(t->tlhstart, TLH_MAX_SIZE - getpagesize());
- int res2 = munmap(t->tlhstart + TLH_MAX_SIZE - getpagesize(), getpagesize());
- assert(res);
- assert(res2);
-}
+ return true;
+ }
-bool tlh_sigsegv_handler(void *addr) {
+ return false;
}
-#endif