Skip to content

Cannot call Path.transform with internal Float64List #6456

Closed

Description

@kasperl

It looks like Path.transform cannot accept an internal Float64List as its argument. I've done a little digging and I think what happens is the following:

First we invoke this method:

static void Path_transform(Dart_NativeArguments args) {
  DartCall(&CanvasPath::transform, args);
}

In return, this converts the Float64List argument to a tonic::Float64List. This ends up calling Dart_TypedDataAcquireData and when the argument is a Float64List allocated internally (not an external one), then the VM disallows using any part of its API that might lead to garbage collections until Dart_TypedDataReleaseData has been called.

I think the issue is that the tonic::Float64List deconstructor hasn't been called when we need to create the Dart wrapper for the result of calling CanvasPath::transform. That means that we have a need to call into the VM before Dart_TypedDataReleaseData has been called. That breaks.

Maybe this issue can be worked around at the tonic level. Right now, hidden in sea of templates, it appears that the DartCall in Path_transform unfolds to something like this:

static void Path_transform(Dart_NativeArguments args) {
  DartConverter<ftl::RefPtr<CanvasPath>>::SetReturnValue(args,
     ... // call CanvasPath::transform with the right receiver an this argument:
     DartConverter<const tonic::Float64List&>::FromArguments(args, 1)
     ...
  );
}

Maybe that could be changed to something like this to allow the tonic:Float64List to be destroyed before we need to set the return value?

static void Path_transform(Dart_NativeArguments args) {
  ftl::RefPtr<CanvasPath> result = 
     ... // call CanvasPath::transform with the right receiver an this argument:
     DartConverter<const tonic::Float64List&>::FromArguments(args, 1)
     ...
  ;
  DartConverter<ftl::RefPtr<CanvasPath>>::SetReturnValue(args, result);
}

Steps to Reproduce

Run the following program:

import 'dart:ui' show Path;
import 'dart:typed_data' show Float64List;

main() {
  new Path().transform(new Float64List(16));
}

Logs

[FATAL:../../lib/tonic/dart_class_provider.cc(24)] Check failed: !Dart_IsError(class_handle). Path: Internal Dart data pointers have been acquired, please release them using Dart_TypedDataReleaseData.

Flutter Doctor

[✓] Flutter (on Linux, channel master)
• Flutter at /usr/local/google/home/kasperl/Dart/flutter
• Framework revision b00e6cd (2 weeks ago), 2016-10-04 20:29:10
• Engine revision 27d012a
• Tools Dart version 1.20.0-dev.5.0

[✓] Android toolchain - develop for Android devices (Android SDK 24.0.3)
• Android SDK at /usr/local/google/home/kasperl/Android/Sdk
• Platform android-24, build-tools 24.0.3
• OpenJDK Runtime Environment (build 1.8.0-google-v7-132676107-132666263)

[✓] Atom - a lightweight development environment for Flutter
• flutter plugin version 0.2.1
• dartlang plugin version 0.6.6

[✓] Connected devices
• None

Activity

  1. abarth commented on Oct 21, 2016

    @abarth
    Contributor

    Yeah, maybe something like this:

    diff --git a/dart_args.h b/dart_args.h
    index 190fcdc..379eb0a 100644
    --- a/dart_args.h
    +++ b/dart_args.h
    @@ -121,8 +121,9 @@ struct DartDispatcher<IndicesHolder<indices...>, ResultType (*)(ArgTypes...)>
           : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
    
       void Dispatch(FunctionPtr func) {
    -    DartReturn((*func)(DartArgHolder<indices, ArgTypes>::value...),
    -               it_->args());
    +    ResultType result = (*func)(
    +        DartArgHolder<indices, ArgTypes>::value...), it_->args();
    +    DartReturn(std::move(result));
       }
    
       ResultType DispatchCtor(FunctionPtr func) {
    @@ -160,9 +161,9 @@ struct DartDispatcher<IndicesHolder<indices...>, ResultType (C::*)(ArgTypes...)>
           : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
    
       void Dispatch(FunctionPtr func) {
    -    DartReturn((GetReceiver<C>(it_->args())->*func)(
    -                   DartArgHolder<indices, ArgTypes>::value...),
    -               it_->args());
    +    ResultType result = (GetReceiver<C>(it_->args())->*func)(
    +        DartArgHolder<indices, ArgTypes>::value...), it_->args();
    +    DartReturn(std::move(result));
       }
     };
    
  2. self-assigned this
    on Oct 21, 2016
  3. abarth commented on Oct 21, 2016

    @abarth
    Contributor

    That trick didn't help

  4. abarth commented on Oct 21, 2016

    @abarth
    Contributor

    I haz a fix.

  5. added a commit that references this issue on Oct 21, 2016
  6. github-actions commented on Sep 5, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  7. locked as resolved and limited conversation to collaborators on Sep 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions