Commit Graph

39 Commits

Author SHA1 Message Date
Samir Jindel f0941f7c7d Improve the performance of closure-converted code.
Summary:

Previously, we would create a wrapper function in the flowgraph around converted
closures, which would forward all the closure's arguments and unpack the context
argument before calling the real closure function.

Now, we perform the unpacking at the top of the real function to avoid having
any wrapper function.

Previously, captured parameters would still be appear live to the GC even if
they're updated, because after they are copied into the context, all updates to
them are done there.

Now, as in regular closures, we zero-out the parameter variable after copying
it's value into the context, avoiding potential memory leaks.

Test Plan:

Ran the closure conversion test suite.
Ran benchmarks on Golem -- all statistically significant regressions are gone.

BUG=
R=dmitryas@google.com, regis@google.com

Review-Url: https://codereview.chromium.org/3008923002 .
2017-09-01 14:59:40 +02:00
Samir Jindel 7bf835b9d5 Fix many bugs with closure conversion in checked mode.
Summary:

Previously, we use the "Vector" type in the kernel tree for the result of the
"VectorCreation" operation as as the parameter type for converted closure
functions. In the VM, we use the "Context" type instead, which the VM treats a
little differently than normal Dart-visible types, and it doesn't not handle
type checks against it correctly, breaking all closure converted code running in
checked mode.

Now, Since we are forced to use dynamic to represent the types of elements of
the context, we may as well just use dynamic for the context type itself.

Previously, we did not correct handle converted closure type checks for closures
that capture type parameters. The way we handled these type checks also had
several latent bugs that prevented type parameters being handled properly.

Now, we handle type parameters for converted closures similarly to normal
closures, and the places we treat them specially are fewer and more integrated
with the rest of the closure type checking code.

There is still a problem where assignments to captured variables are not
checked, because they are transformed to assignments into the context, whose
elements are necessarily untyped. This breaks many co19 tests, which expect type
errors on these assignments. The example below should error in checked mode, but
after closure conversion is runs with no errors.

int b;
bool c;
(() { b = c; })()

Test Plan:

- All test cases in "pkg/kernel/testcases/closures" now run in checked mode.

- Added a test "closures_types.dart" to check that captured type parameters are
  handled correctly in the converted closures' signature types.

R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/3007623002 .
2017-08-28 17:39:32 +02:00
Samir Jindel 7b53e209c5 Fix several bugs in closure conversion.
Summary:

1. Previously, in 'BuildGraphOfConvertedClosureFunction', the VM was unable to
   correctly forward parameters to converted closure functions when
   they were captured in the converted function's body. This could happen when, for
   example, a closure was introduced into it by async conversion.

   Now, this is fixed by an approach that mirrors the technique in
   'BuildGraphOfFunction'.

2. Previously, local variables declared inside loop bodies were being saved in
   the loop's enclosing context, so closures within the loop would see new
   values initialized to the variable in subsequent iterations.

   Now, this is fixed by creating nested contexts for all loops, regardless of
   whether the loop variables are captured.

3. Previously, arity checks were not being performed on converted closures, so
   they could be called with too few or too many arguments. In the former case, the
   missing arguments would be filled in with garbage on the stack.

   Now, the assembly generation in 'CompileGraph' inserts argument count checks
   for converted closures as well as regular closures.

Test Plan:

Introduced new tests in the closure conversion suite to test each bug:

1. syncstart.dart
2. loop2.dart, blocks.dart, updated for_in_closure.dart
3. arity.dart

With these changes, closure conversion passes all co19 tests in non-checked mode, except those that are not passed without it:

python tools/test.py -m release -c dartk --vm-options "--reify --reify_generic_functions" co19

BUG=
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/3000333002 .
2017-08-24 20:21:28 +02:00
Samir Jindel 402e6f492d [kernel] Fix bug with redirecting constructors in closure conversion.
Previously, the captured variable analysis did not provide sufficient
information for the conversion phase regarding variable uses in initalizers: in
particular, it did not differentiate the case when a variable is used in an
initializer and captured in the body vs. being captured in the body and not used
in an initializer. In addition, there were a few bugs stemming from the use
of lazy iterables and OR conjunctives with effectful operations.

Now, we separate the information about which variables are captured from flags
indicating whether variables are used in initializers. The other bugs are fixed
in obvious ways.

Finally, we reintroduce some code that ensures that redirecting factory
constructors listed in "_redirecting#" field (a hack used when writing DILL
files) remain with one-expression bodies after closure conversion.

Test Plan:

Added a test case for the initializers bug, ensured that the patched SDK builds
with closure conversion always-on.

Reviewers: dmitryas@google.com

BUG=
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2995083002 .
2017-08-17 18:15:44 +02:00
Samir Jindel 6c5d1fba95 [kernel] Support for top-level generic functions.
Summary:

