v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
interpreter-assembler.h
Go to the documentation of this file.
1// Copyright 2015 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_INTERPRETER_INTERPRETER_ASSEMBLER_H_
6#define V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_
7
13#include "src/runtime/runtime.h"
14
15namespace v8 {
16namespace internal {
17namespace interpreter {
18
20 public:
22 OperandScale operand_scale);
26
27 // Returns the 32-bit unsigned count immediate for bytecode operand
28 // |operand_index| in the current bytecode.
29 TNode<Uint32T> BytecodeOperandCount(int operand_index);
30 // Returns the 32-bit unsigned flag for bytecode operand |operand_index|
31 // in the current bytecode.
32 TNode<Uint32T> BytecodeOperandFlag8(int operand_index);
33 // Returns the 32-bit unsigned 2-byte flag for bytecode operand
34 // |operand_index| in the current bytecode.
35 TNode<Uint32T> BytecodeOperandFlag16(int operand_index);
36 // Returns the 32-bit zero-extended index immediate for bytecode operand
37 // |operand_index| in the current bytecode.
38 TNode<Uint32T> BytecodeOperandIdxInt32(int operand_index);
39 // Returns the word zero-extended index immediate for bytecode operand
40 // |operand_index| in the current bytecode.
41 TNode<UintPtrT> BytecodeOperandIdx(int operand_index);
42 // Returns the smi index immediate for bytecode operand |operand_index|
43 // in the current bytecode.
44 TNode<Smi> BytecodeOperandIdxSmi(int operand_index);
45 // Returns the TaggedIndex immediate for bytecode operand |operand_index|
46 // in the current bytecode.
47 TNode<TaggedIndex> BytecodeOperandIdxTaggedIndex(int operand_index);
48 // Returns the 32-bit unsigned immediate for bytecode operand |operand_index|
49 // in the current bytecode.
50 TNode<Uint32T> BytecodeOperandUImm(int operand_index);
51 // Returns the word-size unsigned immediate for bytecode operand
52 // |operand_index| in the current bytecode.
53 TNode<UintPtrT> BytecodeOperandUImmWord(int operand_index);
54 // Returns the unsigned smi immediate for bytecode operand |operand_index| in
55 // the current bytecode.
56 TNode<Smi> BytecodeOperandUImmSmi(int operand_index);
57 // Returns the 32-bit signed immediate for bytecode operand |operand_index|
58 // in the current bytecode.
59 TNode<Int32T> BytecodeOperandImm(int operand_index);
60 // Returns the word-size signed immediate for bytecode operand |operand_index|
61 // in the current bytecode.
62 TNode<IntPtrT> BytecodeOperandImmIntPtr(int operand_index);
63 // Returns the smi immediate for bytecode operand |operand_index| in the
64 // current bytecode.
65 TNode<Smi> BytecodeOperandImmSmi(int operand_index);
66 // Returns the 32-bit unsigned runtime id immediate for bytecode operand
67 // |operand_index| in the current bytecode.
68 TNode<Uint32T> BytecodeOperandRuntimeId(int operand_index);
69 // Returns the word zero-extended native context index immediate for bytecode
70 // operand |operand_index| in the current bytecode.
71 TNode<UintPtrT> BytecodeOperandNativeContextIndex(int operand_index);
72 // Returns the 32-bit unsigned intrinsic id immediate for bytecode operand
73 // |operand_index| in the current bytecode.
74 TNode<Uint32T> BytecodeOperandIntrinsicId(int operand_index);
75 // Accumulator.
76 TNode<Object> GetAccumulator();
77 void SetAccumulator(TNode<Object> value);
78 void ClobberAccumulator(TNode<Object> clobber_value);
79
80 // Context.
81 TNode<Context> GetContext();
82 void SetContext(TNode<Context> value);
83
84 // Context at |depth| in the context chain starting at |context|.
85 TNode<Context> GetContextAtDepth(TNode<Context> context,
86 TNode<Uint32T> depth);
87
88 // A RegListNodePair provides an abstraction over lists of registers.
90 public:
91 RegListNodePair(TNode<IntPtrT> base_reg_location, TNode<Word32T> reg_count)
92 : base_reg_location_(base_reg_location), reg_count_(reg_count) {}
93
94 TNode<Word32T> reg_count() const { return reg_count_; }
95 TNode<IntPtrT> base_reg_location() const { return base_reg_location_; }
96
97 private:
100 };
101
102 // Backup/restore register file to/from a fixed array of the correct length.
103 // There is an asymmetry between suspend/export and resume/import.
104 // - Suspend copies arguments and registers to the generator.
105 // - Resume copies only the registers from the generator, the arguments
106 // are copied by the ResumeGenerator trampoline.
107 TNode<FixedArray> ExportParametersAndRegisterFile(
109 TNode<FixedArray> ImportRegisterFile(TNode<FixedArray> array,
111
112 // Loads from and stores to the interpreter register file.
113 TNode<Object> LoadRegister(Register reg);
114 TNode<IntPtrT> LoadAndUntagRegister(Register reg);
115 TNode<Object> LoadRegisterAtOperandIndex(int operand_index);
116 std::pair<TNode<Object>, TNode<Object>> LoadRegisterPairAtOperandIndex(
117 int operand_index);
118 void StoreRegister(TNode<Object> value, Register reg);
119 void StoreRegisterAtOperandIndex(TNode<Object> value, int operand_index);
120 void StoreRegisterPairAtOperandIndex(TNode<Object> value1,
121 TNode<Object> value2, int operand_index);
122 void StoreRegisterTripleAtOperandIndex(TNode<Object> value1,
123 TNode<Object> value2,
124 TNode<Object> value3,
125 int operand_index);
126
127 RegListNodePair GetRegisterListAtOperandIndex(int operand_index);
128 TNode<Object> LoadRegisterFromRegisterList(const RegListNodePair& reg_list,
129 int index);
130 TNode<IntPtrT> RegisterLocationInRegisterList(const RegListNodePair& reg_list,
131 int index);
132
133 // Load constant at the index specified in operand |operand_index| from the
134 // constant pool.
135 TNode<Object> LoadConstantPoolEntryAtOperandIndex(int operand_index);
136 // Load and untag constant at the index specified in operand |operand_index|
137 // from the constant pool.
138 TNode<IntPtrT> LoadAndUntagConstantPoolEntryAtOperandIndex(int operand_index);
139 // Load constant at |index| in the constant pool.
140 TNode<Object> LoadConstantPoolEntry(TNode<WordT> index);
141 // Load and untag constant at |index| in the constant pool.
142 TNode<IntPtrT> LoadAndUntagConstantPoolEntry(TNode<WordT> index);
143
144 TNode<JSFunction> LoadFunctionClosure();
145
146 // Load the FeedbackVector for the current function. The returned node could
147 // be undefined.
148 TNode<Union<FeedbackVector, Undefined>> LoadFeedbackVector();
149
151#ifndef V8_JITLESS
152 return LoadFeedbackVector();
153#else
154 return UndefinedConstant();
155#endif // V8_JITLESS
156 }
157
159#ifndef V8_JITLESS
160 return UpdateFeedbackMode::kOptionalFeedback;
161#else
162 return UpdateFeedbackMode::kNoFeedback;
163#endif // !V8_JITLESS
164 }
165
166 // Call JSFunction or Callable |function| with |args| arguments, possibly
167 // including the receiver depending on |receiver_mode|. After the call returns
168 // directly dispatches to the next bytecode.
169 void CallJSAndDispatch(TNode<JSAny> function, TNode<Context> context,
170 const RegListNodePair& args,
171 ConvertReceiverMode receiver_mode);
172
173 // Call JSFunction or Callable |function| with |arg_count| arguments (not
174 // including receiver) passed as |args|, possibly including the receiver
175 // depending on |receiver_mode|. After the call returns directly dispatches to
176 // the next bytecode.
177 template <class... TArgs>
178 void CallJSAndDispatch(TNode<JSAny> function, TNode<Context> context,
179 TNode<Word32T> arg_count,
180 ConvertReceiverMode receiver_mode, TArgs... args);
181
182 // Call JSFunction or Callable |function| with |args|
183 // arguments (not including receiver), and the final argument being spread.
184 // After the call returns directly dispatches to the next bytecode.
185 void CallJSWithSpreadAndDispatch(TNode<JSAny> function,
186 TNode<Context> context,
187 const RegListNodePair& args,
188 TNode<UintPtrT> slot_id);
189
190 // Call constructor |target| with |args| arguments (not including receiver).
191 // The |new_target| is the same as the |target| for the new keyword, but
192 // differs for the super keyword.
193 TNode<Object> Construct(
195 const RegListNodePair& args, TNode<UintPtrT> slot_id,
196 TNode<Union<FeedbackVector, Undefined>> maybe_feedback_vector);
197
198 // Call constructor |target| with |args| arguments (not including
199 // receiver). The last argument is always a spread. The |new_target| is the
200 // same as the |target| for the new keyword, but differs for the super
201 // keyword.
202 TNode<Object> ConstructWithSpread(TNode<JSAny> target, TNode<Context> context,
204 const RegListNodePair& args,
205 TNode<UintPtrT> slot_id);
206
207 // Call constructor |target|, forwarding all arguments in the current JS
208 // frame.
209 TNode<Object> ConstructForwardAllArgs(TNode<JSAny> target,
210 TNode<Context> context,
212 TNode<TaggedIndex> slot_id);
213
214 // Call runtime function with |args| arguments.
215 template <class T = Object>
216 TNode<T> CallRuntimeN(TNode<Uint32T> function_id, TNode<Context> context,
217 const RegListNodePair& args, int return_count);
218
219 // Jump forward relative to the current bytecode by the |jump_offset|.
220 void Jump(TNode<IntPtrT> jump_offset);
221
222 // Jump backward relative to the current bytecode by the |jump_offset|.
223 void JumpBackward(TNode<IntPtrT> jump_offset);
224
225 // Jump forward relative to the current bytecode by |jump_offset| if the
226 // word values |lhs| and |rhs| are equal.
227 void JumpIfTaggedEqual(TNode<Object> lhs, TNode<Object> rhs,
228 TNode<IntPtrT> jump_offset);
229
230 // Jump forward relative to the current bytecode by offest specified in
231 // operand |operand_index| if the word values |lhs| and |rhs| are equal.
232 void JumpIfTaggedEqual(TNode<Object> lhs, TNode<Object> rhs,
233 int operand_index);
234
235 // Jump forward relative to the current bytecode by offest specified from the
236 // constant pool if the word values |lhs| and |rhs| are equal.
237 // The constant's index is specified in operand |operand_index|.
238 void JumpIfTaggedEqualConstant(TNode<Object> lhs, TNode<Object> rhs,
239 int operand_index);
240
241 // Jump forward relative to the current bytecode by |jump_offset| if the
242 // word values |lhs| and |rhs| are not equal.
243 void JumpIfTaggedNotEqual(TNode<Object> lhs, TNode<Object> rhs,
244 TNode<IntPtrT> jump_offset);
245
246 // Jump forward relative to the current bytecode by offest specified in
247 // operand |operand_index| if the word values |lhs| and |rhs| are not equal.
248 void JumpIfTaggedNotEqual(TNode<Object> lhs, TNode<Object> rhs,
249 int operand_index);
250
251 // Jump forward relative to the current bytecode by offest specified from the
252 // constant pool if the word values |lhs| and |rhs| are not equal.
253 // The constant's index is specified in operand |operand_index|.
254 void JumpIfTaggedNotEqualConstant(TNode<Object> lhs, TNode<Object> rhs,
255 int operand_index);
256
257 // Updates the profiler interrupt budget for a return.
258 void UpdateInterruptBudgetOnReturn();
259
260 // Adjusts the interrupt budget by the provided weight. Returns the new
261 // budget.
262 TNode<Int32T> UpdateInterruptBudget(TNode<Int32T> weight);
263 // Decrements the bytecode array's interrupt budget by a 32-bit unsigned
264 // |weight| and calls Runtime::kInterrupt if counter reaches zero.
269 void DecreaseInterruptBudget(TNode<Int32T> weight,
270 StackCheckBehavior stack_check_behavior);
271
272 TNode<Int8T> LoadOsrState(TNode<FeedbackVector> feedback_vector);
273
274 // Dispatch to the bytecode.
275 void Dispatch();
276
277 // Dispatch bytecode as wide operand variant.
278 void DispatchWide(OperandScale operand_scale);
279
280 // Dispatch to |target_bytecode| at |new_bytecode_offset|.
281 // |target_bytecode| should be equivalent to loading from the offset.
282 void DispatchToBytecode(TNode<WordT> target_bytecode,
283 TNode<IntPtrT> new_bytecode_offset);
284
285 // Dispatches to |target_bytecode| at BytecodeOffset(). Includes short-star
286 // lookahead if the current bytecode_ is likely followed by a short-star
287 // instruction.
288 void DispatchToBytecodeWithOptionalStarLookahead(
289 TNode<WordT> target_bytecode);
290
291 // Abort with the given abort reason.
292 void Abort(AbortReason abort_reason);
293 void AbortIfWordNotEqual(TNode<WordT> lhs, TNode<WordT> rhs,
294 AbortReason abort_reason);
295 // Abort if |register_count| is invalid for given register file array.
296 void AbortIfRegisterCountInvalid(TNode<FixedArray> parameters_and_registers,
298 TNode<UintPtrT> register_count);
299
300 // Attempts to OSR.
305 void OnStackReplacement(TNode<Context> context,
306 TNode<FeedbackVector> feedback_vector,
307 TNode<IntPtrT> relative_jump,
308 TNode<Int32T> loop_depth,
309 TNode<IntPtrT> feedback_slot, TNode<Int8T> osr_state,
310 OnStackReplacementParams params);
311
312 // The BytecodeOffset() is the offset from the ByteCodeArray pointer; to
313 // translate into runtime `BytecodeOffset` (defined in utils.h as the offset
314 // from the start of the bytecode section), this constant has to be applied.
315 static constexpr int kFirstBytecodeOffset =
316 BytecodeArray::kHeaderSize - kHeapObjectTag;
317
318 // Returns the offset from the BytecodeArrayPointer of the current bytecode.
320
321 protected:
322 Bytecode bytecode() const { return bytecode_; }
323 static bool TargetSupportsUnalignedAccess();
324
325 void ToNumberOrNumeric(Object::Conversion mode);
326
327 void StoreRegisterForShortStar(TNode<Object> value, TNode<WordT> opcode);
328
329 // Load the bytecode at |bytecode_offset|.
330 TNode<WordT> LoadBytecode(TNode<IntPtrT> bytecode_offset);
331
332 // Load the parameter count of the current function from its BytecodeArray.
333 TNode<IntPtrT> LoadParameterCountWithoutReceiver();
334
335 private:
336 // Returns a pointer to the current function's BytecodeArray object.
337 TNode<BytecodeArray> BytecodeArrayTaggedPointer();
338
339 // Returns a pointer to first entry in the interpreter dispatch table.
340 TNode<ExternalReference> DispatchTablePointer();
341
342 // Returns the accumulator value without checking whether bytecode
343 // uses it. This is intended to be used only in dispatch and in
344 // tracing as these need to bypass accumulator use validity checks.
345 TNode<Object> GetAccumulatorUnchecked();
346
347 // Returns the frame pointer for the interpreted frame of the function being
348 // interpreted.
349 TNode<RawPtrT> GetInterpretedFramePointer();
350
351 // Operations on registers.
352 TNode<IntPtrT> RegisterLocation(Register reg);
353 TNode<IntPtrT> RegisterLocation(TNode<IntPtrT> reg_index);
354 TNode<IntPtrT> NextRegister(TNode<IntPtrT> reg_index);
355 TNode<Object> LoadRegister(TNode<IntPtrT> reg_index);
356 void StoreRegister(TNode<Object> value, TNode<IntPtrT> reg_index);
357
358 // Saves and restores interpreter bytecode offset to the interpreter stack
359 // frame when performing a call.
360 void CallPrologue();
361 void CallEpilogue();
362
363 // Increment the dispatch counter for the (current, next) bytecode pair.
364 void TraceBytecodeDispatch(TNode<WordT> target_bytecode);
365
366 // Traces the current bytecode by calling |function_id|.
367 void TraceBytecode(Runtime::FunctionId function_id);
368
369 // Returns the offset of register |index| relative to RegisterFilePointer().
370 TNode<IntPtrT> RegisterFrameOffset(TNode<IntPtrT> index);
371
372 // Returns the offset of an operand relative to the current bytecode offset.
373 TNode<IntPtrT> OperandOffset(int operand_index);
374
375 // Returns a value built from an sequence of bytes in the bytecode
376 // array starting at |relative_offset| from the current bytecode.
377 // The |result_type| determines the size and signedness. of the
378 // value read. This method should only be used on architectures that
379 // do not support unaligned memory accesses.
380 TNode<Word32T> BytecodeOperandReadUnaligned(int relative_offset,
381 MachineType result_type);
382
383 // Returns zero- or sign-extended to word32 value of the operand.
384 TNode<Uint8T> BytecodeOperandUnsignedByte(int operand_index);
385 TNode<Int8T> BytecodeOperandSignedByte(int operand_index);
386 TNode<Uint16T> BytecodeOperandUnsignedShort(int operand_index);
387 TNode<Int16T> BytecodeOperandSignedShort(int operand_index);
388 TNode<Uint32T> BytecodeOperandUnsignedQuad(int operand_index);
389 TNode<Int32T> BytecodeOperandSignedQuad(int operand_index);
390
391 // Returns zero- or sign-extended to word32 value of the operand of
392 // given size.
393 TNode<Int32T> BytecodeSignedOperand(int operand_index,
394 OperandSize operand_size);
395 TNode<Uint32T> BytecodeUnsignedOperand(int operand_index,
396 OperandSize operand_size);
397
398 // Returns the word-size sign-extended register index for bytecode operand
399 // |operand_index| in the current bytecode.
400 TNode<IntPtrT> BytecodeOperandReg(int operand_index);
401
402 // Returns the word zero-extended index immediate for bytecode operand
403 // |operand_index| in the current bytecode for use when loading a constant
404 // pool element.
405 TNode<UintPtrT> BytecodeOperandConstantPoolIdx(int operand_index);
406
407 // Jump to a specific bytecode offset.
408 void JumpToOffset(TNode<IntPtrT> new_bytecode_offset);
409
410 // Jump forward relative to the current bytecode by |jump_offset| if the
411 // |condition| is true. Helper function for JumpIfTaggedEqual and
412 // JumpIfTaggedNotEqual.
413 void JumpConditional(TNode<BoolT> condition, TNode<IntPtrT> jump_offset);
414
415 // Jump forward relative to the current bytecode by offest specified in
416 // operand |operand_index| if the |condition| is true. Helper function for
417 // JumpIfTaggedEqual and JumpIfTaggedNotEqual.
418 void JumpConditionalByImmediateOperand(TNode<BoolT> condition,
419 int operand_index);
420
421 // Jump forward relative to the current bytecode by offest specified from the
422 // constant pool if the |condition| is true. The constant's index is specified
423 // in operand |operand_index|. Helper function for JumpIfTaggedEqualConstant
424 // and JumpIfTaggedNotEqualConstant.
425 void JumpConditionalByConstantOperand(TNode<BoolT> condition,
426 int operand_index);
427
428 // Save the bytecode offset to the interpreter frame.
429 void SaveBytecodeOffset();
430 // Reload the bytecode offset from the interpreter frame.
431 TNode<IntPtrT> ReloadBytecodeOffset();
432
433 // Updates and returns BytecodeOffset() advanced by the current bytecode's
434 // size. Traces the exit of the current bytecode.
435 TNode<IntPtrT> Advance();
436
437 // Updates and returns BytecodeOffset() advanced by delta bytecodes.
438 // Traces the exit of the current bytecode.
439 TNode<IntPtrT> Advance(int delta);
440 TNode<IntPtrT> Advance(TNode<IntPtrT> delta);
441
442 // Look ahead for short Star and inline it in a branch, including subsequent
443 // dispatch. Anything after this point can assume that the following
444 // instruction was not a short Star.
445 void StarDispatchLookahead(TNode<WordT> target_bytecode);
446
447 // Build code for short Star at the current BytecodeOffset() and Advance() to
448 // the next dispatch offset.
449 void InlineShortStar(TNode<WordT> target_bytecode);
450
451 // Dispatch to the bytecode handler with code entry point |handler_entry|.
452 void DispatchToBytecodeHandlerEntry(TNode<RawPtrT> handler_entry,
453 TNode<IntPtrT> bytecode_offset);
454
455 int CurrentBytecodeSize() const;
456
457 OperandScale operand_scale() const { return operand_scale_; }
458
470};
471
472} // namespace interpreter
473} // namespace internal
474} // namespace v8
475
476#endif // V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_
int16_t parameter_count
Definition builtins.cc:67
RegListNodePair(TNode< IntPtrT > base_reg_location, TNode< Word32T > reg_count)
CodeStubAssembler::TVariable< Object > accumulator_
InterpreterAssembler(const InterpreterAssembler &)=delete
InterpreterAssembler & operator=(const InterpreterAssembler &)=delete
CodeStubAssembler::TVariable< IntPtrT > bytecode_offset_
CodeStubAssembler::TVariable< RawPtrT > interpreted_frame_pointer_
CodeStubAssembler::TVariable< ExternalReference > dispatch_table_
CodeStubAssembler::TVariable< BytecodeArray > bytecode_array_
static constexpr UpdateFeedbackMode DefaultUpdateFeedbackMode()
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
base::Vector< const RegExpInstruction > bytecode_
LiftoffRegister reg
RegListBase< RegisterT > registers
const int kHeapObjectTag
Definition v8-internal.h:72
#define V8_EXPORT_PRIVATE
Definition macros.h:460