interpreter-assembler.h 13.3 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2015 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.

#ifndef V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_
#define V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_

#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/interpreter/bytecode-register.h"
13 14 15 16 17 18 19
#include "src/interpreter/bytecodes.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {
namespace interpreter {

20
class InterpreterAssembler : public CodeStubAssembler {
21
 public:
22 23
  InterpreterAssembler(Isolate* isolate, Zone* zone, Bytecode bytecode,
                       OperandScale operand_scale);
24 25 26 27 28
  virtual ~InterpreterAssembler();

  // Returns the count immediate for bytecode operand |operand_index| in the
  // current bytecode.
  compiler::Node* BytecodeOperandCount(int operand_index);
29 30 31
  // Returns the 8-bit flag for bytecode operand |operand_index| in the
  // current bytecode.
  compiler::Node* BytecodeOperandFlag(int operand_index);
32 33 34
  // Returns the index immediate for bytecode operand |operand_index| in the
  // current bytecode.
  compiler::Node* BytecodeOperandIdx(int operand_index);
35 36 37
  // Returns the UImm8 immediate for bytecode operand |operand_index| in the
  // current bytecode.
  compiler::Node* BytecodeOperandUImm(int operand_index);
38 39 40 41 42 43
  // Returns the Imm8 immediate for bytecode operand |operand_index| in the
  // current bytecode.
  compiler::Node* BytecodeOperandImm(int operand_index);
  // Returns the register index for bytecode operand |operand_index| in the
  // current bytecode.
  compiler::Node* BytecodeOperandReg(int operand_index);
44 45 46
  // Returns the runtime id immediate for bytecode operand
  // |operand_index| in the current bytecode.
  compiler::Node* BytecodeOperandRuntimeId(int operand_index);
47 48 49
  // Returns the intrinsic id immediate for bytecode operand
  // |operand_index| in the current bytecode.
  compiler::Node* BytecodeOperandIntrinsicId(int operand_index);
50 51 52 53 54 55 56 57 58

  // Accumulator.
  compiler::Node* GetAccumulator();
  void SetAccumulator(compiler::Node* value);

  // Context.
  compiler::Node* GetContext();
  void SetContext(compiler::Node* value);

59
  // Context at |depth| in the context chain starting at |context|.
60 61 62
  compiler::Node* GetContextAtDepth(compiler::Node* context,
                                    compiler::Node* depth);

63 64 65 66 67
  // Goto the given |target| if the context chain starting at |context| has any
  // extensions up to the given |depth|.
  void GotoIfHasContextExtensionUpToDepth(compiler::Node* context,
                                          compiler::Node* depth, Label* target);

68 69 70
  // Number of registers.
  compiler::Node* RegisterCount();

71 72
  // Backup/restore register file to/from a fixed array of the correct length.
  compiler::Node* ExportRegisterFile(compiler::Node* array);
73 74
  compiler::Node* ImportRegisterFile(compiler::Node* array);

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  // Loads from and stores to the interpreter register file.
  compiler::Node* LoadRegister(Register reg);
  compiler::Node* LoadRegister(compiler::Node* reg_index);
  compiler::Node* StoreRegister(compiler::Node* value, Register reg);
  compiler::Node* StoreRegister(compiler::Node* value,
                                compiler::Node* reg_index);

  // Returns the next consecutive register.
  compiler::Node* NextRegister(compiler::Node* reg_index);

  // Returns the location in memory of the register |reg_index| in the
  // interpreter register file.
  compiler::Node* RegisterLocation(compiler::Node* reg_index);

  // Load constant at |index| in the constant pool.
  compiler::Node* LoadConstantPoolEntry(compiler::Node* index);

92 93 94
  // Load and untag constant at |index| in the constant pool.
  compiler::Node* LoadAndUntagConstantPoolEntry(compiler::Node* index);

95 96 97 98 99 100 101 102 103 104 105 106
  // Load |slot_index| from |context|.
  compiler::Node* LoadContextSlot(compiler::Node* context, int slot_index);
  compiler::Node* LoadContextSlot(compiler::Node* context,
                                  compiler::Node* slot_index);
  // Stores |value| into |slot_index| of |context|.
  compiler::Node* StoreContextSlot(compiler::Node* context,
                                   compiler::Node* slot_index,
                                   compiler::Node* value);

