mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:58:13 +00:00
[vm] Remove FallThroughError
code in the VM
Since Dart 2.0 we can never have FallThroughErrors. The CFE does not synthesize breaks unterminated cases which never reach the end of the block. For example: * Call to something that returns never. * Nested complete switch which returns from every branch. In these cases we need to construct a correct control flow in the VM, even though it is dead code. Because the CFE does not make the outer switch a labelled statement, we cannot find a jump target in the VM. Therefore, throw something (just not a FallThroughError). This should never be hit at runtime, because it's dead code. When the CFE emits synthetic breaks, we can remove this workaround. TEST=build SDK and run default suites. Bug: https://github.com/dart-lang/sdk/issues/50595 Change-Id: I595dd3baf7253b0ac4931445bd5b6da49e84cae4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273740 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com>
This commit is contained in:
parent
636232628b
commit
d86c043cbb
|
@ -4957,42 +4957,14 @@ Fragment StreamingFlowGraphBuilder::BuildSwitchCase(SwitchHelper* helper,
|
|||
body_fragment += Drop();
|
||||
}
|
||||
|
||||
// The Dart language specification mandates fall-throughs in [SwitchCase]es
|
||||
// to be runtime errors.
|
||||
// TODO(http://dartbug.com/50595): The CFE does not insert breaks for
|
||||
// unterminated cases which never reach the end of their control flow.
|
||||
// If the CFE inserts synthesized breaks, we can add an assert here instead.
|
||||
if (!is_default && body_fragment.is_open() &&
|
||||
(case_index < (helper->case_count() - 1))) {
|
||||
const Class& klass = Class::ZoneHandle(
|
||||
Z, Library::LookupCoreClass(Symbols::FallThroughError()));
|
||||
ASSERT(!klass.IsNull());
|
||||
const auto& error = klass.EnsureIsFinalized(thread());
|
||||
ASSERT(error == Error::null());
|
||||
|
||||
GrowableHandlePtrArray<const String> pieces(Z, 3);
|
||||
pieces.Add(Symbols::FallThroughError());
|
||||
pieces.Add(Symbols::Dot());
|
||||
pieces.Add(H.DartSymbolObfuscate("_create"));
|
||||
|
||||
const Function& constructor = Function::ZoneHandle(
|
||||
Z, klass.LookupConstructorAllowPrivate(String::ZoneHandle(
|
||||
Z, Symbols::FromConcatAll(H.thread(), pieces))));
|
||||
ASSERT(!constructor.IsNull());
|
||||
const String& url = H.DartSymbolPlain(
|
||||
parsed_function()->function().ToLibNamePrefixedQualifiedCString());
|
||||
|
||||
// Create instance of _FallThroughError
|
||||
body_fragment += AllocateObject(TokenPosition::kNoSource, klass, 0);
|
||||
LocalVariable* instance = MakeTemporary();
|
||||
|
||||
// Call _FallThroughError._create constructor.
|
||||
body_fragment += LoadLocal(instance); // this
|
||||
body_fragment += Constant(url); // url
|
||||
body_fragment += NullConstant(); // line
|
||||
|
||||
body_fragment +=
|
||||
StaticCall(TokenPosition::kNoSource, constructor, 3, ICData::kStatic);
|
||||
body_fragment += Drop();
|
||||
|
||||
// Throw the exception
|
||||
const auto& error =
|
||||
String::ZoneHandle(Z, Symbols::New(thread(), "Unreachable code."));
|
||||
body_fragment += Constant(error);
|
||||
body_fragment += ThrowException(TokenPosition::kNoSource);
|
||||
body_fragment += Drop();
|
||||
}
|
||||
|
|
|
@ -687,7 +687,7 @@ Fragment FlowGraphBuilder::ThrowTypeError() {
|
|||
|
||||
Fragment instructions;
|
||||
|
||||
// Create instance of _FallThroughError
|
||||
// Create instance of _TypeError
|
||||
instructions += AllocateObject(TokenPosition::kNoSource, klass, 0);
|
||||
LocalVariable* instance = MakeTemporary();
|
||||
|
||||
|
|
|
@ -7420,7 +7420,7 @@ static void CheckConcatAll(const String* data[], intptr_t n) {
|
|||
|
||||
ISOLATE_UNIT_TEST_CASE(Symbols_FromConcatAll) {
|
||||
{
|
||||
const String* data[3] = {&Symbols::FallThroughError(), &Symbols::Dot(),
|
||||
const String* data[3] = {&Symbols::NullThrownError(), &Symbols::Dot(),
|
||||
&Symbols::isPaused()};
|
||||
CheckConcatAll(data, 3);
|
||||
}
|
||||
|
@ -7475,7 +7475,7 @@ ISOLATE_UNIT_TEST_CASE(Symbols_FromConcatAll) {
|
|||
|
||||
{
|
||||
const String& empty = String::Handle(String::New(""));
|
||||
const String* data[3] = {&Symbols::FallThroughError(), &empty,
|
||||
const String* data[3] = {&Symbols::NullThrownError(), &empty,
|
||||
&Symbols::isPaused()};
|
||||
CheckConcatAll(data, 3);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,6 @@ class ObjectPointerVisitor;
|
|||
V(ExprTemp, ":expr_temp") \
|
||||
V(ExternalOneByteString, "_ExternalOneByteString") \
|
||||
V(ExternalTwoByteString, "_ExternalTwoByteString") \
|
||||
V(FallThroughError, "FallThroughError") \
|
||||
V(FfiAbiSpecificMapping, "_FfiAbiSpecificMapping") \
|
||||
V(FfiBool, "Bool") \
|
||||
V(FfiCallback, "_FfiCallback") \
|
||||
|
|
Loading…
Reference in a new issue