Skip to content

Commit 7e28ecc

Browse files
mkustermanncommit-bot@chromium.org
authored andcommitted
[vm/concurrency] Avoid calling into Dart code for evaluation of enum constants
There is no need to call from C++ into Dart code just so the Dart code can return a constant. Instead we can get the constant directly in C++ code. This avoids calling into Dart code during class finalization to evaluate enum constants. Issue #36097 Change-Id: Ia0b09482188be2d0ce83ce9ffc20e5c15e52d070 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170540 Commit-Queue: Martin Kustermann <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 4c7740a commit 7e28ecc

File tree

6 files changed

+68
-8
lines changed

6 files changed

+68
-8
lines changed

runtime/vm/compiler/frontend/constant_reader.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ ConstantReader::ConstantReader(KernelReaderHelper* helper,
1919
script_(helper->script()),
2020
result_(Instance::Handle(zone_)) {}
2121

22+
InstancePtr ConstantReader::ReadConstantInitializer() {
23+
Tag tag = helper_->ReadTag(); // read tag.
24+
switch (tag) {
25+
case kSomething:
26+
return ReadConstantExpression();
27+
default:
28+
H.ReportError(script_, TokenPosition::kNoSource,
29+
"Not a constant expression: unexpected kernel tag %s (%d)",
30+
Reader::TagName(tag), tag);
31+
}
32+
return result_.raw();
33+
}
34+
2235
InstancePtr ConstantReader::ReadConstantExpression() {
2336
Tag tag = helper_->ReadTag(); // read tag.
2437
switch (tag) {

runtime/vm/compiler/frontend/constant_reader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ConstantReader {
2323

2424
virtual ~ConstantReader() {}
2525

26+
InstancePtr ReadConstantInitializer();
2627
InstancePtr ReadConstantExpression();
2728
ObjectPtr ReadAnnotations();
2829

runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
3333
FieldHelper field_helper(this);
3434
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
3535

36+
// Constants are directly accessed at use sites of Dart code. In C++ - if
37+
// we need to access static constants - we do so directly using the kernel
38+
// evaluation instead of invoking the initializer function in Dart code.
39+
//
40+
// If the field is marked as @pragma('vm:entry-point') then the embedder might
41+
// invoke the getter, so we'll generate the initializer function.
42+
ASSERT(!field_helper.IsConst() ||
43+
Field::Handle(Z, parsed_function()->function().accessor_field())
44+
.VerifyEntryPoint(EntryPointPragma::kGetterOnly) ==
45+
Error::null());
46+
3647
Tag initializer_tag = ReadTag(); // read first part of initializer.
3748
if (initializer_tag != kSomething) {
3849
UNREACHABLE();
@@ -45,14 +56,8 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
4556

4657
Fragment body(normal_entry);
4758
body += B->CheckStackOverflowInPrologue(field_helper.position_);
48-
if (field_helper.IsConst()) {
49-
// This will read the initializer.
50-
body += Constant(
51-
Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
52-
} else {
53-
body += SetupCapturedParameters(parsed_function()->function());
54-
body += BuildExpression(); // read initializer.
55-
}
59+
body += SetupCapturedParameters(parsed_function()->function());
60+
body += BuildExpression(); // read initializer.
5661
body += Return(TokenPosition::kNoSource);
5762

5863
PrologueInfo prologue_info(-1, -1);

runtime/vm/kernel.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,38 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
347347
script.set_debug_positions(array_object);
348348
}
349349

350+
ObjectPtr EvaluateStaticConstFieldInitializer(const Field& field) {
351+
ASSERT(field.is_static() && field.is_const());
352+
353+
LongJumpScope jump;
354+
if (setjmp(*jump.Set()) == 0) {
355+
Thread* thread = Thread::Current();
356+
Zone* zone = thread->zone();
357+
TranslationHelper helper(thread);
358+
Script& script = Script::Handle(zone, field.Script());
359+
helper.InitFromScript(script);
360+
361+
const Class& owner_class = Class::Handle(zone, field.Owner());
362+
ActiveClass active_class;
363+
ActiveClassScope active_class_scope(&active_class, &owner_class);
364+
365+
KernelReaderHelper kernel_reader(
366+
zone, &helper, script,
367+
ExternalTypedData::Handle(zone, field.KernelData()),
368+
field.KernelDataProgramOffset());
369+
kernel_reader.SetOffset(field.kernel_offset());
370+
ConstantReader constant_reader(&kernel_reader, &active_class);
371+
372+
FieldHelper field_helper(&kernel_reader);
373+
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
374+
ASSERT(field_helper.IsConst());
375+
376+
return constant_reader.ReadConstantInitializer();
377+
} else {
378+
return Thread::Current()->StealStickyError();
379+
}
380+
}
381+
350382
class MetadataEvaluator : public KernelReaderHelper {
351383
public:
352384
MetadataEvaluator(Zone* zone,

runtime/vm/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ class KernelLineStartsReader {
195195

196196
void CollectTokenPositionsFor(const Script& script);
197197

198+
ObjectPtr EvaluateStaticConstFieldInitializer(const Field& field);
198199
ObjectPtr EvaluateMetadata(const Field& metadata_field,
199200
bool is_annotations_offset);
200201
ObjectPtr BuildParameterDescriptor(const Function& function);

runtime/vm/object.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10611,6 +10611,14 @@ ErrorPtr Field::InitializeStatic() const {
1061110611
ObjectPtr Field::EvaluateInitializer() const {
1061210612
Thread* const thread = Thread::Current();
1061310613
ASSERT(thread->IsMutatorThread());
10614+
10615+
#if !defined(DART_PRECOMPILED_RUNTIME)
10616+
if (is_static() && is_const()) {
10617+
ASSERT(!FLAG_precompiled_mode);
10618+
return kernel::EvaluateStaticConstFieldInitializer(*this);
10619+
}
10620+
#endif // !defined(DART_PRECOMPILED_RUNTIME)
10621+
1061410622
NoOOBMessageScope no_msg_scope(thread);
1061510623
NoReloadScope no_reload_scope(thread->isolate(), thread);
1061610624
const Function& initializer = Function::Handle(EnsureInitializerFunction());

0 commit comments

Comments
 (0)