StackScriptFunction.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Js
  7. {
  8. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  9. #define BOX_PARAM(function, returnAddress, reason) function, returnAddress, reason
  10. #else
  11. #define BOX_PARAM(function, returnAddress, reason) function, returnAddress
  12. #endif
  13. class StackScriptFunction : public ScriptFunction
  14. {
  15. public:
  16. static JavascriptFunction * EnsureBoxed(BOX_PARAM(JavascriptFunction * function, void * returnAddress, char16 const * reason));
  17. static void Box(FunctionBody * functionBody, ScriptFunction ** functionRef);
  18. static ScriptFunction * OP_NewStackScFunc(FrameDisplay *environment, FunctionInfoPtrPtr infoRef, ScriptFunction * stackFunction);
  19. static uint32 GetOffsetOfBoxedScriptFunction() { return offsetof(StackScriptFunction, boxedScriptFunction); }
  20. static JavascriptFunction * GetCurrentFunctionObject(JavascriptFunction * function);
  21. StackScriptFunction(FunctionProxy * proxy, ScriptFunctionType* deferredPrototypeType) :
  22. ScriptFunction(proxy, deferredPrototypeType), boxedScriptFunction(nullptr) {};
  23. #if DBG
  24. static bool IsBoxed(Var var)
  25. {
  26. return VarTo<StackScriptFunction>(var)->boxedScriptFunction != nullptr;
  27. }
  28. #endif
  29. // A stack function object does not escape, so it should never be marshaled.
  30. // Defining this function also make the vtable unique, so that we can detect stack function
  31. // via the vtable
  32. DEFINE_VTABLE_CTOR(StackScriptFunction, ScriptFunction);
  33. virtual void MarshalToScriptContext(Js::ScriptContext * scriptContext) override
  34. {
  35. Assert(false);
  36. }
  37. private:
  38. static ScriptFunction * Box(StackScriptFunction * stackScriptFunction, void * returnAddress);
  39. struct BoxState
  40. {
  41. public:
  42. BoxState(ArenaAllocator * alloc, FunctionBody * functionBody, ScriptContext * scriptContext, void * returnAddress = nullptr);
  43. void Box();
  44. ScriptFunction * GetBoxedScriptFunction(ScriptFunction * stackScriptFunction);
  45. private:
  46. JsUtil::BaseHashSet<FunctionBody *, ArenaAllocator> frameToBox;
  47. JsUtil::BaseHashSet<FunctionProxy *, ArenaAllocator> functionObjectToBox;
  48. JsUtil::BaseDictionary<void *, void*, ArenaAllocator> boxedValues;
  49. ScriptContext * scriptContext;
  50. void * returnAddress;
  51. Field(Var) * BoxScopeSlots(Field(Var) * scopeSlots, uint count);
  52. bool NeedBoxFrame(FunctionBody * functionBody);
  53. bool NeedBoxScriptFunction(ScriptFunction * scriptFunction);
  54. ScriptFunction * BoxStackFunction(ScriptFunction * scriptFunction);
  55. FrameDisplay * BoxFrameDisplay(FrameDisplay * frameDisplay);
  56. FrameDisplay * GetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
  57. Var * GetScopeSlotsFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
  58. void SetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, FrameDisplay * frameDisplay);
  59. void SetScopeSlotsFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Var * scopeSlots);
  60. void BoxNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
  61. void UpdateFrameDisplay(ScriptFunction *nestedFunc);
  62. void Finish();
  63. template<class Fn>
  64. void ForEachStackNestedFunction(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Fn fn);
  65. template<class Fn>
  66. void ForEachStackNestedFunctionInterpreted(InterpreterStackFrame *interpreterFrame, FunctionBody * callerFunctionBody, Fn fn);
  67. template<class Fn>
  68. void ForEachStackNestedFunctionNative(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Fn fn);
  69. static uintptr_t GetNativeFrameDisplayIndex(FunctionBody * functionBody);
  70. static uintptr_t GetNativeScopeSlotsIndex(FunctionBody * functionBody);
  71. };
  72. ScriptFunction * boxedScriptFunction;
  73. #if ENABLE_TTD
  74. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  75. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  76. #endif
  77. public:
  78. virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
  79. {
  80. return VTableValue::VtableStackScriptFunction;
  81. }
  82. };
  83. template <> inline bool VarIsImpl<StackScriptFunction>(RecyclableObject* obj)
  84. {
  85. bool result = VarIs<ScriptFunction>(obj);
  86. if (result)
  87. {
  88. Assert(ThreadContext::IsOnStack(obj));
  89. }
  90. return result;
  91. }
  92. };