[dart2wasm] Make slow path call StackTrace.current on null errors

For throwing normal exceptions we already outlined obtaining
the current stack. We can do this for null check errors as well.

Change-Id: Ie0505bfd99ff9c6738040c47b07e542439ee74a5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419161
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann
2025-03-31 04:10:39 -07:00
committed by Commit Queue
parent 90aecc4fe8
commit b8d25b791a
5 changed files with 28 additions and 9 deletions
+10 -4
View File
@@ -274,6 +274,15 @@ class AsyncStateMachineCodeGenerator extends StateMachineCodeGenerator {
b.return_();
}
void callCompleteErrorWithCurrentStack() {
b.local_get(_suspendStateLocal);
b.struct_get(
asyncSuspendStateInfo.struct, FieldIndex.asyncSuspendStateCompleter);
b.local_get(exceptionLocal);
call(translator.completerCompleteErrorWithCurrentStack.reference);
b.return_();
}
// Handle Dart exceptions.
b.catch_legacy(translator.getExceptionTag(b.module));
b.local_set(stackTraceLocal);
@@ -289,10 +298,7 @@ class AsyncStateMachineCodeGenerator extends StateMachineCodeGenerator {
// JS exceptions won't have a Dart stack trace, so we attach the current
// Dart stack trace.
call(translator.stackTraceCurrent.reference);
b.local_set(stackTraceLocal);
callCompleteError();
callCompleteErrorWithCurrentStack();
b.end(); // try
+1 -2
View File
@@ -2651,8 +2651,7 @@ abstract class AstCodeGenerator
// We lower a null check to a br_on_non_null, throwing a [TypeError] in
// the null case.
b.br_on_non_null(nullCheckBlock);
call(translator.stackTraceCurrent.reference);
call(translator.throwNullCheckError.reference);
call(translator.throwNullCheckErrorWithCurrentStack.reference);
b.unreachable();
b.end();
return nonNullOperandType;
+5 -2
View File
@@ -147,6 +147,9 @@ mixin KernelNodes {
index.getField("dart:async", "_Completer", "future");
late final Procedure completerComplete =
index.getProcedure("dart:async", "_AsyncCompleter", "complete");
late final Procedure completerCompleteErrorWithCurrentStack =
index.getProcedure(
"dart:async", "_AsyncCompleter", "_completeErrorWithCurrentStack");
late final Procedure completerCompleteError =
index.getProcedure("dart:async", "_Completer", "completeError");
late final Procedure awaitHelper =
@@ -290,8 +293,8 @@ mixin KernelNodes {
"_throwUnimplementedExternalMemberError");
late final Procedure stackTraceCurrent =
index.getProcedure("dart:core", "StackTrace", "get:current");
late final Procedure throwNullCheckError =
index.getProcedure("dart:core", "_TypeError", "_throwNullCheckError");
late final Procedure throwNullCheckErrorWithCurrentStack = index.getProcedure(
"dart:core", "_TypeError", "_throwNullCheckErrorWithCurrentStack");
late final Procedure throwAsCheckError =
index.getProcedure("dart:core", "_TypeError", "_throwAsCheckError");
late final Procedure throwInterfaceTypeAsCheckError1 = index
@@ -84,6 +84,15 @@ _AsyncSuspendState _newAsyncSuspendState(
@pragma("wasm:entry-point")
_AsyncCompleter<T> _makeAsyncCompleter<T>() => _AsyncCompleter<T>();
@patch
@pragma("wasm:entry-point")
class _AsyncCompleter<T> extends _Completer<T> {
@pragma("wasm:entry-point")
void _completeErrorWithCurrentStack(Object error) {
completeError(error, StackTrace.current);
}
}
@pragma("wasm:entry-point")
void _awaitHelper(_AsyncSuspendState suspendState, Object? operand) {
if (operand is! Future) {
+3 -1
View File
@@ -73,7 +73,9 @@ class _TypeError extends _Error implements TypeError {
}
@pragma("wasm:entry-point")
static Never _throwNullCheckError(StackTrace stackTrace) {
@pragma("wasm:never-inline")
static Never _throwNullCheckErrorWithCurrentStack() {
final stackTrace = StackTrace.current;
final typeError = _TypeError.fromMessageAndStackTrace(
"Null check operator used on a null value",
stackTrace,