26 explicit VM(
Engine &engine);
36 const Value *args =
nullptr,
38 DebugAction initialAction = DebugAction::StepInto);
39 ExecStatus resumeExecution();
40 bool isPaused()
const {
return !frames_.empty(); }
41 Value takeResult() {
return std::move(lastResult_); }
56 const std::string &ownerClass = std::string(),
57 bool isCtor =
false,
const Value *ctorSeed =
nullptr);
68 std::shared_ptr<VmContinuation> cont);
71 std::unique_ptr<PausedState> savePausedState();
72 void restorePausedState(std::unique_ptr<PausedState> state);
79 void setCompiledFuncs(
const std::unordered_map<std::string, BytecodeChunk> *funcs)
81 compiledFuncs_ = funcs;
82 scriptLocalFuncs_ =
nullptr;
84 void setCompiledFuncs(
const std::unordered_map<std::string, BytecodeChunk> *funcs,
85 const std::unordered_map<std::string, BytecodeChunk> *scriptLocal)
87 compiledFuncs_ = funcs;
88 scriptLocalFuncs_ = scriptLocal;
94 const BytecodeChunk *findCompiledFunc(
const std::string &name)
const
96 if (scriptLocalFuncs_) {
97 auto it = scriptLocalFuncs_->find(name);
98 if (it != scriptLocalFuncs_->end())
101 if (compiledFuncs_) {
102 auto it = compiledFuncs_->find(name);
103 if (it != compiledFuncs_->end())
110 const std::vector<std::pair<std::string, Value>> &lastVarMap()
const {
return lastVarMap_; }
111 void clearLastVarMap() { lastVarMap_.clear(); }
115 void setFrameDynVars(std::unordered_map<std::string, Value> *dv);
122 Value *registers =
nullptr;
123 bool wasReentrantEval =
false;
129 auto &f = frames_.back();
130 return { f.chunk, f.R };
134 size_t frameCount()
const {
return frames_.size(); }
140 FrameView frameViewAt(
size_t depthFromTop)
142 if (depthFromTop >= frames_.size())
144 auto &f = frames_[frames_.size() - 1 - depthFromTop];
145 return { f.chunk, f.R };
149 int callDepth()
const {
return std::max(0,
static_cast<int>(frames_.size()) - 1); }
154 const std::string ¤tMethodClass()
const
156 static const std::string kEmpty;
157 return frames_.empty() ? kEmpty : frames_.back().ownerClass;
159 bool currentMethodIsCtor()
const
161 return !frames_.empty() && frames_.back().isCtor;
164 void setMaxRecursionDepth(
int d) { maxRecursion_ = d; }
172 Environment *callerEnvAtDepth(
int n);
177 void assignInCallerFrame(
int n,
const std::string &name,
const Value &val);
185 Environment *inheritedScope_ =
nullptr;
189 bool inReentrantEval_ =
false;
197 void setStopOnError(
bool b) { stopOnError_ = b; }
198 bool atErrorPause()
const {
return atErrorPause_; }
199 const std::string &errorPauseMessage()
const {
return errorPauseMsg_; }
201 bool stopOnError_ =
false;
202 bool atErrorPause_ =
false;
203 std::exception_ptr pausedError_;
204 std::string errorPauseMsg_;
210 void writeToFrameMatchingEnv(Environment *env,
const std::string &name,
216 const std::vector<std::string> ¤tFrameCallerArgNames()
const
218 static const std::vector<std::string> kEmpty;
219 if (frames_.size() < 2)
return kEmpty;
220 return frames_.back().callerArgNames;
229 std::unordered_map<std::string, Value>
230 snapshotFrameVars(Environment *frameEnv);
235 void setNextFrameDynVars(std::unordered_map<std::string, Value> *dv)
237 nextFrameDynVars_ = dv;
242 std::unordered_map<std::string, Value> *nextFrameDynVars_ =
nullptr;
243 const std::unordered_map<std::string, BytecodeChunk> *compiledFuncs_ =
nullptr;
244 const std::unordered_map<std::string, BytecodeChunk> *scriptLocalFuncs_ =
nullptr;
247 static constexpr size_t kRegStackSize = 256 * 50;
248 std::vector<Value> regStack_;
249 size_t regStackTop_ = 0;
255 const BytecodeChunk *chunk =
nullptr;
256 const Instruction *ip =
nullptr;
260 size_t forStackBase = 0;
261 size_t tryStackBase = 0;
263 bool isMultiReturn =
false;
270 std::string ownerClass;
275 std::unordered_map<std::string, Value> *dynVars =
nullptr;
280 std::unique_ptr<Environment> env;
287 std::vector<std::string> callerArgNames;
294 std::shared_ptr<VmContinuation> cont;
296 std::vector<CallFrame> frames_;
303 const double *data =
nullptr;
304 const void *rawData =
nullptr;
305 ValueType rangeType = ValueType::DOUBLE;
314 double lazyStart = 0.0;
315 double lazyStep = 1.0;
317 std::vector<ForState> forStack_;
322 const Instruction *catchIp;
327 std::vector<TryHandler> tryStack_;
333 std::vector<CallFrame> frames;
334 std::vector<ForState> forStack;
335 std::vector<TryHandler> tryStack;
336 std::vector<Value> regSnapshot;
337 size_t regStackTop = 0;
347 std::vector<const BytecodeChunk *>>
349 bool wasReentrantEval =
false;
353 int maxRecursion_ = 200;
356 std::unordered_map<const BytecodeChunk *, std::vector<const BytecodeChunk *>> chunkCallCache_;
359 std::vector<std::pair<std::string, Value>> lastVarMap_;
362 static constexpr size_t kMaxReturns = 16;
363 Value returnBuf_[kMaxReturns];
364 uint8_t returnCount_ = 0;
367 ExecStatus dispatchLoop();
374 uint8_t destReg,
size_t nargout,
375 bool isMulti =
false, uint8_t outBase = 0, uint8_t nout = 0,
376 const std::string &ownerClass = std::string(),
bool isCtor =
false,
377 const Value *ctorSeed =
nullptr);
378 void popCallFrame(
Value retVal);
383 bool startContinuation(std::shared_ptr<VmContinuation> cont);
393 void exportTopLevelVariables();
396 bool dispatchTryCatch(
const char *msg,
const char *identifier);
397 [[noreturn]]
void enrichAndThrow(
const std::exception &ex,
402 void forSetVar(
Value &varReg,
const ForState &fs);
406 Value unarySlowPath(OpCode op,
const Value &operand);
414 bool tryBinaryOpFrame(uint8_t dst, OpCode op, uint8_t lhsReg, uint8_t rhsReg,
416 bool tryUnaryOpFrame(uint8_t dst, OpCode op, uint8_t operandReg,
438 bool execCallIndirectTarget(
const Value &target, uint8_t dstReg, uint8_t argBase, uint8_t na,
440 bool execCallIndirectSpan(
const Value &target, uint8_t dstReg,
441 const Value *AB, uint8_t na,
Value *R, CallFrame &frame,
448 void execIndirectIndexTarget(
const Value &target, uint8_t dstReg, uint8_t argBase, uint8_t na,
450 void execIndirectIndexSpan(
const Value &mv, uint8_t dstReg,
const Value *AB,
451 uint8_t na,
Value *R);