// Copyright 2015 the V8 project authors. All rights reserved.
|
// Use of this source code is governed by a BSD-style license that can be
|
// found in the LICENSE file.
|
|
#ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|
#define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|
|
#include "src/ast/ast.h"
|
#include "src/base/compiler-specific.h"
|
#include "src/globals.h"
|
#include "src/interpreter/bytecode-array-writer.h"
|
#include "src/interpreter/bytecode-flags.h"
|
#include "src/interpreter/bytecode-register-allocator.h"
|
#include "src/interpreter/bytecode-register.h"
|
#include "src/interpreter/bytecode-source-info.h"
|
#include "src/interpreter/bytecodes.h"
|
#include "src/interpreter/constant-array-builder.h"
|
#include "src/interpreter/handler-table-builder.h"
|
#include "src/zone/zone-containers.h"
|
|
namespace v8 {
|
namespace internal {
|
|
class FeedbackVectorSpec;
|
class Isolate;
|
|
namespace interpreter {
|
|
class BytecodeLabel;
|
class BytecodeNode;
|
class BytecodeRegisterOptimizer;
|
class BytecodeJumpTable;
|
class Register;
|
|
class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
|
public:
|
BytecodeArrayBuilder(
|
Zone* zone, int parameter_count, int locals_count,
|
FeedbackVectorSpec* feedback_vector_spec = nullptr,
|
SourcePositionTableBuilder::RecordingMode source_position_mode =
|
SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS);
|
|
Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate);
|
|
// Get the number of parameters expected by function.
|
int parameter_count() const {
|
DCHECK_GE(parameter_count_, 0);
|
return parameter_count_;
|
}
|
|
// Get the number of locals required for bytecode array.
|
int locals_count() const {
|
DCHECK_GE(local_register_count_, 0);
|
return local_register_count_;
|
}
|
|
// Returns the number of fixed (non-temporary) registers.
|
int fixed_register_count() const { return locals_count(); }
|
|
// Returns the number of fixed and temporary registers.
|
int total_register_count() const {
|
DCHECK_LE(fixed_register_count(),
|
register_allocator()->maximum_register_count());
|
return register_allocator()->maximum_register_count();
|
}
|
|
Register Local(int index) const;
|
Register Parameter(int parameter_index) const;
|
Register Receiver() const;
|
|
// Constant loads to accumulator.
|
BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry);
|
BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
|
BytecodeArrayBuilder& LoadLiteral(double value);
|
BytecodeArrayBuilder& LoadLiteral(const AstRawString* raw_string);
|
BytecodeArrayBuilder& LoadLiteral(const Scope* scope);
|
BytecodeArrayBuilder& LoadLiteral(AstBigInt bigint);
|
BytecodeArrayBuilder& LoadLiteral(AstSymbol symbol);
|
BytecodeArrayBuilder& LoadUndefined();
|
BytecodeArrayBuilder& LoadNull();
|
BytecodeArrayBuilder& LoadTheHole();
|
BytecodeArrayBuilder& LoadTrue();
|
BytecodeArrayBuilder& LoadFalse();
|
BytecodeArrayBuilder& LoadBoolean(bool value);
|
|
// Global loads to the accumulator and stores from the accumulator.
|
BytecodeArrayBuilder& LoadGlobal(const AstRawString* name, int feedback_slot,
|
TypeofMode typeof_mode);
|
BytecodeArrayBuilder& StoreGlobal(const AstRawString* name,
|
int feedback_slot);
|
|
// Load the object at |slot_index| at |depth| in the context chain starting
|
// with |context| into the accumulator.
|
enum ContextSlotMutability { kImmutableSlot, kMutableSlot };
|
BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index,
|
int depth,
|
ContextSlotMutability immutable);
|
|
// Stores the object in the accumulator into |slot_index| at |depth| in the
|
// context chain starting with |context|.
|
BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index,
|
int depth);
|
|
// Load from a module variable into the accumulator. |depth| is the depth of
|
// the current context relative to the module context.
|
BytecodeArrayBuilder& LoadModuleVariable(int cell_index, int depth);
|
|
// Store from the accumulator into a module variable. |depth| is the depth of
|
// the current context relative to the module context.
|
BytecodeArrayBuilder& StoreModuleVariable(int cell_index, int depth);
|
|
// Register-accumulator transfers.
|
BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
|
BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
|
|
// Register-register transfer.
|
BytecodeArrayBuilder& MoveRegister(Register from, Register to);
|
|
// Named load property.
|
BytecodeArrayBuilder& LoadNamedProperty(Register object,
|
const AstRawString* name,
|
int feedback_slot);
|
// Keyed load property. The key should be in the accumulator.
|
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
|
// Named load property of the @@iterator symbol.
|
BytecodeArrayBuilder& LoadIteratorProperty(Register object,
|
int feedback_slot);
|
// Named load property of the @@asyncIterator symbol.
|
BytecodeArrayBuilder& LoadAsyncIteratorProperty(Register object,
|
int feedback_slot);
|
|
// Store properties. Flag for NeedsSetFunctionName() should
|
// be in the accumulator.
|
BytecodeArrayBuilder& StoreDataPropertyInLiteral(
|
Register object, Register name, DataPropertyInLiteralFlags flags,
|
int feedback_slot);
|
|
// Collect type information for developer tools. The value for which we
|
// record the type is stored in the accumulator.
|
BytecodeArrayBuilder& CollectTypeProfile(int position);
|
|
// Store a property named by a property name. The value to be stored should be
|
// in the accumulator.
|
BytecodeArrayBuilder& StoreNamedProperty(Register object,
|
const AstRawString* name,
|
int feedback_slot,
|
LanguageMode language_mode);
|
// Store a property named by a constant from the constant pool. The value to
|
// be stored should be in the accumulator.
|
BytecodeArrayBuilder& StoreNamedProperty(Register object,
|
size_t constant_pool_entry,
|
int feedback_slot,
|
LanguageMode language_mode);
|
// Store an own property named by a constant from the constant pool. The
|
// value to be stored should be in the accumulator.
|
BytecodeArrayBuilder& StoreNamedOwnProperty(Register object,
|
const AstRawString* name,
|
int feedback_slot);
|
// Store a property keyed by a value in a register. The value to be stored
|
// should be in the accumulator.
|
BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
|
int feedback_slot,
|
LanguageMode language_mode);
|
// Store an own element in an array literal. The value to be stored should be
|
// in the accumulator.
|
BytecodeArrayBuilder& StoreInArrayLiteral(Register array, Register index,
|
int feedback_slot);
|
// Store the home object property. The value to be stored should be in the
|
// accumulator.
|
BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
|
int feedback_slot,
|
LanguageMode language_mode);
|
|
// Store the class fields property. The initializer to be stored should
|
// be in the accumulator.
|
BytecodeArrayBuilder& StoreClassFieldsInitializer(Register constructor,
|
int feedback_slot);
|
|
// Load class fields property.
|
BytecodeArrayBuilder& LoadClassFieldsInitializer(Register constructor,
|
int feedback_slot);
|
|
// Lookup the variable with |name|.
|
BytecodeArrayBuilder& LoadLookupSlot(const AstRawString* name,
|
TypeofMode typeof_mode);
|
|
// Lookup the variable with |name|, which is known to be at |slot_index| at
|
// |depth| in the context chain if not shadowed by a context extension
|
// somewhere in that context chain.
|
BytecodeArrayBuilder& LoadLookupContextSlot(const AstRawString* name,
|
TypeofMode typeof_mode,
|
int slot_index, int depth);
|
|
// Lookup the variable with |name|, which has its feedback in |feedback_slot|
|
// and is known to be global if not shadowed by a context extension somewhere
|
// up to |depth| in that context chain.
|
BytecodeArrayBuilder& LoadLookupGlobalSlot(const AstRawString* name,
|
TypeofMode typeof_mode,
|
int feedback_slot, int depth);
|
|
// Store value in the accumulator into the variable with |name|.
|
BytecodeArrayBuilder& StoreLookupSlot(
|
const AstRawString* name, LanguageMode language_mode,
|
LookupHoistingMode lookup_hoisting_mode);
|
|
// Create a new closure for a SharedFunctionInfo which will be inserted at
|
// constant pool index |shared_function_info_entry|.
|
BytecodeArrayBuilder& CreateClosure(size_t shared_function_info_entry,
|
int slot, int flags);
|
|
// Create a new local context for a |scope|.
|
BytecodeArrayBuilder& CreateBlockContext(const Scope* scope);
|
|
// Create a new context for a catch block with |exception| and |scope|.
|
BytecodeArrayBuilder& CreateCatchContext(Register exception,
|
const Scope* scope);
|
|
// Create a new context with the given |scope| and size |slots|.
|
BytecodeArrayBuilder& CreateFunctionContext(const Scope* scope, int slots);
|
|
// Create a new eval context with the given |scope| and size |slots|.
|
BytecodeArrayBuilder& CreateEvalContext(const Scope* scope, int slots);
|
|
// Creates a new context with the given |scope| for a with-statement
|
// with the |object| in a register.
|
BytecodeArrayBuilder& CreateWithContext(Register object, const Scope* scope);
|
|
// Create a new arguments object in the accumulator.
|
BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
|
|
// Literals creation. Constant elements should be in the accumulator.
|
BytecodeArrayBuilder& CreateRegExpLiteral(const AstRawString* pattern,
|
int literal_index, int flags);
|
BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
|
int literal_index, int flags);
|
BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
|
BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
|
int literal_index, int flags,
|
Register output);
|
BytecodeArrayBuilder& CreateEmptyObjectLiteral();
|
BytecodeArrayBuilder& CloneObject(Register source, int flags,
|
int feedback_slot);
|
|
// Gets or creates the template for a TemplateObjectDescription which will
|
// be inserted at constant pool index |template_object_description_entry|.
|
BytecodeArrayBuilder& GetTemplateObject(
|
size_t template_object_description_entry, int feedback_slot);
|
|
// Push the context in accumulator as the new context, and store in register
|
// |context|.
|
BytecodeArrayBuilder& PushContext(Register context);
|
|
// Pop the current context and replace with |context|.
|
BytecodeArrayBuilder& PopContext(Register context);
|
|
// Call a JS function which is known to be a property of a JS object. The
|
// JSFunction or Callable to be called should be in |callable|. The arguments
|
// should be in |args|, with the receiver in |args[0]|. The call type of the
|
// expression is in |call_type|. Type feedback is recorded in the
|
// |feedback_slot| in the type feedback vector.
|
BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args,
|
int feedback_slot);
|
|
// Call a JS function with an known undefined receiver. The JSFunction or
|
// Callable to be called should be in |callable|. The arguments should be in
|
// |args|, with no receiver as it is implicitly set to undefined. Type
|
// feedback is recorded in the |feedback_slot| in the type feedback vector.
|
BytecodeArrayBuilder& CallUndefinedReceiver(Register callable,
|
RegisterList args,
|
int feedback_slot);
|
|
// Call a JS function with an any receiver, possibly (but not necessarily)
|
// undefined. The JSFunction or Callable to be called should be in |callable|.
|
// The arguments should be in |args|, with the receiver in |args[0]|. Type
|
// feedback is recorded in the |feedback_slot| in the type feedback vector.
|
BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
|
int feedback_slot);
|
|
// Tail call into a JS function. The JSFunction or Callable to be called
|
// should be in |callable|. The arguments should be in |args|, with the
|
// receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
|
// the type feedback vector.
|
BytecodeArrayBuilder& TailCall(Register callable, RegisterList args,
|
int feedback_slot);
|
|
// Call a JS function. The JSFunction or Callable to be called should be in
|
// |callable|, the receiver in |args[0]| and the arguments in |args[1]|
|
// onwards. The final argument must be a spread.
|
BytecodeArrayBuilder& CallWithSpread(Register callable, RegisterList args,
|
int feedback_slot);
|
|
// Call the Construct operator. The accumulator holds the |new_target|.
|
// The |constructor| is in a register and arguments are in |args|.
|
BytecodeArrayBuilder& Construct(Register constructor, RegisterList args,
|
int feedback_slot);
|
|
// Call the Construct operator for use with a spread. The accumulator holds
|
// the |new_target|. The |constructor| is in a register and arguments are in
|
// |args|. The final argument must be a spread.
|
BytecodeArrayBuilder& ConstructWithSpread(Register constructor,
|
RegisterList args,
|
int feedback_slot);
|
|
// Call the runtime function with |function_id| and arguments |args|.
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
|
RegisterList args);
|
// Call the runtime function with |function_id| with single argument |arg|.
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
|
Register arg);
|
// Call the runtime function with |function_id| with no arguments.
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id);
|
|
// Call the runtime function with |function_id| and arguments |args|, that
|
// returns a pair of values. The return values will be returned in
|
// |return_pair|.
|
BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
|
RegisterList args,
|
RegisterList return_pair);
|
// Call the runtime function with |function_id| with single argument |arg|
|
// that returns a pair of values. The return values will be returned in
|
// |return_pair|.
|
BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
|
Register arg,
|
RegisterList return_pair);
|
|
// Call the JS runtime function with |context_index| and arguments |args|,
|
// with no receiver as it is implicitly set to undefined.
|
BytecodeArrayBuilder& CallJSRuntime(int context_index, RegisterList args);
|
|
// Operators (register holds the lhs value, accumulator holds the rhs value).
|
// Type feedback will be recorded in the |feedback_slot|
|
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
|
int feedback_slot);
|
// Same as above, but lhs in the accumulator and rhs in |literal|.
|
BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
|
Smi* literal,
|
int feedback_slot);
|
|
// Unary and Count Operators (value stored in accumulator).
|
// Type feedback will be recorded in the |feedback_slot|
|
BytecodeArrayBuilder& UnaryOperation(Token::Value op, int feedback_slot);
|
|
enum class ToBooleanMode {
|
kConvertToBoolean, // Perform ToBoolean conversion on accumulator.
|
kAlreadyBoolean, // Accumulator is already a Boolean.
|
};
|
|
// Unary Operators.
|
BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
|
BytecodeArrayBuilder& TypeOf();
|
|
// Expects a heap object in the accumulator. Returns its super constructor in
|
// the register |out| if it passes the IsConstructor test. Otherwise, it
|
// throws a TypeError exception.
|
BytecodeArrayBuilder& GetSuperConstructor(Register out);
|
|
// Deletes property from an object. This expects that accumulator contains
|
// the key to be deleted and the register contains a reference to the object.
|
BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
|
|
// JavaScript defines two kinds of 'nil'.
|
enum NilValue { kNullValue, kUndefinedValue };
|
|
// Tests.
|
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
|
int feedback_slot);
|
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
|
BytecodeArrayBuilder& CompareReference(Register reg);
|
BytecodeArrayBuilder& CompareUndetectable();
|
BytecodeArrayBuilder& CompareUndefined();
|
BytecodeArrayBuilder& CompareNull();
|
BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
|
BytecodeArrayBuilder& CompareTypeOf(
|
TestTypeOfFlags::LiteralFlag literal_flag);
|
|
// Converts accumulator and stores result in register |out|.
|
BytecodeArrayBuilder& ToObject(Register out);
|
BytecodeArrayBuilder& ToName(Register out);
|
BytecodeArrayBuilder& ToString();
|
|
// Converts accumulator and stores result back in accumulator.
|
BytecodeArrayBuilder& ToNumber(int feedback_slot);
|
BytecodeArrayBuilder& ToNumeric(int feedback_slot);
|
|
// Flow Control.
|
BytecodeArrayBuilder& Bind(BytecodeLabel* label);
|
BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
|
BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
|
|
BytecodeArrayBuilder& Jump(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);
|
|
BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
|
NilValue nil);
|
BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
|
NilValue nil);
|
|
BytecodeArrayBuilder& SwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
|
|
BytecodeArrayBuilder& StackCheck(int position);
|
|
// Sets the pending message to the value in the accumulator, and returns the
|
// previous pending message in the accumulator.
|
BytecodeArrayBuilder& SetPendingMessage();
|
|
BytecodeArrayBuilder& Throw();
|
BytecodeArrayBuilder& ReThrow();
|
BytecodeArrayBuilder& Abort(AbortReason reason);
|
BytecodeArrayBuilder& Return();
|
BytecodeArrayBuilder& ThrowReferenceErrorIfHole(const AstRawString* name);
|
BytecodeArrayBuilder& ThrowSuperNotCalledIfHole();
|
BytecodeArrayBuilder& ThrowSuperAlreadyCalledIfNotHole();
|
|
// Debugger.
|
BytecodeArrayBuilder& Debugger();
|
|
// Increment the block counter at the given slot (block code coverage).
|
BytecodeArrayBuilder& IncBlockCounter(int slot);
|
|
// Complex flow control.
|
BytecodeArrayBuilder& ForInEnumerate(Register receiver);
|
BytecodeArrayBuilder& ForInPrepare(RegisterList cache_info_triple,
|
int feedback_slot);
|
BytecodeArrayBuilder& ForInContinue(Register index, Register cache_length);
|
BytecodeArrayBuilder& ForInNext(Register receiver, Register index,
|
RegisterList cache_type_array_pair,
|
int feedback_slot);
|
BytecodeArrayBuilder& ForInStep(Register index);
|
|
// Generators.
|
BytecodeArrayBuilder& SuspendGenerator(Register generator,
|
RegisterList registers,
|
int suspend_id);
|
BytecodeArrayBuilder& SwitchOnGeneratorState(Register generator,
|
BytecodeJumpTable* jump_table);
|
BytecodeArrayBuilder& ResumeGenerator(Register generator,
|
RegisterList registers);
|
|
// Exception handling.
|
BytecodeArrayBuilder& MarkHandler(int handler_id,
|
HandlerTable::CatchPrediction will_catch);
|
BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
|
BytecodeArrayBuilder& MarkTryEnd(int handler_id);
|
|
// Creates a new handler table entry and returns a {hander_id} identifying the
|
// entry, so that it can be referenced by above exception handling support.
|
int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
|
|
// Allocates a new jump table of given |size| and |case_value_base| in the
|
// constant pool.
|
BytecodeJumpTable* AllocateJumpTable(int size, int case_value_base);
|
|
// Gets a constant pool entry.
|
size_t GetConstantPoolEntry(const AstRawString* raw_string);
|
size_t GetConstantPoolEntry(AstBigInt bigint);
|
size_t GetConstantPoolEntry(const Scope* scope);
|
size_t GetConstantPoolEntry(double number);
|
#define ENTRY_GETTER(NAME, ...) size_t NAME##ConstantPoolEntry();
|
SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
|
#undef ENTRY_GETTER
|
|
// Allocates a slot in the constant pool which can later be set.
|
size_t AllocateDeferredConstantPoolEntry();
|
// Sets the deferred value into an allocated constant pool entry.
|
void SetDeferredConstantPoolEntry(size_t entry, Handle<Object> object);
|
|
void InitializeReturnPosition(FunctionLiteral* literal);
|
|
void SetStatementPosition(Statement* stmt) {
|
if (stmt->position() == kNoSourcePosition) return;
|
latest_source_info_.MakeStatementPosition(stmt->position());
|
}
|
|
void SetExpressionPosition(Expression* expr) {
|
SetExpressionPosition(expr->position());
|
}
|
|
void SetExpressionPosition(int position) {
|
if (position == kNoSourcePosition) return;
|
if (!latest_source_info_.is_statement()) {
|
// Ensure the current expression position is overwritten with the
|
// latest value.
|
latest_source_info_.MakeExpressionPosition(position);
|
}
|
}
|
|
void SetExpressionAsStatementPosition(Expression* expr) {
|
if (expr->position() == kNoSourcePosition) return;
|
latest_source_info_.MakeStatementPosition(expr->position());
|
}
|
|
void SetReturnPosition(int source_position, FunctionLiteral* literal) {
|
if (source_position != kNoSourcePosition) {
|
latest_source_info_.MakeStatementPosition(source_position);
|
} else if (literal->return_position() != kNoSourcePosition) {
|
latest_source_info_.MakeStatementPosition(literal->return_position());
|
}
|
}
|
|
bool RequiresImplicitReturn() const { return !return_seen_in_block_; }
|
|
// Returns the raw operand value for the given register or register list.
|
uint32_t GetInputRegisterOperand(Register reg);
|
uint32_t GetOutputRegisterOperand(Register reg);
|
uint32_t GetInputRegisterListOperand(RegisterList reg_list);
|
uint32_t GetOutputRegisterListOperand(RegisterList reg_list);
|
|
// Outputs raw register transfer bytecodes without going through the register
|
// optimizer.
|
void OutputLdarRaw(Register reg);
|
void OutputStarRaw(Register reg);
|
void OutputMovRaw(Register src, Register dest);
|
|
// Accessors
|
BytecodeRegisterAllocator* register_allocator() {
|
return ®ister_allocator_;
|
}
|
const BytecodeRegisterAllocator* register_allocator() const {
|
return ®ister_allocator_;
|
}
|
Zone* zone() const { return zone_; }
|
|
private:
|
friend class BytecodeRegisterAllocator;
|
template <Bytecode bytecode, AccumulatorUse accumulator_use,
|
OperandType... operand_types>
|
friend class BytecodeNodeBuilder;
|
|
const FeedbackVectorSpec* feedback_vector_spec() const {
|
return feedback_vector_spec_;
|
}
|
|
// Returns the current source position for the given |bytecode|.
|
V8_INLINE BytecodeSourceInfo CurrentSourcePosition(Bytecode bytecode);
|
|
#define DECLARE_BYTECODE_OUTPUT(Name, ...) \
|
template <typename... Operands> \
|
V8_INLINE BytecodeNode Create##Name##Node(Operands... operands); \
|
template <typename... Operands> \
|
V8_INLINE void Output##Name(Operands... operands); \
|
template <typename... Operands> \
|
V8_INLINE void Output##Name(BytecodeLabel* label, Operands... operands);
|
BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT)
|
#undef DECLARE_OPERAND_TYPE_INFO
|
|
V8_INLINE void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
|
|
bool RegisterIsValid(Register reg) const;
|
bool RegisterListIsValid(RegisterList reg_list) const;
|
|
// Sets a deferred source info which should be emitted before any future
|
// source info (either attached to a following bytecode or as a nop).
|
void SetDeferredSourceInfo(BytecodeSourceInfo source_info);
|
// Either attach deferred source info to node, or emit it as a nop bytecode
|
// if node already have valid source info.
|
void AttachOrEmitDeferredSourceInfo(BytecodeNode* node);
|
|
// Write bytecode to bytecode array.
|
void Write(BytecodeNode* node);
|
void WriteJump(BytecodeNode* node, BytecodeLabel* label);
|
void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label);
|
|
// Not implemented as the illegal bytecode is used inside internally
|
// to indicate a bytecode field is not valid or an error has occurred
|
// during bytecode generation.
|
BytecodeArrayBuilder& Illegal();
|
|
template <Bytecode bytecode, AccumulatorUse accumulator_use>
|
void PrepareToOutputBytecode();
|
|
void LeaveBasicBlock() { return_seen_in_block_ = false; }
|
|
BytecodeArrayWriter* bytecode_array_writer() {
|
return &bytecode_array_writer_;
|
}
|
ConstantArrayBuilder* constant_array_builder() {
|
return &constant_array_builder_;
|
}
|
const ConstantArrayBuilder* constant_array_builder() const {
|
return &constant_array_builder_;
|
}
|
HandlerTableBuilder* handler_table_builder() {
|
return &handler_table_builder_;
|
}
|
|
Zone* zone_;
|
FeedbackVectorSpec* feedback_vector_spec_;
|
bool bytecode_generated_;
|
ConstantArrayBuilder constant_array_builder_;
|
HandlerTableBuilder handler_table_builder_;
|
bool return_seen_in_block_;
|
int parameter_count_;
|
int local_register_count_;
|
BytecodeRegisterAllocator register_allocator_;
|
BytecodeArrayWriter bytecode_array_writer_;
|
BytecodeRegisterOptimizer* register_optimizer_;
|
BytecodeSourceInfo latest_source_info_;
|
BytecodeSourceInfo deferred_source_info_;
|
|
DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
|
};
|
|
V8_EXPORT_PRIVATE std::ostream& operator<<(
|
std::ostream& os, const BytecodeArrayBuilder::ToBooleanMode& mode);
|
|
} // namespace interpreter
|
} // namespace internal
|
} // namespace v8
|
|
#endif // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
|