1use std::sync::Arc;
16
17use super::super::super::context::JITDuration;
18use super::super::super::jit_array::{ArrayElementKind, JitArray};
19use super::super::super::nan_boxing::*;
20
21#[derive(Clone)]
23pub struct JitTaskGroup {
24 pub kind: u8,
25 pub task_ids: Vec<u64>,
26}
27
28fn typed_array_to_jit<T: Copy + CastToF64>(
33 data: &[T],
34 hk: u16,
35 kind: ArrayElementKind,
36) -> u64 {
37 let boxed_arr: Vec<u64> = data.iter().map(|&v| box_number(v.cast_f64())).collect();
38 let mut jit_arr = JitArray::from_vec(boxed_arr);
39 jit_arr.typed_data = data.as_ptr() as *mut u64;
40 jit_arr.element_kind = kind.as_byte();
41 jit_arr.typed_storage_kind = kind.as_byte();
42 jit_box(hk, jit_arr)
43}
44
45fn jit_to_typed_array<T, F>(bits: u64, from_fn: F) -> shape_value::ValueWord
47where
48 T: Default + Copy,
49 f64: IntoTyped<T>,
50 F: FnOnce(Arc<shape_value::typed_buffer::TypedBuffer<T>>) -> shape_value::ValueWord,
51{
52 let arr = unsafe { jit_unbox::<JitArray>(bits) };
53 let data: Vec<T> = arr
54 .iter()
55 .map(|&b| {
56 if is_number(b) {
57 <f64 as IntoTyped<T>>::into_typed(unbox_number(b))
58 } else {
59 T::default()
60 }
61 })
62 .collect();
63 let buf = shape_value::typed_buffer::TypedBuffer {
64 data,
65 validity: None,
66 };
67 from_fn(Arc::new(buf))
68}
69
70trait CastToF64 {
72 fn cast_f64(self) -> f64;
73}
74impl CastToF64 for i8 { fn cast_f64(self) -> f64 { self as f64 } }
75impl CastToF64 for i16 { fn cast_f64(self) -> f64 { self as f64 } }
76impl CastToF64 for i32 { fn cast_f64(self) -> f64 { self as f64 } }
77impl CastToF64 for i64 { fn cast_f64(self) -> f64 { self as f64 } }
78impl CastToF64 for u8 { fn cast_f64(self) -> f64 { self as f64 } }
79impl CastToF64 for u16 { fn cast_f64(self) -> f64 { self as f64 } }
80impl CastToF64 for u32 { fn cast_f64(self) -> f64 { self as f64 } }
81impl CastToF64 for u64 { fn cast_f64(self) -> f64 { self as f64 } }
82impl CastToF64 for f32 { fn cast_f64(self) -> f64 { self as f64 } }
83impl CastToF64 for f64 { fn cast_f64(self) -> f64 { self } }
84
85trait IntoTyped<T> {
87 fn into_typed(self) -> T;
88}
89impl IntoTyped<i8> for f64 { fn into_typed(self) -> i8 { self as i8 } }
90impl IntoTyped<i16> for f64 { fn into_typed(self) -> i16 { self as i16 } }
91impl IntoTyped<i32> for f64 { fn into_typed(self) -> i32 { self as i32 } }
92impl IntoTyped<i64> for f64 { fn into_typed(self) -> i64 { self as i64 } }
93impl IntoTyped<u8> for f64 { fn into_typed(self) -> u8 { self as u8 } }
94impl IntoTyped<u16> for f64 { fn into_typed(self) -> u16 { self as u16 } }
95impl IntoTyped<u32> for f64 { fn into_typed(self) -> u32 { self as u32 } }
96impl IntoTyped<u64> for f64 { fn into_typed(self) -> u64 { self as u64 } }
97impl IntoTyped<f32> for f64 { fn into_typed(self) -> f32 { self as f32 } }
98impl IntoTyped<f64> for f64 { fn into_typed(self) -> f64 { self } }
99
100pub fn jit_bits_to_nanboxed(bits: u64) -> shape_value::ValueWord {
106 use shape_value::ValueWord;
107
108 if is_number(bits) {
109 return ValueWord::from_f64(unbox_number(bits));
110 }
111 if bits == TAG_NULL {
112 return ValueWord::none();
113 }
114 if bits == TAG_BOOL_TRUE {
115 return ValueWord::from_bool(true);
116 }
117 if bits == TAG_BOOL_FALSE {
118 return ValueWord::from_bool(false);
119 }
120 if bits == TAG_UNIT {
121 return ValueWord::unit();
122 }
123 if is_inline_function(bits) {
124 let func_id = unbox_function_id(bits);
125 return ValueWord::from_function_ref(format!("__func_{}", func_id), None);
126 }
127 if is_ok_tag(bits) {
128 let inner_bits = unsafe { unbox_result_inner(bits) };
129 let inner = jit_bits_to_nanboxed(inner_bits);
130 return ValueWord::from_ok(inner);
131 }
132 if is_err_tag(bits) {
133 let inner_bits = unsafe { unbox_result_inner(bits) };
134 let inner = jit_bits_to_nanboxed(inner_bits);
135 return ValueWord::from_err(inner);
136 }
137 if is_some_tag(bits) {
138 let inner_bits = unsafe { unbox_some_inner(bits) };
139 let inner = jit_bits_to_nanboxed(inner_bits);
140 return ValueWord::from_some(inner);
141 }
142
143 match heap_kind(bits) {
144 Some(HK_STRING) => {
145 let s = unsafe { jit_unbox::<String>(bits) };
146 ValueWord::from_string(Arc::new(s.clone()))
147 }
148 Some(HK_ARRAY) => {
149 let arr = unsafe { jit_unbox::<JitArray>(bits) };
150 let values: Vec<ValueWord> = arr.iter().map(|&b| jit_bits_to_nanboxed(b)).collect();
151 ValueWord::from_array(Arc::new(values))
152 }
153 Some(HK_CLOSURE) => {
154 let closure = unsafe { jit_unbox::<super::super::super::context::JITClosure>(bits) };
155 ValueWord::from_function_ref(format!("__func_{}", closure.function_id), None)
156 }
157 Some(HK_TASK_GROUP) => {
158 let tg = unsafe { jit_unbox::<JitTaskGroup>(bits) };
159 ValueWord::from_task_group(tg.kind, tg.task_ids.clone())
160 }
161 Some(HK_FUTURE) => {
162 let id = unsafe { jit_unbox::<u64>(bits) };
163 ValueWord::from_future(*id)
164 }
165 Some(HK_FLOAT_ARRAY) => {
166 let arr = unsafe { jit_unbox::<JitArray>(bits) };
168 let floats: Vec<f64> = arr
169 .iter()
170 .map(|&b| {
171 if is_number(b) {
172 unbox_number(b)
173 } else {
174 0.0
175 }
176 })
177 .collect();
178 let aligned = shape_value::aligned_vec::AlignedVec::from_vec(floats);
179 let buf = shape_value::typed_buffer::AlignedTypedBuffer::from_aligned(aligned);
180 ValueWord::from_float_array(Arc::new(buf))
181 }
182 Some(HK_INT_ARRAY) => {
183 let arr = unsafe { jit_unbox::<JitArray>(bits) };
185 let ints: Vec<i64> = arr
186 .iter()
187 .map(|&b| {
188 if is_number(b) {
189 unbox_number(b) as i64
190 } else {
191 0
192 }
193 })
194 .collect();
195 let buf = shape_value::typed_buffer::TypedBuffer { data: ints, validity: None };
196 ValueWord::from_int_array(Arc::new(buf))
197 }
198 Some(HK_FLOAT_ARRAY_SLICE) => {
199 let arr = unsafe { jit_unbox::<JitArray>(bits) };
201 if arr.slice_parent_arc.is_null() {
202 let floats: Vec<f64> = arr
204 .iter()
205 .map(|&b| if is_number(b) { unbox_number(b) } else { 0.0 })
206 .collect();
207 let aligned = shape_value::aligned_vec::AlignedVec::from_vec(floats);
208 let buf =
209 shape_value::typed_buffer::AlignedTypedBuffer::from_aligned(aligned);
210 ValueWord::from_float_array(Arc::new(buf))
211 } else {
212 let parent = unsafe {
215 Arc::from_raw(
216 arr.slice_parent_arc
217 as *const shape_value::heap_value::MatrixData,
218 )
219 };
220 let parent_clone = Arc::clone(&parent);
223 std::mem::forget(parent);
224 ValueWord::from_float_array_slice(
225 parent_clone,
226 arr.slice_offset,
227 arr.slice_len,
228 )
229 }
230 }
231 Some(HK_MATRIX) => {
232 let jm = unsafe {
234 jit_unbox::<crate::jit_matrix::JitMatrix>(bits)
235 };
236 let mat_arc = jm.to_arc();
237 ValueWord::from_matrix(mat_arc)
238 }
239 Some(HK_BOOL_ARRAY) => jit_to_typed_array::<u8, _>(bits, ValueWord::from_bool_array),
241 Some(HK_I8_ARRAY) => jit_to_typed_array::<i8, _>(bits, ValueWord::from_i8_array),
242 Some(HK_I16_ARRAY) => jit_to_typed_array::<i16, _>(bits, ValueWord::from_i16_array),
243 Some(HK_I32_ARRAY) => jit_to_typed_array::<i32, _>(bits, ValueWord::from_i32_array),
244 Some(HK_U8_ARRAY) => jit_to_typed_array::<u8, _>(bits, ValueWord::from_u8_array),
245 Some(HK_U16_ARRAY) => jit_to_typed_array::<u16, _>(bits, ValueWord::from_u16_array),
246 Some(HK_U32_ARRAY) => jit_to_typed_array::<u32, _>(bits, ValueWord::from_u32_array),
247 Some(HK_U64_ARRAY) => jit_to_typed_array::<u64, _>(bits, ValueWord::from_u64_array),
248 Some(HK_F32_ARRAY) => jit_to_typed_array::<f32, _>(bits, ValueWord::from_f32_array),
249 _ => ValueWord::none(),
250 }
251}
252
253pub fn jit_bits_to_nanboxed_with_ctx(
255 bits: u64,
256 ctx: *const super::super::super::context::JITContext,
257) -> shape_value::ValueWord {
258 use shape_value::ValueWord;
259
260 if is_number(bits) {
261 return ValueWord::from_f64(unbox_number(bits));
262 }
263
264 if is_inline_function(bits) {
266 let func_id = unbox_function_id(bits);
267 let name = lookup_function_name(ctx, func_id);
268 return ValueWord::from_function_ref(name, None);
269 }
270
271 if is_heap_kind(bits, HK_CLOSURE) {
272 let closure = unsafe { jit_unbox::<super::super::super::context::JITClosure>(bits) };
273 let name = lookup_function_name(ctx, closure.function_id);
274 return ValueWord::from_function_ref(name, None);
275 }
276
277 if is_heap_kind(bits, HK_ARRAY) {
278 let arr = unsafe { jit_unbox::<JitArray>(bits) };
279 let values: Vec<ValueWord> = arr
280 .iter()
281 .map(|&b| jit_bits_to_nanboxed_with_ctx(b, ctx))
282 .collect();
283 return ValueWord::from_array(Arc::new(values));
284 }
285
286 jit_bits_to_nanboxed(bits)
288}
289
290fn lookup_function_name(
292 ctx: *const super::super::super::context::JITContext,
293 func_id: u16,
294) -> String {
295 if !ctx.is_null() {
296 unsafe {
297 let ctx_ref = &*ctx;
298 if !ctx_ref.function_names_ptr.is_null()
299 && (func_id as usize) < ctx_ref.function_names_len
300 {
301 return (*ctx_ref.function_names_ptr.add(func_id as usize)).clone();
302 }
303 }
304 }
305 format!("__func_{}", func_id)
306}
307
308pub fn jit_bits_to_typed_scalar(
318 bits: u64,
319 hint: Option<shape_vm::SlotKind>,
320) -> shape_value::TypedScalar {
321 use shape_value::TypedScalar;
322 use shape_vm::SlotKind;
323
324 if is_number(bits) {
325 let f = unbox_number(bits);
326 if let Some(h) = hint {
328 match h {
329 SlotKind::Int8 | SlotKind::NullableInt8 => {
330 return TypedScalar::i8(f as i8);
331 }
332 SlotKind::UInt8 | SlotKind::NullableUInt8 => {
333 return TypedScalar::u8(f as u8);
334 }
335 SlotKind::Int16 | SlotKind::NullableInt16 => {
336 return TypedScalar::i16(f as i16);
337 }
338 SlotKind::UInt16 | SlotKind::NullableUInt16 => {
339 return TypedScalar::u16(f as u16);
340 }
341 SlotKind::Int32 | SlotKind::NullableInt32 => {
342 return TypedScalar::i32(f as i32);
343 }
344 SlotKind::UInt32 | SlotKind::NullableUInt32 => {
345 return TypedScalar::u32(f as u32);
346 }
347 SlotKind::Int64 | SlotKind::NullableInt64 => {
348 return TypedScalar::i64(f as i64);
349 }
350 SlotKind::UInt64 | SlotKind::NullableUInt64 => {
351 return TypedScalar::u64(f as u64);
352 }
353 SlotKind::Float64 | SlotKind::NullableFloat64 => {
354 return TypedScalar::f64_from_bits(bits);
355 }
356 _ => {
357 }
359 }
360 }
361 return TypedScalar::f64_from_bits(bits);
363 }
364
365 if bits == TAG_BOOL_TRUE {
366 return TypedScalar::bool(true);
367 }
368 if bits == TAG_BOOL_FALSE {
369 return TypedScalar::bool(false);
370 }
371 if bits == TAG_NULL || bits == TAG_NONE {
372 return TypedScalar::none();
373 }
374 if bits == TAG_UNIT {
375 return TypedScalar::unit();
376 }
377
378 TypedScalar::none()
380}
381
382pub fn typed_scalar_to_jit_bits(ts: &shape_value::TypedScalar) -> u64 {
387 use shape_value::ScalarKind;
388
389 match ts.kind {
390 ScalarKind::I8 | ScalarKind::I16 | ScalarKind::I32 | ScalarKind::I64 => {
391 box_number(ts.payload_lo as i64 as f64)
392 }
393 ScalarKind::U8 | ScalarKind::U16 | ScalarKind::U32 | ScalarKind::U64 => {
394 box_number(ts.payload_lo as f64)
395 }
396 ScalarKind::I128 | ScalarKind::U128 => box_number(ts.payload_lo as i64 as f64),
397 ScalarKind::F64 | ScalarKind::F32 => ts.payload_lo, ScalarKind::Bool => {
399 if ts.payload_lo != 0 {
400 TAG_BOOL_TRUE
401 } else {
402 TAG_BOOL_FALSE
403 }
404 }
405 ScalarKind::None => TAG_NULL,
406 ScalarKind::Unit => TAG_UNIT,
407 }
408}
409
410pub fn nanboxed_to_jit_bits(nb: &shape_value::ValueWord) -> u64 {
412 use shape_value::NanTag;
413 use shape_value::heap_value::HeapValue;
414
415 match nb.tag() {
416 NanTag::F64 => box_number(unsafe { nb.as_f64_unchecked() }),
417 NanTag::I48 => box_number(unsafe { nb.as_i64_unchecked() } as f64),
418 NanTag::Bool => {
419 if unsafe { nb.as_bool_unchecked() } {
420 TAG_BOOL_TRUE
421 } else {
422 TAG_BOOL_FALSE
423 }
424 }
425 NanTag::None => TAG_NULL,
426 NanTag::Unit => TAG_UNIT,
427 NanTag::Function => {
428 let func_id = unsafe { nb.as_function_unchecked() };
429 box_function(func_id)
430 }
431 NanTag::ModuleFunction => TAG_NULL,
432 NanTag::Ref => TAG_NULL,
433 NanTag::Heap => match nb.as_heap_ref() {
434 Some(HeapValue::String(s)) => jit_box(HK_STRING, s.clone()),
435 Some(HeapValue::Array(arr)) => {
436 let boxed_arr: Vec<u64> = arr.iter().map(|v| nanboxed_to_jit_bits(v)).collect();
442 jit_box(HK_ARRAY, JitArray::from_vec(boxed_arr))
443 }
444 Some(HeapValue::Time(dt)) => jit_box(HK_TIME, dt.timestamp()),
445 Some(HeapValue::Duration(dur)) => {
446 let unit_code = match dur.unit {
447 crate::ast::DurationUnit::Seconds => 0,
448 crate::ast::DurationUnit::Minutes => 1,
449 crate::ast::DurationUnit::Hours => 2,
450 crate::ast::DurationUnit::Days => 3,
451 crate::ast::DurationUnit::Weeks => 4,
452 crate::ast::DurationUnit::Months => 5,
453 crate::ast::DurationUnit::Years => 6,
454 crate::ast::DurationUnit::Samples => 7,
455 };
456 jit_box(
457 HK_DURATION,
458 JITDuration {
459 value: dur.value,
460 unit: unit_code,
461 },
462 )
463 }
464 Some(HeapValue::Timeframe(tf)) => {
465 let internal_tf = crate::ast::data::Timeframe::new(
466 tf.value,
467 match tf.unit {
468 crate::ast::TimeframeUnit::Second => {
469 crate::ast::data::TimeframeUnit::Second
470 }
471 crate::ast::TimeframeUnit::Minute => {
472 crate::ast::data::TimeframeUnit::Minute
473 }
474 crate::ast::TimeframeUnit::Hour => crate::ast::data::TimeframeUnit::Hour,
475 crate::ast::TimeframeUnit::Day => crate::ast::data::TimeframeUnit::Day,
476 crate::ast::TimeframeUnit::Week => crate::ast::data::TimeframeUnit::Week,
477 crate::ast::TimeframeUnit::Month => crate::ast::data::TimeframeUnit::Month,
478 crate::ast::TimeframeUnit::Year => crate::ast::data::TimeframeUnit::Year,
479 },
480 );
481 jit_box(HK_TIMEFRAME, internal_tf)
482 }
483 Some(HeapValue::Ok(inner)) => {
484 let inner_bits = nanboxed_to_jit_bits(inner);
485 box_ok(inner_bits)
486 }
487 Some(HeapValue::Err(inner)) => {
488 let inner_bits = nanboxed_to_jit_bits(inner);
489 box_err(inner_bits)
490 }
491 Some(HeapValue::Some(inner)) => {
492 let inner_bits = nanboxed_to_jit_bits(inner);
493 box_some(inner_bits)
494 }
495 Some(HeapValue::BigInt(i)) => box_number(*i as f64),
497 Some(HeapValue::TaskGroup { kind, task_ids }) => jit_box(
498 HK_TASK_GROUP,
499 JitTaskGroup {
500 kind: *kind,
501 task_ids: task_ids.clone(),
502 },
503 ),
504 Some(HeapValue::Future(id)) => jit_box(HK_FUTURE, *id),
505 Some(HeapValue::FloatArray(buf)) => {
506 let len = buf.data.len();
509 let boxed_arr: Vec<u64> = buf
510 .data
511 .as_slice()
512 .iter()
513 .map(|&v| box_number(v))
514 .collect();
515 let mut jit_arr = JitArray::from_vec(boxed_arr);
516 jit_arr.typed_data = buf.data.as_slice().as_ptr() as *mut u64;
521 jit_arr.element_kind =
522 crate::jit_array::ArrayElementKind::Float64.as_byte();
523 jit_arr.typed_storage_kind =
524 crate::jit_array::ArrayElementKind::Float64.as_byte();
525 let _ = len; jit_box(HK_FLOAT_ARRAY, jit_arr)
527 }
528 Some(HeapValue::IntArray(buf)) => {
529 let boxed_arr: Vec<u64> = buf
532 .data
533 .iter()
534 .map(|&v| box_number(v as f64))
535 .collect();
536 let mut jit_arr = JitArray::from_vec(boxed_arr);
537 jit_arr.typed_data = buf.data.as_ptr() as *mut u64;
538 jit_arr.element_kind =
539 crate::jit_array::ArrayElementKind::Int64.as_byte();
540 jit_arr.typed_storage_kind =
541 crate::jit_array::ArrayElementKind::Int64.as_byte();
542 jit_box(HK_INT_ARRAY, jit_arr)
543 }
544 Some(HeapValue::FloatArraySlice {
545 parent,
546 offset,
547 len,
548 }) => {
549 let off = *offset as usize;
553 let slice_len = *len as usize;
554 let parent_slice = parent.data.as_slice();
555 let end = (off + slice_len).min(parent_slice.len());
556 let actual_slice = &parent_slice[off..end];
557 let boxed_arr: Vec<u64> = actual_slice
558 .iter()
559 .map(|&v| box_number(v))
560 .collect();
561 let mut jit_arr = JitArray::from_vec(boxed_arr);
562 if !parent_slice.is_empty() && off < parent_slice.len() {
564 jit_arr.typed_data =
565 unsafe { parent_slice.as_ptr().add(off) } as *mut u64;
566 }
567 jit_arr.element_kind =
568 crate::jit_array::ArrayElementKind::Float64.as_byte();
569 jit_arr.typed_storage_kind =
570 crate::jit_array::ArrayElementKind::Float64.as_byte();
571 jit_arr.slice_parent_arc =
575 Arc::into_raw(Arc::clone(parent)) as *const ();
576 jit_arr.slice_offset = *offset;
577 jit_arr.slice_len = *len;
578 jit_box(HK_FLOAT_ARRAY_SLICE, jit_arr)
579 }
580 Some(HeapValue::Matrix(mat_arc)) => {
581 let jm = crate::jit_matrix::JitMatrix::from_arc(mat_arc);
583 jit_box(HK_MATRIX, jm)
584 }
585 Some(HeapValue::BoolArray(buf)) => typed_array_to_jit(&buf.data, HK_BOOL_ARRAY, ArrayElementKind::Bool),
587 Some(HeapValue::I8Array(buf)) => typed_array_to_jit(&buf.data, HK_I8_ARRAY, ArrayElementKind::I8),
588 Some(HeapValue::I16Array(buf)) => typed_array_to_jit(&buf.data, HK_I16_ARRAY, ArrayElementKind::I16),
589 Some(HeapValue::I32Array(buf)) => typed_array_to_jit(&buf.data, HK_I32_ARRAY, ArrayElementKind::I32),
590 Some(HeapValue::U8Array(buf)) => typed_array_to_jit(&buf.data, HK_U8_ARRAY, ArrayElementKind::U8),
591 Some(HeapValue::U16Array(buf)) => typed_array_to_jit(&buf.data, HK_U16_ARRAY, ArrayElementKind::U16),
592 Some(HeapValue::U32Array(buf)) => typed_array_to_jit(&buf.data, HK_U32_ARRAY, ArrayElementKind::U32),
593 Some(HeapValue::U64Array(buf)) => typed_array_to_jit(&buf.data, HK_U64_ARRAY, ArrayElementKind::U64),
594 Some(HeapValue::F32Array(buf)) => typed_array_to_jit(&buf.data, HK_F32_ARRAY, ArrayElementKind::F32),
595 _ => TAG_NULL,
596 },
597 }
598}