• 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 
5 #ifndef V8_OBJECTS_JS_FUNCTION_H_
6 #define V8_OBJECTS_JS_FUNCTION_H_
7 
8 #include "src/objects/code-kind.h"
9 #include "src/objects/js-objects.h"
10 #include "torque-generated/field-offsets.h"
11 
12 // Has to be the last include (doesn't have include guards):
13 #include "src/objects/object-macros.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 #include "torque-generated/src/objects/js-function-tq.inc"
19 
20 // An abstract superclass for classes representing JavaScript function values.
21 // It doesn't carry any functionality but allows function classes to be
22 // identified in the type system.
23 class JSFunctionOrBoundFunction
24     : public TorqueGeneratedJSFunctionOrBoundFunction<JSFunctionOrBoundFunction,
25                                                       JSObject> {
26  public:
27   STATIC_ASSERT(kHeaderSize == JSObject::kHeaderSize);
28   TQ_OBJECT_CONSTRUCTORS(JSFunctionOrBoundFunction)
29 };
30 
31 // JSBoundFunction describes a bound function exotic object.
32 class JSBoundFunction
33     : public TorqueGeneratedJSBoundFunction<JSBoundFunction,
34                                             JSFunctionOrBoundFunction> {
35  public:
36   static MaybeHandle<String> GetName(Isolate* isolate,
37                                      Handle<JSBoundFunction> function);
38   static Maybe<int> GetLength(Isolate* isolate,
39                               Handle<JSBoundFunction> function);
40   static MaybeHandle<NativeContext> GetFunctionRealm(
41       Handle<JSBoundFunction> function);
42 
43   // Dispatched behavior.
44   DECL_PRINTER(JSBoundFunction)
45   DECL_VERIFIER(JSBoundFunction)
46 
47   // The bound function's string representation implemented according
48   // to ES6 section 19.2.3.5 Function.prototype.toString ( ).
49   static Handle<String> ToString(Handle<JSBoundFunction> function);
50 
51   TQ_OBJECT_CONSTRUCTORS(JSBoundFunction)
52 };
53 
54 // JSFunction describes JavaScript functions.
55 class JSFunction : public JSFunctionOrBoundFunction {
56  public:
57   // [prototype_or_initial_map]:
58   DECL_ACCESSORS(prototype_or_initial_map, HeapObject)
59 
60   // [shared]: The information about the function that
61   // can be shared by instances.
62   DECL_ACCESSORS(shared, SharedFunctionInfo)
63 
64   static const int kLengthDescriptorIndex = 0;
65   static const int kNameDescriptorIndex = 1;
66   // Home object descriptor index when function has a [[HomeObject]] slot.
67   static const int kMaybeHomeObjectDescriptorIndex = 2;
68   // Fast binding requires length and name accessors.
69   static const int kMinDescriptorsForFastBind = 2;
70 
71   // [context]: The context for this function.
72   inline Context context();
73   inline bool has_context() const;
74   inline void set_context(HeapObject context);
75   inline JSGlobalProxy global_proxy();
76   inline NativeContext native_context();
77   inline int length();
78 
79   static Handle<Object> GetName(Isolate* isolate, Handle<JSFunction> function);
80   static Handle<NativeContext> GetFunctionRealm(Handle<JSFunction> function);
81 
82   // [code]: The generated code object for this function.  Executed
83   // when the function is invoked, e.g. foo() or new foo(). See
84   // [[Call]] and [[Construct]] description in ECMA-262, section
85   // 8.6.2, page 27.
86   inline Code code() const;
87   inline void set_code(Code code);
88   inline void set_code_no_write_barrier(Code code);
89 
90   // Get the abstract code associated with the function, which will either be
91   // a Code object or a BytecodeArray.
92   inline AbstractCode abstract_code();
93 
94   // The predicates for querying code kinds related to this function have
95   // specific terminology:
96   //
97   // - Attached: all code kinds that are directly attached to this JSFunction
98   //   object.
99   // - Available: all code kinds that are either attached or available through
100   //   indirect means such as the feedback vector's optimized code cache.
101   // - Active: the single code kind that would be executed if this function
102   //   were called in its current state. Note that there may not be an active
103   //   code kind if the function is not compiled.
104   //
105   // Note: code objects that are marked_for_deoptimization are not part of the
106   // attached/available/active sets. This is because the JSFunction might have
107   // been already deoptimized but its code() still needs to be unlinked, which
108   // will happen on its next activation.
109 
110   // True, iff any generated code kind is attached/available to this function.
111   V8_EXPORT_PRIVATE bool HasAttachedOptimizedCode() const;
112   bool HasAvailableOptimizedCode() const;
113 
114   bool HasAvailableCodeKind(CodeKind kind) const;
115 
116   V8_EXPORT_PRIVATE bool ActiveTierIsIgnition() const;
117   bool ActiveTierIsTurbofan() const;
118   bool ActiveTierIsNCI() const;
119   bool ActiveTierIsMidtierTurboprop() const;
120   bool ActiveTierIsToptierTurboprop() const;
121 
122   CodeKind NextTier() const;
123 
124   // Similar to SharedFunctionInfo::CanDiscardCompiled. Returns true, if the
125   // attached code can be recreated at a later point by replacing it with
126   // CompileLazy.
127   bool CanDiscardCompiled() const;
128 
129   // Tells whether or not this function checks its optimization marker in its
130   // feedback vector.
131   inline bool ChecksOptimizationMarker();
132 
133   // Tells whether or not this function has a (non-zero) optimization marker.
134   inline bool HasOptimizationMarker();
135 
136   // Mark this function for lazy recompilation. The function will be recompiled
137   // the next time it is executed.
138   inline void MarkForOptimization(ConcurrencyMode mode);
139 
140   // Tells whether or not the function is already marked for lazy recompilation.
141   inline bool IsMarkedForOptimization();
142   inline bool IsMarkedForConcurrentOptimization();
143 
144   // Tells whether or not the function is on the concurrent recompilation queue.
145   inline bool IsInOptimizationQueue();
146 
147   // Sets the optimization marker in the function's feedback vector.
148   inline void SetOptimizationMarker(OptimizationMarker marker);
149 
150   // Clears the optimization marker in the function's feedback vector.
151   inline void ClearOptimizationMarker();
152 
153   // If slack tracking is active, it computes instance size of the initial map
154   // with minimum permissible object slack.  If it is not active, it simply
155   // returns the initial map's instance size.
156   int ComputeInstanceSizeWithMinSlack(Isolate* isolate);
157 
158   // Completes inobject slack tracking on initial map if it is active.
159   inline void CompleteInobjectSlackTrackingIfActive();
160 
161   // [raw_feedback_cell]: Gives raw access to the FeedbackCell used to hold the
162   /// FeedbackVector eventually. Generally this shouldn't be used to get the
163   // feedback_vector, instead use feedback_vector() which correctly deals with
164   // the JSFunction's bytecode being flushed.
165   DECL_ACCESSORS(raw_feedback_cell, FeedbackCell)
166 
167   // Functions related to feedback vector. feedback_vector() can be used once
168   // the function has feedback vectors allocated. feedback vectors may not be
169   // available after compile when lazily allocating feedback vectors.
170   inline FeedbackVector feedback_vector() const;
171   inline bool has_feedback_vector() const;
172   V8_EXPORT_PRIVATE static void EnsureFeedbackVector(
173       Handle<JSFunction> function, IsCompiledScope* compiled_scope);
174 
175   // Functions related to closure feedback cell array that holds feedback cells
176   // used to create closures from this function. We allocate closure feedback
177   // cell arrays after compile, when we want to allocate feedback vectors
178   // lazily.
179   inline bool has_closure_feedback_cell_array() const;
180   inline ClosureFeedbackCellArray closure_feedback_cell_array() const;
181   static void EnsureClosureFeedbackCellArray(Handle<JSFunction> function);
182 
183   // Initializes the feedback cell of |function|. In lite mode, this would be
184   // initialized to the closure feedback cell array that holds the feedback
185   // cells for create closure calls from this function. In the regular mode,
186   // this allocates feedback vector.
187   static void InitializeFeedbackCell(Handle<JSFunction> function,
188                                      IsCompiledScope* compiled_scope);
189 
190   // Unconditionally clear the type feedback vector.
191   void ClearTypeFeedbackInfo();
192 
193   // Resets function to clear compiled data after bytecode has been flushed.
194   inline bool NeedsResetDueToFlushedBytecode();
195   inline void ResetIfBytecodeFlushed(
196       base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
197                                         HeapObject target)>>
198           gc_notify_updated_slot = base::nullopt);
199 
200   DECL_GETTER(has_prototype_slot, bool)
201 
202   // The initial map for an object created by this constructor.
203   DECL_GETTER(initial_map, Map)
204 
205   static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
206                             Handle<HeapObject> prototype);
207   DECL_GETTER(has_initial_map, bool)
208   V8_EXPORT_PRIVATE static void EnsureHasInitialMap(
209       Handle<JSFunction> function);
210 
211   // Creates a map that matches the constructor's initial map, but with
212   // [[prototype]] being new.target.prototype. Because new.target can be a
213   // JSProxy, this can call back into JavaScript.
214   static V8_WARN_UNUSED_RESULT MaybeHandle<Map> GetDerivedMap(
215       Isolate* isolate, Handle<JSFunction> constructor,
216       Handle<JSReceiver> new_target);
217 
218   // Get and set the prototype property on a JSFunction. If the
219   // function has an initial map the prototype is set on the initial
220   // map. Otherwise, the prototype is put in the initial map field
221   // until an initial map is needed.
222   DECL_GETTER(has_prototype, bool)
223   DECL_GETTER(has_instance_prototype, bool)
224   DECL_GETTER(prototype, Object)
225   DECL_GETTER(instance_prototype, HeapObject)
226   DECL_GETTER(has_prototype_property, bool)
227   DECL_GETTER(PrototypeRequiresRuntimeLookup, bool)
228   static void SetPrototype(Handle<JSFunction> function, Handle<Object> value);
229 
230   // Returns if this function has been compiled to native code yet.
231   inline bool is_compiled() const;
232 
GetHeaderSize(bool function_has_prototype_slot)233   static int GetHeaderSize(bool function_has_prototype_slot) {
234     return function_has_prototype_slot ? JSFunction::kSizeWithPrototype
235                                        : JSFunction::kSizeWithoutPrototype;
236   }
237 
238   // Prints the name of the function using PrintF.
239   void PrintName(FILE* out = stdout);
240 
241   DECL_CAST(JSFunction)
242 
243   // Calculate the instance size and in-object properties count.
244   // {CalculateExpectedNofProperties} can trigger compilation.
245   static V8_WARN_UNUSED_RESULT int CalculateExpectedNofProperties(
246       Isolate* isolate, Handle<JSFunction> function);
247   static void CalculateInstanceSizeHelper(InstanceType instance_type,
248                                           bool has_prototype_slot,
249                                           int requested_embedder_fields,
250                                           int requested_in_object_properties,
251                                           int* instance_size,
252                                           int* in_object_properties);
253 
254   // Dispatched behavior.
255   DECL_PRINTER(JSFunction)
256   DECL_VERIFIER(JSFunction)
257 
258   // The function's name if it is configured, otherwise shared function info
259   // debug name.
260   static Handle<String> GetName(Handle<JSFunction> function);
261 
262   // ES6 section 9.2.11 SetFunctionName
263   // Because of the way this abstract operation is used in the spec,
264   // it should never fail, but in practice it will fail if the generated
265   // function name's length exceeds String::kMaxLength.
266   static V8_WARN_UNUSED_RESULT bool SetName(Handle<JSFunction> function,
267                                             Handle<Name> name,
268                                             Handle<String> prefix);
269 
270   // The function's displayName if it is set, otherwise name if it is
271   // configured, otherwise shared function info
272   // debug name.
273   static Handle<String> GetDebugName(Handle<JSFunction> function);
274 
275   // The function's string representation implemented according to
276   // ES6 section 19.2.3.5 Function.prototype.toString ( ).
277   static Handle<String> ToString(Handle<JSFunction> function);
278 
279   struct FieldOffsets {
280     DEFINE_FIELD_OFFSET_CONSTANTS(JSFunctionOrBoundFunction::kHeaderSize,
281                                   TORQUE_GENERATED_JS_FUNCTION_FIELDS)
282   };
283   static constexpr int kSharedFunctionInfoOffset =
284       FieldOffsets::kSharedFunctionInfoOffset;
285   static constexpr int kContextOffset = FieldOffsets::kContextOffset;
286   static constexpr int kFeedbackCellOffset = FieldOffsets::kFeedbackCellOffset;
287   static constexpr int kCodeOffset = FieldOffsets::kCodeOffset;
288   static constexpr int kPrototypeOrInitialMapOffset =
289       FieldOffsets::kPrototypeOrInitialMapOffset;
290 
291  private:
292   // JSFunction doesn't have a fixed header size:
293   // Hide JSFunctionOrBoundFunction::kHeaderSize to avoid confusion.
294   static const int kHeaderSize;
295 
296   // Returns the set of code kinds of compilation artifacts (bytecode,
297   // generated code) attached to this JSFunction.
298   // Note that attached code objects that are marked_for_deoptimization are not
299   // included in this set.
300   // TODO(jgruber): Currently at most one code kind can be attached. Consider
301   // adding a NOT_COMPILED kind and changing this function to simply return the
302   // kind if this becomes more convenient in the future.
303   CodeKinds GetAttachedCodeKinds() const;
304 
305   // As above, but also considers locations outside of this JSFunction. For
306   // example the optimized code cache slot in the feedback vector, and the
307   // shared function info.
308   CodeKinds GetAvailableCodeKinds() const;
309 
310  public:
311   static constexpr int kSizeWithoutPrototype = kPrototypeOrInitialMapOffset;
312   static constexpr int kSizeWithPrototype = FieldOffsets::kHeaderSize;
313 
314   OBJECT_CONSTRUCTORS(JSFunction, JSFunctionOrBoundFunction);
315 };
316 
317 }  // namespace internal
318 }  // namespace v8
319 
320 #include "src/objects/object-macros-undef.h"
321 
322 #endif  // V8_OBJECTS_JS_FUNCTION_H_
323