Previously, there was no support for generic methods in kernel. This prevented
us from being able to pass captured type arguments to the target top-level
function in converted closures, so these type arguments were always instantiated
to 'dynamic'.

Now, we save the type arguments to the closure creation operation in the
context, and read them out and forward them appropriately in closure wrapper
function. Since fasta doesn't currently support generic methods (their type
parameters are replaced by 'dynamic'), only top-level generic functions can
surface in kernel, as they are generated by closure conversion of closures that
capture type parameters of a class.

My focus here is enabling closure conversion to work in only these cases, and as
such, the code has some temporary "hacks" in the VM that may not work for
generic member functions or generic closures when they are enabled in fasta.

Test Plan:

I ran all the tests in closures/, and those which were previously expected to
crash due to missing VM support now pass and produce correct results.

Further testing is paused until we understand why the recent commit "[kernel]
Insert kernel bodies into VM heap" has broken all these tests.

Reviewers: regis@google.com, jensj@google.com, dmitryas@google.com

BUG=
R=dmitryas@google.com, jensj@google.com

Review-Url: https://codereview.chromium.org/2998803002 .
2017-08-16 15:24:26 +02:00
Samir Jindel 454ab91576 Fix duplicate context creation when closures appear in initializers.
Summary:

Previously, when a function parameter was captured both in an initializer and in
the body of a constructor, we would create two contexts: one created in a local
initializer and used by other initializers, and another in the body of the
function. This is incorrect, as it means that changes to the parameter in the
initializer's closure won't be visible in the body.

Now, to work around this problem we re-use the context created for the
initializers in the body of the constructor by moving the body into a new
constructor, and redirecting the original constructor to that one, passing the
context as an additional argument. This dance is necessary because local
initializers aren't visible in the body of a constructor.

Test Plan:

A few of the existing closure conversion tests were changed or fixed by this
revision. We also modify the 'closure_in_initializer.dart' test to hit this case
directly.

R=dmitryas@google.com

Reviewers: dmitryas@google.com
Review-Url: https://codereview.chromium.org/2991853002 .
2017-08-03 11:33:40 +02:00
Samir Jindel ff0c3936a1 Revert "Revert "Preserve type variables in closure conversion.""
This reverts commit fd4a0c658f.
2017-07-26 13:27:35 +02:00
Samir Jindel fd4a0c658f Revert "Preserve type variables in closure conversion."
This reverts commit 4d7490c609.
2017-07-26 12:44:15 +02:00
Samir Jindel 4d7490c609 Preserve type variables in closure conversion.
Summary:

Previously, we filled in all occurrences of captured type variables with either
"dynamic" or their bound, if they had one.

Now, we add extra type parameters to the top-level function corresponding to the
closure, and pass in the corresponding arguments as type arguments to the
"MakeClosure" operation.

Test Plan:

Updated [type_variables.dart] and added a new test case to it.

R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2989563002 .
2017-07-26 12:43:02 +02:00
Dmitry Stefantsov 5475240725 Add support for converted closures with explicit contexts to VM
The closure-conversion transformation is not enabled yet.  This commit
only adds the support for it to FlowGraphBuilder and
StreamingFlowGraphBuilder.  More work should be done before enabling the
transformation; most mportantly, the 'platform.dill' file that is used
in the Kernel isolate and is loaded by VM for linking with executed
programs should be separated.  The former should receive a file not
touched by the transformation, and the latter should receive a
transformed one.

BUG=
R=jensj@google.com, karlklose@google.com, kustermann@google.com

Review-Url: https://codereview.chromium.org/2891053003 .
2017-07-21 11:45:15 +02:00
Samir Jindel 239e044874 Remove dead code for closure-converting tearoffs.
This review scraps the (currently disabled) code for converting tearoffs in the
closure conversion pass.

The closure conversion pass can only ever do a partial job with tearoffs, due to
the possibility of an unconverted library tearing off a method from any object
it likes. Partially converting [PropertyGet]s makes the closure conversion pass
slower and introduces a new method for any field or method anywhere with a name
used in any [PropertyGet], inflating code size and potentially regressing
performance. As it provides no concrete value in return we've decided to scrap
this aspect of the transformation. Anyway, creating closures for tearoffs is
much easier for a backend than converting anonymous or nested functions, since
there is only one object ("this") captured. Thus ignoring tear-offs does not
undermine the value of the transformation.

BUG=
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2986553002 .
2017-07-20 16:47:09 +02:00
Samir Jindel a459f73fac Convert closures in all initializers, and share the context between them.
Summary:

Previously, we only handled `FieldInitializer` and `LocalInitializer`.

Now we handle all initializers.

Previously, we would create separate contexts for each initializers, which was
incorrect because it changes made to an argument from a closure within one
initializer would not be seen by a closure within another.

