/[svn]/linuxsampler/trunk/src/scriptvm/ScriptVM.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/scriptvm/ScriptVM.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2581 by schoenebeck, Fri May 30 12:48:05 2014 UTC revision 3581 by schoenebeck, Fri Aug 30 11:40:25 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck   * Copyright (c) 2014 - 2019 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 9  Line 9 
9    
10  #include "ScriptVM.h"  #include "ScriptVM.h"
11    
12    #include <string.h>
13    #include <assert.h>
14  #include "../common/global_private.h"  #include "../common/global_private.h"
15  #include "tree.h"  #include "tree.h"
16    #include "CoreVMFunctions.h"
17    #include "CoreVMDynVars.h"
18    #include "editor/NkspScanner.h"
19    
20  #define DEBUG_SCRIPTVM_CORE 0  #define DEBUG_SCRIPTVM_CORE 0
21    
22    /**
23     * Maximum amount of VM instructions to be executed per ScriptVM::exec() call
24     * in case loops are involved, before the script got automatically suspended
25     * for a certain amount of time to avoid any RT instability issues.
26     *
27     * The following value takes a max. execution time of 300 microseconds as aimed
28     * target, assuming an execution time of approximately 5 microseconds per
29     * instruction this leads to the very approximate value set below.
30     */
31    #define SCRIPTVM_MAX_INSTR_PER_CYCLE_SOFT 70
32    
33    /**
34     * Absolute maximum amount of VM instructions to be executed per
35     * ScriptVM::exec() call (even if no loops are involved), before the script got
36     * automatically suspended for a certain amount of time to avoid any RT
37     * instability issues.
38     *
39     * A distinction between "soft" and "hard" limit is done here ATM because a
40     * script author typically expects that his script might be interrupted
41     * automatically if he is using while() loops, however he might not be
42     * prepared that his script might also be interrupted if no loop is involved
43     * (i.e. on very large scripts).
44     *
45     * The following value takes a max. execution time of 1000 microseconds as
46     * aimed target, assuming an execution time of approximately 5 microseconds per
47     * instruction this leads to the very approximate value set below.
48     */
49    #define SCRIPTVM_MAX_INSTR_PER_CYCLE_HARD 210
50    
51    /**
52     * In case either SCRIPTVM_MAX_INSTR_PER_CYCLE_SOFT or
53     * SCRIPTVM_MAX_INSTR_PER_CYCLE_HARD was exceeded when calling
54     * ScriptVM::exec() : the amount of microseconds the respective script
55     * execution instance should be automatically suspended by the VM.
56     */
57    #define SCRIPT_VM_FORCE_SUSPENSION_MICROSECONDS 1000
58    
59  int InstrScript_parse(LinuxSampler::ParserContext*);  int InstrScript_parse(LinuxSampler::ParserContext*);
60    
61  namespace LinuxSampler {  namespace LinuxSampler {
62    
63        #if DEBUG_SCRIPTVM_CORE
64      static void _printIndents(int n) {      static void _printIndents(int n) {
65          for (int i = 0; i < n; ++i) printf("  ");          for (int i = 0; i < n; ++i) printf("  ");
66          fflush(stdout);          fflush(stdout);
67      }      }
68        #endif
69    
70      static int _requiredMaxStackSizeFor(Statement* statement, int depth = 0) {      static vmint _requiredMaxStackSizeFor(Statement* statement, vmint depth = 0) {
71          if (!statement) return 1;          if (!statement) return 1;
72    
73          switch (statement->statementType()) {          switch (statement->statementType()) {
# Line 40  namespace LinuxSampler { Line 84  namespace LinuxSampler {
84                  printf("-> STMT_LIST\n");                  printf("-> STMT_LIST\n");
85                  #endif                  #endif
86                  Statements* stmts = (Statements*) statement;                  Statements* stmts = (Statements*) statement;
87                  int max = 0;                  vmint max = 0;
88                  for (int i = 0; stmts->statement(i); ++i) {                  for (int i = 0; stmts->statement(i); ++i) {
89                      int size = _requiredMaxStackSizeFor( stmts->statement(i), depth+1 );                      vmint size = _requiredMaxStackSizeFor( stmts->statement(i), depth+1 );
90                      if (max < size) max = size;                      if (max < size) max = size;
91                  }                  }
92                  return max + 1;                  return max + 1;
# Line 54  namespace LinuxSampler { Line 98  namespace LinuxSampler {
98                  printf("-> STMT_BRANCH\n");                  printf("-> STMT_BRANCH\n");
99                  #endif                  #endif
100                  BranchStatement* branchStmt = (BranchStatement*) statement;                  BranchStatement* branchStmt = (BranchStatement*) statement;
101                  int max = 0;                  vmint max = 0;
102                  for (int i = 0; branchStmt->branch(i); ++i) {                  for (int i = 0; branchStmt->branch(i); ++i) {
103                      int size = _requiredMaxStackSizeFor( branchStmt->branch(i), depth+1 );                      vmint size = _requiredMaxStackSizeFor( branchStmt->branch(i), depth+1 );
104                      if (max < size) max = size;                      if (max < size) max = size;
105                  }                  }
106                  return max + 1;                  return max + 1;
# Line 73  namespace LinuxSampler { Line 117  namespace LinuxSampler {
117                  else                  else
118                      return 1;                      return 1;
119              }              }
120    
121                case STMT_SYNC: {
122                    #if DEBUG_SCRIPTVM_CORE
123                    _printIndents(depth);
124                    printf("-> STMT_SYNC\n");
125                    #endif
126                    SyncBlock* syncStmt = (SyncBlock*) statement;
127                    if (syncStmt->statements())
128                        return _requiredMaxStackSizeFor( syncStmt->statements() ) + 1;
129                    else
130                        return 1;
131                }
132    
133                case STMT_NOOP:
134                    break; // no operation like the name suggests
135          }          }
136    
137          return 1; // actually just to avoid compiler warning          return 1; // actually just to avoid compiler warning
138      }      }
139    
140      static int _requiredMaxStackSizeFor(EventHandlers* handlers) {      static vmint _requiredMaxStackSizeFor(EventHandlers* handlers) {
141          int max = 1;          vmint max = 1;
142          for (int i = 0; i < handlers->size(); ++i) {          for (int i = 0; i < handlers->size(); ++i) {
143              int size = _requiredMaxStackSizeFor(handlers->eventHandler(i));              vmint size = _requiredMaxStackSizeFor(handlers->eventHandler(i));
144              if (max < size) max = size;              if (max < size) max = size;
145          }          }
146          return max;          return max;
147      }      }
148    
149      ScriptVM::ScriptVM() : fnWait(this) {      ScriptVM::ScriptVM() :
150          m_context = new ParserContext(this);          m_eventHandler(NULL), m_parserContext(NULL), m_autoSuspend(true),
151            m_acceptExitRes(false)
152        {
153            m_fnMessage = new CoreVMFunction_message;
154            m_fnExit = new CoreVMFunction_exit(this);
155            m_fnWait = new CoreVMFunction_wait(this);
156            m_fnAbs = new CoreVMFunction_abs;
157            m_fnRandom = new CoreVMFunction_random;
158            m_fnNumElements = new CoreVMFunction_num_elements;
159            m_fnInc = new CoreVMFunction_inc;
160            m_fnDec = new CoreVMFunction_dec;
161            m_fnInRange = new CoreVMFunction_in_range;
162            m_varRealTimer = new CoreVMDynVar_NKSP_REAL_TIMER;
163            m_varPerfTimer = new CoreVMDynVar_NKSP_PERF_TIMER;
164            m_fnShLeft = new CoreVMFunction_sh_left;
165            m_fnShRight = new CoreVMFunction_sh_right;
166            m_fnMin = new CoreVMFunction_min;
167            m_fnMax = new CoreVMFunction_max;
168            m_fnArrayEqual = new CoreVMFunction_array_equal;
169            m_fnSearch = new CoreVMFunction_search;
170            m_fnSort = new CoreVMFunction_sort;
171            m_fnIntToReal = new CoreVMFunction_int_to_real;
172            m_fnRealToInt = new CoreVMFunction_real_to_int;
173      }      }
174    
175      ScriptVM::~ScriptVM() {      ScriptVM::~ScriptVM() {
176          if (m_context) {          delete m_fnMessage;
177              if (m_context->globalIntMemory) {          delete m_fnExit;
178                  delete m_context->globalIntMemory;          delete m_fnWait;
179                  m_context->globalIntMemory = NULL;          delete m_fnAbs;
180              }          delete m_fnRandom;
181              delete m_context;          delete m_fnNumElements;
182          }          delete m_fnInc;
183            delete m_fnDec;
184            delete m_fnInRange;
185            delete m_fnShLeft;
186            delete m_fnShRight;
187            delete m_fnMin;
188            delete m_fnMax;
189            delete m_fnArrayEqual;
190            delete m_fnSearch;
191            delete m_fnSort;
192            delete m_fnIntToReal;
193            delete m_fnRealToInt;
194            delete m_varRealTimer;
195            delete m_varPerfTimer;
196      }      }
197    
198      void ScriptVM::loadScript(const String& s) {      VMParserContext* ScriptVM::loadScript(const String& s) {
199          std::istringstream iss(s);          std::istringstream iss(s);
200          loadScript(&iss);          return loadScript(&iss);
201      }      }
202            
203      void ScriptVM::loadScript(std::istream* is) {      VMParserContext* ScriptVM::loadScript(std::istream* is) {
204          m_context->createScanner(is);          ParserContext* context = new ParserContext(this);
205          InstrScript_parse(m_context);          //printf("parserCtx=0x%lx\n", (uint64_t)context);
206          std::cout << "Allocating " << m_context->globalIntVarCount * sizeof(int) << " bytes of global int VM memory.\n";  
207          std::cout << "Allocating " << m_context->globalStrVarCount << " of global VM string variables.\n";          context->registerBuiltInConstIntVariables( builtInConstIntVariables() );
208          if (!m_context->globalIntMemory)          context->registerBuiltInIntVariables( builtInIntVariables() );
209              m_context->globalIntMemory = new ArrayList<int>();          context->registerBuiltInIntArrayVariables( builtInIntArrayVariables() );
210          if (!m_context->globalStrMemory)          context->registerBuiltInDynVariables( builtInDynamicVariables() );
211              m_context->globalStrMemory = new ArrayList<String>();  
212          m_context->globalIntMemory->resize(m_context->globalIntVarCount);          context->createScanner(is);
213          m_context->globalStrMemory->resize(m_context->globalStrVarCount);  
214      }          InstrScript_parse(context);
215            dmsg(2,("Allocating %lld bytes of global int VM memory.\n", context->globalIntVarCount * sizeof(vmint)));
216            dmsg(2,("Allocating %lld bytes of global real VM memory.\n", context->globalRealVarCount * sizeof(vmfloat)));
217            dmsg(2,("Allocating %lld bytes of global unit factor VM memory.\n", context->globalUnitFactorCount * sizeof(vmfloat)));
218            dmsg(2,("Allocating %lld of global VM string variables.\n", context->globalStrVarCount));
219            if (!context->globalIntMemory)
220                context->globalIntMemory = new ArrayList<vmint>();
221            if (!context->globalRealMemory)
222                context->globalRealMemory = new ArrayList<vmfloat>();
223            if (!context->globalUnitFactorMemory)
224                context->globalUnitFactorMemory = new ArrayList<vmfloat>();
225            if (!context->globalStrMemory)
226                context->globalStrMemory = new ArrayList<String>();
227            context->globalIntMemory->resize(context->globalIntVarCount);
228            context->globalRealMemory->resize(context->globalRealVarCount);
229            context->globalUnitFactorMemory->resize(context->globalUnitFactorCount);
230            memset(&((*context->globalIntMemory)[0]), 0, context->globalIntVarCount * sizeof(vmint));
231            memset(&((*context->globalRealMemory)[0]), 0, context->globalRealVarCount * sizeof(vmfloat));
232            for (vmint i = 0; i < context->globalUnitFactorCount; ++i)
233                (*context->globalUnitFactorMemory)[i] = VM_NO_FACTOR;
234            context->globalStrMemory->resize(context->globalStrVarCount);
235    
236      std::vector<ParserIssue> ScriptVM::issues() const {          context->destroyScanner();
         return m_context->issues;  
     }  
237    
238      std::vector<ParserIssue> ScriptVM::errors() const {          return context;
         return m_context->errors;  
239      }      }
240    
241      std::vector<ParserIssue> ScriptVM::warnings() const {      void ScriptVM::dumpParsedScript(VMParserContext* context) {
242          return m_context->warnings;          ParserContext* ctx = dynamic_cast<ParserContext*>(context);
243      }          if (!ctx) {
   
     void ScriptVM::dumpParsedScript() {  
         if (!m_context) {  
244              std::cerr << "No VM context. So nothing to dump.\n";              std::cerr << "No VM context. So nothing to dump.\n";
245              return;              return;
246          }          }
247          if (!m_context->handlers) {          if (!ctx->handlers) {
248              std::cerr << "No event handlers defined in script. So nothing to dump.\n";              std::cerr << "No event handlers defined in script. So nothing to dump.\n";
249              return;              return;
250          }          }
251          if (!m_context->globalIntMemory) {          if (!ctx->globalIntMemory) {
252              std::cerr << "Internal error: no global memory assigend to script VM.\n";              std::cerr << "Internal error: no global integer memory assigend to script VM.\n";
253                return;
254            }
255            if (!ctx->globalRealMemory) {
256                std::cerr << "Internal error: no global real number memory assigend to script VM.\n";
257              return;              return;
258          }          }
259          m_context->handlers->dump();          ctx->handlers->dump();
260        }
261    
262        VMExecContext* ScriptVM::createExecContext(VMParserContext* parserContext) {
263            ParserContext* parserCtx = dynamic_cast<ParserContext*>(parserContext);
264            ExecContext* execCtx = new ExecContext();
265            
266            if (parserCtx->requiredMaxStackSize < 0) {
267                 parserCtx->requiredMaxStackSize =
268                    _requiredMaxStackSizeFor(&*parserCtx->handlers);
269            }
270            execCtx->stack.resize(parserCtx->requiredMaxStackSize);
271            dmsg(2,("Created VM exec context with %lld bytes VM stack size.\n",
272                    parserCtx->requiredMaxStackSize * sizeof(ExecContext::StackFrame)));
273            //printf("execCtx=0x%lx\n", (uint64_t)execCtx);
274            const vmint polyIntSize = parserCtx->polyphonicIntVarCount;
275            execCtx->polyphonicIntMemory.resize(polyIntSize);
276            memset(&execCtx->polyphonicIntMemory[0], 0, polyIntSize * sizeof(vmint));
277    
278            const vmint polyRealSize = parserCtx->polyphonicRealVarCount;
279            execCtx->polyphonicRealMemory.resize(polyRealSize);
280            memset(&execCtx->polyphonicRealMemory[0], 0, polyRealSize * sizeof(vmfloat));
281    
282            const vmint polyFactorSize = parserCtx->polyphonicUnitFactorCount;
283            execCtx->polyphonicUnitFactorMemory.resize(polyFactorSize);
284            for (vmint i = 0; i < polyFactorSize; ++i)
285                execCtx->polyphonicUnitFactorMemory[i] = VM_NO_FACTOR;
286    
287            dmsg(2,("Allocated %lld bytes polyphonic int memory.\n", polyIntSize * sizeof(vmint)));
288            dmsg(2,("Allocated %lld bytes polyphonic real memory.\n", polyRealSize * sizeof(vmfloat)));
289            dmsg(2,("Allocated %lld bytes unit factor memory.\n", polyFactorSize * sizeof(vmfloat)));
290            return execCtx;
291        }
292    
293        std::vector<VMSourceToken> ScriptVM::syntaxHighlighting(const String& s) {
294            std::istringstream iss(s);
295            return syntaxHighlighting(&iss);
296      }      }
297    
298      VMExecContext* ScriptVM::createExecContext() {      std::vector<VMSourceToken> ScriptVM::syntaxHighlighting(std::istream* is) {
299          ExecContext* ctx = new ExecContext();          try {
300          const int stackSize = _requiredMaxStackSizeFor(&*m_context->handlers);              NkspScanner scanner(is);
301          ctx->stack.resize(stackSize);              std::vector<SourceToken> tokens = scanner.tokens();
302          std::cout << "Created VM exec context with "              std::vector<VMSourceToken> result;
303                    << stackSize * sizeof(ExecContext::StackFrame)              result.resize(tokens.size());
304                    << " bytes VM stack size.\n";              for (vmint i = 0; i < tokens.size(); ++i) {
305          const int polySize = m_context->polyphonicIntVarCount;                  SourceToken* st = new SourceToken;
306          ctx->polyphonicIntMemory.resize(polySize);                  *st = tokens[i];
307          std::cout << "Allocated " << polySize * sizeof(int)                  result[i] = VMSourceToken(st);
308                    << " bytes polyphonic memory.\n";              }
309          return ctx;              return result;
310      }          } catch (...) {
311                return std::vector<VMSourceToken>();
312      VMEventHandler* ScriptVM::eventHandler(uint index) {          }
         if (!m_context) return NULL;  
         if (!m_context->handlers) return NULL;  
         return m_context->handlers->eventHandler(index);  
     }  
   
     VMEventHandler* ScriptVM::eventHandlerByName(const String& name) {  
         if (!m_context) return NULL;  
         if (!m_context->handlers) return NULL;  
         return m_context->handlers->eventHandlerByName(name);  
313      }      }
314    
315      VMFunction* ScriptVM::functionByName(const String& name) {      VMFunction* ScriptVM::functionByName(const String& name) {
316          if (name == "message") return &fnMessage;          if (name == "message") return m_fnMessage;
317          else if (name == "exit") return &fnExit;          else if (name == "exit") return m_fnExit;
318          else if (name == "wait") return &fnWait;          else if (name == "wait") return m_fnWait;
319            else if (name == "abs") return m_fnAbs;
320            else if (name == "random") return m_fnRandom;
321            else if (name == "num_elements") return m_fnNumElements;
322            else if (name == "inc") return m_fnInc;
323            else if (name == "dec") return m_fnDec;
324            else if (name == "in_range") return m_fnInRange;
325            else if (name == "sh_left") return m_fnShLeft;
326            else if (name == "sh_right") return m_fnShRight;
327            else if (name == "min") return m_fnMin;
328            else if (name == "max") return m_fnMax;
329            else if (name == "array_equal") return m_fnArrayEqual;
330            else if (name == "search") return m_fnSearch;
331            else if (name == "sort") return m_fnSort;
332            else if (name == "int_to_real") return m_fnIntToReal;
333            else if (name == "real") return m_fnIntToReal;
334            else if (name == "real_to_int") return m_fnRealToInt;
335            else if (name == "int") return m_fnRealToInt;
336          return NULL;          return NULL;
337      }      }
338        
339        bool ScriptVM::isFunctionDisabled(VMFunction* fn, VMParserContext* ctx) {
340            ParserContext* parserCtx = dynamic_cast<ParserContext*>(ctx);
341            if (!parserCtx) return false;
342    
343            if (fn == m_fnMessage && parserCtx->userPreprocessorConditions.count("NKSP_NO_MESSAGE"))
344                return true;
345    
346            return false;
347        }
348    
349        std::map<String,VMIntPtr*> ScriptVM::builtInIntVariables() {
350            return std::map<String,VMIntPtr*>();
351        }
352    
353        std::map<String,VMInt8Array*> ScriptVM::builtInIntArrayVariables() {
354            return std::map<String,VMInt8Array*>();
355        }
356    
357        std::map<String,VMDynVar*> ScriptVM::builtInDynamicVariables() {
358            std::map<String,VMDynVar*> m;
359    
360            m["$NKSP_PERF_TIMER"] = m_varPerfTimer;
361            m["$NKSP_REAL_TIMER"] = m_varRealTimer;
362            m["$KSP_TIMER"] = m_varRealTimer;
363    
364            return m;
365        }
366    
367        std::map<String,vmint> ScriptVM::builtInConstIntVariables() {
368            std::map<String,vmint> m;
369    
370            m["$NI_CB_TYPE_INIT"] = VM_EVENT_HANDLER_INIT;
371            m["$NI_CB_TYPE_NOTE"] = VM_EVENT_HANDLER_NOTE;
372            m["$NI_CB_TYPE_RELEASE"] = VM_EVENT_HANDLER_RELEASE;
373            m["$NI_CB_TYPE_CONTROLLER"] = VM_EVENT_HANDLER_CONTROLLER;
374    
375            return m;
376        }
377    
378        VMEventHandler* ScriptVM::currentVMEventHandler() {
379            return m_eventHandler;
380        }
381    
382        VMParserContext* ScriptVM::currentVMParserContext() {
383            return m_parserContext;
384        }
385    
386      VMExecContext* ScriptVM::currentVMExecContext() {      VMExecContext* ScriptVM::currentVMExecContext() {
387          if (!m_context) return NULL;          if (!m_parserContext) return NULL;
388          return m_context->execContext;          return m_parserContext->execContext;
389        }
390    
391        void ScriptVM::setAutoSuspendEnabled(bool b) {
392            m_autoSuspend = b;
393        }
394    
395        bool ScriptVM::isAutoSuspendEnabled() const {
396            return m_autoSuspend;
397        }
398    
399        void ScriptVM::setExitResultEnabled(bool b) {
400            m_acceptExitRes = b;
401      }      }
402    
403      VMExecStatus_t ScriptVM::exec(VMEventHandler* handler, VMExecContext* execContex) {      bool ScriptVM::isExitResultEnabled() const {
404          if (!m_context) {          return m_acceptExitRes;
405              std::cerr << "No VM parser context. Did you load a script?.\n";      }
406    
407        VMExecStatus_t ScriptVM::exec(VMParserContext* parserContext, VMExecContext* execContex, VMEventHandler* handler) {
408            m_parserContext = dynamic_cast<ParserContext*>(parserContext);
409            if (!m_parserContext) {
410                std::cerr << "No VM parser context provided. Did you load a script?\n";
411              return VMExecStatus_t(VM_EXEC_NOT_RUNNING | VM_EXEC_ERROR);              return VMExecStatus_t(VM_EXEC_NOT_RUNNING | VM_EXEC_ERROR);
412          }          }
413    
414            // a ParserContext object is always tied to exactly one ScriptVM object
415            assert(m_parserContext->functionProvider == this);
416    
417          ExecContext* ctx = dynamic_cast<ExecContext*>(execContex);          ExecContext* ctx = dynamic_cast<ExecContext*>(execContex);
418          if (!ctx) {          if (!ctx) {
419              std::cerr << "Invalid VM exec context.\n";              std::cerr << "Invalid VM exec context.\n";
# Line 198  namespace LinuxSampler { Line 421  namespace LinuxSampler {
421          }          }
422          EventHandler* h = dynamic_cast<EventHandler*>(handler);          EventHandler* h = dynamic_cast<EventHandler*>(handler);
423          if (!h) return VM_EXEC_NOT_RUNNING;          if (!h) return VM_EXEC_NOT_RUNNING;
424            m_eventHandler = handler;
425    
426          m_context->execContext = ctx;          m_parserContext->execContext = ctx;
427    
428          ctx->status = VM_EXEC_RUNNING;          ctx->status = VM_EXEC_RUNNING;
429          StmtFlags_t flags = STMT_SUCCESS;          ctx->instructionsCount = 0;
430            ctx->clearExitRes();
431            StmtFlags_t& flags = ctx->flags;
432            vmint instructionsCounter = 0;
433            vmint synced = m_autoSuspend ? 0 : 1;
434    
435          int& frameIdx = ctx->stackFrame;          int& frameIdx = ctx->stackFrame;
436          if (frameIdx < 0) { // start condition ...          if (frameIdx < 0) { // start condition ...
# Line 258  namespace LinuxSampler { Line 486  namespace LinuxSampler {
486                      if (frame.subindex < 0) ctx->popStack();                      if (frame.subindex < 0) ctx->popStack();
487                      else {                      else {
488                          BranchStatement* branchStmt = (BranchStatement*) frame.statement;                          BranchStatement* branchStmt = (BranchStatement*) frame.statement;
489                          frame.subindex = branchStmt->evalBranch();                          frame.subindex =
490                                (decltype(frame.subindex))
491                                    branchStmt->evalBranch();
492                          if (frame.subindex >= 0) {                          if (frame.subindex >= 0) {
493                              ctx->pushStack(                              ctx->pushStack(
494                                  branchStmt->branch(frame.subindex)                                  branchStmt->branch(frame.subindex)
# Line 279  namespace LinuxSampler { Line 509  namespace LinuxSampler {
509                          ctx->pushStack(                          ctx->pushStack(
510                              whileStmt->statements()                              whileStmt->statements()
511                          );                          );
512                            if (flags == STMT_SUCCESS && !synced &&
513                                instructionsCounter > SCRIPTVM_MAX_INSTR_PER_CYCLE_SOFT)
514                            {
515                                flags = StmtFlags_t(STMT_SUSPEND_SIGNALLED);
516                                ctx->suspendMicroseconds = SCRIPT_VM_FORCE_SUSPENSION_MICROSECONDS;
517                            }
518                      } else ctx->popStack();                      } else ctx->popStack();
519                        break;
520                    }
521    
522                    case STMT_SYNC: {
523                        #if DEBUG_SCRIPTVM_CORE
524                        _printIndents(frameIdx);
525                        printf("-> STMT_SYNC\n");
526                        #endif
527                        SyncBlock* syncStmt = (SyncBlock*) frame.statement;
528                        if (!frame.subindex++ && syncStmt->statements()) {
529                            ++synced;
530                            ctx->pushStack(
531                                syncStmt->statements()
532                            );
533                        } else {
534                            ctx->popStack();
535                            --synced;
536                        }
537                        break;
538                  }                  }
539    
540                    case STMT_NOOP:
541                        break; // no operation like the name suggests
542                }
543    
544                if (flags == STMT_SUCCESS && !synced &&
545                    instructionsCounter > SCRIPTVM_MAX_INSTR_PER_CYCLE_HARD)
546                {
547                    flags = StmtFlags_t(STMT_SUSPEND_SIGNALLED);
548                    ctx->suspendMicroseconds = SCRIPT_VM_FORCE_SUSPENSION_MICROSECONDS;
549              }              }
550    
551                ++instructionsCounter;
552          }          }
553    
554          if (flags & STMT_SUSPEND_SIGNALLED) {          if ((flags & STMT_SUSPEND_SIGNALLED) && !(flags & STMT_ABORT_SIGNALLED)) {
555              ctx->status = VM_EXEC_SUSPENDED;              ctx->status = VM_EXEC_SUSPENDED;
556                ctx->flags  = STMT_SUCCESS;
557          } else {          } else {
558              ctx->status = VM_EXEC_NOT_RUNNING;              ctx->status = VM_EXEC_NOT_RUNNING;
559              if (flags & STMT_ERROR_OCCURRED)              if (flags & STMT_ERROR_OCCURRED)
# Line 293  namespace LinuxSampler { Line 561  namespace LinuxSampler {
561              ctx->reset();              ctx->reset();
562          }          }
563    
564          m_context->execContext = NULL;          ctx->instructionsCount = instructionsCounter;
565    
566            m_eventHandler = NULL;
567            m_parserContext->execContext = NULL;
568            m_parserContext = NULL;
569          return ctx->status;          return ctx->status;
570      }      }
571    

Legend:
Removed from v.2581  
changed lines
  Added in v.3581

  ViewVC Help
Powered by ViewVC