[vm] Simplify evaluation of asserts
Since Dart 2, assert statements only accept bool conditions, so evaluation of the assert condition can be simplified in the VM. TEST=existing Change-Id: I0f54ad66b9d9aef707fef4eac192128a3994e7c9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425920 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
c644933a82
commit
16909d8ccb
+6
-10
@@ -11,18 +11,10 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
// Scan the stack until we hit the first function in the _AssertionError
|
||||
// class. We then return the next frame's script taking inlining into account.
|
||||
static ScriptPtr FindScript(DartFrameIterator* iterator) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
// The precompiled runtime faces two issues in recovering the correct
|
||||
// assertion text. First, the precompiled runtime does not include
|
||||
// the inlining meta-data so we cannot walk the inline-aware stack trace.
|
||||
// Second, the script text itself is missing so whatever script is returned
|
||||
// from here will be missing the assertion expression text.
|
||||
iterator->NextFrame(); // Skip _AssertionError._evaluateAssertion frame
|
||||
return Exceptions::GetCallerScript(iterator);
|
||||
#else
|
||||
StackFrame* stack_frame = iterator->NextFrame();
|
||||
Code& code = Code::Handle();
|
||||
Function& func = Function::Handle();
|
||||
@@ -60,8 +52,8 @@ static ScriptPtr FindScript(DartFrameIterator* iterator) {
|
||||
}
|
||||
UNREACHABLE();
|
||||
return Script::null();
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
// Allocate and throw a new AssertionError.
|
||||
// Arg0: index of the first token of the failed assertion.
|
||||
@@ -69,6 +61,9 @@ static ScriptPtr FindScript(DartFrameIterator* iterator) {
|
||||
// Arg2: Message object or null.
|
||||
// Return value: none, throws an exception.
|
||||
DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 0, 3) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
// No need to type check the arguments. This function can only be called
|
||||
// internally from the VM.
|
||||
const TokenPosition assertion_start = TokenPosition::Deserialize(
|
||||
@@ -114,6 +109,7 @@ DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 0, 3) {
|
||||
Exceptions::ThrowByType(Exceptions::kAssertion, args);
|
||||
UNREACHABLE();
|
||||
return Object::null();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Allocate and throw a new AssertionError.
|
||||
|
||||
@@ -1521,10 +1521,6 @@ Fragment StreamingFlowGraphBuilder::Return(TokenPosition position) {
|
||||
/*omit_result_type_check=*/false);
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::EvaluateAssertion() {
|
||||
return flow_graph_builder_->EvaluateAssertion();
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position,
|
||||
int catch_try_index) {
|
||||
return flow_graph_builder_->RethrowException(position, catch_try_index);
|
||||
@@ -4626,13 +4622,6 @@ Fragment StreamingFlowGraphBuilder::BuildAssertStatement(
|
||||
TargetEntryInstr* otherwise;
|
||||
|
||||
Fragment instructions;
|
||||
// Asserts can be of the following two kinds:
|
||||
//
|
||||
// * `assert(expr)`
|
||||
// * `assert(() { ... })`
|
||||
//
|
||||
// The call to `_AssertionError._evaluateAssertion()` will take care of both
|
||||
// and returns a boolean.
|
||||
instructions += BuildExpression(position); // read condition.
|
||||
|
||||
const TokenPosition condition_start_offset =
|
||||
@@ -4640,7 +4629,6 @@ Fragment StreamingFlowGraphBuilder::BuildAssertStatement(
|
||||
const TokenPosition condition_end_offset =
|
||||
ReadPosition(); // read condition end offset.
|
||||
|
||||
instructions += EvaluateAssertion();
|
||||
instructions += RecordCoverage(condition_start_offset);
|
||||
instructions += Constant(Bool::True());
|
||||
instructions += BranchIfEqual(&then, &otherwise);
|
||||
@@ -4648,6 +4636,8 @@ Fragment StreamingFlowGraphBuilder::BuildAssertStatement(
|
||||
const Class& klass =
|
||||
Class::ZoneHandle(Z, Library::LookupCoreClass(Symbols::AssertionError()));
|
||||
ASSERT(!klass.IsNull());
|
||||
const auto& error = klass.EnsureIsFinalized(thread());
|
||||
ASSERT(error == Error::null());
|
||||
|
||||
Fragment otherwise_fragment(otherwise);
|
||||
if (CompilerState::Current().is_aot()) {
|
||||
|
||||
@@ -158,7 +158,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
||||
Fragment LoadLocal(LocalVariable* variable);
|
||||
IndirectGotoInstr* IndirectGoto(intptr_t target_count);
|
||||
Fragment Return(TokenPosition position);
|
||||
Fragment EvaluateAssertion();
|
||||
Fragment RethrowException(TokenPosition position, int catch_try_index);
|
||||
Fragment ThrowNoSuchMethodError(TokenPosition position,
|
||||
const Function& target,
|
||||
|
||||
@@ -2281,19 +2281,6 @@ bool FlowGraphBuilder::NeedsDebugStepCheck(Value* value,
|
||||
return false;
|
||||
}
|
||||
|
||||
Fragment FlowGraphBuilder::EvaluateAssertion() {
|
||||
const Class& klass =
|
||||
Class::ZoneHandle(Z, Library::LookupCoreClass(Symbols::AssertionError()));
|
||||
ASSERT(!klass.IsNull());
|
||||
const auto& error = klass.EnsureIsFinalized(H.thread());
|
||||
ASSERT(error == Error::null());
|
||||
const Function& target = Function::ZoneHandle(
|
||||
Z, klass.LookupStaticFunctionAllowPrivate(Symbols::EvaluateAssertion()));
|
||||
ASSERT(!target.IsNull());
|
||||
return StaticCall(TokenPosition::kNoSource, target, /* argument_count = */ 1,
|
||||
ICData::kStatic);
|
||||
}
|
||||
|
||||
Fragment FlowGraphBuilder::CheckAssignable(const AbstractType& dst_type,
|
||||
const String& dst_name,
|
||||
AssertAssignableInstr::Kind kind,
|
||||
|
||||
@@ -277,7 +277,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
|
||||
Fragment BuildImplicitClosureCreation(TokenPosition position,
|
||||
const Function& target);
|
||||
|
||||
Fragment EvaluateAssertion();
|
||||
Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type,
|
||||
const String& name_symbol);
|
||||
Fragment CheckAssignable(
|
||||
|
||||
@@ -100,7 +100,6 @@ class ObjectPointerVisitor;
|
||||
V(EqualOperator, "==") \
|
||||
V(Error, "Error") \
|
||||
V(EvalSourceUri, "evaluate:source") \
|
||||
V(EvaluateAssertion, "_evaluateAssertion") \
|
||||
V(ExceptionHandlers, "ExceptionHandlers") \
|
||||
V(ExceptionVar, ":exception_var") \
|
||||
V(Expando, "Expando") \
|
||||
|
||||
@@ -66,20 +66,6 @@ class _AssertionError extends Error implements AssertionError {
|
||||
Object? message,
|
||||
);
|
||||
|
||||
@pragma("vm:entry-point", "call")
|
||||
static bool _evaluateAssertion(condition) {
|
||||
if (identical(condition, true) || identical(condition, false)) {
|
||||
return condition;
|
||||
}
|
||||
if (condition is _Closure) {
|
||||
return (condition as dynamic Function())();
|
||||
}
|
||||
if (condition is Function) {
|
||||
condition = (condition as dynamic Function())();
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
String get _messageString {
|
||||
final msg = message;
|
||||
if (msg == null) return "is not true.";
|
||||
|
||||
Reference in New Issue
Block a user