summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/frames.tq
blob: 555918834795192bbc7f2219566f84dc6809bd4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 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;
  assert(
      (Convert<uintptr>(BitcastTaggedToWord(o)) >>> kSmiTagSize) <
      kFrameTypeCount);
  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);
}

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);
}

type ContextOrFrameType = Context | FrameType;
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)(
    f: ArgumentsAdaptorFrame): Smi {
  return LoadSmiFromFrame(f, kArgumentsAdaptorFrameLengthOffset);
}

operator '==' macro FrameTypeEquals(f1: FrameType, f2: FrameType): bool {
  return WordEqual(f1, f2);
}

macro Cast<A: type>(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;
  if (t == ARGUMENTS_ADAPTOR_FRAME) {
    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.
@export
macro LoadTargetFromFrame(): JSFunction {
  return LoadFramePointer().function;
}