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_COMPILER_INTERPRETER_ASSEMBLER_H_ 6 #define V8_COMPILER_INTERPRETER_ASSEMBLER_H_ 7 8 // Clients of this interface shouldn't depend on lots of compiler internals. 9 // Do not include anything from src/compiler here! 10 #include "src/allocation.h" 11 #include "src/base/smart-pointers.h" 12 #include "src/builtins.h" 13 #include "src/frames.h" 14 #include "src/interpreter/bytecodes.h" 15 #include "src/runtime/runtime.h" 16 17 namespace v8 { 18 namespace internal { 19 20 class CallInterfaceDescriptor; 21 class Isolate; 22 class Zone; 23 24 namespace compiler { 25 26 class CallDescriptor; 27 class Graph; 28 class Node; 29 class Operator; 30 class RawMachineAssembler; 31 class Schedule; 32 33 class InterpreterAssembler { 34 public: 35 InterpreterAssembler(Isolate* isolate, Zone* zone, 36 interpreter::Bytecode bytecode); 37 virtual ~InterpreterAssembler(); 38 39 Handle<Code> GenerateCode(); 40 41 // Returns the count immediate for bytecode operand |operand_index| in the 42 // current bytecode. 43 Node* BytecodeOperandCount(int operand_index); 44 // Returns the index immediate for bytecode operand |operand_index| in the 45 // current bytecode. 46 Node* BytecodeOperandIdx(int operand_index); 47 // Returns the Imm8 immediate for bytecode operand |operand_index| in the 48 // current bytecode. 49 Node* BytecodeOperandImm(int operand_index); 50 // Returns the register index for bytecode operand |operand_index| in the 51 // current bytecode. 52 Node* BytecodeOperandReg(int operand_index); 53 54 // Accumulator. 55 Node* GetAccumulator(); 56 void SetAccumulator(Node* value); 57 58 // Context. 59 Node* GetContext(); 60 void SetContext(Node* value); 61 62 // Loads from and stores to the interpreter register file. 63 Node* LoadRegister(int offset); 64 Node* LoadRegister(interpreter::Register reg); 65 Node* LoadRegister(Node* reg_index); 66 Node* StoreRegister(Node* value, int offset); 67 Node* StoreRegister(Node* value, interpreter::Register reg); 68 Node* StoreRegister(Node* value, Node* reg_index); 69 70 // Returns the next consecutive register. 71 Node* NextRegister(Node* reg_index); 72 73 // Returns the location in memory of the register |reg_index| in the 74 // interpreter register file. 75 Node* RegisterLocation(Node* reg_index); 76 77 // Constants. 78 Node* Int32Constant(int value); 79 Node* IntPtrConstant(intptr_t value); 80 Node* NumberConstant(double value); 81 Node* HeapConstant(Handle<HeapObject> object); 82 Node* BooleanConstant(bool value); 83 84 // Tag and untag Smi values. 85 Node* SmiTag(Node* value); 86 Node* SmiUntag(Node* value); 87 88 // Basic arithmetic operations. 89 Node* IntPtrAdd(Node* a, Node* b); 90 Node* IntPtrSub(Node* a, Node* b); 91 Node* WordShl(Node* value, int shift); 92 93 // Load constant at |index| in the constant pool. 94 Node* LoadConstantPoolEntry(Node* index); 95 96 // Load an element from a fixed array on the heap. 97 Node* LoadFixedArrayElement(Node* fixed_array, int index); 98 99 // Load a field from an object on the heap. 100 Node* LoadObjectField(Node* object, int offset); 101 102 // Load |slot_index| from |context|. 103 Node* LoadContextSlot(Node* context, int slot_index); 104 Node* LoadContextSlot(Node* context, Node* slot_index); 105 // Stores |value| into |slot_index| of |context|. 106 Node* StoreContextSlot(Node* context, Node* slot_index, Node* value); 107 108 // Load the TypeFeedbackVector for the current function. 109 Node* LoadTypeFeedbackVector(); 110 111 // Project the output value at index |index| 112 Node* Projection(int index, Node* node); 113 114 // Call constructor |constructor| with |arg_count| arguments (not 115 // including receiver) and the first argument located at 116 // |first_arg|. The |new_target| is the same as the 117 // |constructor| for the new keyword, but differs for the super 118 // keyword. 119 Node* CallConstruct(Node* new_target, Node* constructor, Node* first_arg, 120 Node* arg_count); 121 122 // Call JSFunction or Callable |function| with |arg_count| 123 // arguments (not including receiver) and the first argument 124 // located at |first_arg|. 125 Node* CallJS(Node* function, Node* first_arg, Node* arg_count); 126 127 // Call an IC code stub. 128 Node* CallIC(CallInterfaceDescriptor descriptor, Node* target, Node* arg1, 129 Node* arg2, Node* arg3); 130 Node* CallIC(CallInterfaceDescriptor descriptor, Node* target, Node* arg1, 131 Node* arg2, Node* arg3, Node* arg4); 132 Node* CallIC(CallInterfaceDescriptor descriptor, Node* target, Node* arg1, 133 Node* arg2, Node* arg3, Node* arg4, Node* arg5); 134 135 // Call runtime function. 136 Node* CallRuntime(Node* function_id, Node* first_arg, Node* arg_count, 137 int return_size = 1); 138 Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1); 139 Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2); 140 Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2, 141 Node* arg3, Node* arg4); 142 143 // Jump relative to the current bytecode by |jump_offset|. 144 void Jump(Node* jump_offset); 145 146 // Jump relative to the current bytecode by |jump_offset| if the 147 // word values |lhs| and |rhs| are equal. 148 void JumpIfWordEqual(Node* lhs, Node* rhs, Node* jump_offset); 149 150 // Returns from the function. 151 void Return(); 152 153 // Dispatch to the bytecode. 154 void Dispatch(); 155 156 // Abort with the given bailout reason. 157 void Abort(BailoutReason bailout_reason); 158 159 protected: 160 static bool TargetSupportsUnalignedAccess(); 161 162 // Protected helpers (for testing) which delegate to RawMachineAssembler. 163 CallDescriptor* call_descriptor() const; 164 Graph* graph(); 165 166 private: 167 // Returns a raw pointer to start of the register file on the stack. 168 Node* RegisterFileRawPointer(); 169 // Returns a tagged pointer to the current function's BytecodeArray object. 170 Node* BytecodeArrayTaggedPointer(); 171 // Returns the offset from the BytecodeArrayPointer of the current bytecode. 172 Node* BytecodeOffset(); 173 // Returns a raw pointer to first entry in the interpreter dispatch table. 174 Node* DispatchTableRawPointer(); 175 176 // Saves and restores interpreter bytecode offset to the interpreter stack 177 // frame when performing a call. 178 void CallPrologue(); 179 void CallEpilogue(); 180 181 // Returns the offset of register |index| relative to RegisterFilePointer(). 182 Node* RegisterFrameOffset(Node* index); 183 184 Node* SmiShiftBitsConstant(); 185 Node* BytecodeOperand(int operand_index); 186 Node* BytecodeOperandSignExtended(int operand_index); 187 Node* BytecodeOperandShort(int operand_index); 188 Node* BytecodeOperandShortSignExtended(int operand_index); 189 190 Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args); 191 Node* CallIC(CallInterfaceDescriptor descriptor, Node* target, Node** args); 192 193 // Returns BytecodeOffset() advanced by delta bytecodes. Note: this does not 194 // update BytecodeOffset() itself. 195 Node* Advance(int delta); 196 Node* Advance(Node* delta); 197 198 // Starts next instruction dispatch at |new_bytecode_offset|. 199 void DispatchTo(Node* new_bytecode_offset); 200 201 // Abort operations for debug code. 202 void AbortIfWordNotEqual(Node* lhs, Node* rhs, BailoutReason bailout_reason); 203 204 // Private helpers which delegate to RawMachineAssembler. 205 Isolate* isolate(); 206 Zone* zone(); 207 208 interpreter::Bytecode bytecode_; 209 base::SmartPointer<RawMachineAssembler> raw_assembler_; 210 211 Node* accumulator_; 212 Node* bytecode_offset_; 213 Node* context_; 214 215 bool code_generated_; 216 217 DISALLOW_COPY_AND_ASSIGN(InterpreterAssembler); 218 }; 219 220 } // namespace compiler 221 } // namespace internal 222 } // namespace v8 223 224 #endif // V8_COMPILER_INTERPRETER_ASSEMBLER_H_ 225