Files
sdk/runtime/lib/function.cc
T
Victor Lima b951498903 [vm/aot] Allow static methods to have unboxed args and return
Static methods and constructors may receive unboxed parameters.
This change adds a bitmap to the RawFunction object indicating
which parameters are unboxed and their types. Also, the stack frame
bitmap was updated to include new bits for those parameters.

The ArgumentsDescriptor object was updated to store not only the number
of arguments, but also their size, since 32-bit platforms would use two
words for each int64 and double value.

In addition, static methods that return non-nullable integers
and doubles may return these values unboxed.

Dart AOT x64:

TypedData.Uint8ClampedListViewVarBench  +11.73%
DeltaBlue                               +9.32%
Meteor (Intel Xeon)                     +4.64%

Flutter release android-armv8:

velocity_tracker_bench                  -2.32% (less is better)

flutter_gallery_readonlydata_size       +0.18%
flutter_gallery_total_size              +0.13%
flutter_gallery_instructions_size       +0.12%

Issue https://github.com/dart-lang/sdk/issues/33549

Change-Id: I97e310f8f30213920af2333fbdedf193d03db5c3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135313
Commit-Queue: Victor Agnez Lima <victoragnez@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-05 15:17:04 +00:00

98 lines
3.8 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// 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.
#include "vm/bootstrap_natives.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/symbols.h"
namespace dart {
DEFINE_NATIVE_ENTRY(Function_apply, 0, 2) {
const int kTypeArgsLen = 0; // TODO(regis): Add support for generic function.
const Array& fun_arguments =
Array::CheckedHandle(zone, arguments->NativeArgAt(0));
const Array& fun_arg_names =
Array::CheckedHandle(zone, arguments->NativeArgAt(1));
const Array& fun_args_desc = Array::Handle(
zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, fun_arguments.Length(),
fun_arg_names));
const Object& result = Object::Handle(
zone, DartEntry::InvokeClosure(fun_arguments, fun_args_desc));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
}
return result.raw();
}
DEFINE_NATIVE_ENTRY(Closure_equals, 0, 2) {
const Closure& receiver =
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(Instance, other, arguments->NativeArgAt(1));
ASSERT(!other.IsNull());
// For implicit instance closures compare receiver instance and function's
// name and owner (multiple function objects could exist for the same
// function due to hot reload).
// Objects of other closure kinds are unique, so use identity comparison.
if (receiver.raw() == other.raw()) {
return Bool::True().raw();
}
if (other.IsClosure()) {
const Function& func_a = Function::Handle(zone, receiver.function());
if (func_a.IsImplicitInstanceClosureFunction()) {
const Closure& other_closure = Closure::Cast(other);
const Function& func_b = Function::Handle(zone, other_closure.function());
if (func_b.IsImplicitInstanceClosureFunction()) {
const Context& context_a = Context::Handle(zone, receiver.context());
const Context& context_b =
Context::Handle(zone, other_closure.context());
RawObject* receiver_a = context_a.At(0);
RawObject* receiver_b = context_b.At(0);
if ((receiver_a == receiver_b) &&
((func_a.raw() == func_b.raw()) ||
((func_a.name() == func_b.name()) &&
(func_a.Owner() == func_b.Owner())))) {
return Bool::True().raw();
}
}
}
}
return Bool::False().raw();
}
DEFINE_NATIVE_ENTRY(Closure_computeHash, 0, 1) {
const Closure& receiver =
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
return Smi::New(receiver.ComputeHash());
}
DEFINE_NATIVE_ENTRY(Closure_clone, 0, 1) {
const Closure& receiver =
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
const TypeArguments& instantiator_type_arguments =
TypeArguments::Handle(zone, receiver.instantiator_type_arguments());
const TypeArguments& function_type_arguments =
TypeArguments::Handle(zone, receiver.function_type_arguments());
const Function& function = Function::Handle(zone, receiver.function());
const Context& context = Context::Handle(zone, receiver.context());
Context& cloned_context = Context::Handle(zone);
if (!context.IsNull()) {
cloned_context = Context::New(context.num_variables());
cloned_context.set_parent(Context::Handle(zone, context.parent()));
Object& instance = Object::Handle(zone);
for (int i = 0; i < context.num_variables(); i++) {
instance = context.At(i);
cloned_context.SetAt(i, instance);
}
}
return Closure::New(instantiator_type_arguments, function_type_arguments,
function, cloned_context);
}
} // namespace dart