Heap Tracer
[hiphop-php.git] / hphp / runtime / base / execution-context.h
blob293504a398cc3cfaa4eac82fd013919332603b5d
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 <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/class-info.h"
32 #include "hphp/runtime/base/ini-setting.h"
33 #include "hphp/runtime/base/mixed-array.h"
34 #include "hphp/runtime/base/string-buffer.h"
35 #include "hphp/runtime/ext/stream/ext_stream.h"
36 #include "hphp/runtime/server/transport.h"
37 #include "hphp/runtime/server/virtual-host.h"
38 #include "hphp/runtime/vm/bytecode.h"
39 #include "hphp/runtime/vm/func.h"
40 #include "hphp/runtime/vm/minstr-state.h"
41 #include "hphp/runtime/vm/pc-filter.h"
43 namespace vixl { class Simulator; }
45 namespace HPHP {
46 struct RequestEventHandler;
47 struct EventHook;
48 struct Resumable;
49 struct PhpFile;
50 namespace jit { struct Translator; }
53 namespace HPHP {
55 ///////////////////////////////////////////////////////////////////////////////
57 struct VMState {
58 PC pc;
59 ActRec* fp;
60 ActRec* firstAR;
61 TypedValue* sp;
62 MInstrState mInstrState;
63 ActRec* jitCalledFrame;
66 enum class CallType {
67 ClsMethod,
68 ObjMethod,
69 CtorMethod,
71 enum class LookupResult {
72 MethodFoundWithThis,
73 MethodFoundNoThis,
74 MagicCallFound,
75 MagicCallStaticFound,
76 MethodNotFound,
79 enum class InclOpFlags {
80 Default = 0,
81 Fatal = 1,
82 Once = 2,
83 DocRoot = 8,
84 Relative = 16,
87 inline InclOpFlags operator|(const InclOpFlags& l, const InclOpFlags& r) {
88 return static_cast<InclOpFlags>(static_cast<int>(l) | static_cast<int>(r));
91 inline bool operator&(const InclOpFlags& l, const InclOpFlags& r) {
92 return static_cast<int>(l) & static_cast<int>(r);
95 struct VMParserFrame {
96 std::string filename;
97 int lineNumber;
100 struct DebuggerSettings {
101 bool bypassCheck = false;
102 bool stackArgs = true;
103 int printLevel = -1;
106 using InvokeArgs = folly::Range<const TypedValue*>;
108 ///////////////////////////////////////////////////////////////////////////////
110 struct ExecutionContext {
111 enum ShutdownType {
112 ShutDown,
113 PostSend,
116 enum class ErrorThrowMode {
117 Never,
118 IfUnhandled,
119 Always,
122 enum class ErrorState {
123 NoError,
124 ErrorRaised,
125 ExecutingUserHandler,
126 ErrorRaisedByUserHandler,
129 public:
130 ExecutionContext();
131 ExecutionContext(const ExecutionContext&) = delete;
132 ExecutionContext& operator=(const ExecutionContext&) = delete;
133 ~ExecutionContext();
134 void sweep();
136 void* operator new(size_t s);
137 void* operator new(size_t s, void* p);
138 void operator delete(void* p);
140 // For RPCRequestHandler.
141 void backupSession();
142 void restoreSession();
145 * API for the debugger. Format of the vector is the same as
146 * IDebuggable::debuggerInfo, but we don't actually need to
147 * implement that interface since the execution context is not
148 * accessed by the debugger polymorphically.
150 void debuggerInfo(std::vector<std::pair<const char*,std::string>>&);
153 * System settings.
155 Transport* getTransport();
156 void setTransport(Transport*);
157 std::string getRequestUrl(size_t szLimit = std::string::npos);
158 String getMimeType() const;
159 void setContentType(const String& mimetype, const String& charset);
160 String getCwd() const;
161 void setCwd(const String&);
164 * Write to output.
166 void write(const String&);
167 void write(const char* s, int len);
168 void write(const char*);
170 void writeStdout(const char* s, int len);
171 size_t getStdoutBytesWritten() const;
173 using PFUNC_STDOUT = void (*)(const char* s, int len, void* data);
174 void setStdout(PFUNC_STDOUT func, void* data);
177 * Output buffering.
179 void obStart(const Variant& handler = uninit_null(), int chunk_size = 0);
180 String obCopyContents();
181 String obDetachContents();
182 int obGetContentLength();
183 void obClean(int handler_flag);
184 bool obFlush();
185 void obFlushAll();
186 bool obEnd();
187 void obEndAll();
188 int obGetLevel();
189 Array obGetStatus(bool full);
190 void obSetImplicitFlush(bool on);
191 Array obGetHandlers();
192 void obProtect(bool on); // making sure obEnd() never passes current level
193 void flush();
194 StringBuffer* swapOutputBuffer(StringBuffer*);
195 String getRawPostData() const;
196 void setRawPostData(const String& pd);
199 * Request sequences and program execution hooks.
201 void registerRequestEventHandler(RequestEventHandler* handler);
202 void registerShutdownFunction(const Variant& function, Array arguments,
203 ShutdownType type);
204 bool removeShutdownFunction(const Variant& function, ShutdownType type);
205 bool hasShutdownFunctions(ShutdownType type);
206 void onRequestShutdown();
207 void onShutdownPreSend();
208 void onShutdownPostSend();
211 * Error handling
213 Variant pushUserErrorHandler(const Variant& function, int error_types);
214 Variant pushUserExceptionHandler(const Variant& function);
215 void popUserErrorHandler();
216 void popUserExceptionHandler();
217 bool errorNeedsHandling(int errnum,
218 bool callUserHandler,
219 ErrorThrowMode mode);
220 bool errorNeedsLogging(int errnum);
221 void handleError(const std::string &msg,
222 int errnum,
223 bool callUserHandler,
224 ErrorThrowMode mode,
225 const std::string &prefix,
226 bool skipFrame = false);
227 bool callUserErrorHandler(const Exception &e, int errnum,
228 bool swallowExceptions);
229 void recordLastError(const Exception &e, int errnum = 0);
230 void clearLastError();
231 bool onFatalError(const Exception &e); // returns handled
232 bool onUnhandledException(Object e);
233 ErrorState getErrorState() const;
234 void setErrorState(ErrorState);
235 String getLastError() const;
236 int getLastErrorNumber() const;
237 String getErrorPage() const;
238 void setErrorPage(const String&);
239 String getLastErrorPath() const;
240 int getLastErrorLine() const;
243 * Misc. settings
245 String getenv(const String& name) const;
246 void setenv(const String& name, const String& value);
247 void unsetenv(const String& name);
248 Array getEnvs() const;
250 String getTimeZone() const;
251 void setTimeZone(const String&);
253 String getDefaultTimeZone() const;
254 void setDefaultTimeZone(const String&);
256 bool getThrowAllErrors() const;
257 void setThrowAllErrors(bool);
259 Variant getExitCallback();
260 void setExitCallback(Variant);
262 void setStreamContext(const SmartPtr<StreamContext>&);
263 const SmartPtr<StreamContext>& getStreamContext();
265 int getPageletTasksStarted() const;
266 void incrPageletTasksStarted();
268 const VirtualHost* getVirtualHost() const;
269 void setVirtualHost(const VirtualHost*);
271 const String& getSandboxId() const;
272 void setSandboxId(const String&);
274 bool hasRequestEventHandlers() const;
276 private:
277 struct OutputBuffer {
278 explicit OutputBuffer(Variant&& h, int chunk_sz)
279 : oss(8192), handler(std::move(h)), chunk_size(chunk_sz)
281 StringBuffer oss;
282 Variant handler;
283 int chunk_size;
284 template<class F> void scan(F& mark) {
285 mark(oss);
286 mark(handler);
287 mark(chunk_size);
291 private:
292 // helper functions
293 void resetCurrentBuffer();
294 void executeFunctions(ShutdownType type);
296 public:
297 void requestInit();
298 void requestExit();
299 void enqueueAPCHandle(APCHandle* handle, size_t size);
301 void manageAPCHandle();
302 void cleanup();
304 public:
305 const Func* lookupMethodCtx(const Class* cls,
306 const StringData* methodName,
307 const Class* pctx,
308 CallType lookupType,
309 bool raise = false);
310 LookupResult lookupObjMethod(const Func*& f,
311 const Class* cls,
312 const StringData* methodName,
313 const Class* ctx,
314 bool raise = false);
315 LookupResult lookupClsMethod(const Func*& f,
316 const Class* cls,
317 const StringData* methodName,
318 ObjectData* this_,
319 const Class* ctx,
320 bool raise = false);
321 LookupResult lookupCtorMethod(const Func*& f,
322 const Class* cls,
323 bool raise = false);
324 ObjectData* createObject(const Class* cls,
325 const Variant& params,
326 bool init);
327 ObjectData* createObject(StringData* clsName,
328 const Variant& params,
329 bool init = true);
330 ObjectData* initObject(const Class* cls,
331 const Variant& params,
332 ObjectData* o);
333 ObjectData* initObject(StringData* clsName,
334 const Variant& params,
335 ObjectData* o);
336 ObjectData* createObjectOnly(StringData* clsName);
339 * Look up a class constant.
341 * The returned Cell is guaranteed not to hold a reference counted
342 * type. Raises an error if the class has no constant with that
343 * name, or if the class is not defined.
345 Cell lookupClsCns(const NamedEntity* ne,
346 const StringData* cls,
347 const StringData* cns);
348 Cell lookupClsCns(const StringData* cls,
349 const StringData* cns);
351 // Get the next outermost VM frame, even across re-entry
352 ActRec* getOuterVMFrame(const ActRec* ar);
354 ActRec* getStackFrame();
355 ObjectData* getThis();
356 Class* getContextClass();
357 Class* getParentContextClass();
358 StringData* getContainingFileName();
359 int getLine();
360 Array getCallerInfo();
361 bool evalUnit(Unit* unit, PC& pc, int funcType);
362 void invokeUnit(TypedValue* retval, const Unit* unit);
363 Unit* compileEvalString(StringData* code,
364 const char* evalFilename = nullptr);
365 StrNR createFunction(const String& args, const String& code);
367 // Compiles the passed string and evaluates it in the given frame. Returns
368 // false on failure.
369 bool evalPHPDebugger(TypedValue* retval, StringData* code, int frame);
371 // Evaluates the a unit compiled via compile_string in the given frame.
372 // Returns false on failure.
373 bool evalPHPDebugger(TypedValue* retval, Unit* unit, int frame);
375 void enterDebuggerDummyEnv();
376 void exitDebuggerDummyEnv();
377 void destructObjects();
379 bool isNested() { return m_nesting != 0; }
380 void pushVMState(Cell* savedSP);
381 void popVMState();
384 * Given a pointer to a VM frame, returns the previous VM frame in the call
385 * stack. This function will also pass back by reference the previous PC (if
386 * prevPc is non-null) and the previous SP (if prevSp is non-null).
388 * If there is no previous VM frame, this function returns NULL and does not
389 * set prevPc and prevSp.
391 * Inspecting live VM frames other than the current one can be dangerous, so
392 * use this function with care. If all you need is the Func that called a
393 * particular frame, use getPrevFunc() instead.
395 ActRec* getPrevVMState(const ActRec* fp,
396 Offset* prevPc = nullptr,
397 TypedValue** prevSp = nullptr,
398 bool* fromVMEntry = nullptr);
401 * Returns the caller of the given frame.
403 const Func* getPrevFunc(const ActRec*);
405 VarEnv* getVarEnv(int frame = 0);
406 void setVar(StringData* name, const TypedValue* v);
407 void bindVar(StringData* name, TypedValue* v);
408 Array getLocalDefinedVariables(int frame);
409 const Variant& getEvaledArg(const StringData* val,
410 const String& namespacedName);
412 private:
413 template <bool forwarding>
414 void pushClsMethodImpl(Class* cls, StringData* name,
415 ObjectData* obj, int numArgs);
416 public:
417 void syncGdbState();
419 enum InvokeFlags {
420 InvokeNormal,
421 InvokeCuf,
422 InvokePseudoMain
425 void invokeFunc(TypedValue* retval,
426 const Func* f,
427 const Variant& args_ = init_null_variant,
428 ObjectData* this_ = nullptr,
429 Class* class_ = nullptr,
430 VarEnv* varEnv = nullptr,
431 StringData* invName = nullptr,
432 InvokeFlags flags = InvokeNormal);
434 void invokeFunc(TypedValue* retval,
435 const CallCtx& ctx,
436 const Variant& args_,
437 VarEnv* varEnv = nullptr);
439 void invokeFuncFew(TypedValue* retval,
440 const Func* f,
441 void* thisOrCls,
442 StringData* invName,
443 int argc,
444 const TypedValue* argv);
446 void invokeFuncFew(TypedValue* retval,
447 const Func* f,
448 void* thisOrCls,
449 StringData* invName = nullptr);
451 void invokeFuncFew(TypedValue* retval,
452 const CallCtx& ctx,
453 int argc,
454 const TypedValue* argv);
456 TypedValue invokeMethod(
457 ObjectData* obj,
458 const Func* meth,
459 InvokeArgs args = InvokeArgs()
462 Variant invokeMethodV(
463 ObjectData* obj,
464 const Func* meth,
465 InvokeArgs args = InvokeArgs()
468 void resumeAsyncFunc(Resumable* resumable, ObjectData* freeObj,
469 Cell awaitResult);
470 void resumeAsyncFuncThrow(Resumable* resumable, ObjectData* freeObj,
471 ObjectData* exception);
473 template<typename T>
474 using SmartStringIMap = smart::hash_map<
475 String,
477 hphp_string_hash,
478 hphp_string_isame
481 public:
482 template<class F> void scan(F& mark) {
483 //mark(m_transport);
484 mark(m_cwd);
485 //mark(m_sb); // points into m_buffers
486 //mark(m_out); // points into m_buffers
487 mark(m_remember_chunk);
488 for (auto& b : m_buffers) b.scan(mark);
489 mark(m_insideOBHandler);
490 mark(m_implicitFlush);
491 mark(m_protectedLevel);
492 //mark(m_stdout);
493 //mark(m_stdoutData);
494 mark(m_stdoutBytesWritten);
495 mark(m_rawPostData);
496 //mark(m_requestEventHandlers);TODO #6512343
497 mark(m_shutdowns);
498 mark(m_userErrorHandlers);
499 mark(m_userExceptionHandlers);
500 //mark(m_errorState);
501 mark(m_lastError);
502 mark(m_errorPage);
503 mark(m_envs);
504 mark(m_timezone);
505 mark(m_timezoneDefault);
506 mark(m_throwAllErrors);
507 //mark(m_streamContext);
508 mark(m_shutdownsBackup);
509 mark(m_userErrorHandlersBackup);
510 mark(m_userExceptionHandlersBackup);
511 mark(m_exitCallback);
512 mark(m_sandboxId);
513 //mark(m_vhost); // VirtualHost* not allocated in php request heap
514 //mark(debuggerSettings);
515 mark(m_liveBCObjs);
516 mark(m_apcMemSize);
517 //mark(m_apcHandles);
518 mark(dynPropTable);
519 mark(m_globalVarEnv);
520 mark(m_evaledFiles);
521 mark(m_evaledFilesOrder);
522 mark(m_createdFuncs);
523 //for (auto& f : m_faults) mark(f);
524 mark(m_lambdaCounter);
525 //mark(m_nestedVMs);
526 mark(m_nesting);
527 mark(m_dbgNoBreak);
528 mark(m_evaledArgs);
529 mark(m_lastErrorPath);
530 mark(m_lastErrorLine);
531 mark(m_setprofileCallback);
532 mark(m_executingSetprofileCallback);
533 //mark(m_activeSims);
536 ///////////////////////////////////////////////////////////////////////////////
537 // only fields past here, please.
538 private:
539 // system settings
540 Transport* m_transport;
541 String m_cwd;
543 // output buffering
544 StringBuffer* m_sb = nullptr; // current buffer being populated with data
545 OutputBuffer* m_out = nullptr; // current OutputBuffer
546 int m_remember_chunk = 0; // in case the output buffer is swapped
547 smart::list<OutputBuffer> m_buffers; // a stack of output buffers
548 bool m_insideOBHandler{false};
549 bool m_implicitFlush;
550 int m_protectedLevel;
551 PFUNC_STDOUT m_stdout;
552 void* m_stdoutData;
553 size_t m_stdoutBytesWritten;
554 String m_rawPostData;
556 // request handlers
557 smart::vector<RequestEventHandler*> m_requestEventHandlers;
558 Array m_shutdowns;
560 // error handling
561 smart::vector<std::pair<Variant,int>> m_userErrorHandlers;
562 smart::vector<Variant> m_userExceptionHandlers;
563 ErrorState m_errorState;
564 String m_lastError;
565 int m_lastErrorNum;
566 String m_errorPage;
568 // misc settings
569 Array m_envs;
570 String m_timezone;
571 String m_timezoneDefault;
572 bool m_throwAllErrors;
573 SmartPtr<StreamContext> m_streamContext;
575 // session backup/restore for RPCRequestHandler
576 Array m_shutdownsBackup;
577 smart::vector<std::pair<Variant,int>> m_userErrorHandlersBackup;
578 smart::vector<Variant> m_userExceptionHandlersBackup;
579 Variant m_exitCallback;
580 String m_sandboxId; // cache the sandbox id for the request
581 int m_pageletTasksStarted;
582 const VirtualHost* m_vhost;
583 public:
584 DebuggerSettings debuggerSettings;
585 smart::set<ObjectData*> m_liveBCObjs;
586 private:
587 size_t m_apcMemSize{0};
588 std::vector<APCHandle*> m_apcHandles; // gets moved to treadmill
589 public:
590 // Although the error handlers may want to access dynamic properties,
591 // we cannot *call* the error handlers (or their destructors) while
592 // destroying the context, so C++ order of destruction is not an issue.
593 smart::hash_map<const ObjectData*,ArrayNoDtor> dynPropTable;
594 VarEnv* m_globalVarEnv;
595 smart::hash_map<const StringData*,Unit*,string_data_hash,string_data_same>
596 m_evaledFiles;
597 smart::vector<const StringData*> m_evaledFilesOrder;
598 smart::vector<Unit*> m_createdFuncs;
599 smart::vector<Fault> m_faults;
600 int m_lambdaCounter;
601 TinyVector<VMState, 32> m_nestedVMs;
602 int m_nesting;
603 bool m_dbgNoBreak;
604 private:
605 Array m_evaledArgs;
606 String m_lastErrorPath;
607 int m_lastErrorLine;
608 public:
609 Variant m_setprofileCallback;
610 bool m_executingSetprofileCallback;
611 smart::vector<vixl::Simulator*> m_activeSims;
614 ///////////////////////////////////////////////////////////////////////////////
616 template<> void ThreadLocalNoCheck<ExecutionContext>::destroy();
618 extern DECLARE_THREAD_LOCAL_NO_CHECK(ExecutionContext, g_context);
620 ///////////////////////////////////////////////////////////////////////////////
623 #include "hphp/runtime/base/execution-context-inl.h"
625 #endif