Return by value from invokeFunc()
[hiphop-php.git] / hphp / runtime / base / execution-context.h
blob6e02c9e1b387ea7c6cd76efc9e7548a8d0e4818d
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2016 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 <list>
21 #include <set>
22 #include <string>
23 #include <unordered_map>
24 #include <utility>
25 #include <vector>
27 #include "hphp/util/lock.h"
28 #include "hphp/util/thread-local.h"
29 #include "hphp/util/tiny-vector.h"
30 #include "hphp/runtime/base/apc-handle.h"
31 #include "hphp/runtime/base/ini-setting.h"
32 #include "hphp/runtime/base/mixed-array.h"
33 #include "hphp/runtime/base/string-buffer.h"
34 #include "hphp/runtime/ext/stream/ext_stream.h"
35 #include "hphp/runtime/server/transport.h"
36 #include "hphp/runtime/server/virtual-host.h"
37 #include "hphp/runtime/vm/bytecode.h"
38 #include "hphp/runtime/vm/func.h"
39 #include "hphp/runtime/vm/minstr-state.h"
40 #include "hphp/runtime/vm/pc-filter.h"
42 namespace HPHP {
43 struct RequestEventHandler;
44 struct EventHook;
45 struct Resumable;
48 namespace HPHP {
50 ///////////////////////////////////////////////////////////////////////////////
52 struct VMState {
53 PC pc;
54 ActRec* fp;
55 ActRec* firstAR;
56 TypedValue* sp;
57 MInstrState mInstrState;
58 ActRec* jitCalledFrame;
60 template<class F> void scan(F& mark) const {
61 mInstrState.scan(mark);
62 mark(&jitCalledFrame, sizeof(jitCalledFrame));
66 enum class InclOpFlags {
67 Default = 0,
68 Fatal = 1,
69 Once = 2,
70 DocRoot = 8,
71 Relative = 16,
74 inline InclOpFlags operator|(const InclOpFlags& l, const InclOpFlags& r) {
75 return static_cast<InclOpFlags>(static_cast<int>(l) | static_cast<int>(r));
78 inline bool operator&(const InclOpFlags& l, const InclOpFlags& r) {
79 return static_cast<int>(l) & static_cast<int>(r);
82 enum class OBFlags {
83 None = 0,
84 Cleanable = 1,
85 Flushable = 2,
86 Removable = 4,
87 OutputDisabled = 8,
88 WriteToStdout = 16,
89 Default = 1 | 2 | 4
92 inline OBFlags operator|(const OBFlags& l, const OBFlags& r) {
93 return static_cast<OBFlags>(static_cast<int>(l) | static_cast<int>(r));
96 inline OBFlags & operator|=(OBFlags& l, const OBFlags& r) {
97 return l = l | r;
100 inline OBFlags operator&(const OBFlags& l, const OBFlags& r) {
101 return static_cast<OBFlags>(static_cast<int>(l) & static_cast<int>(r));
104 inline bool any(OBFlags f) { return f != OBFlags::None; }
105 inline bool operator!(OBFlags f) { return f == OBFlags::None; }
107 struct VMParserFrame {
108 std::string filename;
109 int lineNumber;
112 struct DebuggerSettings {
113 bool bypassCheck = false;
114 bool stackArgs = true;
115 int printLevel = -1;
118 struct ThrowAllErrorsSetter {
119 ThrowAllErrorsSetter();
120 ~ThrowAllErrorsSetter();
122 private:
123 bool m_throwAllErrors;
126 using InvokeArgs = folly::Range<const TypedValue*>;
128 ///////////////////////////////////////////////////////////////////////////////
130 struct ExecutionContext {
131 friend ThrowAllErrorsSetter;
133 enum ShutdownType {
134 ShutDown,
135 PostSend,
138 enum class ErrorThrowMode {
139 Never,
140 IfUnhandled,
141 Always,
144 enum class ErrorState {
145 NoError,
146 ErrorRaised,
147 ExecutingUserHandler,
148 ErrorRaisedByUserHandler,
151 public:
152 ExecutionContext();
153 ExecutionContext(const ExecutionContext&) = delete;
154 ExecutionContext& operator=(const ExecutionContext&) = delete;
155 ~ExecutionContext();
156 void sweep();
158 void* operator new(size_t s);
159 void* operator new(size_t s, void* p);
160 void operator delete(void* p);
162 // For RPCRequestHandler.
163 void backupSession();
164 void restoreSession();
167 * API for the debugger. Format of the vector is the same as
168 * IDebuggable::debuggerInfo, but we don't actually need to
169 * implement that interface since the execution context is not
170 * accessed by the debugger polymorphically.
172 void debuggerInfo(std::vector<std::pair<const char*,std::string>>&);
175 * System settings.
177 Transport* getTransport();
178 void setTransport(Transport*);
179 std::string getRequestUrl(size_t szLimit = std::string::npos);
180 String getMimeType() const;
181 void setContentType(const String& mimetype, const String& charset);
182 String getCwd() const;
183 void setCwd(const String&);
186 * Write to output.
188 void write(const String&);
189 void write(const char* s, int len);
190 void write(const char*);
192 void writeStdout(const char* s, int len);
193 size_t getStdoutBytesWritten() const;
196 * Write to the transport, or to stdout if there is no transport.
198 void writeTransport(const char* s, int len);
200 using PFUNC_STDOUT = void (*)(const char* s, int len, void* data);
201 void setStdout(PFUNC_STDOUT func, void* data);
204 * Output buffering.
206 void obStart(const Variant& handler = uninit_null(),
207 int chunk_size = 0,
208 OBFlags flags = OBFlags::Default);
209 String obCopyContents();
210 String obDetachContents();
211 int obGetContentLength();
212 void obClean(int handler_flag);
213 bool obFlush(bool force = false);
214 void obFlushAll();
215 bool obEnd();
216 void obEndAll();
217 int obGetLevel();
218 String obGetBufferName();
219 Array obGetStatus(bool full);
220 void obSetImplicitFlush(bool on);
221 Array obGetHandlers();
222 void obProtect(bool on); // making sure obEnd() never passes current level
223 void flush();
224 StringBuffer* swapOutputBuffer(StringBuffer*);
225 String getRawPostData() const;
226 void setRawPostData(const String& pd);
229 * Request sequences and program execution hooks.
231 std::size_t registerRequestEventHandler(RequestEventHandler* handler);
232 void unregisterRequestEventHandler(RequestEventHandler* handler,
233 std::size_t index);
234 void registerShutdownFunction(const Variant& function, Array arguments,
235 ShutdownType type);
236 bool removeShutdownFunction(const Variant& function, ShutdownType type);
237 bool hasShutdownFunctions(ShutdownType type);
238 void onRequestShutdown();
239 void onShutdownPreSend();
240 void onShutdownPostSend();
243 * Error handling
245 Variant pushUserErrorHandler(const Variant& function, int error_types);
246 Variant pushUserExceptionHandler(const Variant& function);
247 void popUserErrorHandler();
248 void popUserExceptionHandler();
249 bool errorNeedsHandling(int errnum,
250 bool callUserHandler,
251 ErrorThrowMode mode);
252 bool errorNeedsLogging(int errnum);
253 void handleError(const std::string &msg,
254 int errnum,
255 bool callUserHandler,
256 ErrorThrowMode mode,
257 const std::string &prefix,
258 bool skipFrame = false);
259 bool callUserErrorHandler(const Exception &e, int errnum,
260 bool swallowExceptions);
261 void recordLastError(const Exception &e, int errnum = 0);
262 void clearLastError();
263 bool onFatalError(const Exception &e); // returns handled
264 bool onUnhandledException(Object e);
265 ErrorState getErrorState() const;
266 void setErrorState(ErrorState);
267 String getLastError() const;
268 int getLastErrorNumber() const;
269 String getErrorPage() const;
270 void setErrorPage(const String&);
271 String getLastErrorPath() const;
272 int getLastErrorLine() const;
275 * Misc. settings
277 String getenv(const String& name) const;
278 void setenv(const String& name, const String& value);
279 void unsetenv(const String& name);
280 Array getEnvs() const;
282 String getTimeZone() const;
283 void setTimeZone(const String&);
285 bool getThrowAllErrors() const;
287 Variant getExitCallback();
288 void setExitCallback(Variant);
290 void setStreamContext(const req::ptr<StreamContext>&);
291 const req::ptr<StreamContext>& getStreamContext();
293 int getPageletTasksStarted() const;
294 void incrPageletTasksStarted();
296 const VirtualHost* getVirtualHost() const;
297 void setVirtualHost(const VirtualHost*);
299 const String& getSandboxId() const;
300 void setSandboxId(const String&);
302 bool hasRequestEventHandlers() const;
304 private:
305 struct OutputBuffer {
306 explicit OutputBuffer(Variant&& h, int chunk_sz, OBFlags flgs)
307 : oss(8192), handler(std::move(h)), chunk_size(chunk_sz), flags(flgs)
309 StringBuffer oss;
310 Variant handler;
311 int chunk_size;
312 OBFlags flags;
313 template<class F> void scan(F& mark) {
314 mark(oss);
315 mark(handler);
316 mark(chunk_size);
320 private:
321 // helper functions
322 void resetCurrentBuffer();
323 void executeFunctions(ShutdownType type);
324 void setThrowAllErrors(bool);
326 public:
327 void requestInit();
328 void requestExit();
329 void enqueueAPCHandle(APCHandle* handle, size_t size);
331 void manageAPCHandle();
332 void cleanup();
334 public:
335 ObjectData* createObject(const Class* cls,
336 const Variant& params,
337 bool init);
338 ObjectData* createObject(StringData* clsName,
339 const Variant& params,
340 bool init = true);
341 ObjectData* initObject(const Class* cls,
342 const Variant& params,
343 ObjectData* o);
344 ObjectData* initObject(StringData* clsName,
345 const Variant& params,
346 ObjectData* o);
347 ObjectData* createObjectOnly(StringData* clsName);
350 * Look up a class constant.
352 * The returned Cell is guaranteed not to hold a reference counted
353 * type. Raises an error if the class has no constant with that
354 * name, or if the class is not defined.
356 Cell lookupClsCns(const NamedEntity* ne,
357 const StringData* cls,
358 const StringData* cns);
359 Cell lookupClsCns(const StringData* cls,
360 const StringData* cns);
362 // Get the next outermost VM frame, even across re-entry
363 ActRec* getOuterVMFrame(const ActRec* ar);
365 ActRec* getStackFrame();
366 ObjectData* getThis();
367 Class* getContextClass();
368 Class* getParentContextClass();
369 StringData* getContainingFileName();
370 int getLine();
371 Array getCallerInfo();
372 bool evalUnit(Unit* unit, PC& pc, int funcType);
373 TypedValue invokeUnit(const Unit* unit);
374 Unit* compileEvalString(StringData* code,
375 const char* evalFilename = nullptr);
376 StrNR createFunction(const String& args, const String& code);
378 // Compiles the passed string and evaluates it in the given frame. Returns
379 // false on failure.
380 bool evalPHPDebugger(TypedValue* retval, StringData* code, int frame);
382 // Evaluates the a unit compiled via compile_string in the given frame.
383 // Returns false on failure.
384 bool evalPHPDebugger(TypedValue* retval, Unit* unit, int frame);
386 void enterDebuggerDummyEnv();
387 void exitDebuggerDummyEnv();
388 void destructObjects();
390 bool isNested() { return m_nesting != 0; }
391 void pushVMState(Cell* savedSP);
392 void popVMState();
395 * Given a pointer to a VM frame, returns the previous VM frame in the call
396 * stack. This function will also pass back by reference the previous PC (if
397 * prevPc is non-null) and the previous SP (if prevSp is non-null).
399 * If there is no previous VM frame, this function returns NULL and does not
400 * set prevPc and prevSp.
402 * Inspecting live VM frames other than the current one can be dangerous, so
403 * use this function with care. If all you need is the Func that called a
404 * particular frame, use getPrevFunc() instead.
406 ActRec* getPrevVMState(const ActRec* fp,
407 Offset* prevPc = nullptr,
408 TypedValue** prevSp = nullptr,
409 bool* fromVMEntry = nullptr);
412 * Returns the caller of the given frame.
414 const Func* getPrevFunc(const ActRec*);
416 ActRec* getFrameAtDepth(int frame = 0);
417 VarEnv* getOrCreateVarEnv(int frame = 0);
418 VarEnv* hasVarEnv(int frame = 0);
419 void setVar(StringData* name, const TypedValue* v);
420 void bindVar(StringData* name, TypedValue* v);
421 Array getLocalDefinedVariables(int frame);
422 const Variant& getEvaledArg(const StringData* val,
423 const String& namespacedName);
425 private:
426 template <bool forwarding>
427 void pushClsMethodImpl(Class* cls, StringData* name,
428 ObjectData* obj, int numArgs);
429 public:
430 void syncGdbState();
432 enum InvokeFlags {
433 InvokeNormal,
434 InvokeCuf,
435 InvokePseudoMain
438 TypedValue invokeFunc(const Func* f,
439 const Variant& args_ = init_null_variant,
440 ObjectData* this_ = nullptr,
441 Class* class_ = nullptr,
442 VarEnv* varEnv = nullptr,
443 StringData* invName = nullptr,
444 InvokeFlags flags = InvokeNormal,
445 bool useWeakTypes = false);
447 TypedValue invokeFunc(const CallCtx& ctx,
448 const Variant& args_,
449 VarEnv* varEnv = nullptr);
451 TypedValue invokeFuncFew(const Func* f,
452 void* thisOrCls,
453 StringData* invName,
454 int argc,
455 const TypedValue* argv,
456 bool useWeakTypes = false);
458 TypedValue invokeFuncFew(const Func* f,
459 void* thisOrCls,
460 StringData* invName = nullptr);
462 TypedValue invokeFuncFew(const CallCtx& ctx,
463 int argc,
464 const TypedValue* argv);
466 TypedValue invokeMethod(
467 ObjectData* obj,
468 const Func* meth,
469 InvokeArgs args = InvokeArgs()
472 Variant invokeMethodV(
473 ObjectData* obj,
474 const Func* meth,
475 InvokeArgs args = InvokeArgs()
478 void resumeAsyncFunc(Resumable* resumable, ObjectData* freeObj,
479 Cell awaitResult);
480 void resumeAsyncFuncThrow(Resumable* resumable, ObjectData* freeObj,
481 ObjectData* exception);
483 bool setHeaderCallback(const Variant& callback);
485 private:
486 template<class FStackCheck, class FInitArgs, class FEnterVM>
487 TypedValue invokeFuncImpl(const Func* f,
488 ObjectData* thiz, Class* cls, uint32_t argc,
489 StringData* invName, bool useWeakTypes,
490 FStackCheck doStackCheck,
491 FInitArgs doInitArgs,
492 FEnterVM doEnterVM);
494 public:
495 template<class F> void scan(F& mark) {
496 //mark(m_transport); Transport &subclasses must not contain heap ptrs.
497 mark(m_cwd);
498 //mark(m_sb); // points into m_buffers
499 //mark(m_out); // points into m_buffers
500 mark(m_remember_chunk);
501 for (auto& b : m_buffers) b.scan(mark);
502 mark(m_insideOBHandler);
503 mark(m_implicitFlush);
504 mark(m_protectedLevel);
505 //mark(m_stdout);
506 //mark(m_stdoutData);
507 mark(m_stdoutBytesWritten);
508 mark(m_rawPostData);
509 //mark(m_requestEventHandlers); type_scanned via ThreadLocal<T>
510 mark(m_shutdowns);
511 mark(m_userErrorHandlers);
512 mark(m_userExceptionHandlers);
513 //mark(m_errorState);
514 mark(m_lastError);
515 mark(m_errorPage);
516 mark(m_envs);
517 mark(m_timezone);
518 mark(m_throwAllErrors);
519 //mark(m_streamContext);
520 mark(m_shutdownsBackup);
521 mark(m_userErrorHandlersBackup);
522 mark(m_userExceptionHandlersBackup);
523 mark(m_exitCallback);
524 mark(m_sandboxId);
525 //mark(m_vhost); // VirtualHost* not allocated in php request heap
526 //mark(debuggerSettings);
527 mark.implicit(m_liveBCObjs); // exact ptrs, but not refcounted.
528 mark(m_apcMemSize);
529 //mark(m_apcHandles);
530 //mark(dynPropTable); // don't root objects with dyn props
531 mark(m_globalVarEnv);
532 for (auto& e : m_evaledFiles) { mark(e.first); mark(e.second.unit); }
533 mark(m_evaledFilesOrder);
534 mark(m_createdFuncs);
535 //for (auto& f : m_faults) mark(f);
536 mark(m_lambdaCounter);
537 for (auto& vmstate : m_nestedVMs) vmstate.scan(mark);
538 mark(m_nesting);
539 mark(m_dbgNoBreak);
540 mark(m_evaledArgs);
541 mark(m_lastErrorPath);
542 mark(m_lastErrorLine);
543 mark(m_setprofileCallback);
544 mark(m_memThresholdCallback);
545 mark(m_executingSetprofileCallback);
546 mark(m_headerCallback);
549 ///////////////////////////////////////////////////////////////////////////////
550 // only fields past here, please.
551 private:
552 // system settings
553 Transport* m_transport;
554 String m_cwd;
556 // output buffering
557 StringBuffer* m_sb = nullptr; // current buffer being populated with data
558 OutputBuffer* m_out = nullptr; // current OutputBuffer
559 int m_remember_chunk = 0; // in case the output buffer is swapped
560 req::list<OutputBuffer> m_buffers; // a stack of output buffers
561 bool m_insideOBHandler{false};
562 bool m_implicitFlush;
563 int m_protectedLevel;
564 PFUNC_STDOUT m_stdout;
565 void* m_stdoutData;
566 size_t m_stdoutBytesWritten;
567 String m_rawPostData;
569 // request handlers
570 req::vector<RequestEventHandler*> m_requestEventHandlers;
571 Array m_shutdowns;
573 // error handling
574 req::vector<std::pair<Variant,int>> m_userErrorHandlers;
575 req::vector<Variant> m_userExceptionHandlers;
576 ErrorState m_errorState;
577 String m_lastError;
578 int m_lastErrorNum;
579 String m_errorPage;
581 // misc settings
582 Array m_envs;
583 String m_timezone;
584 bool m_throwAllErrors;
585 req::ptr<StreamContext> m_streamContext;
587 // session backup/restore for RPCRequestHandler
588 Array m_shutdownsBackup;
589 req::vector<std::pair<Variant,int>> m_userErrorHandlersBackup;
590 req::vector<Variant> m_userExceptionHandlersBackup;
591 Variant m_exitCallback;
592 String m_sandboxId; // cache the sandbox id for the request
593 int m_pageletTasksStarted;
594 const VirtualHost* m_vhost;
595 public:
596 DebuggerSettings debuggerSettings;
597 req::set<ObjectData*> m_liveBCObjs; // objects with destructors
598 private:
599 size_t m_apcMemSize{0};
600 std::vector<APCHandle*> m_apcHandles; // gets moved to treadmill
601 public:
602 // Although the error handlers may want to access dynamic properties,
603 // we cannot *call* the error handlers (or their destructors) while
604 // destroying the context, so C++ order of destruction is not an issue.
605 req::hash_map<const ObjectData*,ArrayNoDtor> dynPropTable;
606 VarEnv* m_globalVarEnv;
607 struct FileInfo {
608 Unit* unit;
609 time_t ts_sec; // timestamp seconds
610 unsigned long ts_nsec; // timestamp nanoseconds (or 0 if ns not supported)
612 req::hash_map<const StringData*, FileInfo, string_data_hash, string_data_same>
613 m_evaledFiles;
614 req::vector<const StringData*> m_evaledFilesOrder;
615 req::vector<Unit*> m_createdFuncs;
616 req::vector<Fault> m_faults;
617 int m_lambdaCounter;
618 req::TinyVector<VMState, 32> m_nestedVMs;
619 int m_nesting;
620 bool m_dbgNoBreak;
621 bool m_unwindingCppException;
622 private:
623 Array m_evaledArgs;
624 String m_lastErrorPath;
625 int m_lastErrorLine;
626 public:
627 Variant m_setprofileCallback;
628 Variant m_memThresholdCallback;
629 uint64_t m_setprofileFlags;
630 bool m_executingSetprofileCallback;
631 public:
632 Cell m_headerCallback;
633 bool m_headerCallbackDone{false}; // used to prevent infinite loops
635 TYPE_SCAN_CONSERVATIVE_FIELD(m_stdoutData);
636 TYPE_SCAN_IGNORE_FIELD(dynPropTable);
639 ///////////////////////////////////////////////////////////////////////////////
641 // MSVC doesn't instantiate this, causing an undefined symbol at link time
642 // if the template<> is present, but other compilers require it.
643 #ifndef _MSC_VER
644 template<>
645 #endif
646 void ThreadLocalNoCheck<ExecutionContext>::destroy();
648 extern DECLARE_THREAD_LOCAL_NO_CHECK(ExecutionContext, g_context);
650 ///////////////////////////////////////////////////////////////////////////////
653 #include "hphp/runtime/base/execution-context-inl.h"
655 #endif