-
-
Notifications
You must be signed in to change notification settings - Fork 613
Expand file tree
/
Copy patharray.rs
More file actions
139 lines (125 loc) · 4.36 KB
/
array.rs
File metadata and controls
139 lines (125 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use crate::{
Context, JsExpect, JsResult, JsValue,
builtins::Array,
string::StaticJsStrings,
vm::opcode::{Operation, RegisterOperand},
};
/// `StoreNewArray` implements the Opcode Operation for `Opcode::StoreNewArray`
///
/// Operation:
/// - Store an empty array in dst.
#[derive(Debug, Clone, Copy)]
pub(crate) struct StoreNewArray;
impl StoreNewArray {
#[inline(always)]
pub(crate) fn operation(array: RegisterOperand, context: &mut Context) {
let value = context
.intrinsics()
.templates()
.array()
.create(Array, Vec::from([JsValue::new(0)]));
context.vm.set_register(array.into(), value.into());
}
}
impl Operation for StoreNewArray {
const NAME: &'static str = "StoreNewArray";
const INSTRUCTION: &'static str = "INST - StoreNewArray";
const COST: u8 = 3;
}
/// `PushValueToArray` implements the Opcode Operation for `Opcode::PushValueToArray`
///
/// Operation:
/// - Push a value to an array.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushValueToArray;
impl PushValueToArray {
#[inline(always)]
pub(crate) fn operation(
(value, array): (RegisterOperand, RegisterOperand),
context: &mut Context,
) -> JsResult<()> {
let value = context.vm.get_register(value.into()).clone();
let o = context
.vm
.get_register(array.into())
.as_object()
.js_expect("should be an object")?;
// Fast path: push directly to dense indexed storage.
{
let mut o_mut = o.borrow_mut();
let len = o_mut.properties().storage[0].as_i32();
if let Some(len) = len
&& o_mut.properties_mut().indexed_properties.push_dense(&value)
{
o_mut.properties_mut().storage[0] = JsValue::new(len + 1);
return Ok(());
}
}
// Slow path: fall through to the generic property machinery.
let len = o
.length_of_array_like(context)
.js_expect("should have 'length' property")?;
o.create_data_property_or_throw(len, value, context)
.js_expect("should be able to create new data property")?;
Ok(())
}
}
impl Operation for PushValueToArray {
const NAME: &'static str = "PushValueToArray";
const INSTRUCTION: &'static str = "INST - PushValueToArray";
const COST: u8 = 3;
}
/// `PushElisionToArray` implements the Opcode Operation for `Opcode::PushElisionToArray`
///
/// Operation:
/// - Push an empty element/hole to an array.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushElisionToArray;
impl PushElisionToArray {
#[inline(always)]
pub(crate) fn operation(array: RegisterOperand, context: &mut Context) -> JsResult<()> {
let array = context.vm.get_register(array.into()).clone();
let o = array.as_object().js_expect("should always be an object")?;
let len = o
.length_of_array_like(context)
.js_expect("arrays should always have a 'length' property")?;
o.set(StaticJsStrings::LENGTH, len + 1, true, context)?;
o.borrow_mut()
.properties_mut()
.indexed_properties
.transform_to_sparse();
Ok(())
}
}
impl Operation for PushElisionToArray {
const NAME: &'static str = "PushElisionToArray";
const INSTRUCTION: &'static str = "INST - PushElisionToArray";
const COST: u8 = 3;
}
/// `PushIteratorToArray` implements the Opcode Operation for `Opcode::PushIteratorToArray`
///
/// Operation:
/// - Push all iterator values to an array.
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushIteratorToArray;
impl PushIteratorToArray {
#[inline(always)]
pub(crate) fn operation(array: RegisterOperand, context: &mut Context) -> JsResult<()> {
let array = context.vm.get_register(array.into()).clone();
let mut iterator = context
.vm
.frame_mut()
.iterators
.pop()
.js_expect("iterator stack should have at least an iterator")?;
while let Some(next) = iterator.step_value(context)? {
Array::push(&array, &[next], context)?;
}
Ok(())
}
}
impl Operation for PushIteratorToArray {
const NAME: &'static str = "PushIteratorToArray";
const INSTRUCTION: &'static str = "INST - PushIteratorToArray";
const COST: u8 = 8;
}