blob: aefd2bc0534c0b25da00f43c4b4fa6ada7c5f3e9 [file] [log] [blame]
Ben Murdoch109988c2016-05-18 11:27:45 +01001// 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"
Ben Murdochf91f0612016-11-29 16:50:11 +00009#include "src/builtins/builtins.h"
Ben Murdochbcf72ee2016-08-08 18:44:38 +010010#include "src/code-stub-assembler.h"
Ben Murdoch109988c2016-05-18 11:27:45 +010011#include "src/frames.h"
Ben Murdochc8c1d9e2017-03-08 14:04:23 +000012#include "src/globals.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000013#include "src/interpreter/bytecode-register.h"
Ben Murdoch109988c2016-05-18 11:27:45 +010014#include "src/interpreter/bytecodes.h"
15#include "src/runtime/runtime.h"
16
17namespace v8 {
18namespace internal {
19namespace interpreter {
20
Ben Murdochc8c1d9e2017-03-08 14:04:23 +000021class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler {
Ben Murdoch109988c2016-05-18 11:27:45 +010022 public:
Ben Murdoch3b9bc312016-06-02 14:46:10 +010023 InterpreterAssembler(Isolate* isolate, Zone* zone, Bytecode bytecode,
24 OperandScale operand_scale);
Ben Murdoch109988c2016-05-18 11:27:45 +010025 virtual ~InterpreterAssembler();
26
27 // Returns the count immediate for bytecode operand |operand_index| in the
28 // current bytecode.
29 compiler::Node* BytecodeOperandCount(int operand_index);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010030 // Returns the 8-bit flag for bytecode operand |operand_index| in the
31 // current bytecode.
32 compiler::Node* BytecodeOperandFlag(int operand_index);
Ben Murdoch109988c2016-05-18 11:27:45 +010033 // Returns the index immediate for bytecode operand |operand_index| in the
34 // current bytecode.
35 compiler::Node* BytecodeOperandIdx(int operand_index);
Ben Murdochf3b273f2017-01-17 12:11:28 +000036 // Returns the UImm8 immediate for bytecode operand |operand_index| in the
37 // current bytecode.
38 compiler::Node* BytecodeOperandUImm(int operand_index);
Ben Murdoch109988c2016-05-18 11:27:45 +010039 // Returns the Imm8 immediate for bytecode operand |operand_index| in the
40 // current bytecode.
41 compiler::Node* BytecodeOperandImm(int operand_index);
42 // Returns the register index for bytecode operand |operand_index| in the
43 // current bytecode.
44 compiler::Node* BytecodeOperandReg(int operand_index);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010045 // Returns the runtime id immediate for bytecode operand
46 // |operand_index| in the current bytecode.
47 compiler::Node* BytecodeOperandRuntimeId(int operand_index);
Ben Murdoch13e2dad2016-09-16 13:49:30 +010048 // Returns the intrinsic id immediate for bytecode operand
49 // |operand_index| in the current bytecode.
50 compiler::Node* BytecodeOperandIntrinsicId(int operand_index);
Ben Murdoch109988c2016-05-18 11:27:45 +010051
52 // Accumulator.
53 compiler::Node* GetAccumulator();
54 void SetAccumulator(compiler::Node* value);
55
56 // Context.
57 compiler::Node* GetContext();
58 void SetContext(compiler::Node* value);
59
Ben Murdochf3b273f2017-01-17 12:11:28 +000060 // Context at |depth| in the context chain starting at |context|.
61 compiler::Node* GetContextAtDepth(compiler::Node* context,
62 compiler::Node* depth);
63
64 // Goto the given |target| if the context chain starting at |context| has any
65 // extensions up to the given |depth|.
66 void GotoIfHasContextExtensionUpToDepth(compiler::Node* context,
67 compiler::Node* depth, Label* target);
68
Ben Murdochbcf72ee2016-08-08 18:44:38 +010069 // Number of registers.
70 compiler::Node* RegisterCount();
71
72 // Backup/restore register file to/from a fixed array of the correct length.
73 compiler::Node* ExportRegisterFile(compiler::Node* array);
74 compiler::Node* ImportRegisterFile(compiler::Node* array);
75
Ben Murdoch109988c2016-05-18 11:27:45 +010076 // Loads from and stores to the interpreter register file.
Ben Murdoch109988c2016-05-18 11:27:45 +010077 compiler::Node* LoadRegister(Register reg);
78 compiler::Node* LoadRegister(compiler::Node* reg_index);
Ben Murdoch109988c2016-05-18 11:27:45 +010079 compiler::Node* StoreRegister(compiler::Node* value, Register reg);
80 compiler::Node* StoreRegister(compiler::Node* value,
81 compiler::Node* reg_index);
82
83 // Returns the next consecutive register.
84 compiler::Node* NextRegister(compiler::Node* reg_index);
85
86 // Returns the location in memory of the register |reg_index| in the
87 // interpreter register file.
88 compiler::Node* RegisterLocation(compiler::Node* reg_index);
89
90 // Load constant at |index| in the constant pool.
91 compiler::Node* LoadConstantPoolEntry(compiler::Node* index);
92
Ben Murdochf91f0612016-11-29 16:50:11 +000093 // Load and untag constant at |index| in the constant pool.
94 compiler::Node* LoadAndUntagConstantPoolEntry(compiler::Node* index);
95
Ben Murdoch109988c2016-05-18 11:27:45 +010096 // Load the TypeFeedbackVector for the current function.
97 compiler::Node* LoadTypeFeedbackVector();
98
Ben Murdochf3b273f2017-01-17 12:11:28 +000099 // Increment the call count for a CALL_IC or construct call.
100 // The call count is located at feedback_vector[slot_id + 1].
101 compiler::Node* IncrementCallCount(compiler::Node* type_feedback_vector,
102 compiler::Node* slot_id);
103
Ben Murdoch109988c2016-05-18 11:27:45 +0100104 // Call JSFunction or Callable |function| with |arg_count|
105 // arguments (not including receiver) and the first argument
Ben Murdochf91f0612016-11-29 16:50:11 +0000106 // located at |first_arg|. Type feedback is collected in the
107 // slot at index |slot_id|.
108 compiler::Node* CallJSWithFeedback(compiler::Node* function,
109 compiler::Node* context,
110 compiler::Node* first_arg,
111 compiler::Node* arg_count,
112 compiler::Node* slot_id,
113 compiler::Node* type_feedback_vector,
114 TailCallMode tail_call_mode);
115
116 // Call JSFunction or Callable |function| with |arg_count|
117 // arguments (not including receiver) and the first argument
Ben Murdoch109988c2016-05-18 11:27:45 +0100118 // located at |first_arg|.
119 compiler::Node* CallJS(compiler::Node* function, compiler::Node* context,
120 compiler::Node* first_arg, compiler::Node* arg_count,
121 TailCallMode tail_call_mode);
122
123 // Call constructor |constructor| with |arg_count| arguments (not
124 // including receiver) and the first argument located at
125 // |first_arg|. The |new_target| is the same as the
126 // |constructor| for the new keyword, but differs for the super
127 // keyword.
128 compiler::Node* CallConstruct(compiler::Node* constructor,
129 compiler::Node* context,
130 compiler::Node* new_target,
131 compiler::Node* first_arg,
Ben Murdochf3b273f2017-01-17 12:11:28 +0000132 compiler::Node* arg_count,
133 compiler::Node* slot_id,
134 compiler::Node* type_feedback_vector);
Ben Murdoch109988c2016-05-18 11:27:45 +0100135
136 // Call runtime function with |arg_count| arguments and the first argument
137 // located at |first_arg|.
138 compiler::Node* CallRuntimeN(compiler::Node* function_id,
139 compiler::Node* context,
140 compiler::Node* first_arg,
141 compiler::Node* arg_count, int return_size = 1);
142
143 // Jump relative to the current bytecode by |jump_offset|.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100144 compiler::Node* Jump(compiler::Node* jump_offset);
Ben Murdoch109988c2016-05-18 11:27:45 +0100145
146 // Jump relative to the current bytecode by |jump_offset| if the
147 // word values |lhs| and |rhs| are equal.
148 void JumpIfWordEqual(compiler::Node* lhs, compiler::Node* rhs,
149 compiler::Node* jump_offset);
150
151 // Jump relative to the current bytecode by |jump_offset| if the
152 // word values |lhs| and |rhs| are not equal.
153 void JumpIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
154 compiler::Node* jump_offset);
155
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100156 // Returns true if the stack guard check triggers an interrupt.
157 compiler::Node* StackCheckTriggeredInterrupt();
Ben Murdoch109988c2016-05-18 11:27:45 +0100158
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100159 // Updates the profiler interrupt budget for a return.
160 void UpdateInterruptBudgetOnReturn();
Ben Murdoch109988c2016-05-18 11:27:45 +0100161
Ben Murdochf91f0612016-11-29 16:50:11 +0000162 // Returns the OSR nesting level from the bytecode header.
163 compiler::Node* LoadOSRNestingLevel();
164
Ben Murdoch109988c2016-05-18 11:27:45 +0100165 // Dispatch to the bytecode.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100166 compiler::Node* Dispatch();
Ben Murdoch109988c2016-05-18 11:27:45 +0100167
168 // Dispatch to bytecode handler.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100169 compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler) {
170 return DispatchToBytecodeHandler(handler, BytecodeOffset());
Ben Murdoch109988c2016-05-18 11:27:45 +0100171 }
172
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100173 // Dispatch bytecode as wide operand variant.
174 void DispatchWide(OperandScale operand_scale);
175
Ben Murdochf91f0612016-11-29 16:50:11 +0000176 // Truncate tagged |value| to word32 and store the type feedback in
177 // |var_type_feedback|.
178 compiler::Node* TruncateTaggedToWord32WithFeedback(
179 compiler::Node* context, compiler::Node* value,
180 Variable* var_type_feedback);
181
Ben Murdoch109988c2016-05-18 11:27:45 +0100182 // Abort with the given bailout reason.
183 void Abort(BailoutReason bailout_reason);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100184 void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
185 BailoutReason bailout_reason);
Ben Murdoch109988c2016-05-18 11:27:45 +0100186
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100187 // Returns the offset from the BytecodeArrayPointer of the current bytecode.
188 compiler::Node* BytecodeOffset();
189
Ben Murdoch109988c2016-05-18 11:27:45 +0100190 protected:
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100191 Bytecode bytecode() const { return bytecode_; }
Ben Murdoch109988c2016-05-18 11:27:45 +0100192 static bool TargetSupportsUnalignedAccess();
193
194 private:
Ben Murdoch109988c2016-05-18 11:27:45 +0100195 // Returns a tagged pointer to the current function's BytecodeArray object.
196 compiler::Node* BytecodeArrayTaggedPointer();
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100197
Ben Murdoch109988c2016-05-18 11:27:45 +0100198 // Returns a raw pointer to first entry in the interpreter dispatch table.
199 compiler::Node* DispatchTableRawPointer();
200
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100201 // Returns the accumulator value without checking whether bytecode
202 // uses it. This is intended to be used only in dispatch and in
203 // tracing as these need to bypass accumulator use validity checks.
204 compiler::Node* GetAccumulatorUnchecked();
205
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100206 // Returns the frame pointer for the interpreted frame of the function being
207 // interpreted.
208 compiler::Node* GetInterpretedFramePointer();
209
Ben Murdoch109988c2016-05-18 11:27:45 +0100210 // Saves and restores interpreter bytecode offset to the interpreter stack
211 // frame when performing a call.
212 void CallPrologue() override;
213 void CallEpilogue() override;
214
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100215 // Increment the dispatch counter for the (current, next) bytecode pair.
216 void TraceBytecodeDispatch(compiler::Node* target_index);
217
Ben Murdoch109988c2016-05-18 11:27:45 +0100218 // Traces the current bytecode by calling |function_id|.
219 void TraceBytecode(Runtime::FunctionId function_id);
220
221 // Updates the bytecode array's interrupt budget by |weight| and calls
222 // Runtime::kInterrupt if counter reaches zero.
223 void UpdateInterruptBudget(compiler::Node* weight);
224
225 // Returns the offset of register |index| relative to RegisterFilePointer().
226 compiler::Node* RegisterFrameOffset(compiler::Node* index);
227
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100228 // Returns the offset of an operand relative to the current bytecode offset.
229 compiler::Node* OperandOffset(int operand_index);
230
231 // Returns a value built from an sequence of bytes in the bytecode
232 // array starting at |relative_offset| from the current bytecode.
233 // The |result_type| determines the size and signedness. of the
234 // value read. This method should only be used on architectures that
235 // do not support unaligned memory accesses.
236 compiler::Node* BytecodeOperandReadUnaligned(int relative_offset,
237 MachineType result_type);
238
239 compiler::Node* BytecodeOperandUnsignedByte(int operand_index);
240 compiler::Node* BytecodeOperandSignedByte(int operand_index);
241 compiler::Node* BytecodeOperandUnsignedShort(int operand_index);
242 compiler::Node* BytecodeOperandSignedShort(int operand_index);
243 compiler::Node* BytecodeOperandUnsignedQuad(int operand_index);
244 compiler::Node* BytecodeOperandSignedQuad(int operand_index);
245
246 compiler::Node* BytecodeSignedOperand(int operand_index,
247 OperandSize operand_size);
248 compiler::Node* BytecodeUnsignedOperand(int operand_index,
249 OperandSize operand_size);
Ben Murdoch109988c2016-05-18 11:27:45 +0100250
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100251 // Jump relative to the current bytecode by |jump_offset| if the
252 // |condition| is true. Helper function for JumpIfWordEqual and
253 // JumpIfWordNotEqual.
254 void JumpConditional(compiler::Node* condition, compiler::Node* jump_offset);
255
Ben Murdochf91f0612016-11-29 16:50:11 +0000256 // Updates and returns BytecodeOffset() advanced by the current bytecode's
257 // size. Traces the exit of the current bytecode.
258 compiler::Node* Advance();
259
260 // Updates and returns BytecodeOffset() advanced by delta bytecodes.
261 // Traces the exit of the current bytecode.
Ben Murdoch109988c2016-05-18 11:27:45 +0100262 compiler::Node* Advance(int delta);
263 compiler::Node* Advance(compiler::Node* delta);
264
Ben Murdochf91f0612016-11-29 16:50:11 +0000265 // Load the bytecode at |bytecode_offset|.
266 compiler::Node* LoadBytecode(compiler::Node* bytecode_offset);
267
268 // Look ahead for Star and inline it in a branch. Returns a new target
269 // bytecode node for dispatch.
270 compiler::Node* StarDispatchLookahead(compiler::Node* target_bytecode);
271
272 // Build code for Star at the current BytecodeOffset() and Advance() to the
273 // next dispatch offset.
274 void InlineStar();
275
276 // Dispatch to |target_bytecode| at |new_bytecode_offset|.
277 // |target_bytecode| should be equivalent to loading from the offset.
278 compiler::Node* DispatchToBytecode(compiler::Node* target_bytecode,
279 compiler::Node* new_bytecode_offset);
Ben Murdoch109988c2016-05-18 11:27:45 +0100280
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100281 // Dispatch to the bytecode handler with code offset |handler|.
282 compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler,
283 compiler::Node* bytecode_offset);
284
285 // Dispatch to the bytecode handler with code entry point |handler_entry|.
286 compiler::Node* DispatchToBytecodeHandlerEntry(
287 compiler::Node* handler_entry, compiler::Node* bytecode_offset);
Ben Murdoch109988c2016-05-18 11:27:45 +0100288
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100289 OperandScale operand_scale() const { return operand_scale_; }
290
Ben Murdoch109988c2016-05-18 11:27:45 +0100291 Bytecode bytecode_;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100292 OperandScale operand_scale_;
Ben Murdochf91f0612016-11-29 16:50:11 +0000293 CodeStubAssembler::Variable bytecode_offset_;
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100294 CodeStubAssembler::Variable interpreted_frame_pointer_;
Ben Murdoch109988c2016-05-18 11:27:45 +0100295 CodeStubAssembler::Variable accumulator_;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100296 AccumulatorUse accumulator_use_;
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100297 bool made_call_;
Ben Murdoch109988c2016-05-18 11:27:45 +0100298
299 bool disable_stack_check_across_call_;
300 compiler::Node* stack_pointer_before_call_;
301
302 DISALLOW_COPY_AND_ASSIGN(InterpreterAssembler);
303};
304
305} // namespace interpreter
306} // namespace internal
307} // namespace v8
308
309#endif // V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_