5 #include "src/interpreter/bytecode-generator.h" 7 #include "src/api-inl.h" 8 #include "src/ast/ast-source-ranges.h" 9 #include "src/ast/scopes.h" 10 #include "src/builtins/builtins-constructor.h" 11 #include "src/code-stubs.h" 12 #include "src/compiler.h" 13 #include "src/interpreter/bytecode-flags.h" 14 #include "src/interpreter/bytecode-jump-table.h" 15 #include "src/interpreter/bytecode-label.h" 16 #include "src/interpreter/bytecode-register-allocator.h" 17 #include "src/interpreter/control-flow-builders.h" 18 #include "src/objects-inl.h" 19 #include "src/objects/debug-objects.h" 20 #include "src/objects/literal-objects-inl.h" 21 #include "src/objects/smi.h" 22 #include "src/parsing/parse-info.h" 23 #include "src/parsing/token.h" 24 #include "src/unoptimized-compilation-info.h" 28 namespace interpreter {
36 : generator_(generator),
38 outer_(generator_->execution_context()),
39 register_(Register::current_context()),
41 DCHECK(scope->NeedsContext() || outer_ ==
nullptr);
43 depth_ = outer_->depth_ + 1;
47 generator_->register_allocator()->NewRegister();
48 outer_->set_register(outer_context_reg);
49 generator_->builder()->PushContext(outer_context_reg);
51 generator_->set_execution_context(
this);
56 DCHECK_EQ(register_.index(), Register::current_context().index());
57 generator_->builder()->PopContext(outer_->reg());
58 outer_->set_register(register_);
60 generator_->set_execution_context(outer_);
64 int ContextChainDepth(
Scope* scope) {
65 return scope_->ContextChainLength(scope);
76 for (
int i = depth;
i > 0; --
i) {
77 previous = previous->outer_;
82 Register reg()
const {
return register_; }
87 void set_register(
Register reg) { register_ = reg; }
101 : generator_(generator), outer_(generator->execution_control()),
102 context_(generator->execution_context()) {
103 generator_->set_execution_control(
this);
105 virtual ~
ControlScope() { generator_->set_execution_control(outer()); }
108 PerformCommand(CMD_BREAK, stmt, kNoSourcePosition);
111 PerformCommand(CMD_CONTINUE, stmt, kNoSourcePosition);
113 void ReturnAccumulator(
int source_position = kNoSourcePosition) {
114 PerformCommand(CMD_RETURN,
nullptr, source_position);
116 void AsyncReturnAccumulator(
int source_position = kNoSourcePosition) {
117 PerformCommand(CMD_ASYNC_RETURN,
nullptr, source_position);
130 static constexpr
bool CommandUsesAccumulator(Command command) {
131 return command != CMD_BREAK && command != CMD_CONTINUE;
134 void PerformCommand(Command command,
Statement* statement,
135 int source_position);
136 virtual bool Execute(Command command,
Statement* statement,
137 int source_position) = 0;
142 void PopContextToExpectedDepth();
164 : generator_(generator),
165 deferred_(generator->zone()),
166 token_register_(token_register),
167 result_register_(result_register),
169 async_return_token_(-1),
170 rethrow_token_(-1) {}
182 void RecordCommand(Command command,
Statement* statement) {
183 int token = GetTokenForCommand(command, statement);
185 DCHECK_LT(token, deferred_.size());
186 DCHECK_EQ(deferred_[token].command, command);
187 DCHECK_EQ(deferred_[token].statement, statement);
188 DCHECK_EQ(deferred_[token].token, token);
190 if (CommandUsesAccumulator(command)) {
191 builder()->StoreAccumulatorInRegister(result_register_);
193 builder()->LoadLiteral(Smi::FromInt(token));
194 builder()->StoreAccumulatorInRegister(token_register_);
195 if (!CommandUsesAccumulator(command)) {
200 builder()->StoreAccumulatorInRegister(result_register_);
207 void RecordHandlerReThrowPath() {
209 RecordCommand(CMD_RETHROW,
nullptr);
214 void RecordFallThroughPath() {
215 builder()->LoadLiteral(Smi::FromInt(-1));
216 builder()->StoreAccumulatorInRegister(token_register_);
221 builder()->StoreAccumulatorInRegister(result_register_);
226 void ApplyDeferredCommands() {
227 if (deferred_.size() == 0)
return;
229 BytecodeLabel fall_through;
231 if (deferred_.size() == 1) {
234 const Entry& entry = deferred_[0];
237 ->LoadLiteral(Smi::FromInt(entry.token))
238 .CompareReference(token_register_)
239 .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &fall_through);
241 if (CommandUsesAccumulator(entry.command)) {
242 builder()->LoadAccumulatorWithRegister(result_register_);
244 execution_control()->PerformCommand(entry.command, entry.statement,
250 BytecodeJumpTable* jump_table =
251 builder()->AllocateJumpTable(static_cast<int>(deferred_.size()), 0);
253 ->LoadAccumulatorWithRegister(token_register_)
254 .SwitchOnSmiNoFeedback(jump_table)
255 .Jump(&fall_through);
256 for (
const Entry& entry : deferred_) {
257 builder()->Bind(jump_table, entry.token);
259 if (CommandUsesAccumulator(entry.command)) {
260 builder()->LoadAccumulatorWithRegister(result_register_);
262 execution_control()->PerformCommand(entry.command, entry.statement,
267 builder()->Bind(&fall_through);
270 BytecodeArrayBuilder* builder() {
return generator_->builder(); }
271 ControlScope* execution_control() {
return generator_->execution_control(); }
274 int GetTokenForCommand(Command command, Statement* statement) {
277 return GetReturnToken();
278 case CMD_ASYNC_RETURN:
279 return GetAsyncReturnToken();
281 return GetRethrowToken();
285 return GetNewTokenForCommand(command, statement);
289 int GetReturnToken() {
290 if (return_token_ == -1) {
291 return_token_ = GetNewTokenForCommand(CMD_RETURN,
nullptr);
293 return return_token_;
296 int GetAsyncReturnToken() {
297 if (async_return_token_ == -1) {
298 async_return_token_ = GetNewTokenForCommand(CMD_ASYNC_RETURN,
nullptr);
300 return async_return_token_;
303 int GetRethrowToken() {
304 if (rethrow_token_ == -1) {
305 rethrow_token_ = GetNewTokenForCommand(CMD_RETHROW,
nullptr);
307 return rethrow_token_;
310 int GetNewTokenForCommand(Command command, Statement* statement) {
311 int token =
static_cast<int>(deferred_.size());
312 deferred_.push_back({command, statement, token});
316 BytecodeGenerator* generator_;
317 ZoneVector<Entry> deferred_;
318 Register token_register_;
319 Register result_register_;
323 int async_return_token_;
335 bool Execute(Command command,
Statement* statement,
336 int source_position)
override {
343 generator()->BuildReturn(source_position);
345 case CMD_ASYNC_RETURN:
347 generator()->BuildAsyncReturn(source_position);
351 generator()->BuildReThrow();
366 statement_(statement),
367 control_builder_(control_builder) {}
370 bool Execute(Command command,
Statement* statement,
371 int source_position)
override {
372 control_builder_->set_needs_continuation_counter();
373 if (statement != statement_)
return false;
376 PopContextToExpectedDepth();
377 control_builder_->Break();
381 case CMD_ASYNC_RETURN:
402 statement_(statement),
403 loop_builder_(loop_builder) {
404 generator->loop_depth_++;
409 bool Execute(Command command,
Statement* statement,
410 int source_position)
override {
411 if (statement != statement_)
return false;
414 PopContextToExpectedDepth();
415 loop_builder_->Break();
418 PopContextToExpectedDepth();
419 loop_builder_->Continue();
422 case CMD_ASYNC_RETURN:
443 bool Execute(Command command,
Statement* statement,
444 int source_position)
override {
449 case CMD_ASYNC_RETURN:
454 generator()->BuildReThrow();
469 try_finally_builder_(try_finally_builder),
470 commands_(commands) {}
473 bool Execute(Command command,
Statement* statement,
474 int source_position)
override {
479 case CMD_ASYNC_RETURN:
481 PopContextToExpectedDepth();
487 commands_->RecordCommand(command, statement);
488 try_finally_builder_->LeaveTry();
503 : generator_(generator) {
504 if (generator_->block_coverage_builder_ ==
nullptr)
return;
505 for (
size_t i = 0;
i < expr->subsequent_length();
i++) {
506 coverage_slots_.push_back(
507 generator_->AllocateNaryBlockCoverageSlotIfEnabled(expr,
i));
511 int GetSlotFor(
size_t subsequent_expr_index)
const {
512 if (generator_->block_coverage_builder_ ==
nullptr) {
513 return BlockCoverageBuilder::kNoCoverageArraySlot;
515 DCHECK(coverage_slots_.size() > subsequent_expr_index);
516 return coverage_slots_[subsequent_expr_index];
521 std::vector<int> coverage_slots_;
524 void BytecodeGenerator::ControlScope::PerformCommand(Command command,
526 int source_position) {
529 if (current->Execute(command, statement, source_position)) {
532 current = current->outer();
533 }
while (current !=
nullptr);
537 void BytecodeGenerator::ControlScope::PopContextToExpectedDepth() {
540 if (generator()->execution_context() != context()) {
541 generator()->builder()->PopContext(context()->reg());
548 : generator_(generator),
549 outer_next_register_index_(
550 generator->register_allocator()->next_register_index()) {}
553 generator_->register_allocator()->ReleaseRegisters(
554 outer_next_register_index_);
559 int outer_next_register_index_;
569 : generator_(generator),
570 outer_(generator->execution_result()),
571 allocator_(generator),
573 type_hint_(TypeHint::kAny) {
574 generator_->set_execution_result(
this);
578 generator_->set_execution_result(outer_);
581 bool IsEffect()
const {
return kind_ == Expression::kEffect; }
582 bool IsValue()
const {
return kind_ == Expression::kValue; }
583 bool IsTest()
const {
return kind_ == Expression::kTest; }
591 void SetResultIsBoolean() {
592 DCHECK_EQ(type_hint_, TypeHint::kAny);
593 type_hint_ = TypeHint::kBoolean;
596 void SetResultIsString() {
597 DCHECK_EQ(type_hint_, TypeHint::kAny);
598 type_hint_ = TypeHint::kString;
601 TypeHint type_hint()
const {
return type_hint_; }
607 Expression::Context kind_;
637 result_consumed_by_test_(
false),
638 fallthrough_(fallthrough),
639 then_labels_(then_labels),
640 else_labels_(else_labels) {}
644 void SetResultConsumedByTest() {
645 result_consumed_by_test_ =
true;
647 bool result_consumed_by_test() {
return result_consumed_by_test_; }
651 void InvertControlFlow() {
652 std::swap(then_labels_, else_labels_);
653 fallthrough_ = inverted_fallthrough();
656 BytecodeLabel* NewThenLabel() {
return then_labels_->New(); }
657 BytecodeLabel* NewElseLabel() {
return else_labels_->New(); }
663 then_labels_ = then_labels;
666 else_labels_ = else_labels;
669 TestFallthrough fallthrough()
const {
return fallthrough_; }
670 TestFallthrough inverted_fallthrough()
const {
671 switch (fallthrough_) {
672 case TestFallthrough::kThen:
673 return TestFallthrough::kElse;
674 case TestFallthrough::kElse:
675 return TestFallthrough::kThen;
677 return TestFallthrough::kNone;
680 void set_fallthrough(TestFallthrough fallthrough) {
681 fallthrough_ = fallthrough;
685 bool result_consumed_by_test_;
686 TestFallthrough fallthrough_;
697 : declarations_(0, zone),
698 constant_pool_entry_(0),
699 has_constant_pool_entry_(
false) {}
704 DCHECK(!slot.IsInvalid());
705 declarations_.push_back(Declaration(name, slot, literal_slot, func));
709 DCHECK(!slot.IsInvalid());
710 declarations_.push_back(Declaration(name, slot,
nullptr));
716 DCHECK(has_constant_pool_entry_);
719 static_cast<int>(declarations_.size() * 4), TENURED);
720 for (
const Declaration& declaration : declarations_) {
723 if (func ==
nullptr) {
724 initial_value = isolate->factory()->undefined_value();
726 initial_value = Compiler::GetSharedFunctionInfo(func, script, isolate);
733 data->set(array_index++, *declaration.name->string());
734 data->set(array_index++, Smi::FromInt(declaration.slot.ToInt()));
735 Object* undefined_or_literal_slot;
736 if (declaration.literal_slot.IsInvalid()) {
737 undefined_or_literal_slot =
ReadOnlyRoots(isolate).undefined_value();
739 undefined_or_literal_slot =
740 Smi::FromInt(declaration.literal_slot.ToInt());
742 data->set(array_index++, undefined_or_literal_slot);
743 data->set(array_index++, *initial_value);
748 size_t constant_pool_entry() {
749 DCHECK(has_constant_pool_entry_);
750 return constant_pool_entry_;
753 void set_constant_pool_entry(
size_t constant_pool_entry) {
755 DCHECK(!has_constant_pool_entry_);
756 constant_pool_entry_ = constant_pool_entry;
757 has_constant_pool_entry_ =
true;
760 bool empty() {
return declarations_.empty(); }
764 Declaration() : slot(FeedbackSlot::Invalid()), func(
nullptr) {}
767 : name(name), slot(slot), literal_slot(literal_slot), func(func) {}
772 literal_slot(FeedbackSlot::Invalid()),
781 size_t constant_pool_entry_;
782 bool has_constant_pool_entry_;
788 : generator_(generator), outer_scope_(generator->current_scope()) {
789 if (scope !=
nullptr) {
790 DCHECK_EQ(outer_scope_, scope->outer_scope());
791 generator_->set_current_scope(scope);
795 if (outer_scope_ != generator_->current_scope()) {
796 generator_->set_current_scope(outer_scope_);
810 PutImpl(slot_kind, 0, variable, slot);
813 PutImpl(slot_kind, 0, node, slot);
815 void Put(FeedbackSlotKind slot_kind,
int variable_index,
817 PutImpl(slot_kind, variable_index, name, slot);
821 return GetImpl(slot_kind, 0, variable);
824 return GetImpl(slot_kind, 0, node);
826 FeedbackSlot Get(FeedbackSlotKind slot_kind,
int variable_index,
828 return GetImpl(slot_kind, variable_index, name);
832 typedef std::tuple<FeedbackSlotKind, int, const void*> Key;
834 void PutImpl(FeedbackSlotKind slot_kind,
int index,
const void* node,
836 Key key = std::make_tuple(slot_kind, index, node);
837 auto entry = std::make_pair(key, slot);
841 FeedbackSlot GetImpl(FeedbackSlotKind slot_kind,
int index,
842 const void* node)
const {
843 Key key = std::make_tuple(slot_kind, index, node);
844 auto iter = map_.find(key);
845 if (iter != map_.end()) {
857 IteratorType
type = IteratorType::kNormal)
858 : type_(
type), object_(object_register), next_(next_register) {
859 DCHECK(object_.is_valid() && next_.is_valid());
862 inline IteratorType
type()
const {
return type_; }
863 inline Register object()
const {
return object_; }
864 inline Register next()
const {
return next_; }
874 static bool IsInEagerLiterals(
876 const std::vector<FunctionLiteral*>& eager_literals) {
878 if (literal == eager_literal)
return true;
885 BytecodeGenerator::BytecodeGenerator(
888 std::vector<FunctionLiteral*>* eager_inner_literals)
889 : zone_(info->zone()),
890 builder_(zone(), info->num_parameters_including_this(),
891 info->scope()->num_stack_slots(), info->feedback_vector_spec(),
892 info->SourcePositionRecordingMode()),
894 ast_string_constants_(ast_string_constants),
895 closure_scope_(info->scope()),
896 current_scope_(info->scope()),
897 eager_inner_literals_(eager_inner_literals),
898 feedback_slot_cache_(new (zone()) FeedbackSlotCache(zone())),
899 globals_builder_(new (zone()) GlobalDeclarationsBuilder(zone())),
900 block_coverage_builder_(nullptr),
901 global_declarations_(0, zone()),
902 function_literals_(0, zone()),
903 native_function_literals_(0, zone()),
904 object_literals_(0, zone()),
905 array_literals_(0, zone()),
906 class_literals_(0, zone()),
907 template_objects_(0, zone()),
908 execution_control_(nullptr),
909 execution_context_(nullptr),
910 execution_result_(nullptr),
911 incoming_new_target_or_generator_(),
912 dummy_feedback_slot_(feedback_spec(), FeedbackSlotKind::kCompareOp),
913 generator_jump_table_(nullptr),
917 DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope());
918 if (info->has_source_range_map()) {
919 block_coverage_builder_ =
new (zone())
920 BlockCoverageBuilder(zone(), builder(), info->source_range_map());
924 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
925 Isolate* isolate, Handle<Script> script) {
926 DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
930 SaveContext save(isolate);
931 isolate->set_context(Context());
934 AllocateDeferredConstants(isolate, script);
936 if (block_coverage_builder_) {
937 info()->set_coverage_info(
938 isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots()));
939 if (FLAG_trace_block_coverage) {
940 info()->coverage_info()->Print(info()->literal()->GetDebugName());
944 if (HasStackOverflow())
return Handle<BytecodeArray>();
945 Handle<BytecodeArray> bytecode_array = builder()->ToBytecodeArray(isolate);
947 if (incoming_new_target_or_generator_.is_valid()) {
948 bytecode_array->set_incoming_new_target_or_generator_register(
949 incoming_new_target_or_generator_);
952 return bytecode_array;
955 void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
956 Handle<Script> script) {
958 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
959 Handle<FixedArray> declarations =
960 globals_builder->AllocateDeclarations(info(), script, isolate);
961 if (declarations.is_null())
return SetStackOverflow();
962 builder()->SetDeferredConstantPoolEntry(
963 globals_builder->constant_pool_entry(), declarations);
967 for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) {
968 FunctionLiteral* expr = literal.first;
969 Handle<SharedFunctionInfo> shared_info =
970 Compiler::GetSharedFunctionInfo(expr, script, isolate);
971 if (shared_info.is_null())
return SetStackOverflow();
972 builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
976 for (std::pair<NativeFunctionLiteral*, size_t> literal :
977 native_function_literals_) {
978 NativeFunctionLiteral* expr = literal.first;
979 v8::Isolate* v8_isolate =
reinterpret_cast<v8::Isolate*
>(isolate);
983 expr->extension()->GetNativeFunctionTemplate(
984 v8_isolate, Utils::ToLocal(expr->name()));
987 Handle<SharedFunctionInfo> shared_info =
988 FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
989 isolate, Utils::OpenHandle(*info), expr->name());
990 DCHECK(!shared_info.is_null());
991 builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
995 for (std::pair<ObjectLiteral*, size_t> literal : object_literals_) {
996 ObjectLiteral* object_literal = literal.first;
997 if (object_literal->properties_count() > 0) {
1000 Handle<ObjectBoilerplateDescription> constant_properties =
1001 object_literal->GetOrBuildBoilerplateDescription(isolate);
1003 builder()->SetDeferredConstantPoolEntry(literal.second,
1004 constant_properties);
1009 for (std::pair<ArrayLiteral*, size_t> literal : array_literals_) {
1010 ArrayLiteral* array_literal = literal.first;
1011 Handle<ArrayBoilerplateDescription> constant_elements =
1012 array_literal->GetOrBuildBoilerplateDescription(isolate);
1013 builder()->SetDeferredConstantPoolEntry(literal.second, constant_elements);
1017 for (std::pair<ClassLiteral*, size_t> literal : class_literals_) {
1018 ClassLiteral* class_literal = literal.first;
1019 Handle<ClassBoilerplate> class_boilerplate =
1020 ClassBoilerplate::BuildClassBoilerplate(isolate, class_literal);
1021 builder()->SetDeferredConstantPoolEntry(literal.second, class_boilerplate);
1025 for (std::pair<GetTemplateObject*, size_t> literal : template_objects_) {
1026 GetTemplateObject* get_template_object = literal.first;
1027 Handle<TemplateObjectDescription> description =
1028 get_template_object->GetOrBuildDescription(isolate);
1029 builder()->SetDeferredConstantPoolEntry(literal.second, description);
1033 void BytecodeGenerator::GenerateBytecode(
uintptr_t stack_limit) {
1034 DisallowHeapAllocation no_allocation;
1035 DisallowHandleAllocation no_handles;
1036 DisallowHandleDereference no_deref;
1038 InitializeAstVisitor(stack_limit);
1041 ContextScope incoming_context(
this, closure_scope());
1044 ControlScopeForTopLevel control(
this);
1046 RegisterAllocationScope register_scope(
this);
1048 AllocateTopLevelRegisters();
1050 if (info()->literal()->CanSuspend()) {
1051 BuildGeneratorPrologue();
1054 if (closure_scope()->NeedsContext()) {
1056 BuildNewLocalActivationContext();
1057 ContextScope local_function_context(
this, closure_scope());
1058 BuildLocalActivationContextInitialization();
1059 GenerateBytecodeBody();
1061 GenerateBytecodeBody();
1065 DCHECK(!builder()->RequiresImplicitReturn());
1068 void BytecodeGenerator::GenerateBytecodeBody() {
1070 VisitArgumentsObject(closure_scope()->arguments());
1073 Variable* rest_parameter = closure_scope()->rest_parameter();
1074 VisitRestArgumentsArray(rest_parameter);
1078 VisitThisFunctionVariable(closure_scope()->function_var());
1079 VisitThisFunctionVariable(closure_scope()->this_function_var());
1082 VisitNewTargetVariable(closure_scope()->new_target_var());
1086 if (IsResumableFunction(info()->literal()->kind())) {
1087 BuildGeneratorObjectVariableInitialization();
1091 if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
1094 if (info()->collect_type_profile()) {
1095 feedback_spec()->AddTypeProfileSlot();
1096 int num_parameters = closure_scope()->num_parameters();
1097 for (
int i = 0;
i < num_parameters;
i++) {
1098 Register parameter(builder()->Parameter(
i));
1099 builder()->LoadAccumulatorWithRegister(parameter).CollectTypeProfile(
1100 closure_scope()->parameter(
i)->initializer_position());
1105 VisitDeclarations(closure_scope()->declarations());
1108 VisitModuleNamespaceImports();
1111 builder()->StackCheck(info()->literal()->start_position());
1114 if (IsBaseConstructor(function_kind()) &&
1115 info()->literal()->requires_instance_members_initializer()) {
1116 BuildInstanceMemberInitialization(Register::function_closure(),
1117 builder()->Receiver());
1121 VisitStatements(info()->literal()->body());
1125 if (builder()->RequiresImplicitReturn()) {
1126 builder()->LoadUndefined();
1131 void BytecodeGenerator::AllocateTopLevelRegisters() {
1132 if (IsResumableFunction(info()->literal()->kind())) {
1135 Variable* generator_object_var = closure_scope()->generator_object_var();
1136 if (generator_object_var->location() == VariableLocation::LOCAL) {
1137 incoming_new_target_or_generator_ =
1138 GetRegisterForLocalVariable(generator_object_var);
1140 incoming_new_target_or_generator_ = register_allocator()->NewRegister();
1142 }
else if (closure_scope()->new_target_var()) {
1145 Variable* new_target_var = closure_scope()->new_target_var();
1146 if (new_target_var->location() == VariableLocation::LOCAL) {
1147 incoming_new_target_or_generator_ =
1148 GetRegisterForLocalVariable(new_target_var);
1150 incoming_new_target_or_generator_ = register_allocator()->NewRegister();
1155 void BytecodeGenerator::BuildGeneratorPrologue() {
1156 DCHECK_GT(info()->literal()->suspend_count(), 0);
1157 DCHECK(generator_object().is_valid());
1158 generator_jump_table_ =
1159 builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0);
1163 builder()->SwitchOnGeneratorState(generator_object(), generator_jump_table_);
1170 void BytecodeGenerator::VisitBlock(Block* stmt) {
1172 CurrentScope current_scope(
this, stmt->scope());
1173 if (stmt->scope() !=
nullptr && stmt->scope()->NeedsContext()) {
1174 BuildNewLocalBlockContext(stmt->scope());
1175 ContextScope scope(
this, stmt->scope());
1176 VisitBlockDeclarationsAndStatements(stmt);
1178 VisitBlockDeclarationsAndStatements(stmt);
1182 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
1183 BlockBuilder block_builder(builder(), block_coverage_builder_, stmt);
1184 ControlScopeForBreakable execution_control(
this, stmt, &block_builder);
1185 if (stmt->scope() !=
nullptr) {
1186 VisitDeclarations(stmt->scope()->declarations());
1188 VisitStatements(stmt->statements());
1191 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
1192 Variable* variable = decl->proxy()->var();
1193 switch (variable->location()) {
1194 case VariableLocation::UNALLOCATED: {
1195 DCHECK(!variable->binding_needs_init());
1197 GetCachedLoadGlobalICSlot(NOT_INSIDE_TYPEOF, variable);
1198 globals_builder()->AddUndefinedDeclaration(variable->raw_name(), slot);
1201 case VariableLocation::LOCAL:
1202 if (variable->binding_needs_init()) {
1203 Register destination(builder()->Local(variable->index()));
1204 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
1207 case VariableLocation::PARAMETER:
1208 if (variable->binding_needs_init()) {
1209 Register destination(builder()->Parameter(variable->index()));
1210 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
1213 case VariableLocation::CONTEXT:
1214 if (variable->binding_needs_init()) {
1215 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
1216 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
1217 variable->index(), 0);
1220 case VariableLocation::LOOKUP: {
1221 DCHECK_EQ(VariableMode::kVar, variable->mode());
1222 DCHECK(!variable->binding_needs_init());
1224 Register name = register_allocator()->NewRegister();
1227 ->LoadLiteral(variable->raw_name())
1228 .StoreAccumulatorInRegister(name)
1229 .CallRuntime(Runtime::kDeclareEvalVar, name);
1232 case VariableLocation::MODULE:
1233 if (variable->IsExport() && variable->binding_needs_init()) {
1234 builder()->LoadTheHole();
1235 BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
1242 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1243 Variable* variable = decl->proxy()->var();
1244 DCHECK(variable->mode() == VariableMode::kLet ||
1245 variable->mode() == VariableMode::kVar);
1246 switch (variable->location()) {
1247 case VariableLocation::UNALLOCATED: {
1249 GetCachedLoadGlobalICSlot(NOT_INSIDE_TYPEOF, variable);
1250 FeedbackSlot literal_slot = GetCachedCreateClosureSlot(decl->fun());
1251 globals_builder()->AddFunctionDeclaration(variable->raw_name(), slot,
1252 literal_slot, decl->fun());
1253 AddToEagerLiteralsIfEager(decl->fun());
1256 case VariableLocation::PARAMETER:
1257 case VariableLocation::LOCAL: {
1258 VisitForAccumulatorValue(decl->fun());
1259 BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
1262 case VariableLocation::CONTEXT: {
1263 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
1264 VisitForAccumulatorValue(decl->fun());
1265 builder()->StoreContextSlot(execution_context()->reg(), variable->index(),
1269 case VariableLocation::LOOKUP: {
1270 RegisterList args = register_allocator()->NewRegisterList(2);
1272 ->LoadLiteral(variable->raw_name())
1273 .StoreAccumulatorInRegister(args[0]);
1274 VisitForAccumulatorValue(decl->fun());
1275 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime(
1276 Runtime::kDeclareEvalFunction, args);
1279 case VariableLocation::MODULE:
1280 DCHECK_EQ(variable->mode(), VariableMode::kLet);
1281 DCHECK(variable->IsExport());
1282 VisitForAccumulatorValue(decl->fun());
1283 BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
1286 DCHECK_IMPLIES(decl->fun()->ShouldEagerCompile(),
1287 IsInEagerLiterals(decl->fun(), *eager_inner_literals_));
1290 void BytecodeGenerator::VisitModuleNamespaceImports() {
1291 if (!closure_scope()->is_module_scope())
return;
1293 RegisterAllocationScope register_scope(
this);
1294 Register module_request = register_allocator()->NewRegister();
1296 ModuleDescriptor* descriptor = closure_scope()->AsModuleScope()->module();
1297 for (
auto entry : descriptor->namespace_imports()) {
1299 ->LoadLiteral(Smi::FromInt(entry->module_request))
1300 .StoreAccumulatorInRegister(module_request)
1301 .CallRuntime(Runtime::kGetModuleNamespace, module_request);
1302 Variable* var = closure_scope()->LookupInModule(entry->local_name);
1303 BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided);
1307 void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
1308 RegisterAllocationScope register_scope(
this);
1309 DCHECK(globals_builder()->empty());
1310 for (Declaration* decl : *declarations) {
1311 RegisterAllocationScope register_scope(
this);
1314 if (globals_builder()->empty())
return;
1316 globals_builder()->set_constant_pool_entry(
1317 builder()->AllocateDeferredConstantPoolEntry());
1318 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
1319 DeclareGlobalsNativeFlag::encode(info()->is_native());
1322 RegisterList args = register_allocator()->NewRegisterList(3);
1324 ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
1325 .StoreAccumulatorInRegister(args[0])
1326 .LoadLiteral(Smi::FromInt(encoded_flags))
1327 .StoreAccumulatorInRegister(args[1])
1328 .MoveRegister(Register::function_closure(), args[2])
1329 .CallRuntime(Runtime::kDeclareGlobals, args);
1332 global_declarations_.push_back(globals_builder());
1333 globals_builder_ =
new (zone()) GlobalDeclarationsBuilder(zone());
1336 void BytecodeGenerator::VisitStatements(
1337 const ZonePtrList<Statement>* statements) {
1338 for (
int i = 0;
i < statements->length();
i++) {
1340 RegisterAllocationScope allocation_scope(
this);
1341 Statement* stmt = statements->at(
i);
1343 if (builder()->RemainderOfBlockIsDead())
break;
1347 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
1348 builder()->SetStatementPosition(stmt);
1349 VisitForEffect(stmt->expression());
1352 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
1355 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
1356 ConditionalControlFlowBuilder conditional_builder(
1357 builder(), block_coverage_builder_, stmt);
1358 builder()->SetStatementPosition(stmt);
1360 if (stmt->condition()->ToBooleanIsTrue()) {
1362 conditional_builder.Then();
1363 Visit(stmt->then_statement());
1364 }
else if (stmt->condition()->ToBooleanIsFalse()) {
1366 if (stmt->HasElseStatement()) {
1367 conditional_builder.Else();
1368 Visit(stmt->else_statement());
1374 VisitForTest(stmt->condition(), conditional_builder.then_labels(),
1375 conditional_builder.else_labels(), TestFallthrough::kThen);
1377 conditional_builder.Then();
1378 Visit(stmt->then_statement());
1380 if (stmt->HasElseStatement()) {
1381 conditional_builder.JumpToEnd();
1382 conditional_builder.Else();
1383 Visit(stmt->else_statement());
1388 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
1389 SloppyBlockFunctionStatement* stmt) {
1390 Visit(stmt->statement());
1393 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
1394 AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
1395 builder()->SetStatementPosition(stmt);
1396 execution_control()->Continue(stmt->target());
1399 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
1400 AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
1401 builder()->SetStatementPosition(stmt);
1402 execution_control()->Break(stmt->target());
1405 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1406 AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
1407 builder()->SetStatementPosition(stmt);
1408 VisitForAccumulatorValue(stmt->expression());
1409 if (stmt->is_async_return()) {
1410 execution_control()->AsyncReturnAccumulator(stmt->end_position());
1412 execution_control()->ReturnAccumulator(stmt->end_position());
1416 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
1417 builder()->SetStatementPosition(stmt);
1418 VisitForAccumulatorValue(stmt->expression());
1419 BuildNewLocalWithContext(stmt->scope());
1420 VisitInScope(stmt->statement(), stmt->scope());
1423 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
1426 ZonePtrList<CaseClause>* clauses = stmt->cases();
1427 SwitchBuilder switch_builder(builder(), block_coverage_builder_, stmt,
1429 ControlScopeForBreakable scope(
this, stmt, &switch_builder);
1430 int default_index = -1;
1432 builder()->SetStatementPosition(stmt);
1435 Register tag = VisitForRegisterValue(stmt->tag());
1436 FeedbackSlot slot = clauses->length() > 0
1437 ? feedback_spec()->AddCompareICSlot()
1438 : FeedbackSlot::Invalid();
1441 for (
int i = 0;
i < clauses->length();
i++) {
1442 CaseClause* clause = clauses->at(
i);
1445 if (clause->is_default()) {
1451 VisitForAccumulatorValue(clause->label());
1452 builder()->CompareOperation(Token::Value::EQ_STRICT, tag,
1453 feedback_index(slot));
1454 switch_builder.Case(ToBooleanMode::kAlreadyBoolean,
i);
1457 if (default_index >= 0) {
1459 switch_builder.DefaultAt(default_index);
1463 switch_builder.Break();
1467 for (
int i = 0;
i < clauses->length();
i++) {
1468 CaseClause* clause = clauses->at(
i);
1469 switch_builder.SetCaseTarget(
i, clause);
1470 VisitStatements(clause->statements());
1474 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
1475 LoopBuilder* loop_builder) {
1476 loop_builder->LoopBody();
1477 ControlScopeForIteration execution_control(
this, stmt, loop_builder);
1478 builder()->StackCheck(stmt->position());
1479 Visit(stmt->body());
1480 loop_builder->BindContinueTarget();
1483 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1484 LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
1485 if (stmt->cond()->ToBooleanIsFalse()) {
1486 VisitIterationBody(stmt, &loop_builder);
1487 }
else if (stmt->cond()->ToBooleanIsTrue()) {
1488 loop_builder.LoopHeader();
1489 VisitIterationBody(stmt, &loop_builder);
1490 loop_builder.JumpToHeader(loop_depth_);
1492 loop_builder.LoopHeader();
1493 VisitIterationBody(stmt, &loop_builder);
1494 builder()->SetExpressionAsStatementPosition(stmt->cond());
1495 BytecodeLabels loop_backbranch(zone());
1496 VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(),
1497 TestFallthrough::kThen);
1498 loop_backbranch.Bind(builder());
1499 loop_builder.JumpToHeader(loop_depth_);
1503 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1504 LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
1506 if (stmt->cond()->ToBooleanIsFalse()) {
1511 loop_builder.LoopHeader();
1512 if (!stmt->cond()->ToBooleanIsTrue()) {
1513 builder()->SetExpressionAsStatementPosition(stmt->cond());
1514 BytecodeLabels loop_body(zone());
1515 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
1516 TestFallthrough::kThen);
1517 loop_body.Bind(builder());
1519 VisitIterationBody(stmt, &loop_builder);
1520 loop_builder.JumpToHeader(loop_depth_);
1523 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1524 LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
1526 if (stmt->init() !=
nullptr) {
1527 Visit(stmt->init());
1529 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1535 loop_builder.LoopHeader();
1536 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
1537 builder()->SetExpressionAsStatementPosition(stmt->cond());
1538 BytecodeLabels loop_body(zone());
1539 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
1540 TestFallthrough::kThen);
1541 loop_body.Bind(builder());
1543 VisitIterationBody(stmt, &loop_builder);
1544 if (stmt->next() !=
nullptr) {
1545 builder()->SetStatementPosition(stmt->next());
1546 Visit(stmt->next());
1548 loop_builder.JumpToHeader(loop_depth_);
1551 void BytecodeGenerator::VisitForInAssignment(Expression* expr) {
1552 DCHECK(expr->IsValidReferenceExpression());
1556 Property*
property = expr->AsProperty();
1557 LhsKind assign_type = Property::GetAssignType(property);
1558 switch (assign_type) {
1560 VariableProxy* proxy = expr->AsVariableProxy();
1561 BuildVariableAssignment(proxy->var(), Token::ASSIGN,
1562 proxy->hole_check_mode());
1565 case NAMED_PROPERTY: {
1566 RegisterAllocationScope register_scope(
this);
1567 Register value = register_allocator()->NewRegister();
1568 builder()->StoreAccumulatorInRegister(value);
1569 Register
object = VisitForRegisterValue(property->obj());
1570 const AstRawString* name =
1571 property->key()->AsLiteral()->AsRawPropertyName();
1572 builder()->LoadAccumulatorWithRegister(value);
1573 FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
1574 builder()->StoreNamedProperty(
object, name, feedback_index(slot),
1576 builder()->LoadAccumulatorWithRegister(value);
1579 case KEYED_PROPERTY: {
1580 RegisterAllocationScope register_scope(
this);
1581 Register value = register_allocator()->NewRegister();
1582 builder()->StoreAccumulatorInRegister(value);
1583 Register
object = VisitForRegisterValue(property->obj());
1584 Register key = VisitForRegisterValue(property->key());
1585 builder()->LoadAccumulatorWithRegister(value);
1586 FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
1587 builder()->StoreKeyedProperty(
object, key, feedback_index(slot),
1589 builder()->LoadAccumulatorWithRegister(value);
1592 case NAMED_SUPER_PROPERTY: {
1593 RegisterAllocationScope register_scope(
this);
1594 RegisterList args = register_allocator()->NewRegisterList(4);
1595 builder()->StoreAccumulatorInRegister(args[3]);
1596 SuperPropertyReference* super_property =
1597 property->obj()->AsSuperPropertyReference();
1598 VisitForRegisterValue(super_property->this_var(), args[0]);
1599 VisitForRegisterValue(super_property->home_object(), args[1]);
1601 ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
1602 .StoreAccumulatorInRegister(args[2])
1603 .CallRuntime(StoreToSuperRuntimeId(), args);
1606 case KEYED_SUPER_PROPERTY: {
1607 RegisterAllocationScope register_scope(
this);
1608 RegisterList args = register_allocator()->NewRegisterList(4);
1609 builder()->StoreAccumulatorInRegister(args[3]);
1610 SuperPropertyReference* super_property =
1611 property->obj()->AsSuperPropertyReference();
1612 VisitForRegisterValue(super_property->this_var(), args[0]);
1613 VisitForRegisterValue(super_property->home_object(), args[1]);
1614 VisitForRegisterValue(property->key(), args[2]);
1615 builder()->CallRuntime(StoreKeyedToSuperRuntimeId(), args);
1621 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1622 if (stmt->subject()->IsNullLiteral() ||
1623 stmt->subject()->IsUndefinedLiteral()) {
1628 BytecodeLabel subject_null_label, subject_undefined_label;
1629 FeedbackSlot slot = feedback_spec()->AddForInSlot();
1632 builder()->SetExpressionAsStatementPosition(stmt->subject());
1633 VisitForAccumulatorValue(stmt->subject());
1634 builder()->JumpIfUndefined(&subject_undefined_label);
1635 builder()->JumpIfNull(&subject_null_label);
1636 Register receiver = register_allocator()->NewRegister();
1637 builder()->ToObject(receiver);
1640 RegisterList triple = register_allocator()->NewRegisterList(3);
1641 Register cache_length = triple[2];
1642 builder()->ForInEnumerate(receiver);
1643 builder()->ForInPrepare(triple, feedback_index(slot));
1646 Register index = register_allocator()->NewRegister();
1647 builder()->LoadLiteral(Smi::zero());
1648 builder()->StoreAccumulatorInRegister(index);
1652 LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
1653 loop_builder.LoopHeader();
1654 builder()->SetExpressionAsStatementPosition(stmt->each());
1655 builder()->ForInContinue(index, cache_length);
1656 loop_builder.BreakIfFalse(ToBooleanMode::kAlreadyBoolean);
1657 builder()->ForInNext(receiver, index, triple.Truncate(2),
1658 feedback_index(slot));
1659 loop_builder.ContinueIfUndefined();
1660 VisitForInAssignment(stmt->each());
1661 VisitIterationBody(stmt, &loop_builder);
1662 builder()->ForInStep(index);
1663 builder()->StoreAccumulatorInRegister(index);
1664 loop_builder.JumpToHeader(loop_depth_);
1666 builder()->Bind(&subject_null_label);
1667 builder()->Bind(&subject_undefined_label);
1670 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1671 LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
1673 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator());
1674 VisitForEffect(stmt->assign_iterator());
1675 VisitForEffect(stmt->assign_next());
1677 loop_builder.LoopHeader();
1678 builder()->SetExpressionAsStatementPosition(stmt->next_result());
1679 VisitForEffect(stmt->next_result());
1680 TypeHint type_hint = VisitForAccumulatorValue(stmt->result_done());
1681 loop_builder.BreakIfTrue(ToBooleanModeFromTypeHint(type_hint));
1683 VisitForEffect(stmt->assign_each());
1684 VisitIterationBody(stmt, &loop_builder);
1685 loop_builder.JumpToHeader(loop_depth_);
1688 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1692 HandlerTable::CatchPrediction outer_catch_prediction = catch_prediction();
1693 set_catch_prediction(stmt->GetCatchPrediction(outer_catch_prediction));
1695 TryCatchBuilder try_control_builder(builder(), block_coverage_builder_, stmt,
1696 catch_prediction());
1701 Register context = register_allocator()->NewRegister();
1702 builder()->MoveRegister(Register::current_context(), context);
1706 try_control_builder.BeginTry(context);
1708 ControlScopeForTryCatch scope(
this, &try_control_builder);
1709 Visit(stmt->try_block());
1710 set_catch_prediction(outer_catch_prediction);
1712 try_control_builder.EndTry();
1714 if (stmt->scope()) {
1716 BuildNewLocalCatchContext(stmt->scope());
1717 builder()->StoreAccumulatorInRegister(context);
1721 if (stmt->ShouldClearPendingException(outer_catch_prediction)) {
1722 builder()->LoadTheHole().SetPendingMessage();
1726 builder()->LoadAccumulatorWithRegister(context);
1729 if (stmt->scope()) {
1730 VisitInScope(stmt->catch_block(), stmt->scope());
1732 VisitBlock(stmt->catch_block());
1734 try_control_builder.EndCatch();
1737 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1740 TryFinallyBuilder try_control_builder(builder(), block_coverage_builder_,
1741 stmt, catch_prediction());
1758 Register token = register_allocator()->NewRegister();
1759 Register result = register_allocator()->NewRegister();
1760 ControlScope::DeferredCommands commands(
this, token, result);
1765 Register context = register_allocator()->NewRegister();
1766 builder()->MoveRegister(Register::current_context(), context);
1770 try_control_builder.BeginTry(context);
1772 ControlScopeForTryFinally scope(
this, &try_control_builder, &commands);
1773 Visit(stmt->try_block());
1775 try_control_builder.EndTry();
1778 commands.RecordFallThroughPath();
1779 try_control_builder.LeaveTry();
1780 try_control_builder.BeginHandler();
1781 commands.RecordHandlerReThrowPath();
1784 try_control_builder.BeginFinally();
1785 Register message = context;
1788 builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister(
1792 Visit(stmt->finally_block());
1793 try_control_builder.EndFinally();
1796 builder()->LoadAccumulatorWithRegister(message).SetPendingMessage();
1799 commands.ApplyDeferredCommands();
1802 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1803 builder()->SetStatementPosition(stmt);
1804 builder()->Debugger();
1807 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1808 DCHECK(expr->scope()->outer_scope() == current_scope());
1809 uint8_t flags = CreateClosureFlags::Encode(
1810 expr->pretenure(), closure_scope()->is_function_scope());
1811 size_t entry = builder()->AllocateDeferredConstantPoolEntry();
1812 FeedbackSlot slot = GetCachedCreateClosureSlot(expr);
1813 builder()->CreateClosure(entry, feedback_index(slot), flags);
1814 function_literals_.push_back(std::make_pair(expr, entry));
1815 AddToEagerLiteralsIfEager(expr);
1818 void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {
1819 if (eager_inner_literals_ && literal->ShouldEagerCompile()) {
1820 DCHECK(!IsInEagerLiterals(literal, *eager_inner_literals_));
1821 eager_inner_literals_->push_back(literal);
1825 bool BytecodeGenerator::ShouldOptimizeAsOneShot()
const {
1826 if (!FLAG_enable_one_shot_optimization)
return false;
1828 if (loop_depth_ > 0)
return false;
1832 bool is_toplevel_iife = info()->literal()->is_iife() &&
1833 current_scope()->outer_scope()->is_script_scope();
1834 return info()->literal()->is_toplevel() || is_toplevel_iife;
1837 void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
1838 size_t class_boilerplate_entry =
1839 builder()->AllocateDeferredConstantPoolEntry();
1840 class_literals_.push_back(std::make_pair(expr, class_boilerplate_entry));
1842 VisitDeclarations(expr->scope()->declarations());
1843 Register class_constructor = register_allocator()->NewRegister();
1846 RegisterAllocationScope register_scope(
this);
1847 RegisterList args = register_allocator()->NewGrowableRegisterList();
1849 Register class_boilerplate = register_allocator()->GrowRegisterList(&args);
1850 Register class_constructor_in_args =
1851 register_allocator()->GrowRegisterList(&args);
1852 Register super_class = register_allocator()->GrowRegisterList(&args);
1853 DCHECK_EQ(ClassBoilerplate::kFirstDynamicArgumentIndex,
1854 args.register_count());
1856 VisitForAccumulatorValueOrTheHole(expr->extends());
1857 builder()->StoreAccumulatorInRegister(super_class);
1859 VisitFunctionLiteral(expr->constructor());
1861 ->StoreAccumulatorInRegister(class_constructor)
1862 .MoveRegister(class_constructor, class_constructor_in_args)
1863 .LoadConstantPoolEntry(class_boilerplate_entry)
1864 .StoreAccumulatorInRegister(class_boilerplate);
1867 for (
int i = 0;
i < expr->properties()->length();
i++) {
1868 ClassLiteral::Property*
property = expr->properties()->at(
i);
1869 if (property->is_computed_name()) {
1870 DCHECK_IMPLIES(property->kind() == ClassLiteral::Property::FIELD,
1871 !
property->is_private());
1872 Register key = register_allocator()->GrowRegisterList(&args);
1874 builder()->SetExpressionAsStatementPosition(property->key());
1875 BuildLoadPropertyKey(property, key);
1876 if (property->is_static()) {
1882 FeedbackSlot slot = GetDummyCompareICSlot();
1885 ->LoadLiteral(ast_string_constants()->prototype_string())
1886 .CompareOperation(Token::Value::EQ_STRICT, key,
1887 feedback_index(slot))
1888 .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done)
1889 .CallRuntime(Runtime::kThrowStaticPrototypeError)
1893 if (property->kind() == ClassLiteral::Property::FIELD &&
1894 !
property->is_private()) {
1896 DCHECK_NOT_NULL(property->computed_name_var());
1897 builder()->LoadAccumulatorWithRegister(key);
1898 BuildVariableAssignment(property->computed_name_var(), Token::INIT,
1899 HoleCheckMode::kElided);
1903 if (property->kind() == ClassLiteral::Property::FIELD) {
1904 if (property->is_private()) {
1905 builder()->CallRuntime(Runtime::kCreatePrivateNameSymbol);
1906 DCHECK_NOT_NULL(property->private_name_var());
1907 BuildVariableAssignment(property->private_name_var(), Token::INIT,
1908 HoleCheckMode::kElided);
1915 Register value = register_allocator()->GrowRegisterList(&args);
1916 VisitForRegisterValue(property->value(), value);
1919 builder()->CallRuntime(Runtime::kDefineClass, args);
1921 Register prototype = register_allocator()->NewRegister();
1922 builder()->StoreAccumulatorInRegister(prototype);
1925 if (expr->class_variable() !=
nullptr) {
1926 DCHECK(expr->class_variable()->IsStackLocal() ||
1927 expr->class_variable()->IsContextSlot());
1928 builder()->LoadAccumulatorWithRegister(class_constructor);
1929 BuildVariableAssignment(expr->class_variable(), Token::INIT,
1930 HoleCheckMode::kElided);
1933 if (expr->instance_members_initializer_function() !=
nullptr) {
1934 Register initializer =
1935 VisitForRegisterValue(expr->instance_members_initializer_function());
1937 if (FunctionLiteral::NeedsHomeObject(
1938 expr->instance_members_initializer_function())) {
1939 FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
1940 builder()->LoadAccumulatorWithRegister(prototype).StoreHomeObjectProperty(
1941 initializer, feedback_index(slot), language_mode());
1944 FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
1946 ->LoadAccumulatorWithRegister(initializer)
1947 .StoreClassFieldsInitializer(class_constructor, feedback_index(slot))
1948 .LoadAccumulatorWithRegister(class_constructor);
1951 if (expr->static_fields_initializer() !=
nullptr) {
1956 if (name.is_valid()) {
1957 Register key = register_allocator()->NewRegister();
1959 ->LoadLiteral(ast_string_constants()->name_string())
1960 .StoreAccumulatorInRegister(key);
1962 DataPropertyInLiteralFlags data_property_flags =
1963 DataPropertyInLiteralFlag::kNoFlags;
1965 feedback_spec()->AddStoreDataPropertyInLiteralICSlot();
1966 builder()->LoadAccumulatorWithRegister(name).StoreDataPropertyInLiteral(
1967 class_constructor, key, data_property_flags, feedback_index(slot));
1970 RegisterList args = register_allocator()->NewRegisterList(1);
1971 Register initializer =
1972 VisitForRegisterValue(expr->static_fields_initializer());
1974 if (FunctionLiteral::NeedsHomeObject(expr->static_fields_initializer())) {
1975 FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
1977 ->LoadAccumulatorWithRegister(class_constructor)
1978 .StoreHomeObjectProperty(initializer, feedback_index(slot),
1983 ->MoveRegister(class_constructor, args[0])
1984 .CallProperty(initializer, args,
1985 feedback_index(feedback_spec()->AddCallICSlot()));
1987 builder()->LoadAccumulatorWithRegister(class_constructor);
1990 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
1991 VisitClassLiteral(expr, Register::invalid_value());
1994 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr, Register name) {
1995 CurrentScope current_scope(
this, expr->scope());
1996 DCHECK_NOT_NULL(expr->scope());
1997 if (expr->scope()->NeedsContext()) {
1998 BuildNewLocalBlockContext(expr->scope());
1999 ContextScope scope(
this, expr->scope());
2000 BuildClassLiteral(expr, name);
2002 BuildClassLiteral(expr, name);
2006 void BytecodeGenerator::VisitInitializeClassMembersStatement(
2007 InitializeClassMembersStatement* stmt) {
2008 RegisterList args = register_allocator()->NewRegisterList(3);
2009 Register constructor = args[0], key = args[1], value = args[2];
2010 builder()->MoveRegister(builder()->Receiver(), constructor);
2012 for (
int i = 0;
i < stmt->fields()->length();
i++) {
2013 ClassLiteral::Property*
property = stmt->fields()->at(
i);
2015 if (property->is_computed_name()) {
2016 DCHECK_EQ(property->kind(), ClassLiteral::Property::FIELD);
2017 DCHECK(!property->is_private());
2018 Variable* var =
property->computed_name_var();
2019 DCHECK_NOT_NULL(var);
2022 BuildVariableLoad(var, HoleCheckMode::kElided);
2023 builder()->StoreAccumulatorInRegister(key);
2024 }
else if (property->kind() == ClassLiteral::Property::FIELD &&
2025 property->is_private()) {
2026 Variable* private_name_var =
property->private_name_var();
2027 DCHECK_NOT_NULL(private_name_var);
2028 BuildVariableLoad(private_name_var, HoleCheckMode::kElided);
2029 builder()->StoreAccumulatorInRegister(key);
2031 BuildLoadPropertyKey(property, key);
2034 builder()->SetExpressionAsStatementPosition(property->value());
2035 VisitForRegisterValue(property->value(), value);
2036 VisitSetHomeObject(value, constructor, property);
2038 Runtime::FunctionId function_id =
2039 property->kind() == ClassLiteral::Property::FIELD &&
2040 !
property->is_private()
2041 ? Runtime::kCreateDataProperty
2042 : Runtime::kAddPrivateField;
2043 builder()->CallRuntime(function_id, args);
2047 void BytecodeGenerator::BuildInstanceMemberInitialization(Register constructor,
2048 Register instance) {
2049 RegisterList args = register_allocator()->NewRegisterList(1);
2050 Register initializer = register_allocator()->NewRegister();
2052 FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
2056 ->LoadClassFieldsInitializer(constructor, feedback_index(slot))
2060 .JumpIfUndefined(&done)
2061 .StoreAccumulatorInRegister(initializer)
2062 .MoveRegister(instance, args[0])
2063 .CallProperty(initializer, args,
2064 feedback_index(feedback_spec()->AddCallICSlot()))
2068 void BytecodeGenerator::VisitNativeFunctionLiteral(
2069 NativeFunctionLiteral* expr) {
2070 size_t entry = builder()->AllocateDeferredConstantPoolEntry();
2071 FeedbackSlot slot = feedback_spec()->AddCreateClosureSlot();
2072 builder()->CreateClosure(entry, feedback_index(slot), NOT_TENURED);
2073 native_function_literals_.push_back(std::make_pair(expr, entry));
2076 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
2077 VisitBlock(expr->block());
2078 VisitVariableProxy(expr->result());
2081 void BytecodeGenerator::VisitConditional(Conditional* expr) {
2082 ConditionalControlFlowBuilder conditional_builder(
2083 builder(), block_coverage_builder_, expr);
2085 if (expr->condition()->ToBooleanIsTrue()) {
2087 conditional_builder.Then();
2088 VisitForAccumulatorValue(expr->then_expression());
2089 }
else if (expr->condition()->ToBooleanIsFalse()) {
2091 conditional_builder.Else();
2092 VisitForAccumulatorValue(expr->else_expression());
2094 VisitForTest(expr->condition(), conditional_builder.then_labels(),
2095 conditional_builder.else_labels(), TestFallthrough::kThen);
2097 conditional_builder.Then();
2098 VisitForAccumulatorValue(expr->then_expression());
2099 conditional_builder.JumpToEnd();
2101 conditional_builder.Else();
2102 VisitForAccumulatorValue(expr->else_expression());
2106 void BytecodeGenerator::VisitLiteral(Literal* expr) {
2107 if (execution_result()->IsEffect())
return;
2108 switch (expr->type()) {
2110 builder()->LoadLiteral(expr->AsSmiLiteral());
2112 case Literal::kHeapNumber:
2113 builder()->LoadLiteral(expr->AsNumber());
2115 case Literal::kUndefined:
2116 builder()->LoadUndefined();
2118 case Literal::kBoolean:
2119 builder()->LoadBoolean(expr->ToBooleanIsTrue());
2120 execution_result()->SetResultIsBoolean();
2122 case Literal::kNull:
2123 builder()->LoadNull();
2125 case Literal::kTheHole:
2126 builder()->LoadTheHole();
2128 case Literal::kString:
2129 builder()->LoadLiteral(expr->AsRawString());
2130 execution_result()->SetResultIsString();
2132 case Literal::kSymbol:
2133 builder()->LoadLiteral(expr->AsSymbol());
2135 case Literal::kBigInt:
2136 builder()->LoadLiteral(expr->AsBigInt());
2141 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
2143 builder()->CreateRegExpLiteral(
2144 expr->raw_pattern(), feedback_index(feedback_spec()->AddLiteralSlot()),
2148 void BytecodeGenerator::BuildCreateObjectLiteral(Register literal,
2149 uint8_t flags,
size_t entry) {
2150 if (ShouldOptimizeAsOneShot()) {
2151 RegisterList args = register_allocator()->NewRegisterList(2);
2153 ->LoadConstantPoolEntry(entry)
2154 .StoreAccumulatorInRegister(args[0])
2155 .LoadLiteral(Smi::FromInt(flags))
2156 .StoreAccumulatorInRegister(args[1])
2157 .CallRuntime(Runtime::kCreateObjectLiteralWithoutAllocationSite, args)
2158 .StoreAccumulatorInRegister(literal);
2164 int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
2166 ->CreateObjectLiteral(entry, literal_index, flags)
2167 .StoreAccumulatorInRegister(literal);
2171 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
2172 expr->InitDepthAndFlags();
2176 if (expr->IsEmptyObjectLiteral()) {
2177 DCHECK(expr->IsFastCloningSupported());
2178 builder()->CreateEmptyObjectLiteral();
2183 uint8_t flags = CreateObjectLiteralFlags::Encode(
2184 expr->ComputeFlags(), expr->IsFastCloningSupported());
2186 Register literal = register_allocator()->NewRegister();
2189 int property_index = 0;
2190 bool clone_object_spread =
2191 expr->properties()->first()->kind() == ObjectLiteral::Property::SPREAD;
2192 if (clone_object_spread) {
2197 RegisterAllocationScope register_scope(
this);
2198 Expression*
property = expr->properties()->first()->value();
2199 Register from_value = VisitForRegisterValue(property);
2201 BytecodeLabels clone_object(zone());
2202 builder()->JumpIfUndefined(clone_object.New());
2203 builder()->JumpIfNull(clone_object.New());
2204 builder()->ToObject(from_value);
2206 clone_object.Bind(builder());
2207 int clone_index = feedback_index(feedback_spec()->AddCloneObjectSlot());
2208 builder()->CloneObject(from_value, flags, clone_index);
2209 builder()->StoreAccumulatorInRegister(literal);
2215 if (expr->properties_count() == 0) {
2216 entry = builder()->EmptyObjectBoilerplateDescriptionConstantPoolEntry();
2218 entry = builder()->AllocateDeferredConstantPoolEntry();
2219 object_literals_.push_back(std::make_pair(expr, entry));
2221 BuildCreateObjectLiteral(literal, flags, entry);
2225 AccessorTable accessor_table(zone());
2226 for (; property_index < expr->properties()->length(); property_index++) {
2227 ObjectLiteral::Property*
property = expr->properties()->at(property_index);
2228 if (property->is_computed_name())
break;
2229 if (!clone_object_spread && property->IsCompileTimeValue())
continue;
2231 RegisterAllocationScope inner_register_scope(
this);
2232 Literal* key =
property->key()->AsLiteral();
2233 switch (property->kind()) {
2234 case ObjectLiteral::Property::SPREAD:
2236 case ObjectLiteral::Property::CONSTANT:
2237 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
2238 DCHECK(clone_object_spread || !property->value()->IsCompileTimeValue());
2240 case ObjectLiteral::Property::COMPUTED: {
2243 if (key->IsStringLiteral()) {
2244 DCHECK(key->IsPropertyName());
2245 if (property->emit_store()) {
2246 builder()->SetExpressionPosition(property->value());
2247 VisitForAccumulatorValue(property->value());
2248 FeedbackSlot slot = feedback_spec()->AddStoreOwnICSlot();
2249 if (FunctionLiteral::NeedsHomeObject(property->value())) {
2250 RegisterAllocationScope register_scope(
this);
2251 Register value = register_allocator()->NewRegister();
2252 builder()->StoreAccumulatorInRegister(value);
2253 builder()->StoreNamedOwnProperty(
2254 literal, key->AsRawPropertyName(), feedback_index(slot));
2255 VisitSetHomeObject(value, literal, property);
2257 builder()->StoreNamedOwnProperty(
2258 literal, key->AsRawPropertyName(), feedback_index(slot));
2261 builder()->SetExpressionPosition(property->value());
2262 VisitForEffect(property->value());
2265 RegisterList args = register_allocator()->NewRegisterList(4);
2267 builder()->MoveRegister(literal, args[0]);
2268 builder()->SetExpressionPosition(property->key());
2269 VisitForRegisterValue(property->key(), args[1]);
2270 builder()->SetExpressionPosition(property->value());
2271 VisitForRegisterValue(property->value(), args[2]);
2272 if (property->emit_store()) {
2274 ->LoadLiteral(Smi::FromEnum(LanguageMode::kSloppy))
2275 .StoreAccumulatorInRegister(args[3])
2276 .CallRuntime(Runtime::kSetKeyedProperty, args);
2277 Register value = args[2];
2278 VisitSetHomeObject(value, literal, property);
2283 case ObjectLiteral::Property::PROTOTYPE: {
2285 if (property->IsNullPrototype())
break;
2286 DCHECK(property->emit_store());
2287 DCHECK(!property->NeedsSetFunctionName());
2288 RegisterList args = register_allocator()->NewRegisterList(2);
2289 builder()->MoveRegister(literal, args[0]);
2290 builder()->SetExpressionPosition(property->value());
2291 VisitForRegisterValue(property->value(), args[1]);
2292 builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
2295 case ObjectLiteral::Property::GETTER:
2296 if (property->emit_store()) {
2297 accessor_table.lookup(key)->second->getter = property;
2300 case ObjectLiteral::Property::SETTER:
2301 if (property->emit_store()) {
2302 accessor_table.lookup(key)->second->setter = property;
2310 for (AccessorTable::Iterator it = accessor_table.begin();
2311 it != accessor_table.end(); ++it) {
2312 RegisterAllocationScope inner_register_scope(
this);
2313 RegisterList args = register_allocator()->NewRegisterList(5);
2314 builder()->MoveRegister(literal, args[0]);
2315 VisitForRegisterValue(it->first, args[1]);
2316 VisitObjectLiteralAccessor(literal, it->second->getter, args[2]);
2317 VisitObjectLiteralAccessor(literal, it->second->setter, args[3]);
2319 ->LoadLiteral(Smi::FromInt(NONE))
2320 .StoreAccumulatorInRegister(args[4])
2321 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args);
2333 for (; property_index < expr->properties()->length(); property_index++) {
2334 ObjectLiteral::Property*
property = expr->properties()->at(property_index);
2335 RegisterAllocationScope inner_register_scope(
this);
2337 if (property->IsPrototype()) {
2339 if (property->IsNullPrototype())
continue;
2340 DCHECK(property->emit_store());
2341 DCHECK(!property->NeedsSetFunctionName());
2342 RegisterList args = register_allocator()->NewRegisterList(2);
2343 builder()->MoveRegister(literal, args[0]);
2344 builder()->SetExpressionPosition(property->value());
2345 VisitForRegisterValue(property->value(), args[1]);
2346 builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
2350 switch (property->kind()) {
2351 case ObjectLiteral::Property::CONSTANT:
2352 case ObjectLiteral::Property::COMPUTED:
2353 case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
2354 Register key = register_allocator()->NewRegister();
2355 BuildLoadPropertyKey(property, key);
2356 builder()->SetExpressionPosition(property->value());
2362 if (property->value()->IsClassLiteral() &&
2363 property->value()->AsClassLiteral()->static_fields_initializer() !=
2365 value = register_allocator()->NewRegister();
2366 VisitClassLiteral(property->value()->AsClassLiteral(), key);
2367 builder()->StoreAccumulatorInRegister(value);
2369 value = VisitForRegisterValue(property->value());
2371 VisitSetHomeObject(value, literal, property);
2373 DataPropertyInLiteralFlags data_property_flags =
2374 DataPropertyInLiteralFlag::kNoFlags;
2375 if (property->NeedsSetFunctionName()) {
2376 data_property_flags |= DataPropertyInLiteralFlag::kSetFunctionName;
2380 feedback_spec()->AddStoreDataPropertyInLiteralICSlot();
2382 ->LoadAccumulatorWithRegister(value)
2383 .StoreDataPropertyInLiteral(literal, key, data_property_flags,
2384 feedback_index(slot));
2387 case ObjectLiteral::Property::GETTER:
2388 case ObjectLiteral::Property::SETTER: {
2389 RegisterList args = register_allocator()->NewRegisterList(4);
2390 builder()->MoveRegister(literal, args[0]);
2391 BuildLoadPropertyKey(property, args[1]);
2392 builder()->SetExpressionPosition(property->value());
2393 VisitForRegisterValue(property->value(), args[2]);
2394 VisitSetHomeObject(args[2], literal, property);
2396 ->LoadLiteral(Smi::FromInt(NONE))
2397 .StoreAccumulatorInRegister(args[3]);
2398 Runtime::FunctionId function_id =
2399 property->kind() == ObjectLiteral::Property::GETTER
2400 ? Runtime::kDefineGetterPropertyUnchecked
2401 : Runtime::kDefineSetterPropertyUnchecked;
2402 builder()->CallRuntime(function_id, args);
2405 case ObjectLiteral::Property::SPREAD: {
2406 RegisterList args = register_allocator()->NewRegisterList(2);
2407 builder()->MoveRegister(literal, args[0]);
2408 builder()->SetExpressionPosition(property->value());
2409 VisitForRegisterValue(property->value(), args[1]);
2410 builder()->CallRuntime(Runtime::kCopyDataProperties, args);
2413 case ObjectLiteral::Property::PROTOTYPE:
2419 builder()->LoadAccumulatorWithRegister(literal);
2422 void BytecodeGenerator::BuildArrayLiteralSpread(Spread* spread, Register array,
2424 FeedbackSlot index_slot,
2425 FeedbackSlot element_slot) {
2426 RegisterAllocationScope register_scope(
this);
2427 Register value = register_allocator()->NewRegister();
2429 builder()->SetExpressionAsStatementPosition(spread->expression());
2430 IteratorRecord iterator =
2431 BuildGetIteratorRecord(spread->expression(), IteratorType::kNormal);
2433 LoopBuilder loop_builder(builder(),
nullptr,
nullptr);
2434 loop_builder.LoopHeader();
2439 BuildIteratorNext(iterator, value);
2440 builder()->LoadNamedProperty(
2441 value, ast_string_constants()->done_string(),
2442 feedback_index(feedback_spec()->AddLoadICSlot()));
2443 loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
2445 loop_builder.LoopBody();
2448 ->LoadNamedProperty(value, ast_string_constants()->value_string(),
2449 feedback_index(feedback_spec()->AddLoadICSlot()))
2450 .StoreAccumulatorInRegister(value)
2452 .StoreInArrayLiteral(array, index, feedback_index(element_slot))
2454 .LoadAccumulatorWithRegister(index)
2455 .UnaryOperation(Token::INC, feedback_index(index_slot))
2456 .StoreAccumulatorInRegister(index);
2457 loop_builder.BindContinueTarget();
2458 loop_builder.JumpToHeader(loop_depth_);
2461 void BytecodeGenerator::BuildCreateArrayLiteral(
2462 const ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
2463 RegisterAllocationScope register_scope(
this);
2464 Register index = register_allocator()->NewRegister();
2465 Register array = register_allocator()->NewRegister();
2466 SharedFeedbackSlot element_slot(feedback_spec(),
2467 FeedbackSlotKind::kStoreInArrayLiteral);
2468 ZonePtrList<Expression>::iterator current = elements->begin();
2469 ZonePtrList<Expression>::iterator end = elements->end();
2470 bool is_empty = elements->is_empty();
2472 if (!is_empty && (*current)->IsSpread()) {
2475 VisitForAccumulatorValue(*current);
2476 builder()->CreateArrayFromIterable().StoreAccumulatorInRegister(array);
2478 if (++current != end) {
2482 auto length = ast_string_constants()->length_string();
2483 int length_load_slot = feedback_index(feedback_spec()->AddLoadICSlot());
2485 ->LoadNamedProperty(array, length, length_load_slot)
2486 .StoreAccumulatorInRegister(index);
2488 }
else if (expr !=
nullptr) {
2496 uint8_t flags = CreateArrayLiteralFlags::Encode(
2497 expr->IsFastCloningSupported(), expr->ComputeFlags());
2498 bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
2500 if (is_empty && optimize_as_one_shot) {
2501 entry = builder()->EmptyArrayBoilerplateDescriptionConstantPoolEntry();
2502 }
else if (!is_empty) {
2503 entry = builder()->AllocateDeferredConstantPoolEntry();
2504 array_literals_.push_back(std::make_pair(expr, entry));
2507 if (optimize_as_one_shot) {
2508 RegisterList args = register_allocator()->NewRegisterList(2);
2510 ->LoadConstantPoolEntry(entry)
2511 .StoreAccumulatorInRegister(args[0])
2512 .LoadLiteral(Smi::FromInt(flags))
2513 .StoreAccumulatorInRegister(args[1])
2514 .CallRuntime(Runtime::kCreateArrayLiteralWithoutAllocationSite, args);
2515 }
else if (is_empty) {
2517 int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
2518 DCHECK(expr->IsFastCloningSupported());
2519 builder()->CreateEmptyArrayLiteral(literal_index);
2522 int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
2523 builder()->CreateArrayLiteral(entry, literal_index, flags);
2525 builder()->StoreAccumulatorInRegister(array);
2530 DCHECK_EQ(current, elements->begin());
2531 ZonePtrList<Expression>::iterator first_spread_or_end =
2532 expr->first_spread_index() >= 0 ? current + expr->first_spread_index()
2534 int array_index = 0;
2535 for (; current != first_spread_or_end; ++current, array_index++) {
2536 Expression* subexpr = *current;
2537 DCHECK(!subexpr->IsSpread());
2539 if (subexpr->IsCompileTimeValue())
continue;
2542 ->LoadLiteral(Smi::FromInt(array_index))
2543 .StoreAccumulatorInRegister(index);
2544 VisitForAccumulatorValue(subexpr);
2545 builder()->StoreInArrayLiteral(array, index,
2546 feedback_index(element_slot.Get()));
2549 if (current != end) {
2552 builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
2556 DCHECK(!elements->is_empty());
2557 int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
2559 ->CreateEmptyArrayLiteral(literal_index)
2560 .StoreAccumulatorInRegister(array);
2562 builder()->LoadLiteral(Smi::FromInt(0)).StoreAccumulatorInRegister(index);
2566 SharedFeedbackSlot index_slot(feedback_spec(), FeedbackSlotKind::kBinaryOp);
2567 SharedFeedbackSlot length_slot(
2568 feedback_spec(), feedback_spec()->GetStoreICSlot(LanguageMode::kStrict));
2569 for (; current != end; ++current) {
2570 Expression* subexpr = *current;
2571 if (subexpr->IsSpread()) {
2572 FeedbackSlot real_index_slot = index_slot.Get();
2573 BuildArrayLiteralSpread(subexpr->AsSpread(), array, index,
2574 real_index_slot, element_slot.Get());
2575 }
else if (!subexpr->IsTheHoleLiteral()) {
2577 VisitForAccumulatorValue(subexpr);
2579 ->StoreInArrayLiteral(array, index,
2580 feedback_index(element_slot.Get()))
2581 .LoadAccumulatorWithRegister(index);
2583 if (current + 1 != end) {
2585 ->UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
2586 .StoreAccumulatorInRegister(index);
2591 auto length = ast_string_constants()->length_string();
2593 ->LoadAccumulatorWithRegister(index)
2594 .UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
2595 .StoreAccumulatorInRegister(index)
2596 .StoreNamedProperty(array, length, feedback_index(length_slot.Get()),
2597 LanguageMode::kStrict);
2601 builder()->LoadAccumulatorWithRegister(array);
2604 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
2605 expr->InitDepthAndFlags();
2606 BuildCreateArrayLiteral(expr->values(), expr);
2609 void BytecodeGenerator::VisitStoreInArrayLiteral(StoreInArrayLiteral* expr) {
2610 builder()->SetExpressionAsStatementPosition(expr);
2611 RegisterAllocationScope register_scope(
this);
2612 Register array = register_allocator()->NewRegister();
2613 Register index = register_allocator()->NewRegister();
2614 VisitForRegisterValue(expr->array(), array);
2615 VisitForRegisterValue(expr->index(), index);
2616 VisitForAccumulatorValue(expr->value());
2617 builder()->StoreInArrayLiteral(
2619 feedback_index(feedback_spec()->AddStoreInArrayLiteralICSlot()));
2622 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
2623 builder()->SetExpressionPosition(proxy);
2624 BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
2627 void BytecodeGenerator::BuildVariableLoad(Variable* variable,
2628 HoleCheckMode hole_check_mode,
2629 TypeofMode typeof_mode) {
2630 switch (variable->location()) {
2631 case VariableLocation::LOCAL: {
2632 Register source(builder()->Local(variable->index()));
2636 builder()->LoadAccumulatorWithRegister(source);
2637 if (hole_check_mode == HoleCheckMode::kRequired) {
2638 BuildThrowIfHole(variable);
2642 case VariableLocation::PARAMETER: {
2644 if (variable->IsReceiver()) {
2645 source = builder()->Receiver();
2647 source = builder()->Parameter(variable->index());
2652 builder()->LoadAccumulatorWithRegister(source);
2653 if (hole_check_mode == HoleCheckMode::kRequired) {
2654 BuildThrowIfHole(variable);
2658 case VariableLocation::UNALLOCATED: {
2662 if (variable->raw_name() == ast_string_constants()->undefined_string()) {
2663 builder()->LoadUndefined();
2665 FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
2666 builder()->LoadGlobal(variable->raw_name(), feedback_index(slot),
2671 case VariableLocation::CONTEXT: {
2672 int depth = execution_context()->ContextChainDepth(variable->scope());
2673 ContextScope* context = execution_context()->Previous(depth);
2674 Register context_reg;
2676 context_reg = context->reg();
2679 context_reg = execution_context()->reg();
2682 BytecodeArrayBuilder::ContextSlotMutability immutable =
2683 (variable->maybe_assigned() == kNotAssigned)
2684 ? BytecodeArrayBuilder::kImmutableSlot
2685 : BytecodeArrayBuilder::kMutableSlot;
2687 builder()->LoadContextSlot(context_reg, variable->index(), depth,
2689 if (hole_check_mode == HoleCheckMode::kRequired) {
2690 BuildThrowIfHole(variable);
2694 case VariableLocation::LOOKUP: {
2695 switch (variable->mode()) {
2696 case VariableMode::kDynamicLocal: {
2697 Variable* local_variable = variable->local_if_not_shadowed();
2699 execution_context()->ContextChainDepth(local_variable->scope());
2700 builder()->LoadLookupContextSlot(variable->raw_name(), typeof_mode,
2701 local_variable->index(), depth);
2702 if (hole_check_mode == HoleCheckMode::kRequired) {
2703 BuildThrowIfHole(variable);
2707 case VariableMode::kDynamicGlobal: {
2709 current_scope()->ContextChainLengthUntilOutermostSloppyEval();
2710 FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
2711 builder()->LoadLookupGlobalSlot(variable->raw_name(), typeof_mode,
2712 feedback_index(slot), depth);
2716 builder()->LoadLookupSlot(variable->raw_name(), typeof_mode);
2720 case VariableLocation::MODULE: {
2721 int depth = execution_context()->ContextChainDepth(variable->scope());
2722 builder()->LoadModuleVariable(variable->index(), depth);
2723 if (hole_check_mode == HoleCheckMode::kRequired) {
2724 BuildThrowIfHole(variable);
2731 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
2732 Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode) {
2733 ValueResultScope accumulator_result(
this);
2734 BuildVariableLoad(variable, hole_check_mode, typeof_mode);
2737 void BytecodeGenerator::BuildReturn(
int source_position) {
2739 RegisterAllocationScope register_scope(
this);
2740 Register result = register_allocator()->NewRegister();
2742 builder()->StoreAccumulatorInRegister(result).CallRuntime(
2743 Runtime::kTraceExit, result);
2745 if (info()->collect_type_profile()) {
2746 builder()->CollectTypeProfile(info()->literal()->return_position());
2748 builder()->SetReturnPosition(source_position, info()->literal());
2749 builder()->Return();
2752 void BytecodeGenerator::BuildAsyncReturn(
int source_position) {
2753 RegisterAllocationScope register_scope(
this);
2755 if (IsAsyncGeneratorFunction(info()->literal()->kind())) {
2756 RegisterList args = register_allocator()->NewRegisterList(3);
2758 ->MoveRegister(generator_object(), args[0])
2759 .StoreAccumulatorInRegister(args[1])
2761 .StoreAccumulatorInRegister(args[2])
2762 .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
2764 DCHECK(IsAsyncFunction(info()->literal()->kind()));
2765 RegisterList args = register_allocator()->NewRegisterList(3);
2767 ->MoveRegister(generator_object(), args[0])
2768 .StoreAccumulatorInRegister(args[1])
2769 .LoadBoolean(info()->literal()->CanSuspend())
2770 .StoreAccumulatorInRegister(args[2])
2771 .CallRuntime(Runtime::kInlineAsyncFunctionResolve, args);
2774 BuildReturn(source_position);
2777 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
2779 void BytecodeGenerator::BuildThrowIfHole(Variable* variable) {
2780 if (variable->is_this()) {
2781 DCHECK(variable->mode() == VariableMode::kConst);
2782 builder()->ThrowSuperNotCalledIfHole();
2784 builder()->ThrowReferenceErrorIfHole(variable->raw_name());
2788 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
2790 if (variable->is_this() && variable->mode() == VariableMode::kConst &&
2791 op == Token::INIT) {
2795 builder()->ThrowSuperAlreadyCalledIfNotHole();
2799 DCHECK(IsLexicalVariableMode(variable->mode()));
2800 BuildThrowIfHole(variable);
2804 void BytecodeGenerator::BuildVariableAssignment(
2805 Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
2806 LookupHoistingMode lookup_hoisting_mode) {
2807 VariableMode mode = variable->mode();
2808 RegisterAllocationScope assignment_register_scope(
this);
2809 BytecodeLabel end_label;
2810 switch (variable->location()) {
2811 case VariableLocation::PARAMETER:
2812 case VariableLocation::LOCAL: {
2813 Register destination;
2814 if (VariableLocation::PARAMETER == variable->location()) {
2815 if (variable->IsReceiver()) {
2816 destination = builder()->Receiver();
2818 destination = builder()->Parameter(variable->index());
2821 destination = builder()->Local(variable->index());
2824 if (hole_check_mode == HoleCheckMode::kRequired) {
2826 Register value_temp = register_allocator()->NewRegister();
2828 ->StoreAccumulatorInRegister(value_temp)
2829 .LoadAccumulatorWithRegister(destination);
2831 BuildHoleCheckForVariableAssignment(variable, op);
2832 builder()->LoadAccumulatorWithRegister(value_temp);
2835 if (mode != VariableMode::kConst || op == Token::INIT) {
2836 builder()->StoreAccumulatorInRegister(destination);
2837 }
else if (variable->throw_on_const_assignment(language_mode())) {
2838 builder()->CallRuntime(Runtime::kThrowConstAssignError);
2842 case VariableLocation::UNALLOCATED: {
2843 FeedbackSlot slot = GetCachedStoreGlobalICSlot(language_mode(), variable);
2844 builder()->StoreGlobal(variable->raw_name(), feedback_index(slot));
2847 case VariableLocation::CONTEXT: {
2848 int depth = execution_context()->ContextChainDepth(variable->scope());
2849 ContextScope* context = execution_context()->Previous(depth);
2850 Register context_reg;
2853 context_reg = context->reg();
2856 context_reg = execution_context()->reg();
2859 if (hole_check_mode == HoleCheckMode::kRequired) {
2861 Register value_temp = register_allocator()->NewRegister();
2863 ->StoreAccumulatorInRegister(value_temp)
2864 .LoadContextSlot(context_reg, variable->index(), depth,
2865 BytecodeArrayBuilder::kMutableSlot);
2867 BuildHoleCheckForVariableAssignment(variable, op);
2868 builder()->LoadAccumulatorWithRegister(value_temp);
2871 if (mode != VariableMode::kConst || op == Token::INIT) {
2872 builder()->StoreContextSlot(context_reg, variable->index(), depth);
2873 }
else if (variable->throw_on_const_assignment(language_mode())) {
2874 builder()->CallRuntime(Runtime::kThrowConstAssignError);
2878 case VariableLocation::LOOKUP: {
2879 builder()->StoreLookupSlot(variable->raw_name(), language_mode(),
2880 lookup_hoisting_mode);
2883 case VariableLocation::MODULE: {
2884 DCHECK(IsDeclaredVariableMode(mode));
2886 if (mode == VariableMode::kConst && op != Token::INIT) {
2887 builder()->CallRuntime(Runtime::kThrowConstAssignError);
2894 DCHECK(variable->IsExport());
2896 int depth = execution_context()->ContextChainDepth(variable->scope());
2897 if (hole_check_mode == HoleCheckMode::kRequired) {
2898 Register value_temp = register_allocator()->NewRegister();
2900 ->StoreAccumulatorInRegister(value_temp)
2901 .LoadModuleVariable(variable->index(), depth);
2902 BuildHoleCheckForVariableAssignment(variable, op);
2903 builder()->LoadAccumulatorWithRegister(value_temp);
2905 builder()->StoreModuleVariable(variable->index(), depth);
2911 void BytecodeGenerator::BuildLoadNamedProperty(Property* property,
2913 const AstRawString* name) {
2914 if (ShouldOptimizeAsOneShot()) {
2915 builder()->LoadNamedPropertyNoFeedback(
object, name);
2917 FeedbackSlot slot = GetCachedLoadICSlot(property->obj(), name);
2918 builder()->LoadNamedProperty(
object, name, feedback_index(slot));
2922 void BytecodeGenerator::BuildStoreNamedProperty(Property* property,
2924 const AstRawString* name) {
2926 if (!execution_result()->IsEffect()) {
2927 value = register_allocator()->NewRegister();
2928 builder()->StoreAccumulatorInRegister(value);
2931 if (ShouldOptimizeAsOneShot()) {
2932 builder()->StoreNamedPropertyNoFeedback(
object, name, language_mode());
2934 FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
2935 builder()->StoreNamedProperty(
object, name, feedback_index(slot),
2939 if (!execution_result()->IsEffect()) {
2940 builder()->LoadAccumulatorWithRegister(value);
2944 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
2945 DCHECK(expr->target()->IsValidReferenceExpression() ||
2946 (expr->op() == Token::INIT && expr->target()->IsVariableProxy() &&
2947 expr->target()->AsVariableProxy()->is_this()));
2948 Register object, key;
2949 RegisterList super_property_args;
2950 const AstRawString* name;
2953 Property*
property = expr->target()->AsProperty();
2954 LhsKind assign_type = Property::GetAssignType(property);
2957 switch (assign_type) {
2961 case NAMED_PROPERTY: {
2962 object = VisitForRegisterValue(property->obj());
2963 name =
property->key()->AsLiteral()->AsRawPropertyName();
2966 case KEYED_PROPERTY: {
2967 object = VisitForRegisterValue(property->obj());
2968 key = VisitForRegisterValue(property->key());
2971 case NAMED_SUPER_PROPERTY: {
2972 super_property_args = register_allocator()->NewRegisterList(4);
2973 SuperPropertyReference* super_property =
2974 property->obj()->AsSuperPropertyReference();
2975 VisitForRegisterValue(super_property->this_var(), super_property_args[0]);
2976 VisitForRegisterValue(super_property->home_object(),
2977 super_property_args[1]);
2979 ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
2980 .StoreAccumulatorInRegister(super_property_args[2]);
2983 case KEYED_SUPER_PROPERTY: {
2984 super_property_args = register_allocator()->NewRegisterList(4);
2985 SuperPropertyReference* super_property =
2986 property->obj()->AsSuperPropertyReference();
2987 VisitForRegisterValue(super_property->this_var(), super_property_args[0]);
2988 VisitForRegisterValue(super_property->home_object(),
2989 super_property_args[1]);
2990 VisitForRegisterValue(property->key(), super_property_args[2]);
2997 if (expr->IsCompoundAssignment()) {
2998 switch (assign_type) {
3000 VariableProxy* proxy = expr->target()->AsVariableProxy();
3001 BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
3004 case NAMED_PROPERTY: {
3005 BuildLoadNamedProperty(property,
object, name);
3008 case KEYED_PROPERTY: {
3011 FeedbackSlot slot = feedback_spec()->AddKeyedLoadICSlot();
3012 builder()->LoadKeyedProperty(
object, feedback_index(slot));
3015 case NAMED_SUPER_PROPERTY: {
3016 builder()->CallRuntime(Runtime::kLoadFromSuper,
3017 super_property_args.Truncate(3));
3020 case KEYED_SUPER_PROPERTY: {
3021 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper,
3022 super_property_args.Truncate(3));
3026 BinaryOperation* binop = expr->AsCompoundAssignment()->binary_operation();
3027 FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
3028 if (expr->value()->IsSmiLiteral()) {
3029 builder()->BinaryOperationSmiLiteral(
3030 binop->op(), expr->value()->AsLiteral()->AsSmiLiteral(),
3031 feedback_index(slot));
3033 Register old_value = register_allocator()->NewRegister();
3034 builder()->StoreAccumulatorInRegister(old_value);
3035 VisitForAccumulatorValue(expr->value());
3036 builder()->BinaryOperation(binop->op(), old_value, feedback_index(slot));
3039 VisitForAccumulatorValue(expr->value());
3043 builder()->SetExpressionPosition(expr);
3044 switch (assign_type) {
3048 VariableProxy* proxy = expr->target()->AsVariableProxy();
3049 BuildVariableAssignment(proxy->var(), expr->op(),
3050 proxy->hole_check_mode(),
3051 expr->lookup_hoisting_mode());
3054 case NAMED_PROPERTY: {
3055 BuildStoreNamedProperty(property,
object, name);
3058 case KEYED_PROPERTY: {
3059 FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
3061 if (!execution_result()->IsEffect()) {
3062 value = register_allocator()->NewRegister();
3063 builder()->StoreAccumulatorInRegister(value);
3065 builder()->StoreKeyedProperty(
object, key, feedback_index(slot),
3067 if (!execution_result()->IsEffect()) {
3068 builder()->LoadAccumulatorWithRegister(value);
3072 case NAMED_SUPER_PROPERTY: {
3074 ->StoreAccumulatorInRegister(super_property_args[3])
3075 .CallRuntime(StoreToSuperRuntimeId(), super_property_args);
3078 case KEYED_SUPER_PROPERTY: {
3080 ->StoreAccumulatorInRegister(super_property_args[3])
3081 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
3087 void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
3088 VisitAssignment(expr);
3094 void BytecodeGenerator::BuildSuspendPoint(Expression* suspend_expr) {
3095 const int suspend_id = suspend_count_++;
3097 RegisterList registers = register_allocator()->AllLiveRegisters();
3101 builder()->SetExpressionPosition(suspend_expr);
3102 builder()->SuspendGenerator(generator_object(), registers, suspend_id);
3105 builder()->Bind(generator_jump_table_, suspend_id);
3109 builder()->ResumeGenerator(generator_object(), registers);
3112 void BytecodeGenerator::VisitYield(Yield* expr) {
3113 builder()->SetExpressionPosition(expr);
3114 VisitForAccumulatorValue(expr->expression());
3117 if (suspend_count_ > 0) {
3118 if (IsAsyncGeneratorFunction(function_kind())) {
3122 RegisterAllocationScope register_scope(
this);
3123 RegisterList args = register_allocator()->NewRegisterList(3);
3125 ->MoveRegister(generator_object(), args[0])
3126 .StoreAccumulatorInRegister(args[1])
3127 .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
3128 .StoreAccumulatorInRegister(args[2])
3129 .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
3133 RegisterAllocationScope register_scope(
this);
3134 RegisterList args = register_allocator()->NewRegisterList(2);
3136 ->StoreAccumulatorInRegister(args[0])
3138 .StoreAccumulatorInRegister(args[1])
3139 .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
3143 BuildSuspendPoint(expr);
3149 if (expr->on_abrupt_resume() == Yield::kNoControl) {
3150 DCHECK(IsAsyncGeneratorFunction(function_kind()));
3154 Register input = register_allocator()->NewRegister();
3155 builder()->StoreAccumulatorInRegister(input).CallRuntime(
3156 Runtime::kInlineGeneratorGetResumeMode, generator_object());
3159 STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
3160 BytecodeJumpTable* jump_table =
3161 builder()->AllocateJumpTable(2, JSGeneratorObject::kNext);
3163 builder()->SwitchOnSmiNoFeedback(jump_table);
3169 builder()->SetExpressionPosition(expr);
3170 builder()->LoadAccumulatorWithRegister(input);
3176 builder()->Bind(jump_table, JSGeneratorObject::kReturn);
3177 builder()->LoadAccumulatorWithRegister(input);
3178 if (IsAsyncGeneratorFunction(function_kind())) {
3179 execution_control()->AsyncReturnAccumulator();
3181 execution_control()->ReturnAccumulator();
3187 builder()->Bind(jump_table, JSGeneratorObject::kNext);
3188 BuildIncrementBlockCoverageCounterIfEnabled(expr,
3189 SourceRangeKind::kContinuation);
3190 builder()->LoadAccumulatorWithRegister(input);
3256 void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
3257 Register output = register_allocator()->NewRegister();
3258 Register resume_mode = register_allocator()->NewRegister();
3259 IteratorType iterator_type = IsAsyncGeneratorFunction(function_kind())
3260 ? IteratorType::kAsync
3261 : IteratorType::kNormal;
3264 RegisterAllocationScope register_scope(
this);
3265 RegisterList iterator_and_input = register_allocator()->NewRegisterList(2);
3266 IteratorRecord iterator = BuildGetIteratorRecord(
3268 register_allocator()->NewRegister() ,
3269 iterator_and_input[0], iterator_type);
3271 Register input = iterator_and_input[1];
3272 builder()->LoadUndefined().StoreAccumulatorInRegister(input);
3274 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
3275 .StoreAccumulatorInRegister(resume_mode);
3290 LoopBuilder loop(builder(),
nullptr,
nullptr);
3294 BytecodeLabels after_switch(zone());
3295 BytecodeJumpTable* switch_jump_table =
3296 builder()->AllocateJumpTable(2, 1);
3299 ->LoadAccumulatorWithRegister(resume_mode)
3300 .SwitchOnSmiNoFeedback(switch_jump_table);
3305 STATIC_ASSERT(JSGeneratorObject::kNext == 0);
3307 FeedbackSlot slot = feedback_spec()->AddCallICSlot();
3308 builder()->CallProperty(iterator.next(), iterator_and_input,
3309 feedback_index(slot));
3310 builder()->Jump(after_switch.New());
3313 STATIC_ASSERT(JSGeneratorObject::kReturn == 1);
3314 builder()->Bind(switch_jump_table, JSGeneratorObject::kReturn);
3316 const AstRawString* return_string =
3317 ast_string_constants()->return_string();
3318 BytecodeLabels no_return_method(zone());
3320 BuildCallIteratorMethod(iterator.object(), return_string,
3321 iterator_and_input, after_switch.New(),
3323 no_return_method.Bind(builder());
3324 builder()->LoadAccumulatorWithRegister(input);
3325 if (iterator_type == IteratorType::kAsync) {
3326 execution_control()->AsyncReturnAccumulator();
3328 execution_control()->ReturnAccumulator();
3332 STATIC_ASSERT(JSGeneratorObject::kThrow == 2);
3333 builder()->Bind(switch_jump_table, JSGeneratorObject::kThrow);
3335 const AstRawString* throw_string =
3336 ast_string_constants()->throw_string();
3337 BytecodeLabels no_throw_method(zone());
3338 BuildCallIteratorMethod(iterator.object(), throw_string,
3339 iterator_and_input, after_switch.New(),
3344 no_throw_method.Bind(builder());
3345 BuildIteratorClose(iterator, expr);
3346 builder()->CallRuntime(Runtime::kThrowThrowMethodMissing);
3349 after_switch.Bind(builder());
3352 if (iterator_type == IteratorType::kAsync) {
3358 BytecodeLabel check_if_done;
3360 ->StoreAccumulatorInRegister(output)
3361 .JumpIfJSReceiver(&check_if_done)
3362 .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, output);
3364 builder()->Bind(&check_if_done);
3366 builder()->LoadNamedProperty(
3367 output, ast_string_constants()->done_string(),
3368 feedback_index(feedback_spec()->AddLoadICSlot()));
3370 loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
3373 if (iterator_type == IteratorType::kNormal) {
3374 builder()->LoadAccumulatorWithRegister(output);
3376 RegisterAllocationScope register_scope(
this);
3377 DCHECK_EQ(iterator_type, IteratorType::kAsync);
3381 builder()->LoadNamedProperty(
3382 output, ast_string_constants()->value_string(),
3383 feedback_index(feedback_spec()->AddLoadICSlot()));
3385 RegisterList args = register_allocator()->NewRegisterList(3);
3387 ->MoveRegister(generator_object(), args[0])
3388 .StoreAccumulatorInRegister(args[1])
3389 .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
3390 .StoreAccumulatorInRegister(args[2])
3391 .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
3394 BuildSuspendPoint(expr);
3395 builder()->StoreAccumulatorInRegister(input);
3397 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
3399 .StoreAccumulatorInRegister(resume_mode);
3401 loop.BindContinueTarget();
3402 loop.JumpToHeader(loop_depth_);
3408 BytecodeLabel completion_is_output_value;
3409 Register output_value = register_allocator()->NewRegister();
3411 ->LoadNamedProperty(output, ast_string_constants()->value_string(),
3412 feedback_index(feedback_spec()->AddLoadICSlot()))
3413 .StoreAccumulatorInRegister(output_value)
3414 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kReturn))
3415 .CompareReference(resume_mode)
3416 .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_output_value)
3417 .LoadAccumulatorWithRegister(output_value);
3418 if (iterator_type == IteratorType::kAsync) {
3419 execution_control()->AsyncReturnAccumulator();
3421 execution_control()->ReturnAccumulator();
3424 builder()->Bind(&completion_is_output_value);
3425 BuildIncrementBlockCoverageCounterIfEnabled(expr,
3426 SourceRangeKind::kContinuation);
3427 builder()->LoadAccumulatorWithRegister(output_value);
3430 void BytecodeGenerator::BuildAwait(Expression* await_expr) {
3437 DCHECK(catch_prediction() != HandlerTable::UNCAUGHT);
3441 RegisterAllocationScope register_scope(
this);
3443 Runtime::FunctionId await_intrinsic_id;
3444 if (IsAsyncGeneratorFunction(function_kind())) {
3445 await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
3446 ? Runtime::kInlineAsyncGeneratorAwaitUncaught
3447 : Runtime::kInlineAsyncGeneratorAwaitCaught;
3449 await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
3450 ? Runtime::kInlineAsyncFunctionAwaitUncaught
3451 : Runtime::kInlineAsyncFunctionAwaitCaught;
3453 RegisterList args = register_allocator()->NewRegisterList(2);
3455 ->MoveRegister(generator_object(), args[0])
3456 .StoreAccumulatorInRegister(args[1])
3457 .CallRuntime(await_intrinsic_id, args);
3460 BuildSuspendPoint(await_expr);
3462 Register input = register_allocator()->NewRegister();
3463 Register resume_mode = register_allocator()->NewRegister();
3466 BytecodeLabel resume_next;
3468 ->StoreAccumulatorInRegister(input)
3469 .CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator_object())
3470 .StoreAccumulatorInRegister(resume_mode)
3471 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
3472 .CompareReference(resume_mode)
3473 .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_next);
3478 builder()->LoadAccumulatorWithRegister(input).ReThrow();
3481 builder()->Bind(&resume_next);
3482 builder()->LoadAccumulatorWithRegister(input);
3485 void BytecodeGenerator::VisitAwait(Await* expr) {
3486 builder()->SetExpressionPosition(expr);
3487 VisitForAccumulatorValue(expr->expression());
3489 BuildIncrementBlockCoverageCounterIfEnabled(expr,
3490 SourceRangeKind::kContinuation);
3493 void BytecodeGenerator::VisitThrow(Throw* expr) {
3494 AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kContinuation);
3495 VisitForAccumulatorValue(expr->exception());
3496 builder()->SetExpressionPosition(expr);
3500 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
3501 LhsKind property_kind = Property::GetAssignType(property);
3502 switch (property_kind) {
3505 case NAMED_PROPERTY: {
3506 builder()->SetExpressionPosition(property);
3507 const AstRawString* name =
3508 property->key()->AsLiteral()->AsRawPropertyName();
3509 BuildLoadNamedProperty(property, obj, name);
3512 case KEYED_PROPERTY: {
3513 VisitForAccumulatorValue(property->key());
3514 builder()->SetExpressionPosition(property);
3515 builder()->LoadKeyedProperty(
3516 obj, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
3519 case NAMED_SUPER_PROPERTY:
3520 VisitNamedSuperPropertyLoad(property, Register::invalid_value());
3522 case KEYED_SUPER_PROPERTY:
3523 VisitKeyedSuperPropertyLoad(property, Register::invalid_value());
3528 void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
3530 Register destination) {
3531 ValueResultScope result_scope(
this);
3532 VisitPropertyLoad(obj, expr);
3533 builder()->StoreAccumulatorInRegister(destination);
3536 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
3537 Register opt_receiver_out) {
3538 RegisterAllocationScope register_scope(
this);
3539 SuperPropertyReference* super_property =
3540 property->obj()->AsSuperPropertyReference();
3541 RegisterList args = register_allocator()->NewRegisterList(3);
3542 VisitForRegisterValue(super_property->this_var(), args[0]);
3543 VisitForRegisterValue(super_property->home_object(), args[1]);
3545 builder()->SetExpressionPosition(property);
3547 ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
3548 .StoreAccumulatorInRegister(args[2])
3549 .CallRuntime(Runtime::kLoadFromSuper, args);
3551 if (opt_receiver_out.is_valid()) {
3552 builder()->MoveRegister(args[0], opt_receiver_out);
3556 void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
3557 Register opt_receiver_out) {
3558 RegisterAllocationScope register_scope(
this);
3559 SuperPropertyReference* super_property =
3560 property->obj()->AsSuperPropertyReference();
3561 RegisterList args = register_allocator()->NewRegisterList(3);
3562 VisitForRegisterValue(super_property->this_var(), args[0]);
3563 VisitForRegisterValue(super_property->home_object(), args[1]);
3564 VisitForRegisterValue(property->key(), args[2]);
3566 builder()->SetExpressionPosition(property);
3567 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args);
3569 if (opt_receiver_out.is_valid()) {
3570 builder()->MoveRegister(args[0], opt_receiver_out);
3574 void BytecodeGenerator::VisitProperty(Property* expr) {
3575 LhsKind property_kind = Property::GetAssignType(expr);
3576 if (property_kind != NAMED_SUPER_PROPERTY &&
3577 property_kind != KEYED_SUPER_PROPERTY) {
3578 Register obj = VisitForRegisterValue(expr->obj());
3579 VisitPropertyLoad(obj, expr);
3581 VisitPropertyLoad(Register::invalid_value(), expr);
3585 void BytecodeGenerator::VisitResolvedProperty(ResolvedProperty* expr) {
3590 void BytecodeGenerator::VisitArguments(
const ZonePtrList<Expression>* args,
3591 RegisterList* arg_regs) {
3593 for (
int i = 0; i < static_cast<int>(args->length());
i++) {
3594 VisitAndPushIntoRegisterList(args->at(
i), arg_regs);
3598 void BytecodeGenerator::VisitCall(Call* expr) {
3599 Expression* callee_expr = expr->expression();
3600 Call::CallType call_type = expr->GetCallType();
3602 if (call_type == Call::SUPER_CALL) {
3603 return VisitCallSuper(expr);
3610 Register callee = register_allocator()->NewRegister();
3611 RegisterList args = register_allocator()->NewGrowableRegisterList();
3613 bool implicit_undefined_receiver =
false;
3616 bool is_spread_call = expr->only_last_arg_is_spread();
3617 bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
3625 switch (call_type) {
3626 case Call::NAMED_PROPERTY_CALL:
3627 case Call::KEYED_PROPERTY_CALL: {
3628 Property*
property = callee_expr->AsProperty();
3629 VisitAndPushIntoRegisterList(property->obj(), &args);
3630 VisitPropertyLoadForRegister(args.last_register(), property, callee);
3633 case Call::RESOLVED_PROPERTY_CALL: {
3634 ResolvedProperty* resolved = callee_expr->AsResolvedProperty();
3635 VisitAndPushIntoRegisterList(resolved->object(), &args);
3636 VisitForAccumulatorValue(resolved->property());
3637 builder()->StoreAccumulatorInRegister(callee);
3640 case Call::GLOBAL_CALL: {
3642 if (!is_spread_call && !optimize_as_one_shot) {
3643 implicit_undefined_receiver =
true;
3647 BuildPushUndefinedIntoRegisterList(&args);
3650 VariableProxy* proxy = callee_expr->AsVariableProxy();
3651 BuildVariableLoadForAccumulatorValue(proxy->var(),
3652 proxy->hole_check_mode());
3653 builder()->StoreAccumulatorInRegister(callee);
3656 case Call::WITH_CALL: {
3657 Register receiver = register_allocator()->GrowRegisterList(&args);
3658 DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
3660 RegisterAllocationScope inner_register_scope(
this);
3661 Register name = register_allocator()->NewRegister();
3664 RegisterList result_pair = register_allocator()->NewRegisterList(2);
3665 Variable* variable = callee_expr->AsVariableProxy()->var();
3667 ->LoadLiteral(variable->raw_name())
3668 .StoreAccumulatorInRegister(name)
3669 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
3671 .MoveRegister(result_pair[0], callee)
3672 .MoveRegister(result_pair[1], receiver);
3676 case Call::OTHER_CALL: {
3678 if (!is_spread_call && !optimize_as_one_shot) {
3679 implicit_undefined_receiver =
true;
3683 BuildPushUndefinedIntoRegisterList(&args);
3685 VisitForRegisterValue(callee_expr, callee);
3688 case Call::NAMED_SUPER_PROPERTY_CALL: {
3689 Register receiver = register_allocator()->GrowRegisterList(&args);
3690 Property*
property = callee_expr->AsProperty();
3691 VisitNamedSuperPropertyLoad(property, receiver);
3692 builder()->StoreAccumulatorInRegister(callee);
3695 case Call::KEYED_SUPER_PROPERTY_CALL: {
3696 Register receiver = register_allocator()->GrowRegisterList(&args);
3697 Property*
property = callee_expr->AsProperty();
3698 VisitKeyedSuperPropertyLoad(property, receiver);
3699 builder()->StoreAccumulatorInRegister(callee);
3702 case Call::SUPER_CALL:
3709 VisitArguments(expr->arguments(), &args);
3710 int reciever_arg_count = implicit_undefined_receiver ? 0 : 1;
3711 CHECK_EQ(reciever_arg_count + expr->arguments()->length(),
3712 args.register_count());
3716 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
3717 RegisterAllocationScope inner_register_scope(
this);
3721 Register first_arg = args[reciever_arg_count];
3722 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
3724 ->MoveRegister(callee, runtime_call_args[0])
3725 .MoveRegister(first_arg, runtime_call_args[1])
3726 .MoveRegister(Register::function_closure(), runtime_call_args[2])
3727 .LoadLiteral(Smi::FromEnum(language_mode()))
3728 .StoreAccumulatorInRegister(runtime_call_args[3])
3729 .LoadLiteral(Smi::FromInt(current_scope()->start_position()))
3730 .StoreAccumulatorInRegister(runtime_call_args[4])
3731 .LoadLiteral(Smi::FromInt(expr->position()))
3732 .StoreAccumulatorInRegister(runtime_call_args[5]);
3736 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args)
3737 .StoreAccumulatorInRegister(callee);
3740 builder()->SetExpressionPosition(expr);
3742 if (is_spread_call) {
3743 DCHECK(!implicit_undefined_receiver);
3744 builder()->CallWithSpread(callee, args,
3745 feedback_index(feedback_spec()->AddCallICSlot()));
3746 }
else if (optimize_as_one_shot) {
3747 DCHECK(!implicit_undefined_receiver);
3748 builder()->CallNoFeedback(callee, args);
3749 }
else if (call_type == Call::NAMED_PROPERTY_CALL ||
3750 call_type == Call::KEYED_PROPERTY_CALL ||
3751 call_type == Call::RESOLVED_PROPERTY_CALL) {
3752 DCHECK(!implicit_undefined_receiver);
3753 builder()->CallProperty(callee, args,
3754 feedback_index(feedback_spec()->AddCallICSlot()));
3755 }
else if (implicit_undefined_receiver) {
3756 builder()->CallUndefinedReceiver(
3757 callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
3759 builder()->CallAnyReceiver(
3760 callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
3764 void BytecodeGenerator::VisitCallSuper(Call* expr) {
3765 RegisterAllocationScope register_scope(
this);
3766 SuperCallReference* super = expr->expression()->AsSuperCallReference();
3767 const ZonePtrList<Expression>* args = expr->arguments();
3769 int first_spread_index = 0;
3770 for (; first_spread_index < args->length(); first_spread_index++) {
3771 if (args->at(first_spread_index)->IsSpread())
break;
3775 Register this_function = VisitForRegisterValue(super->this_function_var());
3776 Register constructor = register_allocator()->NewRegister();
3778 ->LoadAccumulatorWithRegister(this_function)
3779 .GetSuperConstructor(constructor);
3781 if (first_spread_index < expr->arguments()->length() - 1) {
3790 BuildCreateArrayLiteral(args,
nullptr);
3793 RegisterList construct_args = register_allocator()->NewRegisterList(3);
3794 builder()->StoreAccumulatorInRegister(construct_args[1]);
3795 builder()->MoveRegister(constructor, construct_args[0]);
3796 VisitForRegisterValue(super->new_target_var(), construct_args[2]);
3797 builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
3799 RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
3800 VisitArguments(args, &args_regs);
3803 VisitForAccumulatorValue(super->new_target_var());
3804 builder()->SetExpressionPosition(expr);
3806 int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
3808 if (first_spread_index == expr->arguments()->length() - 1) {
3809 builder()->ConstructWithSpread(constructor, args_regs,
3810 feedback_slot_index);
3812 DCHECK_EQ(first_spread_index, expr->arguments()->length());
3820 builder()->Construct(constructor, args_regs, feedback_slot_index);
3829 if (!IsDefaultConstructor(info()->literal()->kind())) {
3830 BuildVariableAssignment(super->this_var()->var(), Token::INIT,
3831 HoleCheckMode::kRequired);
3844 if (info()->literal()->requires_instance_members_initializer() ||
3845 !IsDerivedConstructor(info()->literal()->kind())) {
3846 Register instance = register_allocator()->NewRegister();
3847 builder()->StoreAccumulatorInRegister(instance);
3848 BuildInstanceMemberInitialization(this_function, instance);
3849 builder()->LoadAccumulatorWithRegister(instance);
3853 void BytecodeGenerator::VisitCallNew(CallNew* expr) {
3854 Register constructor = VisitForRegisterValue(expr->expression());
3855 RegisterList args = register_allocator()->NewGrowableRegisterList();
3856 VisitArguments(expr->arguments(), &args);
3860 builder()->SetExpressionPosition(expr);
3861 builder()->LoadAccumulatorWithRegister(constructor);
3863 int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
3864 if (expr->only_last_arg_is_spread()) {
3865 builder()->ConstructWithSpread(constructor, args, feedback_slot_index);
3867 builder()->Construct(constructor, args, feedback_slot_index);
3871 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3872 if (expr->is_jsruntime()) {
3873 RegisterList args = register_allocator()->NewGrowableRegisterList();
3874 VisitArguments(expr->arguments(), &args);
3875 builder()->CallJSRuntime(expr->context_index(), args);
3878 RegisterList args = register_allocator()->NewGrowableRegisterList();
3879 VisitArguments(expr->arguments(), &args);
3880 Runtime::FunctionId function_id = expr->function()->function_id;
3881 builder()->CallRuntime(function_id, args);
3885 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
3886 VisitForEffect(expr->expression());
3887 builder()->LoadUndefined();
3890 void BytecodeGenerator::VisitForTypeOfValue(Expression* expr) {
3891 if (expr->IsVariableProxy()) {
3894 VariableProxy* proxy = expr->AsVariableProxy();
3895 BuildVariableLoadForAccumulatorValue(proxy->var(), proxy->hole_check_mode(),
3898 VisitForAccumulatorValue(expr);
3902 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
3903 VisitForTypeOfValue(expr->expression());
3904 builder()->TypeOf();
3907 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
3908 if (execution_result()->IsEffect()) {
3909 VisitForEffect(expr->expression());
3910 }
else if (execution_result()->IsTest()) {
3914 TestResultScope* test_result = execution_result()->AsTest();
3915 test_result->InvertControlFlow();
3916 VisitInSameTestExecutionScope(expr->expression());
3918 TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
3919 builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
3921 execution_result()->SetResultIsBoolean();
3925 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3926 switch (expr->op()) {
3927 case Token::Value::NOT:
3930 case Token::Value::TYPEOF:
3933 case Token::Value::VOID:
3936 case Token::Value::DELETE:
3939 case Token::Value::ADD:
3940 case Token::Value::SUB:
3941 case Token::Value::BIT_NOT:
3942 VisitForAccumulatorValue(expr->expression());
3943 builder()->SetExpressionPosition(expr);
3944 builder()->UnaryOperation(
3945 expr->op(), feedback_index(feedback_spec()->AddBinaryOpICSlot()));
3952 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
3953 if (expr->expression()->IsProperty()) {
3956 Property*
property = expr->expression()->AsProperty();
3957 Register
object = VisitForRegisterValue(property->obj());
3958 VisitForAccumulatorValue(property->key());
3959 builder()->Delete(
object, language_mode());
3960 }
else if (expr->expression()->IsVariableProxy()) {
3964 VariableProxy* proxy = expr->expression()->AsVariableProxy();
3965 DCHECK(is_sloppy(language_mode()) || proxy->is_this() ||
3966 proxy->is_new_target());
3967 if (proxy->is_this() || proxy->is_new_target()) {
3968 builder()->LoadTrue();
3970 Variable* variable = proxy->var();
3971 switch (variable->location()) {
3972 case VariableLocation::PARAMETER:
3973 case VariableLocation::LOCAL:
3974 case VariableLocation::CONTEXT: {
3977 builder()->LoadFalse();
3980 case VariableLocation::UNALLOCATED:
3987 case VariableLocation::LOOKUP: {
3988 Register name_reg = register_allocator()->NewRegister();
3990 ->LoadLiteral(variable->raw_name())
3991 .StoreAccumulatorInRegister(name_reg)
3992 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg);
4001 VisitForEffect(expr->expression());
4002 builder()->LoadTrue();
4006 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
4007 DCHECK(expr->expression()->IsValidReferenceExpression());
4010 Property*
property = expr->expression()->AsProperty();
4011 LhsKind assign_type = Property::GetAssignType(property);
4013 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect();
4016 Register object, key, old_value;
4017 RegisterList super_property_args;
4018 const AstRawString* name;
4019 switch (assign_type) {
4021 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4022 BuildVariableLoadForAccumulatorValue(proxy->var(),
4023 proxy->hole_check_mode());
4026 case NAMED_PROPERTY: {
4027 object = VisitForRegisterValue(property->obj());
4028 name =
property->key()->AsLiteral()->AsRawPropertyName();
4029 builder()->LoadNamedProperty(
4031 feedback_index(GetCachedLoadICSlot(property->obj(), name)));
4034 case KEYED_PROPERTY: {
4035 object = VisitForRegisterValue(property->obj());
4038 key = register_allocator()->NewRegister();
4039 VisitForAccumulatorValue(property->key());
4040 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
4041 object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
4044 case NAMED_SUPER_PROPERTY: {
4045 super_property_args = register_allocator()->NewRegisterList(4);
4046 RegisterList load_super_args = super_property_args.Truncate(3);
4047 SuperPropertyReference* super_property =
4048 property->obj()->AsSuperPropertyReference();
4049 VisitForRegisterValue(super_property->this_var(), load_super_args[0]);
4050 VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
4052 ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
4053 .StoreAccumulatorInRegister(load_super_args[2])
4054 .CallRuntime(Runtime::kLoadFromSuper, load_super_args);
4057 case KEYED_SUPER_PROPERTY: {
4058 super_property_args = register_allocator()->NewRegisterList(4);
4059 RegisterList load_super_args = super_property_args.Truncate(3);
4060 SuperPropertyReference* super_property =
4061 property->obj()->AsSuperPropertyReference();
4062 VisitForRegisterValue(super_property->this_var(), load_super_args[0]);
4063 VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
4064 VisitForRegisterValue(property->key(), load_super_args[2]);
4065 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args);
4071 FeedbackSlot count_slot = feedback_spec()->AddBinaryOpICSlot();
4073 old_value = register_allocator()->NewRegister();
4078 ->ToNumeric(feedback_index(count_slot))
4079 .StoreAccumulatorInRegister(old_value);
4083 builder()->UnaryOperation(expr->op(), feedback_index(count_slot));
4086 builder()->SetExpressionPosition(expr);
4087 switch (assign_type) {
4089 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4090 BuildVariableAssignment(proxy->var(), expr->op(),
4091 proxy->hole_check_mode());
4094 case NAMED_PROPERTY: {
4095 FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
4097 if (!execution_result()->IsEffect()) {
4098 value = register_allocator()->NewRegister();
4099 builder()->StoreAccumulatorInRegister(value);
4101 builder()->StoreNamedProperty(
object, name, feedback_index(slot),
4103 if (!execution_result()->IsEffect()) {
4104 builder()->LoadAccumulatorWithRegister(value);
4108 case KEYED_PROPERTY: {
4109 FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
4111 if (!execution_result()->IsEffect()) {
4112 value = register_allocator()->NewRegister();
4113 builder()->StoreAccumulatorInRegister(value);
4115 builder()->StoreKeyedProperty(
object, key, feedback_index(slot),
4117 if (!execution_result()->IsEffect()) {
4118 builder()->LoadAccumulatorWithRegister(value);
4122 case NAMED_SUPER_PROPERTY: {
4124 ->StoreAccumulatorInRegister(super_property_args[3])
4125 .CallRuntime(StoreToSuperRuntimeId(), super_property_args);
4128 case KEYED_SUPER_PROPERTY: {
4130 ->StoreAccumulatorInRegister(super_property_args[3])
4131 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
4138 builder()->LoadAccumulatorWithRegister(old_value);
4142 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
4143 switch (binop->op()) {
4145 VisitCommaExpression(binop);
4148 VisitLogicalOrExpression(binop);
4151 VisitLogicalAndExpression(binop);
4154 VisitArithmeticExpression(binop);
4159 void BytecodeGenerator::VisitNaryOperation(NaryOperation* expr) {
4160 switch (expr->op()) {
4162 VisitNaryCommaExpression(expr);
4165 VisitNaryLogicalOrExpression(expr);
4168 VisitNaryLogicalAndExpression(expr);
4171 VisitNaryArithmeticExpression(expr);
4176 void BytecodeGenerator::BuildLiteralCompareNil(
4177 Token::Value op, BytecodeArrayBuilder::NilValue nil) {
4178 if (execution_result()->IsTest()) {
4179 TestResultScope* test_result = execution_result()->AsTest();
4180 switch (test_result->fallthrough()) {
4181 case TestFallthrough::kThen:
4182 builder()->JumpIfNotNil(test_result->NewElseLabel(), op, nil);
4184 case TestFallthrough::kElse:
4185 builder()->JumpIfNil(test_result->NewThenLabel(), op, nil);
4187 case TestFallthrough::kNone:
4189 ->JumpIfNil(test_result->NewThenLabel(), op, nil)
4190 .Jump(test_result->NewElseLabel());
4192 test_result->SetResultConsumedByTest();
4194 builder()->CompareNil(op, nil);
4198 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4199 Expression* sub_expr;
4201 if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
4204 VisitForTypeOfValue(sub_expr);
4205 builder()->SetExpressionPosition(expr);
4206 TestTypeOfFlags::LiteralFlag literal_flag =
4207 TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
4208 if (literal_flag == TestTypeOfFlags::LiteralFlag::kOther) {
4209 builder()->LoadFalse();
4211 builder()->CompareTypeOf(literal_flag);
4213 }
else if (expr->IsLiteralCompareUndefined(&sub_expr)) {
4214 VisitForAccumulatorValue(sub_expr);
4215 builder()->SetExpressionPosition(expr);
4216 BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kUndefinedValue);
4217 }
else if (expr->IsLiteralCompareNull(&sub_expr)) {
4218 VisitForAccumulatorValue(sub_expr);
4219 builder()->SetExpressionPosition(expr);
4220 BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kNullValue);
4222 Register lhs = VisitForRegisterValue(expr->left());
4223 VisitForAccumulatorValue(expr->right());
4224 builder()->SetExpressionPosition(expr);
4225 if (expr->op() == Token::IN) {
4226 builder()->CompareOperation(expr->op(), lhs);
4227 }
else if (expr->op() == Token::INSTANCEOF) {
4228 FeedbackSlot slot = feedback_spec()->AddInstanceOfSlot();
4229 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
4231 FeedbackSlot slot = feedback_spec()->AddCompareICSlot();
4232 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
4236 execution_result()->SetResultIsBoolean();
4239 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
4240 FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
4241 Expression* subexpr;
4243 if (expr->IsSmiLiteralOperation(&subexpr, &literal)) {
4244 TypeHint type_hint = VisitForAccumulatorValue(subexpr);
4245 builder()->SetExpressionPosition(expr);
4246 builder()->BinaryOperationSmiLiteral(expr->op(), literal,
4247 feedback_index(slot));
4248 if (expr->op() == Token::ADD && type_hint == TypeHint::kString) {
4249 execution_result()->SetResultIsString();
4252 TypeHint lhs_type = VisitForAccumulatorValue(expr->left());
4253 Register lhs = register_allocator()->NewRegister();
4254 builder()->StoreAccumulatorInRegister(lhs);
4255 TypeHint rhs_type = VisitForAccumulatorValue(expr->right());
4256 if (expr->op() == Token::ADD &&
4257 (lhs_type == TypeHint::kString || rhs_type == TypeHint::kString)) {
4258 execution_result()->SetResultIsString();
4261 builder()->SetExpressionPosition(expr);
4262 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
4266 void BytecodeGenerator::VisitNaryArithmeticExpression(NaryOperation* expr) {
4268 TypeHint type_hint = VisitForAccumulatorValue(expr->first());
4270 for (
size_t i = 0;
i < expr->subsequent_length(); ++
i) {
4271 RegisterAllocationScope register_scope(
this);
4272 if (expr->subsequent(
i)->IsSmiLiteral()) {
4273 builder()->SetExpressionPosition(expr->subsequent_op_position(
i));
4274 builder()->BinaryOperationSmiLiteral(
4275 expr->op(), expr->subsequent(
i)->AsLiteral()->AsSmiLiteral(),
4276 feedback_index(feedback_spec()->AddBinaryOpICSlot()));
4278 Register lhs = register_allocator()->NewRegister();
4279 builder()->StoreAccumulatorInRegister(lhs);
4280 TypeHint rhs_hint = VisitForAccumulatorValue(expr->subsequent(
i));
4281 if (rhs_hint == TypeHint::kString) type_hint = TypeHint::kString;
4282 builder()->SetExpressionPosition(expr->subsequent_op_position(
i));
4283 builder()->BinaryOperation(
4285 feedback_index(feedback_spec()->AddBinaryOpICSlot()));
4289 if (type_hint == TypeHint::kString && expr->op() == Token::ADD) {
4291 execution_result()->SetResultIsString();
4297 void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); }
4299 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
4303 void BytecodeGenerator::VisitImportCallExpression(ImportCallExpression* expr) {
4304 RegisterList args = register_allocator()->NewRegisterList(2);
4305 VisitForRegisterValue(expr->argument(), args[1]);
4307 ->MoveRegister(Register::function_closure(), args[0])
4308 .CallRuntime(Runtime::kDynamicImportCall, args);
4311 void BytecodeGenerator::BuildGetIterator(Expression* iterable,
4312 IteratorType hint) {
4313 RegisterList args = register_allocator()->NewRegisterList(1);
4314 Register method = register_allocator()->NewRegister();
4315 Register obj = args[0];
4317 VisitForAccumulatorValue(iterable);
4319 if (hint == IteratorType::kAsync) {
4321 builder()->StoreAccumulatorInRegister(obj).LoadAsyncIteratorProperty(
4322 obj, feedback_index(feedback_spec()->AddLoadICSlot()));
4324 BytecodeLabel async_iterator_undefined, async_iterator_null, done;
4326 builder()->JumpIfUndefined(&async_iterator_undefined);
4327 builder()->JumpIfNull(&async_iterator_null);
4330 builder()->StoreAccumulatorInRegister(method).CallProperty(
4331 method, args, feedback_index(feedback_spec()->AddCallICSlot()));
4334 builder()->JumpIfJSReceiver(&done);
4335 builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid);
4337 builder()->Bind(&async_iterator_undefined);
4338 builder()->Bind(&async_iterator_null);
4342 ->LoadIteratorProperty(obj,
4343 feedback_index(feedback_spec()->AddLoadICSlot()))
4344 .StoreAccumulatorInRegister(method);
4347 builder()->CallProperty(method, args,
4348 feedback_index(feedback_spec()->AddCallICSlot()));
4352 Register sync_iter = method;
4353 builder()->StoreAccumulatorInRegister(sync_iter).CallRuntime(
4354 Runtime::kInlineCreateAsyncFromSyncIterator, sync_iter);
4356 builder()->Bind(&done);
4360 ->StoreAccumulatorInRegister(obj)
4361 .LoadIteratorProperty(obj,
4362 feedback_index(feedback_spec()->AddLoadICSlot()))
4363 .StoreAccumulatorInRegister(method);
4366 builder()->CallProperty(method, args,
4367 feedback_index(feedback_spec()->AddCallICSlot()));
4370 BytecodeLabel no_type_error;
4371 builder()->JumpIfJSReceiver(&no_type_error);
4372 builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
4373 builder()->Bind(&no_type_error);
4379 BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
4380 Expression* iterable, Register next, Register
object, IteratorType hint) {
4381 DCHECK(next.is_valid() &&
object.is_valid());
4382 BuildGetIterator(iterable, hint);
4385 ->StoreAccumulatorInRegister(
object)
4386 .LoadNamedProperty(
object, ast_string_constants()->next_string(),
4387 feedback_index(feedback_spec()->AddLoadICSlot()))
4388 .StoreAccumulatorInRegister(next);
4389 return IteratorRecord(
object, next, hint);
4392 BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
4393 Expression* iterable, IteratorType hint) {
4394 Register next = register_allocator()->NewRegister();
4395 Register
object = register_allocator()->NewRegister();
4396 return BuildGetIteratorRecord(iterable, next,
object, hint);
4399 void BytecodeGenerator::BuildIteratorNext(
const IteratorRecord& iterator,
4400 Register next_result) {
4401 DCHECK(next_result.is_valid());
4402 builder()->CallProperty(iterator.next(), RegisterList(iterator.object()),
4403 feedback_index(feedback_spec()->AddCallICSlot()));
4407 BytecodeLabel is_object;
4409 ->StoreAccumulatorInRegister(next_result)
4410 .JumpIfJSReceiver(&is_object)
4411 .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, next_result)
4415 void BytecodeGenerator::BuildCallIteratorMethod(Register iterator,
4416 const AstRawString* method_name,
4417 RegisterList receiver_and_args,
4418 BytecodeLabel* if_called,
4419 BytecodeLabels* if_notcalled) {
4420 RegisterAllocationScope register_scope(
this);
4422 Register method = register_allocator()->NewRegister();
4423 FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
4425 ->LoadNamedProperty(iterator, method_name, feedback_index(slot))
4426 .JumpIfUndefined(if_notcalled->New())
4427 .JumpIfNull(if_notcalled->New())
4428 .StoreAccumulatorInRegister(method)
4429 .CallProperty(method, receiver_and_args,
4430 feedback_index(feedback_spec()->AddCallICSlot()))
4434 void BytecodeGenerator::BuildIteratorClose(
const IteratorRecord& iterator,
4436 RegisterAllocationScope register_scope(
this);
4437 BytecodeLabels done(zone());
4438 BytecodeLabel if_called;
4439 RegisterList args = RegisterList(iterator.object());
4440 BuildCallIteratorMethod(iterator.object(),
4441 ast_string_constants()->return_string(), args,
4443 builder()->Bind(&if_called);
4445 if (iterator.type() == IteratorType::kAsync) {
4446 DCHECK_NOT_NULL(expr);
4450 builder()->JumpIfJSReceiver(done.New());
4452 RegisterAllocationScope register_scope(
this);
4453 Register return_result = register_allocator()->NewRegister();
4455 ->StoreAccumulatorInRegister(return_result)
4456 .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, return_result);
4459 done.Bind(builder());
4462 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
4463 builder()->SetExpressionPosition(expr);
4464 BuildGetIterator(expr->iterable(), expr->hint());
4467 void BytecodeGenerator::VisitGetTemplateObject(GetTemplateObject* expr) {
4468 builder()->SetExpressionPosition(expr);
4469 size_t entry = builder()->AllocateDeferredConstantPoolEntry();
4470 template_objects_.push_back(std::make_pair(expr, entry));
4471 FeedbackSlot literal_slot = feedback_spec()->AddLiteralSlot();
4472 builder()->GetTemplateObject(entry, feedback_index(literal_slot));
4475 void BytecodeGenerator::VisitTemplateLiteral(TemplateLiteral* expr) {
4476 const ZonePtrList<const AstRawString>& parts = *expr->string_parts();
4477 const ZonePtrList<Expression>& substitutions = *expr->substitutions();
4479 DCHECK_GT(substitutions.length(), 0);
4480 DCHECK_EQ(parts.length(), substitutions.length() + 1);
4485 FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
4486 Register last_part = register_allocator()->NewRegister();
4487 bool last_part_valid =
false;
4489 builder()->SetExpressionPosition(expr);
4490 for (
int i = 0;
i < substitutions.length(); ++
i) {
4492 builder()->StoreAccumulatorInRegister(last_part);
4493 last_part_valid =
true;
4496 if (!parts[
i]->IsEmpty()) {
4497 builder()->LoadLiteral(parts[
i]);
4498 if (last_part_valid) {
4499 builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
4501 builder()->StoreAccumulatorInRegister(last_part);
4502 last_part_valid =
true;
4505 TypeHint type_hint = VisitForAccumulatorValue(substitutions[
i]);
4506 if (type_hint != TypeHint::kString) {
4507 builder()->ToString();
4509 if (last_part_valid) {
4510 builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
4512 last_part_valid =
false;
4515 if (!parts.last()->IsEmpty()) {
4516 builder()->StoreAccumulatorInRegister(last_part);
4517 builder()->LoadLiteral(parts.last());
4518 builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
4522 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
4523 builder()->LoadAccumulatorWithRegister(Register::function_closure());
4526 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
4531 void BytecodeGenerator::VisitSuperPropertyReference(
4532 SuperPropertyReference* expr) {
4533 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
4536 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
4537 VisitForEffect(binop->left());
4538 Visit(binop->right());
4541 void BytecodeGenerator::VisitNaryCommaExpression(NaryOperation* expr) {
4542 DCHECK_GT(expr->subsequent_length(), 0);
4544 VisitForEffect(expr->first());
4545 for (
size_t i = 0;
i < expr->subsequent_length() - 1; ++
i) {
4546 VisitForEffect(expr->subsequent(
i));
4548 Visit(expr->subsequent(expr->subsequent_length() - 1));
4551 void BytecodeGenerator::VisitLogicalTestSubExpression(
4552 Token::Value token, Expression* expr, BytecodeLabels* then_labels,
4553 BytecodeLabels* else_labels,
int coverage_slot) {
4554 DCHECK(token == Token::OR || token == Token::AND);
4556 BytecodeLabels test_next(zone());
4557 if (token == Token::OR) {
4558 VisitForTest(expr, then_labels, &test_next, TestFallthrough::kElse);
4560 DCHECK_EQ(Token::AND, token);
4561 VisitForTest(expr, &test_next, else_labels, TestFallthrough::kThen);
4563 test_next.Bind(builder());
4565 BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
4568 void BytecodeGenerator::VisitLogicalTest(Token::Value token, Expression* left,
4570 int right_coverage_slot) {
4571 DCHECK(token == Token::OR || token == Token::AND);
4572 TestResultScope* test_result = execution_result()->AsTest();
4573 BytecodeLabels* then_labels = test_result->then_labels();
4574 BytecodeLabels* else_labels = test_result->else_labels();
4575 TestFallthrough fallthrough = test_result->fallthrough();
4577 VisitLogicalTestSubExpression(token, left, then_labels, else_labels,
4578 right_coverage_slot);
4580 VisitForTest(right, then_labels, else_labels, fallthrough);
4583 void BytecodeGenerator::VisitNaryLogicalTest(
4584 Token::Value token, NaryOperation* expr,
4585 const NaryCodeCoverageSlots* coverage_slots) {
4586 DCHECK(token == Token::OR || token == Token::AND);
4587 DCHECK_GT(expr->subsequent_length(), 0);
4589 TestResultScope* test_result = execution_result()->AsTest();
4590 BytecodeLabels* then_labels = test_result->then_labels();
4591 BytecodeLabels* else_labels = test_result->else_labels();
4592 TestFallthrough fallthrough = test_result->fallthrough();
4594 VisitLogicalTestSubExpression(token, expr->first(), then_labels, else_labels,
4595 coverage_slots->GetSlotFor(0));
4596 for (
size_t i = 0;
i < expr->subsequent_length() - 1; ++
i) {
4597 VisitLogicalTestSubExpression(token, expr->subsequent(
i), then_labels,
4599 coverage_slots->GetSlotFor(
i + 1));
4602 VisitForTest(expr->subsequent(expr->subsequent_length() - 1), then_labels,
4603 else_labels, fallthrough);
4606 bool BytecodeGenerator::VisitLogicalOrSubExpression(Expression* expr,
4607 BytecodeLabels* end_labels,
4608 int coverage_slot) {
4609 if (expr->ToBooleanIsTrue()) {
4610 VisitForAccumulatorValue(expr);
4611 end_labels->Bind(builder());
4613 }
else if (!expr->ToBooleanIsFalse()) {
4614 TypeHint type_hint = VisitForAccumulatorValue(expr);
4615 builder()->JumpIfTrue(ToBooleanModeFromTypeHint(type_hint),
4619 BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
4624 bool BytecodeGenerator::VisitLogicalAndSubExpression(Expression* expr,
4625 BytecodeLabels* end_labels,
4626 int coverage_slot) {
4627 if (expr->ToBooleanIsFalse()) {
4628 VisitForAccumulatorValue(expr);
4629 end_labels->Bind(builder());
4631 }
else if (!expr->ToBooleanIsTrue()) {
4632 TypeHint type_hint = VisitForAccumulatorValue(expr);
4633 builder()->JumpIfFalse(ToBooleanModeFromTypeHint(type_hint),
4637 BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
4642 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
4643 Expression* left = binop->left();
4644 Expression* right = binop->right();
4646 int right_coverage_slot =
4647 AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
4649 if (execution_result()->IsTest()) {
4650 TestResultScope* test_result = execution_result()->AsTest();
4651 if (left->ToBooleanIsTrue()) {
4652 builder()->Jump(test_result->NewThenLabel());
4653 }
else if (left->ToBooleanIsFalse() && right->ToBooleanIsFalse()) {
4654 BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
4655 builder()->Jump(test_result->NewElseLabel());
4657 VisitLogicalTest(Token::OR, left, right, right_coverage_slot);
4659 test_result->SetResultConsumedByTest();
4661 BytecodeLabels end_labels(zone());
4662 if (VisitLogicalOrSubExpression(left, &end_labels, right_coverage_slot)) {
4665 VisitForAccumulatorValue(right);
4666 end_labels.Bind(builder());
4670 void BytecodeGenerator::VisitNaryLogicalOrExpression(NaryOperation* expr) {
4671 Expression* first = expr->first();
4672 DCHECK_GT(expr->subsequent_length(), 0);
4674 NaryCodeCoverageSlots coverage_slots(
this, expr);
4676 if (execution_result()->IsTest()) {
4677 TestResultScope* test_result = execution_result()->AsTest();
4678 if (first->ToBooleanIsTrue()) {
4679 builder()->Jump(test_result->NewThenLabel());
4681 VisitNaryLogicalTest(Token::OR, expr, &coverage_slots);
4683 test_result->SetResultConsumedByTest();
4685 BytecodeLabels end_labels(zone());
4686 if (VisitLogicalOrSubExpression(first, &end_labels,
4687 coverage_slots.GetSlotFor(0))) {
4690 for (
size_t i = 0;
i < expr->subsequent_length() - 1; ++
i) {
4691 if (VisitLogicalOrSubExpression(expr->subsequent(
i), &end_labels,
4692 coverage_slots.GetSlotFor(
i + 1))) {
4698 VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
4699 end_labels.Bind(builder());
4703 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
4704 Expression* left = binop->left();
4705 Expression* right = binop->right();
4707 int right_coverage_slot =
4708 AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
4710 if (execution_result()->IsTest()) {
4711 TestResultScope* test_result = execution_result()->AsTest();
4712 if (left->ToBooleanIsFalse()) {
4713 builder()->Jump(test_result->NewElseLabel());
4714 }
else if (left->ToBooleanIsTrue() && right->ToBooleanIsTrue()) {
4715 BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
4716 builder()->Jump(test_result->NewThenLabel());
4718 VisitLogicalTest(Token::AND, left, right, right_coverage_slot);
4720 test_result->SetResultConsumedByTest();
4722 BytecodeLabels end_labels(zone());
4723 if (VisitLogicalAndSubExpression(left, &end_labels, right_coverage_slot)) {
4726 VisitForAccumulatorValue(right);
4727 end_labels.Bind(builder());
4731 void BytecodeGenerator::VisitNaryLogicalAndExpression(NaryOperation* expr) {
4732 Expression* first = expr->first();
4733 DCHECK_GT(expr->subsequent_length(), 0);
4735 NaryCodeCoverageSlots coverage_slots(
this, expr);
4737 if (execution_result()->IsTest()) {
4738 TestResultScope* test_result = execution_result()->AsTest();
4739 if (first->ToBooleanIsFalse()) {
4740 builder()->Jump(test_result->NewElseLabel());
4742 VisitNaryLogicalTest(Token::AND, expr, &coverage_slots);
4744 test_result->SetResultConsumedByTest();
4746 BytecodeLabels end_labels(zone());
4747 if (VisitLogicalAndSubExpression(first, &end_labels,
4748 coverage_slots.GetSlotFor(0))) {
4751 for (
size_t i = 0;
i < expr->subsequent_length() - 1; ++
i) {
4752 if (VisitLogicalAndSubExpression(expr->subsequent(
i), &end_labels,
4753 coverage_slots.GetSlotFor(
i + 1))) {
4759 VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
4760 end_labels.Bind(builder());
4764 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
4765 Visit(expr->expression());
4768 void BytecodeGenerator::BuildNewLocalActivationContext() {
4769 ValueResultScope value_execution_result(
this);
4770 Scope* scope = closure_scope();
4771 DCHECK_EQ(current_scope(), closure_scope());
4774 if (scope->is_script_scope()) {
4775 Register scope_reg = register_allocator()->NewRegister();
4777 ->LoadLiteral(scope)
4778 .StoreAccumulatorInRegister(scope_reg)
4779 .CallRuntime(Runtime::kNewScriptContext, scope_reg);
4780 }
else if (scope->is_module_scope()) {
4782 DCHECK(scope->outer_scope()->is_script_scope());
4786 RegisterList args = register_allocator()->NewRegisterList(2);
4788 ->MoveRegister(builder()->Parameter(0), args[0])
4790 .StoreAccumulatorInRegister(args[1])
4791 .CallRuntime(Runtime::kPushModuleContext, args);
4793 DCHECK(scope->is_function_scope() || scope->is_eval_scope());
4794 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
4795 if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
4796 switch (scope->scope_type()) {
4798 builder()->CreateEvalContext(scope, slot_count);
4800 case FUNCTION_SCOPE:
4801 builder()->CreateFunctionContext(scope, slot_count);
4807 Register arg = register_allocator()->NewRegister();
4808 builder()->LoadLiteral(scope).StoreAccumulatorInRegister(arg).CallRuntime(
4809 Runtime::kNewFunctionContext, arg);
4814 void BytecodeGenerator::BuildLocalActivationContextInitialization() {
4815 DeclarationScope* scope = closure_scope();
4817 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
4818 Variable* variable = scope->receiver();
4819 Register receiver(builder()->Receiver());
4821 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
4822 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
4823 execution_context()->reg(), variable->index(), 0);
4827 int num_parameters = scope->num_parameters();
4828 for (
int i = 0;
i < num_parameters;
i++) {
4829 Variable* variable = scope->parameter(
i);
4830 if (!variable->IsContextSlot())
continue;
4832 Register parameter(builder()->Parameter(
i));
4834 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
4835 builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot(
4836 execution_context()->reg(), variable->index(), 0);
4840 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {
4841 ValueResultScope value_execution_result(
this);
4842 DCHECK(scope->is_block_scope());
4844 builder()->CreateBlockContext(scope);
4847 void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
4848 ValueResultScope value_execution_result(
this);
4850 Register extension_object = register_allocator()->NewRegister();
4852 builder()->ToObject(extension_object);
4853 builder()->CreateWithContext(extension_object, scope);
4856 void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
4857 ValueResultScope value_execution_result(
this);
4858 DCHECK(scope->catch_variable()->IsContextSlot());
4860 Register exception = register_allocator()->NewRegister();
4861 builder()->StoreAccumulatorInRegister(exception);
4862 builder()->CreateCatchContext(exception, scope);
4865 void BytecodeGenerator::VisitObjectLiteralAccessor(
4866 Register home_object, ObjectLiteralProperty* property, Register value_out) {
4867 if (property ==
nullptr) {
4868 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
4870 VisitForRegisterValue(property->value(), value_out);
4871 VisitSetHomeObject(value_out, home_object, property);
4875 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
4876 LiteralProperty* property) {
4877 Expression* expr =
property->value();
4878 if (FunctionLiteral::NeedsHomeObject(expr)) {
4879 FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
4881 ->LoadAccumulatorWithRegister(home_object)
4882 .StoreHomeObjectProperty(value, feedback_index(slot), language_mode());
4886 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
4887 if (variable ==
nullptr)
return;
4889 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
4893 builder()->CreateArguments(closure_scope()->GetArgumentsType());
4894 BuildVariableAssignment(variable, Token::ASSIGN, HoleCheckMode::kElided);
4897 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
4898 if (rest ==
nullptr)
return;
4902 builder()->CreateArguments(CreateArgumentsType::kRestParameter);
4903 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
4904 BuildVariableAssignment(rest, Token::ASSIGN, HoleCheckMode::kElided);
4907 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
4908 if (variable ==
nullptr)
return;
4911 builder()->LoadAccumulatorWithRegister(Register::function_closure());
4912 BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
4915 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
4916 if (variable ==
nullptr)
return;
4922 if (IsResumableFunction(info()->literal()->kind()))
return;
4924 if (variable->location() == VariableLocation::LOCAL) {
4926 DCHECK_EQ(incoming_new_target_or_generator_.index(),
4927 GetRegisterForLocalVariable(variable).index());
4932 builder()->LoadAccumulatorWithRegister(incoming_new_target_or_generator_);
4933 BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
4936 void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() {
4937 DCHECK(IsResumableFunction(info()->literal()->kind()));
4939 Variable* generator_object_var = closure_scope()->generator_object_var();
4940 RegisterAllocationScope register_scope(
this);
4941 RegisterList args = register_allocator()->NewRegisterList(2);
4942 Runtime::FunctionId function_id =
4943 (IsAsyncFunction(info()->literal()->kind()) &&
4944 !IsAsyncGeneratorFunction(info()->literal()->kind()))
4945 ? Runtime::kInlineAsyncFunctionEnter
4946 : Runtime::kInlineCreateJSGeneratorObject;
4948 ->MoveRegister(Register::function_closure(), args[0])
4949 .MoveRegister(builder()->Receiver(), args[1])
4950 .CallRuntime(function_id, args)
4951 .StoreAccumulatorInRegister(generator_object());
4953 if (generator_object_var->location() == VariableLocation::LOCAL) {
4956 DCHECK_EQ(generator_object().index(),
4957 GetRegisterForLocalVariable(generator_object_var).index());
4959 BuildVariableAssignment(generator_object_var, Token::INIT,
4960 HoleCheckMode::kElided);
4964 void BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
4965 RegisterList* reg_list) {
4966 Register reg = register_allocator()->GrowRegisterList(reg_list);
4967 builder()->LoadUndefined().StoreAccumulatorInRegister(reg);
4970 void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
4972 if (property->key()->IsStringLiteral()) {
4973 VisitForRegisterValue(property->key(), out_reg);
4975 VisitForAccumulatorValue(property->key());
4976 builder()->ToName(out_reg);
4980 int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(
4981 AstNode* node, SourceRangeKind kind) {
4982 return (block_coverage_builder_ ==
nullptr)
4983 ? BlockCoverageBuilder::kNoCoverageArraySlot
4984 : block_coverage_builder_->AllocateBlockCoverageSlot(node, kind);
4987 int BytecodeGenerator::AllocateNaryBlockCoverageSlotIfEnabled(
4988 NaryOperation* node,
size_t index) {
4989 return (block_coverage_builder_ ==
nullptr)
4990 ? BlockCoverageBuilder::kNoCoverageArraySlot
4991 : block_coverage_builder_->AllocateNaryBlockCoverageSlot(node,
4995 void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
4996 AstNode* node, SourceRangeKind kind) {
4997 if (block_coverage_builder_ ==
nullptr)
return;
4998 block_coverage_builder_->IncrementBlockCounter(node, kind);
5001 void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
5002 int coverage_array_slot) {
5003 if (block_coverage_builder_ !=
nullptr) {
5004 block_coverage_builder_->IncrementBlockCounter(coverage_array_slot);
5009 BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
5011 ValueResultScope accumulator_scope(
this);
5013 return accumulator_scope.type_hint();
5016 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
5017 if (expr ==
nullptr) {
5018 builder()->LoadTheHole();
5020 VisitForAccumulatorValue(expr);
5025 void BytecodeGenerator::VisitForEffect(Expression* expr) {
5026 EffectResultScope effect_scope(
this);
5032 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
5033 VisitForAccumulatorValue(expr);
5034 Register result = register_allocator()->NewRegister();
5035 builder()->StoreAccumulatorInRegister(result);
5041 void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
5042 Register destination) {
5043 ValueResultScope register_scope(
this);
5045 builder()->StoreAccumulatorInRegister(destination);
5050 void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
5051 RegisterList* reg_list) {
5053 ValueResultScope register_scope(
this);
5060 Register destination = register_allocator()->GrowRegisterList(reg_list);
5061 builder()->StoreAccumulatorInRegister(destination);
5064 void BytecodeGenerator::BuildTest(ToBooleanMode mode,
5065 BytecodeLabels* then_labels,
5066 BytecodeLabels* else_labels,
5067 TestFallthrough fallthrough) {
5068 switch (fallthrough) {
5069 case TestFallthrough::kThen:
5070 builder()->JumpIfFalse(mode, else_labels->New());
5072 case TestFallthrough::kElse:
5073 builder()->JumpIfTrue(mode, then_labels->New());
5075 case TestFallthrough::kNone:
5076 builder()->JumpIfTrue(mode, then_labels->New());
5077 builder()->Jump(else_labels->New());
5084 void BytecodeGenerator::VisitForTest(Expression* expr,
5085 BytecodeLabels* then_labels,
5086 BytecodeLabels* else_labels,
5087 TestFallthrough fallthrough) {
5088 bool result_consumed;
5094 TestResultScope test_result(
this, then_labels, else_labels, fallthrough);
5096 result_consumed = test_result.result_consumed_by_test();
5097 type_hint = test_result.type_hint();
5100 then_labels = test_result.then_labels();
5101 else_labels = test_result.else_labels();
5102 fallthrough = test_result.fallthrough();
5104 if (!result_consumed) {
5105 BuildTest(ToBooleanModeFromTypeHint(type_hint), then_labels, else_labels,
5110 void BytecodeGenerator::VisitInSameTestExecutionScope(Expression* expr) {
5111 DCHECK(execution_result()->IsTest());
5113 RegisterAllocationScope reg_scope(
this);
5116 if (!execution_result()->AsTest()->result_consumed_by_test()) {
5117 TestResultScope* result_scope = execution_result()->AsTest();
5118 BuildTest(ToBooleanModeFromTypeHint(result_scope->type_hint()),
5119 result_scope->then_labels(), result_scope->else_labels(),
5120 result_scope->fallthrough());
5121 result_scope->SetResultConsumedByTest();
5125 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
5126 DCHECK(scope->declarations()->is_empty());
5127 CurrentScope current_scope(
this, scope);
5128 ContextScope context_scope(
this, scope);
5132 Register BytecodeGenerator::GetRegisterForLocalVariable(Variable* variable) {
5133 DCHECK_EQ(VariableLocation::LOCAL, variable->location());
5134 return builder()->Local(variable->index());
5137 FunctionKind BytecodeGenerator::function_kind()
const {
5138 return info()->literal()->kind();
5141 LanguageMode BytecodeGenerator::language_mode()
const {
5142 return current_scope()->language_mode();
5145 Register BytecodeGenerator::generator_object()
const {
5146 DCHECK(IsResumableFunction(info()->literal()->kind()));
5147 return incoming_new_target_or_generator_;
5150 FeedbackVectorSpec* BytecodeGenerator::feedback_spec() {
5151 return info()->feedback_vector_spec();
5154 int BytecodeGenerator::feedback_index(FeedbackSlot slot)
const {
5155 DCHECK(!slot.IsInvalid());
5156 return FeedbackVector::GetIndex(slot);
5159 FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
5160 TypeofMode typeof_mode, Variable* variable) {
5161 FeedbackSlotKind slot_kind =
5162 typeof_mode == INSIDE_TYPEOF
5163 ? FeedbackSlotKind::kLoadGlobalInsideTypeof
5164 : FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
5165 FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
5166 if (!slot.IsInvalid()) {
5169 slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode);
5170 feedback_slot_cache()->Put(slot_kind, variable, slot);
5174 FeedbackSlot BytecodeGenerator::GetCachedStoreGlobalICSlot(
5175 LanguageMode language_mode, Variable* variable) {
5176 FeedbackSlotKind slot_kind = is_strict(language_mode)
5177 ? FeedbackSlotKind::kStoreGlobalStrict
5178 : FeedbackSlotKind::kStoreGlobalSloppy;
5179 FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
5180 if (!slot.IsInvalid()) {
5183 slot = feedback_spec()->AddStoreGlobalICSlot(language_mode);
5184 feedback_slot_cache()->Put(slot_kind, variable, slot);
5188 FeedbackSlot BytecodeGenerator::GetCachedLoadICSlot(
const Expression* expr,
5189 const AstRawString* name) {
5190 if (!FLAG_ignition_share_named_property_feedback) {
5191 return feedback_spec()->AddLoadICSlot();
5193 FeedbackSlotKind slot_kind = FeedbackSlotKind::kLoadProperty;
5194 if (!expr->IsVariableProxy()) {
5195 return feedback_spec()->AddLoadICSlot();
5197 const VariableProxy* proxy = expr->AsVariableProxy();
5199 feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name);
5200 if (!slot.IsInvalid()) {
5203 slot = feedback_spec()->AddLoadICSlot();
5204 feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name, slot);
5208 FeedbackSlot BytecodeGenerator::GetCachedStoreICSlot(
const Expression* expr,
5209 const AstRawString* name) {
5210 if (!FLAG_ignition_share_named_property_feedback) {
5211 return feedback_spec()->AddStoreICSlot(language_mode());
5213 FeedbackSlotKind slot_kind = is_strict(language_mode())
5214 ? FeedbackSlotKind::kStoreNamedStrict
5215 : FeedbackSlotKind::kStoreNamedSloppy;
5216 if (!expr->IsVariableProxy()) {
5217 return feedback_spec()->AddStoreICSlot(language_mode());
5219 const VariableProxy* proxy = expr->AsVariableProxy();
5221 feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name);
5222 if (!slot.IsInvalid()) {
5225 slot = feedback_spec()->AddStoreICSlot(language_mode());
5226 feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name, slot);
5230 FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot(
5231 FunctionLiteral* literal) {
5232 FeedbackSlotKind slot_kind = FeedbackSlotKind::kCreateClosure;
5233 FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, literal);
5234 if (!slot.IsInvalid()) {
5237 slot = feedback_spec()->AddCreateClosureSlot();
5238 feedback_slot_cache()->Put(slot_kind, literal, slot);
5242 FeedbackSlot BytecodeGenerator::GetDummyCompareICSlot() {
5243 return dummy_feedback_slot_.Get();
5246 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() {
5247 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict
5248 : Runtime::kStoreToSuper_Sloppy;
5251 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
5252 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
5253 : Runtime::kStoreKeyedToSuper_Sloppy;
V8_INLINE bool IsEmpty() const