• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_BYTECODE_ARRAY_BUILDER_H_
6 #define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
7 
8 #include "src/ast/ast.h"
9 #include "src/interpreter/bytecode-array-writer.h"
10 #include "src/interpreter/bytecode-register-allocator.h"
11 #include "src/interpreter/bytecodes.h"
12 #include "src/interpreter/constant-array-builder.h"
13 #include "src/interpreter/handler-table-builder.h"
14 #include "src/zone-containers.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 class Isolate;
20 
21 namespace interpreter {
22 
23 class BytecodeLabel;
24 class BytecodeNode;
25 class BytecodePipelineStage;
26 class Register;
27 
28 class BytecodeArrayBuilder final : public ZoneObject {
29  public:
30   BytecodeArrayBuilder(Isolate* isolate, Zone* zone, int parameter_count,
31                        int context_count, int locals_count,
32                        FunctionLiteral* literal = nullptr);
33 
34   Handle<BytecodeArray> ToBytecodeArray();
35 
36   // Get the number of parameters expected by function.
parameter_count()37   int parameter_count() const {
38     DCHECK_GE(parameter_count_, 0);
39     return parameter_count_;
40   }
41 
42   // Get the number of locals required for bytecode array.
locals_count()43   int locals_count() const {
44     DCHECK_GE(local_register_count_, 0);
45     return local_register_count_;
46   }
47 
48   // Get number of contexts required for bytecode array.
context_count()49   int context_count() const {
50     DCHECK_GE(context_register_count_, 0);
51     return context_register_count_;
52   }
53 
54   Register first_context_register() const;
55   Register last_context_register() const;
56 
57   // Returns the number of fixed (non-temporary) registers.
fixed_register_count()58   int fixed_register_count() const { return context_count() + locals_count(); }
59 
60   // Returns the number of fixed and temporary registers.
fixed_and_temporary_register_count()61   int fixed_and_temporary_register_count() const {
62     return fixed_register_count() + temporary_register_count();
63   }
64 
temporary_register_count()65   int temporary_register_count() const {
66     return temporary_register_allocator()->allocation_count();
67   }
68 
69   Register Parameter(int parameter_index) const;
70 
71   // Return true if the register |reg| represents a parameter or a
72   // local.
73   bool RegisterIsParameterOrLocal(Register reg) const;
74 
75   // Returns true if the register |reg| is a live temporary register.
76   bool TemporaryRegisterIsLive(Register reg) const;
77 
78   // Constant loads to accumulator.
79   BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
80   BytecodeArrayBuilder& LoadLiteral(Handle<Object> object);
81   BytecodeArrayBuilder& LoadUndefined();
82   BytecodeArrayBuilder& LoadNull();
83   BytecodeArrayBuilder& LoadTheHole();
84   BytecodeArrayBuilder& LoadTrue();
85   BytecodeArrayBuilder& LoadFalse();
86 
87   // Global loads to the accumulator and stores from the accumulator.
88   BytecodeArrayBuilder& LoadGlobal(int feedback_slot, TypeofMode typeof_mode);
89   BytecodeArrayBuilder& StoreGlobal(const Handle<String> name,
90                                     int feedback_slot,
91                                     LanguageMode language_mode);
92 
93   // Load the object at |slot_index| in |context| into the accumulator.
94   BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index);
95 
96   // Stores the object in the accumulator into |slot_index| of |context|.
97   BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index);
98 
99   // Register-accumulator transfers.
100   BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
101   BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
102 
103   // Register-register transfer.
104   BytecodeArrayBuilder& MoveRegister(Register from, Register to);
105 
106   // Named load property.
107   BytecodeArrayBuilder& LoadNamedProperty(Register object,
108                                           const Handle<Name> name,
109                                           int feedback_slot);
110   // Keyed load property. The key should be in the accumulator.
111   BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
112 
113   // Store properties. The value to be stored should be in the accumulator.
114   BytecodeArrayBuilder& StoreNamedProperty(Register object,
115                                            const Handle<Name> name,
116                                            int feedback_slot,
117                                            LanguageMode language_mode);
118   BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
119                                            int feedback_slot,
120                                            LanguageMode language_mode);
121 
122   // Lookup the variable with |name|.
123   BytecodeArrayBuilder& LoadLookupSlot(const Handle<String> name,
124                                        TypeofMode typeof_mode);
125 
126   // Store value in the accumulator into the variable with |name|.
127   BytecodeArrayBuilder& StoreLookupSlot(const Handle<String> name,
128                                         LanguageMode language_mode);
129 
130   // Create a new closure for the SharedFunctionInfo.
131   BytecodeArrayBuilder& CreateClosure(Handle<SharedFunctionInfo> shared_info,
132                                       PretenureFlag tenured);
133 
134   // Create a new arguments object in the accumulator.
135   BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
136 
137   // Literals creation.  Constant elements should be in the accumulator.
138   BytecodeArrayBuilder& CreateRegExpLiteral(Handle<String> pattern,
139                                             int literal_index, int flags);
140   BytecodeArrayBuilder& CreateArrayLiteral(Handle<FixedArray> constant_elements,
141                                            int literal_index, int flags);
142   BytecodeArrayBuilder& CreateObjectLiteral(
143       Handle<FixedArray> constant_properties, int literal_index, int flags);
144 
145   // Push the context in accumulator as the new context, and store in register
146   // |context|.
147   BytecodeArrayBuilder& PushContext(Register context);
148 
149   // Pop the current context and replace with |context|.
150   BytecodeArrayBuilder& PopContext(Register context);
151 
152   // Call a JS function. The JSFunction or Callable to be called should be in
153   // |callable|, the receiver should be in |receiver_args| and all subsequent
154   // arguments should be in registers <receiver_args + 1> to
155   // <receiver_args + receiver_arg_count - 1>.
156   BytecodeArrayBuilder& Call(
157       Register callable, Register receiver_args, size_t receiver_arg_count,
158       int feedback_slot, TailCallMode tail_call_mode = TailCallMode::kDisallow);
159 
TailCall(Register callable,Register receiver_args,size_t receiver_arg_count,int feedback_slot)160   BytecodeArrayBuilder& TailCall(Register callable, Register receiver_args,
161                                  size_t receiver_arg_count, int feedback_slot) {
162     return Call(callable, receiver_args, receiver_arg_count, feedback_slot,
163                 TailCallMode::kAllow);
164   }
165 
166   // Call the new operator. The accumulator holds the |new_target|.
167   // The |constructor| is in a register followed by |arg_count|
168   // consecutive arguments starting at |first_arg| for the constuctor
169   // invocation.
170   BytecodeArrayBuilder& New(Register constructor, Register first_arg,
171                             size_t arg_count);
172 
173   // Call the runtime function with |function_id|. The first argument should be
174   // in |first_arg| and all subsequent arguments should be in registers
175   // <first_arg + 1> to <first_arg + arg_count - 1>.
176   BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
177                                     Register first_arg, size_t arg_count);
178 
179   // Call the runtime function with |function_id| that returns a pair of values.
180   // The first argument should be in |first_arg| and all subsequent arguments
181   // should be in registers <first_arg + 1> to <first_arg + arg_count - 1>. The
182   // return values will be returned in <first_return> and <first_return + 1>.
183   BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
184                                            Register first_arg, size_t arg_count,
185                                            Register first_return);
186 
187   // Call the JS runtime function with |context_index|. The the receiver should
188   // be in |receiver_args| and all subsequent arguments should be in registers
189   // <receiver + 1> to <receiver + receiver_args_count - 1>.
190   BytecodeArrayBuilder& CallJSRuntime(int context_index, Register receiver_args,
191                                       size_t receiver_args_count);
192 
193   // Operators (register holds the lhs value, accumulator holds the rhs value).
194   BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg);
195 
196   // Count Operators (value stored in accumulator).
197   BytecodeArrayBuilder& CountOperation(Token::Value op);
198 
199   // Unary Operators.
200   BytecodeArrayBuilder& LogicalNot();
201   BytecodeArrayBuilder& TypeOf();
202 
203   // Deletes property from an object. This expects that accumulator contains
204   // the key to be deleted and the register contains a reference to the object.
205   BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
206 
207   // Tests.
208   BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
209 
210   // Casts.
211   BytecodeArrayBuilder& CastAccumulatorToBoolean();
212   BytecodeArrayBuilder& CastAccumulatorToJSObject();
213   BytecodeArrayBuilder& CastAccumulatorToName();
214   BytecodeArrayBuilder& CastAccumulatorToNumber();
215 
216   // Flow Control.
217   BytecodeArrayBuilder& Bind(BytecodeLabel* label);
218   BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
219 
220   BytecodeArrayBuilder& Jump(BytecodeLabel* label);
221   BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label);
222   BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
223   BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
224   BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
225   BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
226 
227   BytecodeArrayBuilder& StackCheck(int position);
228 
229   BytecodeArrayBuilder& Throw();
230   BytecodeArrayBuilder& ReThrow();
231   BytecodeArrayBuilder& Return();
232 
233   // Debugger.
234   BytecodeArrayBuilder& Debugger();
235 
236   // Complex flow control.
237   BytecodeArrayBuilder& ForInPrepare(Register cache_info_triple);
238   BytecodeArrayBuilder& ForInDone(Register index, Register cache_length);
239   BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
240                                   Register cache_type_array_pair,
241                                   int feedback_slot);
242   BytecodeArrayBuilder& ForInStep(Register index);
243 
244   // Generators.
245   BytecodeArrayBuilder& SuspendGenerator(Register generator);
246   BytecodeArrayBuilder& ResumeGenerator(Register generator);
247 
248   // Exception handling.
249   BytecodeArrayBuilder& MarkHandler(int handler_id, bool will_catch);
250   BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
251   BytecodeArrayBuilder& MarkTryEnd(int handler_id);
252 
253   // Creates a new handler table entry and returns a {hander_id} identifying the
254   // entry, so that it can be referenced by above exception handling support.
NewHandlerEntry()255   int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
256 
257   void InitializeReturnPosition(FunctionLiteral* literal);
258 
259   void SetStatementPosition(Statement* stmt);
260   void SetExpressionPosition(Expression* expr);
261   void SetExpressionAsStatementPosition(Expression* expr);
262 
263   // Accessors
temporary_register_allocator()264   TemporaryRegisterAllocator* temporary_register_allocator() {
265     return &temporary_allocator_;
266   }
temporary_register_allocator()267   const TemporaryRegisterAllocator* temporary_register_allocator() const {
268     return &temporary_allocator_;
269   }
zone()270   Zone* zone() const { return zone_; }
271 
272   void EnsureReturn();
273 
RegisterOperand(Register reg)274   static uint32_t RegisterOperand(Register reg) {
275     return static_cast<uint32_t>(reg.ToOperand());
276   }
277 
SignedOperand(int value)278   static uint32_t SignedOperand(int value) {
279     return static_cast<uint32_t>(value);
280   }
281 
UnsignedOperand(int value)282   static uint32_t UnsignedOperand(int value) {
283     DCHECK_GE(value, 0);
284     return static_cast<uint32_t>(value);
285   }
286 
UnsignedOperand(size_t value)287   static uint32_t UnsignedOperand(size_t value) {
288     DCHECK_LE(value, kMaxUInt32);
289     return static_cast<uint32_t>(value);
290   }
291 
292  private:
293   friend class BytecodeRegisterAllocator;
294 
295   static Bytecode BytecodeForBinaryOperation(Token::Value op);
296   static Bytecode BytecodeForCountOperation(Token::Value op);
297   static Bytecode BytecodeForCompareOperation(Token::Value op);
298   static Bytecode BytecodeForStoreNamedProperty(LanguageMode language_mode);
299   static Bytecode BytecodeForStoreKeyedProperty(LanguageMode language_mode);
300   static Bytecode BytecodeForLoadGlobal(TypeofMode typeof_mode);
301   static Bytecode BytecodeForStoreGlobal(LanguageMode language_mode);
302   static Bytecode BytecodeForStoreLookupSlot(LanguageMode language_mode);
303   static Bytecode BytecodeForCreateArguments(CreateArgumentsType type);
304   static Bytecode BytecodeForDelete(LanguageMode language_mode);
305   static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
306 
307   void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
308               uint32_t operand2, uint32_t operand3);
309   void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
310               uint32_t operand2);
311   void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
312   void Output(Bytecode bytecode, uint32_t operand0);
313   void Output(Bytecode bytecode);
314 
315   BytecodeArrayBuilder& OutputJump(Bytecode jump_bytecode,
316                                    BytecodeLabel* label);
317 
318   bool RegisterIsValid(Register reg) const;
319   bool OperandsAreValid(Bytecode bytecode, int operand_count,
320                         uint32_t operand0 = 0, uint32_t operand1 = 0,
321                         uint32_t operand2 = 0, uint32_t operand3 = 0) const;
322 
323   // Attach latest source position to |node|.
324   void AttachSourceInfo(BytecodeNode* node);
325 
326   // Set position for return.
327   void SetReturnPosition();
328 
329   // Gets a constant pool entry for the |object|.
330   size_t GetConstantPoolEntry(Handle<Object> object);
331 
332   // Not implemented as the illegal bytecode is used inside internally
333   // to indicate a bytecode field is not valid or an error has occured
334   // during bytecode generation.
335   BytecodeArrayBuilder& Illegal();
336 
LeaveBasicBlock()337   void LeaveBasicBlock() { return_seen_in_block_ = false; }
338 
isolate()339   Isolate* isolate() const { return isolate_; }
bytecode_array_writer()340   BytecodeArrayWriter* bytecode_array_writer() {
341     return &bytecode_array_writer_;
342   }
pipeline()343   BytecodePipelineStage* pipeline() { return pipeline_; }
constant_array_builder()344   ConstantArrayBuilder* constant_array_builder() {
345     return &constant_array_builder_;
346   }
constant_array_builder()347   const ConstantArrayBuilder* constant_array_builder() const {
348     return &constant_array_builder_;
349   }
handler_table_builder()350   HandlerTableBuilder* handler_table_builder() {
351     return &handler_table_builder_;
352   }
353 
354   Isolate* isolate_;
355   Zone* zone_;
356   bool bytecode_generated_;
357   ConstantArrayBuilder constant_array_builder_;
358   HandlerTableBuilder handler_table_builder_;
359   bool return_seen_in_block_;
360   int parameter_count_;
361   int local_register_count_;
362   int context_register_count_;
363   int return_position_;
364   TemporaryRegisterAllocator temporary_allocator_;
365   BytecodeArrayWriter bytecode_array_writer_;
366   BytecodePipelineStage* pipeline_;
367   BytecodeSourceInfo latest_source_info_;
368 
369   DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
370 };
371 
372 }  // namespace interpreter
373 }  // namespace internal
374 }  // namespace v8
375 
376 #endif  // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
377