Bug Summary

File:out/../deps/v8/src/compiler/bytecode-analysis.cc
Warning:line 266, column 9
Forming reference to null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bytecode-analysis.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D V8_GYP_BUILD -D V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D V8_TARGET_ARCH_X64 -D V8_HAVE_TARGET_OS -D V8_TARGET_OS_LINUX -D V8_EMBEDDER_STRING="-node.8" -D ENABLE_DISASSEMBLER -D V8_PROMISE_INTERNAL_FIELD_COUNT=1 -D V8_SHORT_BUILTIN_CALLS -D OBJECT_PRINT -D V8_INTL_SUPPORT -D V8_ATOMIC_OBJECT_FIELD_WRITES -D V8_ENABLE_LAZY_SOURCE_POSITIONS -D V8_USE_SIPHASH -D V8_SHARED_RO_HEAP -D V8_WIN64_UNWINDING_INFO -D V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -D V8_SNAPSHOT_COMPRESSION -D V8_ENABLE_WEBASSEMBLY -D V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS -D V8_ALLOCATION_FOLDING -D V8_ALLOCATION_SITE_TRACKING -D V8_SCRIPTORMODULE_LEGACY_LIFETIME -D V8_ADVANCED_BIGINT_ALGORITHMS -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/v8 -I ../deps/v8/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/generate-bytecode-output-root -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-return-type -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/v8/src/compiler/bytecode-analysis.cc
1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/bytecode-analysis.h"
6
7#include <utility>
8
9#include "src/compiler/bytecode-liveness-map.h"
10#include "src/interpreter/bytecode-array-iterator.h"
11#include "src/interpreter/bytecode-array-random-iterator.h"
12#include "src/objects/objects-inl.h"
13#include "src/utils/ostreams.h"
14
15namespace v8 {
16namespace internal {
17namespace compiler {
18
19using interpreter::Bytecode;
20using interpreter::BytecodeOperands;
21using interpreter::Bytecodes;
22using interpreter::ImplicitRegisterUse;
23using interpreter::OperandType;
24using interpreter::Register;
25
26BytecodeLoopAssignments::BytecodeLoopAssignments(int parameter_count,
27 int register_count, Zone* zone)
28 : parameter_count_(parameter_count),
29 bit_vector_(
30 zone->New<BitVector>(parameter_count + register_count, zone)) {}
31
32void BytecodeLoopAssignments::Add(interpreter::Register r) {
33 if (r.is_parameter()) {
34 bit_vector_->Add(r.ToParameterIndex());
35 } else {
36 bit_vector_->Add(parameter_count_ + r.index());
37 }
38}
39
40void BytecodeLoopAssignments::AddList(interpreter::Register r, uint32_t count) {
41 if (r.is_parameter()) {
42 for (uint32_t i = 0; i < count; i++) {
43 DCHECK(interpreter::Register(r.index() + i).is_parameter())((void) 0);
44 bit_vector_->Add(r.ToParameterIndex() + i);
45 }
46 } else {
47 for (uint32_t i = 0; i < count; i++) {
48 DCHECK(!interpreter::Register(r.index() + i).is_parameter())((void) 0);
49 bit_vector_->Add(parameter_count_ + r.index() + i);
50 }
51 }
52}
53
54
55void BytecodeLoopAssignments::Union(const BytecodeLoopAssignments& other) {
56 bit_vector_->Union(*other.bit_vector_);
57}
58
59bool BytecodeLoopAssignments::ContainsParameter(int index) const {
60 DCHECK_GE(index, 0)((void) 0);
61 DCHECK_LT(index, parameter_count())((void) 0);
62 return bit_vector_->Contains(index);
63}
64
65bool BytecodeLoopAssignments::ContainsLocal(int index) const {
66 DCHECK_GE(index, 0)((void) 0);
67 DCHECK_LT(index, local_count())((void) 0);
68 return bit_vector_->Contains(parameter_count_ + index);
69}
70
71ResumeJumpTarget::ResumeJumpTarget(int suspend_id, int target_offset,
72 int final_target_offset)
73 : suspend_id_(suspend_id),
74 target_offset_(target_offset),
75 final_target_offset_(final_target_offset) {}
76
77ResumeJumpTarget ResumeJumpTarget::Leaf(int suspend_id, int target_offset) {
78 return ResumeJumpTarget(suspend_id, target_offset, target_offset);
79}
80
81ResumeJumpTarget ResumeJumpTarget::AtLoopHeader(int loop_header_offset,
82 const ResumeJumpTarget& next) {
83 return ResumeJumpTarget(next.suspend_id(), loop_header_offset,
84 next.target_offset());
85}
86
87BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array,
88 Zone* zone, BytecodeOffset osr_bailout_id,
89 bool analyze_liveness)
90 : bytecode_array_(bytecode_array),
91 zone_(zone),
92 osr_bailout_id_(osr_bailout_id),
93 analyze_liveness_(analyze_liveness),
94 loop_stack_(zone),
95 loop_end_index_queue_(zone),
96 resume_jump_targets_(zone),
97 end_to_header_(zone),
98 header_to_info_(zone),
99 osr_entry_point_(-1) {
100 Analyze();
101}
102
103namespace {
104
105template <Bytecode bytecode, OperandType operand_type, size_t i>
106void UpdateInLivenessForOutOperand(
107 BytecodeLivenessState* in_liveness,
108 const interpreter::BytecodeArrayIterator& iterator) {
109 switch (operand_type) {
110 case OperandType::kRegOut: {
111 Register r = iterator.GetRegisterOperand(i);
112 if (!r.is_parameter()) {
113 in_liveness->MarkRegisterDead(r.index());
114 }
115 break;
116 }
117 case OperandType::kRegOutList: {
118 Register r = iterator.GetRegisterOperand(i);
119 uint32_t reg_count = iterator.GetRegisterCountOperand(i + 1);
120 if (!r.is_parameter()) {
121 for (uint32_t j = 0; j < reg_count; ++j) {
122 DCHECK(!Register(r.index() + j).is_parameter())((void) 0);
123 in_liveness->MarkRegisterDead(r.index() + j);
124 }
125 }
126 break;
127 }
128 case OperandType::kRegOutPair: {
129 Register r = iterator.GetRegisterOperand(i);
130 if (!r.is_parameter()) {
131 DCHECK(!Register(r.index() + 1).is_parameter())((void) 0);
132 in_liveness->MarkRegisterDead(r.index());
133 in_liveness->MarkRegisterDead(r.index() + 1);
134 }
135 break;
136 }
137 case OperandType::kRegOutTriple: {
138 Register r = iterator.GetRegisterOperand(i);
139 if (!r.is_parameter()) {
140 DCHECK(!Register(r.index() + 1).is_parameter())((void) 0);
141 DCHECK(!Register(r.index() + 2).is_parameter())((void) 0);
142 in_liveness->MarkRegisterDead(r.index());
143 in_liveness->MarkRegisterDead(r.index() + 1);
144 in_liveness->MarkRegisterDead(r.index() + 2);
145 }
146 break;
147 }
148 default:
149 DCHECK(!Bytecodes::IsRegisterOutputOperandType(operand_type))((void) 0);
150 break;
151 }
152}
153
154template <Bytecode bytecode, OperandType operand_type, size_t i>
155void UpdateInLivenessForInOperand(
156 BytecodeLivenessState* in_liveness,
157 const interpreter::BytecodeArrayIterator& iterator) {
158 switch (operand_type) {
159 case OperandType::kReg: {
160 Register r = iterator.GetRegisterOperand(i);
161 if (!r.is_parameter()) {
162 in_liveness->MarkRegisterLive(r.index());
163 }
164 break;
165 }
166 case OperandType::kRegPair: {
167 Register r = iterator.GetRegisterOperand(i);
168 if (!r.is_parameter()) {
169 DCHECK(!Register(r.index() + 1).is_parameter())((void) 0);
170 in_liveness->MarkRegisterLive(r.index());
171 in_liveness->MarkRegisterLive(r.index() + 1);
172 }
173 break;
174 }
175 case OperandType::kRegList: {
176 Register r = iterator.GetRegisterOperand(i);
177 uint32_t reg_count = iterator.GetRegisterCountOperand(i + 1);
178 if (!r.is_parameter()) {
179 for (uint32_t j = 0; j < reg_count; ++j) {
180 DCHECK(!interpreter::Register(r.index() + j).is_parameter())((void) 0);
181 in_liveness->MarkRegisterLive(r.index() + j);
182 }
183 }
184 break;
185 }
186 default:
187 DCHECK(!Bytecodes::IsRegisterInputOperandType(operand_type))((void) 0);
188 break;
189 }
190}
191
192template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use,
193 OperandType... operand_types, size_t... operand_index>
194void UpdateInLiveness(BytecodeLivenessState* in_liveness,
195 const interpreter::BytecodeArrayIterator& iterator,
196 std::index_sequence<operand_index...>) {
197 // Special case Suspend and Resume to just pass through liveness.
198 if (bytecode == Bytecode::kSuspendGenerator) {
199 // The generator object has to be live.
200 in_liveness->MarkRegisterLive(iterator.GetRegisterOperand(0).index());
201 // Suspend additionally reads and returns the accumulator
202 DCHECK(Bytecodes::ReadsAccumulator(bytecode))((void) 0);
203 in_liveness->MarkAccumulatorLive();
204 return;
205 }
206 if (bytecode == Bytecode::kResumeGenerator) {
207 // The generator object has to be live.
208 in_liveness->MarkRegisterLive(iterator.GetRegisterOperand(0).index());
209 return;
210 }
211
212 if (BytecodeOperands::WritesAccumulator(implicit_register_use)) {
213 in_liveness->MarkAccumulatorDead();
214 }
215 (UpdateInLivenessForOutOperand<bytecode, operand_types, operand_index>(
216 in_liveness, iterator),
217 ...);
218
219 if (Bytecodes::WritesImplicitRegister(bytecode)) {
220 in_liveness->MarkRegisterDead(Register::FromShortStar(bytecode).index());
221 }
222
223 if (BytecodeOperands::ReadsAccumulator(implicit_register_use)) {
224 in_liveness->MarkAccumulatorLive();
225 }
226 (UpdateInLivenessForInOperand<bytecode, operand_types, operand_index>(
227 in_liveness, iterator),
228 ...);
229}
230
231template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use,
232 OperandType... operand_types>
233void UpdateInLiveness(BytecodeLivenessState* in_liveness,
234 const interpreter::BytecodeArrayIterator& iterator) {
235 UpdateInLiveness<bytecode, implicit_register_use, operand_types...>(
236 in_liveness, iterator,
237 std::make_index_sequence<sizeof...(operand_types)>());
238}
239
240void UpdateInLiveness(Bytecode bytecode, BytecodeLivenessState* in_liveness,
241 const interpreter::BytecodeArrayIterator& iterator) {
242 switch (bytecode) {
243#define BYTECODE_UPDATE_IN_LIVENESS(Name, ...) \
244 case Bytecode::k##Name: \
245 return UpdateInLiveness<Bytecode::k##Name, __VA_ARGS__>(in_liveness, \
246 iterator);
247 BYTECODE_LIST(BYTECODE_UPDATE_IN_LIVENESS)BYTECODE_UPDATE_IN_LIVENESS(Wide, ImplicitRegisterUse::kNone)
BYTECODE_UPDATE_IN_LIVENESS(ExtraWide, ImplicitRegisterUse::
kNone) BYTECODE_UPDATE_IN_LIVENESS(DebugBreakWide, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(DebugBreakExtraWide
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(DebugBreak0, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(DebugBreak1, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg) BYTECODE_UPDATE_IN_LIVENESS(DebugBreak2, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kReg
) BYTECODE_UPDATE_IN_LIVENESS(DebugBreak3, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kReg
, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS(DebugBreak4,
ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kReg, OperandType::kReg, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS
(DebugBreak5, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRuntimeId, OperandType::kReg, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS
(DebugBreak6, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRuntimeId, OperandType::kReg, OperandType::kReg, OperandType
::kReg) BYTECODE_UPDATE_IN_LIVENESS(Ldar, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS
(LdaZero, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(LdaSmi, ImplicitRegisterUse::kWriteAccumulator, OperandType::
kImm) BYTECODE_UPDATE_IN_LIVENESS(LdaUndefined, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(LdaNull, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(LdaTheHole, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(LdaTrue, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(LdaFalse, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(LdaConstant,
ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(LdaContextSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(LdaImmutableContextSlot, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kReg, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(LdaCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(LdaImmutableCurrentContextSlot
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(Star, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut
) BYTECODE_UPDATE_IN_LIVENESS(Mov, ImplicitRegisterUse::kNone
, OperandType::kReg, OperandType::kRegOut) BYTECODE_UPDATE_IN_LIVENESS
(PushContext, ImplicitRegisterUse::kReadAccumulator, OperandType
::kRegOut) BYTECODE_UPDATE_IN_LIVENESS(PopContext, ImplicitRegisterUse
::kNone, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS(TestReferenceEqual
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
) BYTECODE_UPDATE_IN_LIVENESS(TestUndetectable, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(TestNull
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(TestUndefined, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(TestTypeOf, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kFlag8) BYTECODE_UPDATE_IN_LIVENESS(LdaGlobal, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(LdaGlobalInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(StaGlobal, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(StaContextSlot
, ImplicitRegisterUse::kReadAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS(StaCurrentContextSlot
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(LdaLookupSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(LdaLookupContextSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(LdaLookupGlobalSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(LdaLookupSlotInsideTypeof
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(LdaLookupContextSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(LdaLookupGlobalSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(StaLookupSlot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_IN_LIVENESS(GetNamedProperty
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(GetNamedPropertyFromSuper
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(GetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(LdaModuleVariable, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kImm, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS(StaModuleVariable
, ImplicitRegisterUse::kReadAccumulator, OperandType::kImm, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(SetNamedProperty, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(DefineNamedOwnProperty
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(SetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(DefineKeyedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(StaInArrayLiteral, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kFlag8, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CollectTypeProfile, ImplicitRegisterUse
::kReadAccumulator, OperandType::kImm) BYTECODE_UPDATE_IN_LIVENESS
(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(Sub, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(Mul, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(Div, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(Mod, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(Exp, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(BitwiseOr, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(BitwiseXor
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(BitwiseAnd, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(ShiftLeft, ImplicitRegisterUse::
kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ShiftRight, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ShiftRightLogical
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(AddSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(SubSmi, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(MulSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(DivSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ModSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(ExpSmi, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(BitwiseOrSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(BitwiseXorSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(BitwiseAndSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ShiftLeftSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ShiftRightSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ShiftRightLogicalSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(Inc, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(Dec, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(Negate, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(BitwiseNot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ToBooleanLogicalNot, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(LogicalNot
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(TypeOf, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(DeletePropertyStrict, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS(DeletePropertySloppy
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
) BYTECODE_UPDATE_IN_LIVENESS(GetSuperConstructor, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_IN_LIVENESS
(CallAnyReceiver, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kRegList, OperandType::kRegCount, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CallProperty, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kRegList
, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CallProperty0, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CallProperty1, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(CallProperty2, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CallUndefinedReceiver, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kReg, OperandType::kRegList, OperandType::kRegCount
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CallUndefinedReceiver0
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CallUndefinedReceiver1, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CallUndefinedReceiver2, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CallWithSpread
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kRegList, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CallRuntime, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kRuntimeId, OperandType::kRegList, OperandType::kRegCount) BYTECODE_UPDATE_IN_LIVENESS
(CallRuntimeForPair, ImplicitRegisterUse::kNone, OperandType::
kRuntimeId, OperandType::kRegList, OperandType::kRegCount, OperandType
::kRegOutPair) BYTECODE_UPDATE_IN_LIVENESS(CallJSRuntime, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kNativeContextIndex, OperandType
::kRegList, OperandType::kRegCount) BYTECODE_UPDATE_IN_LIVENESS
(InvokeIntrinsic, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIntrinsicId, OperandType::kRegList, OperandType::kRegCount
) BYTECODE_UPDATE_IN_LIVENESS(Construct, ImplicitRegisterUse::
kReadWriteAccumulator, OperandType::kReg, OperandType::kRegList
, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ConstructWithSpread, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kRegList, OperandType::kRegCount
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(TestEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestEqualStrict, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestLessThan, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestGreaterThan, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestLessThanOrEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestGreaterThanOrEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestInstanceOf, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(TestIn, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ToName, ImplicitRegisterUse::kReadAccumulator, OperandType::
kRegOut) BYTECODE_UPDATE_IN_LIVENESS(ToNumber, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(ToObject, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_IN_LIVENESS
(ToString, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator,
OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_IN_LIVENESS
(CreateArrayLiteral, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_IN_LIVENESS
(CreateArrayFromIterable, ImplicitRegisterUse::kReadWriteAccumulator
) BYTECODE_UPDATE_IN_LIVENESS(CreateEmptyArrayLiteral, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CreateObjectLiteral, ImplicitRegisterUse::kWriteAccumulator,
OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_IN_LIVENESS
(CreateEmptyObjectLiteral, ImplicitRegisterUse::kWriteAccumulator
) BYTECODE_UPDATE_IN_LIVENESS(CloneObject, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kFlag8, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(GetTemplateObject, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CreateClosure, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_IN_LIVENESS
(CreateBlockContext, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CreateCatchContext, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(CreateFunctionContext, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(CreateEvalContext, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS(CreateWithContext
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(CreateMappedArguments, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(CreateUnmappedArguments
, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(CreateRestParameter, ImplicitRegisterUse::kWriteAccumulator)
BYTECODE_UPDATE_IN_LIVENESS(JumpLoop, ImplicitRegisterUse::kNone
, OperandType::kUImm, OperandType::kImm) BYTECODE_UPDATE_IN_LIVENESS
(Jump, ImplicitRegisterUse::kNone, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(JumpConstant, ImplicitRegisterUse::kNone, OperandType::kIdx)
BYTECODE_UPDATE_IN_LIVENESS(JumpIfNullConstant, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfNotNullConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(JumpIfUndefinedConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfNotUndefinedConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(JumpIfUndefinedOrNullConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfTrueConstant, ImplicitRegisterUse::kReadAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_IN_LIVENESS(JumpIfFalseConstant, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfJSReceiverConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(JumpIfToBooleanTrueConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfToBooleanFalseConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(JumpIfToBooleanTrue
, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfToBooleanFalse, ImplicitRegisterUse::kReadAccumulator,
OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS(JumpIfTrue, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfFalse, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(JumpIfNull, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfNotNull, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(JumpIfUndefined, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfNotUndefined, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(JumpIfUndefinedOrNull, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(JumpIfJSReceiver, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_IN_LIVENESS(SwitchOnSmiNoFeedback, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx, OperandType::kUImm, OperandType
::kImm) BYTECODE_UPDATE_IN_LIVENESS(ForInEnumerate, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS
(ForInPrepare, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRegOutTriple, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ForInContinue, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg) BYTECODE_UPDATE_IN_LIVENESS(ForInNext
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kReg, OperandType::kRegPair, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ForInStep, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg) BYTECODE_UPDATE_IN_LIVENESS(SetPendingMessage, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_IN_LIVENESS(Throw, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_IN_LIVENESS(ReThrow, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_IN_LIVENESS(Return, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_IN_LIVENESS(ThrowReferenceErrorIfHole
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(ThrowSuperNotCalledIfHole, ImplicitRegisterUse::kReadAccumulator
) BYTECODE_UPDATE_IN_LIVENESS(ThrowSuperAlreadyCalledIfNotHole
, ImplicitRegisterUse::kReadAccumulator) BYTECODE_UPDATE_IN_LIVENESS
(ThrowIfNotSuperConstructor, ImplicitRegisterUse::kNone, OperandType
::kReg) BYTECODE_UPDATE_IN_LIVENESS(SwitchOnGeneratorState, ImplicitRegisterUse
::kNone, OperandType::kReg, OperandType::kIdx, OperandType::kUImm
) BYTECODE_UPDATE_IN_LIVENESS(SuspendGenerator, ImplicitRegisterUse
::kReadAccumulator, OperandType::kReg, OperandType::kRegList,
OperandType::kRegCount, OperandType::kUImm) BYTECODE_UPDATE_IN_LIVENESS
(ResumeGenerator, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kRegOutList, OperandType::kRegCount) BYTECODE_UPDATE_IN_LIVENESS
(GetIterator, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS
(Debugger, ImplicitRegisterUse::kNone) BYTECODE_UPDATE_IN_LIVENESS
(IncBlockCounter, ImplicitRegisterUse::kNone, OperandType::kIdx
) BYTECODE_UPDATE_IN_LIVENESS(Abort, ImplicitRegisterUse::kNone
, OperandType::kIdx) BYTECODE_UPDATE_IN_LIVENESS(Star15, ImplicitRegisterUse
::kReadAccumulatorWriteShortStar) BYTECODE_UPDATE_IN_LIVENESS
(Star14, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)
BYTECODE_UPDATE_IN_LIVENESS(Star13, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star12, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star11, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star10, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star9, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star8, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star7, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star6, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star5, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star4, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star3, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star2, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star1, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Star0, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_IN_LIVENESS(Illegal, ImplicitRegisterUse::kNone
)
248#undef BYTECODE_UPDATE_IN_LIVENESS
249 }
250}
251
252template <bool IsFirstUpdate = false>
253void EnsureOutLivenessIsNotAlias(
254 BytecodeLiveness& liveness,
255 BytecodeLivenessState* next_bytecode_in_liveness, Zone* zone) {
256 if (!IsFirstUpdate) {
12
Taking false branch
257 // We should have copied the next bytecode's in liveness already in the
258 // first pass, so on subsequent passes this should already not be an alias.
259 DCHECK_NE(liveness.out, next_bytecode_in_liveness)((void) 0);
260 return;
261 }
262 if (liveness.out == next_bytecode_in_liveness) {
13
Assuming 'next_bytecode_in_liveness' is equal to field 'out'
14
Taking true branch
263 // If the out-liveness is aliasing the next bytecode's in-liveness,
264 // reallocate it and copy the data to the newly allocated state.
265 liveness.out =
266 zone->New<BytecodeLivenessState>(*next_bytecode_in_liveness, zone);
15
Forming reference to null pointer
267 }
268}
269
270template <bool IsFirstUpdate, Bytecode bytecode>
271void UpdateOutLiveness(BytecodeLiveness& liveness,
272 BytecodeLivenessState* next_bytecode_in_liveness,
273 const interpreter::BytecodeArrayIterator& iterator,
274 Handle<BytecodeArray> bytecode_array,
275 const BytecodeLivenessMap& liveness_map, Zone* zone) {
276 // On subsequent updates, only update out-liveness manually if it isn't
277 // already aliasing the next bytecode's in-liveness.
278 if (!IsFirstUpdate && liveness.out == next_bytecode_in_liveness) return;
279
280 // Special case Suspend and Resume to just pass through liveness.
281 if (bytecode == Bytecode::kSuspendGenerator ||
282 bytecode == Bytecode::kResumeGenerator) {
283 DCHECK_NOT_NULL(next_bytecode_in_liveness)((void) 0);
284 if (IsFirstUpdate) {
285 liveness.out = next_bytecode_in_liveness;
286 } else {
287 liveness.out->Union(*next_bytecode_in_liveness);
288 }
289 return;
290 }
291
292 // Update from next bytecode (unless there isn't one or this is an
293 // unconditional jump).
294 if (next_bytecode_in_liveness != nullptr &&
3
Assuming pointer value is null
295 !Bytecodes::IsUnconditionalJump(bytecode) &&
296 !Bytecodes::Returns(bytecode) &&
297 !Bytecodes::UnconditionallyThrows(bytecode)) {
298 if (IsFirstUpdate) {
299 // On first update, we can assume that this out-liveness is the same as
300 // the next liveness, and can directly alias it -- we'll allocate a new
301 // one using EnsureOutLivenessIsNotAlias if it needs to be mutated.
302 DCHECK_NULL(liveness.out)((void) 0);
303 liveness.out = next_bytecode_in_liveness;
304 } else {
305 liveness.out->Union(*next_bytecode_in_liveness);
306 }
307 } else if (IsFirstUpdate) {
4
Taking true branch
308 // Otherwise, on the first allocation we need to make sure that there is an
309 // allocated out liveness.
310 DCHECK_NULL(liveness.out)((void) 0);
311 liveness.out = zone->New<BytecodeLivenessState>(
312 bytecode_array->register_count(), zone);
313 }
314
315 DCHECK_NOT_NULL(liveness.out)((void) 0);
316
317 // Update from jump target (if any). Skip loops, we update these manually in
318 // the liveness iterations.
319 if (Bytecodes::IsForwardJump(bytecode)) {
5
Taking false branch
320 int target_offset = iterator.GetJumpTargetOffset();
321 EnsureOutLivenessIsNotAlias<IsFirstUpdate>(liveness,
322 next_bytecode_in_liveness, zone);
323 liveness.out->Union(*liveness_map.GetInLiveness(target_offset));
324 } else if (Bytecodes::IsSwitch(bytecode)) {
6
Taking false branch
325 EnsureOutLivenessIsNotAlias<IsFirstUpdate>(liveness,
326 next_bytecode_in_liveness, zone);
327 for (interpreter::JumpTableTargetOffset entry :
328 iterator.GetJumpTableTargetOffsets()) {
329 liveness.out->Union(*liveness_map.GetInLiveness(entry.target_offset));
330 }
331 }
332
333 // Update from exception handler (if any).
334 if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
7
Taking true branch
335 int handler_context;
336 // TODO(leszeks): We should look up this range only once per entry.
337 HandlerTable table(*bytecode_array);
338 int handler_offset =
339 table.LookupRange(iterator.current_offset(), &handler_context, nullptr);
340
341 if (handler_offset != -1) {
8
Assuming the condition is true
9
Taking true branch
342 EnsureOutLivenessIsNotAlias<IsFirstUpdate>(
11
Calling 'EnsureOutLivenessIsNotAlias<true>'
343 liveness, next_bytecode_in_liveness, zone);
10
Passing null pointer value via 2nd parameter 'next_bytecode_in_liveness'
344 bool was_accumulator_live = liveness.out->AccumulatorIsLive();
345 liveness.out->Union(*liveness_map.GetInLiveness(handler_offset));
346 liveness.out->MarkRegisterLive(handler_context);
347 if (!was_accumulator_live) {
348 // The accumulator is reset to the exception on entry into a handler,
349 // and so shouldn't be considered live coming out of this bytecode just
350 // because it's live coming into the handler. So, kill the accumulator
351 // if the handler is the only thing that made it live.
352 liveness.out->MarkAccumulatorDead();
353
354 // TODO(leszeks): Ideally the accumulator wouldn't be considered live at
355 // the start of the handler, but looking up if the current bytecode is
356 // the start of a handler is not free, so we should only do it if we
357 // decide it's necessary.
358 }
359 }
360 }
361}
362
363template <bool IsFirstUpdate = false>
364void UpdateOutLiveness(Bytecode bytecode, BytecodeLiveness& liveness,
365 BytecodeLivenessState* next_bytecode_in_liveness,
366 const interpreter::BytecodeArrayIterator& iterator,
367 Handle<BytecodeArray> bytecode_array,
368 const BytecodeLivenessMap& liveness_map, Zone* zone) {
369 switch (bytecode) {
370#define BYTECODE_UPDATE_OUT_LIVENESS(Name, ...) \
371 case Bytecode::k##Name: \
372 return UpdateOutLiveness<IsFirstUpdate, Bytecode::k##Name>( \
373 liveness, next_bytecode_in_liveness, iterator, bytecode_array, \
374 liveness_map, zone);
375 BYTECODE_LIST(BYTECODE_UPDATE_OUT_LIVENESS)BYTECODE_UPDATE_OUT_LIVENESS(Wide, ImplicitRegisterUse::kNone
) BYTECODE_UPDATE_OUT_LIVENESS(ExtraWide, ImplicitRegisterUse
::kNone) BYTECODE_UPDATE_OUT_LIVENESS(DebugBreakWide, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(DebugBreakExtraWide
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(DebugBreak0, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(DebugBreak1, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg) BYTECODE_UPDATE_OUT_LIVENESS(DebugBreak2, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kReg
) BYTECODE_UPDATE_OUT_LIVENESS(DebugBreak3, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kReg
, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS(DebugBreak4
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kReg, OperandType::kReg, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS
(DebugBreak5, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRuntimeId, OperandType::kReg, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS
(DebugBreak6, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRuntimeId, OperandType::kReg, OperandType::kReg, OperandType
::kReg) BYTECODE_UPDATE_OUT_LIVENESS(Ldar, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS
(LdaZero, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(LdaSmi, ImplicitRegisterUse::kWriteAccumulator, OperandType::
kImm) BYTECODE_UPDATE_OUT_LIVENESS(LdaUndefined, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(LdaNull, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(LdaTheHole,
ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(LdaTrue, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(LdaFalse, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(LdaConstant, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(LdaContextSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(LdaImmutableContextSlot
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(LdaCurrentContextSlot
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(LdaImmutableCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(Star, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_OUT_LIVENESS
(Mov, ImplicitRegisterUse::kNone, OperandType::kReg, OperandType
::kRegOut) BYTECODE_UPDATE_OUT_LIVENESS(PushContext, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_OUT_LIVENESS
(PopContext, ImplicitRegisterUse::kNone, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS
(TestReferenceEqual, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS(TestUndetectable
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(TestNull, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(TestUndefined, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(TestTypeOf, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kFlag8) BYTECODE_UPDATE_OUT_LIVENESS(LdaGlobal, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(LdaGlobalInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(StaGlobal, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(StaContextSlot
, ImplicitRegisterUse::kReadAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(StaCurrentContextSlot
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(LdaLookupSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(LdaLookupContextSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(LdaLookupGlobalSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(LdaLookupSlotInsideTypeof
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(LdaLookupContextSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(LdaLookupGlobalSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(StaLookupSlot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_OUT_LIVENESS(GetNamedProperty
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(GetNamedPropertyFromSuper
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(GetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(LdaModuleVariable, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kImm, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(StaModuleVariable
, ImplicitRegisterUse::kReadAccumulator, OperandType::kImm, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(SetNamedProperty, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(DefineNamedOwnProperty
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(SetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(DefineKeyedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(StaInArrayLiteral, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kFlag8, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CollectTypeProfile, ImplicitRegisterUse
::kReadAccumulator, OperandType::kImm) BYTECODE_UPDATE_OUT_LIVENESS
(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(Sub, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(Mul, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(Div, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(Mod, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(Exp, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(BitwiseOr, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(BitwiseXor
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(BitwiseAnd,
ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(ShiftLeft, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(ShiftRight, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(ShiftRightLogical, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(AddSmi, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(SubSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(MulSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(DivSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(ModSmi, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ExpSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(BitwiseOrSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(BitwiseXorSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(BitwiseAndSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(ShiftLeftSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(ShiftRightSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(ShiftRightLogicalSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(Inc, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(Dec, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(Negate, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(BitwiseNot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(ToBooleanLogicalNot, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(LogicalNot
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(TypeOf, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(DeletePropertyStrict, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS(DeletePropertySloppy
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
) BYTECODE_UPDATE_OUT_LIVENESS(GetSuperConstructor, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_OUT_LIVENESS
(CallAnyReceiver, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kRegList, OperandType::kRegCount, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CallProperty, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kRegList
, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CallProperty0, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CallProperty1, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(CallProperty2, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CallUndefinedReceiver, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kReg, OperandType::kRegList, OperandType::kRegCount
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CallUndefinedReceiver0
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CallUndefinedReceiver1, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CallUndefinedReceiver2, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CallWithSpread
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kRegList, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CallRuntime, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kRuntimeId, OperandType::kRegList, OperandType::kRegCount) BYTECODE_UPDATE_OUT_LIVENESS
(CallRuntimeForPair, ImplicitRegisterUse::kNone, OperandType::
kRuntimeId, OperandType::kRegList, OperandType::kRegCount, OperandType
::kRegOutPair) BYTECODE_UPDATE_OUT_LIVENESS(CallJSRuntime, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kNativeContextIndex, OperandType
::kRegList, OperandType::kRegCount) BYTECODE_UPDATE_OUT_LIVENESS
(InvokeIntrinsic, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIntrinsicId, OperandType::kRegList, OperandType::kRegCount
) BYTECODE_UPDATE_OUT_LIVENESS(Construct, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kRegList
, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ConstructWithSpread, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kRegList, OperandType::kRegCount
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(TestEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestEqualStrict, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestLessThan, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestGreaterThan, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestLessThanOrEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestGreaterThanOrEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestInstanceOf, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(TestIn, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ToName, ImplicitRegisterUse::kReadAccumulator, OperandType::
kRegOut) BYTECODE_UPDATE_OUT_LIVENESS(ToNumber, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(ToObject, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_OUT_LIVENESS
(ToString, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator,
OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_OUT_LIVENESS
(CreateArrayLiteral, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_OUT_LIVENESS
(CreateArrayFromIterable, ImplicitRegisterUse::kReadWriteAccumulator
) BYTECODE_UPDATE_OUT_LIVENESS(CreateEmptyArrayLiteral, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CreateObjectLiteral, ImplicitRegisterUse::kWriteAccumulator,
OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_OUT_LIVENESS
(CreateEmptyObjectLiteral, ImplicitRegisterUse::kWriteAccumulator
) BYTECODE_UPDATE_OUT_LIVENESS(CloneObject, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kFlag8, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(GetTemplateObject, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CreateClosure, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_OUT_LIVENESS
(CreateBlockContext, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CreateCatchContext, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(CreateFunctionContext, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(CreateEvalContext, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(CreateWithContext
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(CreateMappedArguments, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(CreateUnmappedArguments
, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(CreateRestParameter, ImplicitRegisterUse::kWriteAccumulator)
BYTECODE_UPDATE_OUT_LIVENESS(JumpLoop, ImplicitRegisterUse::
kNone, OperandType::kUImm, OperandType::kImm) BYTECODE_UPDATE_OUT_LIVENESS
(Jump, ImplicitRegisterUse::kNone, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(JumpConstant, ImplicitRegisterUse::kNone, OperandType::kIdx)
BYTECODE_UPDATE_OUT_LIVENESS(JumpIfNullConstant, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfNotNullConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfUndefinedConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfNotUndefinedConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfUndefinedOrNullConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfTrueConstant, ImplicitRegisterUse::kReadAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfFalseConstant, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfJSReceiverConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfToBooleanTrueConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfToBooleanFalseConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfToBooleanTrue
, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfToBooleanFalse, ImplicitRegisterUse::kReadAccumulator,
OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfTrue,
ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfFalse, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfNull, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfNotNull, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfUndefined, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfNotUndefined, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(JumpIfUndefinedOrNull, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(JumpIfJSReceiver, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_OUT_LIVENESS(SwitchOnSmiNoFeedback, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx, OperandType::kUImm, OperandType
::kImm) BYTECODE_UPDATE_OUT_LIVENESS(ForInEnumerate, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS
(ForInPrepare, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRegOutTriple, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ForInContinue, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg) BYTECODE_UPDATE_OUT_LIVENESS(ForInNext
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kReg, OperandType::kRegPair, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ForInStep, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg) BYTECODE_UPDATE_OUT_LIVENESS(SetPendingMessage, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(Throw, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(ReThrow, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(Return, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_OUT_LIVENESS(ThrowReferenceErrorIfHole
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(ThrowSuperNotCalledIfHole, ImplicitRegisterUse::kReadAccumulator
) BYTECODE_UPDATE_OUT_LIVENESS(ThrowSuperAlreadyCalledIfNotHole
, ImplicitRegisterUse::kReadAccumulator) BYTECODE_UPDATE_OUT_LIVENESS
(ThrowIfNotSuperConstructor, ImplicitRegisterUse::kNone, OperandType
::kReg) BYTECODE_UPDATE_OUT_LIVENESS(SwitchOnGeneratorState, ImplicitRegisterUse
::kNone, OperandType::kReg, OperandType::kIdx, OperandType::kUImm
) BYTECODE_UPDATE_OUT_LIVENESS(SuspendGenerator, ImplicitRegisterUse
::kReadAccumulator, OperandType::kReg, OperandType::kRegList,
OperandType::kRegCount, OperandType::kUImm) BYTECODE_UPDATE_OUT_LIVENESS
(ResumeGenerator, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kRegOutList, OperandType::kRegCount) BYTECODE_UPDATE_OUT_LIVENESS
(GetIterator, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS
(Debugger, ImplicitRegisterUse::kNone) BYTECODE_UPDATE_OUT_LIVENESS
(IncBlockCounter, ImplicitRegisterUse::kNone, OperandType::kIdx
) BYTECODE_UPDATE_OUT_LIVENESS(Abort, ImplicitRegisterUse::kNone
, OperandType::kIdx) BYTECODE_UPDATE_OUT_LIVENESS(Star15, ImplicitRegisterUse
::kReadAccumulatorWriteShortStar) BYTECODE_UPDATE_OUT_LIVENESS
(Star14, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)
BYTECODE_UPDATE_OUT_LIVENESS(Star13, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star12, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star11, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star10, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star9, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star8, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star7, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star6, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star5, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star4, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star3, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star2, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star1, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Star0, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_OUT_LIVENESS(Illegal, ImplicitRegisterUse::
kNone)
376#undef BYTECODE_UPDATE_OUT_LIVENESS
377 }
378}
379
380template <bool IsFirstUpdate, Bytecode bytecode,
381 ImplicitRegisterUse implicit_register_use,
382 OperandType... operand_types>
383void UpdateLiveness(BytecodeLiveness& liveness,
384 BytecodeLivenessState** next_bytecode_in_liveness,
385 const interpreter::BytecodeArrayIterator& iterator,
386 Handle<BytecodeArray> bytecode_array,
387 const BytecodeLivenessMap& liveness_map, Zone* zone) {
388 UpdateOutLiveness<IsFirstUpdate, bytecode>(
2
Calling 'UpdateOutLiveness<true, v8::internal::interpreter::Bytecode::kDebugBreak6>'
389 liveness, *next_bytecode_in_liveness, iterator, bytecode_array,
1
Passing value via 2nd parameter 'next_bytecode_in_liveness'
390 liveness_map, zone);
391 if (IsFirstUpdate) {
392 // On the first update, allocate the in-liveness as a copy of the
393 // out-liveness.
394 DCHECK_NULL(liveness.in)((void) 0);
395 liveness.in = zone->New<BytecodeLivenessState>(*liveness.out, zone);
396 } else {
397 // On subsequent updates, copy liveness from the out vector.
398 // TODO(leszeks): If this copy doesn't change liveness, we could
399 // opportunistically terminate early.
400 liveness.in->CopyFrom(*liveness.out);
401 }
402 UpdateInLiveness<bytecode, implicit_register_use, operand_types...>(
403 liveness.in, iterator);
404
405 *next_bytecode_in_liveness = liveness.in;
406}
407
408template <bool IsFirstUpdate = false>
409void UpdateLiveness(Bytecode bytecode, BytecodeLiveness& liveness,
410 BytecodeLivenessState** next_bytecode_in_liveness,
411 const interpreter::BytecodeArrayIterator& iterator,
412 Handle<BytecodeArray> bytecode_array,
413 const BytecodeLivenessMap& liveness_map, Zone* zone) {
414 switch (bytecode) {
415#define BYTECODE_UPDATE_LIVENESS(Name, ...) \
416 case Bytecode::k##Name: \
417 return UpdateLiveness<IsFirstUpdate, Bytecode::k##Name, __VA_ARGS__>( \
418 liveness, next_bytecode_in_liveness, iterator, bytecode_array, \
419 liveness_map, zone);
420 BYTECODE_LIST(BYTECODE_UPDATE_LIVENESS)BYTECODE_UPDATE_LIVENESS(Wide, ImplicitRegisterUse::kNone) BYTECODE_UPDATE_LIVENESS
(ExtraWide, ImplicitRegisterUse::kNone) BYTECODE_UPDATE_LIVENESS
(DebugBreakWide, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS
(DebugBreakExtraWide, ImplicitRegisterUse::kReadWriteAccumulator
) BYTECODE_UPDATE_LIVENESS(DebugBreak0, ImplicitRegisterUse::
kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS(DebugBreak1, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg) BYTECODE_UPDATE_LIVENESS
(DebugBreak2, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kReg) BYTECODE_UPDATE_LIVENESS(DebugBreak3
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kReg, OperandType::kReg) BYTECODE_UPDATE_LIVENESS
(DebugBreak4, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kReg, OperandType::kReg
) BYTECODE_UPDATE_LIVENESS(DebugBreak5, ImplicitRegisterUse::
kReadWriteAccumulator, OperandType::kRuntimeId, OperandType::
kReg, OperandType::kReg) BYTECODE_UPDATE_LIVENESS(DebugBreak6
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kRuntimeId
, OperandType::kReg, OperandType::kReg, OperandType::kReg) BYTECODE_UPDATE_LIVENESS
(Ldar, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg
) BYTECODE_UPDATE_LIVENESS(LdaZero, ImplicitRegisterUse::kWriteAccumulator
) BYTECODE_UPDATE_LIVENESS(LdaSmi, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kImm) BYTECODE_UPDATE_LIVENESS(LdaUndefined, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS(LdaNull, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS(LdaTheHole, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS(LdaTrue, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS(LdaFalse, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS(LdaConstant, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(LdaContextSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(LdaImmutableContextSlot, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kReg, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(LdaCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(LdaImmutableCurrentContextSlot
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(Star, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut
) BYTECODE_UPDATE_LIVENESS(Mov, ImplicitRegisterUse::kNone, OperandType
::kReg, OperandType::kRegOut) BYTECODE_UPDATE_LIVENESS(PushContext
, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut
) BYTECODE_UPDATE_LIVENESS(PopContext, ImplicitRegisterUse::kNone
, OperandType::kReg) BYTECODE_UPDATE_LIVENESS(TestReferenceEqual
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
) BYTECODE_UPDATE_LIVENESS(TestUndetectable, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS(TestNull, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS(TestUndefined
, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS
(TestTypeOf, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kFlag8) BYTECODE_UPDATE_LIVENESS(LdaGlobal, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(LdaGlobalInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(StaGlobal, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(StaContextSlot
, ImplicitRegisterUse::kReadAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS(StaCurrentContextSlot
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(LdaLookupSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(LdaLookupContextSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(LdaLookupGlobalSlot, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(LdaLookupSlotInsideTypeof, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(LdaLookupContextSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(LdaLookupGlobalSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(StaLookupSlot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_LIVENESS(GetNamedProperty
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(GetNamedPropertyFromSuper
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(GetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(LdaModuleVariable, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kImm, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS(StaModuleVariable
, ImplicitRegisterUse::kReadAccumulator, OperandType::kImm, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(SetNamedProperty, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(DefineNamedOwnProperty
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(SetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(DefineKeyedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(StaInArrayLiteral, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator
, OperandType::kReg, OperandType::kReg, OperandType::kFlag8, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(CollectTypeProfile, ImplicitRegisterUse
::kReadAccumulator, OperandType::kImm) BYTECODE_UPDATE_LIVENESS
(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(Sub, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(Mul, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(Div, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(Mod, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(Exp, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(BitwiseOr, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(BitwiseXor
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(BitwiseAnd, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(ShiftLeft, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(ShiftRight, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(ShiftRightLogical
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(AddSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(SubSmi, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(MulSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(DivSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(ModSmi, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(ExpSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(BitwiseOrSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(BitwiseXorSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(BitwiseAndSmi, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(ShiftLeftSmi, ImplicitRegisterUse::
kReadWriteAccumulator, OperandType::kImm, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(ShiftRightSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kImm, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(ShiftRightLogicalSmi
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(Inc, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(Dec, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(Negate, ImplicitRegisterUse::
kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(BitwiseNot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(ToBooleanLogicalNot, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS(LogicalNot,
ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS
(TypeOf, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS
(DeletePropertyStrict, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg) BYTECODE_UPDATE_LIVENESS(DeletePropertySloppy
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
) BYTECODE_UPDATE_LIVENESS(GetSuperConstructor, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_LIVENESS
(CallAnyReceiver, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kRegList, OperandType::kRegCount, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(CallProperty, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kRegList
, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CallProperty0, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CallProperty1, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(CallProperty2, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kReg, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CallUndefinedReceiver, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kReg, OperandType::kRegList, OperandType::kRegCount
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(CallUndefinedReceiver0
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(CallUndefinedReceiver1, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(CallUndefinedReceiver2, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kReg, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(CallWithSpread
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kRegList, OperandType::kRegCount, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CallRuntime, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kRuntimeId, OperandType::kRegList, OperandType::kRegCount) BYTECODE_UPDATE_LIVENESS
(CallRuntimeForPair, ImplicitRegisterUse::kNone, OperandType::
kRuntimeId, OperandType::kRegList, OperandType::kRegCount, OperandType
::kRegOutPair) BYTECODE_UPDATE_LIVENESS(CallJSRuntime, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kNativeContextIndex, OperandType
::kRegList, OperandType::kRegCount) BYTECODE_UPDATE_LIVENESS(
InvokeIntrinsic, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIntrinsicId, OperandType::kRegList, OperandType::kRegCount
) BYTECODE_UPDATE_LIVENESS(Construct, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kRegList, OperandType::kRegCount
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(ConstructWithSpread
, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg
, OperandType::kRegList, OperandType::kRegCount, OperandType::
kIdx) BYTECODE_UPDATE_LIVENESS(TestEqual, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(TestEqualStrict, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(TestLessThan, ImplicitRegisterUse::
kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(TestGreaterThan, ImplicitRegisterUse::kReadWriteAccumulator,
OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(TestLessThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(TestGreaterThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator
, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(TestInstanceOf, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(TestIn, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kReg, OperandType::kIdx
) BYTECODE_UPDATE_LIVENESS(ToName, ImplicitRegisterUse::kReadAccumulator
, OperandType::kRegOut) BYTECODE_UPDATE_LIVENESS(ToNumber, ImplicitRegisterUse
::kReadWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(ToObject, ImplicitRegisterUse
::kReadAccumulator, OperandType::kRegOut) BYTECODE_UPDATE_LIVENESS
(ToString, ImplicitRegisterUse::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS
(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator,
OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_LIVENESS
(CreateArrayLiteral, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_LIVENESS
(CreateArrayFromIterable, ImplicitRegisterUse::kReadWriteAccumulator
) BYTECODE_UPDATE_LIVENESS(CreateEmptyArrayLiteral, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CreateObjectLiteral, ImplicitRegisterUse::kWriteAccumulator,
OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_LIVENESS
(CreateEmptyObjectLiteral, ImplicitRegisterUse::kWriteAccumulator
) BYTECODE_UPDATE_LIVENESS(CloneObject, ImplicitRegisterUse::
kWriteAccumulator, OperandType::kReg, OperandType::kFlag8, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(GetTemplateObject, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CreateClosure, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kIdx, OperandType::kFlag8) BYTECODE_UPDATE_LIVENESS
(CreateBlockContext, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(CreateCatchContext, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(CreateFunctionContext, ImplicitRegisterUse::kWriteAccumulator
, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(CreateEvalContext, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS(CreateWithContext
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(CreateMappedArguments, ImplicitRegisterUse
::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS(CreateUnmappedArguments
, ImplicitRegisterUse::kWriteAccumulator) BYTECODE_UPDATE_LIVENESS
(CreateRestParameter, ImplicitRegisterUse::kWriteAccumulator)
BYTECODE_UPDATE_LIVENESS(JumpLoop, ImplicitRegisterUse::kNone
, OperandType::kUImm, OperandType::kImm) BYTECODE_UPDATE_LIVENESS
(Jump, ImplicitRegisterUse::kNone, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(JumpConstant, ImplicitRegisterUse::kNone, OperandType::kIdx)
BYTECODE_UPDATE_LIVENESS(JumpIfNullConstant, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(JumpIfNotNullConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(JumpIfUndefinedConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(JumpIfNotUndefinedConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(JumpIfUndefinedOrNullConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(JumpIfTrueConstant, ImplicitRegisterUse::kReadAccumulator, OperandType
::kIdx) BYTECODE_UPDATE_LIVENESS(JumpIfFalseConstant, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(JumpIfJSReceiverConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(JumpIfToBooleanTrueConstant
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(JumpIfToBooleanFalseConstant, ImplicitRegisterUse::kReadAccumulator
, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(JumpIfToBooleanTrue
, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(JumpIfToBooleanFalse, ImplicitRegisterUse::kReadAccumulator,
OperandType::kUImm) BYTECODE_UPDATE_LIVENESS(JumpIfTrue, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(JumpIfFalse, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(JumpIfNull, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(JumpIfNotNull, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(JumpIfUndefined, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(JumpIfNotUndefined, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(JumpIfUndefinedOrNull, ImplicitRegisterUse
::kReadAccumulator, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(JumpIfJSReceiver, ImplicitRegisterUse::kReadAccumulator, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(SwitchOnSmiNoFeedback, ImplicitRegisterUse
::kReadAccumulator, OperandType::kIdx, OperandType::kUImm, OperandType
::kImm) BYTECODE_UPDATE_LIVENESS(ForInEnumerate, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg) BYTECODE_UPDATE_LIVENESS
(ForInPrepare, ImplicitRegisterUse::kReadWriteAccumulator, OperandType
::kRegOutTriple, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(
ForInContinue, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg, OperandType::kReg) BYTECODE_UPDATE_LIVENESS(ForInNext
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kReg, OperandType::kRegPair, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(ForInStep, ImplicitRegisterUse::kWriteAccumulator, OperandType
::kReg) BYTECODE_UPDATE_LIVENESS(SetPendingMessage, ImplicitRegisterUse
::kReadWriteAccumulator) BYTECODE_UPDATE_LIVENESS(Throw, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_LIVENESS(ReThrow, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_LIVENESS(Return, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_LIVENESS(ThrowReferenceErrorIfHole
, ImplicitRegisterUse::kReadAccumulator, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(ThrowSuperNotCalledIfHole, ImplicitRegisterUse::kReadAccumulator
) BYTECODE_UPDATE_LIVENESS(ThrowSuperAlreadyCalledIfNotHole, ImplicitRegisterUse
::kReadAccumulator) BYTECODE_UPDATE_LIVENESS(ThrowIfNotSuperConstructor
, ImplicitRegisterUse::kNone, OperandType::kReg) BYTECODE_UPDATE_LIVENESS
(SwitchOnGeneratorState, ImplicitRegisterUse::kNone, OperandType
::kReg, OperandType::kIdx, OperandType::kUImm) BYTECODE_UPDATE_LIVENESS
(SuspendGenerator, ImplicitRegisterUse::kReadAccumulator, OperandType
::kReg, OperandType::kRegList, OperandType::kRegCount, OperandType
::kUImm) BYTECODE_UPDATE_LIVENESS(ResumeGenerator, ImplicitRegisterUse
::kWriteAccumulator, OperandType::kReg, OperandType::kRegOutList
, OperandType::kRegCount) BYTECODE_UPDATE_LIVENESS(GetIterator
, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, OperandType
::kIdx, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS(Debugger,
ImplicitRegisterUse::kNone) BYTECODE_UPDATE_LIVENESS(IncBlockCounter
, ImplicitRegisterUse::kNone, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(Abort, ImplicitRegisterUse::kNone, OperandType::kIdx) BYTECODE_UPDATE_LIVENESS
(Star15, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)
BYTECODE_UPDATE_LIVENESS(Star14, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star13, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star12, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star11, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star10, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star9, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star8, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star7, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star6, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star5, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star4, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star3, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star2, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star1, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Star0, ImplicitRegisterUse::kReadAccumulatorWriteShortStar
) BYTECODE_UPDATE_LIVENESS(Illegal, ImplicitRegisterUse::kNone
)
421#undef BYTECODE_UPDATE_LIVENESS
422 }
423}
424
425void UpdateAssignments(Bytecode bytecode, BytecodeLoopAssignments* assignments,
426 const interpreter::BytecodeArrayIterator& iterator) {
427 int num_operands = Bytecodes::NumberOfOperands(bytecode);
428 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
429
430 for (int i = 0; i < num_operands; ++i) {
431 switch (operand_types[i]) {
432 case OperandType::kRegOut: {
433 assignments->Add(iterator.GetRegisterOperand(i));
434 break;
435 }
436 case OperandType::kRegOutList: {
437 interpreter::Register r = iterator.GetRegisterOperand(i++);
438 uint32_t reg_count = iterator.GetRegisterCountOperand(i);
439 assignments->AddList(r, reg_count);
440 break;
441 }
442 case OperandType::kRegOutPair: {
443 assignments->AddList(iterator.GetRegisterOperand(i), 2);
444 break;
445 }
446 case OperandType::kRegOutTriple: {
447 assignments->AddList(iterator.GetRegisterOperand(i), 3);
448 break;
449 }
450 default:
451 DCHECK(!Bytecodes::IsRegisterOutputOperandType(operand_types[i]))((void) 0);
452 break;
453 }
454 }
455
456 if (Bytecodes::WritesImplicitRegister(bytecode)) {
457 assignments->Add(interpreter::Register::FromShortStar(bytecode));
458 }
459}
460
461} // namespace
462
463void BytecodeAnalysis::Analyze() {
464 loop_stack_.push({-1, nullptr});
465
466 BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
467 int generator_switch_index = -1;
468 int osr_loop_end_offset = osr_bailout_id_.ToInt();
469 DCHECK_EQ(osr_loop_end_offset < 0, osr_bailout_id_.IsNone())((void) 0);
470
471 interpreter::BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
472
473 bytecode_count_ = iterator.size();
474 if (analyze_liveness_) {
475 liveness_map_.emplace(bytecode_array()->length(), zone());
476 }
477
478 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
479 Bytecode bytecode = iterator.current_bytecode();
480 int current_offset = iterator.current_offset();
481
482 if (bytecode == Bytecode::kSwitchOnGeneratorState) {
483 DCHECK_EQ(generator_switch_index, -1)((void) 0);
484 generator_switch_index = iterator.current_index();
485 } else if (bytecode == Bytecode::kJumpLoop) {
486 // Every byte up to and including the last byte within the backwards jump
487 // instruction is considered part of the loop, set loop end accordingly.
488 int loop_end = current_offset + iterator.current_bytecode_size();
489 int loop_header = iterator.GetJumpTargetOffset();
490 PushLoop(loop_header, loop_end);
491
492 if (current_offset == osr_loop_end_offset) {
493 osr_entry_point_ = loop_header;
494 } else if (current_offset < osr_loop_end_offset) {
495 // Assert that we've found the osr_entry_point if we've gone past the
496 // osr_loop_end_offset. Note, we are iterating the bytecode in reverse,
497 // so the less-than in the above condition is correct.
498 DCHECK_LE(0, osr_entry_point_)((void) 0);
499 }
500
501 // Save the index so that we can do another pass later.
502 if (analyze_liveness_) {
503 loop_end_index_queue_.push_back(iterator.current_index());
504 }
505 }
506
507 // We have to pop from loop_stack_ if:
508 // 1) We entered the body of the loop
509 // 2) If we have a JumpLoop that jumps to itself (i.e an empty loop)
510 bool pop_current_loop = loop_stack_.size() > 1 &&
511 (bytecode != Bytecode::kJumpLoop ||
512 iterator.GetJumpTargetOffset() == current_offset);
513
514 if (pop_current_loop) {
515 LoopStackEntry& current_loop = loop_stack_.top();
516 LoopInfo* current_loop_info = current_loop.loop_info;
517
518 // TODO(leszeks): Ideally, we'd only set values that were assigned in
519 // the loop *and* are live when the loop exits. However, this requires
520 // tracking the out-liveness of *all* loop exits, which is not
521 // information we currently have.
522 UpdateAssignments(bytecode, &current_loop_info->assignments(), iterator);
523
524 // Update suspend counts for this loop.
525 if (bytecode == Bytecode::kSuspendGenerator) {
526 int suspend_id = iterator.GetUnsignedImmediateOperand(3);
527 int resume_offset = current_offset + iterator.current_bytecode_size();
528 current_loop_info->AddResumeTarget(
529 ResumeJumpTarget::Leaf(suspend_id, resume_offset));
530 }
531
532 // If we've reached the header of the loop, pop it off the stack.
533 if (current_offset == current_loop.header_offset) {
534 loop_stack_.pop();
535 if (loop_stack_.size() > 1) {
536 // If there is still an outer loop, propagate inner loop assignments.
537 LoopInfo* parent_loop_info = loop_stack_.top().loop_info;
538
539 parent_loop_info->assignments().Union(
540 current_loop_info->assignments());
541
542 // Also, propagate resume targets. Instead of jumping to the target
543 // itself, the outer loop will jump to this loop header for any
544 // targets that are inside the current loop, so that this loop stays
545 // reducible. Hence, a nested loop of the form:
546 //
547 // switch (#1 -> suspend1, #2 -> suspend2)
548 // loop {
549 // suspend1: suspend #1
550 // loop {
551 // suspend2: suspend #2
552 // }
553 // }
554 //
555 // becomes:
556 //
557 // switch (#1 -> loop1, #2 -> loop1)
558 // loop1: loop {
559 // switch (#1 -> suspend1, #2 -> loop2)
560 // suspend1: suspend #1
561 // loop2: loop {
562 // switch (#2 -> suspend2)
563 // suspend2: suspend #2
564 // }
565 // }
566 for (const auto& target : current_loop_info->resume_jump_targets()) {
567 parent_loop_info->AddResumeTarget(
568 ResumeJumpTarget::AtLoopHeader(current_offset, target));
569 }
570
571 } else {
572 // Otherwise, just propagate inner loop suspends to top-level.
573 for (const auto& target : current_loop_info->resume_jump_targets()) {
574 resume_jump_targets_.push_back(
575 ResumeJumpTarget::AtLoopHeader(current_offset, target));
576 }
577 }
578 }
579 } else if (bytecode == Bytecode::kSuspendGenerator) {
580 // If we're not in a loop, we still need to look for suspends.
581 // TODO(leszeks): It would be nice to de-duplicate this with the in-loop
582 // case
583 int suspend_id = iterator.GetUnsignedImmediateOperand(3);
584 int resume_offset = current_offset + iterator.current_bytecode_size();
585 resume_jump_targets_.push_back(
586 ResumeJumpTarget::Leaf(suspend_id, resume_offset));
587 }
588
589 if (analyze_liveness_) {
590 BytecodeLiveness& liveness =
591 liveness_map().InsertNewLiveness(current_offset);
592 UpdateLiveness<true>(bytecode, liveness, &next_bytecode_in_liveness,
593 iterator, bytecode_array(), liveness_map(), zone());
594 }
595 }
596
597 DCHECK_EQ(loop_stack_.size(), 1u)((void) 0);
598 DCHECK_EQ(loop_stack_.top().header_offset, -1)((void) 0);
599
600 DCHECK(ResumeJumpTargetsAreValid())((void) 0);
601
602 if (!analyze_liveness_) return;
603
604 // At this point, every bytecode has a valid in and out liveness, except for
605 // propagating liveness across back edges (i.e. JumpLoop). Subsequent liveness
606 // analysis iterations can only add additional liveness bits that are pulled
607 // across these back edges.
608 //
609 // Furthermore, a loop header's in-liveness can only change based on any
610 // bytecodes *after* the loop end -- it cannot change as a result of the
611 // JumpLoop liveness being updated, as the only liveness bits than can be
612 // added to the loop body are those of the loop header.
613 //
614 // So, if we know that the liveness of bytecodes after a loop header won't
615 // change (e.g. because there are no loops in them, or we have already ensured
616 // those loops are valid), we can safely update the loop end and pass over the
617 // loop body, and then never have to pass over that loop end again, because we
618 // have shown that its target, the loop header, can't change from the entries
619 // after the loop, and can't change from any loop body pass.
620 //
621 // This means that in a pass, we can iterate backwards over the bytecode
622 // array, process any loops that we encounter, and on subsequent passes we can
623 // skip processing those loops (though we still have to process inner loops).
624 //
625 // Equivalently, we can queue up loop ends from back to front, and pass over
626 // the loops in that order, as this preserves both the bottom-to-top and
627 // outer-to-inner requirements.
628
629 for (int loop_end_index : loop_end_index_queue_) {
630 iterator.GoToIndex(loop_end_index);
631
632 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop)((void) 0);
633
634 int header_offset = iterator.GetJumpTargetOffset();
635 int end_offset = iterator.current_offset();
636
637 BytecodeLiveness& header_liveness =
638 liveness_map().GetLiveness(header_offset);
639 BytecodeLiveness& end_liveness = liveness_map().GetLiveness(end_offset);
640
641 if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) {
642 // Only update the loop body if the loop end liveness changed.
643 continue;
644 }
645 end_liveness.in->CopyFrom(*end_liveness.out);
646 next_bytecode_in_liveness = end_liveness.in;
647
648 // Advance into the loop body.
649 --iterator;
650 for (; iterator.current_offset() > header_offset; --iterator) {
651 Bytecode bytecode = iterator.current_bytecode();
652 int current_offset = iterator.current_offset();
653 BytecodeLiveness& liveness = liveness_map().GetLiveness(current_offset);
654 UpdateLiveness(bytecode, liveness, &next_bytecode_in_liveness, iterator,
655 bytecode_array(), liveness_map(), zone());
656 }
657 // Now we are at the loop header. Since the in-liveness of the header
658 // can't change, we need only to update the out-liveness.
659 UpdateOutLiveness(iterator.current_bytecode(), header_liveness,
660 next_bytecode_in_liveness, iterator, bytecode_array(),
661 liveness_map(), zone());
662 }
663
664 // Process the generator switch statement separately, once the loops are done.
665 // This has to be a separate pass because the generator switch can jump into
666 // the middle of loops (and is the only kind of jump that can jump across a
667 // loop header).
668 if (generator_switch_index != -1) {
669 iterator.GoToIndex(generator_switch_index);
670 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kSwitchOnGeneratorState)((void) 0);
671
672 int current_offset = iterator.current_offset();
673 BytecodeLiveness& switch_liveness =
674 liveness_map().GetLiveness(current_offset);
675
676 bool any_changed = false;
677 for (interpreter::JumpTableTargetOffset entry :
678 iterator.GetJumpTableTargetOffsets()) {
679 if (switch_liveness.out->UnionIsChanged(
680 *liveness_map().GetInLiveness(entry.target_offset))) {
681 any_changed = true;
682 }
683 }
684
685 // If the switch liveness changed, we have to propagate it up the remaining
686 // bytecodes before it.
687 if (any_changed) {
688 switch_liveness.in->CopyFrom(*switch_liveness.out);
689 UpdateInLiveness(Bytecode::kSwitchOnGeneratorState, switch_liveness.in,
690 iterator);
691 next_bytecode_in_liveness = switch_liveness.in;
692 for (--iterator; iterator.IsValid(); --iterator) {
693 Bytecode bytecode = iterator.current_bytecode();
694 BytecodeLiveness& liveness =
695 liveness_map().GetLiveness(iterator.current_offset());
696
697 // There shouldn't be any more loops.
698 DCHECK_NE(bytecode, Bytecode::kJumpLoop)((void) 0);
699
700 UpdateLiveness(bytecode, liveness, &next_bytecode_in_liveness, iterator,
701 bytecode_array(), liveness_map(), zone());
702 }
703 }
704 }
705
706 DCHECK(analyze_liveness_)((void) 0);
707 if (FLAG_trace_environment_liveness) {
708 StdoutStream of;
709 PrintLivenessTo(of);
710 }
711
712 DCHECK(LivenessIsValid())((void) 0);
713}
714
715void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) {
716 DCHECK_LT(loop_header, loop_end)((void) 0);
717 DCHECK_LT(loop_stack_.top().header_offset, loop_header)((void) 0);
718 DCHECK_EQ(end_to_header_.find(loop_end), end_to_header_.end())((void) 0);
719 DCHECK_EQ(header_to_info_.find(loop_header), header_to_info_.end())((void) 0);
720
721 int parent_offset = loop_stack_.top().header_offset;
722
723 end_to_header_.insert({loop_end, loop_header});
724 auto it = header_to_info_.insert(
725 {loop_header, LoopInfo(parent_offset, bytecode_array_->parameter_count(),
726 bytecode_array_->register_count(), zone_)});
727 // Get the loop info pointer from the output of insert.
728 LoopInfo* loop_info = &it.first->second;
729
730 loop_stack_.push({loop_header, loop_info});
731}
732
733bool BytecodeAnalysis::IsLoopHeader(int offset) const {
734 return header_to_info_.find(offset) != header_to_info_.end();
735}
736
737int BytecodeAnalysis::GetLoopOffsetFor(int offset) const {
738 auto loop_end_to_header = end_to_header_.upper_bound(offset);
739 // If there is no next end => offset is not in a loop.
740 if (loop_end_to_header == end_to_header_.end()) {
741 return -1;
742 }
743 // If the header precedes the offset, this is the loop
744 //
745 // .> header <--loop_end_to_header
746 // |
747 // | <--offset
748 // |
749 // `- end
750 if (loop_end_to_header->second <= offset) {
751 return loop_end_to_header->second;
752 }
753 // Otherwise there is a (potentially nested) loop after this offset.
754 //
755 // <--offset
756 //
757 // .> header
758 // |
759 // | .> header <--loop_end_to_header
760 // | |
761 // | `- end
762 // |
763 // `- end
764 // We just return the parent of the next loop (might be -1).
765 DCHECK(header_to_info_.upper_bound(offset) != header_to_info_.end())((void) 0);
766
767 return header_to_info_.upper_bound(offset)->second.parent_offset();
768}
769
770const LoopInfo& BytecodeAnalysis::GetLoopInfoFor(int header_offset) const {
771 DCHECK(IsLoopHeader(header_offset))((void) 0);
772
773 return header_to_info_.find(header_offset)->second;
774}
775
776const LoopInfo* BytecodeAnalysis::TryGetLoopInfoFor(int header_offset) const {
777 auto it = header_to_info_.find(header_offset);
778 if (it == header_to_info_.end()) return nullptr;
779 return &it->second;
780}
781
782const BytecodeLivenessState* BytecodeAnalysis::GetInLivenessFor(
783 int offset) const {
784 if (!analyze_liveness_) return nullptr;
785
786 return liveness_map().GetInLiveness(offset);
787}
788
789const BytecodeLivenessState* BytecodeAnalysis::GetOutLivenessFor(
790 int offset) const {
791 if (!analyze_liveness_) return nullptr;
792
793 return liveness_map().GetOutLiveness(offset);
794}
795
796std::ostream& BytecodeAnalysis::PrintLivenessTo(std::ostream& os) const {
797 interpreter::BytecodeArrayIterator iterator(bytecode_array());
798
799 for (; !iterator.done(); iterator.Advance()) {
800 int current_offset = iterator.current_offset();
801
802 const BytecodeLivenessState* in_liveness = GetInLivenessFor(current_offset);
803 const BytecodeLivenessState* out_liveness =
804 GetOutLivenessFor(current_offset);
805
806 os << ToString(*in_liveness) << " -> " << ToString(*out_liveness) << " | "
807 << current_offset << ": ";
808 iterator.PrintTo(os) << std::endl;
809 }
810
811 return os;
812}
813
814#if DEBUG
815bool BytecodeAnalysis::ResumeJumpTargetsAreValid() {
816 bool valid = true;
817
818 // Find the generator switch.
819 interpreter::BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
820 for (iterator.GoToStart(); iterator.IsValid(); ++iterator) {
821 if (iterator.current_bytecode() == Bytecode::kSwitchOnGeneratorState) {
822 break;
823 }
824 }
825
826 // If the iterator is invalid, we've reached the end without finding the
827 // generator switch. So, ensure there are no jump targets and exit.
828 if (!iterator.IsValid()) {
829 // Check top-level.
830 if (!resume_jump_targets().empty()) {
831 PrintF(stderrstderr,
832 "Found %zu top-level resume targets but no resume switch\n",
833 resume_jump_targets().size());
834 valid = false;
835 }
836 // Check loops.
837 for (const std::pair<const int, LoopInfo>& loop_info : header_to_info_) {
838 if (!loop_info.second.resume_jump_targets().empty()) {
839 PrintF(stderrstderr,
840 "Found %zu resume targets at loop at offset %d, but no resume "
841 "switch\n",
842 loop_info.second.resume_jump_targets().size(), loop_info.first);
843 valid = false;
844 }
845 }
846
847 return valid;
848 }
849
850 // Otherwise, we've found the resume switch. Check that the top level jumps
851 // only to leaves and loop headers, then check that each loop header handles
852 // all the unresolved jumps, also jumping only to leaves and inner loop
853 // headers.
854
855 // First collect all required suspend ids.
856 std::map<int, int> unresolved_suspend_ids;
857 for (interpreter::JumpTableTargetOffset offset :
858 iterator.GetJumpTableTargetOffsets()) {
859 int suspend_id = offset.case_value;
860 int resume_offset = offset.target_offset;
861
862 unresolved_suspend_ids[suspend_id] = resume_offset;
863 }
864
865 // Check top-level.
866 if (!ResumeJumpTargetLeavesResolveSuspendIds(-1, resume_jump_targets(),
867 &unresolved_suspend_ids)) {
868 valid = false;
869 }
870 // Check loops.
871 for (const std::pair<const int, LoopInfo>& loop_info : header_to_info_) {
872 if (!ResumeJumpTargetLeavesResolveSuspendIds(
873 loop_info.first, loop_info.second.resume_jump_targets(),
874 &unresolved_suspend_ids)) {
875 valid = false;
876 }
877 }
878
879 // Check that everything is resolved.
880 if (!unresolved_suspend_ids.empty()) {
881 PrintF(stderrstderr,
882 "Found suspend ids that are not resolved by a final leaf resume "
883 "jump:\n");
884
885 for (const std::pair<const int, int>& target : unresolved_suspend_ids) {
886 PrintF(stderrstderr, " %d -> %d\n", target.first, target.second);
887 }
888 valid = false;
889 }
890
891 return valid;
892}
893
894bool BytecodeAnalysis::ResumeJumpTargetLeavesResolveSuspendIds(
895 int parent_offset, const ZoneVector<ResumeJumpTarget>& resume_jump_targets,
896 std::map<int, int>* unresolved_suspend_ids) {
897 bool valid = true;
898 for (const ResumeJumpTarget& target : resume_jump_targets) {
899 std::map<int, int>::iterator it =
900 unresolved_suspend_ids->find(target.suspend_id());
901 if (it == unresolved_suspend_ids->end()) {
902 PrintF(
903 stderrstderr,
904 "No unresolved suspend found for resume target with suspend id %d\n",
905 target.suspend_id());
906 valid = false;
907 continue;
908 }
909 int expected_target = it->second;
910
911 if (target.is_leaf()) {
912 // Leaves should have the expected target as their target.
913 if (target.target_offset() != expected_target) {
914 PrintF(
915 stderrstderr,
916 "Expected leaf resume target for id %d to have target offset %d, "
917 "but had %d\n",
918 target.suspend_id(), expected_target, target.target_offset());
919 valid = false;
920 } else {
921 // Make sure we're resuming to a Resume bytecode
922 interpreter::BytecodeArrayIterator iterator(bytecode_array(),
923 target.target_offset());
924 if (iterator.current_bytecode() != Bytecode::kResumeGenerator) {
925 PrintF(stderrstderr,
926 "Expected resume target for id %d, offset %d, to be "
927 "ResumeGenerator, but found %s\n",
928 target.suspend_id(), target.target_offset(),
929 Bytecodes::ToString(iterator.current_bytecode()));
930
931 valid = false;
932 }
933 }
934 // We've resolved this suspend id, so erase it to make sure we don't
935 // resolve it twice.
936 unresolved_suspend_ids->erase(it);
937 } else {
938 // Non-leaves should have a direct inner loop header as their target.
939 if (!IsLoopHeader(target.target_offset())) {
940 PrintF(stderrstderr,
941 "Expected non-leaf resume target for id %d to have a loop "
942 "header at target offset %d\n",
943 target.suspend_id(), target.target_offset());
944 valid = false;
945 } else {
946 LoopInfo loop_info = GetLoopInfoFor(target.target_offset());
947 if (loop_info.parent_offset() != parent_offset) {
948 PrintF(stderrstderr,
949 "Expected non-leaf resume target for id %d to have a direct "
950 "inner loop at target offset %d\n",
951 target.suspend_id(), target.target_offset());
952 valid = false;
953 }
954 // If the target loop is a valid inner loop, we'll check its validity
955 // when we analyze its resume targets.
956 }
957 }
958 }
959 return valid;
960}
961
962bool BytecodeAnalysis::LivenessIsValid() {
963 interpreter::BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
964
965 BytecodeLivenessState previous_liveness(bytecode_array()->register_count(),
966 zone());
967
968 int invalid_offset = -1;
969 int which_invalid = -1;
970 BytecodeLivenessState invalid_liveness(bytecode_array()->register_count(),
971 zone());
972
973 BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
974
975 // Ensure that there are no liveness changes if we iterate one more time.
976 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
977 Bytecode bytecode = iterator.current_bytecode();
978
979 int current_offset = iterator.current_offset();
980
981 BytecodeLiveness& liveness = liveness_map().GetLiveness(current_offset);
982
983 previous_liveness.CopyFrom(*liveness.out);
984
985 UpdateOutLiveness(bytecode, liveness, next_bytecode_in_liveness, iterator,
986 bytecode_array(), liveness_map(), zone());
987 // UpdateOutLiveness skips kJumpLoop, so we update it manually.
988 if (bytecode == Bytecode::kJumpLoop) {
989 int target_offset = iterator.GetJumpTargetOffset();
990 liveness.out->Union(*liveness_map().GetInLiveness(target_offset));
991 }
992
993 if (!liveness.out->Equals(previous_liveness)) {
994 invalid_liveness.CopyFrom(*liveness.out);
995 // Reset the invalid liveness.
996 liveness.out->CopyFrom(previous_liveness);
997 invalid_offset = current_offset;
998 which_invalid = 1;
999 break;
1000 }
1001
1002 previous_liveness.CopyFrom(*liveness.in);
1003
1004 liveness.in->CopyFrom(*liveness.out);
1005 UpdateInLiveness(bytecode, liveness.in, iterator);
1006
1007 if (!liveness.in->Equals(previous_liveness)) {
1008 invalid_liveness.CopyFrom(*liveness.in);
1009 // Reset the invalid liveness.
1010 liveness.in->CopyFrom(previous_liveness);
1011 invalid_offset = current_offset;
1012 which_invalid = 0;
1013 break;
1014 }
1015
1016 next_bytecode_in_liveness = liveness.in;
1017 }
1018
1019 // Ensure that the accumulator is not live when jumping out of a loop, or on
1020 // the back-edge of a loop.
1021 for (iterator.GoToStart(); iterator.IsValid() && invalid_offset == -1;
1022 ++iterator) {
1023 Bytecode bytecode = iterator.current_bytecode();
1024 int current_offset = iterator.current_offset();
1025 int loop_header = GetLoopOffsetFor(current_offset);
1026
1027 // We only care if we're inside a loop.
1028 if (loop_header == -1) continue;
1029
1030 // We only care about jumps.
1031 if (!Bytecodes::IsJump(bytecode)) continue;
1032
1033 int jump_target = iterator.GetJumpTargetOffset();
1034
1035 // If this is a forward jump to somewhere else in the same loop, ignore it.
1036 if (Bytecodes::IsForwardJump(bytecode) &&
1037 GetLoopOffsetFor(jump_target) == loop_header) {
1038 continue;
1039 }
1040
1041 // The accumulator must be dead at the start of the target of the jump.
1042 if (liveness_map().GetLiveness(jump_target).in->AccumulatorIsLive()) {
1043 invalid_offset = jump_target;
1044 which_invalid = 0;
1045 break;
1046 }
1047 }
1048
1049 if (invalid_offset != -1) {
1050 OFStream of(stderrstderr);
1051 of << "Invalid liveness:" << std::endl;
1052
1053 // Dump the bytecode, annotated with the liveness and marking loops.
1054
1055 int loop_indent = 0;
1056
1057 interpreter::BytecodeArrayIterator forward_iterator(bytecode_array());
1058 for (; !forward_iterator.done(); forward_iterator.Advance()) {
1059 int current_offset = forward_iterator.current_offset();
1060 const BytecodeLivenessState* in_liveness =
1061 GetInLivenessFor(current_offset);
1062 const BytecodeLivenessState* out_liveness =
1063 GetOutLivenessFor(current_offset);
1064
1065 std::string in_liveness_str = ToString(*in_liveness);
1066 std::string out_liveness_str = ToString(*out_liveness);
1067
1068 of << in_liveness_str << " | " << out_liveness_str << " : "
1069 << current_offset << " : ";
1070
1071 // Draw loop back edges by indentin everything between loop headers and
1072 // jump loop instructions.
1073 if (forward_iterator.current_bytecode() == Bytecode::kJumpLoop) {
1074 loop_indent--;
1075 }
1076 for (int i = 0; i < loop_indent; ++i) {
1077 of << "| ";
1078 }
1079 if (forward_iterator.current_bytecode() == Bytecode::kJumpLoop) {
1080 of << "`-";
1081 } else if (IsLoopHeader(current_offset)) {
1082 of << ".>";
1083 loop_indent++;
1084 }
1085 forward_iterator.PrintTo(of);
1086 if (Bytecodes::IsJump(forward_iterator.current_bytecode())) {
1087 of << " (@" << forward_iterator.GetJumpTargetOffset() << ")";
1088 }
1089 of << std::endl;
1090
1091 if (current_offset == invalid_offset) {
1092 // Underline the invalid liveness.
1093 char in_underline = which_invalid == 0 ? '^' : ' ';
1094 char out_underline = which_invalid == 0 ? ' ' : '^';
1095 of << std::string(in_liveness_str.size(), in_underline) << " "
1096 << std::string(out_liveness_str.size(), out_underline);
1097
1098 // Make sure to draw the loop indentation marks on this additional line.
1099 of << " : " << current_offset << " : ";
1100 for (int i = 0; i < loop_indent; ++i) {
1101 of << "| ";
1102 }
1103
1104 of << std::endl;
1105
1106 // Print the invalid liveness.
1107 if (which_invalid == 0) {
1108 of << ToString(invalid_liveness) << " "
1109 << std::string(out_liveness_str.size(), ' ');
1110 } else {
1111 of << std::string(in_liveness_str.size(), ' ') << " "
1112 << ToString(invalid_liveness);
1113 }
1114
1115 // Make sure to draw the loop indentation marks on this additional line.
1116 of << " : " << current_offset << " : ";
1117 for (int i = 0; i < loop_indent; ++i) {
1118 of << "| ";
1119 }
1120
1121 of << std::endl;
1122 }
1123 }
1124 }
1125
1126 return invalid_offset == -1;
1127}
1128#endif
1129
1130} // namespace compiler
1131} // namespace internal
1132} // namespace v8