Line data Source code
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 :
8 : #include "src/allocation.h"
9 : #include "src/builtins/builtins.h"
10 : #include "src/code-stub-assembler.h"
11 : #include "src/frames.h"
12 : #include "src/globals.h"
13 : #include "src/interpreter/bytecode-register.h"
14 : #include "src/interpreter/bytecodes.h"
15 : #include "src/runtime/runtime.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace interpreter {
20 :
21 : class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler {
22 : public:
23 : InterpreterAssembler(compiler::CodeAssemblerState* state, Bytecode bytecode,
24 : OperandScale operand_scale);
25 : ~InterpreterAssembler();
26 :
27 : // Returns the 32-bit unsigned count immediate for bytecode operand
28 : // |operand_index| in the current bytecode.
29 : compiler::Node* BytecodeOperandCount(int operand_index);
30 : // Returns the 32-bit unsigned flag for bytecode operand |operand_index|
31 : // in the current bytecode.
32 : compiler::Node* BytecodeOperandFlag(int operand_index);
33 : // Returns the 32-bit zero-extended index immediate for bytecode operand
34 : // |operand_index| in the current bytecode.
35 : compiler::Node* BytecodeOperandIdxInt32(int operand_index);
36 : // Returns the word zero-extended index immediate for bytecode operand
37 : // |operand_index| in the current bytecode.
38 : compiler::Node* BytecodeOperandIdx(int operand_index);
39 : // Returns the smi index immediate for bytecode operand |operand_index|
40 : // in the current bytecode.
41 : compiler::Node* BytecodeOperandIdxSmi(int operand_index);
42 : // Returns the 32-bit unsigned immediate for bytecode operand |operand_index|
43 : // in the current bytecode.
44 : compiler::Node* BytecodeOperandUImm(int operand_index);
45 : // Returns the word-size unsigned immediate for bytecode operand
46 : // |operand_index| in the current bytecode.
47 : compiler::Node* BytecodeOperandUImmWord(int operand_index);
48 : // Returns the 32-bit signed immediate for bytecode operand |operand_index|
49 : // in the current bytecode.
50 : compiler::Node* BytecodeOperandImm(int operand_index);
51 : // Returns the word-size signed immediate for bytecode operand |operand_index|
52 : // in the current bytecode.
53 : compiler::Node* BytecodeOperandImmIntPtr(int operand_index);
54 : // Returns the smi immediate for bytecode operand |operand_index| in the
55 : // current bytecode.
56 : compiler::Node* BytecodeOperandImmSmi(int operand_index);
57 : // Returns the word-size sign-extended register index for bytecode operand
58 : // |operand_index| in the current bytecode.
59 : compiler::Node* BytecodeOperandReg(int operand_index);
60 : // Returns the 32-bit unsigned runtime id immediate for bytecode operand
61 : // |operand_index| in the current bytecode.
62 : compiler::Node* BytecodeOperandRuntimeId(int operand_index);
63 : // Returns the 32-bit unsigned intrinsic id immediate for bytecode operand
64 : // |operand_index| in the current bytecode.
65 : compiler::Node* BytecodeOperandIntrinsicId(int operand_index);
66 :
67 : // Accumulator.
68 : compiler::Node* GetAccumulator();
69 : void SetAccumulator(compiler::Node* value);
70 :
71 : // Context.
72 : compiler::Node* GetContext();
73 : void SetContext(compiler::Node* value);
74 :
75 : // Context at |depth| in the context chain starting at |context|.
76 : compiler::Node* GetContextAtDepth(compiler::Node* context,
77 : compiler::Node* depth);
78 :
79 : // Goto the given |target| if the context chain starting at |context| has any
80 : // extensions up to the given |depth|.
81 : void GotoIfHasContextExtensionUpToDepth(compiler::Node* context,
82 : compiler::Node* depth, Label* target);
83 :
84 : // Number of registers.
85 : compiler::Node* RegisterCount();
86 :
87 : // Backup/restore register file to/from a fixed array of the correct length.
88 : compiler::Node* ExportRegisterFile(compiler::Node* array);
89 : compiler::Node* ImportRegisterFile(compiler::Node* array);
90 :
91 : // Loads from and stores to the interpreter register file.
92 : compiler::Node* LoadRegister(Register reg);
93 : compiler::Node* LoadRegister(compiler::Node* reg_index);
94 : compiler::Node* LoadAndUntagRegister(Register reg);
95 : compiler::Node* StoreRegister(compiler::Node* value, Register reg);
96 : compiler::Node* StoreRegister(compiler::Node* value,
97 : compiler::Node* reg_index);
98 : compiler::Node* StoreAndTagRegister(compiler::Node* value, Register reg);
99 :
100 : // Returns the next consecutive register.
101 : compiler::Node* NextRegister(compiler::Node* reg_index);
102 :
103 : // Returns the location in memory of the register |reg_index| in the
104 : // interpreter register file.
105 : compiler::Node* RegisterLocation(compiler::Node* reg_index);
106 :
107 : // Load constant at |index| in the constant pool.
108 : compiler::Node* LoadConstantPoolEntry(compiler::Node* index);
109 :
110 : // Load and untag constant at |index| in the constant pool.
111 : compiler::Node* LoadAndUntagConstantPoolEntry(compiler::Node* index);
112 :
113 : // Load the FeedbackVector for the current function.
114 : compiler::Node* LoadFeedbackVector();
115 :
116 : // Increment the call count for a CALL_IC or construct call.
117 : // The call count is located at feedback_vector[slot_id + 1].
118 : compiler::Node* IncrementCallCount(compiler::Node* feedback_vector,
119 : compiler::Node* slot_id);
120 :
121 : // Call JSFunction or Callable |function| with |arg_count| arguments (not
122 : // including receiver) and the first argument located at |first_arg|. Type
123 : // feedback is collected in the slot at index |slot_id|.
124 : //
125 : // If the |receiver_mode| is kNullOrUndefined, then the receiver is implicitly
126 : // undefined and |first_arg| is the first parameter. Otherwise, |first_arg| is
127 : // the receiver and it is converted according to |receiver_mode|.
128 : compiler::Node* CallJSWithFeedback(
129 : compiler::Node* function, compiler::Node* context,
130 : compiler::Node* first_arg, compiler::Node* arg_count,
131 : compiler::Node* slot_id, compiler::Node* feedback_vector,
132 : ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode);
133 :
134 : // Call JSFunction or Callable |function| with |arg_count| arguments (not
135 : // including receiver) and the first argument located at |first_arg|, possibly
136 : // including the receiver depending on |receiver_mode|.
137 : compiler::Node* CallJS(compiler::Node* function, compiler::Node* context,
138 : compiler::Node* first_arg, compiler::Node* arg_count,
139 : ConvertReceiverMode receiver_mode,
140 : TailCallMode tail_call_mode);
141 :
142 : // Call JSFunction or Callable |function| with |arg_count|
143 : // arguments (not including receiver) and the first argument
144 : // located at |first_arg|.
145 : compiler::Node* CallJSWithSpread(compiler::Node* function,
146 : compiler::Node* context,
147 : compiler::Node* first_arg,
148 : compiler::Node* arg_count);
149 :
150 : // Call constructor |constructor| with |arg_count| arguments (not
151 : // including receiver) and the first argument located at
152 : // |first_arg|. The |new_target| is the same as the
153 : // |constructor| for the new keyword, but differs for the super
154 : // keyword.
155 : compiler::Node* Construct(compiler::Node* constructor,
156 : compiler::Node* context, compiler::Node* new_target,
157 : compiler::Node* first_arg,
158 : compiler::Node* arg_count, compiler::Node* slot_id,
159 : compiler::Node* feedback_vector);
160 :
161 : // Call constructor |constructor| with |arg_count| arguments (not including
162 : // receiver) and the first argument located at |first_arg|. The last argument
163 : // is always a spread. The |new_target| is the same as the |constructor| for
164 : // the new keyword, but differs for the super keyword.
165 : compiler::Node* ConstructWithSpread(compiler::Node* constructor,
166 : compiler::Node* context,
167 : compiler::Node* new_target,
168 : compiler::Node* first_arg,
169 : compiler::Node* arg_count);
170 :
171 : // Call runtime function with |arg_count| arguments and the first argument
172 : // located at |first_arg|.
173 : compiler::Node* CallRuntimeN(compiler::Node* function_id,
174 : compiler::Node* context,
175 : compiler::Node* first_arg,
176 : compiler::Node* arg_count, int return_size = 1);
177 :
178 : // Jump forward relative to the current bytecode by the |jump_offset|.
179 : compiler::Node* Jump(compiler::Node* jump_offset);
180 :
181 : // Jump backward relative to the current bytecode by the |jump_offset|.
182 : compiler::Node* JumpBackward(compiler::Node* jump_offset);
183 :
184 : // Jump forward relative to the current bytecode by |jump_offset| if the
185 : // word values |lhs| and |rhs| are equal.
186 : void JumpIfWordEqual(compiler::Node* lhs, compiler::Node* rhs,
187 : compiler::Node* jump_offset);
188 :
189 : // Jump forward relative to the current bytecode by |jump_offset| if the
190 : // word values |lhs| and |rhs| are not equal.
191 : void JumpIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
192 : compiler::Node* jump_offset);
193 :
194 : // Returns true if the stack guard check triggers an interrupt.
195 : compiler::Node* StackCheckTriggeredInterrupt();
196 :
197 : // Updates the profiler interrupt budget for a return.
198 : void UpdateInterruptBudgetOnReturn();
199 :
200 : // Returns the OSR nesting level from the bytecode header.
201 : compiler::Node* LoadOSRNestingLevel();
202 :
203 : // Dispatch to the bytecode.
204 : compiler::Node* Dispatch();
205 :
206 : // Dispatch to bytecode handler.
207 903 : compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler) {
208 903 : return DispatchToBytecodeHandler(handler, BytecodeOffset());
209 : }
210 :
211 : // Dispatch bytecode as wide operand variant.
212 : void DispatchWide(OperandScale operand_scale);
213 :
214 : // Truncate tagged |value| to word32 and store the type feedback in
215 : // |var_type_feedback|.
216 : compiler::Node* TruncateTaggedToWord32WithFeedback(
217 : compiler::Node* context, compiler::Node* value,
218 : Variable* var_type_feedback);
219 :
220 : // Abort with the given bailout reason.
221 : void Abort(BailoutReason bailout_reason);
222 : void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
223 : BailoutReason bailout_reason);
224 :
225 : // Dispatch to frame dropper trampoline if necessary.
226 : void MaybeDropFrames(compiler::Node* context);
227 :
228 : // Returns the offset from the BytecodeArrayPointer of the current bytecode.
229 : compiler::Node* BytecodeOffset();
230 :
231 : protected:
232 : Bytecode bytecode() const { return bytecode_; }
233 : static bool TargetSupportsUnalignedAccess();
234 :
235 : private:
236 : // Returns a tagged pointer to the current function's BytecodeArray object.
237 : compiler::Node* BytecodeArrayTaggedPointer();
238 :
239 : // Returns a raw pointer to first entry in the interpreter dispatch table.
240 : compiler::Node* DispatchTableRawPointer();
241 :
242 : // Returns the accumulator value without checking whether bytecode
243 : // uses it. This is intended to be used only in dispatch and in
244 : // tracing as these need to bypass accumulator use validity checks.
245 : compiler::Node* GetAccumulatorUnchecked();
246 :
247 : // Returns the frame pointer for the interpreted frame of the function being
248 : // interpreted.
249 : compiler::Node* GetInterpretedFramePointer();
250 :
251 : // Saves and restores interpreter bytecode offset to the interpreter stack
252 : // frame when performing a call.
253 : void CallPrologue();
254 : void CallEpilogue();
255 :
256 : // Increment the dispatch counter for the (current, next) bytecode pair.
257 : void TraceBytecodeDispatch(compiler::Node* target_index);
258 :
259 : // Traces the current bytecode by calling |function_id|.
260 : void TraceBytecode(Runtime::FunctionId function_id);
261 :
262 : // Updates the bytecode array's interrupt budget by a 32-bit unsigned |weight|
263 : // and calls Runtime::kInterrupt if counter reaches zero. If |backward|, then
264 : // the interrupt budget is decremented, otherwise it is incremented.
265 : void UpdateInterruptBudget(compiler::Node* weight, bool backward);
266 :
267 : // Returns the offset of register |index| relative to RegisterFilePointer().
268 : compiler::Node* RegisterFrameOffset(compiler::Node* index);
269 :
270 : // Returns the offset of an operand relative to the current bytecode offset.
271 : compiler::Node* OperandOffset(int operand_index);
272 :
273 : // Returns a value built from an sequence of bytes in the bytecode
274 : // array starting at |relative_offset| from the current bytecode.
275 : // The |result_type| determines the size and signedness. of the
276 : // value read. This method should only be used on architectures that
277 : // do not support unaligned memory accesses.
278 : compiler::Node* BytecodeOperandReadUnaligned(int relative_offset,
279 : MachineType result_type);
280 :
281 : // Returns zero- or sign-extended to word32 value of the operand.
282 : compiler::Node* BytecodeOperandUnsignedByte(int operand_index);
283 : compiler::Node* BytecodeOperandSignedByte(int operand_index);
284 : compiler::Node* BytecodeOperandUnsignedShort(int operand_index);
285 : compiler::Node* BytecodeOperandSignedShort(int operand_index);
286 : compiler::Node* BytecodeOperandUnsignedQuad(int operand_index);
287 : compiler::Node* BytecodeOperandSignedQuad(int operand_index);
288 :
289 : // Returns zero- or sign-extended to word32 value of the operand of
290 : // given size.
291 : compiler::Node* BytecodeSignedOperand(int operand_index,
292 : OperandSize operand_size);
293 : compiler::Node* BytecodeUnsignedOperand(int operand_index,
294 : OperandSize operand_size);
295 :
296 : // Jump relative to the current bytecode by the |jump_offset|. If |backward|,
297 : // then jump backward (subtract the offset), otherwise jump forward (add the
298 : // offset). Helper function for Jump and JumpBackward.
299 : compiler::Node* Jump(compiler::Node* jump_offset, bool backward);
300 :
301 : // Jump forward relative to the current bytecode by |jump_offset| if the
302 : // |condition| is true. Helper function for JumpIfWordEqual and
303 : // JumpIfWordNotEqual.
304 : void JumpConditional(compiler::Node* condition, compiler::Node* jump_offset);
305 :
306 : // Save the bytecode offset to the interpreter frame.
307 : void SaveBytecodeOffset();
308 :
309 : // Updates and returns BytecodeOffset() advanced by the current bytecode's
310 : // size. Traces the exit of the current bytecode.
311 : compiler::Node* Advance();
312 :
313 : // Updates and returns BytecodeOffset() advanced by delta bytecodes.
314 : // Traces the exit of the current bytecode.
315 : compiler::Node* Advance(int delta);
316 : compiler::Node* Advance(compiler::Node* delta, bool backward = false);
317 :
318 : // Load the bytecode at |bytecode_offset|.
319 : compiler::Node* LoadBytecode(compiler::Node* bytecode_offset);
320 :
321 : // Look ahead for Star and inline it in a branch. Returns a new target
322 : // bytecode node for dispatch.
323 : compiler::Node* StarDispatchLookahead(compiler::Node* target_bytecode);
324 :
325 : // Build code for Star at the current BytecodeOffset() and Advance() to the
326 : // next dispatch offset.
327 : void InlineStar();
328 :
329 : // Dispatch to |target_bytecode| at |new_bytecode_offset|.
330 : // |target_bytecode| should be equivalent to loading from the offset.
331 : compiler::Node* DispatchToBytecode(compiler::Node* target_bytecode,
332 : compiler::Node* new_bytecode_offset);
333 :
334 : // Dispatch to the bytecode handler with code offset |handler|.
335 : compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler,
336 : compiler::Node* bytecode_offset);
337 :
338 : // Dispatch to the bytecode handler with code entry point |handler_entry|.
339 : compiler::Node* DispatchToBytecodeHandlerEntry(
340 : compiler::Node* handler_entry, compiler::Node* bytecode_offset);
341 :
342 : int CurrentBytecodeSize() const;
343 :
344 : OperandScale operand_scale() const { return operand_scale_; }
345 :
346 : Bytecode bytecode_;
347 : OperandScale operand_scale_;
348 : CodeStubAssembler::Variable bytecode_offset_;
349 : CodeStubAssembler::Variable interpreted_frame_pointer_;
350 : CodeStubAssembler::Variable bytecode_array_;
351 : CodeStubAssembler::Variable dispatch_table_;
352 : CodeStubAssembler::Variable accumulator_;
353 : AccumulatorUse accumulator_use_;
354 : bool made_call_;
355 : bool reloaded_frame_ptr_;
356 : bool saved_bytecode_offset_;
357 :
358 : bool disable_stack_check_across_call_;
359 : compiler::Node* stack_pointer_before_call_;
360 :
361 : DISALLOW_COPY_AND_ASSIGN(InterpreterAssembler);
362 : };
363 :
364 : } // namespace interpreter
365 : } // namespace internal
366 : } // namespace v8
367 :
368 : #endif // V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_
|