• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5namespace function {
6
7extern macro OrdinaryHasInstance(Context, Object, Object): JSAny;
8
9// ES6 section 19.2.3.6 Function.prototype[@@hasInstance]
10javascript builtin FunctionPrototypeHasInstance(
11    js-implicit context: NativeContext, receiver: JSAny)(value: JSAny): JSAny {
12  return OrdinaryHasInstance(context, receiver, value);
13}
14
15extern transitioning builtin
16FunctionPrototypeBind(implicit context: Context)(
17    JSFunction, JSAny, int32): JSAny;
18
19const kLengthDescriptorIndex: constexpr int32
20    generates 'JSFunctionOrBoundFunctionOrWrappedFunction::kLengthDescriptorIndex'
21    ;
22const kNameDescriptorIndex: constexpr int32
23    generates 'JSFunctionOrBoundFunctionOrWrappedFunction::kNameDescriptorIndex'
24    ;
25const kMinDescriptorsForFastBindAndWrap: constexpr int31
26    generates 'JSFunction::kMinDescriptorsForFastBindAndWrap';
27
28macro CheckAccessor(implicit context: Context)(
29    array: DescriptorArray, index: constexpr int32,
30    name: Name): void labels Slow {
31  const descriptor: DescriptorEntry = array.descriptors[index];
32  const key: Name|Undefined = descriptor.key;
33  if (!TaggedEqual(key, name)) goto Slow;
34
35  // The descriptor value must be an AccessorInfo.
36  Cast<AccessorInfo>(descriptor.value) otherwise goto Slow;
37}
38
39// ES6 section 19.2.3.2 Function.prototype.bind
40transitioning javascript builtin
41FastFunctionPrototypeBind(
42    js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
43    target: JSFunction)(...arguments): JSAny {
44  const argc: intptr = arguments.actual_count;
45  try {
46    typeswitch (receiver) {
47      case (fn: JSFunction|JSBoundFunction|JSWrappedFunction): {
48        // Disallow binding of slow-mode functions. We need to figure out
49        // whether the length and name property are in the original state.
50        Comment('Disallow binding of slow-mode functions');
51        if (IsDictionaryMap(fn.map)) goto Slow;
52
53        // Check whether the length and name properties are still present as
54        // AccessorInfo objects. If so, their value can be recomputed even if
55        // the actual value on the object changes.
56
57        if (fn.map.bit_field3.number_of_own_descriptors <
58            kMinDescriptorsForFastBindAndWrap) {
59          goto Slow;
60        }
61
62        const descriptors: DescriptorArray = fn.map.instance_descriptors;
63        CheckAccessor(
64            descriptors, kLengthDescriptorIndex, LengthStringConstant())
65            otherwise Slow;
66        CheckAccessor(descriptors, kNameDescriptorIndex, NameStringConstant())
67            otherwise Slow;
68
69        // Choose the right bound function map based on whether the target is
70        // constructable.
71
72        const boundFunctionMap: Map =
73            IsConstructor(fn) ?
74            *NativeContextSlot(
75                ContextSlot::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX) :
76            *NativeContextSlot(ContextSlot::
77                                    BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX);
78
79        // Verify that prototype matches that of the target bound function.
80
81        if (fn.map.prototype != boundFunctionMap.prototype) goto Slow;
82
83        // Allocate the arguments array.
84
85        const argumentsArray = arguments.length <= 1 ?
86            kEmptyFixedArray :
87            NewFixedArray(
88                arguments.length - 1, ArgumentsIterator{arguments, current: 1});
89
90        const boundReceiver: JSAny = arguments[0];
91
92        const result = new JSBoundFunction{
93          map: boundFunctionMap,
94          properties_or_hash: kEmptyFixedArray,
95          elements: kEmptyFixedArray,
96          bound_target_function: fn,
97          bound_this: boundReceiver,
98          bound_arguments: argumentsArray
99        };
100        return result;
101      }
102
103      case (JSAny): {
104        goto Slow;
105      }
106    }
107  } label Slow {
108    tail FunctionPrototypeBind(
109        LoadTargetFromFrame(), newTarget, Convert<int32>(argc));
110  }
111}
112}  // namespace function
113