| 24 | } |
| 25 | |
| 26 | void ClosureCreate(char* paramBase, unsigned int helper, unsigned int argument, ExternFuncInfo::Upvalue* upvalue) |
| 27 | { |
| 28 | // Function with a list of external variables to capture |
| 29 | ExternFuncInfo &func = NULLC::commonLinker->exFunctions[argument]; |
| 30 | // Array of upvalue lists |
| 31 | ExternFuncInfo::Upvalue **externalList = NULLC::commonLinker->exCloseLists.data; |
| 32 | // Function external list |
| 33 | ExternLocalInfo *externals = &NULLC::commonLinker->exLocals[func.offsetToFirstLocal + func.localCount]; |
| 34 | // For every function external |
| 35 | for(unsigned int i = 0; i < func.externCount; i++) |
| 36 | { |
| 37 | // coroutine locals are closed immediately |
| 38 | if(externals[i].target == ~0u) |
| 39 | { |
| 40 | upvalue->ptr = (unsigned int*)&upvalue->next; |
| 41 | }else{ |
| 42 | if(externals[i].closeListID & 0x80000000) // If external variable can be found in current scope |
| 43 | { |
| 44 | // Take a pointer to it |
| 45 | upvalue->ptr = (unsigned int*)¶mBase[externals[i].target]; |
| 46 | }else{ // Otherwise, we have to get pointer from functions' existing closure |
| 47 | // Pointer to previous closure is the last function parameter (offset of cmd.helper from stack frame base) |
| 48 | unsigned int *prevClosure = (unsigned int*)*(uintptr_t*)(¶mBase[helper]); |
| 49 | // Take pointer from inside the closure (externals[i].target is in bytes, but array is of unsigned int elements) |
| 50 | upvalue->ptr = *(unsigned int**)((char*)prevClosure + externals[i].target); |
| 51 | } |
| 52 | // Next upvalue will be current list head |
| 53 | upvalue->next = externalList[externals[i].closeListID & ~0x80000000]; |
| 54 | // Save variable size |
| 55 | upvalue->size = externals[i].size; |
| 56 | // Change list head to a new upvalue |
| 57 | externalList[externals[i].closeListID & ~0x80000000] = upvalue; |
| 58 | } |
| 59 | // Move to the next upvalue (upvalue size is max(sizeof(ExternFuncInfo::Upvalue), externals[i].size) |
| 60 | #ifdef _M_X64 |
| 61 | upvalue = (ExternFuncInfo::Upvalue*)((int*)upvalue + ((externals[i].size >> 2) < 4 ? 5 : 2 + (externals[i].size >> 2))); |
| 62 | #else |
| 63 | upvalue = (ExternFuncInfo::Upvalue*)((int*)upvalue + ((externals[i].size >> 2) < 3 ? 3 : 1 + (externals[i].size >> 2))); |
| 64 | #endif |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | void CloseUpvalues(char* paramBase, unsigned int depth, unsigned int argument) |
| 69 | { |