| // 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, 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::New(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, 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, 1) { | |
| const Closure& receiver = | |
| Closure::CheckedHandle(zone, arguments->NativeArgAt(0)); | |
| return Smi::New(receiver.ComputeHash()); | |
| } | |
| DEFINE_NATIVE_ENTRY(Closure_clone, 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 |