Skip to content

Cannot call Path.transform with internal Float64List #6456

@kasperl

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

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