blob: 3b716b7a64725ff0e2514a30ee3b85b7d091a332 [file] [log] [blame]
// Copyright 2018 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.
type FrameType extends Smi constexpr 'StackFrame::Type';
const ARGUMENTS_ADAPTOR_FRAME: constexpr FrameType
generates 'StackFrame::ARGUMENTS_ADAPTOR';
const STUB_FRAME: constexpr FrameType
generates 'StackFrame::STUB';
const kFrameTypeCount:
constexpr int31 generates 'StackFrame::NUMBER_OF_TYPES';
FromConstexpr<FrameType, constexpr FrameType>(t: constexpr FrameType):
FrameType {
// Note that althought FrameTypes sometimes masquerade as Smis (their
// LSB is a zero), they are not. For efficiency in storing them as a
// constant into a frame, they are simply the FrameType value shifted
// up by a single bit.
const i: constexpr uintptr = %RawConstexprCast<constexpr uintptr>(t)
<< kSmiTagSize;
return %RawDownCast<FrameType>(BitcastWordToTaggedSigned(i));
Cast<FrameType>(o: Object): FrameType
labels CastError {
if (TaggedIsNotSmi(o)) goto CastError;
Convert<int32>(BitcastTaggedToWordForTagAndSmiBits(o)) <
Convert<int32>(kFrameTypeCount << kSmiTagSize));
return %RawDownCast<FrameType>(o);
type FrameBase extends RawPtr constexpr 'void*';
type StandardFrame extends FrameBase constexpr 'void*';
type ArgumentsAdaptorFrame extends FrameBase constexpr 'void*';
type StubFrame extends FrameBase constexpr 'void*';
type FrameWithArguments = StandardFrame|ArgumentsAdaptorFrame;
type Frame = FrameWithArguments|StubFrame;
extern macro LoadFramePointer(): Frame;
extern macro LoadParentFramePointer(): Frame;
// Load values from a specified frame by given offset in bytes.
macro LoadObjectFromFrame(f: Frame, o: constexpr int32): Object {
return LoadBufferObject(f, o);
macro LoadPointerFromFrame(f: Frame, o: constexpr int32): RawPtr {
return LoadBufferPointer(f, o);
macro LoadSmiFromFrame(f: Frame, o: constexpr int32): Smi {
return LoadBufferSmi(f, o);
macro LoadIntptrFromFrame(f: Frame, o: constexpr int32): intptr {
return LoadBufferIntptr(f, o);
const kStandardFrameFunctionOffset: constexpr int31
generates 'StandardFrameConstants::kFunctionOffset';
operator '.function' macro LoadFunctionFromFrame(f: Frame): JSFunction {
// TODO(danno): Use RawDownCast here in order to avoid passing the implicit
// context, since this accessor is used in legacy CSA code through
// LoadTargetFromFrame
const result: Object = LoadObjectFromFrame(f, kStandardFrameFunctionOffset);
return %RawDownCast<JSFunction>(result);
const kStandardFrameCallerFPOffset: constexpr int31
generates 'StandardFrameConstants::kCallerFPOffset';
operator '.caller' macro LoadCallerFromFrame(f: Frame): Frame {
const result: RawPtr = LoadPointerFromFrame(f, kStandardFrameCallerFPOffset);
return %RawDownCast<Frame>(result);
const kStandardFrameArgCOffset: constexpr int31
generates 'StandardFrameConstants::kArgCOffset';
operator '.argument_count' macro LoadArgCFromFrame(f: Frame): intptr {
return LoadIntptrFromFrame(f, kStandardFrameArgCOffset);
type ContextOrFrameType = Context|FrameType;
Cast<ContextOrFrameType>(implicit context: Context)(o: Object):
labels CastError {
typeswitch (o) {
case (c: Context): {
return c;
case (t: FrameType): {
return t;
case (Object): {
goto CastError;
const kStandardFrameContextOrFrameTypeOffset: constexpr int31
generates 'StandardFrameConstants::kContextOrFrameTypeOffset';
operator '.context_or_frame_type'
macro LoadContextOrFrameTypeFromFrame(implicit context: Context)(f: Frame):
ContextOrFrameType {
return UnsafeCast<ContextOrFrameType>(
LoadObjectFromFrame(f, kStandardFrameContextOrFrameTypeOffset));
const kArgumentsAdaptorFrameLengthOffset: constexpr int31
generates 'ArgumentsAdaptorFrameConstants::kLengthOffset';
operator '.length'
macro LoadLengthFromAdapterFrame(implicit context: Context)(
f: ArgumentsAdaptorFrame): Smi {
return LoadSmiFromFrame(f, kArgumentsAdaptorFrameLengthOffset);
operator '==' macro FrameTypeEquals(f1: FrameType, f2: FrameType): bool {
return TaggedEqual(f1, f2);
macro Cast<A : type extends Frame>(implicit context: Context)(o: Frame):
A labels CastError;
Cast<StandardFrame>(implicit context: Context)(f: Frame):
StandardFrame labels CastError {
const o: HeapObject =
Cast<HeapObject>(f.context_or_frame_type) otherwise CastError;
// StandardFrames (which include interpreted and JIT-compiled frames),
// unlike other frame types, don't have their own type marker stored in
// the frame, but rather have the function's context stored where the
// type marker is stored for other frame types. From Torque, it would
// be quite expensive to do the test required to distinguish interpreter
// frames from JITted ones (and other StandardFrame types), so
// StandardFrame is the level of granularity support when iterating the
// stack from generated code.
// See the descriptions and frame layouts in src/frame-constants.h.
if (IsContext(o)) {
return %RawDownCast<StandardFrame>(f);
goto CastError;
Cast<ArgumentsAdaptorFrame>(implicit context: Context)(f: Frame):
ArgumentsAdaptorFrame labels CastError {
const t: FrameType =
Cast<FrameType>(f.context_or_frame_type) otherwise CastError;
return %RawDownCast<ArgumentsAdaptorFrame>(f);
goto CastError;
// Load target function from the current JS frame.
// This is an alternative way of getting the target function in addition to
// Parameter(Descriptor::kJSTarget). The latter should be used near the
// beginning of builtin code while the target value is still in the register
// and the former should be used in slow paths in order to reduce register
// pressure on the fast path.
macro LoadTargetFromFrame(): JSFunction {
return LoadFramePointer().function;