@@ -218,6 +218,11 @@ namespace Js
218
218
{
219
219
Assert (!this ->isDetached );
220
220
221
+ // we are about to lose track of the buffer to another owner
222
+ // report that we no longer own the memory
223
+ Recycler* recycler = GetType ()->GetLibrary ()->GetRecycler ();
224
+ recycler->ReportExternalMemoryFree (bufferLength);
225
+
221
226
this ->buffer = nullptr ;
222
227
this ->bufferLength = 0 ;
223
228
this ->isDetached = true ;
@@ -696,6 +701,13 @@ namespace Js
696
701
Recycler* recycler = type->GetScriptContext ()->GetRecycler ();
697
702
JavascriptArrayBuffer* result = RecyclerNewFinalized (recycler, JavascriptArrayBuffer, buffer, length, type);
698
703
Assert (result);
704
+
705
+ // we take the ownership of the buffer and will have to free it so charge it to our quota.
706
+ if (!recycler->RequestExternalMemoryAllocation (length))
707
+ {
708
+ JavascriptError::ThrowOutOfMemoryError (result->GetScriptContext ());
709
+ }
710
+
699
711
recycler->AddExternalMemoryUsage (length);
700
712
return result;
701
713
}
@@ -707,7 +719,6 @@ namespace Js
707
719
{
708
720
freeFunction (this ->buffer );
709
721
this ->buffer = nullptr ;
710
- this ->recycler ->ReportExternalMemoryFree (this ->bufferLength );
711
722
}
712
723
this ->bufferLength = 0 ;
713
724
}
@@ -770,12 +781,6 @@ namespace Js
770
781
771
782
void JavascriptArrayBuffer::Finalize (bool isShutdown)
772
783
{
773
- // In debugger scenario, ScriptAuthor can create scriptContext and delete scriptContext
774
- // explicitly. So for the builtin, while javascriptLibrary is still alive fine, the
775
- // matching scriptContext might have been deleted and the javascriptLibrary->scriptContext
776
- // field reset (but javascriptLibrary is still alive).
777
- // Use the recycler field off library instead of scriptcontext to avoid av.
778
-
779
784
// Recycler may not be available at Dispose. We need to
780
785
// free the memory and report that it has been freed at the same
781
786
// time. Otherwise, AllocationPolicyManager is unable to provide correct feedback
@@ -885,6 +890,12 @@ namespace Js
885
890
if (buffer)
886
891
{
887
892
result = RecyclerNewFinalized (recycler, WebAssemblyArrayBuffer, buffer, length, type);
893
+
894
+ // we take the ownership of the buffer and will have to free it so charge it to our quota.
895
+ if (!recycler->RequestExternalMemoryAllocation (length))
896
+ {
897
+ JavascriptError::ThrowOutOfMemoryError (result->GetScriptContext ());
898
+ }
888
899
}
889
900
else
890
901
{
@@ -898,9 +909,9 @@ namespace Js
898
909
{
899
910
result = RecyclerNewFinalized (recycler, WebAssemblyArrayBuffer, length, type);
900
911
}
901
- // Only add external memory when we create a new internal buffer
902
- recycler->AddExternalMemoryUsage (length);
903
912
}
913
+
914
+ recycler->AddExternalMemoryUsage (length);
904
915
Assert (result);
905
916
return result;
906
917
}
@@ -955,6 +966,11 @@ namespace Js
955
966
{
956
967
return nullptr ;
957
968
}
969
+
970
+ // We are transferring the buffer to the new owner.
971
+ // To avoid double-charge to the allocation quota we will free the "diff" amount here.
972
+ this ->GetRecycler ()->ReportExternalMemoryFree (growSize);
973
+
958
974
return finalizeGrowMemory (this ->GetLibrary ()->CreateWebAssemblyArrayBuffer (this ->buffer , newBufferLength));
959
975
}
960
976
#endif
@@ -990,6 +1006,10 @@ namespace Js
990
1006
return nullptr ;
991
1007
}
992
1008
1009
+ // We are transferring the buffer to the new owner.
1010
+ // To avoid double-charge to the allocation quota we will free the "diff" amount here.
1011
+ this ->GetRecycler ()->ReportExternalMemoryFree (growSize);
1012
+
993
1013
WebAssemblyArrayBuffer* newArrayBuffer = finalizeGrowMemory (this ->GetLibrary ()->CreateWebAssemblyArrayBuffer (newBuffer, newBufferLength));
994
1014
// We've successfully Detached this buffer and created a new WebAssemblyArrayBuffer
995
1015
autoDisableInterrupt.Completed ();
@@ -1018,15 +1038,37 @@ namespace Js
1018
1038
ProjectionArrayBuffer* ProjectionArrayBuffer::Create (byte* buffer, uint32 length, DynamicType * type)
1019
1039
{
1020
1040
Recycler* recycler = type->GetScriptContext ()->GetRecycler ();
1041
+ ProjectionArrayBuffer* result = RecyclerNewFinalized (recycler, ProjectionArrayBuffer, buffer, length, type);
1042
+
1043
+ // we take the ownership of the buffer and will have to free it so charge it to our quota.
1044
+ if (!recycler->RequestExternalMemoryAllocation (length))
1045
+ {
1046
+ JavascriptError::ThrowOutOfMemoryError (result->GetScriptContext ());
1047
+ }
1048
+
1021
1049
// This is user passed [in] buffer, user should AddExternalMemoryUsage before calling jscript, but
1022
1050
// I don't see we ask everyone to do this. Let's add the memory pressure here as well.
1023
1051
recycler->AddExternalMemoryUsage (length);
1024
- return RecyclerNewFinalized (recycler, ProjectionArrayBuffer, buffer, length, type);
1052
+ return result;
1053
+
1025
1054
}
1026
1055
1027
- void ProjectionArrayBuffer::Dispose (bool isShutdown)
1056
+ void ProjectionArrayBuffer::Finalize (bool isShutdown)
1028
1057
{
1029
1058
CoTaskMemFree (buffer);
1059
+ // Recycler may not be available at Dispose. We need to
1060
+ // free the memory and report that it has been freed at the same
1061
+ // time. Otherwise, AllocationPolicyManager is unable to provide correct feedback
1062
+ Recycler* recycler = GetType ()->GetLibrary ()->GetRecycler ();
1063
+ recycler->ReportExternalMemoryFree (bufferLength);
1064
+
1065
+ buffer = nullptr ;
1066
+ bufferLength = 0 ;
1067
+ }
1068
+
1069
+ void ProjectionArrayBuffer::Dispose (bool isShutdown)
1070
+ {
1071
+ /* See ProjectionArrayBuffer::Finalize */
1030
1072
}
1031
1073
1032
1074
ExternalArrayBuffer::ExternalArrayBuffer (byte *buffer, uint32 length, DynamicType *type)
0 commit comments