2 +----------------------------------------------------------------------+
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_
23 #include <unordered_map>
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
; }
46 struct RequestEventHandler
;
50 namespace jit
{ struct Translator
; }
55 ///////////////////////////////////////////////////////////////////////////////
62 MInstrState mInstrState
;
63 ActRec
* jitCalledFrame
;
71 enum class LookupResult
{
79 enum class InclOpFlags
{
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
{
100 struct DebuggerSettings
{
101 bool bypassCheck
= false;
102 bool stackArgs
= true;
106 using InvokeArgs
= folly::Range
<const TypedValue
*>;
108 ///////////////////////////////////////////////////////////////////////////////
110 struct ExecutionContext
{
116 enum class ErrorThrowMode
{
122 enum class ErrorState
{
125 ExecutingUserHandler
,
126 ErrorRaisedByUserHandler
,
131 ExecutionContext(const ExecutionContext
&) = delete;
132 ExecutionContext
& operator=(const ExecutionContext
&) = delete;
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
>>&);
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
&);
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
);
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
);
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
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
,
204 bool removeShutdownFunction(const Variant
& function
, ShutdownType type
);
205 bool hasShutdownFunctions(ShutdownType type
);
206 void onRequestShutdown();
207 void onShutdownPreSend();
208 void onShutdownPostSend();
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
,
223 bool callUserHandler
,
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;
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;
277 struct OutputBuffer
{
278 explicit OutputBuffer(Variant
&& h
, int chunk_sz
)
279 : oss(8192), handler(std::move(h
)), chunk_size(chunk_sz
)
284 template<class F
> void scan(F
& mark
) {
293 void resetCurrentBuffer();
294 void executeFunctions(ShutdownType type
);
299 void enqueueAPCHandle(APCHandle
* handle
, size_t size
);
301 void manageAPCHandle();
305 const Func
* lookupMethodCtx(const Class
* cls
,
306 const StringData
* methodName
,
310 LookupResult
lookupObjMethod(const Func
*& f
,
312 const StringData
* methodName
,
315 LookupResult
lookupClsMethod(const Func
*& f
,
317 const StringData
* methodName
,
321 LookupResult
lookupCtorMethod(const Func
*& f
,
324 ObjectData
* createObject(const Class
* cls
,
325 const Variant
& params
,
327 ObjectData
* createObject(StringData
* clsName
,
328 const Variant
& params
,
330 ObjectData
* initObject(const Class
* cls
,
331 const Variant
& params
,
333 ObjectData
* initObject(StringData
* clsName
,
334 const Variant
& params
,
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();
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
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
);
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
);
413 template <bool forwarding
>
414 void pushClsMethodImpl(Class
* cls
, StringData
* name
,
415 ObjectData
* obj
, int numArgs
);
425 void invokeFunc(TypedValue
* retval
,
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
,
436 const Variant
& args_
,
437 VarEnv
* varEnv
= nullptr);
439 void invokeFuncFew(TypedValue
* retval
,
444 const TypedValue
* argv
);
446 void invokeFuncFew(TypedValue
* retval
,
449 StringData
* invName
= nullptr);
451 void invokeFuncFew(TypedValue
* retval
,
454 const TypedValue
* argv
);
456 TypedValue
invokeMethod(
459 InvokeArgs args
= InvokeArgs()
462 Variant
invokeMethodV(
465 InvokeArgs args
= InvokeArgs()
468 void resumeAsyncFunc(Resumable
* resumable
, ObjectData
* freeObj
,
470 void resumeAsyncFuncThrow(Resumable
* resumable
, ObjectData
* freeObj
,
471 ObjectData
* exception
);
474 using SmartStringIMap
= smart::hash_map
<
482 template<class F
> void scan(F
& mark
) {
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
);
493 //mark(m_stdoutData);
494 mark(m_stdoutBytesWritten
);
496 //mark(m_requestEventHandlers);TODO #6512343
498 mark(m_userErrorHandlers
);
499 mark(m_userExceptionHandlers
);
500 //mark(m_errorState);
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
);
513 //mark(m_vhost); // VirtualHost* not allocated in php request heap
514 //mark(debuggerSettings);
517 //mark(m_apcHandles);
519 mark(m_globalVarEnv
);
521 mark(m_evaledFilesOrder
);
522 mark(m_createdFuncs
);
523 //for (auto& f : m_faults) mark(f);
524 mark(m_lambdaCounter
);
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.
540 Transport
* m_transport
;
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
;
553 size_t m_stdoutBytesWritten
;
554 String m_rawPostData
;
557 smart::vector
<RequestEventHandler
*> m_requestEventHandlers
;
561 smart::vector
<std::pair
<Variant
,int>> m_userErrorHandlers
;
562 smart::vector
<Variant
> m_userExceptionHandlers
;
563 ErrorState m_errorState
;
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
;
584 DebuggerSettings debuggerSettings
;
585 smart::set
<ObjectData
*> m_liveBCObjs
;
587 size_t m_apcMemSize
{0};
588 std::vector
<APCHandle
*> m_apcHandles
; // gets moved to treadmill
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
>
597 smart::vector
<const StringData
*> m_evaledFilesOrder
;
598 smart::vector
<Unit
*> m_createdFuncs
;
599 smart::vector
<Fault
> m_faults
;
601 TinyVector
<VMState
, 32> m_nestedVMs
;
606 String m_lastErrorPath
;
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"