Now, we create the context in a `LocalInitializer` so all initializers will see
the same copy of the argument variables.

There is still an outstanding issue where variables introduced as local
initializers and later captured by closures in subsequent initializers are not
placed into the context. However, this will at least trigger an assert in the closure conversion pass.

Test Plan:

'closures_initializers/initializers.dart(.expect)' has been updated with very
simple test cases for super and redirecting initializers. The second bug
mentioned (captured local initializers) has not been reproduced yet.

BUG=
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2981603002 .
2017-07-14 10:59:17 +02:00
Samir Jindel 4df146dd9a Revert "Fix closure conversion in field and local initializers."
This reverts commit a49dcb6bb1.

Committed: https://github.com/dart-lang/sdk/commit/a7d1837d3d757a5cd1ba65a22a8e387bd956ea0b
Review-Url: https://codereview.chromium.org/2974673002 .
2017-07-10 10:12:45 +02:00
Samir Jindel a7d1837d3d Revert "Fix closure conversion in field and local initializers."
This reverts commit a49dcb6bb1.

Review-Url: https://codereview.chromium.org/2974673002 .
2017-07-07 18:42:51 +02:00
Samir Jindel a49dcb6bb1 Fix closure conversion in field and local initializers.
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2971293002 .
2017-07-07 17:48:38 +02:00
Dmitry Stefantsov b1e629f078 Add tests for handling closures in LocalInitializers
BUG=https://github.com/dart-lang/sdk/issues/29887
R=sjindel@google.com

Review-Url: https://codereview.chromium.org/2944433002 .
2017-07-06 16:39:25 +02:00
Dmitry Stefantsov fb290206a0 Remove unused imports to make analyzer happy
R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2945493004 .
2017-06-16 11:09:17 +02:00
Dmitry Stefantsov 6ebe771a71 Remove unnecessary contexts in closure conversion
R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2939043002 .
2017-06-16 11:01:10 +02:00
Dmitry Stefantsov c4f4d010fb Remove ContextClass that is not needed since we're using Vectors
Previously reified representation of contexts, also known as
ContextClass, was used in closure conversion.  Now that we've switched
to Vectors, we no longer need that class.

R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2937213002 .
2017-06-16 10:32:36 +02:00
Dmitry Stefantsov 5982ace801 Add transformLibraries for closure conversion
Closure conversion can now be run on a part of a program.  It allows
using closure conversion in kernel-isolate.  It comes at a cost of
temporarily sacrificing implementation of tear-offs via closures; VM
mechanism for tear-offs is used for now.

R=ahe@google.com

Review-Url: https://codereview.chromium.org/2938773003 .
2017-06-15 14:18:10 +02:00
Dmitry Stefantsov 504f55c043 Unbind canonical name of getter after renaming it in closure conversion
R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2936203002 .
2017-06-15 10:58:28 +02:00
Jacob Richman 997b4e62af Run formatter on a few frontend and kernel files that hadn't been formatted.
BUG=
R=asgerf@google.com

Review-Url: https://codereview.chromium.org/2820323005 .
2017-04-20 09:25:13 -07:00
Dmitry Stefantsov 42f82d1d21 Add primitive to create closures and use it for closure conversion
A new AST node 'ClosureCreation' is added. It takes a name of a
top-level function, a context, and a closure function type and creates a
closure of the given type. The effect of this closure invocation is the
same as of the invocation of the given top-level function with the
contexts as the first argument.

In order to use 'ClosureCreation', the closure conversion pass now
transforms closures into top-level functions, not closure classes. These
functions receive the context as the first argument.

The type of the expression represented by 'ClosureCreation' is its third
parameter. It its the responsibility of closure conversion pass to
create the correct types for 'ClosureCreation' nodes based on types of
closures transformed into top-level functions.

R=asgerf@google.com

Review-Url: https://codereview.chromium.org/2778223002 .
2017-03-31 14:43:56 +02:00
Asger Feldthaus f396d919ae Remove some additional code that depended on the old type propagation.
BUG=
R=kmillikin@google.com

Review-Url: https://codereview.chromium.org/2781473004 .
2017-03-28 13:51:21 +02:00
Asger Feldthaus a3402df15c [Kernel] Remove code from the old type propagation.
BUG=
R=kmillikin@google.com

Review-Url: https://codereview.chromium.org/2780513004 .
2017-03-28 12:43:22 +02:00
Dmitry Stefantsov 9ab86da19c Add Vector type to Kernel
There are four operations that work on Vectors: Vector creation, looking
up an item in a Vector, assigning a value to an item in a Vector, and
copying a Vector. The first three operations are allowed to only use
integer literals as number operands (length for Vector creation, index
for item lookup and assignment). Corresponding AST nodes are created for
these operations.

