diff --git a/src/builtins.cc b/src/builtins.cc index 6fea014117..f48fa15348 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -1022,45 +1022,6 @@ BUILTIN(GeneratorPoisonPill) { // -// Searches the hidden prototype chain of the given object for the first -// object that is an instance of the given type. If no such object can -// be found then Heap::null_value() is returned. -static inline Object* FindHidden(Heap* heap, - Object* object, - FunctionTemplateInfo* type) { - for (PrototypeIterator iter(heap->isolate(), object, - PrototypeIterator::START_AT_RECEIVER); - !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { - if (type->IsTemplateFor(iter.GetCurrent())) { - return iter.GetCurrent(); - } - } - return heap->null_value(); -} - - -// Returns the holder JSObject if the function can legally be called -// with this receiver. Returns Heap::null_value() if the call is -// illegal. Any arguments that don't fit the expected type is -// overwritten with undefined. Note that holder and the arguments are -// implicitly rewritten with the first object in the hidden prototype -// chain that actually has the expected type. -static inline Object* TypeCheck(Heap* heap, Object* recv, - FunctionTemplateInfo* info) { - // API calls are only supported with JSObject receivers. - if (!recv->IsJSObject()) return heap->null_value(); - Object* recv_type = info->signature(); - if (recv_type->IsUndefined()) return recv; - // If necessary, check the receiver - Object* holder = recv; - if (!recv_type->IsUndefined()) { - holder = FindHidden(heap, holder, FunctionTemplateInfo::cast(recv_type)); - if (holder == heap->null_value()) return heap->null_value(); - } - return holder; -} - - template MUST_USE_RESULT static Object* HandleApiCallHelper( BuiltinArguments args, Isolate* isolate) { @@ -1084,7 +1045,7 @@ MUST_USE_RESULT static Object* HandleApiCallHelper( DCHECK(!args[0]->IsNull()); if (args[0]->IsUndefined()) args[0] = function->global_proxy(); - Object* raw_holder = TypeCheck(heap, args[0], *fun_data); + Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]); if (raw_holder->IsNull()) { // This function cannot be called with the given receiver. Abort! diff --git a/src/objects.cc b/src/objects.cc index 4601bd1270..9ec776ddaf 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -234,6 +234,25 @@ bool FunctionTemplateInfo::IsTemplateFor(Map* map) { } +// TODO(dcarney): CallOptimization duplicates this logic, merge. +Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate, + Object* receiver) { + // API calls are only supported with JSObject receivers. + if (!receiver->IsJSObject()) return isolate->heap()->null_value(); + Object* recv_type = this->signature(); + // No signature, return holder. + if (recv_type->IsUndefined()) return receiver; + FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type); + // Check the receiver. + for (PrototypeIterator iter(isolate, receiver, + PrototypeIterator::START_AT_RECEIVER); + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { + if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent(); + } + return isolate->heap()->null_value(); +} + + Handle JSObject::EnsureWritableFastElements( Handle object) { DCHECK(object->HasFastSmiOrObjectElements()); diff --git a/src/objects.h b/src/objects.h index d0a6e333d1..cb7b78f69d 100644 --- a/src/objects.h +++ b/src/objects.h @@ -10640,6 +10640,10 @@ class FunctionTemplateInfo: public TemplateInfo { bool IsTemplateFor(Object* object); bool IsTemplateFor(Map* map); + // Returns the holder JSObject if the function can legally be called with this + // receiver. Returns Heap::null_value() if the call is illegal. + Object* GetCompatibleReceiver(Isolate* isolate, Object* receiver); + private: // Bit position in the flag, from least significant bit position. static const int kHiddenPrototypeBit = 0;