blob: 8a109732a002ed38a202a31af90aad276599fadf [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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"
Ben Murdochc5610432016-08-08 18:44:38 +01009#include "src/interpreter/bytecode-array-writer.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010010#include "src/interpreter/bytecode-register-allocator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/interpreter/bytecodes.h"
12#include "src/interpreter/constant-array-builder.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010013#include "src/interpreter/handler-table-builder.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/zone-containers.h"
15
16namespace v8 {
17namespace internal {
18
19class Isolate;
20
21namespace interpreter {
22
23class BytecodeLabel;
Ben Murdochc5610432016-08-08 18:44:38 +010024class BytecodeNode;
25class BytecodePipelineStage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026class Register;
27
Ben Murdochda12d292016-06-02 14:46:10 +010028class BytecodeArrayBuilder final : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +010030 BytecodeArrayBuilder(Isolate* isolate, Zone* zone, int parameter_count,
Ben Murdochda12d292016-06-02 14:46:10 +010031 int context_count, int locals_count,
32 FunctionLiteral* literal = nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033
34 Handle<BytecodeArray> ToBytecodeArray();
35
Ben Murdoch097c5b22016-05-18 11:27:45 +010036 // Get the number of parameters expected by function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 int parameter_count() const {
38 DCHECK_GE(parameter_count_, 0);
39 return parameter_count_;
40 }
41
Ben Murdoch097c5b22016-05-18 11:27:45 +010042 // Get the number of locals required for bytecode array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 int locals_count() const {
44 DCHECK_GE(local_register_count_, 0);
45 return local_register_count_;
46 }
47
Ben Murdoch097c5b22016-05-18 11:27:45 +010048 // Get number of contexts required for bytecode array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 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.
58 int fixed_register_count() const { return context_count() + locals_count(); }
59
Ben Murdoch097c5b22016-05-18 11:27:45 +010060 // Returns the number of fixed and temporary registers.
61 int fixed_and_temporary_register_count() const {
62 return fixed_register_count() + temporary_register_count();
63 }
64
65 int temporary_register_count() const {
66 return temporary_register_allocator()->allocation_count();
67 }
68
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069 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
Ben Murdoch097c5b22016-05-18 11:27:45 +010075 // Returns true if the register |reg| is a live temporary register.
76 bool TemporaryRegisterIsLive(Register reg) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077
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();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086
87 // Global loads to the accumulator and stores from the accumulator.
Ben Murdoch61f157c2016-09-16 13:49:30 +010088 BytecodeArrayBuilder& LoadGlobal(int feedback_slot, TypeofMode typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105
106 // Named load property.
107 BytecodeArrayBuilder& LoadNamedProperty(Register object,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100108 const Handle<Name> name,
109 int feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 // Keyed load property. The key should be in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112
113 // Store properties. The value to be stored should be in the accumulator.
114 BytecodeArrayBuilder& StoreNamedProperty(Register object,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100115 const Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100153 // |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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159
Ben Murdoch097c5b22016-05-18 11:27:45 +0100160 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.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100175 // <first_arg + 1> to <first_arg + arg_count - 1>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 // should be in registers <first_arg + 1> to <first_arg + arg_count - 1>. The
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 // 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100188 // 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192
193 // Operators (register holds the lhs value, accumulator holds the rhs value).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100194 BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195
196 // Count Operators (value stored in accumulator).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100197 BytecodeArrayBuilder& CountOperation(Token::Value op);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198
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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206
207 // Tests.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208 BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209
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);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100223 BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
225 BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
226
Ben Murdochc5610432016-08-08 18:44:38 +0100227 BytecodeArrayBuilder& StackCheck(int position);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 BytecodeArrayBuilder& Throw();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100230 BytecodeArrayBuilder& ReThrow();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 BytecodeArrayBuilder& Return();
232
Ben Murdoch097c5b22016-05-18 11:27:45 +0100233 // Debugger.
234 BytecodeArrayBuilder& Debugger();
235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 // Complex flow control.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100237 BytecodeArrayBuilder& ForInPrepare(Register cache_info_triple);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 BytecodeArrayBuilder& ForInDone(Register index, Register cache_length);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
Ben Murdochda12d292016-06-02 14:46:10 +0100240 Register cache_type_array_pair,
241 int feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 BytecodeArrayBuilder& ForInStep(Register index);
243
Ben Murdochc5610432016-08-08 18:44:38 +0100244 // Generators.
245 BytecodeArrayBuilder& SuspendGenerator(Register generator);
246 BytecodeArrayBuilder& ResumeGenerator(Register generator);
247
Ben Murdoch097c5b22016-05-18 11:27:45 +0100248 // 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.
255 int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
256
Ben Murdochda12d292016-06-02 14:46:10 +0100257 void InitializeReturnPosition(FunctionLiteral* literal);
258
Ben Murdoch097c5b22016-05-18 11:27:45 +0100259 void SetStatementPosition(Statement* stmt);
260 void SetExpressionPosition(Expression* expr);
Ben Murdochda12d292016-06-02 14:46:10 +0100261 void SetExpressionAsStatementPosition(Expression* expr);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 // Accessors
Ben Murdoch097c5b22016-05-18 11:27:45 +0100264 TemporaryRegisterAllocator* temporary_register_allocator() {
265 return &temporary_allocator_;
266 }
267 const TemporaryRegisterAllocator* temporary_register_allocator() const {
268 return &temporary_allocator_;
269 }
Ben Murdochc5610432016-08-08 18:44:38 +0100270 Zone* zone() const { return zone_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100271
Ben Murdochda12d292016-06-02 14:46:10 +0100272 void EnsureReturn();
273
Ben Murdoch61f157c2016-09-16 13:49:30 +0100274 static uint32_t RegisterOperand(Register reg) {
275 return static_cast<uint32_t>(reg.ToOperand());
276 }
277
278 static uint32_t SignedOperand(int value) {
279 return static_cast<uint32_t>(value);
280 }
281
282 static uint32_t UnsignedOperand(int value) {
283 DCHECK_GE(value, 0);
284 return static_cast<uint32_t>(value);
285 }
286
287 static uint32_t UnsignedOperand(size_t value) {
288 DCHECK_LE(value, kMaxUInt32);
289 return static_cast<uint32_t>(value);
290 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291
292 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100293 friend class BytecodeRegisterAllocator;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294
295 static Bytecode BytecodeForBinaryOperation(Token::Value op);
296 static Bytecode BytecodeForCountOperation(Token::Value op);
297 static Bytecode BytecodeForCompareOperation(Token::Value op);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100298 static Bytecode BytecodeForStoreNamedProperty(LanguageMode language_mode);
299 static Bytecode BytecodeForStoreKeyedProperty(LanguageMode language_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 static Bytecode BytecodeForLoadGlobal(TypeofMode typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 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);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306
Ben Murdoch61f157c2016-09-16 13:49:30 +0100307 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 void Output(Bytecode bytecode);
314
315 BytecodeArrayBuilder& OutputJump(Bytecode jump_bytecode,
316 BytecodeLabel* label);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317
Ben Murdoch61f157c2016-09-16 13:49:30 +0100318 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;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322
Ben Murdochc5610432016-08-08 18:44:38 +0100323 // Attach latest source position to |node|.
324 void AttachSourceInfo(BytecodeNode* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325
Ben Murdochda12d292016-06-02 14:46:10 +0100326 // Set position for return.
327 void SetReturnPosition();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328
329 // Gets a constant pool entry for the |object|.
330 size_t GetConstantPoolEntry(Handle<Object> object);
331
Ben Murdochc5610432016-08-08 18:44:38 +0100332 // 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
Ben Murdoch61f157c2016-09-16 13:49:30 +0100337 void LeaveBasicBlock() { return_seen_in_block_ = false; }
338
Ben Murdoch097c5b22016-05-18 11:27:45 +0100339 Isolate* isolate() const { return isolate_; }
Ben Murdochc5610432016-08-08 18:44:38 +0100340 BytecodeArrayWriter* bytecode_array_writer() {
341 return &bytecode_array_writer_;
342 }
343 BytecodePipelineStage* pipeline() { return pipeline_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344 ConstantArrayBuilder* constant_array_builder() {
345 return &constant_array_builder_;
346 }
347 const ConstantArrayBuilder* constant_array_builder() const {
348 return &constant_array_builder_;
349 }
350 HandlerTableBuilder* handler_table_builder() {
351 return &handler_table_builder_;
352 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100353
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 Isolate* isolate_;
355 Zone* zone_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 bool bytecode_generated_;
357 ConstantArrayBuilder constant_array_builder_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100358 HandlerTableBuilder handler_table_builder_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100359 bool return_seen_in_block_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 int parameter_count_;
361 int local_register_count_;
362 int context_register_count_;
Ben Murdochda12d292016-06-02 14:46:10 +0100363 int return_position_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100364 TemporaryRegisterAllocator temporary_allocator_;
Ben Murdochc5610432016-08-08 18:44:38 +0100365 BytecodeArrayWriter bytecode_array_writer_;
366 BytecodePipelineStage* pipeline_;
367 BytecodeSourceInfo latest_source_info_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368
369 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
370};
371
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372} // namespace interpreter
373} // namespace internal
374} // namespace v8
375
376#endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_