Skip to content

Commit 252f08a

Browse files
committed
Unify all set property instructions into set_by_name function
1 parent 982338c commit 252f08a

File tree

1 file changed

+76
-124
lines changed

1 file changed

+76
-124
lines changed

core/engine/src/vm/opcode/set/property.rs

Lines changed: 76 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::JsValue;
12
use crate::value::JsVariant;
23
use crate::vm::opcode::VaryingOperand;
34
use crate::{
@@ -9,6 +10,77 @@ use crate::{
910
};
1011
use boa_macros::js_str;
1112

13+
fn set_by_name(
14+
value: VaryingOperand,
15+
value_object: &JsValue,
16+
receiver: &JsValue,
17+
index: VaryingOperand,
18+
context: &mut Context,
19+
) -> JsResult<()> {
20+
let value = context.vm.get_register(value.into()).clone();
21+
22+
let object = value_object.to_object(context)?;
23+
24+
let ic = &context.vm.frame().code_block().ic[usize::from(index)];
25+
26+
let object_borrowed = object.borrow();
27+
if let Some((shape, slot)) = ic.match_or_reset(object_borrowed.shape()) {
28+
let slot_index = slot.index as usize;
29+
30+
if slot.attributes.is_accessor_descriptor() {
31+
let result = if slot.attributes.contains(SlotAttributes::PROTOTYPE) {
32+
let prototype = shape.prototype().expect("prototype should have value");
33+
let prototype = prototype.borrow();
34+
35+
prototype.properties().storage[slot_index + 1].clone()
36+
} else {
37+
object_borrowed.properties().storage[slot_index + 1].clone()
38+
};
39+
40+
drop(object_borrowed);
41+
if slot.attributes.has_set() && result.is_object() {
42+
result.as_object().expect("should contain getter").call(
43+
receiver,
44+
std::slice::from_ref(&value),
45+
context,
46+
)?;
47+
}
48+
} else if slot.attributes.contains(SlotAttributes::PROTOTYPE) {
49+
let prototype = shape.prototype().expect("prototype should have value");
50+
let mut prototype = prototype.borrow_mut();
51+
52+
prototype.properties_mut().storage[slot_index] = value.clone();
53+
} else {
54+
drop(object_borrowed);
55+
let mut object_borrowed = object.borrow_mut();
56+
object_borrowed.properties_mut().storage[slot_index] = value.clone();
57+
}
58+
return Ok(());
59+
}
60+
drop(object_borrowed);
61+
62+
let name: PropertyKey = ic.name.clone().into();
63+
64+
let context = &mut InternalMethodPropertyContext::new(context);
65+
let succeeded = object.__set__(name.clone(), value.clone(), receiver.clone(), context)?;
66+
if !succeeded && context.vm.frame().code_block.strict() {
67+
return Err(JsNativeError::typ()
68+
.with_message(format!("cannot set non-writable property: {name}"))
69+
.into());
70+
}
71+
72+
// Cache the property.
73+
let slot = *context.slot();
74+
if succeeded && slot.is_cachable() {
75+
let ic = &context.vm.frame().code_block.ic[usize::from(index)];
76+
let object_borrowed = object.borrow();
77+
let shape = object_borrowed.shape();
78+
ic.set(shape, slot);
79+
}
80+
81+
Ok(())
82+
}
83+
1284
/// `SetPropertyByName` implements the Opcode Operation for `Opcode::SetPropertyByName`
1385
///
1486
/// Operation:
@@ -22,68 +94,8 @@ impl SetPropertyByName {
2294
(value, object, index): (VaryingOperand, VaryingOperand, VaryingOperand),
2395
context: &mut Context,
2496
) -> JsResult<()> {
25-
let value = context.vm.get_register(value.into()).clone();
26-
let value_object = context.vm.get_register(object.into()).clone();
27-
let object = value_object.to_object(context)?;
28-
29-
let ic = &context.vm.frame().code_block().ic[usize::from(index)];
30-
31-
let object_borrowed = object.borrow();
32-
if let Some((shape, slot)) = ic.match_or_reset(object_borrowed.shape()) {
33-
let slot_index = slot.index as usize;
34-
35-
if slot.attributes.is_accessor_descriptor() {
36-
let result = if slot.attributes.contains(SlotAttributes::PROTOTYPE) {
37-
let prototype = shape.prototype().expect("prototype should have value");
38-
let prototype = prototype.borrow();
39-
40-
prototype.properties().storage[slot_index + 1].clone()
41-
} else {
42-
object_borrowed.properties().storage[slot_index + 1].clone()
43-
};
44-
45-
drop(object_borrowed);
46-
if slot.attributes.has_set() && result.is_object() {
47-
result.as_object().expect("should contain getter").call(
48-
&value_object,
49-
&[value],
50-
context,
51-
)?;
52-
}
53-
} else if slot.attributes.contains(SlotAttributes::PROTOTYPE) {
54-
let prototype = shape.prototype().expect("prototype should have value");
55-
let mut prototype = prototype.borrow_mut();
56-
57-
prototype.properties_mut().storage[slot_index] = value.clone();
58-
} else {
59-
drop(object_borrowed);
60-
let mut object_borrowed = object.borrow_mut();
61-
object_borrowed.properties_mut().storage[slot_index] = value.clone();
62-
}
63-
return Ok(());
64-
}
65-
drop(object_borrowed);
66-
67-
let name: PropertyKey = ic.name.clone().into();
68-
69-
let context = &mut InternalMethodPropertyContext::new(context);
70-
let succeeded = object.__set__(name.clone(), value.clone(), value_object, context)?;
71-
if !succeeded && context.vm.frame().code_block.strict() {
72-
return Err(JsNativeError::typ()
73-
.with_message(format!("cannot set non-writable property: {name}"))
74-
.into());
75-
}
76-
77-
// Cache the property.
78-
let slot = *context.slot();
79-
if succeeded && slot.is_cachable() {
80-
let ic = &context.vm.frame().code_block.ic[usize::from(index)];
81-
let object_borrowed = object.borrow();
82-
let shape = object_borrowed.shape();
83-
ic.set(shape, slot);
84-
}
85-
86-
Ok(())
97+
let object = context.vm.get_register(object.into()).clone();
98+
set_by_name(value, &object, &object, index, context)
8799
}
88100
}
89101

