blob: 3930a06e1b6f64e60bd6718916a5ccb152195f93 [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 Murdoch097c5b22016-05-18 11:27:45 +010014#include "src/interpreter/source-position-table.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/zone-containers.h"
16
17namespace v8 {
18namespace internal {
19
20class Isolate;
21
22namespace interpreter {
23
24class BytecodeLabel;
Ben Murdochc5610432016-08-08 18:44:38 +010025class BytecodeNode;
26class BytecodePipelineStage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027class Register;
28
Ben Murdochda12d292016-06-02 14:46:10 +010029class BytecodeArrayBuilder final : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +010031 BytecodeArrayBuilder(Isolate* isolate, Zone* zone, int parameter_count,
Ben Murdochda12d292016-06-02 14:46:10 +010032 int context_count, int locals_count,
33 FunctionLiteral* literal = nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034
35 Handle<BytecodeArray> ToBytecodeArray();
36
Ben Murdoch097c5b22016-05-18 11:27:45 +010037 // Get the number of parameters expected by function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 int parameter_count() const {
39 DCHECK_GE(parameter_count_, 0);
40 return parameter_count_;
41 }
42
Ben Murdoch097c5b22016-05-18 11:27:45 +010043 // Get the number of locals required for bytecode array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 int locals_count() const {
45 DCHECK_GE(local_register_count_, 0);
46 return local_register_count_;
47 }
48
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 // Get number of contexts required for bytecode array.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 int context_count() const {
51 DCHECK_GE(context_register_count_, 0);
52 return context_register_count_;
53 }
54
55 Register first_context_register() const;
56 Register last_context_register() const;
57
58 // Returns the number of fixed (non-temporary) registers.
59 int fixed_register_count() const { return context_count() + locals_count(); }
60
Ben Murdoch097c5b22016-05-18 11:27:45 +010061 // Returns the number of fixed and temporary registers.
62 int fixed_and_temporary_register_count() const {
63 return fixed_register_count() + temporary_register_count();
64 }
65
66 int temporary_register_count() const {
67 return temporary_register_allocator()->allocation_count();
68 }
69
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 Register Parameter(int parameter_index) const;
71
72 // Return true if the register |reg| represents a parameter or a
73 // local.
74 bool RegisterIsParameterOrLocal(Register reg) const;
75
Ben Murdoch097c5b22016-05-18 11:27:45 +010076 // Returns true if the register |reg| is a live temporary register.
77 bool TemporaryRegisterIsLive(Register reg) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078
79 // Constant loads to accumulator.
80 BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
81 BytecodeArrayBuilder& LoadLiteral(Handle<Object> object);
82 BytecodeArrayBuilder& LoadUndefined();
83 BytecodeArrayBuilder& LoadNull();
84 BytecodeArrayBuilder& LoadTheHole();
85 BytecodeArrayBuilder& LoadTrue();
86 BytecodeArrayBuilder& LoadFalse();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087
88 // Global loads to the accumulator and stores from the accumulator.
89 BytecodeArrayBuilder& LoadGlobal(const Handle<String> name, int feedback_slot,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 TypeofMode typeof_mode);
91 BytecodeArrayBuilder& StoreGlobal(const Handle<String> name,
92 int feedback_slot,
93 LanguageMode language_mode);
94
95 // Load the object at |slot_index| in |context| into the accumulator.
96 BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index);
97
98 // Stores the object in the accumulator into |slot_index| of |context|.
99 BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index);
100
101 // Register-accumulator transfers.
102 BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
103 BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
104
105 // Register-register transfer.
106 BytecodeArrayBuilder& MoveRegister(Register from, Register to);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107
108 // Named load property.
109 BytecodeArrayBuilder& LoadNamedProperty(Register object,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110 const Handle<Name> name,
111 int feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 // Keyed load property. The key should be in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114
115 // Store properties. The value to be stored should be in the accumulator.
116 BytecodeArrayBuilder& StoreNamedProperty(Register object,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100117 const Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 int feedback_slot,
119 LanguageMode language_mode);
120 BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
121 int feedback_slot,
122 LanguageMode language_mode);
123
124 // Lookup the variable with |name|.
125 BytecodeArrayBuilder& LoadLookupSlot(const Handle<String> name,
126 TypeofMode typeof_mode);
127
128 // Store value in the accumulator into the variable with |name|.
129 BytecodeArrayBuilder& StoreLookupSlot(const Handle<String> name,
130 LanguageMode language_mode);
131
132 // Create a new closure for the SharedFunctionInfo.
133 BytecodeArrayBuilder& CreateClosure(Handle<SharedFunctionInfo> shared_info,
134 PretenureFlag tenured);
135
136 // Create a new arguments object in the accumulator.
137 BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
138
139 // Literals creation. Constant elements should be in the accumulator.
140 BytecodeArrayBuilder& CreateRegExpLiteral(Handle<String> pattern,
141 int literal_index, int flags);
142 BytecodeArrayBuilder& CreateArrayLiteral(Handle<FixedArray> constant_elements,
143 int literal_index, int flags);
144 BytecodeArrayBuilder& CreateObjectLiteral(
145 Handle<FixedArray> constant_properties, int literal_index, int flags);
146
147 // Push the context in accumulator as the new context, and store in register
148 // |context|.
149 BytecodeArrayBuilder& PushContext(Register context);
150
151 // Pop the current context and replace with |context|.
152 BytecodeArrayBuilder& PopContext(Register context);
153
154 // Call a JS function. The JSFunction or Callable to be called should be in
Ben Murdoch097c5b22016-05-18 11:27:45 +0100155 // |callable|, the receiver should be in |receiver_args| and all subsequent
156 // arguments should be in registers <receiver_args + 1> to
157 // <receiver_args + receiver_arg_count - 1>.
158 BytecodeArrayBuilder& Call(
159 Register callable, Register receiver_args, size_t receiver_arg_count,
160 int feedback_slot, TailCallMode tail_call_mode = TailCallMode::kDisallow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161
Ben Murdoch097c5b22016-05-18 11:27:45 +0100162 BytecodeArrayBuilder& TailCall(Register callable, Register receiver_args,
163 size_t receiver_arg_count, int feedback_slot) {
164 return Call(callable, receiver_args, receiver_arg_count, feedback_slot,
165 TailCallMode::kAllow);
166 }
167
168 // Call the new operator. The accumulator holds the |new_target|.
169 // The |constructor| is in a register followed by |arg_count|
170 // consecutive arguments starting at |first_arg| for the constuctor
171 // invocation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 BytecodeArrayBuilder& New(Register constructor, Register first_arg,
173 size_t arg_count);
174
175 // Call the runtime function with |function_id|. The first argument should be
176 // in |first_arg| and all subsequent arguments should be in registers
Ben Murdoch097c5b22016-05-18 11:27:45 +0100177 // <first_arg + 1> to <first_arg + arg_count - 1>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
179 Register first_arg, size_t arg_count);
180
181 // Call the runtime function with |function_id| that returns a pair of values.
182 // The first argument should be in |first_arg| and all subsequent arguments
Ben Murdoch097c5b22016-05-18 11:27:45 +0100183 // should be in registers <first_arg + 1> to <first_arg + arg_count - 1>. The
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 // return values will be returned in <first_return> and <first_return + 1>.
185 BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
186 Register first_arg, size_t arg_count,
187 Register first_return);
188
189 // Call the JS runtime function with |context_index|. The the receiver should
Ben Murdoch097c5b22016-05-18 11:27:45 +0100190 // be in |receiver_args| and all subsequent arguments should be in registers
191 // <receiver + 1> to <receiver + receiver_args_count - 1>.
192 BytecodeArrayBuilder& CallJSRuntime(int context_index, Register receiver_args,
193 size_t receiver_args_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194
195 // Operators (register holds the lhs value, accumulator holds the rhs value).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197
198 // Count Operators (value stored in accumulator).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100199 BytecodeArrayBuilder& CountOperation(Token::Value op);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200
201 // Unary Operators.
202 BytecodeArrayBuilder& LogicalNot();
203 BytecodeArrayBuilder& TypeOf();
204
205 // Deletes property from an object. This expects that accumulator contains
206 // the key to be deleted and the register contains a reference to the object.
207 BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208
209 // Tests.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210 BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211
212 // Casts.
213 BytecodeArrayBuilder& CastAccumulatorToBoolean();
214 BytecodeArrayBuilder& CastAccumulatorToJSObject();
215 BytecodeArrayBuilder& CastAccumulatorToName();
216 BytecodeArrayBuilder& CastAccumulatorToNumber();
217
218 // Flow Control.
219 BytecodeArrayBuilder& Bind(BytecodeLabel* label);
220 BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
221
222 BytecodeArrayBuilder& Jump(BytecodeLabel* label);
223 BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label);
224 BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100225 BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
227 BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
228
Ben Murdochc5610432016-08-08 18:44:38 +0100229 BytecodeArrayBuilder& StackCheck(int position);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 BytecodeArrayBuilder& Throw();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100232 BytecodeArrayBuilder& ReThrow();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 BytecodeArrayBuilder& Return();
234
Ben Murdoch097c5b22016-05-18 11:27:45 +0100235 // Debugger.
236 BytecodeArrayBuilder& Debugger();
237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 // Complex flow control.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 BytecodeArrayBuilder& ForInPrepare(Register cache_info_triple);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 BytecodeArrayBuilder& ForInDone(Register index, Register cache_length);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241 BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
Ben Murdochda12d292016-06-02 14:46:10 +0100242 Register cache_type_array_pair,
243 int feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 BytecodeArrayBuilder& ForInStep(Register index);
245
Ben Murdochc5610432016-08-08 18:44:38 +0100246 // Generators.
247 BytecodeArrayBuilder& SuspendGenerator(Register generator);
248 BytecodeArrayBuilder& ResumeGenerator(Register generator);
249
Ben Murdoch097c5b22016-05-18 11:27:45 +0100250 // Exception handling.
251 BytecodeArrayBuilder& MarkHandler(int handler_id, bool will_catch);
252 BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
253 BytecodeArrayBuilder& MarkTryEnd(int handler_id);
254
255 // Creates a new handler table entry and returns a {hander_id} identifying the
256 // entry, so that it can be referenced by above exception handling support.
257 int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
258
Ben Murdochda12d292016-06-02 14:46:10 +0100259 void InitializeReturnPosition(FunctionLiteral* literal);
260
Ben Murdoch097c5b22016-05-18 11:27:45 +0100261 void SetStatementPosition(Statement* stmt);
262 void SetExpressionPosition(Expression* expr);
Ben Murdochda12d292016-06-02 14:46:10 +0100263 void SetExpressionAsStatementPosition(Expression* expr);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100264
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 // Accessors
Ben Murdoch097c5b22016-05-18 11:27:45 +0100266 TemporaryRegisterAllocator* temporary_register_allocator() {
267 return &temporary_allocator_;
268 }
269 const TemporaryRegisterAllocator* temporary_register_allocator() const {
270 return &temporary_allocator_;
271 }
Ben Murdochc5610432016-08-08 18:44:38 +0100272 Zone* zone() const { return zone_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100273
Ben Murdochda12d292016-06-02 14:46:10 +0100274 void EnsureReturn();
275
Ben Murdochda12d292016-06-02 14:46:10 +0100276 static uint32_t RegisterOperand(Register reg);
277 static Register RegisterFromOperand(uint32_t operand);
278 static uint32_t SignedOperand(int value, OperandSize size);
279 static uint32_t UnsignedOperand(int value);
280 static uint32_t UnsignedOperand(size_t value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281
282 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100283 friend class BytecodeRegisterAllocator;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284
285 static Bytecode BytecodeForBinaryOperation(Token::Value op);
286 static Bytecode BytecodeForCountOperation(Token::Value op);
287 static Bytecode BytecodeForCompareOperation(Token::Value op);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 static Bytecode BytecodeForStoreIC(LanguageMode language_mode);
289 static Bytecode BytecodeForKeyedStoreIC(LanguageMode language_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290 static Bytecode BytecodeForLoadGlobal(TypeofMode typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 static Bytecode BytecodeForStoreGlobal(LanguageMode language_mode);
292 static Bytecode BytecodeForStoreLookupSlot(LanguageMode language_mode);
293 static Bytecode BytecodeForCreateArguments(CreateArgumentsType type);
294 static Bytecode BytecodeForDelete(LanguageMode language_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295 static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 static Bytecode GetJumpWithConstantOperand(Bytecode jump_smi8_operand);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 void Output(Bytecode bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100300 void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
301 uint32_t operand0, uint32_t operand1, uint32_t operand2,
302 uint32_t operand3);
303 void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
304 uint32_t operand0, uint32_t operand1, uint32_t operand2);
305 void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
306 uint32_t operand0, uint32_t operand1);
307 void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
308 uint32_t operand0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309
310 BytecodeArrayBuilder& OutputJump(Bytecode jump_bytecode,
311 BytecodeLabel* label);
Ben Murdochc5610432016-08-08 18:44:38 +0100312 void PatchJump(size_t jump_target, size_t jump_location);
313 void PatchJumpWith8BitOperand(ZoneVector<uint8_t>* bytecodes,
314 size_t jump_location, int delta);
315 void PatchJumpWith16BitOperand(ZoneVector<uint8_t>* bytecodes,
316 size_t jump_location, int delta);
317 void PatchJumpWith32BitOperand(ZoneVector<uint8_t>* bytecodes,
318 size_t jump_location, int delta);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319
320 void LeaveBasicBlock();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321
Ben Murdochda12d292016-06-02 14:46:10 +0100322 bool OperandIsValid(Bytecode bytecode, OperandScale operand_scale,
323 int operand_index, uint32_t operand_value) const;
324 bool RegisterIsValid(Register reg, OperandSize reg_size) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325
Ben Murdochc5610432016-08-08 18:44:38 +0100326 // Attach latest source position to |node|.
327 void AttachSourceInfo(BytecodeNode* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328
Ben Murdochda12d292016-06-02 14:46:10 +0100329 // Set position for return.
330 void SetReturnPosition();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331
332 // Gets a constant pool entry for the |object|.
333 size_t GetConstantPoolEntry(Handle<Object> object);
334
Ben Murdochc5610432016-08-08 18:44:38 +0100335 // Not implemented as the illegal bytecode is used inside internally
336 // to indicate a bytecode field is not valid or an error has occured
337 // during bytecode generation.
338 BytecodeArrayBuilder& Illegal();
339
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340 Isolate* isolate() const { return isolate_; }
Ben Murdochc5610432016-08-08 18:44:38 +0100341 BytecodeArrayWriter* bytecode_array_writer() {
342 return &bytecode_array_writer_;
343 }
344 BytecodePipelineStage* pipeline() { return pipeline_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100345 ConstantArrayBuilder* constant_array_builder() {
346 return &constant_array_builder_;
347 }
348 const ConstantArrayBuilder* constant_array_builder() const {
349 return &constant_array_builder_;
350 }
351 HandlerTableBuilder* handler_table_builder() {
352 return &handler_table_builder_;
353 }
354 SourcePositionTableBuilder* source_position_table_builder() {
355 return &source_position_table_builder_;
356 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358 Isolate* isolate_;
359 Zone* zone_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 bool bytecode_generated_;
361 ConstantArrayBuilder constant_array_builder_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100362 HandlerTableBuilder handler_table_builder_;
363 SourcePositionTableBuilder source_position_table_builder_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 bool exit_seen_in_block_;
365 int unbound_jumps_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 int parameter_count_;
367 int local_register_count_;
368 int context_register_count_;
Ben Murdochda12d292016-06-02 14:46:10 +0100369 int return_position_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100370 TemporaryRegisterAllocator temporary_allocator_;
Ben Murdochc5610432016-08-08 18:44:38 +0100371 BytecodeArrayWriter bytecode_array_writer_;
372 BytecodePipelineStage* pipeline_;
373 BytecodeSourceInfo latest_source_info_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374
375 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
376};
377
378
379// A label representing a branch target in a bytecode array. When a
380// label is bound, it represents a known position in the bytecode
381// array. For labels that are forward references there can be at most
382// one reference whilst it is unbound.
383class BytecodeLabel final {
384 public:
385 BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {}
386
387 bool is_bound() const { return bound_; }
388 size_t offset() const { return offset_; }
389
390 private:
391 static const size_t kInvalidOffset = static_cast<size_t>(-1);
392
393 void bind_to(size_t offset) {
394 DCHECK(!bound_ && offset != kInvalidOffset);
395 offset_ = offset;
396 bound_ = true;
397 }
398
399 void set_referrer(size_t offset) {
400 DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset);
401 offset_ = offset;
402 }
403
404 bool is_forward_target() const {
405 return offset() != kInvalidOffset && !is_bound();
406 }
407
408 // There are three states for a label:
409 // bound_ offset_
410 // UNSET false kInvalidOffset
411 // FORWARD_TARGET false Offset of referring jump
412 // BACKWARD_TARGET true Offset of label in bytecode array when bound
413 bool bound_;
414 size_t offset_;
415
416 friend class BytecodeArrayBuilder;
417};
418
419} // namespace interpreter
420} // namespace internal
421} // namespace v8
422
423#endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_