blob: d781506e0a9315151138132589cf71f40cda93d1 [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
namespace Js
{
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
#define BOX_PARAM(function, returnAddress, reason) function, returnAddress, reason
#else
#define BOX_PARAM(function, returnAddress, reason) function, returnAddress
#endif
class StackScriptFunction : public ScriptFunction
{
public:
static JavascriptFunction * EnsureBoxed(BOX_PARAM(JavascriptFunction * function, void * returnAddress, char16 const * reason));
static void Box(FunctionBody * functionBody, ScriptFunction ** functionRef);
static ScriptFunction * OP_NewStackScFunc(FrameDisplay *environment, FunctionInfoPtrPtr infoRef, ScriptFunction * stackFunction);
static uint32 GetOffsetOfBoxedScriptFunction() { return offsetof(StackScriptFunction, boxedScriptFunction); }
static JavascriptFunction * GetCurrentFunctionObject(JavascriptFunction * function);
StackScriptFunction(FunctionProxy * proxy, ScriptFunctionType* deferredPrototypeType) :
ScriptFunction(proxy, deferredPrototypeType), boxedScriptFunction(nullptr) {};
#if DBG
static bool IsBoxed(Var var)
{
return StackScriptFunction::FromVar(var)->boxedScriptFunction != nullptr;
}
#endif
// A stack function object does not escape, so it should never be marshaled.
// Defining this function also make the vtable unique, so that we can detect stack function
// via the vtable
DEFINE_VTABLE_CTOR(StackScriptFunction, ScriptFunction);
virtual void MarshalToScriptContext(Js::ScriptContext * scriptContext) override
{
Assert(false);
}
private:
static ScriptFunction * Box(StackScriptFunction * stackScriptFunction, void * returnAddress);
static StackScriptFunction * FromVar(Var var);
struct BoxState
{
public:
BoxState(ArenaAllocator * alloc, FunctionBody * functionBody, ScriptContext * scriptContext, void * returnAddress = nullptr);
void Box();
ScriptFunction * GetBoxedScriptFunction(ScriptFunction * stackScriptFunction);
private:
JsUtil::BaseHashSet<FunctionBody *, ArenaAllocator> frameToBox;
JsUtil::BaseHashSet<FunctionProxy *, ArenaAllocator> functionObjectToBox;
JsUtil::BaseDictionary<void *, void*, ArenaAllocator> boxedValues;
ScriptContext * scriptContext;
void * returnAddress;
Var * BoxScopeSlots(Var * scopeSlots, uint count);
bool NeedBoxFrame(FunctionBody * functionBody);
bool NeedBoxScriptFunction(ScriptFunction * scriptFunction);
ScriptFunction * BoxStackFunction(ScriptFunction * scriptFunction);
FrameDisplay * BoxFrameDisplay(FrameDisplay * frameDisplay);
FrameDisplay * GetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
Var * GetScopeSlotsFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
void SetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, FrameDisplay * frameDisplay);
void SetScopeSlotsFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Var * scopeSlots);
void BoxNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
void UpdateFrameDisplay(ScriptFunction *nestedFunc);
void Finish();
template<class Fn>
void ForEachStackNestedFunction(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Fn fn);
template<class Fn>
void ForEachStackNestedFunctionInterpreted(InterpreterStackFrame *interpreterFrame, FunctionBody * callerFunctionBody, Fn fn);
template<class Fn>
void ForEachStackNestedFunctionNative(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Fn fn);
static uintptr_t GetNativeFrameDisplayIndex(FunctionBody * functionBody);
static uintptr_t GetNativeScopeSlotsIndex(FunctionBody * functionBody);
};
ScriptFunction * boxedScriptFunction;
#if ENABLE_TTD
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
virtual void MarshalCrossSite_TTDInflate() override
{
Assert(false);
}
#endif
public:
virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
{
return VTableValue::VtableStackScriptFunction;
}
};
};