@@ -111,69 +123,9 @@ impl SetPropertyByNameWithThis {
111123
),
112124
context: &mut Context,
113125
) -> JsResult<()> {
114-
let value = context.vm.get_register(value.into()).clone();
115-
let receiver = context.vm.get_register(receiver.into()).clone();
116126
let value_object = context.vm.get_register(object.into()).clone();
117-
let object = value_object.to_object(context)?;
118-
119-
let ic = &context.vm.frame().code_block().ic[usize::from(index)];
120-
121-
let object_borrowed = object.borrow();
122-
if let Some((shape, slot)) = ic.match_or_reset(object_borrowed.shape()) {
123-
let slot_index = slot.index as usize;
124-
125-
if slot.attributes.is_accessor_descriptor() {
126-
let result = if slot.attributes.contains(SlotAttributes::PROTOTYPE) {
127-
let prototype = shape.prototype().expect("prototype should have value");
128-
let prototype = prototype.borrow();
129-
130-
prototype.properties().storage[slot_index + 1].clone()
131-
} else {
132-
object_borrowed.properties().storage[slot_index + 1].clone()
133-
};
134-
135-
drop(object_borrowed);
136-
if slot.attributes.has_set() && result.is_object() {
137-
result.as_object().expect("should contain getter").call(
138-
&receiver,
139-
std::slice::from_ref(&value),
140-
context,
141-
)?;
142-
}
143-
} else if slot.attributes.contains(SlotAttributes::PROTOTYPE) {
144-
let prototype = shape.prototype().expect("prototype should have value");
145-
let mut prototype = prototype.borrow_mut();
146-
147-
prototype.properties_mut().storage[slot_index] = value.clone();
148-
} else {
149-
drop(object_borrowed);
150-
let mut object_borrowed = object.borrow_mut();
151-
object_borrowed.properties_mut().storage[slot_index] = value.clone();
152-
}
153-
return Ok(());
154-
}
155-
drop(object_borrowed);
156-
157-
let name: PropertyKey = ic.name.clone().into();
158-
159-
let context = &mut InternalMethodPropertyContext::new(context);
160-
let succeeded = object.__set__(name.clone(), value.clone(), receiver.clone(), context)?;
161-
if !succeeded && context.vm.frame().code_block.strict() {
162-
return Err(JsNativeError::typ()
163-
.with_message(format!("cannot set non-writable property: {name}"))
164-
.into());
165-
}
166-
167-
// Cache the property.
168-
let slot = *context.slot();
169-
if succeeded && slot.is_cachable() {
170-
let ic = &context.vm.frame().code_block.ic[usize::from(index)];
171-
let object_borrowed = object.borrow();
172-
let shape = object_borrowed.shape();
173-
ic.set(shape, slot);
174-
}
175-
176-
Ok(())
127+
let receiver = context.vm.get_register(receiver.into()).clone();
128+
set_by_name(value, &value_object, &receiver, index, context)
177129
}
178130
}
179131

0 commit comments

Comments
 (0)