fe2f9aca21
DartEntry::InvokeCallable (and DartEntry::InvokeClosure) are only called for dynamic invocations. Instead of making it the responsibility of the caller to check the callable function if it can't receive dynamic invocation, move the call to DoArgumentTypesMatch into DartEntry::InvokeCallable. Since all current callers of these and related functions already have a handle on the current thread, thread it through instead of retrieving it via Thread::Current(). Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try Change-Id: I5f9260b0edace5b4017aa235a980a802405a2f1b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168020 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Clement Skau <cskau@google.com>
98 lines
3.8 KiB
C++
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(thread, 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());
|
|
ObjectPtr receiver_a = context_a.At(0);
|
|
ObjectPtr 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
|