Skip to content

Commit 7c10074

Browse files
committed
Optimize property get and set
1 parent 350bfa4 commit 7c10074

File tree

11 files changed

+411
-100
lines changed

11 files changed

+411
-100
lines changed

core/engine/src/bytecompiler/declaration/declaration_pattern.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,7 @@ impl ByteCompiler<'_> {
4040

4141
match name {
4242
PropertyName::Literal(ident) => {
43-
self.emit_get_property_by_name(
44-
&dst,
45-
object,
46-
object,
47-
ident.sym(),
48-
);
43+
self.emit_get_property_by_name(&dst, None, object, ident.sym());
4944
let key = self.register_allocator.alloc();
5045
self.emit_push_literal(
5146
Literal::String(
@@ -162,7 +157,7 @@ impl ByteCompiler<'_> {
162157
PropertyName::Literal(ident) => {
163158
compiler.emit_get_property_by_name(
164159
&dst,
165-
object,
160+
None,
166161
object,
167162
ident.sym(),
168163
);
@@ -209,12 +204,7 @@ impl ByteCompiler<'_> {
209204

210205
match name {
211206
PropertyName::Literal(ident) => {
212-
self.emit_get_property_by_name(
213-
&dst,
214-
object,
215-
object,
216-
ident.sym(),
217-
);
207+
self.emit_get_property_by_name(&dst, None, object, ident.sym());
218208
}
219209
PropertyName::Computed(node) => {
220210
let key = self.register_allocator.alloc();

core/engine/src/bytecompiler/expression/assign.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,11 @@ impl ByteCompiler<'_> {
183183
let object = compiler.register_allocator.alloc();
184184
compiler.compile_expr(access.target(), &object);
185185

186-
compiler.emit_get_property_by_name(dst, &object, &object, name.sym());
186+
compiler.emit_get_property_by_name(dst, None, &object, name.sym());
187187

188188
early_exit = emit(&mut compiler, dst, assign.rhs(), assign.op());
189189

190-
compiler.emit_set_property_by_name(dst, &object, &object, name.sym());
190+
compiler.emit_set_property_by_name(dst, None, &object, name.sym());
191191

192192
compiler.register_allocator.dealloc(object);
193193
}
@@ -247,11 +247,21 @@ impl ByteCompiler<'_> {
247247
compiler.bytecode.emit_super(object.variable());
248248
compiler.bytecode.emit_this(receiver.variable());
249249

250-
compiler.emit_get_property_by_name(dst, &receiver, &object, name.sym());
250+
compiler.emit_get_property_by_name(
251+
dst,
252+
Some(&receiver),
253+
&object,
254+
name.sym(),
255+
);
251256

252257
early_exit = emit(&mut compiler, dst, assign.rhs(), assign.op());
253258

254-
compiler.emit_set_property_by_name(dst, &receiver, &object, name.sym());
259+
compiler.emit_set_property_by_name(
260+
dst,
261+
Some(&receiver),
262+
&object,
263+
name.sym(),
264+
);
255265

256266
compiler.register_allocator.dealloc(receiver);
257267
compiler.register_allocator.dealloc(object);

core/engine/src/bytecompiler/expression/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,7 @@ impl ByteCompiler<'_> {
263263
self.compile_expr(access.target(), &this);
264264
match access.field() {
265265
PropertyAccessField::Const(ident) => {
266-
self.emit_get_property_by_name(
267-
&function,
268-
&this,
269-
&this,
270-
ident.sym(),
271-
);
266+
self.emit_get_property_by_name(&function, None, &this, ident.sym());
272267
}
273268
PropertyAccessField::Expr(field) => {
274269
let key = self.register_allocator.alloc();

core/engine/src/bytecompiler/expression/update.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,15 @@ impl ByteCompiler<'_> {
8383

8484
match access.field() {
8585
PropertyAccessField::Const(ident) => {
86-
compiler.emit_get_property_by_name(dst, &object, &object, ident.sym());
86+
compiler.emit_get_property_by_name(dst, None, &object, ident.sym());
8787
let value = compiler.register_allocator.alloc();
8888
if increment {
8989
compiler.bytecode.emit_inc(value.variable(), dst.variable());
9090
} else {
9191
compiler.bytecode.emit_dec(value.variable(), dst.variable());
9292
}
9393

94-
compiler.emit_set_property_by_name(
95-
&value,
96-
&object,
97-
&object,
98-
ident.sym(),
99-
);
94+
compiler.emit_set_property_by_name(&value, None, &object, ident.sym());
10095

10196
if !post {
10297
compiler
@@ -184,7 +179,12 @@ impl ByteCompiler<'_> {
184179
compiler.bytecode.emit_super(object.variable());
185180
compiler.bytecode.emit_this(receiver.variable());
186181

187-
compiler.emit_get_property_by_name(dst, &receiver, &object, ident.sym());
182+
compiler.emit_get_property_by_name(
183+
dst,
184+
Some(&receiver),
185+
&object,
186+
ident.sym(),
187+
);
188188

189189
let value = compiler.register_allocator.alloc();
190190
if increment {
@@ -193,7 +193,12 @@ impl ByteCompiler<'_> {
193193
compiler.bytecode.emit_dec(value.variable(), dst.variable());
194194
}
195195

196-
compiler.emit_set_property_by_name(&value, &receiver, &object, ident.sym());
196+
compiler.emit_set_property_by_name(
197+
&value,
198+
Some(&receiver),
199+
&object,
200+
ident.sym(),
201+
);
197202
if !post {
198203
compiler
199204
.bytecode

core/engine/src/bytecompiler/mod.rs

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use boa_ast::{
5252
use boa_gc::Gc;
5353
use boa_interner::{Interner, Sym};
5454
use boa_macros::js_str;
55+
use boa_string::StaticJsStrings;
5556
use rustc_hash::FxHashMap;
5657
use thin_vec::ThinVec;
5758

@@ -921,7 +922,7 @@ impl<'ctx> ByteCompiler<'ctx> {
921922
fn emit_get_property_by_name(
922923
&mut self,
923924
dst: &Register,
924-
receiver: &Register,
925+
receiver: Option<&Register>,
925926
value: &Register,
926927
ident: Sym,
927928
) {
@@ -933,18 +934,32 @@ impl<'ctx> ByteCompiler<'ctx> {
933934
};
934935
self.ic.push(InlineCache::new(name.clone()));
935936

936-
self.bytecode.emit_get_property_by_name(
937-
dst.variable(),
938-
receiver.variable(),
939-
value.variable(),
940-
ic_index.into(),
941-
);
937+
if let Some(receiver) = receiver {
938+
self.bytecode.emit_get_property_by_name_with_this(
939+
dst.variable(),
940+
receiver.variable(),
941+
value.variable(),
942+
ic_index.into(),
943+
);
944+
} else if name == &StaticJsStrings::LENGTH {
945+
self.bytecode.emit_get_length_property(
946+
dst.variable(),
947+
value.variable(),
948+
ic_index.into(),
949+
);
950+
} else {
951+
self.bytecode.emit_get_property_by_name(
952+
dst.variable(),
953+
value.variable(),
954+
ic_index.into(),
955+
);
956+
}
942957
}
943958

944959
fn emit_set_property_by_name(
945960
&mut self,
946961
value: &Register,
947-
receiver: &Register,
962+
receiver: Option<&Register>,
948963
object: &Register,
949964
ident: Sym,
950965
) {
@@ -956,12 +971,20 @@ impl<'ctx> ByteCompiler<'ctx> {
956971
};
957972
self.ic.push(InlineCache::new(name.clone()));
958973

959-
self.bytecode.emit_set_property_by_name(
960-
value.variable(),
961-
receiver.variable(),
962-
object.variable(),
963-
ic_index.into(),
964-
);
974+
if let Some(receiver) = receiver {
975+
self.bytecode.emit_set_property_by_name_with_this(
976+
value.variable(),
977+
receiver.variable(),
978+
object.variable(),
979+
ic_index.into(),
980+
);
981+
} else {
982+
self.bytecode.emit_set_property_by_name(
983+
value.variable(),
984+
object.variable(),
985+
ic_index.into(),
986+
);
987+
}
965988
}
966989

967990
fn emit_type_error(&mut self, message: &str) {
@@ -1119,7 +1142,7 @@ impl<'ctx> ByteCompiler<'ctx> {
11191142

11201143
match access.field() {
11211144
PropertyAccessField::Const(ident) => {
1122-
compiler.emit_get_property_by_name(dst, &object, &object, ident.sym());
1145+
compiler.emit_get_property_by_name(dst, None, &object, ident.sym());
11231146
}
11241147
PropertyAccessField::Expr(expr) => {
11251148
let key = compiler.register_allocator.alloc();
@@ -1157,7 +1180,12 @@ impl<'ctx> ByteCompiler<'ctx> {
11571180
compiler.bytecode.emit_this(receiver.variable());
11581181
match access.field() {
11591182
PropertyAccessField::Const(ident) => {
1160-
compiler.emit_get_property_by_name(dst, &receiver, &value, ident.sym());
1183+
compiler.emit_get_property_by_name(
1184+
dst,
1185+
Some(&receiver),
1186+
&value,
1187+
ident.sym(),
1188+
);
11611189
}
11621190
PropertyAccessField::Expr(expr) => {
11631191
let key = compiler.register_allocator.alloc();
@@ -1222,7 +1250,7 @@ impl<'ctx> ByteCompiler<'ctx> {
12221250
let object = self.register_allocator.alloc();
12231251
self.compile_expr(access.target(), &object);
12241252
let value = expr_fn(self);
1225-
self.emit_set_property_by_name(value, &object, &object, name.sym());
1253+
self.emit_set_property_by_name(value, None, &object, name.sym());
12261254
self.register_allocator.dealloc(object);
12271255
}
12281256
PropertyAccessField::Expr(expr) => {
@@ -1271,7 +1299,7 @@ impl<'ctx> ByteCompiler<'ctx> {
12711299

12721300
let value = expr_fn(self);
12731301

1274-
self.emit_set_property_by_name(value, &receiver, &object, name.sym());
1302+
self.emit_set_property_by_name(value, Some(&receiver), &object, name.sym());
12751303

12761304
self.register_allocator.dealloc(receiver);
12771305
self.register_allocator.dealloc(object);
@@ -1393,7 +1421,7 @@ impl<'ctx> ByteCompiler<'ctx> {
13931421

13941422
match access.field() {
13951423
PropertyAccessField::Const(ident) => {
1396-
self.emit_get_property_by_name(dst, this, this, ident.sym());
1424+
self.emit_get_property_by_name(dst, None, this, ident.sym());
13971425
}
13981426
PropertyAccessField::Expr(field) => {
13991427
let key = self.register_allocator.alloc();
@@ -1422,7 +1450,7 @@ impl<'ctx> ByteCompiler<'ctx> {
14221450

14231451
match access.field() {
14241452
PropertyAccessField::Const(ident) => {
1425-
self.emit_get_property_by_name(dst, this, &object, ident.sym());
1453+
self.emit_get_property_by_name(dst, Some(this), &object, ident.sym());
14261454
}
14271455
PropertyAccessField::Expr(expr) => {
14281456
let key = self.register_allocator.alloc();
@@ -1525,7 +1553,7 @@ impl<'ctx> ByteCompiler<'ctx> {
15251553
self.bytecode.emit_move(this.variable(), value.variable());
15261554
match field {
15271555
PropertyAccessField::Const(name) => {
1528-
self.emit_get_property_by_name(value, value, value, name.sym());
1556+
self.emit_get_property_by_name(value, None, value, name.sym());
15291557
}
15301558
PropertyAccessField::Expr(expr) => {
15311559
let key = self.register_allocator.alloc();

core/engine/src/value/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -620,13 +620,13 @@ impl JsValue {
620620
JsVariant::Undefined | JsVariant::Null => Err(JsNativeError::typ()
621621
.with_message("cannot convert 'null' or 'undefined' to object")
622622
.into()),
623-
JsVariant::Boolean(_) => Ok(constructors.boolean().prototype().clone()),
623+
JsVariant::Boolean(_) => Ok(constructors.boolean().prototype()),
624624
JsVariant::Integer32(_) | JsVariant::Float64(_) => {
625-
Ok(constructors.number().prototype().clone())
625+
Ok(constructors.number().prototype())
626626
}
627-
JsVariant::String(_) => Ok(constructors.string().prototype().clone()),
628-
JsVariant::Symbol(_) => Ok(constructors.symbol().prototype().clone()),
629-
JsVariant::BigInt(_) => Ok(constructors.bigint().prototype().clone()),
627+
JsVariant::String(_) => Ok(constructors.string().prototype()),
628+
JsVariant::Symbol(_) => Ok(constructors.symbol().prototype()),
629+
JsVariant::BigInt(_) => Ok(constructors.bigint().prototype()),
630630
JsVariant::Object(object) => Ok(object.clone()),
631631
}
632632
}

core/engine/src/vm/code_block.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,30 @@ impl CodeBlock {
626626
Instruction::DeletePropertyByName { object, name_index } => {
627627
format!("object:{object}, name_index:{name_index}")
628628
}
629+
Instruction::GetLengthProperty {
630+
dst,
631+
value,
632+
ic_index,
633+
} => {
634+
let ic = &self.ic[u32::from(*ic_index) as usize];
635+
format!(
636+
"dst:{dst}, value:{value}, shape:0x{:x}]",
637+
ic.shape.borrow().to_addr_usize(),
638+
)
639+
}
629640
Instruction::GetPropertyByName {
641+
dst,
642+
value,
643+
ic_index,
644+
} => {
645+
let ic = &self.ic[u32::from(*ic_index) as usize];
646+
format!(
647+
"dst:{dst}, value:{value}, ic:[name:{}, shape:0x{:x}]",
648+
ic.name.to_std_string_escaped(),
649+
ic.shape.borrow().to_addr_usize(),
650+
)
651+
}
652+
Instruction::GetPropertyByNameWithThis {
630653
dst,
631654
receiver,
632655
value,
@@ -640,6 +663,17 @@ impl CodeBlock {
640663
)
641664
}
642665
Instruction::SetPropertyByName {
666+
value,
667+
object,
668+
ic_index,
669+
} => {
670+
let ic = &self.ic[u32::from(*ic_index) as usize];
671+
format!(
672+
"object:{object}, value:{value}, ic:shape:0x{:x}",
673+
ic.shape.borrow().to_addr_usize(),
674+
)
675+
}
676+
Instruction::SetPropertyByNameWithThis {
643677
value,
644678
receiver,
645679
object,
@@ -901,10 +935,7 @@ impl CodeBlock {
901935
| Instruction::Reserved57
902936
| Instruction::Reserved58
903937
| Instruction::Reserved59
904-
| Instruction::Reserved60
905-
| Instruction::Reserved61
906-
| Instruction::Reserved62
907-
| Instruction::Reserved63 => unreachable!("Reserved opcodes are unreachable"),
938+
| Instruction::Reserved60 => unreachable!("Reserved opcodes are unreachable"),
908939
}
909940
}
910941
}

core/engine/src/vm/flowgraph/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,13 @@ impl CodeBlock {
280280
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
281281
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
282282
}
283-
Instruction::GetPropertyByName { .. }
283+
Instruction::GetPropertyByNameWithThis { .. }
284+
| Instruction::GetLengthProperty { .. }
285+
| Instruction::GetPropertyByName { .. }
284286
| Instruction::GetPropertyByValue { .. }
285287
| Instruction::GetPropertyByValuePush { .. }
286288
| Instruction::SetPropertyByName { .. }
289+
| Instruction::SetPropertyByNameWithThis { .. }
287290
| Instruction::DefineOwnPropertyByName { .. }
288291
| Instruction::DefineClassStaticMethodByName { .. }
289292
| Instruction::DefineClassMethodByName { .. }
@@ -512,10 +515,7 @@ impl CodeBlock {
512515
| Instruction::Reserved57
513516
| Instruction::Reserved58
514517
| Instruction::Reserved59
515-
| Instruction::Reserved60
516-
| Instruction::Reserved61
517-
| Instruction::Reserved62
518-
| Instruction::Reserved63 => unreachable!("Reserved opcodes are unreachable"),
518+
| Instruction::Reserved60 => unreachable!("Reserved opcodes are unreachable"),
519519
}
520520
}
521521

0 commit comments

Comments
 (0)