frames.tq 5.87 KB
Newer Older
1 2 3 4
// 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.

5
type FrameType extends Smi constexpr 'StackFrame::Type';
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
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;
21
  return %RawDownCast<FrameType>(BitcastWordToTaggedSigned(i));
22 23 24 25 26
}
Cast<FrameType>(o: Object): FrameType
    labels CastError {
  if (TaggedIsNotSmi(o)) goto CastError;
  assert(
27 28
      Convert<int32>(BitcastTaggedToWordForTagAndSmiBits(o)) <
      Convert<int32>(kFrameTypeCount << kSmiTagSize));
29
  return %RawDownCast<FrameType>(o);
30 31
}

32 33 34 35
type FrameBase extends RawPtr constexpr 'void*';
type StandardFrame extends FrameBase constexpr 'void*';
type ArgumentsAdaptorFrame extends FrameBase constexpr 'void*';
type StubFrame extends FrameBase constexpr 'void*';
36 37
type FrameWithArguments = StandardFrame|ArgumentsAdaptorFrame;
type Frame = FrameWithArguments|StubFrame;
38 39 40 41 42 43 44 45 46 47 48 49 50 51

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);
}
52 53 54
macro LoadIntptrFromFrame(f: Frame, o: constexpr int32): intptr {
  return LoadBufferIntptr(f, o);
}
55 56 57 58

const kStandardFrameFunctionOffset: constexpr int31
    generates 'StandardFrameConstants::kFunctionOffset';
operator '.function' macro LoadFunctionFromFrame(f: Frame): JSFunction {
59
  // TODO(danno): Use RawDownCast here in order to avoid passing the implicit
60 61 62
  // context, since this accessor is used in legacy CSA code through
  // LoadTargetFromFrame
  const result: Object = LoadObjectFromFrame(f, kStandardFrameFunctionOffset);
63
  return %RawDownCast<JSFunction>(result);
64 65 66 67 68 69
}

const kStandardFrameCallerFPOffset: constexpr int31
    generates 'StandardFrameConstants::kCallerFPOffset';
operator '.caller' macro LoadCallerFromFrame(f: Frame): Frame {
  const result: RawPtr = LoadPointerFromFrame(f, kStandardFrameCallerFPOffset);
70
  return %RawDownCast<Frame>(result);
71 72
}

73 74 75 76 77 78
const kStandardFrameArgCOffset: constexpr int31
    generates 'StandardFrameConstants::kArgCOffset';
operator '.argument_count' macro LoadArgCFromFrame(f: Frame): intptr {
  return LoadIntptrFromFrame(f, kStandardFrameArgCOffset);
}

79
type ContextOrFrameType = Context|FrameType;
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
Cast<ContextOrFrameType>(implicit context: Context)(o: Object):
    ContextOrFrameType
    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)(
109
    f: ArgumentsAdaptorFrame): Smi {
110 111 112 113
  return LoadSmiFromFrame(f, kArgumentsAdaptorFrameLengthOffset);
}

operator '==' macro FrameTypeEquals(f1: FrameType, f2: FrameType): bool {
114
  return TaggedEqual(f1, f2);
115 116
}

117 118
macro Cast<A : type extends Frame>(implicit context: Context)(o: Frame):
    A labels CastError;
119 120 121 122 123 124 125 126 127 128 129 130 131 132
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)) {
133
    return %RawDownCast<StandardFrame>(f);
134 135 136 137
  }
  goto CastError;
}

138 139
Cast<ArgumentsAdaptorFrame>(implicit context: Context)(f: Frame):
    ArgumentsAdaptorFrame labels CastError {
140 141 142
  const t: FrameType =
      Cast<FrameType>(f.context_or_frame_type) otherwise CastError;
  if (t == ARGUMENTS_ADAPTOR_FRAME) {
143
    return %RawDownCast<ArgumentsAdaptorFrame>(f);
144 145 146 147 148 149 150 151 152 153
  }
  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.
154
@export
155 156 157
macro LoadTargetFromFrame(): JSFunction {
  return LoadFramePointer().function;
}