  // Load the TypeFeedbackVector for the current function.
  compiler::Node* LoadTypeFeedbackVector();

107 108 109 110 111
  // Increment the call count for a CALL_IC or construct call.
  // The call count is located at feedback_vector[slot_id + 1].
  compiler::Node* IncrementCallCount(compiler::Node* type_feedback_vector,
                                     compiler::Node* slot_id);

112 113 114 115 116 117 118 119 120 121 122 123
  // Call JSFunction or Callable |function| with |arg_count|
  // arguments (not including receiver) and the first argument
  // located at |first_arg|. Type feedback is collected in the
  // slot at index |slot_id|.
  compiler::Node* CallJSWithFeedback(compiler::Node* function,
                                     compiler::Node* context,
                                     compiler::Node* first_arg,
                                     compiler::Node* arg_count,
                                     compiler::Node* slot_id,
                                     compiler::Node* type_feedback_vector,
                                     TailCallMode tail_call_mode);

124 125 126 127
  // Call JSFunction or Callable |function| with |arg_count|
  // arguments (not including receiver) and the first argument
  // located at |first_arg|.
  compiler::Node* CallJS(compiler::Node* function, compiler::Node* context,
128 129
                         compiler::Node* first_arg, compiler::Node* arg_count,
                         TailCallMode tail_call_mode);
130 131 132 133 134 135 136 137 138 139

  // Call constructor |constructor| with |arg_count| arguments (not
  // including receiver) and the first argument located at
  // |first_arg|. The |new_target| is the same as the
  // |constructor| for the new keyword, but differs for the super
  // keyword.
  compiler::Node* CallConstruct(compiler::Node* constructor,
                                compiler::Node* context,
                                compiler::Node* new_target,
                                compiler::Node* first_arg,
140 141 142
                                compiler::Node* arg_count,
                                compiler::Node* slot_id,
                                compiler::Node* type_feedback_vector);
143 144 145 146 147 148 149 150 151

  // Call runtime function with |arg_count| arguments and the first argument
  // located at |first_arg|.
  compiler::Node* CallRuntimeN(compiler::Node* function_id,
                               compiler::Node* context,
                               compiler::Node* first_arg,
                               compiler::Node* arg_count, int return_size = 1);

  // Jump relative to the current bytecode by |jump_offset|.
152
  compiler::Node* Jump(compiler::Node* jump_offset);
153 154 155 156 157 158 159 160 161 162 163

  // Jump relative to the current bytecode by |jump_offset| if the
  // word values |lhs| and |rhs| are equal.
  void JumpIfWordEqual(compiler::Node* lhs, compiler::Node* rhs,
                       compiler::Node* jump_offset);

  // Jump relative to the current bytecode by |jump_offset| if the
  // word values |lhs| and |rhs| are not equal.
  void JumpIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
                          compiler::Node* jump_offset);

164 165
  // Returns true if the stack guard check triggers an interrupt.
  compiler::Node* StackCheckTriggeredInterrupt();
166

167 168
  // Updates the profiler interrupt budget for a return.
  void UpdateInterruptBudgetOnReturn();
169

170 171 172
  // Returns the OSR nesting level from the bytecode header.
  compiler::Node* LoadOSRNestingLevel();

173
  // Dispatch to the bytecode.
174
  compiler::Node* Dispatch();
175

176
  // Dispatch to bytecode handler.
177 178
  compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler) {
    return DispatchToBytecodeHandler(handler, BytecodeOffset());
179 180
  }

181 182 183
  // Dispatch bytecode as wide operand variant.
  void DispatchWide(OperandScale operand_scale);

184 185 186 187 188 189
  // Truncate tagged |value| to word32 and store the type feedback in
  // |var_type_feedback|.
  compiler::Node* TruncateTaggedToWord32WithFeedback(
      compiler::Node* context, compiler::Node* value,
      Variable* var_type_feedback);

190 191
  // Abort with the given bailout reason.
  void Abort(BailoutReason bailout_reason);
192 193
  void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
                           BailoutReason bailout_reason);
194

195 196 197
  // Returns the offset from the BytecodeArrayPointer of the current bytecode.
  compiler::Node* BytecodeOffset();

198
 protected:
199
  Bytecode bytecode() const { return bytecode_; }
200 201 202 203 204
  static bool TargetSupportsUnalignedAccess();

 private:
  // Returns a tagged pointer to the current function's BytecodeArray object.
  compiler::Node* BytecodeArrayTaggedPointer();
205

206 207 208
  // Returns a raw pointer to first entry in the interpreter dispatch table.
  compiler::Node* DispatchTableRawPointer();

209 210 211 212 213
  // Returns the accumulator value without checking whether bytecode
  // uses it. This is intended to be used only in dispatch and in
  // tracing as these need to bypass accumulator use validity checks.
  compiler::Node* GetAccumulatorUnchecked();

