51d1c8923a
This is a reland of commit 88496ba1c3
Fixes on top of the original change:
* Closure layout is changed to avoid gap between fixed fields and
variable-length elements on compressed pointers architecture.
This gap was causing crashes in the GC when scanning closure
objects.
* pkg/vm_snapshot_analysis/test/instruction_sizes_test is fixed
on arm64 by decreasing threshold for detecting size changes.
Original change's description:
> [vm,dart2bytecode,modular_aot] Variable-length closure objects
>
> Extend closure objects with variable number of elements to capture.
> This is needed to support capturing multiple independent contexts
> after capturing is computed in the front-end.
>
> The following fixed Closure fields are moved into variable-length
> elements:
> - delayed type arguments;
> - instantiator type arguments;
> - function type arguments;
> - context.
>
> Number of elements and presence/indices of various type arguments
> are encoded into the new length_and_flags field in the Closure.
>
> Most closure objects don't need any of the type arguments so this
> change will reduce average Closure object size.
TEST=ci
Issue: https://github.com/dart-lang/sdk/issues/61572
Issue: https://github.com/dart-lang/sdk/issues/61635
Change-Id: I8685e632e2d0832766ecdc470f3cf9a6b880de48
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/494243
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
255 lines
6.9 KiB
Plaintext
255 lines
6.9 KiB
Plaintext
Bytecode
|
|
Dynamic Module Entry Point: DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::main
|
|
Library 'DART_SDK/pkg/dart2bytecode/testcases/invisible.dart'
|
|
name '#lib'
|
|
script 'DART_SDK/pkg/dart2bytecode/testcases/invisible.dart'
|
|
|
|
Class '', script = 'DART_SDK/pkg/dart2bytecode/testcases/invisible.dart'
|
|
|
|
|
|
Function 'visible', static, reflectable, debuggable
|
|
parameters [FunctionType () -> void 'fun'] (required: 1)
|
|
return-type void
|
|
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
PushConstant CP#0
|
|
DirectCall CP#1, 1
|
|
Drop1
|
|
Push FP[-5]
|
|
StoreLocal r0
|
|
Push r0
|
|
UncheckedClosureCall CP#3, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ObjectRef 'visible()'
|
|
[1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = Reserved
|
|
[3] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
|
|
}
|
|
|
|
|
|
Function 'invisible', static, reflectable, debuggable, invisible, has-pragma
|
|
parameters [FunctionType () -> void 'fun'] (required: 1)
|
|
return-type void
|
|
annotations const List<dynamic> [const dart:core::pragma {dart:core::pragma::name (field): 'vm:invisible', dart:core::pragma::options (field): null}]
|
|
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
PushConstant CP#0
|
|
DirectCall CP#1, 1
|
|
Drop1
|
|
Push FP[-5]
|
|
StoreLocal r0
|
|
Push r0
|
|
UncheckedClosureCall CP#3, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ObjectRef 'invisible()'
|
|
[1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = Reserved
|
|
[3] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
|
|
}
|
|
|
|
|
|
Function 'visibleClosure', static, reflectable, debuggable
|
|
parameters [FunctionType () -> void 'fun'] (required: 1)
|
|
return-type void
|
|
|
|
Bytecode {
|
|
Entry 4
|
|
CheckStack 0
|
|
AllocateContext 0, 1
|
|
PopLocal r0
|
|
Push r0
|
|
Push FP[-5]
|
|
StoreContextVar 0, 0
|
|
AllocateClosure CP#6
|
|
StoreLocal r3
|
|
Push r3
|
|
Push r0
|
|
StoreClosureElement 0
|
|
PopLocal r2
|
|
Push r2
|
|
Push r2
|
|
UncheckedClosureCall CP#4, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ClosureFunction 0
|
|
[1] = ObjectRef 'visibleInner'
|
|
[2] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[3] = Reserved
|
|
[4] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
|
|
[5] = EndClosureFunctionScope
|
|
[6] = AllocateClosure 0, num-elements: 1, flags: 0
|
|
[7] = Reserved
|
|
}
|
|
Closure DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::visibleClosure::'visibleInner' () -> Null
|
|
ClosureCode {
|
|
Entry 3
|
|
Push FP[-5]
|
|
LoadClosureElement 0
|
|
PopLocal r0
|
|
CheckStack 0
|
|
PushConstant CP#1
|
|
DirectCall CP#2, 1
|
|
Drop1
|
|
Push r0
|
|
LoadContextVar 0, 0
|
|
StoreLocal r2
|
|
Push r2
|
|
UncheckedClosureCall CP#4, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
|
|
|
|
Function 'invisibleClosure', static, reflectable, debuggable
|
|
parameters [FunctionType () -> void 'fun'] (required: 1)
|
|
return-type void
|
|
|
|
Bytecode {
|
|
Entry 4
|
|
CheckStack 0
|
|
AllocateContext 0, 1
|
|
PopLocal r0
|
|
Push r0
|
|
Push FP[-5]
|
|
StoreContextVar 0, 0
|
|
AllocateClosure CP#6
|
|
StoreLocal r3
|
|
Push r3
|
|
Push r0
|
|
StoreClosureElement 0
|
|
PopLocal r2
|
|
Push r2
|
|
Push r2
|
|
UncheckedClosureCall CP#4, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ClosureFunction 0
|
|
[1] = ObjectRef 'invisibleInner'
|
|
[2] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[3] = Reserved
|
|
[4] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
|
|
[5] = EndClosureFunctionScope
|
|
[6] = AllocateClosure 0, num-elements: 1, flags: 0
|
|
[7] = Reserved
|
|
}
|
|
Closure DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::invisibleClosure::'invisibleInner' invisible annotations const List<dynamic> [const dart:core::pragma {dart:core::pragma::name (field): 'vm:invisible', dart:core::pragma::options (field): null}]
|
|
() -> Null
|
|
ClosureCode {
|
|
Entry 3
|
|
Push FP[-5]
|
|
LoadClosureElement 0
|
|
PopLocal r0
|
|
CheckStack 0
|
|
PushConstant CP#1
|
|
DirectCall CP#2, 1
|
|
Drop1
|
|
Push r0
|
|
LoadContextVar 0, 0
|
|
StoreLocal r2
|
|
Push r2
|
|
UncheckedClosureCall CP#4, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
|
|
|
|
Function 'main', static, reflectable, debuggable
|
|
parameters [] (required: 0)
|
|
return-type dynamic
|
|
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
}
|
|
|
|
Class 'A', script = 'DART_SDK/pkg/dart2bytecode/testcases/invisible.dart'
|
|
extends dart:core::Object
|
|
|
|
|
|
Function 'visible', constructor, reflectable, debuggable
|
|
parameters [FunctionType () -> void 'fun'] (required: 1)
|
|
return-type DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::A
|
|
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-6]
|
|
DirectCall CP#0, 1
|
|
Drop1
|
|
PushConstant CP#2
|
|
DirectCall CP#3, 1
|
|
Drop1
|
|
Push FP[-5]
|
|
StoreLocal r0
|
|
Push r0
|
|
UncheckedClosureCall CP#5, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = ObjectRef 'A.visible'
|
|
[3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[4] = Reserved
|
|
[5] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
|
|
}
|
|
|
|
|
|
Function 'invisible', constructor, reflectable, debuggable, invisible, has-pragma
|
|
parameters [FunctionType () -> void 'fun'] (required: 1)
|
|
return-type DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::A
|
|
annotations const List<dynamic> [const dart:core::pragma {dart:core::pragma::name (field): 'vm:invisible', dart:core::pragma::options (field): null}]
|
|
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-6]
|
|
DirectCall CP#0, 1
|
|
Drop1
|
|
PushConstant CP#2
|
|
DirectCall CP#3, 1
|
|
Drop1
|
|
Push FP[-5]
|
|
StoreLocal r0
|
|
Push r0
|
|
UncheckedClosureCall CP#5, 1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = ObjectRef 'A.invisible'
|
|
[3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[4] = Reserved
|
|
[5] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
|
|
}
|
|
|