/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/execution/frame-constants.h
880 строк
41 KB
Michaël Zasso
deps: update V8 to 14.6.202.33
24 апр 2026, 19:01
Не верифицирован
24 апр 2026, 19:01
f1e0b83
Код
Авторство
О чём код?
// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_EXECUTION_FRAME_CONSTANTS_H_ #define V8_EXECUTION_FRAME_CONSTANTS_H_ #include "src/common/globals.h" #include "src/flags/flags.h" namespace v8 { namespace internal { // Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume // two slots. // // Stack slot indices >= 0 access the callee stack with slot 0 corresponding to // the callee's saved return address and 1 corresponding to the saved frame // pointer. Some frames have additional information stored in the fixed header, // for example JSFunctions store the function context and marker in the fixed // header, with slot index 2 corresponding to the current function context and 3 // corresponding to the frame marker/JSFunction. // // slot JS frame // +-----------------+-------------------------------- // -n-1 | parameter n | ^ // |- - - - - - - - -| | // -n | parameter n-1 | Caller // ... | ... | frame slots // -2 | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1 | parameter 0 | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | Fixed | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp |Context/Frm. Type| v if a constant pool | // |-----------------+---- is used, cp = 1, | // 3+cp | | ^ otherwise, cp = 0 | // |- - - - - - - - -| | | // 4+cp | | | Callee // |- - - - - - - - -| | frame slots // ... | | Frame slots (slot >= 0) // |- - - - - - - - -| | | // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class CommonFrameConstants : public AllStatic { public: static constexpr int kCallerFPOffset = 0 * kSystemPointerSize; static constexpr int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize; static constexpr int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize; // Fixed part of the frame consists of return address, caller fp, // constant pool (if V8_EMBEDDED_CONSTANT_POOL_BOOL), context, and // function. CommonFrame::IterateExpressions assumes that kLastObjectOffset // is the last object pointer. static constexpr int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize; static constexpr int kFixedSlotCountAboveFp = kFixedFrameSizeAboveFp / kSystemPointerSize; static constexpr int kCPSlotSize = V8_EMBEDDED_CONSTANT_POOL_BOOL ? kSystemPointerSize : 0; static constexpr int kCPSlotCount = kCPSlotSize / kSystemPointerSize; static constexpr int kConstantPoolOffset = kCPSlotSize ? -1 * kSystemPointerSize : 0; static constexpr int kContextOrFrameTypeSize = kSystemPointerSize; static constexpr int kContextOrFrameTypeOffset = -(kCPSlotSize + kContextOrFrameTypeSize); }; // StandardFrames are used for both unoptimized and optimized JavaScript // frames. They always have a context below the saved fp/constant // pool, below that the JSFunction of the executing function and below that an // integer (not a Smi) containing the actual number of arguments passed to the // JavaScript code. // // slot JS frame // +-----------------+-------------------------------- // -n-1 | parameter n | ^ // |- - - - - - - - -| | // -n | parameter n-1 | Caller // ... | ... | frame slots // -2 | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1 | parameter 0 | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | Fixed | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp | Context | | if a constant pool | // |- - - - - - - - -| | is used, cp = 1, | // 3+cp | JSFunction | | otherwise, cp = 0 | // |- - - - - - - - -| | | // 4+cp | argc | v | // +-----------------+---- | // 5+cp | expressions or | ^ Callee // |- - - - - - - - -| | frame slots // ... | pushed values | Frame slots (slot >= 0) // |- - - - - - - - -| | | // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class StandardFrameConstants : public CommonFrameConstants { public: static constexpr int kFixedFrameSizeFromFp = 3 * kSystemPointerSize + kCPSlotSize; static constexpr int kFixedFrameSize = kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; static constexpr int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kSystemPointerSize; static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; static constexpr int kContextOffset = kContextOrFrameTypeOffset; static constexpr int kFunctionOffset = -2 * kSystemPointerSize - kCPSlotSize; static constexpr int kArgCOffset = -3 * kSystemPointerSize - kCPSlotSize; static constexpr int kExpressionsOffset = -4 * kSystemPointerSize - kCPSlotSize; static constexpr int kFirstPushedFrameValueOffset = kExpressionsOffset; static constexpr int kLastObjectOffset = kContextOffset; }; // TypedFrames have a type maker value below the saved FP/constant pool to // distinguish them from StandardFrames, which have a context in that position // instead. // // slot JS frame // +-----------------+-------------------------------- // -n-1 | parameter n | ^ // |- - - - - - - - -| | // -n | parameter n-1 | Caller // ... | ... | frame slots // -2 | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1 | parameter 0 | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | Fixed | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp |Frame Type Marker| v if a constant pool | // |-----------------+---- is used, cp = 1, | // 3+cp | pushed value 0 | ^ otherwise, cp = 0 | // |- - - - - - - - -| | | // 4+cp | pushed value 1 | | Callee // |- - - - - - - - -| | frame slots // ... | | Frame slots (slot >= 0) // |- - - - - - - - -| | | // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class TypedFrameConstants : public CommonFrameConstants { public: // FP-relative. static constexpr int kFrameTypeSize = kContextOrFrameTypeSize; static constexpr int kFrameTypeOffset = kContextOrFrameTypeOffset; static constexpr int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize; static constexpr int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kSystemPointerSize; static constexpr int kFixedFrameSize = StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; static constexpr int kFirstPushedFrameValueOffset = -kFixedFrameSizeFromFp - kSystemPointerSize; }; #define FRAME_PUSHED_VALUE_OFFSET(parent, x) \ (parent::kFirstPushedFrameValueOffset - (x)*kSystemPointerSize) #define FRAME_SIZE(parent, count) \ (parent::kFixedFrameSize + (count)*kSystemPointerSize) #define FRAME_SIZE_FROM_FP(parent, count) \ (parent::kFixedFrameSizeFromFp + (count)*kSystemPointerSize) #define DEFINE_FRAME_SIZES(parent, count) \ static constexpr int kFixedFrameSize = FRAME_SIZE(parent, count); \ static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; \ static constexpr int kFixedFrameSizeFromFp = \ FRAME_SIZE_FROM_FP(parent, count); \ static constexpr int kFixedSlotCountFromFp = \ kFixedFrameSizeFromFp / kSystemPointerSize; \ static constexpr int kFirstPushedFrameValueOffset = \ parent::kFirstPushedFrameValueOffset - (count) * kSystemPointerSize; \ /* The number of slots added on top of given parent frame type. */ \ template <typename TParentFrameConstants> \ static constexpr int getExtraSlotsCountFrom() { \ return kFixedSlotCount - TParentFrameConstants::kFixedSlotCount; \ } \ /* TODO(ishell): remove in favour of getExtraSlotsCountFrom() because */ \ /* it's not clear from which base should we count "extra" - from direct */ \ /* parent or maybe from parent's parent? */ \ static constexpr int kExtraSlotCount = \ kFixedSlotCount - parent::kFixedSlotCount #define STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(x) \ FRAME_PUSHED_VALUE_OFFSET(StandardFrameConstants, x) #define DEFINE_STANDARD_FRAME_SIZES(count) \ DEFINE_FRAME_SIZES(StandardFrameConstants, count) #define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \ FRAME_PUSHED_VALUE_OFFSET(TypedFrameConstants, x) #define DEFINE_TYPED_FRAME_SIZES(count) \ DEFINE_FRAME_SIZES(TypedFrameConstants, count) class BuiltinFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); DEFINE_TYPED_FRAME_SIZES(2); }; class ConstructFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); static constexpr int kConstructorOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); static constexpr int kNewTargetOrImplicitReceiverOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(4); DEFINE_TYPED_FRAME_SIZES(5); static constexpr int kLastObjectOffset = kContextOffset; }; class FastConstructFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); static constexpr int kImplicitReceiverOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); DEFINE_TYPED_FRAME_SIZES(2); }; #if V8_ENABLE_WEBASSEMBLY class CWasmEntryFrameConstants : public TypedFrameConstants { public: // FP-relative: static constexpr int kCEntryFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); DEFINE_TYPED_FRAME_SIZES(1); }; class WasmFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kWasmInstanceDataOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); DEFINE_TYPED_FRAME_SIZES(1); // The WasmTrapHandlerLandingPad builtin gets called from the WebAssembly // trap handler when an out-of-bounds memory access happened or when a null // reference gets dereferenced. This builtin then fakes a call from the // instruction that triggered the signal to the runtime. This is done by // setting a return address and then jumping to a builtin which will call // further to the runtime. As the return address we use the fault address + // {kProtectedInstructionReturnAddressOffset}. Using the fault address itself // would cause problems with safepoints and source positions. // // The problem with safepoints is that a safepoint has to be registered at the // return address, and that at most one safepoint should be registered at a // location. However, there could already be a safepoint registered at the // fault address if the fault address is the return address of a call. // // The problem with source positions is that the stack trace code looks for // the source position of a call before the return address. The source // position of the faulty memory access, however, is recorded at the fault // address. Therefore the stack trace code would not find the source position // if we used the fault address as the return address. static constexpr int kProtectedInstructionReturnAddressOffset = 1; }; #if V8_ENABLE_DRUMBRAKE class WasmInterpreterFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kWasmInstanceObjectOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); DEFINE_TYPED_FRAME_SIZES(1); }; // Fixed frame slots shared by the interpreter wasm-to-js wrapper. class WasmToJSInterpreterFrameConstants : public TypedFrameConstants { public: // This slot contains the number of slots at the top of the frame that need to // be scanned by the GC. static constexpr int kGCScanSlotLimitOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); // The stack pointer at the moment of the JS function call. static constexpr int kGCSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); // Returned for a successful completion of the WasmToJS call (no exception). static constexpr int kSuccess = 1; }; class WasmInterpreterCWasmEntryConstants : public TypedFrameConstants { public: // FP-relative: static constexpr int kCEntryFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); static constexpr int kSPFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); DEFINE_TYPED_FRAME_SIZES(2); }; #endif // V8_ENABLE_DRUMBRAKE class WasmExitFrameConstants : public WasmFrameConstants { public: // FP-relative. static const int kCallingPCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); DEFINE_TYPED_FRAME_SIZES(2); }; // Fixed frame slots used by the js-to-wasm wrapper. class JSToWasmWrapperFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kResultArrayParamOffset = 2 * kSystemPointerSize; // A WasmTrustedInstanceData or WasmImportData depending on the callee. static constexpr int kImplicitArgOffset = 3 * kSystemPointerSize; // Contains RawPtr to stack-allocated buffer. static constexpr int kWrapperBufferOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); // Offsets into the wrapper buffer for values passed from Torque to the // assembly builtin. static constexpr size_t kWrapperBufferReturnCount = 0; static constexpr size_t kWrapperBufferRefReturnCount = 4; static constexpr size_t kWrapperBufferSigRepresentationArray = 8; static constexpr size_t kWrapperBufferStackReturnBufferSize = 16; static constexpr size_t kWrapperBufferCallTarget = 24; static constexpr size_t kWrapperBufferParamStart = 32; static constexpr size_t kWrapperBufferParamEnd = 40; // Offsets into the wrapper buffer for values passed from the assembly builtin // to Torque. static constexpr size_t kWrapperBufferStackReturnBufferStart = 16; static constexpr size_t kWrapperBufferFPReturnRegister1 = 24; static constexpr size_t kWrapperBufferFPReturnRegister2 = 32; static constexpr size_t kWrapperBufferGPReturnRegister1 = 40; static constexpr size_t kWrapperBufferGPReturnRegister2 = kWrapperBufferGPReturnRegister1 + kSystemPointerSize; // Size of the wrapper buffer static constexpr int kWrapperBufferSize = kWrapperBufferGPReturnRegister2 + kSystemPointerSize; static_assert(kWrapperBufferParamEnd + kSystemPointerSize <= kWrapperBufferSize); }; // Fixed frame slots used by the ReturnPromiseOnSuspendAsm wrapper // and the WasmResume wrapper. class WasmJspiFrameConstants : public JSToWasmWrapperFrameConstants { public: // StackSwitching stack layout // ------+-----------------+---------------------- // | return addr | // fp |- - - - - - - - -| -------------------| // | fp | | // fp-p |- - - - - - - - -| | // | frame marker | | no GC scan // fp-2p |- - - - - - - - -| | // | scan_count | | // fp-3p |- - - - - - - - -| -------------------| // | wasm_instance | | // fp-4p |- - - - - - - - -| | fixed GC scan // | result_array | | // fp-5p |- - - - - - - - -| -------------------| // | .... | <- spill_slot_limit | // | spill slots | | GC scan scan_count slots // | .... | <- spill_slot_base--| // |- - - - - - - - -| | // This slot contains the number of slots at the top of the frame that need to // be scanned by the GC. static constexpr int kGCScanSlotCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); // Tagged pointer to WasmTrustedInstanceData or WasmImportData. static constexpr int kImplicitArgOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); // Tagged pointer to a JS Array for result values. static constexpr int kResultArrayOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); static constexpr int kLastSpillOffset = kResultArrayOffset; static constexpr int kNumSpillSlots = 4; }; class WasmToJSWrapperConstants { public: // FP-relative. static constexpr size_t kSignatureOffset = 2 * kSystemPointerSize; }; #if V8_ENABLE_DRUMBRAKE class BuiltinWasmInterpreterWrapperConstants : public TypedFrameConstants { public: // This slot contains the number of slots at the top of the frame that need to // be scanned by the GC. static constexpr int kGCScanSlotCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); // The number of parameters passed to this function. static constexpr int kInParamCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); // The number of parameters according to the signature. static constexpr int kParamCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); // The number of return values according to the siganture. static constexpr int kReturnCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); // `reps_` of wasm::FunctionSig. static constexpr int kSigRepsOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(4); // The current valuetype in the function signature being converted. static constexpr int kValueTypesArrayStartOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(5); // Array of arguments/return values. static constexpr int kArgRetsAddressOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(6); // Whether the array is for arguments or return values. static constexpr int kArgRetsIsArgsOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(7); // The index of the argument or return value being converted. static constexpr int kCurrentIndexOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(8); // Precomputed signature data. static constexpr int kSignatureDataOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(9); }; #endif // V8_ENABLE_DRUMBRAKE #endif // V8_ENABLE_WEBASSEMBLY class BuiltinContinuationFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); static constexpr int kFrameSPtoFPDeltaAtDeoptimize = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); static constexpr int kBuiltinContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); static constexpr int kBuiltinIndexOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); // The argument count is in the first allocatable register, stored below the // fixed part of the frame and therefore is not part of the fixed frame size. static constexpr int kArgCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(4); DEFINE_TYPED_FRAME_SIZES(4); // Returns the number of padding stack slots needed when we have // 'register_count' register slots. // This is needed on some architectures to ensure the stack pointer is // aligned. static int PaddingSlotCount(int register_count); }; class ExitFrameConstants : public TypedFrameConstants { public: // FP-relative. static constexpr int kSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); static constexpr int kLastExitFrameField = kSPOffset; DEFINE_TYPED_FRAME_SIZES(1); // FP-relative displacement of the caller's SP. It points just // below the saved PC. static constexpr int kCallerSPDisplacement = kCallerSPOffset; }; #define EXIT_FRAME_PUSHED_VALUE_OFFSET(x) \ FRAME_PUSHED_VALUE_OFFSET(ExitFrameConstants, x) #define DEFINE_EXIT_FRAME_SIZES(x) DEFINE_FRAME_SIZES(ExitFrameConstants, x) // Behaves like an exit frame but with extra arguments (target, new target and // JS arguments count), followed by JS arguments passed to the JS function // (receiver and etc.). // // slot JS frame // +-----------------+-------------------------------- // -n-1-k| parameter n | ^ // |- - - - - - - - -| | // -n-k | parameter n-1 | Caller // ... | ... | frame slots // -2-k | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1-k | receiver | v // -----+-----------------+-------------------------------- // -k | extra arg k-1 | ^ // |- - - - - - - - -| | // -k+1 | extra arg k-2 | Extra arguments passed // ... | ... | to CPP builtin // -2 | extra arg 1 | k := kNumExtraArgs // |- - - - - - - - -| | // -1 | extra arg 0 | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | ExitFrame | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp |Frame Type Marker| | if a constant pool | // |- - - - - - - - -| | is used, cp = 1, | // 3+cp | caller SP | v otherwise, cp = 0 | // |-----------------+---- | // 4+cp | ... | ^ Callee // |- - - - - - - - -| | frame slots // ... | C function args | Frame slots (slot >= 0) // |- - - - - - - - -| | | // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class BuiltinExitFrameConstants : public ExitFrameConstants { public: // The following constants must be in sync with BuiltinArguments' extra // arguments layout. This is guaraneed by static_asserts elsewhere. static constexpr int kNewTargetIndex = 0; static constexpr int kTargetIndex = 1; static constexpr int kArgcIndex = 2; // This padding is required only on arm64 to keep the SP 16-byte aligned. static constexpr int kOptionalPaddingIndex = 3; #if V8_TARGET_ARCH_ARM64 static constexpr int kNumExtraArgs = 4; #else static constexpr int kNumExtraArgs = 3; #endif // V8_TARGET_ARCH_ARM64 static constexpr int kNumExtraArgsWithReceiver = kNumExtraArgs + 1; // BuiltinArguments' arguments_ array. static constexpr int kArgumentsArrayOffset = kFixedFrameSizeAboveFp; static constexpr int kTargetOffset = kArgumentsArrayOffset + kTargetIndex * kSystemPointerSize; static constexpr int kNewTargetOffset = kArgumentsArrayOffset + kNewTargetIndex * kSystemPointerSize; static constexpr int kArgcOffset = kArgumentsArrayOffset + kArgcIndex * kSystemPointerSize; // JS arguments. static constexpr int kReceiverOffset = kArgumentsArrayOffset + kNumExtraArgs * kSystemPointerSize; static constexpr int kFirstArgumentOffset = kReceiverOffset + kSystemPointerSize; }; // Behaves like an exit frame but with v8::FunctionCallbackInfo's implicit // arguments (FCI), followed by JS arguments passed to the JS function // (receiver and etc.). // // slot JS frame // +-----------------+-------------------------------- // -n-1-k| parameter n | ^ // |- - - - - - - - -| | // -n-k | parameter n-1 | Caller // ... | ... | frame slots // -2-k | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1-k | receiver | v // -----+-----------------+-------------------------------- // -k | FCI slot k-1 | ^ // |- - - - - - - - -| | // -k+1 | FCI slot k-2 | v8::FunctionCallbackInfo's // ... | ... | Api arguments block // -2 | FCI slot 1 | k := FCI::kApiArgsLength // |- - - - - - - - -| | // -1 | FCI slot 0 | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | ExitFrame | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp |Frame Type Marker| | if a constant pool | // |- - - - - - - - -| | is used, cp = 1, | // 3+cp | caller SP | v otherwise, cp = 0 | // |-----------------+---- | // 4+cp | FCI::kArgcIndex | ^ Callee // |- - - - - - - - -| | frame slots // ... | C function args | Frame slots (slot >= 0) // |- - - - - - - - -| | | // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class ApiCallbackExitFrameConstants : public ExitFrameConstants { public: // FP-relative. // Offset of v8::FunctionCallbackInfo<T>::kArgcIndex slot. static constexpr int kFCIArgcOffset = EXIT_FRAME_PUSHED_VALUE_OFFSET(0); DEFINE_EXIT_FRAME_SIZES(1); // Make sure there's no gap between ExitFrame and kArgcIndex slot. static_assert(kSPOffset - kSystemPointerSize == kFCIArgcOffset); // v8::FunctionCallbackInfo object starts at argc slot which must be // right below the ExitFrame. static constexpr int kFunctionCallbackInfoOffset = kFCIArgcOffset; // v8::FunctionCallbackInfo's Api arguments. static constexpr int kApiArgsArrayOffset = kFixedFrameSizeAboveFp; static constexpr int kFunctionCallbackInfoApiArgsLength = 4; // The following constants must be in sync with v8::FunctionCallbackInfo's // layout. This is guaraneed by static_asserts elsewhere. static constexpr int kReturnValueOffset = kApiArgsArrayOffset + 1 * kSystemPointerSize; static constexpr int kContextOffset = kApiArgsArrayOffset + 2 * kSystemPointerSize; static constexpr int kTargetOffset = kApiArgsArrayOffset + 3 * kSystemPointerSize; // JS arguments. static constexpr int kReceiverOffset = kApiArgsArrayOffset + 4 * kSystemPointerSize; static constexpr int kFirstJSArgumentOffset = kReceiverOffset + kSystemPointerSize; }; // This frame has almost the same layout as ApiCallbackExitFrameConstants with // the only difference that this frame also has a "new.target" slot located // in the frame. // // slot JS frame // +-----------------+-------------------------------- // -n-1-k| parameter n | ^ // |- - - - - - - - -| | // -n-k | parameter n-1 | Caller // ... | ... | frame slots // -2-k | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1-k | receiver | v // -----+-----------------+-------------------------------- // -k | FCI slot ... | ^ // |- - - - - - - - -| | // -k+1 | FCI slot ... | v8::FunctionCallbackInfo's // ... | ... | Api arguments block // -2 | FCI slot ... | k := FCI::kApiArgsLength // |- - - - - - - - -| | // -1 | FCI slot ... | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | ExitFrame | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp |Frame Type Marker| | if a constant pool | // |- - - - - - - - -| | is used, cp = 1, | // 3+cp | caller SP | v otherwise, cp = 0 | // |-----------------+---- | // 4+cp | FCI::kArgcIndex | ^ | // |- - - - - - - - -| | <-- FCI object | // 5+cp | FCI::kNewTarget | | | // |- - - - - - - - -| | | // 6+cp | padding (arm64) | Frame slots Callee // |- - - - - - - - -| | frame slots // ... | C function args | | (slot >= 0) // |- - - - - - - - -| | | // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class ApiConstructExitFrameConstants : public ApiCallbackExitFrameConstants { public: // FP-relative. // Offset of v8::FunctionCallbackInfo<T>::kNewTargetIndex slot. static constexpr int kFCINewTargetOffset = FRAME_PUSHED_VALUE_OFFSET(ApiCallbackExitFrameConstants, 0); DEFINE_FRAME_SIZES(ApiCallbackExitFrameConstants, 1); // Make sure there's no gap between ApiCallbackExitFrame and kNewTargetIndex // slot. static_assert(kFCIArgcOffset - kSystemPointerSize == kFCINewTargetOffset); }; // Behaves like an exit frame but with v8::PropertyCallbackInfo's (PCI) // fields allocated in GC-ed area of the exit frame, followed by zero or // more parameters (required by some callback kinds). // // slot JS frame // +-----------------+-------------------------------- // -n-1-k| parameter n | ^ // |- - - - - - - - -| | // -n-k | parameter n-1 | Caller // ... | ... | frame slots // -2-k | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1-k | parameter 0 | v // -----+-----------------+-------------------------------- // -k | PCI slot ... | ^ // |- - - - - - - - -| | // -k+1 | PCI slot ... | v8::PropertyCallbackInfo's // ... | ... | PCI::args[k] // -2 | PCI slot ... | k := PCI::kApiArgsLength // |- - - - - - - - -| | // -1 | PCI slot ... | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | ExitFrame | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp |Frame Type Marker| | if a constant pool | // |- - - - - - - - -| | is used, cp = 1, | // 3+cp | caller SP | v otherwise, cp = 0 | // |-----------------+---- | // 4+cp | PCI::kPKeyIndex | ^ | // |- - - - - - - - -| | <-- PCI object | // ... | C function args | Frame slots Callee // |- - - - - - - - -| | frame slots // | | | (slot >= 0) // | | v | // -----+-----------------+----- <-- stack ptr ------------- // class ApiAccessorExitFrameConstants : public ExitFrameConstants { public: // The following constants must be in sync with v8::PropertyCallbackInfo's // layout. This is guaraneed by static_asserts elsewhere. static constexpr int kPropertyCallbackInfoReturnValueIndex = 1; static constexpr int kPropertyCallbackInfoHolderIndex = 3; static constexpr int kPropertyCallbackInfoValueIndex = 5; // The number of Api arguments pushed on top of PC for getter/setter // callbacks. static constexpr int kPropertyCallbackInfoGetterApiArgsLength = 4; static constexpr int kPropertyCallbackInfoSetterApiArgsLength = 6; // FP-relative. // Offset of v8::PropertyCallbackInfo<T>::kPropertyKeyIndex slot. static constexpr int kPropertyKeyOffset = EXIT_FRAME_PUSHED_VALUE_OFFSET(0); DEFINE_EXIT_FRAME_SIZES(1); // Make sure there's no gap between ExitFrame and kPropertyKeyOffset slot. static_assert(kSPOffset - kSystemPointerSize == kPropertyKeyOffset); // v8::PropertyCallbackInfo object starts at property key slot which must be // right below the ExitFrame. static constexpr int kPropertyCallbackInfoOffset = kPropertyKeyOffset; // v8::PropertyCallbackInfo's Api arguments (mandatory + optional). static constexpr int kArgsArrayOffset = kFixedFrameSizeAboveFp; static constexpr int kReturnValueOffset = kArgsArrayOffset + kPropertyCallbackInfoReturnValueIndex * kSystemPointerSize; static constexpr int kHolderOffset = kArgsArrayOffset + kPropertyCallbackInfoHolderIndex * kSystemPointerSize; static constexpr int kValueOffset = kArgsArrayOffset + kPropertyCallbackInfoValueIndex * kSystemPointerSize; }; // Unoptimized frames are used for interpreted and baseline-compiled JavaScript // frames. They are a "standard" frame, with an additional fixed header for the // BytecodeArray, bytecode offset (if running interpreted), feedback vector (if // running baseline code), and then the interpreter register file. // // slot JS frame // +-----------------+-------------------------------- // -n-1 | parameter n | ^ // |- - - - - - - - -| | // -n | parameter n-1 | Caller // ... | ... | frame slots // -2 | parameter 1 | (slot < 0) // |- - - - - - - - -| | // -1 | parameter 0 | v // -----+-----------------+-------------------------------- // 0 | return addr | ^ ^ // |- - - - - - - - -| | | // 1 | saved frame ptr | Fixed | // |- - - - - - - - -| Header <-- frame ptr | // 2 | [Constant Pool] | | | // |- - - - - - - - -| | | // 2+cp | Context | | if a constant pool | // |- - - - - - - - -| | is used, cp = 1, | // 3+cp | JSFunction | | otherwise, cp = 0 | // |- - - - - - - - -| | | // 4+cp | argc | v | // +-----------------+---- | // 5+cp | BytecodeArray | ^ | // |- - - - - - - - -| | | // 6+cp | offset / cell | Unoptimized code header | // |- - - - - - - - -| | | // 7+cp | FBV | v | // +-----------------+---- | // 8+cp | register 0 | ^ Callee // |- - - - - - - - -| | frame slots // 9+cp | register 1 | Register file (slot >= 0) // ... | ... | | | // | register n-1 | | | // |- - - - - - - - -| | | // 9+cp+n| register n | v v // -----+-----------------+----- <-- stack ptr ------------- // class UnoptimizedFrameConstants : public StandardFrameConstants { public: // FP-relative. static constexpr int kBytecodeArrayFromFp = STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(0); static constexpr int kBytecodeOffsetOrFeedbackCellFromFp = STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(1); static constexpr int kFeedbackVectorFromFp = STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(2); DEFINE_STANDARD_FRAME_SIZES(3); static constexpr int kFirstParamFromFp = StandardFrameConstants::kCallerSPOffset; static constexpr int kRegisterFileFromFp = -kFixedFrameSizeFromFp - kSystemPointerSize; static constexpr int kExpressionsOffset = kRegisterFileFromFp; // Expression index for {JavaScriptFrame::GetExpressionAddress}. static constexpr int kBytecodeArrayExpressionIndex = -3; static constexpr int kBytecodeOffsetOrFeedbackCellExpressionIndex = -2; static constexpr int kFeedbackVectorExpressionIndex = -1; static constexpr int kRegisterFileExpressionIndex = 0; // Returns the number of stack slots needed for 'register_count' registers. // This is needed because some architectures must pad the stack frame with // additional stack slots to ensure the stack pointer is aligned. static int RegisterStackSlotCount(int register_count); }; // Interpreter frames are unoptimized frames that are being executed by the // interpreter. In this case, the "offset or cell" slot contains the bytecode // offset of the currently executing bytecode. class InterpreterFrameConstants : public UnoptimizedFrameConstants { public: static constexpr int kBytecodeOffsetExpressionIndex = kBytecodeOffsetOrFeedbackCellExpressionIndex; static constexpr int kBytecodeOffsetFromFp = kBytecodeOffsetOrFeedbackCellFromFp; }; // Sparkplug frames are unoptimized frames that are being executed by // sparkplug-compiled baseline code. base. In this case, the "offset or cell" // slot contains the closure feedback cell. class BaselineFrameConstants : public UnoptimizedFrameConstants { public: static constexpr int kFeedbackCellExpressionIndex = kBytecodeOffsetOrFeedbackCellExpressionIndex; static constexpr int kFeedbackCellFromFp = kBytecodeOffsetOrFeedbackCellFromFp; }; inline static int FPOffsetToFrameSlot(int frame_offset) { return StandardFrameConstants::kFixedSlotCountAboveFp - 1 - frame_offset / kSystemPointerSize; } inline static int FrameSlotToFPOffset(int slot) { return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) * kSystemPointerSize; } } // namespace internal } // namespace v8 #if V8_TARGET_ARCH_IA32 #include "src/execution/ia32/frame-constants-ia32.h" #elif V8_TARGET_ARCH_X64 #include "src/execution/x64/frame-constants-x64.h" #elif V8_TARGET_ARCH_ARM64 #include "src/execution/arm64/frame-constants-arm64.h" #elif V8_TARGET_ARCH_ARM #include "src/execution/arm/frame-constants-arm.h" #elif V8_TARGET_ARCH_PPC64 #include "src/execution/ppc/frame-constants-ppc.h" #elif V8_TARGET_ARCH_MIPS64 #include "src/execution/mips64/frame-constants-mips64.h" #elif V8_TARGET_ARCH_LOONG64 #include "src/execution/loong64/frame-constants-loong64.h" #elif V8_TARGET_ARCH_S390X #include "src/execution/s390/frame-constants-s390.h" #elif V8_TARGET_ARCH_RISCV32 || V8_TARGET_ARCH_RISCV64 #include "src/execution/riscv/frame-constants-riscv.h" #else #error Unsupported target architecture. #endif #endif // V8_EXECUTION_FRAME_CONSTANTS_H_