Vectors are used to represent contexts in Closure Conversion. The parent
context is stored as item 0 in its children contexts. The "golden" tests
for this transformation are adjusted accordingly.

The support for Vectors is added to ast-to-text, ast-to-binary, and
binary-to-ast transformations.

R=asgerf@google.com, kmillikin@google.com

Review-Url: https://codereview.chromium.org/2767773004 .
2017-03-27 15:52:32 +02:00
Peter von der Ahé 02573b3caa Remove Fasta's copy of accessors.dart.
R=asgerf@google.com, jensj@google.com

Review-Url: https://codereview.chromium.org/2777883002 .
2017-03-27 14:04:43 +02:00
Jacob Richman d1fa3c67af Run dartfmt on kernel package
BUG=
R=asgerf@google.com

Review-Url: https://codereview.chromium.org/2747113004 .
2017-03-17 08:21:52 -07:00
Peter von der Ahé 0d83d61601 Remove unnecessary casts.
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2752823003 .
2017-03-16 10:49:47 +01:00
Dmitry Stefantsov b87a479c2b Pass type arguments as a list in generic methods invocations
All generic methods are equipped with one extra named parameter for
passing type arguments as a list of type values.

Additinally, this change forces strong mode usage for 'dartk' in
'reified_dart'. Strong mode is required for loader to not strip away
type arguments from generic methods. In future, a command line argument
may be implemented for that (e.g. --generic-methods), if generic method
support will land before the strong mode.

R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2713163002 .
2017-03-16 10:47:11 +01:00
Dmitry Stefantsov 5526d5eeca Don't create a closure class if it already exists
R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2743363007 .
2017-03-15 10:04:05 +01:00
Jens Johansen a58fe4898d [Fasta] include source code in dill
At least for now, only when passing --include-source

BUG=
R=ahe@google.com

Review-Url: https://codereview.chromium.org/2729913005 .
2017-03-07 15:48:25 +01:00
Karl Klose 5df5395559 closure conversion: Do not set Context.parent if the value is null
R=dmitryas@google.com

Review-Url: https://codereview.chromium.org/2716573002 .
2017-02-28 11:23:00 +01:00
Karl Klose 5a42bf8062 Support closures in initializers
Moved the code to modify the current block with context updates to its own class and added another class for context updates in initializer expressions.

R=ahe@google.com

Review-Url: https://codereview.chromium.org/2712473003 .
2017-02-28 11:16:41 +01:00
Asger Feldthaus 8bfc4b47c0 Implement canonical name scheme in kernel.
This adds a class CanonicalName that can represent a library, class,
or member.  All references now go through a Reference object, which is
linked to both the AST node and its CanonicalName, so either can be
created first.

dartk now accepts multiple input files:
- If multiple dart files are given, they are all compiled.
- If multiple binaries are given, they are linked together.
Mixed dart and binary input is not supported by dartk.

dartk now has a flag --include-sdk which includes the entire SDK in
the output.  This is so the SDK can be compiled alone and then linked.

Example of compiling separately and then linking:
  dartk foo.dart -o foo.dill
  dartk main.dart -o main.dill
  dartk --include-sdk -o sdk.dill
  dartk main.dill foo.dill sdk.dill --target=vm --link -o program.dill

dartk still has incredibly slow cold start due to the analyzer loading
the dart sdk, so this does not actually speed things up at the moment.

BUG=
R=ahe@google.com, kmillikin@google.com, kustermann@google.com, sigmund@google.com

Review-Url: https://codereview.chromium.org/2665723002 .
2017-02-23 14:12:10 +01:00
Karl Klose e88a478a7c Handle constructor bodies
Also rewrites untransformed closures (for example those in initializers) to throw an exception.

R=ahe@google.com

Review-Url: https://codereview.chromium.org/2639253003 .
2017-01-19 13:32:18 +01:00
Karl Klose 8c6a174091 Use List::filled instead of List:: in closure conversion
The redirecting factory List:: is currently removed and replaced with the actual target at the callsites during construction of kernel, but referencing the actual target here would make the transformation platform specific.

R=asgerf@google.com

Review-Url: https://codereview.chromium.org/2637083002 .
2017-01-17 15:17:11 +01:00
Jens Johansen 41165b47e3 Fix to closure mock.dart
program.uriToLineStarts is now program.uriToSource.

BUG=
R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2609183002 .
2017-01-04 12:36:46 +01:00
Karl Klose ff99a0ce59 Merge kernel closure conversion into the Dart SDK
This is the result of:
- taking the diff of the branch closure_conversion to master in the kernel
repository
- updating the file paths
- applying the diff to the Dart SDK
- fixing conflicts between the changes to pkg/kernel in the Dart SDK and the master branch in the kernel repository

R=asgerf@google.com

Review-Url: https://codereview.chromium.org/2561723003 .
2016-12-15 10:16:22 +01:00