18b4b6b93c
This CL merges nested loops that share the same header offset with its parent loop, by not emitting JumpLoop bytecode for these inner loops. Instead, we generate a Jump to its parent's JumpToHeader (which in turn can be a JumpLoop or another Jump to its parent's JumpToHeader). Originally, every loop had a unique first Bytecode to jump to. Since IterationBody StackChecks are going to become implicit this will no longer be the case. As a note, this CL just sets the foundation that the follow-up CLs will build on top of. Since we have explicit StackChecks, and they are at the beginning of loops we do not have nested loops as of now. Bug: v8:10149, v8:9960 Change-Id: I6daee4d2c6d6216f022228c87c4aa74e163997b2 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2062390 Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#66626}
546 lines
22 KiB
C++
546 lines
22 KiB
C++
// 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_GENERATOR_H_
|
|
#define V8_INTERPRETER_BYTECODE_GENERATOR_H_
|
|
|
|
#include "src/ast/ast.h"
|
|
#include "src/interpreter/bytecode-array-builder.h"
|
|
#include "src/interpreter/bytecode-label.h"
|
|
#include "src/interpreter/bytecode-register.h"
|
|
#include "src/interpreter/bytecodes.h"
|
|
#include "src/objects/feedback-vector.h"
|
|
#include "src/objects/function-kind.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
class AstNodeSourceRanges;
|
|
class AstStringConstants;
|
|
class BytecodeArray;
|
|
class UnoptimizedCompilationInfo;
|
|
enum class SourceRangeKind;
|
|
|
|
namespace interpreter {
|
|
|
|
class TopLevelDeclarationsBuilder;
|
|
class LoopBuilder;
|
|
class BlockCoverageBuilder;
|
|
class BytecodeJumpTable;
|
|
|
|
class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
|
public:
|
|
explicit BytecodeGenerator(
|
|
UnoptimizedCompilationInfo* info,
|
|
const AstStringConstants* ast_string_constants,
|
|
std::vector<FunctionLiteral*>* eager_inner_literals);
|
|
|
|
void GenerateBytecode(uintptr_t stack_limit);
|
|
template <typename LocalIsolate>
|
|
Handle<BytecodeArray> FinalizeBytecode(LocalIsolate* isolate,
|
|
Handle<Script> script);
|
|
template <typename LocalIsolate>
|
|
Handle<ByteArray> FinalizeSourcePositionTable(LocalIsolate* isolate);
|
|
|
|
#ifdef DEBUG
|
|
int CheckBytecodeMatches(BytecodeArray bytecode);
|
|
#endif
|
|
|
|
#define DECLARE_VISIT(type) void Visit##type(type* node);
|
|
AST_NODE_LIST(DECLARE_VISIT)
|
|
#undef DECLARE_VISIT
|
|
|
|
// Visiting function for declarations list and statements are overridden.
|
|
void VisitModuleDeclarations(Declaration::List* declarations);
|
|
void VisitGlobalDeclarations(Declaration::List* declarations);
|
|
void VisitDeclarations(Declaration::List* declarations);
|
|
void VisitStatements(const ZonePtrList<Statement>* statments);
|
|
|
|
private:
|
|
class AccumulatorPreservingScope;
|
|
class ContextScope;
|
|
class ControlScope;
|
|
class ControlScopeForBreakable;
|
|
class ControlScopeForIteration;
|
|
class ControlScopeForTopLevel;
|
|
class ControlScopeForTryCatch;
|
|
class ControlScopeForTryFinally;
|
|
class CurrentScope;
|
|
class EffectResultScope;
|
|
class ExpressionResultScope;
|
|
class FeedbackSlotCache;
|
|
class IteratorRecord;
|
|
class LoopScope;
|
|
class NaryCodeCoverageSlots;
|
|
class OptionalChainNullLabelScope;
|
|
class RegisterAllocationScope;
|
|
class TestResultScope;
|
|
class TopLevelDeclarationsBuilder;
|
|
class ValueResultScope;
|
|
|
|
using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
|
|
|
|
enum class TestFallthrough { kThen, kElse, kNone };
|
|
enum class TypeHint { kAny, kBoolean, kString };
|
|
enum class AccumulatorPreservingMode { kNone, kPreserve };
|
|
|
|
// An assignment has to evaluate its LHS before its RHS, but has to assign to
|
|
// the LHS after both evaluations are done. This class stores the data
|
|
// computed in the LHS evaulation that has to live across the RHS evaluation,
|
|
// and is used in the actual LHS assignment.
|
|
class AssignmentLhsData {
|
|
public:
|
|
static AssignmentLhsData NonProperty(Expression* expr);
|
|
static AssignmentLhsData NamedProperty(Expression* object_expr,
|
|
Register object,
|
|
const AstRawString* name);
|
|
static AssignmentLhsData KeyedProperty(Register object, Register key);
|
|
static AssignmentLhsData PrivateMethodOrAccessor(AssignType type,
|
|
Property* property);
|
|
static AssignmentLhsData NamedSuperProperty(
|
|
RegisterList super_property_args);
|
|
static AssignmentLhsData KeyedSuperProperty(
|
|
RegisterList super_property_args);
|
|
|
|
AssignType assign_type() const { return assign_type_; }
|
|
Expression* expr() const {
|
|
DCHECK(assign_type_ == NON_PROPERTY || assign_type_ == PRIVATE_METHOD ||
|
|
assign_type_ == PRIVATE_GETTER_ONLY ||
|
|
assign_type_ == PRIVATE_SETTER_ONLY ||
|
|
assign_type_ == PRIVATE_GETTER_AND_SETTER);
|
|
return expr_;
|
|
}
|
|
Expression* object_expr() const {
|
|
DCHECK_EQ(assign_type_, NAMED_PROPERTY);
|
|
return object_expr_;
|
|
}
|
|
Register object() const {
|
|
DCHECK(assign_type_ == NAMED_PROPERTY || assign_type_ == KEYED_PROPERTY);
|
|
return object_;
|
|
}
|
|
Register key() const {
|
|
DCHECK(assign_type_ == KEYED_PROPERTY);
|
|
return key_;
|
|
}
|
|
const AstRawString* name() const {
|
|
DCHECK(assign_type_ == NAMED_PROPERTY);
|
|
return name_;
|
|
}
|
|
RegisterList super_property_args() const {
|
|
DCHECK(assign_type_ == NAMED_SUPER_PROPERTY ||
|
|
assign_type_ == KEYED_SUPER_PROPERTY);
|
|
return super_property_args_;
|
|
}
|
|
|
|
private:
|
|
AssignmentLhsData(AssignType assign_type, Expression* expr,
|
|
RegisterList super_property_args, Register object,
|
|
Register key, Expression* object_expr,
|
|
const AstRawString* name)
|
|
: assign_type_(assign_type),
|
|
expr_(expr),
|
|
super_property_args_(super_property_args),
|
|
object_(object),
|
|
key_(key),
|
|
object_expr_(object_expr),
|
|
name_(name) {}
|
|
|
|
AssignType assign_type_;
|
|
|
|
// Different assignment types use different fields:
|
|
//
|
|
// NON_PROPERTY: expr
|
|
// NAMED_PROPERTY: object_expr, object, name
|
|
// KEYED_PROPERTY, PRIVATE_METHOD: object, key
|
|
// NAMED_SUPER_PROPERTY: super_property_args
|
|
// KEYED_SUPER_PROPERT: super_property_args
|
|
Expression* expr_;
|
|
RegisterList super_property_args_;
|
|
Register object_;
|
|
Register key_;
|
|
Expression* object_expr_;
|
|
const AstRawString* name_;
|
|
};
|
|
|
|
void GenerateBytecodeBody();
|
|
template <typename LocalIsolate>
|
|
void AllocateDeferredConstants(LocalIsolate* isolate, Handle<Script> script);
|
|
|
|
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
|
|
|
|
// Dispatched from VisitBinaryOperation.
|
|
void VisitArithmeticExpression(BinaryOperation* binop);
|
|
void VisitCommaExpression(BinaryOperation* binop);
|
|
void VisitLogicalOrExpression(BinaryOperation* binop);
|
|
void VisitLogicalAndExpression(BinaryOperation* binop);
|
|
void VisitNullishExpression(BinaryOperation* binop);
|
|
|
|
// Dispatched from VisitNaryOperation.
|
|
void VisitNaryArithmeticExpression(NaryOperation* expr);
|
|
void VisitNaryCommaExpression(NaryOperation* expr);
|
|
void VisitNaryLogicalOrExpression(NaryOperation* expr);
|
|
void VisitNaryLogicalAndExpression(NaryOperation* expr);
|
|
void VisitNaryNullishExpression(NaryOperation* expr);
|
|
|
|
// Dispatched from VisitUnaryOperation.
|
|
void VisitVoid(UnaryOperation* expr);
|
|
void VisitTypeOf(UnaryOperation* expr);
|
|
void VisitNot(UnaryOperation* expr);
|
|
void VisitDelete(UnaryOperation* expr);
|
|
|
|
// Visits a typeof expression for the value on which to perform the typeof.
|
|
void VisitForTypeOfValue(Expression* expr);
|
|
|
|
// Used by flow control routines to evaluate loop condition.
|
|
void VisitCondition(Expression* expr);
|
|
|
|
// Visit the arguments expressions in |args| and store them in |args_regs|,
|
|
// growing |args_regs| for each argument visited.
|
|
void VisitArguments(const ZonePtrList<Expression>* args,
|
|
RegisterList* arg_regs);
|
|
|
|
// Visit a keyed super property load. The optional
|
|
// |opt_receiver_out| register will have the receiver stored to it
|
|
// if it's a valid register. The loaded value is placed in the
|
|
// accumulator.
|
|
void VisitKeyedSuperPropertyLoad(Property* property,
|
|
Register opt_receiver_out);
|
|
|
|
// Visit a named super property load. The optional
|
|
// |opt_receiver_out| register will have the receiver stored to it
|
|
// if it's a valid register. The loaded value is placed in the
|
|
// accumulator.
|
|
void VisitNamedSuperPropertyLoad(Property* property,
|
|
Register opt_receiver_out);
|
|
|
|
void VisitPropertyLoad(Register obj, Property* expr);
|
|
void VisitPropertyLoadForRegister(Register obj, Property* expr,
|
|
Register destination);
|
|
|
|
AssignmentLhsData PrepareAssignmentLhs(
|
|
Expression* lhs, AccumulatorPreservingMode accumulator_preserving_mode =
|
|
AccumulatorPreservingMode::kNone);
|
|
void BuildAssignment(const AssignmentLhsData& data, Token::Value op,
|
|
LookupHoistingMode lookup_hoisting_mode);
|
|
|
|
void BuildThisVariableLoad();
|
|
|
|
void BuildDeclareCall(Runtime::FunctionId id);
|
|
|
|
Expression* GetDestructuringDefaultValue(Expression** target);
|
|
void BuildDestructuringArrayAssignment(
|
|
ArrayLiteral* pattern, Token::Value op,
|
|
LookupHoistingMode lookup_hoisting_mode);
|
|
void BuildDestructuringObjectAssignment(
|
|
ObjectLiteral* pattern, Token::Value op,
|
|
LookupHoistingMode lookup_hoisting_mode);
|
|
|
|
void BuildLoadNamedProperty(const Expression* object_expr, Register object,
|
|
const AstRawString* name);
|
|
void BuildStoreNamedProperty(const Expression* object_expr, Register object,
|
|
const AstRawString* name);
|
|
|
|
void BuildVariableLoad(Variable* variable, HoleCheckMode hole_check_mode,
|
|
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
|
|
void BuildVariableLoadForAccumulatorValue(
|
|
Variable* variable, HoleCheckMode hole_check_mode,
|
|
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
|
|
void BuildVariableAssignment(
|
|
Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
|
|
LookupHoistingMode lookup_hoisting_mode = LookupHoistingMode::kNormal);
|
|
void BuildLiteralCompareNil(Token::Value compare_op,
|
|
BytecodeArrayBuilder::NilValue nil);
|
|
void BuildReturn(int source_position = kNoSourcePosition);
|
|
void BuildAsyncReturn(int source_position = kNoSourcePosition);
|
|
void BuildAsyncGeneratorReturn();
|
|
void BuildReThrow();
|
|
void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op);
|
|
void BuildThrowIfHole(Variable* variable);
|
|
|
|
void BuildNewLocalActivationContext();
|
|
void BuildLocalActivationContextInitialization();
|
|
void BuildNewLocalBlockContext(Scope* scope);
|
|
void BuildNewLocalCatchContext(Scope* scope);
|
|
void BuildNewLocalWithContext(Scope* scope);
|
|
|
|
void BuildGeneratorPrologue();
|
|
void BuildSuspendPoint(int position);
|
|
|
|
void BuildAwait(int position = kNoSourcePosition);
|
|
void BuildAwait(Expression* await_expr);
|
|
|
|
void BuildFinalizeIteration(IteratorRecord iterator, Register done,
|
|
Register iteration_continuation_token);
|
|
|
|
void BuildGetIterator(IteratorType hint);
|
|
|
|
// Create an IteratorRecord with pre-allocated registers holding the next
|
|
// method and iterator object.
|
|
IteratorRecord BuildGetIteratorRecord(Register iterator_next,
|
|
Register iterator_object,
|
|
IteratorType hint);
|
|
|
|
// Create an IteratorRecord allocating new registers to hold the next method
|
|
// and iterator object.
|
|
IteratorRecord BuildGetIteratorRecord(IteratorType hint);
|
|
void BuildIteratorNext(const IteratorRecord& iterator, Register next_result);
|
|
void BuildIteratorClose(const IteratorRecord& iterator,
|
|
Expression* expr = nullptr);
|
|
void BuildCallIteratorMethod(Register iterator, const AstRawString* method,
|
|
RegisterList receiver_and_args,
|
|
BytecodeLabel* if_called,
|
|
BytecodeLabels* if_notcalled);
|
|
|
|
void BuildFillArrayWithIterator(IteratorRecord iterator, Register array,
|
|
Register index, Register value,
|
|
FeedbackSlot next_value_slot,
|
|
FeedbackSlot next_done_slot,
|
|
FeedbackSlot index_slot,
|
|
FeedbackSlot element_slot);
|
|
// Create Array literals. |expr| can be nullptr, but if provided,
|
|
// a boilerplate will be used to create an initial array for elements
|
|
// before the first spread.
|
|
void BuildCreateArrayLiteral(const ZonePtrList<Expression>* elements,
|
|
ArrayLiteral* expr);
|
|
void BuildCreateObjectLiteral(Register literal, uint8_t flags, size_t entry);
|
|
void AllocateTopLevelRegisters();
|
|
void VisitArgumentsObject(Variable* variable);
|
|
void VisitRestArgumentsArray(Variable* rest);
|
|
void VisitCallSuper(Call* call);
|
|
void BuildInvalidPropertyAccess(MessageTemplate tmpl, Property* property);
|
|
void BuildPrivateBrandCheck(Property* property, Register object,
|
|
MessageTemplate tmpl);
|
|
void BuildPrivateGetterAccess(Register obj, Register access_pair);
|
|
void BuildPrivateSetterAccess(Register obj, Register access_pair,
|
|
Register value);
|
|
void BuildPrivateMethods(ClassLiteral* expr, bool is_static,
|
|
Register home_object);
|
|
void BuildClassLiteral(ClassLiteral* expr, Register name);
|
|
void VisitClassLiteral(ClassLiteral* expr, Register name);
|
|
void VisitNewTargetVariable(Variable* variable);
|
|
void VisitThisFunctionVariable(Variable* variable);
|
|
void BuildPrivateBrandInitialization(Register receiver);
|
|
void BuildInstanceMemberInitialization(Register constructor,
|
|
Register instance);
|
|
void BuildGeneratorObjectVariableInitialization();
|
|
void VisitBlockDeclarationsAndStatements(Block* stmt);
|
|
void VisitSetHomeObject(Register value, Register home_object,
|
|
LiteralProperty* property);
|
|
void VisitLiteralAccessor(Register home_object, LiteralProperty* property,
|
|
Register value_out);
|
|
void VisitForInAssignment(Expression* expr);
|
|
void VisitModuleNamespaceImports();
|
|
|
|
// Visit a logical OR/AND within a test context, rewiring the jumps based
|
|
// on the expression values.
|
|
void VisitLogicalTest(Token::Value token, Expression* left, Expression* right,
|
|
int right_coverage_slot);
|
|
void VisitNaryLogicalTest(Token::Value token, NaryOperation* expr,
|
|
const NaryCodeCoverageSlots* coverage_slots);
|
|
|
|
// Visit a (non-RHS) test for a logical op, which falls through if the test
|
|
// fails or jumps to the appropriate labels if it succeeds.
|
|
void VisitLogicalTestSubExpression(Token::Value token, Expression* expr,
|
|
BytecodeLabels* then_labels,
|
|
BytecodeLabels* else_labels,
|
|
int coverage_slot);
|
|
|
|
// Helpers for binary and nary logical op value expressions.
|
|
bool VisitLogicalOrSubExpression(Expression* expr, BytecodeLabels* end_labels,
|
|
int coverage_slot);
|
|
bool VisitLogicalAndSubExpression(Expression* expr,
|
|
BytecodeLabels* end_labels,
|
|
int coverage_slot);
|
|
|
|
// Helper for binary and nary nullish op value expressions.
|
|
bool VisitNullishSubExpression(Expression* expr, BytecodeLabels* end_labels,
|
|
int coverage_slot);
|
|
|
|
// Visit the body of a loop iteration.
|
|
void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop_builder);
|
|
|
|
// Visit a statement and switch scopes, the context is in the accumulator.
|
|
void VisitInScope(Statement* stmt, Scope* scope);
|
|
|
|
void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list);
|
|
|
|
void BuildLoadPropertyKey(LiteralProperty* property, Register out_reg);
|
|
|
|
int AllocateBlockCoverageSlotIfEnabled(AstNode* node, SourceRangeKind kind);
|
|
int AllocateNaryBlockCoverageSlotIfEnabled(NaryOperation* node, size_t index);
|
|
|
|
void BuildIncrementBlockCoverageCounterIfEnabled(AstNode* node,
|
|
SourceRangeKind kind);
|
|
void BuildIncrementBlockCoverageCounterIfEnabled(int coverage_array_slot);
|
|
|
|
void BuildTest(ToBooleanMode mode, BytecodeLabels* then_labels,
|
|
BytecodeLabels* else_labels, TestFallthrough fallthrough);
|
|
|
|
template <typename TryBodyFunc, typename CatchBodyFunc>
|
|
void BuildTryCatch(TryBodyFunc try_body_func, CatchBodyFunc catch_body_func,
|
|
HandlerTable::CatchPrediction catch_prediction,
|
|
TryCatchStatement* stmt_for_coverage = nullptr);
|
|
template <typename TryBodyFunc, typename FinallyBodyFunc>
|
|
void BuildTryFinally(TryBodyFunc try_body_func,
|
|
FinallyBodyFunc finally_body_func,
|
|
HandlerTable::CatchPrediction catch_prediction,
|
|
TryFinallyStatement* stmt_for_coverage = nullptr);
|
|
|
|
template <typename ExpressionFunc>
|
|
void BuildOptionalChain(ExpressionFunc expression_func);
|
|
|
|
// Visitors for obtaining expression result in the accumulator, in a
|
|
// register, or just getting the effect. Some visitors return a TypeHint which
|
|
// specifies the type of the result of the visited expression.
|
|
TypeHint VisitForAccumulatorValue(Expression* expr);
|
|
void VisitForAccumulatorValueOrTheHole(Expression* expr);
|
|
V8_WARN_UNUSED_RESULT Register VisitForRegisterValue(Expression* expr);
|
|
V8_INLINE void VisitForRegisterValue(Expression* expr, Register destination);
|
|
void VisitAndPushIntoRegisterList(Expression* expr, RegisterList* reg_list);
|
|
void VisitForEffect(Expression* expr);
|
|
void VisitForTest(Expression* expr, BytecodeLabels* then_labels,
|
|
BytecodeLabels* else_labels, TestFallthrough fallthrough);
|
|
void VisitForNullishTest(Expression* expr, BytecodeLabels* then_labels,
|
|
BytecodeLabels* test_next_labels,
|
|
BytecodeLabels* else_labels);
|
|
|
|
void VisitInSameTestExecutionScope(Expression* expr);
|
|
|
|
Register GetRegisterForLocalVariable(Variable* variable);
|
|
|
|
// Returns the runtime function id for a store to super for the function's
|
|
// language mode.
|
|
inline Runtime::FunctionId StoreToSuperRuntimeId();
|
|
inline Runtime::FunctionId StoreKeyedToSuperRuntimeId();
|
|
|
|
// Returns a cached slot, or create and cache a new slot if one doesn't
|
|
// already exists.
|
|
FeedbackSlot GetCachedLoadGlobalICSlot(TypeofMode typeof_mode,
|
|
Variable* variable);
|
|
FeedbackSlot GetCachedStoreGlobalICSlot(LanguageMode language_mode,
|
|
Variable* variable);
|
|
FeedbackSlot GetCachedLoadICSlot(const Expression* expr,
|
|
const AstRawString* name);
|
|
FeedbackSlot GetCachedStoreICSlot(const Expression* expr,
|
|
const AstRawString* name);
|
|
FeedbackSlot GetDummyCompareICSlot();
|
|
|
|
int GetCachedCreateClosureSlot(FunctionLiteral* literal);
|
|
|
|
void AddToEagerLiteralsIfEager(FunctionLiteral* literal);
|
|
|
|
// Checks if the visited expression is one shot, i.e executed only once. Any
|
|
// expression either in a top level code or an IIFE that is not within a loop
|
|
// is eligible for one shot optimizations.
|
|
inline bool ShouldOptimizeAsOneShot() const;
|
|
|
|
static constexpr ToBooleanMode ToBooleanModeFromTypeHint(TypeHint type_hint) {
|
|
return type_hint == TypeHint::kBoolean ? ToBooleanMode::kAlreadyBoolean
|
|
: ToBooleanMode::kConvertToBoolean;
|
|
}
|
|
|
|
inline Register generator_object() const;
|
|
|
|
inline BytecodeArrayBuilder* builder() { return &builder_; }
|
|
inline Zone* zone() const { return zone_; }
|
|
inline DeclarationScope* closure_scope() const { return closure_scope_; }
|
|
inline UnoptimizedCompilationInfo* info() const { return info_; }
|
|
inline const AstStringConstants* ast_string_constants() const {
|
|
return ast_string_constants_;
|
|
}
|
|
|
|
inline Scope* current_scope() const { return current_scope_; }
|
|
inline void set_current_scope(Scope* scope) { current_scope_ = scope; }
|
|
|
|
inline ControlScope* execution_control() const { return execution_control_; }
|
|
inline void set_execution_control(ControlScope* scope) {
|
|
execution_control_ = scope;
|
|
}
|
|
inline ContextScope* execution_context() const { return execution_context_; }
|
|
inline void set_execution_context(ContextScope* context) {
|
|
execution_context_ = context;
|
|
}
|
|
inline void set_execution_result(ExpressionResultScope* execution_result) {
|
|
execution_result_ = execution_result;
|
|
}
|
|
ExpressionResultScope* execution_result() const { return execution_result_; }
|
|
BytecodeRegisterAllocator* register_allocator() {
|
|
return builder()->register_allocator();
|
|
}
|
|
|
|
TopLevelDeclarationsBuilder* top_level_builder() {
|
|
DCHECK_NOT_NULL(top_level_builder_);
|
|
return top_level_builder_;
|
|
}
|
|
inline LanguageMode language_mode() const;
|
|
inline FunctionKind function_kind() const;
|
|
inline FeedbackVectorSpec* feedback_spec();
|
|
inline int feedback_index(FeedbackSlot slot) const;
|
|
|
|
inline FeedbackSlotCache* feedback_slot_cache() {
|
|
return feedback_slot_cache_;
|
|
}
|
|
|
|
inline HandlerTable::CatchPrediction catch_prediction() const {
|
|
return catch_prediction_;
|
|
}
|
|
inline void set_catch_prediction(HandlerTable::CatchPrediction value) {
|
|
catch_prediction_ = value;
|
|
}
|
|
|
|
LoopScope* current_loop_scope() const { return current_loop_scope_; }
|
|
void set_current_loop_scope(LoopScope* loop_scope) {
|
|
current_loop_scope_ = loop_scope;
|
|
}
|
|
|
|
Zone* zone_;
|
|
BytecodeArrayBuilder builder_;
|
|
UnoptimizedCompilationInfo* info_;
|
|
const AstStringConstants* ast_string_constants_;
|
|
DeclarationScope* closure_scope_;
|
|
Scope* current_scope_;
|
|
|
|
// External vector of literals to be eagerly compiled.
|
|
std::vector<FunctionLiteral*>* eager_inner_literals_;
|
|
|
|
FeedbackSlotCache* feedback_slot_cache_;
|
|
|
|
TopLevelDeclarationsBuilder* top_level_builder_;
|
|
BlockCoverageBuilder* block_coverage_builder_;
|
|
ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_;
|
|
ZoneVector<std::pair<NativeFunctionLiteral*, size_t>>
|
|
native_function_literals_;
|
|
ZoneVector<std::pair<ObjectLiteral*, size_t>> object_literals_;
|
|
ZoneVector<std::pair<ArrayLiteral*, size_t>> array_literals_;
|
|
ZoneVector<std::pair<ClassLiteral*, size_t>> class_literals_;
|
|
ZoneVector<std::pair<GetTemplateObject*, size_t>> template_objects_;
|
|
|
|
ControlScope* execution_control_;
|
|
ContextScope* execution_context_;
|
|
ExpressionResultScope* execution_result_;
|
|
|
|
Register incoming_new_target_or_generator_;
|
|
|
|
BytecodeLabels* optional_chaining_null_labels_;
|
|
|
|
// Dummy feedback slot for compare operations, where we don't care about
|
|
// feedback
|
|
SharedFeedbackSlot dummy_feedback_slot_;
|
|
|
|
BytecodeJumpTable* generator_jump_table_;
|
|
int suspend_count_;
|
|
// TODO(solanes): assess if we can move loop_depth_ into LoopScope.
|
|
int loop_depth_;
|
|
|
|
LoopScope* current_loop_scope_;
|
|
|
|
HandlerTable::CatchPrediction catch_prediction_;
|
|
};
|
|
|
|
} // namespace interpreter
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_INTERPRETER_BYTECODE_GENERATOR_H_
|