From 33feee3b030c24f85a7f5a5c8475ef4f7aa1780b Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Wed, 13 Jun 2018 22:28:04 +0000 Subject: [PATCH] [vm/kernel/bytecode] Fix arguments passing in native factory constructors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VM requires to pass null type arguments to factory constructors of non-generic classes. This includes native implementation of native factory constructors. Bytecode generation for bodies of native factory constructors is fixed to push this extra argument for NativeCall. Change-Id: I741a783c6964da88ecd0bfd1d2ec4aa3b1868708 Reviewed-on: https://dart-review.googlesource.com/60200 Reviewed-by: Zach Anderson Reviewed-by: Régis Crelier Commit-Queue: Alexander Markov --- pkg/vm/lib/bytecode/gen_bytecode.dart | 5 +++++ .../testcases/bytecode/instance_creation.dart | 6 ++++++ .../bytecode/instance_creation.dart.expect | 17 +++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart index 797bc67c615..4e218c891b1 100644 --- a/pkg/vm/lib/bytecode/gen_bytecode.dart +++ b/pkg/vm/lib/bytecode/gen_bytecode.dart @@ -152,6 +152,11 @@ class BytecodeGenerator extends RecursiveVisitor { if (locals.hasTypeArgsVar) { asm.emitPush(locals.typeArgsVarIndexInFrame); + } else if (enclosingMember is Procedure && + (enclosingMember as Procedure).isFactory) { + // Null type arguments are passed to factory constructors even if class + // is not generic. TODO(alexmarkov): Clean this up. + _genPushNull(); } if (locals.hasReceiver) { asm.emitPush(locals.getVarIndexInFrame(locals.receiverVar)); diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart b/pkg/vm/testcases/bytecode/instance_creation.dart index 5821f59a9d8..85ea5d71f54 100644 --- a/pkg/vm/testcases/bytecode/instance_creation.dart +++ b/pkg/vm/testcases/bytecode/instance_creation.dart @@ -2,6 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// ignore_for_file: native_function_body_in_non_sdk_code + class Base { T1 t1; T2 t2; @@ -67,6 +69,10 @@ void foo5() { new I.test_factory2(param: 42); } +class J { + factory J() native "agent_J"; +} + main() { foo1(); foo2(); diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect index 32c2c325ec3..be92aa5b66e 100644 --- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect +++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect @@ -1,6 +1,7 @@ library #lib; import self as self; import "dart:core" as core; +import "dart:_internal" as _in; class Base extends core::Object { generic-covariant-impl field self::Base::T1 t1 = null; @@ -385,6 +386,22 @@ ConstantPool { ] static factory test_factory2({dynamic param = null}) → self::I return new self::I::•(param); } +class J extends core::Object { +[@vm.bytecode= +Bytecode { + Entry 0 + CheckStack + PushConstant CP#0 + NativeCall CP#1 + ReturnTOS +} +ConstantPool { + [0] = Null + [1] = NativeEntry agent_J +} +] @_in::ExternalName::•("agent_J") + external static factory •() → self::J; +} [@vm.bytecode= Bytecode { Entry 1