#include "Cmm.h" dupClosure(P_ clos) { ASSERT(LOOKS_LIKE_CLOSURE_PTR(clos)); W_ info, type; clos = UNTAG(R1); info = %INFO_PTR(clos); type = TO_W_(%INFO_TYPE(%STD_INFO(info))); // Check if we can/should copy this closure switch [0 .. N_CLOSURE_TYPES] type { case FUN, FUN_1_0, FUN_0_1, FUN_1_1, FUN_2_0, FUN_0_2: { goto type_ok; } // Do not copy data without pointers case CONSTR, CONSTR_1_0, CONSTR_0_1, CONSTR_1_1, CONSTR_2_0, CONSTR_0_2, CONSTR_NOCAF: { if (TO_W_(%INFO_PTRS(%STD_INFO(clos))) > 0) { goto type_ok; } else { return (clos); } } // Thunks are good case THUNK, THUNK_1_0, THUNK_0_1, THUNK_2_0, THUNK_1_1, THUNK_0_2, THUNK_SELECTOR, AP, PAP: { goto type_ok; } // FUN_STATIC, THUNK_STATIC fall through to this case because of #9 default: { goto type_not_ok; } } type_not_ok: // Return the closure unchanged foreign "C" dupUnsupportedWarning(clos "ptr"); return (clos); type_ok: W_ len, bytes; (len) = foreign "C" closure_sizeW(clos "ptr"); bytes = WDS(len); ALLOC_PRIM_P(bytes, dupClosure, clos); W_ copy; copy = Hp - bytes + WDS(1); prim %memcpy(Hp - bytes + WDS(1), clos, bytes, 1); return (copy); }