Flutter Engine
The Flutter Engine
slot_test.cc
Go to the documentation of this file.
1// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "include/dart_api.h"
6
7#include "platform/globals.h"
8
11#include "vm/object.h"
12#include "vm/parser.h"
13#include "vm/symbols.h"
14#include "vm/unit_test.h"
15
16namespace dart {
17
18// This is a regression test for b/121271056: there might be a race between
19// background compiler and mutator where mutator changes guarded state of
20// the field after Slot was created from it. A situation is possible where we
21// have a clone of a field with its guarded state set to unknown, however
22// Slot::Get for this field returns a Slot created from the previous clone of
23// the same field with a known guarded state. In this case we must add *old*
24// clone from which the Slot was created to guarded fields and not the new
25// clone, because new clone has no guarded state to begin with and thus
26// ParsedFunction::AddToGuardedFields(...) would simply ignore it.
27// Such slots with inconsistent guarded state that are not in the current
28// list of guarded fields arise due to unsuccessful inlining attempts.
29// If we built and discard the graph, then guarded fields associated with
30// that graph are also discarded. However the slot itself stays behind in
31// the global cache.
32// Adding old clone would lead to correct rejection of the compilation
33// attempt because Slot type information is different from the current guarded
34// state of the field.
35TEST_CASE(SlotFromGuardedField) {
36 if (!FLAG_use_field_guards) {
37 return;
38 }
39
40 TransitionNativeToVM transition(thread);
41 Zone* zone = thread->zone();
42
43 // Setup: create dummy class, function and a field.
44 const Class& dummy_class = Class::Handle(Class::New(
45 Library::Handle(), String::Handle(Symbols::New(thread, "DummyClass")),
46 Script::Handle(), TokenPosition::kNoSource));
48
50 const Function& dummy_function = Function::ZoneHandle(
51 Function::New(signature, String::Handle(Symbols::New(thread, "foo")),
52 UntaggedFunction::kRegularFunction, false, false, false,
53 false, false, dummy_class, TokenPosition::kMinSource));
54
55 const Field& field = Field::Handle(
56 Field::New(String::Handle(Symbols::New(thread, "field")),
57 /*is_static=*/false, /*is_final=*/false, /*is_const=*/false,
58 /*is_reflectable=*/true, /*is_late=*/false, dummy_class,
59 Object::dynamic_type(), TokenPosition::kMinSource,
61
62 // Set non-trivial guarded state on the field.
63 field.set_guarded_cid_unsafe(kSmiCid);
64 field.set_is_nullable_unsafe(false);
65
66 // Enter compiler state.
67 CompilerState compiler_state(thread, /*is_aot=*/false,
68 /*is_optimizing=*/true);
69
70 const Field& field_clone_1 = Field::ZoneHandle(field.CloneFromOriginal());
71 const Field& field_clone_2 = Field::ZoneHandle(field.CloneFromOriginal());
72
73 // Check that Slot::Get() returns correctly canonicalized and configured
74 // slot that matches properties of the field.
75 ParsedFunction* parsed_function =
76 new (zone) ParsedFunction(thread, dummy_function);
77 const Slot& slot1 = Slot::Get(field_clone_1, parsed_function);
78 const Slot& slot2 = Slot::Get(field_clone_2, parsed_function);
79 EXPECT_EQ(&slot1, &slot2);
80 EXPECT(slot1.is_guarded_field());
81 EXPECT(!slot1.type().is_nullable());
82 EXPECT_EQ(kSmiCid, slot1.type().ToCid());
83
84 // Check that the field was added (once) to the list of guarded fields.
85 EXPECT_EQ(1, parsed_function->guarded_fields()->Length());
86 EXPECT(parsed_function->guarded_fields()->HasKey(&field_clone_1));
87
88 // Change the guarded state of the field to "unknown" - emulating concurrent
89 // modification of the guarded state in mutator) and create a new clone of
90 // the field.
92 field.set_is_nullable_unsafe(true);
93 const Field& field_clone_3 = Field::ZoneHandle(field.CloneFromOriginal());
94
95 // Slot::Get must return the same slot and add the field from which it
96 // was created to the guarded fields list.
97 ParsedFunction* parsed_function2 =
98 new (zone) ParsedFunction(thread, dummy_function);
99 const Slot& slot3 = Slot::Get(field_clone_3, parsed_function2);
100 EXPECT_EQ(&slot1, &slot3);
101 EXPECT_EQ(1, parsed_function2->guarded_fields()->Length());
102 EXPECT(parsed_function2->guarded_fields()->HasKey(&field_clone_1));
103}
104
105} // namespace dart
#define EXPECT(type, expectedAlignment, expectedSize)
intptr_t Length() const
Definition: hash_map.h:27
bool HasKey(typename KeyValueTrait::Key key) const
Definition: hash_map.h:52
void set_is_synthesized_class_unsafe() const
Definition: object.cc:5651
static ClassPtr New(IsolateGroup *isolate_group, bool register_class=true)
Definition: object.cc:3053
bool is_nullable() const
Definition: compile_type.h:76
void set_is_nullable_unsafe(bool val) const
Definition: object.h:4762
FieldPtr CloneFromOriginal() const
Definition: object.cc:11735
void set_guarded_cid_unsafe(intptr_t cid) const
Definition: object.h:4665
static FunctionTypePtr New(intptr_t num_parent_type_arguments=0, Nullability nullability=Nullability::kNonNullable, Heap::Space space=Heap::kOld)
Definition: object.cc:11631
static FunctionPtr New(const FunctionType &signature, const String &name, UntaggedFunction::Kind kind, bool is_static, bool is_const, bool is_abstract, bool is_external, bool is_native, const Object &owner, TokenPosition token_pos, Heap::Space space=Heap::kOld)
Definition: object.cc:10243
static Object & Handle()
Definition: object.h:407
static Object & ZoneHandle()
Definition: object.h:419
const FieldSet * guarded_fields() const
Definition: parser.h:191
bool is_guarded_field() const
Definition: slot.h:527
static const Slot & Get(const Field &field, const ParsedFunction *parsed_function)
Definition: slot.cc:351
CompileType type() const
Definition: slot.h:538
static StringPtr New(Thread *thread, const char *cstr)
Definition: symbols.h:723
static const TokenPosition kMinSource
Definition: dart_vm.cc:33
@ kDynamicCid
Definition: class_id.h:253
TEST_CASE(DirectoryCurrent)