Line data Source code
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/base/compiler-specific.h"
10 : #include "src/globals.h"
11 : #include "src/interpreter/bytecode-array-writer.h"
12 : #include "src/interpreter/bytecode-flags.h"
13 : #include "src/interpreter/bytecode-register-allocator.h"
14 : #include "src/interpreter/bytecode-register.h"
15 : #include "src/interpreter/bytecode-source-info.h"
16 : #include "src/interpreter/bytecodes.h"
17 : #include "src/interpreter/constant-array-builder.h"
18 : #include "src/interpreter/handler-table-builder.h"
19 : #include "src/zone/zone-containers.h"
20 :
21 : namespace v8 {
22 : namespace internal {
23 :
24 : class Isolate;
25 :
26 : namespace interpreter {
27 :
28 : class BytecodeLabel;
29 : class BytecodeNode;
30 : class BytecodeRegisterOptimizer;
31 : class BytecodeJumpTable;
32 : class Register;
33 :
34 : class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
35 : : public NON_EXPORTED_BASE(ZoneObject) {
36 : public:
37 : BytecodeArrayBuilder(
38 : Isolate* isolate, Zone* zone, int parameter_count, int locals_count,
39 : FeedbackVectorSpec* feedback_vector_spec = nullptr,
40 : SourcePositionTableBuilder::RecordingMode source_position_mode =
41 : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS);
42 :
43 : Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate);
44 :
45 : // Get the number of parameters expected by function.
46 : int parameter_count() const {
47 : DCHECK_GE(parameter_count_, 0);
48 : return parameter_count_;
49 : }
50 :
51 : // Get the number of locals required for bytecode array.
52 : int locals_count() const {
53 : DCHECK_GE(local_register_count_, 0);
54 : return local_register_count_;
55 : }
56 :
57 : // Returns the number of fixed (non-temporary) registers.
58 2154155 : int fixed_register_count() const { return locals_count(); }
59 :
60 : // Returns the number of fixed and temporary registers.
61 : int total_register_count() const {
62 : DCHECK_LE(fixed_register_count(),
63 : register_allocator()->maximum_register_count());
64 2153872 : return register_allocator()->maximum_register_count();
65 : }
66 :
67 : Register Local(int index) const;
68 : Register Parameter(int parameter_index) const;
69 : Register Receiver() const;
70 :
71 : // Constant loads to accumulator.
72 : BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry);
73 : BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
74 : BytecodeArrayBuilder& LoadLiteral(const AstRawString* raw_string);
75 : BytecodeArrayBuilder& LoadLiteral(const Scope* scope);
76 : BytecodeArrayBuilder& LoadLiteral(const AstValue* ast_value);
77 : BytecodeArrayBuilder& LoadUndefined();
78 : BytecodeArrayBuilder& LoadNull();
79 : BytecodeArrayBuilder& LoadTheHole();
80 : BytecodeArrayBuilder& LoadTrue();
81 : BytecodeArrayBuilder& LoadFalse();
82 : BytecodeArrayBuilder& LoadBoolean(bool value);
83 :
84 : // Global loads to the accumulator and stores from the accumulator.
85 : BytecodeArrayBuilder& LoadGlobal(const AstRawString* name, int feedback_slot,
86 : TypeofMode typeof_mode);
87 : BytecodeArrayBuilder& StoreGlobal(const AstRawString* name, int feedback_slot,
88 : LanguageMode language_mode);
89 :
90 : // Load the object at |slot_index| at |depth| in the context chain starting
91 : // with |context| into the accumulator.
92 : enum ContextSlotMutability { kImmutableSlot, kMutableSlot };
93 : BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index,
94 : int depth,
95 : ContextSlotMutability immutable);
96 :
97 : // Stores the object in the accumulator into |slot_index| at |depth| in the
98 : // context chain starting with |context|.
99 : BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
100 : int depth);
101 :
102 : // Load from a module variable into the accumulator. |depth| is the depth of
103 : // the current context relative to the module context.
104 : BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);
105 :
106 : // Store from the accumulator into a module variable. |depth| is the depth of
107 : // the current context relative to the module context.
108 : BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);
109 :
110 : // Register-accumulator transfers.
111 : BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
112 : BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
113 :
114 : // Register-register transfer.
115 : BytecodeArrayBuilder& MoveRegister(Register from, Register to);
116 :
117 : // Named load property.
118 : BytecodeArrayBuilder& LoadNamedProperty(Register object,
119 : const AstRawString* name,
120 : int feedback_slot);
121 : // Keyed load property. The key should be in the accumulator.
122 : BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
123 : // Named load property of the @@iterator symbol.
124 : BytecodeArrayBuilder& LoadIteratorProperty(Register object,
125 : int feedback_slot);
126 : // Named load property of the @@asyncIterator symbol.
127 : BytecodeArrayBuilder& LoadAsyncIteratorProperty(Register object,
128 : int feedback_slot);
129 :
130 : // Store properties. Flag for NeedsSetFunctionName() should
131 : // be in the accumulator.
132 : BytecodeArrayBuilder& StoreDataPropertyInLiteral(
133 : Register object, Register name, DataPropertyInLiteralFlags flags,
134 : int feedback_slot);
135 :
136 : // Collect type information for developer tools. The value for which we
137 : // record the type is stored in the accumulator.
138 : BytecodeArrayBuilder& CollectTypeProfile(int position);
139 :
140 : // Store a property named by a property name. The value to be stored should be
141 : // in the accumulator.
142 : BytecodeArrayBuilder& StoreNamedProperty(Register object,
143 : const AstRawString* name,
144 : int feedback_slot,
145 : LanguageMode language_mode);
146 : // Store a property named by a constant from the constant pool. The value to
147 : // be stored should be in the accumulator.
148 : BytecodeArrayBuilder& StoreNamedProperty(Register object,
149 : size_t constant_pool_entry,
150 : int feedback_slot,
151 : LanguageMode language_mode);
152 : // Store an own property named by a constant from the constant pool. The
153 : // value to be stored should be in the accumulator.
154 : BytecodeArrayBuilder& StoreNamedOwnProperty(Register object,
155 : const AstRawString* name,
156 : int feedback_slot);
157 : // Store a property keyed by a value in a register. The value to be stored
158 : // should be in the accumulator.
159 : BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
160 : int feedback_slot,
161 : LanguageMode language_mode);
162 : // Store the home object property. The value to be stored should be in the
163 : // accumulator.
164 : BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
165 : int feedback_slot,
166 : LanguageMode language_mode);
167 :
168 : // Lookup the variable with |name|.
169 : BytecodeArrayBuilder& LoadLookupSlot(const AstRawString* name,
170 : TypeofMode typeof_mode);
171 :
172 : // Lookup the variable with |name|, which is known to be at |slot_index| at
173 : // |depth| in the context chain if not shadowed by a context extension
174 : // somewhere in that context chain.
175 : BytecodeArrayBuilder& LoadLookupContextSlot(const AstRawString* name,
176 : TypeofMode typeof_mode,
177 : int slot_index, int depth);
178 :
179 : // Lookup the variable with |name|, which has its feedback in |feedback_slot|
180 : // and is known to be global if not shadowed by a context extension somewhere
181 : // up to |depth| in that context chain.
182 : BytecodeArrayBuilder& LoadLookupGlobalSlot(const AstRawString* name,
183 : TypeofMode typeof_mode,
184 : int feedback_slot, int depth);
185 :
186 : // Store value in the accumulator into the variable with |name|.
187 : BytecodeArrayBuilder& StoreLookupSlot(
188 : const AstRawString* name, LanguageMode language_mode,
189 : LookupHoistingMode lookup_hoisting_mode);
190 :
191 : // Create a new closure for a SharedFunctionInfo which will be inserted at
192 : // constant pool index |shared_function_info_entry|.
193 : BytecodeArrayBuilder& CreateClosure(size_t shared_function_info_entry,
194 : int slot, int flags);
195 :
196 : // Create a new local context for a |scope| and a closure which should be
197 : // in the accumulator.
198 : BytecodeArrayBuilder& CreateBlockContext(const Scope* scope);
199 :
200 : // Create a new context for a catch block with |exception|, |name|,
201 : // |scope|, and the closure in the accumulator.
202 : BytecodeArrayBuilder& CreateCatchContext(Register exception,
203 : const AstRawString* name,
204 : const Scope* scope);
205 :
206 : // Create a new context with size |slots|.
207 : BytecodeArrayBuilder& CreateFunctionContext(int slots);
208 :
209 : // Create a new eval context with size |slots|.
210 : BytecodeArrayBuilder& CreateEvalContext(int slots);
211 :
212 : // Creates a new context with the given |scope| for a with-statement
213 : // with the |object| in a register and the closure in the accumulator.
214 : BytecodeArrayBuilder& CreateWithContext(Register object, const Scope* scope);
215 :
216 : // Create a new arguments object in the accumulator.
217 : BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
218 :
219 : // Literals creation. Constant elements should be in the accumulator.
220 : BytecodeArrayBuilder& CreateRegExpLiteral(const AstRawString* pattern,
221 : int literal_index, int flags);
222 : BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
223 : int literal_index, int flags);
224 : BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
225 : BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
226 : int literal_index, int flags,
227 : Register output);
228 : BytecodeArrayBuilder& CreateEmptyObjectLiteral();
229 :
230 : // Gets or creates the template for a TemplateObjectDescription which will
231 : // be inserted at constant pool index |template_object_description_entry|.
232 : BytecodeArrayBuilder& GetTemplateObject(
233 : size_t template_object_description_entry);
234 :
235 : // Push the context in accumulator as the new context, and store in register
236 : // |context|.
237 : BytecodeArrayBuilder& PushContext(Register context);
238 :
239 : // Pop the current context and replace with |context|.
240 : BytecodeArrayBuilder& PopContext(Register context);
241 :
242 : // Call a JS function which is known to be a property of a JS object. The
243 : // JSFunction or Callable to be called should be in |callable|. The arguments
244 : // should be in |args|, with the receiver in |args[0]|. The call type of the
245 : // expression is in |call_type|. Type feedback is recorded in the
246 : // |feedback_slot| in the type feedback vector.
247 : BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args,
248 : int feedback_slot);
249 :
250 : // Call a JS function with an known undefined receiver. The JSFunction or
251 : // Callable to be called should be in |callable|. The arguments should be in
252 : // |args|, with no receiver as it is implicitly set to undefined. Type
253 : // feedback is recorded in the |feedback_slot| in the type feedback vector.
254 : BytecodeArrayBuilder& CallUndefinedReceiver(Register callable,
255 : RegisterList args,
256 : int feedback_slot);
257 :
258 : // Call a JS function with an any receiver, possibly (but not necessarily)
259 : // undefined. The JSFunction or Callable to be called should be in |callable|.
260 : // The arguments should be in |args|, with the receiver in |args[0]|. Type
261 : // feedback is recorded in the |feedback_slot| in the type feedback vector.
262 : BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
263 : int feedback_slot);
264 :
265 : // Tail call into a JS function. The JSFunction or Callable to be called
266 : // should be in |callable|. The arguments should be in |args|, with the
267 : // receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
268 : // the type feedback vector.
269 : BytecodeArrayBuilder& TailCall(Register callable, RegisterList args,
270 : int feedback_slot);
271 :
272 : // Call a JS function. The JSFunction or Callable to be called should be in
273 : // |callable|, the receiver in |args[0]| and the arguments in |args[1]|
274 : // onwards. The final argument must be a spread.
275 : BytecodeArrayBuilder& CallWithSpread(Register callable, RegisterList args,
276 : int feedback_slot);
277 :
278 : // Call the Construct operator. The accumulator holds the |new_target|.
279 : // The |constructor| is in a register and arguments are in |args|.
280 : BytecodeArrayBuilder& Construct(Register constructor, RegisterList args,
281 : int feedback_slot);
282 :
283 : // Call the Construct operator for use with a spread. The accumulator holds
284 : // the |new_target|. The |constructor| is in a register and arguments are in
285 : // |args|. The final argument must be a spread.
286 : BytecodeArrayBuilder& ConstructWithSpread(Register constructor,
287 : RegisterList args,
288 : int feedback_slot);
289 :
290 : // Call the runtime function with |function_id| and arguments |args|.
291 : BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
292 : RegisterList args);
293 : // Call the runtime function with |function_id| with single argument |arg|.
294 : BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
295 : Register arg);
296 : // Call the runtime function with |function_id| with no arguments.
297 : BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id);
298 :
299 : // Call the runtime function with |function_id| and arguments |args|, that
300 : // returns a pair of values. The return values will be returned in
301 : // |return_pair|.
302 : BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
303 : RegisterList args,
304 : RegisterList return_pair);
305 : // Call the runtime function with |function_id| with single argument |arg|
306 : // that returns a pair of values. The return values will be returned in
307 : // |return_pair|.
308 : BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
309 : Register arg,
310 : RegisterList return_pair);
311 :
312 : // Call the JS runtime function with |context_index| and arguments |args|,
313 : // with no receiver as it is implicitly set to undefined.
314 : BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args);
315 :
316 : // Operators (register holds the lhs value, accumulator holds the rhs value).
317 : // Type feedback will be recorded in the |feedback_slot|
318 : BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
319 : int feedback_slot);
320 : // Same as above, but lhs in the accumulator and rhs in |literal|.
321 : BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
322 : Smi* literal,
323 : int feedback_slot);
324 :
325 : // Unary and Count Operators (value stored in accumulator).
326 : // Type feedback will be recorded in the |feedback_slot|
327 : BytecodeArrayBuilder& UnaryOperation(Token::Value op, int feedback_slot);
328 :
329 : enum class ToBooleanMode {
330 : kConvertToBoolean, // Perform ToBoolean conversion on accumulator.
331 : kAlreadyBoolean, // Accumulator is already a Boolean.
332 : };
333 :
334 : // Unary Operators.
335 : BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
336 : BytecodeArrayBuilder& TypeOf();
337 :
338 : // Expects a heap object in the accumulator. Returns its super constructor in
339 : // the register |out| if it passes the IsConstructor test. Otherwise, it
340 : // throws a TypeError exception.
341 : BytecodeArrayBuilder& GetSuperConstructor(Register out);
342 :
343 : // Deletes property from an object. This expects that accumulator contains
344 : // the key to be deleted and the register contains a reference to the object.
345 : BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
346 :
347 : // Tests.
348 : BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
349 : int feedback_slot);
350 : BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
351 : BytecodeArrayBuilder& CompareUndetectable();
352 : BytecodeArrayBuilder& CompareUndefined();
353 : BytecodeArrayBuilder& CompareNull();
354 : BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
355 : BytecodeArrayBuilder& CompareTypeOf(
356 : TestTypeOfFlags::LiteralFlag literal_flag);
357 :
358 : // Converts accumulator and stores result in register |out|.
359 : BytecodeArrayBuilder& ToObject(Register out);
360 : BytecodeArrayBuilder& ToName(Register out);
361 :
362 : // Converts accumulator and stores result back in accumulator.
363 : BytecodeArrayBuilder& ToNumber(int feedback_slot);
364 : BytecodeArrayBuilder& ToNumeric(int feedback_slot);
365 :
366 : // Flow Control.
367 : BytecodeArrayBuilder& Bind(BytecodeLabel* label);
368 : BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
369 : BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
370 :
371 : BytecodeArrayBuilder& Jump(BytecodeLabel* label);
372 : BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);
373 :
374 : BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
375 : BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
376 : BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
377 : BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
378 : BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
379 : BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
380 : BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
381 : BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
382 : BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
383 : NilValue nil);
384 : BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
385 : NilValue nil);
386 :
387 : BytecodeArrayBuilder& SwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
388 :
389 : BytecodeArrayBuilder& StackCheck(int position);
390 :
391 : // Sets the pending message to the value in the accumulator, and returns the
392 : // previous pending message in the accumulator.
393 : BytecodeArrayBuilder& SetPendingMessage();
394 :
395 : BytecodeArrayBuilder& Throw();
396 : BytecodeArrayBuilder& ReThrow();
397 : BytecodeArrayBuilder& Abort(BailoutReason reason);
398 : BytecodeArrayBuilder& Return();
399 : BytecodeArrayBuilder& ThrowReferenceErrorIfHole(const AstRawString* name);
400 : BytecodeArrayBuilder& ThrowSuperNotCalledIfHole();
401 : BytecodeArrayBuilder& ThrowSuperAlreadyCalledIfNotHole();
402 :
403 : // Debugger.
404 : BytecodeArrayBuilder& Debugger();
405 :
406 : // Increment the block counter at the given slot (block code coverage).
407 : BytecodeArrayBuilder& IncBlockCounter(int slot);
408 :
409 : // Complex flow control.
410 : BytecodeArrayBuilder& ForInEnumerate(Register receiver);
411 : BytecodeArrayBuilder& ForInPrepare(RegisterList cache_info_triple,
412 : int feedback_slot);
413 : BytecodeArrayBuilder& ForInContinue(Register index, Register cache_length);
414 : BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
415 : RegisterList cache_type_array_pair,
416 : int feedback_slot);
417 : BytecodeArrayBuilder& ForInStep(Register index);
418 :
419 : // Generators.
420 : BytecodeArrayBuilder& SuspendGenerator(Register generator,
421 : RegisterList registers,
422 : int suspend_id);
423 : BytecodeArrayBuilder& RestoreGeneratorState(Register generator);
424 : BytecodeArrayBuilder& RestoreGeneratorRegisters(Register generator,
425 : RegisterList registers);
426 :
427 : // Exception handling.
428 : BytecodeArrayBuilder& MarkHandler(int handler_id,
429 : HandlerTable::CatchPrediction will_catch);
430 : BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
431 : BytecodeArrayBuilder& MarkTryEnd(int handler_id);
432 :
433 : // Creates a new handler table entry and returns a {hander_id} identifying the
434 : // entry, so that it can be referenced by above exception handling support.
435 138435 : int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
436 :
437 : // Allocates a new jump table of given |size| and |case_value_base| in the
438 : // constant pool.
439 : BytecodeJumpTable* AllocateJumpTable(int size, int case_value_base);
440 :
441 : // Gets a constant pool entry.
442 : size_t GetConstantPoolEntry(const AstRawString* raw_string);
443 : size_t GetConstantPoolEntry(const AstValue* heap_number);
444 : size_t GetConstantPoolEntry(const Scope* scope);
445 : #define ENTRY_GETTER(NAME, ...) size_t NAME##ConstantPoolEntry();
446 : SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
447 : #undef ENTRY_GETTER
448 :
449 : // Allocates a slot in the constant pool which can later be set.
450 : size_t AllocateDeferredConstantPoolEntry();
451 : // Sets the deferred value into an allocated constant pool entry.
452 : void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
453 :
454 : void InitializeReturnPosition(FunctionLiteral* literal);
455 :
456 : void SetStatementPosition(Statement* stmt) {
457 12737271 : if (stmt->position() == kNoSourcePosition) return;
458 : latest_source_info_.MakeStatementPosition(stmt->position());
459 : }
460 :
461 : void SetExpressionPosition(Expression* expr) {
462 25602008 : if (expr->position() == kNoSourcePosition) return;
463 22206493 : if (!latest_source_info_.is_statement()) {
464 : // Ensure the current expression position is overwritten with the
465 : // latest value.
466 : latest_source_info_.MakeExpressionPosition(expr->position());
467 : }
468 : }
469 :
470 : void SetExpressionAsStatementPosition(Expression* expr) {
471 232553 : if (expr->position() == kNoSourcePosition) return;
472 : latest_source_info_.MakeStatementPosition(expr->position());
473 : }
474 :
475 2606771 : void SetReturnPosition(int source_position, FunctionLiteral* literal) {
476 2606771 : if (source_position != kNoSourcePosition) {
477 : latest_source_info_.MakeStatementPosition(source_position);
478 1533066 : } else if (literal->return_position() != kNoSourcePosition) {
479 1533067 : latest_source_info_.MakeStatementPosition(literal->return_position());
480 : }
481 2606773 : }
482 :
483 : bool RequiresImplicitReturn() const { return !return_seen_in_block_; }
484 :
485 : // Returns the raw operand value for the given register or register list.
486 : uint32_t GetInputRegisterOperand(Register reg);
487 : uint32_t GetOutputRegisterOperand(Register reg);
488 : uint32_t GetInputRegisterListOperand(RegisterList reg_list);
489 : uint32_t GetOutputRegisterListOperand(RegisterList reg_list);
490 :
491 : // Outputs raw register transfer bytecodes without going through the register
492 : // optimizer.
493 : void OutputLdarRaw(Register reg);
494 : void OutputStarRaw(Register reg);
495 : void OutputMovRaw(Register src, Register dest);
496 :
497 : // Accessors
498 : BytecodeRegisterAllocator* register_allocator() {
499 : return ®ister_allocator_;
500 : }
501 : const BytecodeRegisterAllocator* register_allocator() const {
502 : return ®ister_allocator_;
503 : }
504 : Zone* zone() const { return zone_; }
505 :
506 : private:
507 : friend class BytecodeRegisterAllocator;
508 : template <Bytecode bytecode, AccumulatorUse accumulator_use,
509 : OperandType... operand_types>
510 : friend class BytecodeNodeBuilder;
511 :
512 : const FeedbackVectorSpec* feedback_vector_spec() const {
513 : return feedback_vector_spec_;
514 : }
515 :
516 : // Returns the current source position for the given |bytecode|.
517 : INLINE(BytecodeSourceInfo CurrentSourcePosition(Bytecode bytecode));
518 :
519 : #define DECLARE_BYTECODE_OUTPUT(Name, ...) \
520 : template <typename... Operands> \
521 : INLINE(BytecodeNode Create##Name##Node(Operands... operands)); \
522 : template <typename... Operands> \
523 : INLINE(void Output##Name(Operands... operands)); \
524 : template <typename... Operands> \
525 : INLINE(void Output##Name(BytecodeLabel* label, Operands... operands));
526 : BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT)
527 : #undef DECLARE_OPERAND_TYPE_INFO
528 :
529 : INLINE(void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table));
530 :
531 : bool RegisterIsValid(Register reg) const;
532 : bool RegisterListIsValid(RegisterList reg_list) const;
533 :
534 : // Sets a deferred source info which should be emitted before any future
535 : // source info (either attached to a following bytecode or as a nop).
536 : void SetDeferredSourceInfo(BytecodeSourceInfo source_info);
537 : // Either attach deferred source info to node, or emit it as a nop bytecode
538 : // if node already have valid source info.
539 : void AttachOrEmitDeferredSourceInfo(BytecodeNode* node);
540 :
541 : // Write bytecode to bytecode array.
542 : void Write(BytecodeNode* node);
543 : void WriteJump(BytecodeNode* node, BytecodeLabel* label);
544 : void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label);
545 :
546 : // Not implemented as the illegal bytecode is used inside internally
547 : // to indicate a bytecode field is not valid or an error has occurred
548 : // during bytecode generation.
549 : BytecodeArrayBuilder& Illegal();
550 :
551 : template <Bytecode bytecode, AccumulatorUse accumulator_use>
552 : void PrepareToOutputBytecode();
553 :
554 5544518 : void LeaveBasicBlock() { return_seen_in_block_ = false; }
555 :
556 : BytecodeArrayWriter* bytecode_array_writer() {
557 : return &bytecode_array_writer_;
558 : }
559 : ConstantArrayBuilder* constant_array_builder() {
560 : return &constant_array_builder_;
561 : }
562 : const ConstantArrayBuilder* constant_array_builder() const {
563 : return &constant_array_builder_;
564 : }
565 : HandlerTableBuilder* handler_table_builder() {
566 : return &handler_table_builder_;
567 : }
568 :
569 : Zone* zone_;
570 : FeedbackVectorSpec* feedback_vector_spec_;
571 : bool bytecode_generated_;
572 : ConstantArrayBuilder constant_array_builder_;
573 : HandlerTableBuilder handler_table_builder_;
574 : bool return_seen_in_block_;
575 : int parameter_count_;
576 : int local_register_count_;
577 : BytecodeRegisterAllocator register_allocator_;
578 : BytecodeArrayWriter bytecode_array_writer_;
579 : BytecodeRegisterOptimizer* register_optimizer_;
580 : BytecodeSourceInfo latest_source_info_;
581 : BytecodeSourceInfo deferred_source_info_;
582 :
583 : DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
584 : };
585 :
586 : V8_EXPORT_PRIVATE std::ostream& operator<<(
587 : std::ostream& os, const BytecodeArrayBuilder::ToBooleanMode& mode);
588 :
589 : } // namespace interpreter
590 : } // namespace internal
591 : } // namespace v8
592 :
593 : #endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|