Skip to content

Commit f04ff04

Browse files
aamCommit Queue
authored andcommitted
[vm/shared/bytecode] Support use of vm:shared in bytecode/interpreter.
Fixes #62032 TEST=ci Change-Id: I80600d81ee73b16338a337f7139bf4e898af6eca Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/466124 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
1 parent 18b93ca commit f04ff04

File tree

13 files changed

+234
-35
lines changed

13 files changed

+234
-35
lines changed

pkg/dart2bytecode/docs/bytecode.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ type FieldDeclaration {
524524
hasGetter, hasSetter,
525525
hasInitializer, hasNontrivialInitializer, hasInitializerCode,
526526
hasSourcePositions, hasAnnotations, hasPragma,
527-
hasCustomScript, isExtensionTypeMember);
527+
hasCustomScript, isExtensionTypeMember, isShared);
528528
PackedObject name;
529529
PackedObject type;
530530
@@ -680,7 +680,8 @@ type ClosureDeclaration {
680680
}
681681
682682
type ClosureCode {
683-
UInt flags = (hasExceptionsTable, hasSourcePositions, hasLocalVariables)
683+
UInt flags = (hasExceptionsTable, hasSourcePositions, hasLocalVariables,
684+
capturesOnlyFinalAndSharedVars)
684685
685686
UInt bytecodeSizeInBytes;
686687
Byte[bytecodeSizeInBytes] bytecodes;

pkg/dart2bytecode/lib/bytecode_generator.dart

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,11 @@ class BytecodeGenerator extends RecursiveVisitor {
521521
flags |= FieldDeclaration.hasAnnotationsFlag;
522522
if (annotations.hasPragma) {
523523
flags |= FieldDeclaration.hasPragmaFlag;
524+
if (pragmaParser
525+
.parsedPragmas<ParsedVmSharedPragma>(field.annotations)
526+
.isNotEmpty) {
527+
flags |= FieldDeclaration.isShared;
528+
}
524529
}
525530
}
526531
ObjectHandle? script;
@@ -814,12 +819,28 @@ class BytecodeGenerator extends RecursiveVisitor {
814819
// because it needs to be initialized lazily.
815820
if (_hasNonTrivialInitializer(field)) return true;
816821

822+
// Avoid runtime check of field type as part of (more frequently used)
823+
// non-shared fields inline getter code.
824+
if (pragmaParser
825+
.parsedPragmas<ParsedVmSharedPragma>(field.annotations)
826+
.isNotEmpty) {
827+
return true;
828+
}
829+
817830
// Static late fields with no initializer also need a getter, to check if
818831
// it's been initialized.
819832
return field.isLate && field.initializer == null;
820833
}
821834

822835
bool _needsSetter(Field field) {
836+
// Avoid runtime check of field type as part of (more frequently used)
837+
// non-shared fields inline setter code.
838+
if (pragmaParser
839+
.parsedPragmas<ParsedVmSharedPragma>(field.annotations)
840+
.isNotEmpty) {
841+
return true;
842+
}
843+
823844
// Final fields don't have a setter, except late final fields
824845
// without initializer.
825846
if (field.isFinal) {
@@ -1650,7 +1671,7 @@ class BytecodeGenerator extends RecursiveVisitor {
16501671
currentLoopDepth = 0;
16511672
savedMaxSourcePositions = <int>[];
16521673

1653-
locals = new LocalVariables(node, options, staticTypeContext);
1674+
locals = new LocalVariables(pragmaParser, node, options, staticTypeContext);
16541675
locals.enterScope(node);
16551676

16561677
final int startPosition;
@@ -2487,10 +2508,14 @@ class BytecodeGenerator extends RecursiveVisitor {
24872508
currentLoopDepth = savedLoopDepth;
24882509
asyncTryBlock = savedAsyncTryBlock;
24892510

2511+
bool capturesOnlyFinalAndSharedVars =
2512+
locals.capturesOnlyFinalAndSharedVars;
2513+
24902514
locals.leaveScope();
24912515

24922516
closure.code = new ClosureCode(asm.bytecode, asm.exceptionsTable,
2493-
finalizeSourcePositions(), finalizeLocalVariables());
2517+
finalizeSourcePositions(), finalizeLocalVariables(),
2518+
capturesOnlyFinalAndSharedVars);
24942519

24952520
_popAssemblerState();
24962521

pkg/dart2bytecode/lib/declarations.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ class FieldDeclaration {
361361
static const hasPragmaFlag = 1 << 15;
362362
static const hasCustomScriptFlag = 1 << 16;
363363
static const isExtensionTypeMemberFlag = 1 << 17;
364+
static const isShared = 1 << 18;
364365

365366
final int flags;
366367
final ObjectHandle name;
@@ -491,6 +492,9 @@ class FieldDeclaration {
491492
if ((flags & hasInitializerFlag) != 0) {
492493
sb.write(', has-initializer');
493494
}
495+
if ((flags & isShared) != 0) {
496+
sb.write(', shared');
497+
}
494498
sb.writeln();
495499
if ((flags & hasInitializerCodeFlag) != 0) {
496500
sb.write(' initializer\n$initializerCode\n');
@@ -1158,11 +1162,13 @@ class ClosureCode {
11581162
static const hasExceptionsTableFlag = 1 << 0;
11591163
static const hasSourcePositionsFlag = 1 << 1;
11601164
static const hasLocalVariablesFlag = 1 << 2;
1165+
static const capturesOnlyFinalAndSharedVarsFlag = 1 << 3;
11611166

11621167
final Uint8List bytecodes;
11631168
final ExceptionsTable exceptionsTable;
11641169
final SourcePositions? sourcePositions;
11651170
final LocalVariableTable? localVariables;
1171+
final bool capturesOnlyFinalAndSharedVars;
11661172

11671173
bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
11681174
bool get hasSourcePositions => sourcePositions?.isNotEmpty ?? false;
@@ -1171,10 +1177,11 @@ class ClosureCode {
11711177
int get flags =>
11721178
(hasExceptionsTable ? hasExceptionsTableFlag : 0) |
11731179
(hasSourcePositions ? hasSourcePositionsFlag : 0) |
1174-
(hasLocalVariables ? hasLocalVariablesFlag : 0);
1180+
(hasLocalVariables ? hasLocalVariablesFlag : 0) |
1181+
(capturesOnlyFinalAndSharedVars ? capturesOnlyFinalAndSharedVarsFlag : 0);
11751182

11761183
ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions,
1177-
this.localVariables);
1184+
this.localVariables, this.capturesOnlyFinalAndSharedVars);
11781185

11791186
void write(BufferedWriter writer) {
11801187
writer.writePackedUInt30(flags);
@@ -1202,8 +1209,12 @@ class ClosureCode {
12021209
final localVariables = ((flags & hasLocalVariablesFlag) != 0)
12031210
? reader.readLinkOffset<LocalVariableTable>()
12041211
: null;
1212+
final capturesOnlyFinalAndSharedVars =
1213+
(flags & capturesOnlyFinalAndSharedVarsFlag) != 0;
1214+
12051215
return new ClosureCode(
1206-
bytecodes, exceptionsTable, sourcePositions, localVariables);
1216+
bytecodes, exceptionsTable, sourcePositions, localVariables,
1217+
capturesOnlyFinalAndSharedVars);
12071218
}
12081219

12091220
@override

pkg/dart2bytecode/lib/local_vars.dart

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'dart:math' show min, max;
77
import 'package:kernel/ast.dart';
88
import 'package:kernel/type_environment.dart';
99

10+
import 'package:vm/transformations/pragma.dart';
11+
1012
import 'dbc.dart';
1113
import 'options.dart' show BytecodeOptions;
1214

@@ -157,8 +159,8 @@ class LocalVariables {
157159
List<VariableDeclaration> get sortedNamedParameters =>
158160
_currentFrame.sortedNamedParameters;
159161

160-
LocalVariables(Member node, this.options, this.staticTypeContext) {
161-
final scopeBuilder = new _ScopeBuilder(this);
162+
LocalVariables(PragmaAnnotationParser pragmaParser, Member node, this.options, this.staticTypeContext) {
163+
final scopeBuilder = new _ScopeBuilder(pragmaParser, this);
162164
node.accept(scopeBuilder);
163165

164166
final allocator = new _Allocator(this);
@@ -175,6 +177,9 @@ class LocalVariables {
175177
_currentFrameInternal = _currentScopeInternal?.frame;
176178
}
177179

180+
bool get capturesOnlyFinalAndSharedVars =>
181+
_currentFrame.capturesOnlyFinalAndSharedVars;
182+
178183
void withTemp(TreeNode node, int temp, void action()) {
179184
final old = _temps![node];
180185
assert(old == null || old.length == 1);
@@ -192,16 +197,18 @@ class VarDesc {
192197
final VariableDeclaration declaration;
193198
Scope scope;
194199
bool isCaptured = false;
200+
bool _isShared;
195201
int? index;
196202
int? originalParamSlotIndex;
197203

198-
VarDesc(this.declaration, this.scope) {
204+
VarDesc(this.declaration, this.scope, this._isShared) {
199205
scope.vars.add(this);
200206
}
201207

202208
Frame get frame => scope.frame;
203209

204210
bool get isAllocated => index != null;
211+
bool get isFinalOrShared => declaration.isFinal || _isShared;
205212

206213
void capture() {
207214
assert(!isAllocated);
@@ -243,6 +250,7 @@ class Frame {
243250
int frameSize = 0;
244251
List<int> temporaries = <int>[];
245252
int? contextLevelAtEntry;
253+
bool capturesOnlyFinalAndSharedVars = true;
246254

247255
Frame(this.function, this.parent);
248256

@@ -302,7 +310,9 @@ class _ScopeBuilder extends RecursiveVisitor {
302310
List<TreeNode> _enclosingTryCatches = const [];
303311
int _loopDepth = 0;
304312

305-
_ScopeBuilder(this.locals);
313+
final PragmaAnnotationParser _pragmaParser;
314+
315+
_ScopeBuilder(this._pragmaParser, this.locals);
306316

307317
List<VariableDeclaration> _sortNamedParameters(FunctionNode function) {
308318
final params = function.namedParameters.toList();
@@ -462,7 +472,10 @@ class _ScopeBuilder extends RecursiveVisitor {
462472
if (scope == null) {
463473
scope = _currentScope;
464474
}
465-
final VarDesc v = new VarDesc(variable, scope);
475+
final isShared = _pragmaParser
476+
.parsedPragmas<ParsedVmSharedPragma>(variable.annotations)
477+
.isNotEmpty;
478+
final VarDesc v = new VarDesc(variable, scope, isShared);
466479
assert(locals._vars[variable] == null,
467480
'Double declaring variable ${variable}!');
468481
locals._vars[variable] = v;
@@ -475,6 +488,9 @@ class _ScopeBuilder extends RecursiveVisitor {
475488
}
476489
if (v.frame != _currentFrame) {
477490
v.capture();
491+
if (!v.isFinalOrShared) {
492+
_currentFrame.capturesOnlyFinalAndSharedVars = false;
493+
}
478494
}
479495
}
480496

pkg/vm/lib/transformations/pragma.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const kVmKeepNamePragmaName = "vm:keep-name";
1717
const kVmPlatformConstPragmaName = "vm:platform-const";
1818
const kVmPlatformConstIfPragmaName = "vm:platform-const-if";
1919
const kVmFfiNative = "vm:ffi:native";
20+
const kVmSharedPragmaName = "vm:shared";
2021

2122
// Pragmas recognized by dart2wasm
2223
const kWasmEntryPointPragmaName = "wasm:entry-point";
@@ -91,6 +92,10 @@ class ParsedDynModuleEntryPointPragma implements ParsedPragma {
9192
const ParsedDynModuleEntryPointPragma();
9293
}
9394

95+
class ParsedVmSharedPragma implements ParsedPragma {
96+
const ParsedVmSharedPragma();
97+
}
98+
9499
abstract class PragmaAnnotationParser {
95100
/// May return 'null' if the annotation does not represent a recognized
96101
/// @pragma.
@@ -234,6 +239,8 @@ class ConstantPragmaAnnotationParser implements PragmaAnnotationParser {
234239
return getEntryPointTypeFromOptions(options, pragmaName);
235240
case kDynModuleEntryPointPragmaName:
236241
return const ParsedDynModuleEntryPointPragma();
242+
case kVmSharedPragmaName:
243+
return const ParsedVmSharedPragma();
237244
default:
238245
return null;
239246
}

runtime/vm/bytecode_reader.cc

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "vm/hash.h"
2222
#include "vm/hash_table.h"
2323
#include "vm/longjump.h"
24+
#include "vm/object.h"
2425
#include "vm/object_store.h"
2526
#include "vm/resolver.h"
2627
#include "vm/reusable_handles.h"
@@ -303,9 +304,14 @@ void BytecodeReaderHelper::ReadCode(const Function& function,
303304
(flags & ClosureCode::kHasSourcePositionsFlag) != 0;
304305
const bool has_local_variables =
305306
(flags & ClosureCode::kHasLocalVariablesFlag) != 0;
307+
const bool does_close_over_only_final_and_shared_vars =
308+
(flags & ClosureCode::kCapturesOnlyFinalAndSharedVarsFlag) != 0;
306309

307310
// Read closure bytecode and attach to closure function.
308311
closure_bytecode = ReadBytecode(pool);
312+
313+
closure.set_does_close_over_only_final_and_shared_vars(
314+
does_close_over_only_final_and_shared_vars);
309315
closure.AttachBytecode(closure_bytecode);
310316

311317
ReadExceptionsTable(closure, closure_bytecode, has_exceptions_table);
@@ -1790,6 +1796,7 @@ void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
17901796
const int kHasPragmaFlag = 1 << 15;
17911797
const int kHasCustomScriptFlag = 1 << 16;
17921798
const int kIsExtensionTypeMemberFlag = 1 << 17;
1799+
const int kIsSharedFlag = 1 << 18;
17931800

17941801
const int num_fields = reader_.ReadListLength();
17951802
if ((num_fields == 0) && !cls.is_enum_class()) {
@@ -1818,6 +1825,7 @@ void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
18181825
const bool is_extension_type_member =
18191826
(flags & kIsExtensionTypeMemberFlag) != 0;
18201827
const bool has_initializer = (flags & kHasInitializerFlag) != 0;
1828+
const bool is_shared = (flags & kIsSharedFlag) != 0;
18211829

18221830
name ^= ReadObject();
18231831
type ^= ReadObject();
@@ -1848,6 +1856,7 @@ void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
18481856
field.set_is_extension_member(is_extension_member);
18491857
field.set_is_extension_type_member(is_extension_type_member);
18501858
field.set_has_initializer(has_initializer);
1859+
field.set_is_shared(is_shared);
18511860

18521861
if (!has_nontrivial_initializer) {
18531862
value = ReadObject();
@@ -1895,15 +1904,20 @@ void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
18951904
function.set_is_extension_type_member(is_extension_type_member);
18961905
SetupFieldAccessorFunction(cls, function, type);
18971906
if (is_static) {
1898-
function.AttachBytecode(Object::implicit_static_getter_bytecode());
1907+
if (is_shared) {
1908+
function.AttachBytecode(
1909+
Object::implicit_shared_static_getter_bytecode());
1910+
} else {
1911+
function.AttachBytecode(Object::implicit_static_getter_bytecode());
1912+
}
18991913
} else {
19001914
function.AttachBytecode(Object::implicit_getter_bytecode());
19011915
}
19021916
functions_->SetAt(function_index_++, function);
19031917
}
19041918

19051919
if ((flags & kHasSetterFlag) != 0) {
1906-
ASSERT(is_late || ((!is_static) && (!is_final)));
1920+
ASSERT(is_late || ((!is_static) && (!is_final)) || is_shared);
19071921
ASSERT(!is_const);
19081922
name ^= ReadObject();
19091923
const auto& signature = FunctionType::Handle(Z, FunctionType::New());
@@ -1922,7 +1936,12 @@ void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
19221936
function.set_is_extension_type_member(is_extension_type_member);
19231937
SetupFieldAccessorFunction(cls, function, type);
19241938
if (is_static) {
1925-
function.AttachBytecode(Object::implicit_static_setter_bytecode());
1939+
if (is_shared) {
1940+
function.AttachBytecode(
1941+
Object::implicit_shared_static_setter_bytecode());
1942+
} else {
1943+
function.AttachBytecode(Object::implicit_static_setter_bytecode());
1944+
}
19261945
} else {
19271946
function.AttachBytecode(Object::implicit_setter_bytecode());
19281947
}

runtime/vm/bytecode_reader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ class BytecodeReaderHelper : public ValueObject {
308308
static const int kHasExceptionsTableFlag = 1 << 0;
309309
static const int kHasSourcePositionsFlag = 1 << 1;
310310
static const int kHasLocalVariablesFlag = 1 << 2;
311+
static const int kCapturesOnlyFinalAndSharedVarsFlag = 1 << 3;
311312
};
312313

313314
// Parameter flags, must be in sync with ParameterFlags constants in

runtime/vm/constants_kbc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ namespace dart {
220220
V(VMInternal_ImplicitGetter, 0, ORDN, ___, ___, ___) \
221221
V(VMInternal_ImplicitSetter, 0, ORDN, ___, ___, ___) \
222222
V(VMInternal_ImplicitStaticGetter, 0, ORDN, ___, ___, ___) \
223+
V(VMInternal_ImplicitSharedStaticGetter, 0, ORDN, ___, ___, ___) \
223224
V(VMInternal_ImplicitStaticSetter, 0, ORDN, ___, ___, ___) \
225+
V(VMInternal_ImplicitSharedStaticSetter, 0, ORDN, ___, ___, ___) \
224226
V(VMInternal_MethodExtractor, 0, ORDN, ___, ___, ___) \
225227
V(VMInternal_InvokeClosure, 0, ORDN, ___, ___, ___) \
226228
V(VMInternal_InvokeField, 0, ORDN, ___, ___, ___) \

0 commit comments

Comments
 (0)