| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeBasePch.h"
- namespace Js
- {
- ScriptContextOptimizationOverrideInfo::ScriptContextOptimizationOverrideInfo()
- : sideEffects(SideEffects_None),
- arraySetElementFastPathVtable(VirtualTableInfo<Js::JavascriptArray>::Address),
- intArraySetElementFastPathVtable(VirtualTableInfo<Js::JavascriptNativeIntArray>::Address),
- floatArraySetElementFastPathVtable(VirtualTableInfo<Js::JavascriptNativeFloatArray>::Address),
- crossSiteRoot(nullptr), crossSitePrev(nullptr), crossSiteNext(nullptr)
- {
- }
- ScriptContextOptimizationOverrideInfo::~ScriptContextOptimizationOverrideInfo()
- {
- ScriptContextOptimizationOverrideInfo * next = crossSiteNext;
- if (next != nullptr)
- {
- ScriptContextOptimizationOverrideInfo * root = crossSiteRoot;
- Assert(root != nullptr);
- if (this == root)
- {
- // Change the root
- ForEachCrossSiteInfo([next](ScriptContextOptimizationOverrideInfo * info)
- {
- info->crossSiteRoot = next;
- });
- }
- ScriptContextOptimizationOverrideInfo * prev = crossSitePrev;
- Assert(prev != nullptr);
- next->crossSitePrev = prev;
- prev->crossSiteNext = next;
- }
- }
- template <typename Fn>
- void ScriptContextOptimizationOverrideInfo::ForEachCrossSiteInfo(Fn fn)
- {
- Assert(crossSiteRoot != nullptr);
- ScriptContextOptimizationOverrideInfo * current = this;
- do
- {
- fn(current);
- current = current->crossSiteNext;
- }
- while (current != this);
- }
- template <typename Fn>
- void ScriptContextOptimizationOverrideInfo::ForEachEditingCrossSiteInfo(Fn fn)
- {
- Assert(crossSiteRoot != nullptr);
- ScriptContextOptimizationOverrideInfo * current = this;
- do
- {
- ScriptContextOptimizationOverrideInfo * next = current->crossSiteNext;
- fn(current);
- current = next;
- }
- while (current != this);
- }
- void
- ScriptContextOptimizationOverrideInfo::Merge(ScriptContextOptimizationOverrideInfo * info)
- {
- ScriptContextOptimizationOverrideInfo * thisRoot = this->crossSiteRoot;
- ScriptContextOptimizationOverrideInfo * infoRoot = info->crossSiteRoot;
- if (thisRoot == infoRoot)
- {
- if (thisRoot != nullptr)
- {
- // Both info is already in the same info group
- return;
- }
- // Both of them are null, just group them
- // Update this to be the template
- this->Update(info);
- // Initialize the cross site list
- this->crossSiteRoot = this;
- this->crossSitePrev = this;
- this->crossSiteNext = this;
- // Insert the info to the list
- this->Insert(info);
- }
- else
- {
- if (thisRoot == nullptr)
- {
- thisRoot = infoRoot;
- infoRoot = nullptr;
- info = this;
- }
- thisRoot->Update(info);
- // Spread the information on the current group
- thisRoot->ForEachCrossSiteInfo([thisRoot](ScriptContextOptimizationOverrideInfo * i)
- {
- thisRoot->CopyTo(i);
- });
- if (infoRoot == nullptr)
- {
- thisRoot->Insert(info);
- }
- else
- {
- // Insert the other group
- info->ForEachEditingCrossSiteInfo([thisRoot](ScriptContextOptimizationOverrideInfo * i)
- {
- thisRoot->Insert(i);
- });
- }
- }
- DebugOnly(Verify());
- }
- void
- ScriptContextOptimizationOverrideInfo::CopyTo(ScriptContextOptimizationOverrideInfo * info)
- {
- info->arraySetElementFastPathVtable = this->arraySetElementFastPathVtable;
- info->intArraySetElementFastPathVtable = this->intArraySetElementFastPathVtable;
- info->floatArraySetElementFastPathVtable = this->floatArraySetElementFastPathVtable;
- info->sideEffects = this->sideEffects;
- }
- void
- ScriptContextOptimizationOverrideInfo::Insert(ScriptContextOptimizationOverrideInfo * info)
- {
- // Copy the information
- this->CopyTo(info);
- // Insert
- // Only insert at the root
- Assert(this == this->crossSiteRoot);
- info->crossSiteRoot = this;
- info->crossSiteNext = this;
- info->crossSitePrev = this->crossSitePrev;
- this->crossSitePrev->crossSiteNext = info;
- this->crossSitePrev = info;
- }
- void
- ScriptContextOptimizationOverrideInfo::Update(ScriptContextOptimizationOverrideInfo * info)
- {
- if (!info->IsEnabledArraySetElementFastPath())
- {
- this->DisableArraySetElementFastPath();
- }
- this->sideEffects = (SideEffects)(this->sideEffects | info->sideEffects);
- }
- void
- ScriptContextOptimizationOverrideInfo::SetSideEffects(SideEffects se)
- {
- if (this->crossSiteRoot == nullptr)
- {
- sideEffects = (SideEffects)(sideEffects | se);
- }
- else if ((sideEffects & se) != se)
- {
- ForEachCrossSiteInfo([se](ScriptContextOptimizationOverrideInfo * info)
- {
- Assert((info->sideEffects & se) != se);
- info->sideEffects = (SideEffects)(info->sideEffects | se);
- });
- }
- }
- bool
- ScriptContextOptimizationOverrideInfo::IsEnabledArraySetElementFastPath() const
- {
- return arraySetElementFastPathVtable != InvalidVtable;
- }
- void
- ScriptContextOptimizationOverrideInfo::DisableArraySetElementFastPath()
- {
- if (this->crossSiteRoot == nullptr)
- {
- arraySetElementFastPathVtable = InvalidVtable;
- intArraySetElementFastPathVtable = InvalidVtable;
- floatArraySetElementFastPathVtable = InvalidVtable;
- }
- else if (IsEnabledArraySetElementFastPath())
- {
- // disable for all script context in the cross site group
- ForEachCrossSiteInfo([](ScriptContextOptimizationOverrideInfo * info)
- {
- Assert(info->IsEnabledArraySetElementFastPath());
- info->arraySetElementFastPathVtable = InvalidVtable;
- info->intArraySetElementFastPathVtable = InvalidVtable;
- info->floatArraySetElementFastPathVtable = InvalidVtable;
- });
- }
- }
- INT_PTR
- ScriptContextOptimizationOverrideInfo::GetArraySetElementFastPathVtable() const
- {
- return (INT_PTR)&arraySetElementFastPathVtable;
- }
- INT_PTR
- ScriptContextOptimizationOverrideInfo::GetIntArraySetElementFastPathVtable() const
- {
- return (INT_PTR)&intArraySetElementFastPathVtable;
- }
- INT_PTR
- ScriptContextOptimizationOverrideInfo::GetFloatArraySetElementFastPathVtable() const
- {
- return (INT_PTR)&floatArraySetElementFastPathVtable;
- }
- void *
- ScriptContextOptimizationOverrideInfo::GetAddressOfArraySetElementFastPathVtable()
- {
- return &arraySetElementFastPathVtable;
- }
- void *
- ScriptContextOptimizationOverrideInfo::GetAddressOfIntArraySetElementFastPathVtable()
- {
- return &intArraySetElementFastPathVtable;
- }
- void *
- ScriptContextOptimizationOverrideInfo::GetAddressOfFloatArraySetElementFastPathVtable()
- {
- return &floatArraySetElementFastPathVtable;
- }
- #if DBG
- void
- ScriptContextOptimizationOverrideInfo::Verify()
- {
- if (this->crossSiteRoot == nullptr)
- {
- return;
- }
- this->ForEachCrossSiteInfo([this](ScriptContextOptimizationOverrideInfo * i)
- {
- Assert(i->crossSiteRoot == this->crossSiteRoot);
- Assert(i->sideEffects == this->sideEffects);
- Assert(i->arraySetElementFastPathVtable == this->arraySetElementFastPathVtable);
- Assert(i->intArraySetElementFastPathVtable == this->intArraySetElementFastPathVtable);
- Assert(i->floatArraySetElementFastPathVtable == this->floatArraySetElementFastPathVtable);
- });
- }
- #endif
- };
|