Use folly::dynamic::object and folly::dynamic::string exclusivly
[hiphop-php.git] / hphp / runtime / base / execution-context.h
blobb71a227fc1d56b47a6da32ba503c00fdbfe5ec5e
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_EXECUTION_CONTEXT_H_
18 #define incl_HPHP_EXECUTION_CONTEXT_H_
20 #include "hphp/runtime/base/class-info.h"
21 #include "hphp/runtime/base/complex-types.h"
22 #include "hphp/runtime/base/ini-setting.h"
23 #include "hphp/runtime/server/transport.h"
24 #include "hphp/runtime/base/debuggable.h"
25 #include "hphp/runtime/server/virtual-host.h"
26 #include "hphp/runtime/base/string-buffer.h"
27 #include "hphp/runtime/base/hphp-array.h"
28 #include "hphp/runtime/vm/func.h"
29 #include "hphp/runtime/vm/bytecode.h"
30 #include "hphp/util/lock.h"
31 #include "hphp/util/thread-local.h"
32 #include <setjmp.h>
34 #define PHP_OUTPUT_HANDLER_START (1<<0)
35 #define PHP_OUTPUT_HANDLER_CONT (1<<1)
36 #define PHP_OUTPUT_HANDLER_END (1<<2)
38 namespace vixl {
39 class Simulator;
42 namespace HPHP {
43 class c_Continuation;
44 namespace Eval {
45 class PhpFile;
48 class EventHook;
49 namespace JIT {
50 class Translator;
52 class PCFilter;
54 ///////////////////////////////////////////////////////////////////////////////
56 typedef hphp_hash_map<StringData*, HPHP::Eval::PhpFile*, string_data_hash,
57 string_data_same> EvaledFilesMap;
58 typedef std::vector<HPHP::Eval::PhpFile*> EvaledFilesVec;
60 /**
61 * Mainly designed for extensions to perform initialization and shutdown
62 * sequences at request scope.
64 class RequestEventHandler {
65 public:
66 RequestEventHandler() : m_inited(false) {}
67 virtual ~RequestEventHandler() {}
69 virtual void requestInit() = 0;
70 virtual void requestShutdown() = 0;
72 void setInited(bool inited) { m_inited = inited;}
73 bool getInited() const { return m_inited;}
75 // Priority of request shutdown call. Lower priority value means
76 // requestShutdown is called earlier than higher priority values.
77 virtual int priority() const { return 0;}
79 protected:
80 bool m_inited;
83 struct VMState {
84 PC pc;
85 ActRec* fp;
86 ActRec* firstAR;
87 TypedValue *sp;
90 class MethodInfoVM : public ClassInfo::MethodInfo,
91 public AtomicCountable {
92 public:
93 ~MethodInfoVM();
94 void atomicRelease() { delete this; }
97 class ClassInfoVM : public ClassInfo,
98 public AtomicCountable {
99 public:
100 ~ClassInfoVM();
101 void atomicRelease() { delete this; }
102 virtual const String& getParentClass() const { return m_parentClass; }
104 const InterfaceSet &getInterfaces() const { return m_interfaces;}
105 const InterfaceVec &getInterfacesVec() const { return m_interfacesVec;}
106 const MethodMap &getMethods() const { return m_methods;}
107 const MethodVec &getMethodsVec() const { return m_methodsVec;}
108 const PropertyMap &getProperties() const { return m_properties;}
109 const PropertyVec &getPropertiesVec() const { return m_propertiesVec;}
110 const ConstantMap &getConstants() const { return m_constants;}
111 const ConstantVec &getConstantsVec() const { return m_constantsVec;}
112 const UserAttributeVec &getUserAttributeVec() const { return m_userAttrVec;}
113 const TraitSet &getTraits() const { return m_traits;}
114 const TraitVec &getTraitsVec() const { return m_traitsVec;}
115 const TraitAliasVec &getTraitAliasesVec() const { return m_traitAliasesVec;}
117 private:
118 String m_parentClass;
119 InterfaceSet m_interfaces; // all interfaces
120 InterfaceVec m_interfacesVec; // all interfaces
121 TraitSet m_traits; // all used traits
122 TraitVec m_traitsVec; // all used traits
123 TraitAliasVec m_traitAliasesVec; // all trait aliases
124 MethodMap m_methods; // all methods
125 MethodVec m_methodsVec; // in source order
126 PropertyMap m_properties; // all properties
127 PropertyVec m_propertiesVec; // in source order
128 ConstantMap m_constants; // all constants
129 ConstantVec m_constantsVec; // in source order
130 UserAttributeVec m_userAttrVec;
132 public:
133 friend class HPHP::Class;
136 enum class CallType {
137 ClsMethod,
138 ObjMethod,
139 CtorMethod,
141 enum class LookupResult {
142 MethodFoundWithThis,
143 MethodFoundNoThis,
144 MagicCallFound,
145 MagicCallStaticFound,
146 MethodNotFound,
149 enum InclOpFlags {
150 InclOpDefault = 0,
151 InclOpFatal = 1,
152 InclOpOnce = 2,
153 InclOpDocRoot = 8,
154 InclOpRelative = 16,
157 inline InclOpFlags
158 operator|(const InclOpFlags &l, const InclOpFlags &r) {
159 return InclOpFlags(int(l) | int(r));
162 inline InclOpFlags
163 operator&(const InclOpFlags &l, const InclOpFlags &r) {
164 return InclOpFlags(int(l) & int(r));
167 struct VMParserFrame {
168 std::string filename;
169 int lineNumber;
172 ///////////////////////////////////////////////////////////////////////////////
175 * Put all global variables here so we can gather them into one thread-local
176 * variable for easy access.
178 class BaseExecutionContext : public IDebuggable {
179 public:
180 // These members are declared first for performance reasons: they
181 // are accessed from within the TC and having their offset fit
182 // within a single byte makes the generated code slightly smaller
183 // and faster.
184 Stack m_stack;
185 ActRec* m_fp;
186 PC m_pc;
187 int64_t m_currentThreadIdx;
188 public:
189 enum ShutdownType {
190 ShutDown,
191 PostSend,
192 CleanUp,
194 ShutdownTypeCount
197 enum class ErrorThrowMode {
198 Never,
199 IfUnhandled,
200 Always,
203 enum class ErrorState {
204 NoError,
205 ErrorRaised,
206 ExecutingUserHandler,
207 ErrorRaisedByUserHandler,
210 public:
211 BaseExecutionContext();
212 ~BaseExecutionContext();
214 // For RPCRequestHandler
215 void backupSession();
216 void restoreSession();
218 // implementing IDebuggable
219 virtual void debuggerInfo(InfoVec &info);
222 * System settings.
224 Transport *getTransport() { return m_transport;}
225 void setTransport(Transport *transport) { m_transport = transport;}
226 std::string getRequestUrl(size_t szLimit = std::string::npos);
227 String getMimeType() const;
228 void setContentType(const String& mimetype, const String& charset);
229 String getRequestMemoryMaxBytes() const { return m_maxMemory; }
230 void setRequestMemoryMaxBytes(const std::string& max);
231 String getCwd() const { return m_cwd;}
232 void setCwd(const String& cwd) { m_cwd = cwd;}
235 * Write to output.
237 void write(const String& s);
238 void write(const char *s, int len);
239 void write(const char *s) { write(s, strlen(s));}
240 void writeStdout(const char *s, int len);
242 typedef void (*PFUNC_STDOUT)(const char *s, int len, void *data);
243 void setStdout(PFUNC_STDOUT func, void *data);
246 * Output buffering.
248 void obStart(CVarRef handler = uninit_null());
249 String obCopyContents();
250 String obDetachContents();
251 int obGetContentLength();
252 void obClean();
253 bool obFlush();
254 void obFlushAll();
255 bool obEnd();
256 void obEndAll();
257 int obGetLevel();
258 Array obGetStatus(bool full);
259 void obSetImplicitFlush(bool on);
260 Array obGetHandlers();
261 void obProtect(bool on); // making sure obEnd() never passes current level
262 void flush();
263 StringBuffer *swapOutputBuffer(StringBuffer *sb) {
264 StringBuffer *current = m_out;
265 m_out = sb;
266 return current;
268 String getRawPostData() const { return m_rawPostData; }
269 void setRawPostData(String& pd) { m_rawPostData = pd; }
272 * Request sequences and program execution hooks.
274 void registerRequestEventHandler(RequestEventHandler *handler);
275 void registerShutdownFunction(CVarRef function, Array arguments,
276 ShutdownType type);
277 Variant popShutdownFunction(ShutdownType type);
278 void onRequestShutdown();
279 void onShutdownPreSend();
280 void onShutdownPostSend();
283 * Error handling
285 Variant pushUserErrorHandler(CVarRef function, int error_types);
286 Variant pushUserExceptionHandler(CVarRef function);
287 void popUserErrorHandler();
288 void popUserExceptionHandler();
289 bool errorNeedsHandling(int errnum,
290 bool callUserHandler,
291 ErrorThrowMode mode);
292 bool errorNeedsLogging(int errnum);
293 void handleError(const std::string &msg,
294 int errnum,
295 bool callUserHandler,
296 ErrorThrowMode mode,
297 const std::string &prefix,
298 bool skipFrame = false);
299 bool callUserErrorHandler(const Exception &e, int errnum,
300 bool swallowExceptions);
301 virtual void recordLastError(const Exception &e, int errnum = 0);
302 bool onFatalError(const Exception &e); // returns handled
303 bool onUnhandledException(Object e);
304 ErrorState getErrorState() const { return m_errorState;}
305 void setErrorState(ErrorState state) { m_errorState = state;}
306 String getLastError() const { return m_lastError;}
307 int getLastErrorNumber() const { return m_lastErrorNum;}
308 int getErrorReportingLevel() const { return m_errorReportingLevel;}
309 void setErrorReportingLevel(int level) { m_errorReportingLevel = level;}
310 String getErrorPage() const { return m_errorPage;}
311 void setErrorPage(const String& page) { m_errorPage = (std::string) page; }
312 bool getLogErrors() const { return m_logErrors;}
313 void setLogErrors(bool on);
314 String getErrorLog() const { return m_errorLog;}
315 void setErrorLog(const String& filename);
318 * Misc. settings
320 String getenv(const String& name) const;
321 void setenv(const String& name, const String& value);
322 Array getEnvs() const { return m_envs; }
324 String getTimeZone() const { return m_timezone;}
325 void setTimeZone(const String& timezone) { m_timezone = timezone;}
326 String getDefaultTimeZone() const { return m_timezoneDefault;}
327 void setDefaultTimeZone(const String& s) { m_timezoneDefault = s;}
328 void setThrowAllErrors(bool f) { m_throwAllErrors = f; }
329 bool getThrowAllErrors() const { return m_throwAllErrors; }
330 void setExitCallback(Variant f) { m_exitCallback = f; }
331 Variant getExitCallback() { return m_exitCallback; }
333 void setStreamContext(Resource &context) { m_streamContext = context; }
334 Resource &getStreamContext() { return m_streamContext; }
336 String getDefaultCharset() const { return m_defaultCharset; }
337 int64_t getSocketDefaultTimeout() const { return m_socketDefaultTimeout; }
339 void restoreIncludePath();
340 void setIncludePath(const String& path);
341 String getIncludePath() const;
342 Array getIncludePathArray() const { return m_include_paths; }
343 const VirtualHost *getVirtualHost() const { return m_vhost; }
344 void setVirtualHost(const VirtualHost *vhost) { m_vhost = vhost; }
346 const String& getSandboxId() const { return m_sandboxId; }
347 void setSandboxId(const String& sandboxId) { m_sandboxId = sandboxId; }
349 DECLARE_DBG_SETTING_ACCESSORS
351 private:
352 class OutputBuffer {
353 public:
354 OutputBuffer() : oss(8192) {}
355 StringBuffer oss;
356 Variant handler;
359 private:
360 static const StaticString s_amp;
361 // system settings
362 Transport *m_transport;
363 std::string m_maxMemory;
364 String m_cwd;
366 // output buffering
367 StringBuffer *m_out; // current output buffer
368 std::list<OutputBuffer*> m_buffers; // a stack of output buffers
369 bool m_implicitFlush;
370 int m_protectedLevel;
371 PFUNC_STDOUT m_stdout;
372 void *m_stdoutData;
373 String m_rawPostData;
375 // request handlers
376 std::set<RequestEventHandler*> m_requestEventHandlerSet;
377 std::vector<RequestEventHandler*> m_requestEventHandlers;
378 Array m_shutdowns;
380 // error handling
381 std::vector<std::pair<Variant,int> > m_userErrorHandlers;
382 std::vector<Variant> m_userExceptionHandlers;
383 ErrorState m_errorState;
384 int64_t m_errorReportingLevel;
385 String m_lastError;
386 int m_lastErrorNum;
387 std::string m_errorPage;
388 bool m_logErrors;
389 String m_errorLog;
391 // misc settings
392 Array m_envs;
393 String m_timezone;
394 String m_timezoneDefault;
395 String m_argSeparatorOutput;
396 bool m_throwAllErrors;
397 Resource m_streamContext;
398 String m_defaultCharset;
399 int64_t m_socketDefaultTimeout;
401 // session backup/restore for RPCRequestHandler
402 Array m_shutdownsBackup;
403 std::vector<std::pair<Variant,int> > m_userErrorHandlersBackup;
404 std::vector<Variant> m_userExceptionHandlersBackup;
406 Variant m_exitCallback;
408 // include_path configuration option
409 Array m_include_paths;
411 // cache the sandbox id for the request
412 String m_sandboxId;
414 const VirtualHost *m_vhost;
415 // helper functions
416 void resetCurrentBuffer();
417 void executeFunctions(CArrRef funcs);
419 DECLARE_DBG_SETTING
422 class VMExecutionContext : public BaseExecutionContext {
423 public:
424 VMExecutionContext();
425 ~VMExecutionContext();
427 typedef std::set<ObjectData*> LiveObjSet;
428 LiveObjSet m_liveBCObjs;
430 // pcre ini_settings
431 long m_preg_backtrace_limit;
432 long m_preg_recursion_limit;
434 public:
435 void requestInit();
436 void requestExit();
438 static void fillContinuationVars(
439 ActRec* origFp, const Func* origFunc, ActRec* genFp, const Func* genFunc);
440 void pushLocalsAndIterators(const HPHP::Func* f, int nparams = 0);
441 void enqueueAPCHandle(APCHandle* handle);
443 private:
444 std::vector<APCHandle*> m_apcHandles;
445 void manageAPCHandle();
447 enum class VectorLeaveCode {
448 ConsumeAll,
449 LeaveLast
451 template <bool setMember, bool warn, bool define, bool unset, bool reffy,
452 unsigned mdepth, VectorLeaveCode mleave, bool saveResult>
453 bool memberHelperPre(PC& pc, unsigned& ndiscard, TypedValue*& base,
454 TypedValue& tvScratch,
455 TypedValue& tvLiteral,
456 TypedValue& tvRef, TypedValue& tvRef2,
457 MemberCode& mcode, TypedValue*& curMember);
458 template <bool warn, bool saveResult, VectorLeaveCode mleave>
459 void getHelperPre(PC& pc, unsigned& ndiscard,
460 TypedValue*& base, TypedValue& tvScratch,
461 TypedValue& tvLiteral,
462 TypedValue& tvRef, TypedValue& tvRef2,
463 MemberCode& mcode, TypedValue*& curMember);
464 template <bool saveResult>
465 void getHelperPost(unsigned ndiscard, TypedValue*& tvRet,
466 TypedValue& tvScratch, Variant& tvRef,
467 Variant& tvRef2);
468 void getHelper(PC& pc, unsigned& ndiscard, TypedValue*& tvRet,
469 TypedValue*& base, TypedValue& tvScratch,
470 TypedValue& tvLiteral,
471 Variant& tvRef, Variant& tvRef2,
472 MemberCode& mcode, TypedValue*& curMember);
474 template <bool warn, bool define, bool unset, bool reffy, unsigned mdepth,
475 VectorLeaveCode mleave>
476 bool setHelperPre(PC& pc, unsigned& ndiscard, TypedValue*& base,
477 TypedValue& tvScratch,
478 TypedValue& tvLiteral,
479 TypedValue& tvRef, TypedValue& tvRef2,
480 MemberCode& mcode, TypedValue*& curMember);
481 template <unsigned mdepth>
482 void setHelperPost(unsigned ndiscard, Variant& tvRef,
483 Variant& tvRef2);
484 template <bool isEmpty>
485 void isSetEmptyM(IOP_ARGS);
487 template<class Op> void implCellBinOp(IOP_ARGS, Op op);
488 template<class Op> void implCellBinOpBool(IOP_ARGS, Op op);
489 void implVerifyRetType(IOP_ARGS);
490 bool cellInstanceOf(TypedValue* c, const HPHP::NamedEntity* s);
491 bool iopInstanceOfHelper(const StringData* s1, Cell* c2);
492 bool initIterator(PC& pc, PC& origPc, Iter* it,
493 Offset offset, Cell* c1);
494 bool initIteratorM(PC& pc, PC& origPc, Iter* it,
495 Offset offset, Ref* r1, TypedValue* val, TypedValue* key);
496 void jmpSurpriseCheck(Offset o);
497 template<Op op> void jmpOpImpl(IOP_ARGS);
498 template<class Op> void roundOpImpl(Op op);
499 #define O(name, imm, pusph, pop, flags) \
500 void iop##name(IOP_ARGS);
501 OPCODES
502 #undef O
504 void classExistsImpl(IOP_ARGS, Attr typeAttr);
505 void fPushObjMethodImpl(
506 Class* cls, StringData* name, ObjectData* obj, int numArgs);
507 ActRec* fPushFuncImpl(const Func* func, int numArgs);
509 public:
510 typedef hphp_hash_map<const StringData*, ClassInfo::ConstantInfo*,
511 string_data_hash, string_data_same> ConstInfoMap;
512 ConstInfoMap m_constInfo;
514 std::unordered_map<const ObjectData*,ArrayNoDtor> dynPropTable;
516 const HPHP::Func* lookupMethodCtx(const HPHP::Class* cls,
517 const StringData* methodName,
518 const HPHP::Class* pctx,
519 CallType lookupType,
520 bool raise = false);
521 LookupResult lookupObjMethod(const HPHP::Func*& f,
522 const HPHP::Class* cls,
523 const StringData* methodName,
524 const Class* ctx,
525 bool raise = false);
526 LookupResult lookupClsMethod(const HPHP::Func*& f,
527 const HPHP::Class* cls,
528 const StringData* methodName,
529 ObjectData* this_,
530 const Class* ctx,
531 bool raise = false);
532 LookupResult lookupCtorMethod(const HPHP::Func*& f,
533 const HPHP::Class* cls,
534 bool raise = false);
535 ObjectData* createObject(StringData* clsName,
536 CVarRef params,
537 bool init = true);
538 ObjectData* createObjectOnly(StringData* clsName);
541 * Look up a class constant.
543 * The returned Cell is guaranteed not to hold a reference counted
544 * type. Raises an error if the class has no constant with that
545 * name, or if the class is not defined.
547 Cell lookupClsCns(const HPHP::NamedEntity* ne,
548 const StringData* cls,
549 const StringData* cns);
550 Cell lookupClsCns(const StringData* cls,
551 const StringData* cns);
553 // Get the next outermost VM frame, even accross re-entry
554 ActRec* getOuterVMFrame(const ActRec* ar);
556 std::string prettyStack(const std::string& prefix) const;
557 static void DumpStack();
558 static void DumpCurUnit(int skip = 0);
559 static void PrintTCCallerInfo();
561 VarEnv* m_globalVarEnv;
563 EvaledFilesMap m_evaledFiles;
564 EvaledFilesVec m_evaledFilesOrder;
565 typedef std::vector<HPHP::Unit*> EvaledUnitsVec;
566 EvaledUnitsVec m_createdFuncs;
569 * Accessors for VMExecutionContext state that check safety wrt
570 * whether these values may be stale due to TC. Asserts in these
571 * usually mean the need for a VMRegAnchor somewhere in the call
572 * chain.
575 void checkRegStateWork() const;
576 void checkRegState() const { if (debug) checkRegStateWork(); }
578 const ActRec* getFP() const { checkRegState(); return m_fp; }
579 ActRec* getFP() { checkRegState(); return m_fp; }
580 PC getPC() const { checkRegState(); return m_pc; }
581 const Stack& getStack() const { checkRegState(); return m_stack; }
582 Stack& getStack() { checkRegState(); return m_stack; }
584 Offset pcOff() const {
585 return getFP()->m_func->unit()->offsetOf(m_pc);
588 ActRec* m_firstAR;
589 std::vector<Fault> m_faults;
591 ActRec* getStackFrame();
592 ObjectData* getThis();
593 Class* getContextClass();
594 Class* getParentContextClass();
595 const String& getContainingFileName();
596 int getLine();
597 Array getCallerInfo();
598 HPHP::Eval::PhpFile* lookupPhpFile(
599 StringData* path, const char* currentDir, bool* initial = nullptr);
600 HPHP::Unit* evalInclude(StringData* path,
601 const StringData* curUnitFilePath, bool* initial);
602 HPHP::Unit* evalIncludeRoot(StringData* path,
603 InclOpFlags flags, bool* initial);
604 HPHP::Eval::PhpFile* lookupIncludeRoot(StringData* path,
605 InclOpFlags flags, bool* initial,
606 HPHP::Unit* unit = 0);
607 bool evalUnit(HPHP::Unit* unit, PC& pc, int funcType);
608 void invokeUnit(TypedValue* retval, HPHP::Unit* unit);
609 HPHP::Unit* compileEvalString(StringData* code,
610 const char* evalFilename = nullptr);
611 const String& createFunction(const String& args, const String& code);
612 bool evalPHPDebugger(TypedValue* retval, StringData *code, int frame);
613 void enterDebuggerDummyEnv();
614 void exitDebuggerDummyEnv();
615 void preventReturnsToTC();
616 void destructObjects();
617 int m_lambdaCounter;
618 struct ReentryRecord {
619 VMState m_savedState;
620 const ActRec* m_entryFP;
621 ReentryRecord(const VMState &s, const ActRec* entryFP) :
622 m_savedState(s), m_entryFP(entryFP) { }
623 ReentryRecord() {}
625 typedef TinyVector<ReentryRecord, 32> NestedVMVec;
626 NestedVMVec m_nestedVMs;
628 int m_nesting;
629 bool isNested() { return m_nesting != 0; }
630 void pushVMState(VMState &savedVM, const ActRec* reentryAR);
631 void popVMState();
633 ActRec* getPrevVMState(const ActRec* fp,
634 Offset* prevPc = nullptr,
635 TypedValue** prevSp = nullptr,
636 bool* fromVMEntry = nullptr);
637 Array debugBacktrace(bool skip = false,
638 bool withSelf = false,
639 bool withThis = false,
640 VMParserFrame* parserFrame = nullptr,
641 bool ignoreArgs = false,
642 int limit = 0);
643 VarEnv* getVarEnv(int frame = 0);
644 void setVar(StringData* name, TypedValue* v, bool ref);
645 Array getLocalDefinedVariables(int frame);
646 HPHP::PCFilter* m_breakPointFilter;
647 HPHP::PCFilter* m_lastLocFilter;
648 bool m_dbgNoBreak;
649 bool doFCall(HPHP::ActRec* ar, PC& pc);
650 bool doFCallArray(PC& pc);
651 bool doFCallArrayTC(PC pc);
652 CVarRef getEvaledArg(const StringData* val, const String& namespacedName);
653 virtual void recordLastError(const Exception &e, int errnum = 0);
654 String getLastErrorPath() const { return m_lastErrorPath; }
655 int getLastErrorLine() const { return m_lastErrorLine; }
657 private:
658 void enterVMWork(ActRec* enterFnAr);
659 void enterVMPrologue(ActRec* enterFnAr);
660 void enterVM(TypedValue* retval, ActRec* ar);
661 void reenterVM(TypedValue* retval, ActRec* ar, TypedValue* savedSP);
662 void doFPushCuf(IOP_ARGS, bool forward, bool safe);
663 template <bool forwarding>
664 void pushClsMethodImpl(Class* cls, StringData* name,
665 ObjectData* obj, int numArgs);
666 bool prepareFuncEntry(ActRec* ar, PC& pc);
667 bool prepareArrayArgs(ActRec* ar, CVarRef arrayArgs);
668 void recordCodeCoverage(PC pc);
669 bool isReturnHelper(uintptr_t address);
670 void switchModeForDebugger();
671 int m_coverPrevLine;
672 HPHP::Unit* m_coverPrevUnit;
673 Array m_evaledArgs;
674 String m_lastErrorPath;
675 int m_lastErrorLine;
676 public:
677 void resetCoverageCounters();
678 void shuffleMagicArgs(ActRec* ar);
679 void syncGdbState();
680 enum InvokeFlags {
681 InvokeNormal = 0,
682 InvokeCuf = 1,
683 InvokePseudoMain = 2
685 void invokeFunc(TypedValue* retval,
686 const HPHP::Func* f,
687 CVarRef args_ = init_null_variant,
688 ObjectData* this_ = nullptr,
689 HPHP::Class* class_ = nullptr,
690 VarEnv* varEnv = nullptr,
691 StringData* invName = nullptr,
692 InvokeFlags flags = InvokeNormal);
693 void invokeFunc(TypedValue* retval,
694 const CallCtx& ctx,
695 CVarRef args_,
696 VarEnv* varEnv = nullptr) {
697 invokeFunc(retval, ctx.func, args_, ctx.this_, ctx.cls, varEnv,
698 ctx.invName);
700 void invokeFuncCleanupHelper(TypedValue* retval,
701 ActRec* ar,
702 int numArgsPushed);
703 void invokeFuncFew(TypedValue* retval,
704 const HPHP::Func* f,
705 void* thisOrCls,
706 StringData* invName,
707 int argc,
708 const TypedValue* argv);
709 void invokeFuncFew(TypedValue* retval,
710 const HPHP::Func* f,
711 void* thisOrCls,
712 StringData* invName = nullptr) {
713 invokeFuncFew(retval, f, thisOrCls, invName, 0, nullptr);
715 void invokeFuncFew(TypedValue* retval,
716 const CallCtx& ctx,
717 int argc,
718 const TypedValue* argv) {
719 invokeFuncFew(retval, ctx.func,
720 ctx.this_ ? (void*)ctx.this_ :
721 ctx.cls ? (char*)ctx.cls + 1 : nullptr,
722 ctx.invName, argc, argv);
724 void invokeContFunc(const HPHP::Func* f,
725 ObjectData* this_,
726 Cell* param = nullptr);
727 // VM ClassInfo support
728 StringIMap<AtomicSmartPtr<MethodInfoVM> > m_functionInfos;
729 StringIMap<AtomicSmartPtr<ClassInfoVM> > m_classInfos;
730 StringIMap<AtomicSmartPtr<ClassInfoVM> > m_interfaceInfos;
731 StringIMap<AtomicSmartPtr<ClassInfoVM> > m_traitInfos;
732 Array getUserFunctionsInfo();
733 Array getConstantsInfo();
734 const ClassInfo::MethodInfo* findFunctionInfo(const String& name);
735 const ClassInfo* findClassInfo(const String& name);
736 const ClassInfo* findInterfaceInfo(const String& name);
737 const ClassInfo* findTraitInfo(const String& name);
738 const ClassInfo::ConstantInfo* findConstantInfo(const String& name);
740 // The op*() methods implement individual opcode handlers.
741 #define O(name, imm, pusph, pop, flags) \
742 void op##name();
743 OPCODES
744 #undef O
745 enum DispatchFlags {
746 LimitInstrs = 1 << 0,
747 BreakOnCtlFlow = 1 << 1,
748 Profile = 1 << 2
750 template <int dispatchFlags>
751 void dispatchImpl(int numInstrs);
752 void dispatch();
753 // dispatchN() runs numInstrs instructions, or to program termination,
754 // whichever comes first. If the program terminates during execution, m_pc is
755 // set to null.
756 void dispatchN(int numInstrs);
758 // dispatchBB() tries to run until a control-flow instruction has been run.
759 void dispatchBB();
761 private:
762 static Mutex s_threadIdxLock;
763 static hphp_hash_map<pid_t, int64_t> s_threadIdxMap;
765 public:
766 static int64_t s_threadIdxCounter;
767 Variant m_setprofileCallback;
768 bool m_executingSetprofileCallback;
770 std::vector<vixl::Simulator*> m_activeSims;
773 class ExecutionContext : public VMExecutionContext {};
775 #if DEBUG
776 #define g_vmContext (&dynamic_cast<HPHP::VMExecutionContext&>( \
777 *HPHP::g_context.getNoCheck()))
778 #else
779 #define g_vmContext (static_cast<HPHP::VMExecutionContext*>( \
780 static_cast<HPHP::BaseExecutionContext*>( \
781 HPHP::g_context.getNoCheck())))
782 #endif
784 ///////////////////////////////////////////////////////////////////////////////
786 class PersistentObjectStore {
787 public:
788 ~PersistentObjectStore();
790 int size() const;
792 void set(const char *type, const char *name, ResourceData *obj);
793 ResourceData *get(const char *type, const char *name);
794 void remove(const char *type, const char *name);
796 const ResourceMap &getMap(const char *type);
798 private:
799 ResourceMapMap m_objects;
801 void removeObject(ResourceData *data);
804 ///////////////////////////////////////////////////////////////////////////////
806 extern DECLARE_THREAD_LOCAL_NO_CHECK(ExecutionContext, g_context);
807 extern DECLARE_THREAD_LOCAL_NO_CHECK(PersistentObjectStore,
808 g_persistentObjects);
810 ///////////////////////////////////////////////////////////////////////////////
813 #endif // incl_HPHP_EXECUTION_CONTEXT_H_