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_GENERATOR_H_ 6 #define V8_INTERPRETER_BYTECODE_GENERATOR_H_ 7 8 #include "src/ast/ast.h" 9 #include "src/interpreter/bytecode-array-builder.h" 10 #include "src/interpreter/bytecode-label.h" 11 #include "src/interpreter/bytecode-register.h" 12 #include "src/interpreter/bytecodes.h" 13 14 namespace v8 { 15 namespace internal { 16 17 class CompilationInfo; 18 19 namespace interpreter { 20 21 class GlobalDeclarationsBuilder; 22 class LoopBuilder; 23 24 class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { 25 public: 26 explicit BytecodeGenerator(CompilationInfo* info); 27 28 void GenerateBytecode(uintptr_t stack_limit); 29 Handle<BytecodeArray> FinalizeBytecode(Isolate* isolate); 30 31 #define DECLARE_VISIT(type) void Visit##type(type* node); 32 AST_NODE_LIST(DECLARE_VISIT) 33 #undef DECLARE_VISIT 34 35 // Visiting function for declarations list and statements are overridden. 36 void VisitDeclarations(Declaration::List* declarations); 37 void VisitStatements(ZoneList<Statement*>* statments); 38 39 private: 40 class ContextScope; 41 class ControlScope; 42 class ControlScopeForBreakable; 43 class ControlScopeForIteration; 44 class ControlScopeForTopLevel; 45 class ControlScopeForTryCatch; 46 class ControlScopeForTryFinally; 47 class CurrentScope; 48 class ExpressionResultScope; 49 class EffectResultScope; 50 class GlobalDeclarationsBuilder; 51 class RegisterAllocationScope; 52 class TestResultScope; 53 class ValueResultScope; 54 55 enum class TestFallthrough { kThen, kElse, kNone }; 56 57 void GenerateBytecodeBody(); 58 void AllocateDeferredConstants(Isolate* isolate); 59 60 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 61 62 // Dispatched from VisitBinaryOperation. 63 void VisitArithmeticExpression(BinaryOperation* binop); 64 void VisitCommaExpression(BinaryOperation* binop); 65 void VisitLogicalOrExpression(BinaryOperation* binop); 66 void VisitLogicalAndExpression(BinaryOperation* binop); 67 68 // Dispatched from VisitUnaryOperation. 69 void VisitVoid(UnaryOperation* expr); 70 void VisitTypeOf(UnaryOperation* expr); 71 void VisitNot(UnaryOperation* expr); 72 void VisitDelete(UnaryOperation* expr); 73 74 // Used by flow control routines to evaluate loop condition. 75 void VisitCondition(Expression* expr); 76 77 // Visit the arguments expressions in |args| and store them in |args_regs|, 78 // growing |args_regs| for each argument visited. 79 void VisitArguments(ZoneList<Expression*>* args, RegisterList* arg_regs); 80 81 // Visit a keyed super property load. The optional 82 // |opt_receiver_out| register will have the receiver stored to it 83 // if it's a valid register. The loaded value is placed in the 84 // accumulator. 85 void VisitKeyedSuperPropertyLoad(Property* property, 86 Register opt_receiver_out); 87 88 // Visit a named super property load. The optional 89 // |opt_receiver_out| register will have the receiver stored to it 90 // if it's a valid register. The loaded value is placed in the 91 // accumulator. 92 void VisitNamedSuperPropertyLoad(Property* property, 93 Register opt_receiver_out); 94 95 void VisitPropertyLoad(Register obj, Property* expr); 96 void VisitPropertyLoadForRegister(Register obj, Property* expr, 97 Register destination); 98 99 void BuildVariableLoad(Variable* variable, FeedbackSlot slot, 100 HoleCheckMode hole_check_mode, 101 TypeofMode typeof_mode = NOT_INSIDE_TYPEOF); 102 void BuildVariableLoadForAccumulatorValue( 103 Variable* variable, FeedbackSlot slot, HoleCheckMode hole_check_mode, 104 TypeofMode typeof_mode = NOT_INSIDE_TYPEOF); 105 void BuildVariableAssignment(Variable* variable, Token::Value op, 106 FeedbackSlot slot, 107 HoleCheckMode hole_check_mode); 108 109 void BuildReturn(); 110 void BuildAsyncReturn(); 111 void BuildReThrow(); 112 void BuildAbort(BailoutReason bailout_reason); 113 void BuildThrowIfHole(const AstRawString* name); 114 void BuildThrowReferenceError(const AstRawString* name); 115 void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op); 116 117 // Build jump to targets[value], where 118 // start_index <= value < start_index + size. 119 void BuildIndexedJump(Register value, size_t start_index, size_t size, 120 ZoneVector<BytecodeLabel>& targets); 121 122 void BuildNewLocalActivationContext(); 123 void BuildLocalActivationContextInitialization(); 124 void BuildNewLocalBlockContext(Scope* scope); 125 void BuildNewLocalCatchContext(Variable* variable, Scope* scope); 126 void BuildNewLocalWithContext(Scope* scope); 127 128 void VisitGeneratorPrologue(); 129 130 void VisitArgumentsObject(Variable* variable); 131 void VisitRestArgumentsArray(Variable* rest); 132 void VisitCallSuper(Call* call); 133 void VisitClassLiteralProperties(ClassLiteral* expr, Register constructor, 134 Register prototype); 135 void BuildClassLiteralNameProperty(ClassLiteral* expr, Register constructor); 136 void VisitThisFunctionVariable(Variable* variable); 137 void VisitNewTargetVariable(Variable* variable); 138 void VisitBlockDeclarationsAndStatements(Block* stmt); 139 void VisitFunctionClosureForContext(); 140 void VisitSetHomeObject(Register value, Register home_object, 141 LiteralProperty* property, int slot_number = 0); 142 void VisitObjectLiteralAccessor(Register home_object, 143 ObjectLiteralProperty* property, 144 Register value_out); 145 void VisitForInAssignment(Expression* expr, FeedbackSlot slot); 146 void VisitModuleNamespaceImports(); 147 148 // Visit the header/body of a loop iteration. 149 void VisitIterationHeader(IterationStatement* stmt, 150 LoopBuilder* loop_builder); 151 void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop_builder); 152 153 // Visit a statement and switch scopes, the context is in the accumulator. 154 void VisitInScope(Statement* stmt, Scope* scope); 155 156 void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list); 157 158 // Visitors for obtaining expression result in the accumulator, in a 159 // register, or just getting the effect. 160 void VisitForAccumulatorValue(Expression* expr); 161 void VisitForAccumulatorValueOrTheHole(Expression* expr); 162 MUST_USE_RESULT Register VisitForRegisterValue(Expression* expr); 163 void VisitForRegisterValue(Expression* expr, Register destination); 164 void VisitAndPushIntoRegisterList(Expression* expr, RegisterList* reg_list); 165 void VisitForEffect(Expression* expr); 166 void VisitForTest(Expression* expr, BytecodeLabels* then_labels, 167 BytecodeLabels* else_labels, TestFallthrough fallthrough); 168 169 // Returns the runtime function id for a store to super for the function's 170 // language mode. 171 inline Runtime::FunctionId StoreToSuperRuntimeId(); 172 inline Runtime::FunctionId StoreKeyedToSuperRuntimeId(); 173 builder()174 inline BytecodeArrayBuilder* builder() const { return builder_; } zone()175 inline Zone* zone() const { return zone_; } closure_scope()176 inline DeclarationScope* closure_scope() const { return closure_scope_; } info()177 inline CompilationInfo* info() const { return info_; } 178 current_scope()179 inline Scope* current_scope() const { return current_scope_; } set_current_scope(Scope * scope)180 inline void set_current_scope(Scope* scope) { current_scope_ = scope; } 181 execution_control()182 inline ControlScope* execution_control() const { return execution_control_; } set_execution_control(ControlScope * scope)183 inline void set_execution_control(ControlScope* scope) { 184 execution_control_ = scope; 185 } execution_context()186 inline ContextScope* execution_context() const { return execution_context_; } set_execution_context(ContextScope * context)187 inline void set_execution_context(ContextScope* context) { 188 execution_context_ = context; 189 } set_execution_result(ExpressionResultScope * execution_result)190 inline void set_execution_result(ExpressionResultScope* execution_result) { 191 execution_result_ = execution_result; 192 } execution_result()193 ExpressionResultScope* execution_result() const { return execution_result_; } register_allocator()194 BytecodeRegisterAllocator* register_allocator() const { 195 return builder()->register_allocator(); 196 } 197 globals_builder()198 GlobalDeclarationsBuilder* globals_builder() { 199 DCHECK_NOT_NULL(globals_builder_); 200 return globals_builder_; 201 } 202 inline LanguageMode language_mode() const; 203 int feedback_index(FeedbackSlot slot) const; 204 prototype_string()205 const AstRawString* prototype_string() const { return prototype_string_; } undefined_string()206 const AstRawString* undefined_string() const { return undefined_string_; } 207 208 Zone* zone_; 209 BytecodeArrayBuilder* builder_; 210 CompilationInfo* info_; 211 DeclarationScope* closure_scope_; 212 Scope* current_scope_; 213 214 GlobalDeclarationsBuilder* globals_builder_; 215 ZoneVector<GlobalDeclarationsBuilder*> global_declarations_; 216 ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_; 217 ZoneVector<std::pair<NativeFunctionLiteral*, size_t>> 218 native_function_literals_; 219 ZoneVector<std::pair<ObjectLiteral*, size_t>> object_literals_; 220 ZoneVector<std::pair<ArrayLiteral*, size_t>> array_literals_; 221 222 ControlScope* execution_control_; 223 ContextScope* execution_context_; 224 ExpressionResultScope* execution_result_; 225 226 ZoneVector<BytecodeLabel> generator_resume_points_; 227 Register generator_state_; 228 int loop_depth_; 229 230 const AstRawString* prototype_string_; 231 const AstRawString* undefined_string_; 232 }; 233 234 } // namespace interpreter 235 } // namespace internal 236 } // namespace v8 237 238 #endif // V8_INTERPRETER_BYTECODE_GENERATOR_H_ 239