[vm/bytecode] Capture receiver if creating a closure
When creating a closure, receiver is loaded in order to obtain
instantiator type arguments. That access was not capturing
receiver, if a closure was created inside another closure.
Change-Id: I9ec6d9f2c90643e6deb9c4efde1b070a3255a387
Reviewed-on: https://dart-review.googlesource.com/c/91442
Commit-Queue: Régis Crelier <regis@google.com>
Auto-Submit: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index b3fac13..0baa233 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -512,6 +512,10 @@
@override
visitFunctionDeclaration(FunctionDeclaration node) {
_currentFrame.hasClosures = true;
+ if (_currentFrame.receiverVar != null) {
+ // Closure creation may load receiver to get instantiator type arguments.
+ _useThis();
+ }
node.variable.accept(this);
_visitFunction(node);
}
@@ -519,6 +523,10 @@
@override
visitFunctionExpression(FunctionExpression node) {
_currentFrame.hasClosures = true;
+ if (_currentFrame.receiverVar != null) {
+ // Closure creation may load receiver to get instantiator type arguments.
+ _useThis();
+ }
_visitFunction(node);
}
diff --git a/pkg/vm/testcases/bytecode/closures.dart b/pkg/vm/testcases/bytecode/closures.dart
index 5e6359f..e96872c 100644
--- a/pkg/vm/testcases/bytecode/closures.dart
+++ b/pkg/vm/testcases/bytecode/closures.dart
@@ -143,6 +143,14 @@
foo(T t) {
return () => t;
}
+
+ bar() {
+ return () {
+ inner() {}
+
+ inner();
+ };
+ }
}
main() {}
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index f801084..cbe6532 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -1177,6 +1177,108 @@
] method foo(generic-covariant-impl self::D::T t) → dynamic {
return () → self::D::T => t;
}
+[@vm.bytecode=
+Bytecode {
+ Entry 3
+ CheckStack 0
+ AllocateContext 0, 1
+ PopLocal r0
+ Push r0
+ Push FP[-5]
+ StoreContextVar 0, 0
+ Allocate CP#5
+ StoreLocal r2
+ Push r2
+ Push FP[-5]
+ LoadTypeArgumentsField CP#6
+ StoreFieldTOS CP#7
+ Push r2
+ PushNull
+ StoreFieldTOS CP#9
+ Push r2
+ PushConstant CP#11
+ StoreFieldTOS CP#12
+ Push r2
+ PushConstant CP#0
+ StoreFieldTOS CP#14
+ Push r2
+ Push r0
+ StoreFieldTOS CP#1
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ClosureFunction 0
+ [1] = InstanceField dart:core::_Closure::_context (field)
+ [2] = Reserved
+ [3] = ClosureFunction 1
+ [4] = EndClosureFunctionScope
+ [5] = Class dart:core::_Closure
+ [6] = TypeArgumentsField #lib::D
+ [7] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [8] = Reserved
+ [9] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+ [10] = Reserved
+ [11] = EmptyTypeArguments
+ [12] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+ [13] = Reserved
+ [14] = InstanceField dart:core::_Closure::_function (field)
+ [15] = Reserved
+ [16] = ArgDesc num-args 1, num-type-args 0, names []
+ [17] = ICData dynamic target-name 'call', arg-desc CP#16
+ [18] = EndClosureFunctionScope
+}
+Closure #lib::D::bar::<anonymous closure> () -> dart:core::Null
+ClosureBytecode {
+ EntryFixed 1, 4
+ CheckStack 0
+ Push FP[-5]
+ LoadFieldTOS CP#1
+ PopLocal r0
+ Allocate CP#5
+ StoreLocal r3
+ Push r3
+ Push r0
+ LoadContextVar 0, 0
+ LoadTypeArgumentsField CP#6
+ StoreFieldTOS CP#7
+ Push r3
+ PushNull
+ StoreFieldTOS CP#9
+ Push r3
+ PushConstant CP#11
+ StoreFieldTOS CP#12
+ Push r3
+ PushConstant CP#3
+ StoreFieldTOS CP#14
+ Push r3
+ Push r0
+ StoreFieldTOS CP#1
+ PopLocal r2
+ Push r2
+ DynamicCall 1, CP#17
+ Drop1
+ PushNull
+ ReturnTOS
+
+}
+
+Closure #lib::D::bar::Closure/0::inner () -> dart:core::Null
+ClosureBytecode {
+ EntryFixed 1, 2
+ CheckStack 0
+ Push FP[-5]
+ LoadFieldTOS CP#1
+ PopLocal r0
+ PushNull
+ ReturnTOS
+
+}
+] method bar() → dynamic {
+ return () → core::Null {
+ function inner() → core::Null {}
+ [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] inner.call();
+ };
+ }
}
[@vm.bytecode=
Bytecode {