@@ -968,181 +968,6 @@ impl<'gc> VM<'gc> {
968968 Some(id)
969969 }
970970
971- fn shared_ta_info(&self, arr: &ArrayHandle<'gc>) -> Option<(u64, usize, usize, String)> {
972- let borrow = arr.borrow();
973- let Value::Object(buf_obj) = borrow.props.get("__typedarray_buffer__")?.clone() else {
974- return None;
975- };
976- let shared_id = self.shared_buffer_id_from_obj(&buf_obj)?;
977- let byte_offset = borrow
978- .props
979- .get("__byte_offset__")
980- .and_then(|v| if let Value::Number(n) = v { Some(*n as usize) } else { None })
981- .unwrap_or(0);
982- let bpe = borrow
983- .props
984- .get("__bytes_per_element__")
985- .and_then(|v| {
986- if let Value::Number(n) = v {
987- Some((*n as usize).max(1))
988- } else {
989- None
990- }
991- })
992- .unwrap_or(1);
993- let ta_name = borrow.props.get("__typedarray_name__").map(value_to_string).unwrap_or_default();
994- Some((shared_id, byte_offset, bpe, ta_name))
995- }
996-
997- fn ensure_shared_ta_info(&mut self, ctx: &GcContext<'gc>, arr: &ArrayHandle<'gc>) -> Option<(u64, usize, usize, String)> {
998- let buf_obj = {
999- let borrow = arr.borrow();
1000- let Value::Object(buf_obj) = borrow.props.get("__typedarray_buffer__")?.clone() else {
1001- return None;
1002- };
1003- buf_obj
1004- };
1005- self.ensure_shared_buffer_id(ctx, &buf_obj)?;
1006- self.shared_ta_info(arr)
1007- }
1008-
1009- fn shared_ta_read_element(&self, arr: &ArrayHandle<'gc>, idx: usize) -> Option<Value<'gc>> {
1010- let (shared_id, byte_offset, bpe, ta_name) = self.shared_ta_info(arr)?;
1011- let base = byte_offset.checked_add(idx.checked_mul(bpe)?)?;
1012- let raw = crate::js_agent::shared_buffer_read(shared_id, base, bpe)?;
1013- let bytes: Vec<Value<'gc>> = raw.into_iter().map(|b| Value::Number(b as f64)).collect();
1014- Some(Self::decode_typed_element(&bytes, 0, bpe, &ta_name))
1015- }
1016-
1017- fn local_ta_read_element(&self, arr: &ArrayHandle<'gc>, idx: usize) -> Option<Value<'gc>> {
1018- let (buf_obj, byte_offset, bpe, ta_name) = {
1019- let borrow = arr.borrow();
1020- let Value::Object(buf_obj) = borrow.props.get("__typedarray_buffer__")?.clone() else {
1021- return None;
1022- };
1023- let byte_offset = borrow
1024- .props
1025- .get("__byte_offset__")
1026- .and_then(|v| if let Value::Number(n) = v { Some(*n as usize) } else { None })
1027- .unwrap_or(0);
1028- let bpe = borrow
1029- .props
1030- .get("__bytes_per_element__")
1031- .and_then(|v| {
1032- if let Value::Number(n) = v {
1033- Some((*n as usize).max(1))
1034- } else {
1035- None
1036- }
1037- })
1038- .unwrap_or(1);
1039- let ta_name = borrow.props.get("__typedarray_name__").map(value_to_string).unwrap_or_default();
1040- (buf_obj, byte_offset, bpe, ta_name)
1041- };
1042- let base = byte_offset.checked_add(idx.checked_mul(bpe)?)?;
1043- let Value::Array(bytes) = buf_obj.borrow().get("__buffer_bytes__")?.clone() else {
1044- return None;
1045- };
1046- let bb = bytes.borrow();
1047- if base + bpe > bb.elements.len() {
1048- return None;
1049- }
1050- Some(Self::decode_typed_element(&bb.elements, base, bpe, &ta_name))
1051- }
1052-
1053- fn decode_typed_element_from_raw(&self, raw: &[u8], bpe: usize, ta_name: &str) -> Value<'gc> {
1054- let bytes: Vec<Value<'gc>> = raw.iter().map(|b| Value::Number(*b as f64)).collect();
1055- Self::decode_typed_element(&bytes, 0, bpe, ta_name)
1056- }
1057-
1058- fn encode_typed_element_to_raw(&self, bpe: usize, ta_name: &str, value: &Value<'gc>) -> Option<Vec<u8>> {
1059- let mut bytes = vec![Value::Number(0.0); bpe];
1060- if ta_name == "BigInt64Array" || ta_name == "BigUint64Array" {
1061- let Value::BigInt(bigint) = value else {
1062- return None;
1063- };
1064- Self::encode_typed_element_bigint(&mut bytes, 0, ta_name, bigint);
1065- } else {
1066- Self::encode_typed_element(&mut bytes, 0, bpe, ta_name, to_number(value));
1067- }
1068- Some(bytes.into_iter().map(|v| to_number(&v) as u8).collect())
1069- }
1070-
1071- fn shared_or_local_ta_element(&self, arr: &ArrayHandle<'gc>, idx: usize) -> Value<'gc> {
1072- self.shared_ta_read_element(arr, idx)
1073- .or_else(|| self.local_ta_read_element(arr, idx))
1074- .unwrap_or_else(|| arr.borrow().elements.get(idx).cloned().unwrap_or(Value::Undefined))
1075- }
1076-
1077- fn shared_atomic_rmw(
1078- &mut self,
1079- ctx: &GcContext<'gc>,
1080- arr: &ArrayHandle<'gc>,
1081- idx: usize,
1082- ta_name: &str,
1083- replacement_v: &Value<'gc>,
1084- op: usize,
1085- ) -> Option<Value<'gc>> {
1086- let (shared_id, byte_offset, bpe, _) = self.ensure_shared_ta_info(ctx, arr)?;
1087- let base = byte_offset.checked_add(idx.checked_mul(bpe)?)?;
1088- let is_bigint_ta = ta_name == "BigInt64Array" || ta_name == "BigUint64Array";
1089-
1090- if is_bigint_ta {
1091- let replacement_bi = self.value_to_bigint(ctx, replacement_v)?;
1092- loop {
1093- let old_raw = crate::js_agent::shared_buffer_read(shared_id, base, bpe)?;
1094- let old_value = self.decode_typed_element_from_raw(&old_raw, bpe, ta_name);
1095- let Value::BigInt(old_bi) = old_value.clone() else {
1096- return Some(Value::Undefined);
1097- };
1098-
1099- let new_bi = match op {
1100- BUILTIN_ATOMICS_ADD => old_bi.as_ref() + &replacement_bi,
1101- BUILTIN_ATOMICS_SUB => old_bi.as_ref() - &replacement_bi,
1102- BUILTIN_ATOMICS_AND => old_bi.as_ref() & &replacement_bi,
1103- BUILTIN_ATOMICS_OR => old_bi.as_ref() | &replacement_bi,
1104- BUILTIN_ATOMICS_XOR => old_bi.as_ref() ^ &replacement_bi,
1105- BUILTIN_ATOMICS_EXCHANGE => replacement_bi.clone(),
1106- _ => old_bi.as_ref().clone(),
1107- };
1108- let new_coerced = coerce_bigint_for_ta(&new_bi, ta_name);
1109- let new_value = Value::BigInt(Box::new(new_coerced));
1110- let new_raw = self.encode_typed_element_to_raw(bpe, ta_name, &new_value)?;
1111- let actual_old = crate::js_agent::shared_buffer_compare_exchange(shared_id, base, &old_raw, &new_raw)?;
1112- if actual_old == old_raw {
1113- arr.borrow_mut(ctx).elements[idx] = new_value;
1114- return Some(old_value);
1115- }
1116- }
1117- }
1118-
1119- let replacement_i32 = to_int32(to_number(replacement_v));
1120- let replacement_f64 = replacement_i32 as f64;
1121- loop {
1122- let old_raw = crate::js_agent::shared_buffer_read(shared_id, base, bpe)?;
1123- let old_value = self.decode_typed_element_from_raw(&old_raw, bpe, ta_name);
1124- let old_f64 = to_number(&old_value);
1125-
1126- let new_f64 = match op {
1127- BUILTIN_ATOMICS_ADD => old_f64 + replacement_f64,
1128- BUILTIN_ATOMICS_SUB => old_f64 - replacement_f64,
1129- BUILTIN_ATOMICS_AND => (to_int32(old_f64) & replacement_i32) as f64,
1130- BUILTIN_ATOMICS_OR => (to_int32(old_f64) | replacement_i32) as f64,
1131- BUILTIN_ATOMICS_XOR => (to_int32(old_f64) ^ replacement_i32) as f64,
1132- BUILTIN_ATOMICS_EXCHANGE => replacement_f64,
1133- _ => old_f64,
1134- };
1135- let new_coerced = coerce_typed_array_value(new_f64, ta_name);
1136- let new_value = Value::Number(new_coerced);
1137- let new_raw = self.encode_typed_element_to_raw(bpe, ta_name, &new_value)?;
1138- let actual_old = crate::js_agent::shared_buffer_compare_exchange(shared_id, base, &old_raw, &new_raw)?;
1139- if actual_old == old_raw {
1140- arr.borrow_mut(ctx).elements[idx] = new_value;
1141- return Some(old_value);
1142- }
1143- }
1144- }
1145-
1146971 fn make_shared_array_buffer_from_id(&mut self, ctx: &GcContext<'gc>, shared_id: u64) -> Option<Value<'gc>> {
1147972 let snapshot = crate::js_agent::shared_buffer_snapshot(shared_id)?;
1148973 let byte_length = snapshot.len();
0 commit comments