[vm/concurrency] Remove usage of current isolate field state from compiler

As part of making the compiler independent of the current isolate (since
JITed code will be shared across all isolate) we make the compiler not
depend on global field state, with one exception: we preserve an existing
optimization that utilizes knowledge whether a global final field was
already initialized (if --enable-isolate-groups is turned off) - we do
so by asking the isolate group for it's own isolate member.

Issue https://github.com/dart-lang/sdk/issues/36097

TEST=Refactoring of existing code.

Change-Id: I2f08d854af6102e05e5a1df8d5b66b514d6f3ce4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182540
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Martin Kustermann 2021-02-04 15:54:27 +00:00 committed by commit-bot@chromium.org
parent 6ce8d74761
commit 5f78a23bb9
6 changed files with 31 additions and 29 deletions

View file

@ -854,8 +854,8 @@ void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) {
if (!FLAG_fields_may_be_reset) {
const Field& field = instr->field();
ASSERT(field.is_static());
if (field.is_final() && instr->IsFieldInitialized()) {
Instance& obj = Instance::Handle(Z, field.StaticValue());
auto& obj = Instance::Handle(Z);
if (field.is_final() && instr->IsFieldInitialized(&obj)) {
if (obj.IsSmi() || (obj.IsOld() && obj.IsCanonical())) {
SetValue(instr, obj);
return;

View file

@ -1135,10 +1135,32 @@ bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const {
return field().ptr() == other->AsLoadStaticField()->field().ptr();
}
bool LoadStaticFieldInstr::IsFieldInitialized() const {
bool LoadStaticFieldInstr::IsFieldInitialized(Instance* field_value) const {
if (FLAG_fields_may_be_reset) {
return false;
}
// Since new isolates will be spawned, the JITed code cannot depend on whether
// global field was initialized when running with --enable-isolate-groups.
if (IsolateGroup::AreIsolateGroupsEnabled()) return false;
const Field& field = this->field();
return (field.StaticValue() != Object::sentinel().ptr()) &&
(field.StaticValue() != Object::transition_sentinel().ptr());
Isolate* only_isolate = IsolateGroup::Current()->FirstIsolate();
if (only_isolate == nullptr) {
// This can happen if background compiler executes this code but the mutator
// is being shutdown and the isolate was already unregistered from the group
// (and is trying to stop this BG compiler).
if (field_value != nullptr) {
*field_value = Object::sentinel().ptr();
}
return false;
}
if (field_value == nullptr) {
field_value = &Instance::Handle();
}
*field_value = only_isolate->field_table()->At(field.field_id());
return (field_value->ptr() != Object::sentinel().ptr()) &&
(field_value->ptr() != Object::transition_sentinel().ptr());
}
Definition* LoadStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
@ -1146,8 +1168,7 @@ Definition* LoadStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
// make it safe to omit code that checks if the field needs initialization
// because the field will be reset so it starts uninitialized in the process
// running the precompiled code. We must be prepared to reinitialize fields.
if (calls_initializer() && !FLAG_fields_may_be_reset &&
IsFieldInitialized()) {
if (calls_initializer() && IsFieldInitialized()) {
set_calls_initializer(false);
}
return this;

View file

@ -5543,7 +5543,7 @@ class LoadStaticFieldInstr : public TemplateDefinition<0, Throws> {
virtual CompileType ComputeType() const;
const Field& field() const { return field_; }
bool IsFieldInitialized() const;
bool IsFieldInitialized(Instance* field_value = nullptr) const;
bool calls_initializer() const { return calls_initializer_; }
void set_calls_initializer(bool value) { calls_initializer_ = value; }

View file

@ -1446,9 +1446,9 @@ CompileType LoadStaticFieldInstr::ComputeType() const {
AbstractType* abstract_type = &AbstractType::ZoneHandle(field.type());
TraceStrongModeType(this, *abstract_type);
ASSERT(field.is_static());
const bool is_initialized = IsFieldInitialized() && !FLAG_fields_may_be_reset;
auto& obj = Instance::Handle();
const bool is_initialized = IsFieldInitialized(&obj);
if (field.is_final() && is_initialized) {
const Instance& obj = Instance::Handle(field.StaticValue());
if (!obj.IsNull()) {
is_nullable = CompileType::kNonNullable;
cid = obj.GetClassId();

View file

@ -70,20 +70,6 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
B->last_used_block_id_, prologue_info);
}
void StreamingFlowGraphBuilder::EvaluateConstFieldValue(const Field& field) {
ASSERT(field.is_const() && field.IsUninitialized());
FieldHelper field_helper(this);
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
Tag initializer_tag = ReadTag(); // read first part of initializer.
ASSERT(initializer_tag == kSomething);
Instance& value =
Instance::Handle(Z, constant_reader_.ReadConstantExpression());
field.SetStaticValue(value);
}
void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
intptr_t optional_parameter_count =
parsed_function()->function().NumOptionalParameters();
@ -1024,10 +1010,6 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraph() {
case UntaggedFunction::kImplicitGetter:
case UntaggedFunction::kImplicitStaticGetter:
case UntaggedFunction::kImplicitSetter: {
const Field& field = Field::Handle(Z, function.accessor_field());
if (field.is_const() && field.IsUninitialized()) {
EvaluateConstFieldValue(field);
}
return B->BuildGraphOfFieldAccessor(function);
}
case UntaggedFunction::kFieldInitializer:

View file

@ -59,7 +59,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
void ParseKernelASTFunction();
void ReadForwardingStubTarget(const Function& function);
void EvaluateConstFieldValue(const Field& field);
void SetupDefaultParameterValues();
FlowGraph* BuildGraphOfFieldInitializer();