| 1 | // Copyright 2017 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_SHARED_FUNCTION_INFO_H_ |
| 6 | #define V8_OBJECTS_SHARED_FUNCTION_INFO_H_ |
| 7 | |
| 8 | #include "src/bailout-reason.h" |
| 9 | #include "src/function-kind.h" |
| 10 | #include "src/objects.h" |
| 11 | #include "src/objects/compressed-slots.h" |
| 12 | #include "src/objects/script.h" |
| 13 | #include "src/objects/slots.h" |
| 14 | #include "src/objects/smi.h" |
| 15 | #include "src/objects/struct.h" |
| 16 | #include "testing/gtest/include/gtest/gtest_prod.h" |
| 17 | #include "torque-generated/class-definitions-from-dsl.h" |
| 18 | |
| 19 | // Has to be the last include (doesn't have include guards): |
| 20 | #include "src/objects/object-macros.h" |
| 21 | |
| 22 | namespace v8 { |
| 23 | |
| 24 | namespace tracing { |
| 25 | class TracedValue; |
| 26 | } |
| 27 | |
| 28 | namespace internal { |
| 29 | |
| 30 | class AsmWasmData; |
| 31 | class BytecodeArray; |
| 32 | class CoverageInfo; |
| 33 | class DebugInfo; |
| 34 | class IsCompiledScope; |
| 35 | class WasmExportedFunctionData; |
| 36 | |
| 37 | // Data collected by the pre-parser storing information about scopes and inner |
| 38 | // functions. |
| 39 | // |
| 40 | // PreparseData Layout: |
| 41 | // +-------------------------------+ |
| 42 | // | data_length | children_length | |
| 43 | // +-------------------------------+ |
| 44 | // | Scope Byte Data ... | |
| 45 | // | ... | |
| 46 | // +-------------------------------+ |
| 47 | // | [Padding] | |
| 48 | // +-------------------------------+ |
| 49 | // | Inner PreparseData 1 | |
| 50 | // +-------------------------------+ |
| 51 | // | ... | |
| 52 | // +-------------------------------+ |
| 53 | // | Inner PreparseData N | |
| 54 | // +-------------------------------+ |
| 55 | class PreparseData : public HeapObject { |
| 56 | public: |
| 57 | DECL_INT_ACCESSORS(data_length) |
| 58 | DECL_INT_ACCESSORS(children_length) |
| 59 | |
| 60 | inline int inner_start_offset() const; |
| 61 | inline ObjectSlot inner_data_start() const; |
| 62 | |
| 63 | inline byte get(int index) const; |
| 64 | inline void set(int index, byte value); |
| 65 | inline void copy_in(int index, const byte* buffer, int length); |
| 66 | |
| 67 | inline PreparseData get_child(int index) const; |
| 68 | inline void set_child(int index, PreparseData value, |
| 69 | WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
| 70 | |
| 71 | // Clear uninitialized padding space. |
| 72 | inline void clear_padding(); |
| 73 | |
| 74 | DECL_CAST(PreparseData) |
| 75 | DECL_PRINTER(PreparseData) |
| 76 | DECL_VERIFIER(PreparseData) |
| 77 | |
| 78 | DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, |
| 79 | TORQUE_GENERATED_PREPARSE_DATA_FIELDS) |
| 80 | static const int kDataStartOffset = kSize; |
| 81 | |
| 82 | class BodyDescriptor; |
| 83 | |
| 84 | static int InnerOffset(int data_length) { |
| 85 | return RoundUp(kDataStartOffset + data_length * kByteSize, kTaggedSize); |
| 86 | } |
| 87 | |
| 88 | static int SizeFor(int data_length, int children_length) { |
| 89 | return InnerOffset(data_length) + children_length * kTaggedSize; |
| 90 | } |
| 91 | |
| 92 | OBJECT_CONSTRUCTORS(PreparseData, HeapObject); |
| 93 | |
| 94 | private: |
| 95 | inline Object get_child_raw(int index) const; |
| 96 | }; |
| 97 | |
| 98 | // Abstract class representing extra data for an uncompiled function, which is |
| 99 | // not stored in the SharedFunctionInfo. |
| 100 | class UncompiledData : public HeapObject { |
| 101 | public: |
| 102 | DECL_ACCESSORS(inferred_name, String) |
| 103 | DECL_INT32_ACCESSORS(start_position) |
| 104 | DECL_INT32_ACCESSORS(end_position) |
| 105 | DECL_INT32_ACCESSORS(function_literal_id) |
| 106 | |
| 107 | // Returns true if the UncompiledData contains a valid function_literal_id. |
| 108 | inline bool has_function_literal_id(); |
| 109 | |
| 110 | DECL_CAST(UncompiledData) |
| 111 | |
| 112 | inline static void Initialize( |
| 113 | UncompiledData data, String inferred_name, int start_position, |
| 114 | int end_position, int function_literal_id, |
| 115 | std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)> |
| 116 | gc_notify_updated_slot = |
| 117 | [](HeapObject object, ObjectSlot slot, HeapObject target) {}); |
| 118 | |
| 119 | // Layout description. |
| 120 | #define UNCOMPILED_DATA_FIELDS(V) \ |
| 121 | V(kStartOfPointerFieldsOffset, 0) \ |
| 122 | V(kInferredNameOffset, kTaggedSize) \ |
| 123 | V(kEndOfTaggedFieldsOffset, 0) \ |
| 124 | /* Raw data fields. */ \ |
| 125 | V(kStartPositionOffset, kInt32Size) \ |
| 126 | V(kEndPositionOffset, kInt32Size) \ |
| 127 | V(kFunctionLiteralIdOffset, kInt32Size) \ |
| 128 | V(kOptionalPaddingOffset, POINTER_SIZE_PADDING(kOptionalPaddingOffset)) \ |
| 129 | /* Header size. */ \ |
| 130 | V(kSize, 0) |
| 131 | |
| 132 | DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, UNCOMPILED_DATA_FIELDS) |
| 133 | #undef UNCOMPILED_DATA_FIELDS |
| 134 | |
| 135 | using BodyDescriptor = FixedBodyDescriptor<kStartOfPointerFieldsOffset, |
| 136 | kEndOfTaggedFieldsOffset, kSize>; |
| 137 | |
| 138 | // Clear uninitialized padding space. |
| 139 | inline void clear_padding(); |
| 140 | |
| 141 | OBJECT_CONSTRUCTORS(UncompiledData, HeapObject); |
| 142 | }; |
| 143 | |
| 144 | // Class representing data for an uncompiled function that does not have any |
| 145 | // data from the pre-parser, either because it's a leaf function or because the |
| 146 | // pre-parser bailed out. |
| 147 | class UncompiledDataWithoutPreparseData : public UncompiledData { |
| 148 | public: |
| 149 | DECL_CAST(UncompiledDataWithoutPreparseData) |
| 150 | DECL_PRINTER(UncompiledDataWithoutPreparseData) |
| 151 | DECL_VERIFIER(UncompiledDataWithoutPreparseData) |
| 152 | |
| 153 | static const int kSize = UncompiledData::kSize; |
| 154 | |
| 155 | // No extra fields compared to UncompiledData. |
| 156 | using BodyDescriptor = UncompiledData::BodyDescriptor; |
| 157 | |
| 158 | OBJECT_CONSTRUCTORS(UncompiledDataWithoutPreparseData, UncompiledData); |
| 159 | }; |
| 160 | |
| 161 | // Class representing data for an uncompiled function that has pre-parsed scope |
| 162 | // data. |
| 163 | class UncompiledDataWithPreparseData : public UncompiledData { |
| 164 | public: |
| 165 | DECL_ACCESSORS(preparse_data, PreparseData) |
| 166 | |
| 167 | DECL_CAST(UncompiledDataWithPreparseData) |
| 168 | DECL_PRINTER(UncompiledDataWithPreparseData) |
| 169 | DECL_VERIFIER(UncompiledDataWithPreparseData) |
| 170 | |
| 171 | inline static void Initialize( |
| 172 | UncompiledDataWithPreparseData data, String inferred_name, |
| 173 | int start_position, int end_position, int function_literal_id, |
| 174 | PreparseData scope_data, |
| 175 | std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)> |
| 176 | gc_notify_updated_slot = |
| 177 | [](HeapObject object, ObjectSlot slot, HeapObject target) {}); |
| 178 | |
| 179 | // Layout description. |
| 180 | |
| 181 | #define UNCOMPILED_DATA_WITH_PREPARSE_DATA_FIELDS(V) \ |
| 182 | V(kStartOfPointerFieldsOffset, 0) \ |
| 183 | V(kPreparseDataOffset, kTaggedSize) \ |
| 184 | V(kEndOfTaggedFieldsOffset, 0) \ |
| 185 | /* Total size. */ \ |
| 186 | V(kSize, 0) |
| 187 | |
| 188 | DEFINE_FIELD_OFFSET_CONSTANTS(UncompiledData::kSize, |
| 189 | UNCOMPILED_DATA_WITH_PREPARSE_DATA_FIELDS) |
| 190 | #undef UNCOMPILED_DATA_WITH_PREPARSE_DATA_FIELDS |
| 191 | |
| 192 | // Make sure the size is aligned |
| 193 | STATIC_ASSERT(IsAligned(kSize, kTaggedSize)); |
| 194 | |
| 195 | using BodyDescriptor = SubclassBodyDescriptor< |
| 196 | UncompiledData::BodyDescriptor, |
| 197 | FixedBodyDescriptor<kStartOfPointerFieldsOffset, kEndOfTaggedFieldsOffset, |
| 198 | kSize>>; |
| 199 | |
| 200 | OBJECT_CONSTRUCTORS(UncompiledDataWithPreparseData, UncompiledData); |
| 201 | }; |
| 202 | |
| 203 | class InterpreterData : public Struct { |
| 204 | public: |
| 205 | DECL_ACCESSORS(bytecode_array, BytecodeArray) |
| 206 | DECL_ACCESSORS(interpreter_trampoline, Code) |
| 207 | |
| 208 | // Layout description. |
| 209 | #define INTERPRETER_DATA_FIELDS(V) \ |
| 210 | V(kBytecodeArrayOffset, kTaggedSize) \ |
| 211 | V(kInterpreterTrampolineOffset, kTaggedSize) \ |
| 212 | /* Total size. */ \ |
| 213 | V(kSize, 0) |
| 214 | |
| 215 | DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, INTERPRETER_DATA_FIELDS) |
| 216 | #undef INTERPRETER_DATA_FIELDS |
| 217 | |
| 218 | DECL_CAST(InterpreterData) |
| 219 | DECL_PRINTER(InterpreterData) |
| 220 | DECL_VERIFIER(InterpreterData) |
| 221 | |
| 222 | OBJECT_CONSTRUCTORS(InterpreterData, Struct); |
| 223 | }; |
| 224 | |
| 225 | // SharedFunctionInfo describes the JSFunction information that can be |
| 226 | // shared by multiple instances of the function. |
| 227 | class SharedFunctionInfo : public HeapObject { |
| 228 | public: |
| 229 | NEVER_READ_ONLY_SPACE |
| 230 | |
| 231 | V8_EXPORT_PRIVATE static constexpr Object const kNoSharedNameSentinel = |
| 232 | Smi::kZero; |
| 233 | |
| 234 | // [name]: Returns shared name if it exists or an empty string otherwise. |
| 235 | inline String Name() const; |
| 236 | inline void SetName(String name); |
| 237 | |
| 238 | // Get the code object which represents the execution of this function. |
| 239 | V8_EXPORT_PRIVATE Code GetCode() const; |
| 240 | |
| 241 | // Get the abstract code associated with the function, which will either be |
| 242 | // a Code object or a BytecodeArray. |
| 243 | inline AbstractCode abstract_code(); |
| 244 | |
| 245 | // Tells whether or not this shared function info is interpreted. |
| 246 | // |
| 247 | // Note: function->IsInterpreted() does not necessarily return the same value |
| 248 | // as function->shared()->IsInterpreted() because the closure might have been |
| 249 | // optimized. |
| 250 | inline bool IsInterpreted() const; |
| 251 | |
| 252 | // Set up the link between shared function info and the script. The shared |
| 253 | // function info is added to the list on the script. |
| 254 | V8_EXPORT_PRIVATE static void SetScript( |
| 255 | Handle<SharedFunctionInfo> shared, Handle<Object> script_object, |
| 256 | int function_literal_id, bool reset_preparsed_scope_data = true); |
| 257 | |
| 258 | // Layout description of the optimized code map. |
| 259 | static const int kEntriesStart = 0; |
| 260 | static const int kContextOffset = 0; |
| 261 | static const int kCachedCodeOffset = 1; |
| 262 | static const int kEntryLength = 2; |
| 263 | static const int kInitialLength = kEntriesStart + kEntryLength; |
| 264 | |
| 265 | static const int kNotFound = -1; |
| 266 | |
| 267 | // [scope_info]: Scope info. |
| 268 | DECL_ACCESSORS(scope_info, ScopeInfo) |
| 269 | |
| 270 | // End position of this function in the script source. |
| 271 | V8_EXPORT_PRIVATE int EndPosition() const; |
| 272 | |
| 273 | // Start position of this function in the script source. |
| 274 | V8_EXPORT_PRIVATE int StartPosition() const; |
| 275 | |
| 276 | // Set the start and end position of this function in the script source. |
| 277 | // Updates the scope info if available. |
| 278 | V8_EXPORT_PRIVATE void SetPosition(int start_position, int end_position); |
| 279 | |
| 280 | // [outer scope info | feedback metadata] Shared storage for outer scope info |
| 281 | // (on uncompiled functions) and feedback metadata (on compiled functions). |
| 282 | DECL_ACCESSORS(raw_outer_scope_info_or_feedback_metadata, HeapObject) |
| 283 | |
| 284 | // Get the outer scope info whether this function is compiled or not. |
| 285 | inline bool HasOuterScopeInfo() const; |
| 286 | inline ScopeInfo GetOuterScopeInfo() const; |
| 287 | |
| 288 | // [feedback metadata] Metadata template for feedback vectors of instances of |
| 289 | // this function. |
| 290 | inline bool HasFeedbackMetadata() const; |
| 291 | DECL_ACCESSORS(feedback_metadata, FeedbackMetadata) |
| 292 | |
| 293 | // Returns if this function has been compiled yet. Note: with bytecode |
| 294 | // flushing, any GC after this call is made could cause the function |
| 295 | // to become uncompiled. If you need to ensure the function remains compiled |
| 296 | // for some period of time, use IsCompiledScope instead. |
| 297 | inline bool is_compiled() const; |
| 298 | |
| 299 | // Returns an IsCompiledScope which reports whether the function is compiled, |
| 300 | // and if compiled, will avoid the function becoming uncompiled while it is |
| 301 | // held. |
| 302 | inline IsCompiledScope is_compiled_scope() const; |
| 303 | |
| 304 | // [length]: The function length - usually the number of declared parameters. |
| 305 | // Use up to 2^16-2 parameters (16 bits of values, where one is reserved for |
| 306 | // kDontAdaptArgumentsSentinel). The value is only reliable when the function |
| 307 | // has been compiled. |
| 308 | inline uint16_t length() const; |
| 309 | inline void set_length(int value); |
| 310 | |
| 311 | // [internal formal parameter count]: The declared number of parameters. |
| 312 | // For subclass constructors, also includes new.target. |
| 313 | // The size of function's frame is internal_formal_parameter_count + 1. |
| 314 | DECL_UINT16_ACCESSORS(internal_formal_parameter_count) |
| 315 | |
| 316 | // Set the formal parameter count so the function code will be |
| 317 | // called without using argument adaptor frames. |
| 318 | inline void DontAdaptArguments(); |
| 319 | |
| 320 | // [expected_nof_properties]: Expected number of properties for the |
| 321 | // function. The value is only reliable when the function has been compiled. |
| 322 | DECL_UINT16_ACCESSORS(expected_nof_properties) |
| 323 | |
| 324 | // [function data]: This field holds some additional data for function. |
| 325 | // Currently it has one of: |
| 326 | // - a FunctionTemplateInfo to make benefit the API [IsApiFunction()]. |
| 327 | // - a BytecodeArray for the interpreter [HasBytecodeArray()]. |
| 328 | // - a InterpreterData with the BytecodeArray and a copy of the |
| 329 | // interpreter trampoline [HasInterpreterData()] |
| 330 | // - an AsmWasmData with Asm->Wasm conversion [HasAsmWasmData()]. |
| 331 | // - a Smi containing the builtin id [HasBuiltinId()] |
| 332 | // - a UncompiledDataWithoutPreparseData for lazy compilation |
| 333 | // [HasUncompiledDataWithoutPreparseData()] |
| 334 | // - a UncompiledDataWithPreparseData for lazy compilation |
| 335 | // [HasUncompiledDataWithPreparseData()] |
| 336 | // - a WasmExportedFunctionData for Wasm [HasWasmExportedFunctionData()] |
| 337 | DECL_ACCESSORS(function_data, Object) |
| 338 | |
| 339 | inline bool IsApiFunction() const; |
| 340 | inline FunctionTemplateInfo get_api_func_data(); |
| 341 | inline void set_api_func_data(FunctionTemplateInfo data); |
| 342 | inline bool HasBytecodeArray() const; |
| 343 | inline BytecodeArray GetBytecodeArray() const; |
| 344 | inline void set_bytecode_array(BytecodeArray bytecode); |
| 345 | inline Code InterpreterTrampoline() const; |
| 346 | inline bool HasInterpreterData() const; |
| 347 | inline InterpreterData interpreter_data() const; |
| 348 | inline void set_interpreter_data(InterpreterData interpreter_data); |
| 349 | inline BytecodeArray GetDebugBytecodeArray() const; |
| 350 | inline void SetDebugBytecodeArray(BytecodeArray bytecode); |
| 351 | inline bool HasAsmWasmData() const; |
| 352 | inline AsmWasmData asm_wasm_data() const; |
| 353 | inline void set_asm_wasm_data(AsmWasmData data); |
| 354 | |
| 355 | // builtin_id corresponds to the auto-generated Builtins::Name id. |
| 356 | inline bool HasBuiltinId() const; |
| 357 | inline int builtin_id() const; |
| 358 | inline void set_builtin_id(int builtin_id); |
| 359 | inline bool HasUncompiledData() const; |
| 360 | inline UncompiledData uncompiled_data() const; |
| 361 | inline void set_uncompiled_data(UncompiledData data); |
| 362 | inline bool HasUncompiledDataWithPreparseData() const; |
| 363 | inline UncompiledDataWithPreparseData uncompiled_data_with_preparse_data() |
| 364 | const; |
| 365 | inline void set_uncompiled_data_with_preparse_data( |
| 366 | UncompiledDataWithPreparseData data); |
| 367 | inline bool HasUncompiledDataWithoutPreparseData() const; |
| 368 | inline bool HasWasmExportedFunctionData() const; |
| 369 | WasmExportedFunctionData wasm_exported_function_data() const; |
| 370 | |
| 371 | // Clear out pre-parsed scope data from UncompiledDataWithPreparseData, |
| 372 | // turning it into UncompiledDataWithoutPreparseData. |
| 373 | inline void ClearPreparseData(); |
| 374 | |
| 375 | // The inferred_name is inferred from variable or property assignment of this |
| 376 | // function. It is used to facilitate debugging and profiling of JavaScript |
| 377 | // code written in OO style, where almost all functions are anonymous but are |
| 378 | // assigned to object properties. |
| 379 | inline bool HasInferredName(); |
| 380 | inline String inferred_name(); |
| 381 | |
| 382 | // Get the function literal id associated with this function, for parsing. |
| 383 | V8_EXPORT_PRIVATE int FunctionLiteralId(Isolate* isolate) const; |
| 384 | |
| 385 | // Break infos are contained in DebugInfo, this is a convenience method |
| 386 | // to simplify access. |
| 387 | V8_EXPORT_PRIVATE bool HasBreakInfo() const; |
| 388 | bool BreakAtEntry() const; |
| 389 | |
| 390 | // Coverage infos are contained in DebugInfo, this is a convenience method |
| 391 | // to simplify access. |
| 392 | bool HasCoverageInfo() const; |
| 393 | CoverageInfo GetCoverageInfo() const; |
| 394 | |
| 395 | // The function's name if it is non-empty, otherwise the inferred name. |
| 396 | String DebugName(); |
| 397 | |
| 398 | // Used for flags such as --turbo-filter. |
| 399 | bool PassesFilter(const char* raw_filter); |
| 400 | |
| 401 | // [script_or_debug_info]: One of: |
| 402 | // - Script from which the function originates. |
| 403 | // - a DebugInfo which holds the actual script [HasDebugInfo()]. |
| 404 | DECL_ACCESSORS(script_or_debug_info, Object) |
| 405 | |
| 406 | inline Object script() const; |
| 407 | inline void set_script(Object script); |
| 408 | |
| 409 | // The function is subject to debugging if a debug info is attached. |
| 410 | inline bool HasDebugInfo() const; |
| 411 | inline DebugInfo GetDebugInfo() const; |
| 412 | inline void SetDebugInfo(DebugInfo debug_info); |
| 413 | |
| 414 | // The offset of the 'function' token in the script source relative to the |
| 415 | // start position. Can return kFunctionTokenOutOfRange if offset doesn't |
| 416 | // fit in 16 bits. |
| 417 | DECL_UINT16_ACCESSORS(raw_function_token_offset) |
| 418 | |
| 419 | // The position of the 'function' token in the script source. Can return |
| 420 | // kNoSourcePosition if raw_function_token_offset() returns |
| 421 | // kFunctionTokenOutOfRange. |
| 422 | inline int function_token_position() const; |
| 423 | |
| 424 | // Returns true if the function has shared name. |
| 425 | inline bool HasSharedName() const; |
| 426 | |
| 427 | // [flags] Bit field containing various flags about the function. |
| 428 | DECL_INT32_ACCESSORS(flags) |
| 429 | |
| 430 | // Is this function a named function expression in the source code. |
| 431 | DECL_BOOLEAN_ACCESSORS(is_named_expression) |
| 432 | |
| 433 | // Is this function a top-level function (scripts, evals). |
| 434 | DECL_BOOLEAN_ACCESSORS(is_toplevel) |
| 435 | |
| 436 | // Indicates if this function can be lazy compiled. |
| 437 | DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation) |
| 438 | |
| 439 | // Indicates the language mode. |
| 440 | inline LanguageMode language_mode() const; |
| 441 | inline void set_language_mode(LanguageMode language_mode); |
| 442 | |
| 443 | // Indicates whether the source is implicitly wrapped in a function. |
| 444 | DECL_BOOLEAN_ACCESSORS(is_wrapped) |
| 445 | |
| 446 | // True if the function has any duplicated parameter names. |
| 447 | DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters) |
| 448 | |
| 449 | // Indicates whether the function is a native function. |
| 450 | // These needs special treatment in .call and .apply since |
| 451 | // null passed as the receiver should not be translated to the |
| 452 | // global object. |
| 453 | DECL_BOOLEAN_ACCESSORS(native) |
| 454 | |
| 455 | // Whether this function was created from a FunctionDeclaration. |
| 456 | DECL_BOOLEAN_ACCESSORS(is_declaration) |
| 457 | |
| 458 | // Indicates that asm->wasm conversion failed and should not be re-attempted. |
| 459 | DECL_BOOLEAN_ACCESSORS(is_asm_wasm_broken) |
| 460 | |
| 461 | // Indicates that the function was created by the Function function. |
| 462 | // Though it's anonymous, toString should treat it as if it had the name |
| 463 | // "anonymous". We don't set the name itself so that the system does not |
| 464 | // see a binding for it. |
| 465 | DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous) |
| 466 | |
| 467 | // Indicates that the function is either an anonymous expression |
| 468 | // or an arrow function (the name field can be set through the API, |
| 469 | // which does not change this flag). |
| 470 | DECL_BOOLEAN_ACCESSORS(is_anonymous_expression) |
| 471 | |
| 472 | // Indicates that the function represented by the shared function info was |
| 473 | // classed as an immediately invoked function execution (IIFE) function and |
| 474 | // is only executed once. |
| 475 | DECL_BOOLEAN_ACCESSORS(is_oneshot_iife) |
| 476 | |
| 477 | // Indicates that the function represented by the shared function info |
| 478 | // cannot observe the actual parameters passed at a call site, which |
| 479 | // means the function doesn't use the arguments object, doesn't use |
| 480 | // rest parameters, and is also in strict mode (meaning that there's |
| 481 | // no way to get to the actual arguments via the non-standard "arguments" |
| 482 | // accessor on sloppy mode functions). This can be used to speed up calls |
| 483 | // to this function even in the presence of arguments mismatch. |
| 484 | // See http://bit.ly/v8-faster-calls-with-arguments-mismatch for more |
| 485 | // information on this. |
| 486 | DECL_BOOLEAN_ACCESSORS(is_safe_to_skip_arguments_adaptor) |
| 487 | |
| 488 | // Indicates that the function has been reported for binary code coverage. |
| 489 | DECL_BOOLEAN_ACCESSORS(has_reported_binary_coverage) |
| 490 | |
| 491 | inline FunctionKind kind() const; |
| 492 | |
| 493 | // Defines the index in a native context of closure's map instantiated using |
| 494 | // this shared function info. |
| 495 | DECL_INT_ACCESSORS(function_map_index) |
| 496 | |
| 497 | // Clear uninitialized padding space. This ensures that the snapshot content |
| 498 | // is deterministic. |
| 499 | inline void clear_padding(); |
| 500 | |
| 501 | // Recalculates the |map_index| value after modifications of this shared info. |
| 502 | inline void UpdateFunctionMapIndex(); |
| 503 | |
| 504 | // Indicates whether optimizations have been disabled for this shared function |
| 505 | // info. If we cannot optimize the function we disable optimization to avoid |
| 506 | // spending time attempting to optimize it again. |
| 507 | inline bool optimization_disabled() const; |
| 508 | |
| 509 | // The reason why optimization was disabled. |
| 510 | inline BailoutReason disable_optimization_reason() const; |
| 511 | |
| 512 | // Disable (further) attempted optimization of all functions sharing this |
| 513 | // shared function info. |
| 514 | void DisableOptimization(BailoutReason reason); |
| 515 | |
| 516 | // This class constructor needs to call out to an instance fields |
| 517 | // initializer. This flag is set when creating the |
| 518 | // SharedFunctionInfo as a reminder to emit the initializer call |
| 519 | // when generating code later. |
| 520 | DECL_BOOLEAN_ACCESSORS(requires_instance_members_initializer) |
| 521 | |
| 522 | // [source code]: Source code for the function. |
| 523 | bool HasSourceCode() const; |
| 524 | static Handle<Object> GetSourceCode(Handle<SharedFunctionInfo> shared); |
| 525 | static Handle<Object> GetSourceCodeHarmony(Handle<SharedFunctionInfo> shared); |
| 526 | |
| 527 | // Tells whether this function should be subject to debugging, e.g. for |
| 528 | // - scope inspection |
| 529 | // - internal break points |
| 530 | // - coverage and type profile |
| 531 | // - error stack trace |
| 532 | inline bool IsSubjectToDebugging(); |
| 533 | |
| 534 | // Whether this function is defined in user-provided JavaScript code. |
| 535 | inline bool IsUserJavaScript(); |
| 536 | |
| 537 | // True if one can flush compiled code from this function, in such a way that |
| 538 | // it can later be re-compiled. |
| 539 | inline bool CanDiscardCompiled() const; |
| 540 | |
| 541 | // Flush compiled data from this function, setting it back to CompileLazy and |
| 542 | // clearing any compiled metadata. |
| 543 | V8_EXPORT_PRIVATE static void DiscardCompiled( |
| 544 | Isolate* isolate, Handle<SharedFunctionInfo> shared_info); |
| 545 | |
| 546 | // Discard the compiled metadata. If called during GC then |
| 547 | // |gc_notify_updated_slot| should be used to record any slot updates. |
| 548 | void DiscardCompiledMetadata( |
| 549 | Isolate* isolate, |
| 550 | std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)> |
| 551 | gc_notify_updated_slot = |
| 552 | [](HeapObject object, ObjectSlot slot, HeapObject target) {}); |
| 553 | |
| 554 | // Returns true if the function has old bytecode that could be flushed. This |
| 555 | // function shouldn't access any flags as it is used by concurrent marker. |
| 556 | // Hence it takes the mode as an argument. |
| 557 | inline bool ShouldFlushBytecode(BytecodeFlushMode mode); |
| 558 | |
| 559 | // Check whether or not this function is inlineable. |
| 560 | bool IsInlineable(); |
| 561 | |
| 562 | // Source size of this function. |
| 563 | int SourceSize(); |
| 564 | |
| 565 | // Returns `false` if formal parameters include rest parameters, optional |
| 566 | // parameters, or destructuring parameters. |
| 567 | // TODO(caitp): make this a flag set during parsing |
| 568 | inline bool has_simple_parameters(); |
| 569 | |
| 570 | // Initialize a SharedFunctionInfo from a parsed function literal. |
| 571 | static void InitFromFunctionLiteral(Handle<SharedFunctionInfo> shared_info, |
| 572 | FunctionLiteral* lit, bool is_toplevel); |
| 573 | |
| 574 | // Sets the expected number of properties based on estimate from parser. |
| 575 | void SetExpectedNofPropertiesFromEstimate(FunctionLiteral* literal); |
| 576 | |
| 577 | // Sets the FunctionTokenOffset field based on the given token position and |
| 578 | // start position. |
| 579 | void SetFunctionTokenPosition(int function_token_position, |
| 580 | int start_position); |
| 581 | |
| 582 | static void EnsureSourcePositionsAvailable( |
| 583 | Isolate* isolate, Handle<SharedFunctionInfo> shared_info); |
| 584 | |
| 585 | // Hash based on function literal id and script id. |
| 586 | V8_EXPORT_PRIVATE uint32_t Hash(); |
| 587 | |
| 588 | inline bool construct_as_builtin() const; |
| 589 | |
| 590 | // Determines and sets the ConstructAsBuiltinBit in |flags|, based on the |
| 591 | // |function_data|. Must be called when creating the SFI after other fields |
| 592 | // are initialized. The ConstructAsBuiltinBit determines whether |
| 593 | // JSBuiltinsConstructStub or JSConstructStubGeneric should be called to |
| 594 | // construct this function. |
| 595 | inline void CalculateConstructAsBuiltin(); |
| 596 | |
| 597 | // Dispatched behavior. |
| 598 | DECL_PRINTER(SharedFunctionInfo) |
| 599 | DECL_VERIFIER(SharedFunctionInfo) |
| 600 | #ifdef OBJECT_PRINT |
| 601 | void PrintSourceCode(std::ostream& os); |
| 602 | #endif |
| 603 | |
| 604 | // Returns the SharedFunctionInfo in a format tracing can support. |
| 605 | std::unique_ptr<v8::tracing::TracedValue> ToTracedValue(); |
| 606 | |
| 607 | // The tracing scope for SharedFunctionInfo objects. |
| 608 | static const char* kTraceScope; |
| 609 | |
| 610 | // Returns the unique TraceID for this SharedFunctionInfo (within the |
| 611 | // kTraceScope, works only for functions that have a Script and start/end |
| 612 | // position). |
| 613 | uint64_t TraceID() const; |
| 614 | |
| 615 | // Returns the unique trace ID reference for this SharedFunctionInfo |
| 616 | // (based on the |TraceID()| above). |
| 617 | std::unique_ptr<v8::tracing::TracedValue> TraceIDRef() const; |
| 618 | |
| 619 | // Iterate over all shared function infos in a given script. |
| 620 | class ScriptIterator { |
| 621 | public: |
| 622 | V8_EXPORT_PRIVATE ScriptIterator(Isolate* isolate, Script script); |
| 623 | ScriptIterator(Isolate* isolate, |
| 624 | Handle<WeakFixedArray> shared_function_infos); |
| 625 | V8_EXPORT_PRIVATE SharedFunctionInfo Next(); |
| 626 | int CurrentIndex() const { return index_ - 1; } |
| 627 | |
| 628 | // Reset the iterator to run on |script|. |
| 629 | void Reset(Script script); |
| 630 | |
| 631 | private: |
| 632 | Isolate* isolate_; |
| 633 | Handle<WeakFixedArray> shared_function_infos_; |
| 634 | int index_; |
| 635 | DISALLOW_COPY_AND_ASSIGN(ScriptIterator); |
| 636 | }; |
| 637 | |
| 638 | // Iterate over all shared function infos on the heap. |
| 639 | class GlobalIterator { |
| 640 | public: |
| 641 | V8_EXPORT_PRIVATE explicit GlobalIterator(Isolate* isolate); |
| 642 | V8_EXPORT_PRIVATE SharedFunctionInfo Next(); |
| 643 | |
| 644 | private: |
| 645 | Script::Iterator script_iterator_; |
| 646 | WeakArrayList::Iterator noscript_sfi_iterator_; |
| 647 | SharedFunctionInfo::ScriptIterator sfi_iterator_; |
| 648 | DISALLOW_HEAP_ALLOCATION(no_gc_) |
| 649 | DISALLOW_COPY_AND_ASSIGN(GlobalIterator); |
| 650 | }; |
| 651 | |
| 652 | DECL_CAST(SharedFunctionInfo) |
| 653 | |
| 654 | // Constants. |
| 655 | static const uint16_t kDontAdaptArgumentsSentinel = static_cast<uint16_t>(-1); |
| 656 | |
| 657 | static const int kMaximumFunctionTokenOffset = kMaxUInt16 - 1; |
| 658 | static const uint16_t kFunctionTokenOutOfRange = static_cast<uint16_t>(-1); |
| 659 | STATIC_ASSERT(kMaximumFunctionTokenOffset + 1 == kFunctionTokenOutOfRange); |
| 660 | |
| 661 | DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, |
| 662 | TORQUE_GENERATED_SHARED_FUNCTION_INFO_FIELDS) |
| 663 | |
| 664 | static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize); |
| 665 | |
| 666 | class BodyDescriptor; |
| 667 | |
| 668 | // Bit positions in |flags|. |
| 669 | #define FLAGS_BIT_FIELDS(V, _) \ |
| 670 | /* Have FunctionKind first to make it cheaper to access */ \ |
| 671 | V(FunctionKindBits, FunctionKind, 5, _) \ |
| 672 | V(IsNativeBit, bool, 1, _) \ |
| 673 | V(IsStrictBit, bool, 1, _) \ |
| 674 | V(IsWrappedBit, bool, 1, _) \ |
| 675 | V(IsClassConstructorBit, bool, 1, _) \ |
| 676 | V(HasDuplicateParametersBit, bool, 1, _) \ |
| 677 | V(AllowLazyCompilationBit, bool, 1, _) \ |
| 678 | V(NeedsHomeObjectBit, bool, 1, _) \ |
| 679 | V(IsDeclarationBit, bool, 1, _) \ |
| 680 | V(IsAsmWasmBrokenBit, bool, 1, _) \ |
| 681 | V(FunctionMapIndexBits, int, 5, _) \ |
| 682 | V(DisabledOptimizationReasonBits, BailoutReason, 4, _) \ |
| 683 | V(RequiresInstanceMembersInitializer, bool, 1, _) \ |
| 684 | V(ConstructAsBuiltinBit, bool, 1, _) \ |
| 685 | V(IsAnonymousExpressionBit, bool, 1, _) \ |
| 686 | V(NameShouldPrintAsAnonymousBit, bool, 1, _) \ |
| 687 | V(HasReportedBinaryCoverageBit, bool, 1, _) \ |
| 688 | V(IsNamedExpressionBit, bool, 1, _) \ |
| 689 | V(IsTopLevelBit, bool, 1, _) \ |
| 690 | V(IsOneshotIIFEBit, bool, 1, _) \ |
| 691 | V(IsSafeToSkipArgumentsAdaptorBit, bool, 1, _) |
| 692 | DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS) |
| 693 | #undef FLAGS_BIT_FIELDS |
| 694 | |
| 695 | // Bailout reasons must fit in the DisabledOptimizationReason bitfield. |
| 696 | STATIC_ASSERT(BailoutReason::kLastErrorMessage <= |
| 697 | DisabledOptimizationReasonBits::kMax); |
| 698 | |
| 699 | STATIC_ASSERT(kLastFunctionKind <= FunctionKindBits::kMax); |
| 700 | |
| 701 | // Indicates that this function uses a super property (or an eval that may |
| 702 | // use a super property). |
| 703 | // This is needed to set up the [[HomeObject]] on the function instance. |
| 704 | inline bool needs_home_object() const; |
| 705 | |
| 706 | V8_INLINE bool IsSharedFunctionInfoWithID() const { |
| 707 | #if V8_SFI_HAS_UNIQUE_ID |
| 708 | return true; |
| 709 | #else |
| 710 | return false; |
| 711 | #endif |
| 712 | } |
| 713 | |
| 714 | private: |
| 715 | // [name_or_scope_info]: Function name string, kNoSharedNameSentinel or |
| 716 | // ScopeInfo. |
| 717 | DECL_ACCESSORS(name_or_scope_info, Object) |
| 718 | |
| 719 | // [outer scope info] The outer scope info, needed to lazily parse this |
| 720 | // function. |
| 721 | DECL_ACCESSORS(outer_scope_info, HeapObject) |
| 722 | |
| 723 | inline void set_kind(FunctionKind kind); |
| 724 | |
| 725 | inline void set_needs_home_object(bool value); |
| 726 | |
| 727 | friend class Factory; |
| 728 | friend class V8HeapExplorer; |
| 729 | FRIEND_TEST(PreParserTest, LazyFunctionLength); |
| 730 | |
| 731 | // Find the index of this function in the parent script. Slow path of |
| 732 | // FunctionLiteralId. |
| 733 | int FindIndexInScript(Isolate* isolate) const; |
| 734 | |
| 735 | OBJECT_CONSTRUCTORS(SharedFunctionInfo, HeapObject); |
| 736 | }; |
| 737 | |
| 738 | class SharedFunctionInfoWithID : public SharedFunctionInfo { |
| 739 | public: |
| 740 | // [unique_id] - For --trace-maps purposes, an identifier that's persistent |
| 741 | // even if the GC moves this SharedFunctionInfo. |
| 742 | DECL_INT_ACCESSORS(unique_id) |
| 743 | |
| 744 | DECL_CAST(SharedFunctionInfoWithID) |
| 745 | |
| 746 | DEFINE_FIELD_OFFSET_CONSTANTS( |
| 747 | SharedFunctionInfo::kSize, |
| 748 | TORQUE_GENERATED_SHARED_FUNCTION_INFO_WITH_ID_FIELDS) |
| 749 | |
| 750 | static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize); |
| 751 | |
| 752 | OBJECT_CONSTRUCTORS(SharedFunctionInfoWithID, SharedFunctionInfo); |
| 753 | }; |
| 754 | |
| 755 | // Printing support. |
| 756 | struct SourceCodeOf { |
| 757 | explicit SourceCodeOf(SharedFunctionInfo v, int max = -1) |
| 758 | : value(v), max_length(max) {} |
| 759 | const SharedFunctionInfo value; |
| 760 | int max_length; |
| 761 | }; |
| 762 | |
| 763 | // IsCompiledScope enables a caller to check if a function is compiled, and |
| 764 | // ensure it remains compiled (i.e., doesn't have it's bytecode flushed) while |
| 765 | // the scope is retained. |
| 766 | class IsCompiledScope { |
| 767 | public: |
| 768 | inline IsCompiledScope(const SharedFunctionInfo shared, Isolate* isolate); |
| 769 | inline IsCompiledScope() : retain_bytecode_(), is_compiled_(false) {} |
| 770 | |
| 771 | inline bool is_compiled() const { return is_compiled_; } |
| 772 | |
| 773 | private: |
| 774 | MaybeHandle<BytecodeArray> retain_bytecode_; |
| 775 | bool is_compiled_; |
| 776 | }; |
| 777 | |
| 778 | std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v); |
| 779 | |
| 780 | } // namespace internal |
| 781 | } // namespace v8 |
| 782 | |
| 783 | #include "src/objects/object-macros-undef.h" |
| 784 | |
| 785 | #endif // V8_OBJECTS_SHARED_FUNCTION_INFO_H_ |
| 786 | |