Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: src/compiler/bytecode-analysis-liveness.h

Issue 2523893003: Reland of [ignition/turbo] Perform liveness analysis on the bytecodes (Closed)
Patch Set: Fix debugger special casing and liveness disabling Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #ifndef V8_COMPILER_BYTECODE_ANALYSIS_LIVENESS_H_
6 #define V8_COMPILER_BYTECODE_ANALYSIS_LIVENESS_H_
7
8 #include "src/bit-vector.h"
9 #include "src/compiler/bytecode-liveness-map.h"
10 #include "src/interpreter/bytecode-array-accessor.h"
11 #include "src/interpreter/bytecodes.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
Jarin 2016/11/28 08:34:43 Why does this stuff have to live in a header?
rmcilroy 2016/11/28 10:00:30 +1. Could this not all just live in bytecode analy
Leszek Swirski 2016/11/28 10:11:01 I suppose it needn't, I moved it here while it was
16
17 using namespace interpreter;
18
19 void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
20 const BytecodeArrayAccessor& accessor) {
21 if (bytecode == Bytecode::kDebugger) {
22 // TODO(leszeks): Do we really need to keep everything alive for a debugger
23 // bytecode? Other ways of breaking the debugger here (such as a debugger
24 // statement in a called function) won't keep locals alive.
Jarin 2016/11/28 08:34:43 I am not sure what you are arguing for. We do want
Leszek Swirski 2016/11/28 10:11:01 I guess what I'm arguing is that this is a leaky a
Jarin 2016/11/28 12:05:42 I talked to Yang and he is happy not to keep varia
Leszek Swirski 2016/11/28 14:18:51 Ok, I'll update the relevant tests to disable live
25 in_liveness.AddAll();
26 return;
27 }
28
29 int num_operands = Bytecodes::NumberOfOperands(bytecode);
30 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
31 AccumulatorUse accumulator_use = Bytecodes::GetAccumulatorUse(bytecode);
32
33 if (accumulator_use == AccumulatorUse::kWrite) {
34 in_liveness.Remove(in_liveness.length() - 1);
35 }
36 for (int i = 0; i < num_operands; ++i) {
Jarin 2016/11/28 08:34:43 Aaaaah, no templates, beauuuuuuutiful.
Leszek Swirski 2016/11/28 10:11:01 :(
37 switch (operand_types[i]) {
38 case OperandType::kRegOut: {
39 interpreter::Register r = accessor.GetRegisterOperand(i);
40 if (!r.is_parameter()) {
41 in_liveness.Remove(r.index());
42 }
43 break;
44 }
45 case OperandType::kRegOutPair: {
46 interpreter::Register r = accessor.GetRegisterOperand(i);
47 if (!r.is_parameter()) {
Jarin 2016/11/28 08:34:43 Out of curiousity, do we ever have output register
Leszek Swirski 2016/11/28 10:11:01 Good point, I do make the assumption that lists of
48 in_liveness.Remove(r.index());
49 in_liveness.Remove(r.index() + 1);
50 }
51 break;
52 }
53 case OperandType::kRegOutTriple: {
54 interpreter::Register r = accessor.GetRegisterOperand(i);
55 if (!r.is_parameter()) {
56 in_liveness.Remove(r.index());
57 in_liveness.Remove(r.index() + 1);
58 in_liveness.Remove(r.index() + 2);
59 }
60 break;
61 }
62 default:
63 DCHECK(!Bytecodes::IsRegisterOutputOperandType(operand_types[i]));
64 break;
65 }
66 }
67
68 if (accumulator_use == AccumulatorUse::kRead) {
69 in_liveness.Add(in_liveness.length() - 1);
70 }
71 for (int i = 0; i < num_operands; ++i) {
72 switch (operand_types[i]) {
73 case OperandType::kReg: {
74 interpreter::Register r = accessor.GetRegisterOperand(i);
75 if (!r.is_parameter()) {
76 in_liveness.Add(r.index());
77 }
78 break;
79 }
80 case OperandType::kRegPair: {
81 interpreter::Register r = accessor.GetRegisterOperand(i);
82 if (!r.is_parameter()) {
83 in_liveness.Add(r.index());
84 in_liveness.Add(r.index() + 1);
85 }
86 break;
87 }
88 case OperandType::kRegList: {
89 interpreter::Register r = accessor.GetRegisterOperand(i);
rmcilroy 2016/11/28 10:00:30 nit - maybe you could add a GetRegisterListOperand
Leszek Swirski 2016/11/28 11:07:22 I'm not sure, liveness here is a raw BitVector so
rmcilroy 2016/11/28 15:16:37 I guess we are fine without it. Please add some co
Leszek Swirski 2016/11/28 16:31:11 Done.
90 i++;
91 if (!r.is_parameter()) {
rmcilroy 2016/11/28 10:00:30 Same comment as Jaro above regarding parameters. M
Leszek Swirski 2016/11/28 11:07:22 Done.
92 uint32_t reg_count = accessor.GetRegisterCountOperand(i);
93
94 for (uint32_t j = 0; j < reg_count; ++j) {
95 in_liveness.Add(r.index() + j);
96 }
97 }
98 }
99 default:
100 DCHECK(!Bytecodes::IsRegisterInputOperandType(operand_types[i]));
101 break;
102 }
103 }
104 }
105
106 void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness,
107 const BytecodeArrayAccessor& accessor,
108 const BytecodeLivenessMap& liveness_map) {
109 if (bytecode == Bytecode::kDebugger) {
110 // TODO(leszeks): Do we really need to keep everything alive for a debugger
111 // bytecode? Other ways of breaking the debugger here (such as a debugger
112 // statement in a called function) won't keep locals alive.
113 out_liveness.AddAll();
114 return;
115 }
116
117 int current_offset = accessor.current_offset();
118 const Handle<BytecodeArray>& bytecode_array = accessor.bytecode_array();
119
120 // Update from jump target (if any). Skip loops, we update these manually in
121 // the liveness iterations.
122 if (Bytecodes::IsForwardJump(bytecode)) {
123 int target_offset = accessor.GetJumpTargetOffset();
124 out_liveness.Union(*liveness_map.GetInLiveness(target_offset));
125 }
126
127 // Update from next bytecode (unless this is an unconditional jump).
128 if (!Bytecodes::IsJump(bytecode) || Bytecodes::IsConditionalJump(bytecode)) {
rmcilroy 2016/11/28 10:00:30 Nit - just add IsUnconditionalJump in bytecodes.h
Leszek Swirski 2016/11/28 11:07:22 Done, also gave me the chance to simplify it a bit
129 int next_offset = current_offset + accessor.current_bytecode_size();
130 if (next_offset < bytecode_array->length()) {
131 out_liveness.Union(*liveness_map.GetInLiveness(next_offset));
132 }
133 }
134
135 // Update from exception handler (if any).
136 if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
137 int handler_context;
138 int handler_offset = bytecode_array->LookupRangeInHandlerTable(
139 current_offset, &handler_context, nullptr);
140
141 if (handler_offset != -1) {
142 out_liveness.Union(*liveness_map.GetInLiveness(handler_offset));
143 out_liveness.Add(handler_context);
144 }
145 }
146 }
147
148 } // namespace compiler
149 } // namespace internal
150 } // namespace v8
151
152 #endif // V8_COMPILER_BYTECODE_ANALYSIS_LIVENESS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698