mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:48:25 +00:00
[VM/AOT] Fix handling of errors from compiling static initializers
* CompileStaticInitializer() should check result of Compile() and should not leave sticky error. If left, this sticky error could be picked up by compilation of some unrelated static initializer. Also, assertions are added to make sure that code which explicitly or implicitly relies on sticky errors is not getting an error on entry. * CompileStaticInitializerIgnoreErrors() clears sticky errors to ignore them. * Added inline bailout reason for cyclic static fields. This guards against inlining of code which uses a field into static initializer. This code might not be called so it should not trigger compilation error eagerly. Change-Id: I52da6f4cd05556125fd1a628b665dcc11621a4f7 Reviewed-on: https://dart-review.googlesource.com/28523 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
2aed87a133
commit
73b265e348
|
@ -417,6 +417,7 @@ void Precompiler::DoCompileAll(
|
|||
// can be used. Also ensures lookup of entry points won't miss functions
|
||||
// because their class hasn't been finalized yet.
|
||||
FinalizeAllClasses();
|
||||
ASSERT(Error::Handle(Z, T->sticky_error()).IsNull());
|
||||
|
||||
ClassFinalizer::SortClasses();
|
||||
TypeRangeCache trc(this, T, I->class_table()->NumCids());
|
||||
|
@ -424,6 +425,7 @@ void Precompiler::DoCompileAll(
|
|||
|
||||
// Precompile static initializers to compute result type information.
|
||||
PrecompileStaticInitializers();
|
||||
ASSERT(Error::Handle(Z, T->sticky_error()).IsNull());
|
||||
|
||||
// Precompile constructors to compute type information for final fields.
|
||||
ClassFinalizer::ClearAllCode();
|
||||
|
@ -526,6 +528,9 @@ void Precompiler::DoCompileAll(
|
|||
}
|
||||
|
||||
static void CompileStaticInitializerIgnoreErrors(const Field& field) {
|
||||
ASSERT(Error::Handle(Thread::Current()->zone(),
|
||||
Thread::Current()->sticky_error())
|
||||
.IsNull());
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
const Function& initializer =
|
||||
|
@ -538,7 +543,11 @@ static void CompileStaticInitializerIgnoreErrors(const Field& field) {
|
|||
} else {
|
||||
// Ignore compile-time errors here. If the field is actually used,
|
||||
// the error will be reported later during Iterate().
|
||||
Thread::Current()->clear_sticky_error();
|
||||
}
|
||||
ASSERT(Error::Handle(Thread::Current()->zone(),
|
||||
Thread::Current()->sticky_error())
|
||||
.IsNull());
|
||||
}
|
||||
|
||||
void Precompiler::PrecompileStaticInitializers() {
|
||||
|
@ -1419,6 +1428,7 @@ RawFunction* Precompiler::CompileStaticInitializer(const Field& field,
|
|||
Thread* thread = Thread::Current();
|
||||
StackZone stack_zone(thread);
|
||||
Zone* zone = stack_zone.GetZone();
|
||||
ASSERT(Error::Handle(zone, thread->sticky_error()).IsNull());
|
||||
|
||||
ParsedFunction* parsed_function;
|
||||
// Check if this field is coming from the Kernel binary.
|
||||
|
@ -1433,7 +1443,12 @@ RawFunction* Precompiler::CompileStaticInitializer(const Field& field,
|
|||
PrecompileParsedFunctionHelper helper(/* precompiler = */ NULL,
|
||||
parsed_function,
|
||||
/* optimized = */ true);
|
||||
helper.Compile(&pipeline);
|
||||
if (!helper.Compile(&pipeline)) {
|
||||
Error& error = Error::Handle(zone, thread->sticky_error());
|
||||
ASSERT(!error.IsNull());
|
||||
Jump(error);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (compute_type && field.is_final()) {
|
||||
intptr_t result_cid = pipeline.result_type().ToCid();
|
||||
|
@ -1454,6 +1469,8 @@ RawFunction* Precompiler::CompileStaticInitializer(const Field& field,
|
|||
Disassembler::DisassembleCode(parsed_function->function(), code,
|
||||
/* optimized = */ true);
|
||||
}
|
||||
|
||||
ASSERT(Error::Handle(zone, thread->sticky_error()).IsNull());
|
||||
return parsed_function->function().raw();
|
||||
}
|
||||
|
||||
|
|
|
@ -2517,6 +2517,7 @@ bool StreamingConstantEvaluator::IsCached(intptr_t offset) {
|
|||
|
||||
Instance& StreamingConstantEvaluator::EvaluateExpression(intptr_t offset,
|
||||
bool reset_position) {
|
||||
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
|
||||
if (!GetCachedConstant(offset, &result_)) {
|
||||
ASSERT(IsAllowedToEvaluate());
|
||||
intptr_t original_offset = builder_->ReaderOffset();
|
||||
|
@ -2784,12 +2785,16 @@ void StreamingConstantEvaluator::EvaluateStaticGet() {
|
|||
NameIndex target =
|
||||
builder_->ReadCanonicalNameReference(); // read target_reference.
|
||||
|
||||
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
|
||||
|
||||
if (H.IsField(target)) {
|
||||
const Field& field = Field::Handle(Z, H.LookupFieldByKernelField(target));
|
||||
if (!field.is_const()) {
|
||||
H.ReportError(script_, position, "Not a constant field.");
|
||||
}
|
||||
if (field.StaticValue() == Object::transition_sentinel().raw()) {
|
||||
builder_->InlineBailout(
|
||||
"kernel::StreamingConstantEvaluator::EvaluateStaticGet::Cyclic");
|
||||
H.ReportError(script_, position, "Not a constant expression.");
|
||||
} else if (field.StaticValue() == Object::sentinel().raw()) {
|
||||
field.SetStaticValue(Object::transition_sentinel());
|
||||
|
@ -3634,6 +3639,7 @@ void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
|
|||
|
||||
Fragment StreamingFlowGraphBuilder::BuildFieldInitializer(
|
||||
NameIndex canonical_name) {
|
||||
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
|
||||
Field& field =
|
||||
Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
|
||||
if (PeekTag() == kNullLiteral) {
|
||||
|
@ -3651,6 +3657,7 @@ Fragment StreamingFlowGraphBuilder::BuildFieldInitializer(
|
|||
|
||||
Fragment StreamingFlowGraphBuilder::BuildInitializers(
|
||||
const Class& parent_class) {
|
||||
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
|
||||
Fragment instructions;
|
||||
|
||||
// Start by getting the position of the constructors initializer.
|
||||
|
@ -4298,6 +4305,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(bool constructor) {
|
|||
}
|
||||
|
||||
FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) {
|
||||
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
|
||||
const Function& function = parsed_function()->function();
|
||||
|
||||
// Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
|
||||
|
@ -6337,6 +6345,7 @@ Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) {
|
|||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
|
||||
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
|
||||
intptr_t offset = ReaderOffset() - 1; // Include the tag.
|
||||
|
||||
TokenPosition position = ReadPosition(); // read position.
|
||||
|
|
|
@ -1206,7 +1206,6 @@ cyclic_type_variable_test/03: Crash
|
|||
cyclic_type_variable_test/04: Crash
|
||||
cyclic_type_variable_test/none: Crash
|
||||
external_test/13: Crash
|
||||
final_syntax_test/09: Crash
|
||||
optional_named_parameters_test/06: Crash
|
||||
optional_named_parameters_test/08: Crash
|
||||
regress_29025_test: Crash
|
||||
|
@ -1521,7 +1520,6 @@ const_constructor2_test/12: CompileTimeError # Issue 31402 (Invocation arguments
|
|||
const_constructor2_test/20: MissingCompileTimeError
|
||||
const_constructor2_test/22: MissingCompileTimeError
|
||||
const_constructor2_test/24: MissingCompileTimeError
|
||||
const_constructor3_test/04: Crash # kernel_binary_flowgraph.cc: 2857: error: expected: !function.IsNull()
|
||||
const_constructor_nonconst_field_test/01: MissingCompileTimeError # Fasta bug: Non-const expression in field initializer.
|
||||
const_dynamic_type_literal_test/02: MissingCompileTimeError
|
||||
const_dynamic_type_literal_test/02: RuntimeError # KernelVM bug: Constant map duplicated key.
|
||||
|
@ -1538,8 +1536,7 @@ const_native_factory_test: MissingCompileTimeError
|
|||
const_native_factory_test/01: MissingCompileTimeError # Fasta bug: Issue 29763
|
||||
const_nested_test: RuntimeError # KernelVM bug: Constant evaluation.
|
||||
const_optional_args_test/01: MissingCompileTimeError # Fasta bug: Default parameter values must be const.
|
||||
const_redirecting_factory_test: Crash # kernel_binary_flowgraph.cc: 2857: error: expected: !function.IsNull(); previous error: CompileTimeError # Issue 31402 (Field declaration)
|
||||
|
||||
const_redirecting_factory_test: CompileTimeError # Issue 31402 (Field declaration)
|
||||
const_switch2_test/01: MissingCompileTimeError # KernelVM bug: Constant evaluation.
|
||||
const_syntax_test/05: MissingCompileTimeError # KernelVM bug: Constant evaluation.
|
||||
const_types_test/01: MissingCompileTimeError
|
||||
|
@ -1704,7 +1701,6 @@ final_attempt_reinitialization_test/02: MissingCompileTimeError # Issue 29900
|
|||
final_for_in_variable_test: MissingCompileTimeError
|
||||
final_param_test: MissingCompileTimeError
|
||||
final_super_field_set_test: MissingCompileTimeError
|
||||
final_syntax_test/09: Crash
|
||||
final_variable_assignment_test/01: MissingCompileTimeError
|
||||
final_variable_assignment_test/02: MissingCompileTimeError
|
||||
final_variable_assignment_test/03: MissingCompileTimeError
|
||||
|
|
Loading…
Reference in a new issue