214 215 216 217
  // Returns the frame pointer for the interpreted frame of the function being
  // interpreted.
  compiler::Node* GetInterpretedFramePointer();

218 219 220 221 222
  // Saves and restores interpreter bytecode offset to the interpreter stack
  // frame when performing a call.
  void CallPrologue() override;
  void CallEpilogue() override;

223 224 225
  // Increment the dispatch counter for the (current, next) bytecode pair.
  void TraceBytecodeDispatch(compiler::Node* target_index);

226 227 228
  // Traces the current bytecode by calling |function_id|.
  void TraceBytecode(Runtime::FunctionId function_id);

229 230 231 232
  // Updates the bytecode array's interrupt budget by |weight| and calls
  // Runtime::kInterrupt if counter reaches zero.
  void UpdateInterruptBudget(compiler::Node* weight);

233 234 235
  // Returns the offset of register |index| relative to RegisterFilePointer().
  compiler::Node* RegisterFrameOffset(compiler::Node* index);

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
  // Returns the offset of an operand relative to the current bytecode offset.
  compiler::Node* OperandOffset(int operand_index);

  // Returns a value built from an sequence of bytes in the bytecode
  // array starting at |relative_offset| from the current bytecode.
  // The |result_type| determines the size and signedness.  of the
  // value read. This method should only be used on architectures that
  // do not support unaligned memory accesses.
  compiler::Node* BytecodeOperandReadUnaligned(int relative_offset,
                                               MachineType result_type);

  compiler::Node* BytecodeOperandUnsignedByte(int operand_index);
  compiler::Node* BytecodeOperandSignedByte(int operand_index);
  compiler::Node* BytecodeOperandUnsignedShort(int operand_index);
  compiler::Node* BytecodeOperandSignedShort(int operand_index);
  compiler::Node* BytecodeOperandUnsignedQuad(int operand_index);
  compiler::Node* BytecodeOperandSignedQuad(int operand_index);

  compiler::Node* BytecodeSignedOperand(int operand_index,
                                        OperandSize operand_size);
  compiler::Node* BytecodeUnsignedOperand(int operand_index,
                                          OperandSize operand_size);
258

259 260 261 262 263
  // Jump relative to the current bytecode by |jump_offset| if the
  // |condition| is true. Helper function for JumpIfWordEqual and
  // JumpIfWordNotEqual.
  void JumpConditional(compiler::Node* condition, compiler::Node* jump_offset);

264 265 266 267 268 269
  // Updates and returns BytecodeOffset() advanced by the current bytecode's
  // size. Traces the exit of the current bytecode.
  compiler::Node* Advance();

  // Updates and returns BytecodeOffset() advanced by delta bytecodes.
  // Traces the exit of the current bytecode.
270 271 272
  compiler::Node* Advance(int delta);
  compiler::Node* Advance(compiler::Node* delta);

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
  // Load the bytecode at |bytecode_offset|.
  compiler::Node* LoadBytecode(compiler::Node* bytecode_offset);

  // Look ahead for Star and inline it in a branch. Returns a new target
  // bytecode node for dispatch.
  compiler::Node* StarDispatchLookahead(compiler::Node* target_bytecode);

  // Build code for Star at the current BytecodeOffset() and Advance() to the
  // next dispatch offset.
  void InlineStar();

  // Dispatch to |target_bytecode| at |new_bytecode_offset|.
  // |target_bytecode| should be equivalent to loading from the offset.
  compiler::Node* DispatchToBytecode(compiler::Node* target_bytecode,
                                     compiler::Node* new_bytecode_offset);
288

289
  // Dispatch to the bytecode handler with code offset |handler|.
290 291
  compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler,
                                            compiler::Node* bytecode_offset);
292 293

  // Dispatch to the bytecode handler with code entry point |handler_entry|.
294 295
  compiler::Node* DispatchToBytecodeHandlerEntry(
      compiler::Node* handler_entry, compiler::Node* bytecode_offset);
296

297 298
  OperandScale operand_scale() const { return operand_scale_; }

299
  Bytecode bytecode_;
300
  OperandScale operand_scale_;
301
  CodeStubAssembler::Variable bytecode_offset_;
302
  CodeStubAssembler::Variable interpreted_frame_pointer_;
303
  CodeStubAssembler::Variable accumulator_;
304
  AccumulatorUse accumulator_use_;
305
  bool made_call_;
306 307 308 309 310 311 312 313 314 315 316 317

  bool disable_stack_check_across_call_;
  compiler::Node* stack_pointer_before_call_;

  DISALLOW_COPY_AND_ASSIGN(InterpreterAssembler);
};

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_INTERPRETER_ASSEMBLER_H_