void caller(void (*trampoline)(void)) { fprintf(stderr, "Attempting to call a trampoline...\n"); trampoline(); }
//Note it's probably cheaper to pass a CapturedCont than a Continuation Trampoline stream2(Search &s, CapturedVar<int> m, Trampoline c) { CapturedLambda(Search &, int) rest; UncountedLambda(Search &, int) rest_uncounted = rest; *rest = [=](Search &s, int n) { n += 1; if (n == 4) { return s.fail(); } else { s.alt(trampoline(rest_uncounted, s, n)); // cout << "m is " << *n * *n << endl; *m = n * n; return c; } }; return trampoline(rest, s, 0); }
//oops, the return value could be nixed by stack clean exception //but it worked when I made it always throw... {}{}{} WHY DOES IT WORK? //OH it works because it doesn't use the search until AFTER it returns the value Trampoline stream1(Search &s, CapturedVar<int> m, Trampoline c) { CapturedLambda(Search &, int) rest; UncountedLambda(Search &, int) rest_uncounted = rest; *rest = [=](Search &s, int n) { n = n + 1; if (n == 10) { return s.fail(); } else { s.alt(trampoline(rest_uncounted, s, n)); *m = n; // cout << "n is " << *n << endl; return c; } }; cout << rest.get()->use_count() << endl; return trampoline(rest, s, 0); }
static void vm_properties_set_property(struct vm_object *p, const char *key, const char *value) { struct vm_object *(*trampoline)(struct vm_object *, struct vm_object *, struct vm_object *); trampoline = vm_method_trampoline_ptr(vm_java_util_Properties_setProperty); struct vm_object *key_obj = vm_object_alloc_string_from_c(key); struct vm_object *value_obj = vm_object_alloc_string_from_c(value); trampoline(p, key_obj, value_obj); }
Trampoline AmbTest(Search &s) { CapturedVar<int> n, m; CapturedCont c1, c2, c3; UncountedCont c1_u = c1, c2_u = c2, c3_u = c3; combine_refs(c1, c2, c3); //note it can't safely use Search inside of functions that return a value *c1 = [=](Search &s) { return stream1(s, n, trampoline(c2_u, s)); }; *c2 = [=](Search &s) { return stream2(s, m, trampoline(c3_u, s)); }; *c3 = [=](Search &s) { if (*n != *m) return s.fail(); else { s.results.insert_or_assign("n", *n); s.results.insert_or_assign("m", *m); return end_search; } }; cout << c1.get()->use_count() << endl; cout << c2.get()->use_count() << endl; cout << c3.get()->use_count() << endl; return trampoline(c1, s); }
/* * CP_jREPL: read evaluate print loop using continuation passing */ OBJ enterTrampoline1(OBJ input){ //fprintf(stdout, "\nStack before Trampoline:\n"); //printJStack(__FILE__,__LINE__,__FUNCTION__); DEBUGCODE(PRINT_STACK->state, printJStack(__FILE__,__LINE__,__FUNCTION__)); VOIDPTRFUNC CP_jREPL(); PUSH((OBJ)((INT)BP)); PUSH((OBJ)((INT)AP)); PUSH((OBJ)CP_jREPL); PUSH(NULL); // last continuation AP = SP; BP = AP - 4; PUSH(input); VOIDPTRFUNC CP_jREPL(); trampoline((VOIDPTRFUNC)CP_jREPL); return js_nil; }
int main() { cont_p cont; cont_p caller_cont; object_p scanner, output; init_symbol_table(); init_wellknown_objects(); init_global_env(); init_cont_list(); fill_initial_env(); scanner = alloc_scanner(stdin); output = alloc_output_stream(stdout); if (setjmp(error_occured) != 0) { // reset continuation list continuation_list->next = continuation_list->first; } // initial continuation caller_cont = cont_list_obtain(continuation_list); caller_cont->args_locals[0] = output; caller_cont->next = finish; cont = cont_list_obtain(continuation_list); cont->caller = caller_cont; cont->args_locals[0] = scanner; cont->args_locals[1] = output; cont->next = repl; trampoline(cont); return 0; }
thread_t *thread_spawn(void (*fn)(void*), void *p, uint8_t auto_free) { thread_t *t = (thread_t*)slab_cache_alloc(&thread_cache); memset(t, 0, sizeof(thread_t)); t->auto_free = auto_free; t->stack = alloc_stack_and_tls(); spinlock_acquire(&thread_list_lock); t->next = thread_list_head; t->next->prev = t; thread_list_head = t; spinlock_release(&thread_list_lock); /* TLS slot zero always contains the thread object. */ *tls_slot(TLS_SLOT_TCB, t->stack) = (uintptr_t)t; /* Store the function and argument temporarily in TLS */ *tls_slot(1, t->stack) = (uintptr_t)fn; *tls_slot(2, t->stack) = (uintptr_t)p; /* In the last valid TLS slot, store a canary. */ *tls_slot(TLS_SLOT_CANARY, t->stack) = CANARY_VAL; if (setjmp(t->jmpbuf) == 0) { jmp_buf_set_stack(t->jmpbuf, t->stack + THREAD_STACK_SZ); scheduler_ready(t); return t; } else { /* Tail call to trampoline which is defined as noinline, to force the creation of a new stack frame as the previous stack frame is now invalid! */ trampoline(); } }
Trampoline unify_tests(Search &s) { LVar A, B, C, D, E, F, G; LVar hello("hello"), one(1), willBeHello, willBeOne, l1(L(A, "hello", B, L(one, C, hello), F)); CapturedCont c, d, e, f, g, h, i, j, k, l; *c = [=](Search &s) { cout << hello << "?=" << willBeHello << endl; return s.identical(1, one, trampoline(d, s)); }; *d = [=](Search &s) { cout << one << "?=" << willBeOne << endl; s.alt(f); return s.identical(hello, "hello", trampoline(e, s)); }; *e = [=](Search &s) { cout << "compare with string succeeded" << endl; s.alt(g); return s.identical(F, G, trampoline(h, s)); }; *f = [=](Search &s) { cout << "compare with string failed" << endl; return end_search; }; *g = [=](Search &s) { cout << "unlike compare with vars did the right thing" << endl; s.alt(i); return s.unify(l1, L("Say", D, "there", L(E, 2, "hello"), G), trampoline(j, s)); }; *h = [=](Search &s) { cout << "unlike compare with vars did the wrong thing" << endl; return end_search; }; *i = [=](Search &s) { cout << "list unify failed" << A << " " << D << " " << B << " " << E << " " << C << endl; return end_search; }; *j = [=](Search &s) { s.alt(l); return s.identical(F, G, trampoline(k, s));}; *k = [=](Search &s) { cout << "list unify: " << A << " " << D << " " << B << " " << E << " " << C << " " << F << " " << G << endl; return end_search; }; *l = [=](Search &s) { cout << "var unify failed" << endl; return end_search; }; return s.unify(hello, willBeHello, trampoline(c, s)); }
inline int c_trampoline(lua_State* L, lua_CFunction f) { return trampoline(L, f); }
int main(void) { trampoline(); return 0; }
/* * There is an ELF kernel and one or more ELF modules loaded. * We wish to start executing the kernel image, so make such * preparations as are required, and do so. */ static int elf64_exec(struct preloaded_file *fp) { struct file_metadata *md; Elf_Ehdr *ehdr; vm_offset_t modulep, kernend, trampcode, trampstack; int err, i; ACPI_TABLE_RSDP *rsdp; char buf[24]; int revision; rsdp = efi_get_table(&acpi20_guid); if (rsdp == NULL) { rsdp = efi_get_table(&acpi_guid); } if (rsdp != NULL) { sprintf(buf, "0x%016llx", (unsigned long long)rsdp); setenv("hint.acpi.0.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); setenv("hint.acpi.0.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; setenv("hint.acpi.0.oem", buf, 1); sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); setenv("hint.acpi.0.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", (unsigned long long)rsdp->XsdtPhysicalAddress); setenv("hint.acpi.0.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); setenv("hint.acpi.0.xsdt_length", buf, 1); } } if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); trampcode = (vm_offset_t)0x0000000040000000; err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, (EFI_PHYSICAL_ADDRESS *)&trampcode); bzero((void *)trampcode, EFI_PAGE_SIZE); trampstack = trampcode + EFI_PAGE_SIZE - 8; bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size); trampoline = (void *)trampcode; PT4 = (p4_entry_t *)0x0000000040000000; err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, (EFI_PHYSICAL_ADDRESS *)&PT4); bzero(PT4, 3 * EFI_PAGE_SIZE); PT3 = &PT4[512]; PT2 = &PT3[512]; /* * This is kinda brutal, but every single 1GB VM memory segment points * to the same first 1GB of physical memory. But it is more than * adequate. */ for (i = 0; i < 512; i++) { /* Each slot of the L4 pages points to the same L3 page. */ PT4[i] = (p4_entry_t)PT3; PT4[i] |= PG_V | PG_RW | PG_U; /* Each slot of the L3 pages points to the same L2 page. */ PT3[i] = (p3_entry_t)PT2; PT3[i] |= PG_V | PG_RW | PG_U; /* The L2 page slots are mapped with 2MB pages for 1GB. */ PT2[i] = i * (2 * 1024 * 1024); PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; } printf("Start @ 0x%lx ...\n", ehdr->e_entry); err = bi_load(fp->f_args, &modulep, &kernend); if (err != 0) return(err); dev_cleanup(); trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4, ehdr->e_entry); panic("exec returned"); }