int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap) { bool allocated = false; try { if (func->Native) { return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, numparams, results, numresults); } else { AllocFrame(static_cast<VMScriptFunction *>(func)); allocated = true; VMFillParams(params, TopFrame(), numparams); int numret = VMExec(this, static_cast<VMScriptFunction *>(func)->Code, results, numresults); PopFrame(); return numret; } } catch (VMException *exception) { if (allocated) { PopFrame(); } if (trap != NULL) { *trap = exception; return -1; } throw; } catch (...) { if (allocated) { PopFrame(); } throw; } }
int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap*/) { bool allocated = false; try { if (func->VarFlags & VARF_Native) { return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults); } else { auto code = static_cast<VMScriptFunction *>(func)->Code; // handle empty functions consisting of a single return explicitly so that empty virtual callbacks do not need to set up an entire VM frame. // code cann be null here in case of some non-fatal DECORATE errors. if (code == nullptr || code->word == (0x00808000|OP_RET)) { return 0; } else if (code->word == (0x00048000|OP_RET)) { if (numresults == 0) return 0; results[0].SetInt(static_cast<VMScriptFunction *>(func)->KonstD[0]); return 1; } else { VMCycles[0].Clock(); VMCalls[0]++; auto &stack = GlobalVMStack; stack.AllocFrame(static_cast<VMScriptFunction *>(func)); allocated = true; VMFillParams(params, stack.TopFrame(), numparams); int numret = VMExec(&stack, code, results, numresults); stack.PopFrame(); VMCycles[0].Unclock(); return numret; } } } #if 0 catch (VMException *exception) { if (allocated) { PopFrame(); } if (trap != NULL) { *trap = exception; return -1; } throw; } #endif catch (...) { if (allocated) { GlobalVMStack.PopFrame(); } throw; } }
int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults, VMException **trap) { bool allocated = false; try { if (func->Native) { return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, numparams, results, numresults); } else { AllocFrame(static_cast<VMScriptFunction *>(func)); allocated = true; VMFillParams(params, TopFrame(), numparams); int numret = VMExec(this, static_cast<VMScriptFunction *>(func)->Code, results, numresults); PopFrame(); return numret; } } catch (VMException *exception) { if (allocated) { PopFrame(); } if (trap != NULL) { *trap = exception; return -1; } throw; } catch (EVMAbortException exception) { if (allocated) { PopFrame(); } if (trap != nullptr) { *trap = nullptr; } Printf("VM execution aborted: "); switch (exception) { case X_READ_NIL: Printf("tried to read from address zero."); break; case X_WRITE_NIL: Printf("tried to write to address zero."); break; case X_TOO_MANY_TRIES: Printf("too many try-catch blocks."); break; case X_ARRAY_OUT_OF_BOUNDS: Printf("array access out of bounds."); break; case X_DIVISION_BY_ZERO: Printf("division by zero."); break; case X_BAD_SELF: Printf("invalid self pointer."); break; } Printf("\n"); return -1; } catch (...) { if (allocated) { PopFrame(); } throw; } }