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