mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 17:04:56 +00:00
[vm/compiler] Make TemplateLoadField::CanCallDart more precise.
Only return true if the stub being invoked will call the
initializer function directly. Notably, return false if the stub
just calls the runtime.
This removes some write barriers in legacy code that were added
after 37d45743
.
TEST=New asserts that check CanCallDart() is false when calling runtime
and is true when calling stubs that call initializer functions
directly, combined with legacy code tests that use non-late fields.
Change-Id: I4118968b6ea42371d068c35d50339574939556e5
Bug: b/208619946
Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-linux-release-ia32-try,vm-kernel-linux-release-x64-try,vm-kernel-nnbd-linux-release-ia32-try,vm-kernel-nnbd-linux-release-simarm-try,vm-kernel-nnbd-linux-release-simarm64-try,vm-kernel-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-release-simarm64-try,vm-kernel-precomp-nnbd-linux-release-simarm_x64-try,vm-kernel-precomp-nnbd-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221943
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
This commit is contained in:
parent
285eea9338
commit
da9b3409e6
|
@ -4203,11 +4203,13 @@ void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
auto& stub = Code::ZoneHandle(compiler->zone());
|
||||
__ Bind(&call_initializer);
|
||||
if (field().needs_load_guard()) {
|
||||
ASSERT(!CanCallDart());
|
||||
stub = object_store->init_static_field_stub();
|
||||
} else if (field().is_late()) {
|
||||
// The stubs below call the initializer function directly, so make sure
|
||||
// one is created.
|
||||
original_field.EnsureInitializerFunction();
|
||||
ASSERT(CanCallDart());
|
||||
stub = field().is_final()
|
||||
? object_store->init_late_final_static_field_stub()
|
||||
: object_store->init_late_static_field_stub();
|
||||
|
@ -4215,6 +4217,7 @@ void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
// We call to runtime for non-late fields because the stub would need to
|
||||
// catch any exception generated by the initialization function to change
|
||||
// the value of the static field from the transition sentinel to null.
|
||||
ASSERT(!CanCallDart());
|
||||
stub = object_store->init_static_field_stub();
|
||||
}
|
||||
|
||||
|
@ -4257,16 +4260,19 @@ void LoadFieldInstr::EmitNativeCodeForInitializerCall(
|
|||
auto object_store = compiler->isolate_group()->object_store();
|
||||
auto& stub = Code::ZoneHandle(compiler->zone());
|
||||
if (field.needs_load_guard()) {
|
||||
ASSERT(!CanCallDart());
|
||||
stub = object_store->init_instance_field_stub();
|
||||
} else if (field.is_late()) {
|
||||
if (!field.has_nontrivial_initializer()) {
|
||||
// Common stub calls runtime which will throw an exception.
|
||||
ASSERT(!CanCallDart());
|
||||
stub = object_store->init_instance_field_stub();
|
||||
} else {
|
||||
// Stubs for late field initialization call initializer
|
||||
// function directly, so make sure one is created.
|
||||
original_field.EnsureInitializerFunction();
|
||||
|
||||
ASSERT(CanCallDart());
|
||||
if (field.is_final()) {
|
||||
stub = object_store->init_late_final_instance_field_stub();
|
||||
} else {
|
||||
|
|
|
@ -5596,15 +5596,15 @@ class TemplateLoadField : public TemplateDefinition<N, Throws> {
|
|||
const Field* field = nullptr)
|
||||
: Base(source, deopt_id),
|
||||
token_pos_(source.token_pos),
|
||||
calls_initializer_(calls_initializer),
|
||||
throw_exception_on_initialization_(false) {
|
||||
calls_runtime_on_initialization_(
|
||||
field != nullptr &&
|
||||
(!field->is_late() || field->needs_load_guard())),
|
||||
throw_exception_on_initialization_(field != nullptr &&
|
||||
!field->has_initializer() &&
|
||||
!calls_runtime_on_initialization_),
|
||||
calls_initializer_(calls_initializer) {
|
||||
ASSERT(!calls_initializer || field != nullptr);
|
||||
ASSERT(!calls_initializer || (deopt_id != DeoptId::kNone));
|
||||
if (calls_initializer_) {
|
||||
ASSERT(field != nullptr);
|
||||
throw_exception_on_initialization_ = !field->needs_load_guard() &&
|
||||
field->is_late() &&
|
||||
!field->has_initializer();
|
||||
}
|
||||
}
|
||||
|
||||
virtual TokenPosition token_pos() const { return token_pos_; }
|
||||
|
@ -5634,15 +5634,17 @@ class TemplateLoadField : public TemplateDefinition<N, Throws> {
|
|||
}
|
||||
|
||||
virtual bool CanCallDart() const {
|
||||
return calls_initializer() && !throw_exception_on_initialization();
|
||||
return calls_initializer() && !throw_exception_on_initialization() &&
|
||||
!calls_runtime_on_initialization_;
|
||||
}
|
||||
virtual bool CanTriggerGC() const { return calls_initializer(); }
|
||||
virtual bool MayThrow() const { return calls_initializer(); }
|
||||
|
||||
private:
|
||||
const TokenPosition token_pos_;
|
||||
const bool calls_runtime_on_initialization_;
|
||||
const bool throw_exception_on_initialization_;
|
||||
bool calls_initializer_;
|
||||
bool throw_exception_on_initialization_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TemplateLoadField);
|
||||
};
|
||||
|
|
|
@ -61,8 +61,7 @@ void StubCodeCompiler::GenerateInitLateStaticFieldStub(Assembler* assembler,
|
|||
__ Comment("Calling initializer function");
|
||||
__ PushRegister(kFieldReg);
|
||||
__ LoadCompressedFieldFromOffset(
|
||||
kFunctionReg, InitInstanceFieldABI::kFieldReg,
|
||||
target::Field::initializer_function_offset());
|
||||
kFunctionReg, kFieldReg, target::Field::initializer_function_offset());
|
||||
if (!FLAG_precompiled_mode) {
|
||||
__ LoadCompressedFieldFromOffset(CODE_REG, kFunctionReg,
|
||||
target::Function::code_offset());
|
||||
|
|
Loading…
Reference in a new issue