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

Side by Side Diff: src/interpreter/bytecode-register-optimizer.cc

Issue 2033013002: [interpreter] Faster and fewer flushes in register optimizer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@oth-0061-tweaks
Patch Set: Created 4 years, 6 months 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
1 // Copyright 2016 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-register-optimizer.h" 5 #include "src/interpreter/bytecode-register-optimizer.h"
6 6
7 namespace v8 { 7 namespace v8 {
8 namespace internal { 8 namespace internal {
9 namespace interpreter { 9 namespace interpreter {
10 10
(...skipping 30 matching lines...) Expand all
41 RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg); 41 RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg);
42 42
43 // Get a member of this register's equivalence set that is intended 43 // Get a member of this register's equivalence set that is intended
44 // to be materialized in place of this register (which is currently 44 // to be materialized in place of this register (which is currently
45 // materialized). The best candidate is deemed to be the register 45 // materialized). The best candidate is deemed to be the register
46 // with the lowest index as this permits temporary registers to be 46 // with the lowest index as this permits temporary registers to be
47 // removed from the bytecode stream. Returns nullptr if no candidate 47 // removed from the bytecode stream. Returns nullptr if no candidate
48 // exists. 48 // exists.
49 RegisterInfo* GetEquivalentToMaterialize(); 49 RegisterInfo* GetEquivalentToMaterialize();
50 50
51 // Get an equivalent register. Returns this if none exists.
52 RegisterInfo* GetEquivalent();
53
51 Register register_value() const { return register_; } 54 Register register_value() const { return register_; }
52 bool materialized() const { return materialized_; } 55 bool materialized() const { return materialized_; }
53 void set_materialized(bool materialized) { materialized_ = materialized; } 56 void set_materialized(bool materialized) { materialized_ = materialized; }
54 void set_equivalence_id(uint32_t equivalence_id) { 57 void set_equivalence_id(uint32_t equivalence_id) {
55 equivalence_id_ = equivalence_id; 58 equivalence_id_ = equivalence_id;
56 } 59 }
57 uint32_t equivalence_id() const { return equivalence_id_; } 60 uint32_t equivalence_id() const { return equivalence_id_; }
58 61
59 private: 62 private:
60 Register register_; 63 Register register_;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 } 157 }
155 if (best_info == nullptr || 158 if (best_info == nullptr ||
156 visitor->register_value() < best_info->register_value()) { 159 visitor->register_value() < best_info->register_value()) {
157 best_info = visitor; 160 best_info = visitor;
158 } 161 }
159 visitor = visitor->next_; 162 visitor = visitor->next_;
160 } 163 }
161 return best_info; 164 return best_info;
162 } 165 }
163 166
167 BytecodeRegisterOptimizer::RegisterInfo*
168 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() {
169 return next_;
170 }
171
164 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( 172 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer(
165 Zone* zone, TemporaryRegisterAllocator* register_allocator, 173 Zone* zone, TemporaryRegisterAllocator* register_allocator,
166 int parameter_count, BytecodePipelineStage* next_stage) 174 int parameter_count, BytecodePipelineStage* next_stage)
167 : accumulator_(Register::virtual_accumulator()), 175 : accumulator_(Register::virtual_accumulator()),
168 temporary_base_(register_allocator->allocation_base()), 176 temporary_base_(register_allocator->allocation_base()),
169 register_info_table_(zone), 177 register_info_table_(zone),
170 equivalence_id_(0), 178 equivalence_id_(0),
171 next_stage_(next_stage), 179 next_stage_(next_stage),
172 flushed_(false), 180 flush_required_(false),
173 zone_(zone) { 181 zone_(zone) {
174 register_allocator->set_observer(this); 182 register_allocator->set_observer(this);
175 183
176 // Calculate offset so register index values can be mapped into 184 // Calculate offset so register index values can be mapped into
177 // a vector of register metadata. 185 // a vector of register metadata.
178 if (parameter_count != 0) { 186 if (parameter_count != 0) {
179 register_info_table_offset_ = 187 register_info_table_offset_ =
180 -Register::FromParameterIndex(0, parameter_count).index(); 188 -Register::FromParameterIndex(0, parameter_count).index();
181 } else { 189 } else {
182 // TODO(oth): This path shouldn't be necessary in bytecode generated 190 // TODO(oth): This path shouldn't be necessary in bytecode generated
183 // from Javascript, but a set of tests do not include the JS receiver. 191 // from Javascript, but a set of tests do not include the JS receiver.
184 register_info_table_offset_ = -accumulator_.index(); 192 register_info_table_offset_ = -accumulator_.index();
185 } 193 }
186 194
187 // Initialize register map for parameters, locals, and the 195 // Initialize register map for parameters, locals, and the
188 // accumulator. 196 // accumulator.
189 register_info_table_.resize(register_info_table_offset_ + 197 register_info_table_.resize(register_info_table_offset_ +
190 static_cast<size_t>(temporary_base_.index())); 198 static_cast<size_t>(temporary_base_.index()));
191 for (size_t i = 0; i < register_info_table_.size(); ++i) { 199 for (size_t i = 0; i < register_info_table_.size(); ++i) {
192 register_info_table_[i] = new (zone) RegisterInfo( 200 register_info_table_[i] = new (zone) RegisterInfo(
193 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true); 201 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true);
194 DCHECK_EQ(register_info_table_[i]->register_value().index(), 202 DCHECK_EQ(register_info_table_[i]->register_value().index(),
195 RegisterFromRegisterInfoTableIndex(i).index()); 203 RegisterFromRegisterInfoTableIndex(i).index());
196 } 204 }
197 accumulator_info_ = GetRegisterInfo(accumulator_); 205 accumulator_info_ = GetRegisterInfo(accumulator_);
198 DCHECK(accumulator_info_->register_value() == accumulator_); 206 DCHECK(accumulator_info_->register_value() == accumulator_);
199 } 207 }
200 208
201 void BytecodeRegisterOptimizer::FlushState() { 209 void BytecodeRegisterOptimizer::FlushState() {
202 if (flushed_) { 210 if (!flush_required_) {
203 return; 211 return;
204 } 212 }
205 213
206 // Materialize all live registers. 214 // Materialize all live registers and break equivalences.
207 size_t count = register_info_table_.size(); 215 size_t count = register_info_table_.size();
208 for (size_t i = 0; i < count; ++i) { 216 for (size_t i = 0; i < count; ++i) {
209 RegisterInfo* reg_info = register_info_table_[i]; 217 RegisterInfo* reg_info = register_info_table_[i];
210 if (!reg_info->IsOnlyMemberOfEquivalenceSet() && 218 if (reg_info->IsOnlyMemberOfEquivalenceSet() || !reg_info->materialized()) {
211 !reg_info->materialized()) { 219 continue;
rmcilroy 2016/06/02 12:51:33 nit - could you add a comment here that you are sk
oth 2016/06/02 14:14:24 Done.
212 DCHECK(RegisterIsTemporary(reg_info->register_value()) || 220 }
213 reg_info->register_value() == accumulator_); 221
214 Materialize(reg_info); 222 // Walk equivalents of this materialized register, materializing
223 // each equivalent if necessary and moving to own equivalent set.
224 RegisterInfo* equivalent;
225 while ((equivalent = reg_info->GetEquivalent()) != reg_info) {
226 if (!equivalent->materialized()) {
227 OutputRegisterTransfer(reg_info, equivalent);
228 }
229 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
215 } 230 }
216 } 231 }
217 232
218 // Break all existing equivalences. 233 flush_required_ = false;
219 for (size_t i = 0; i < count; ++i) {
220 RegisterInfo* reg_info = register_info_table_[i];
221 if (!reg_info->IsOnlyMemberOfEquivalenceSet()) {
222 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
223 }
224 }
225
226 flushed_ = true;
227 } 234 }
228 235
229 // override 236 // override
230 void BytecodeRegisterOptimizer::FlushBasicBlock() { 237 void BytecodeRegisterOptimizer::FlushBasicBlock() {
231 FlushState(); 238 FlushState();
232 next_stage_->FlushBasicBlock(); 239 next_stage_->FlushBasicBlock();
233 } 240 }
234 241
235 // override 242 // override
236 size_t BytecodeRegisterOptimizer::FlushForOffset() { 243 size_t BytecodeRegisterOptimizer::FlushForOffset() {
237 FlushState(); 244 FlushState();
238 return next_stage_->FlushForOffset(); 245 return next_stage_->FlushForOffset();
239 } 246 }
240 247
241 // override 248 // override
242 void BytecodeRegisterOptimizer::Write(BytecodeNode* node) { 249 void BytecodeRegisterOptimizer::Write(BytecodeNode* node) {
243 flushed_ = false;
244
245 // 250 //
246 // Transfers with observable registers as the destination will be 251 // Transfers with observable registers as the destination will be
247 // immediately materialized so the source position information will 252 // immediately materialized so the source position information will
248 // be ordered correctly. 253 // be ordered correctly.
249 // 254 //
250 // Transfers without observable destination registers will initially 255 // Transfers without observable destination registers will initially
251 // be emitted as Nop's with the source position. They may, or may 256 // be emitted as Nop's with the source position. They may, or may
252 // not, be materialized by the optimizer. However, the source 257 // not, be materialized by the optimizer. However, the source
253 // position is not lost and being attached to a Nop is fine as the 258 // position is not lost and being attached to a Nop is fine as the
254 // destination register is not observable in the debugger. 259 // destination register is not observable in the debugger.
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 const BytecodeSourceInfo& source_info) { 368 const BytecodeSourceInfo& source_info) {
364 // Materialize an alternate in the equivalence set that 369 // Materialize an alternate in the equivalence set that
365 // |output_info| is leaving. 370 // |output_info| is leaving.
366 if (output_info->materialized()) { 371 if (output_info->materialized()) {
367 CreateMaterializedEquivalent(output_info); 372 CreateMaterializedEquivalent(output_info);
368 } 373 }
369 374
370 // Add |output_info| to new equivalence set. 375 // Add |output_info| to new equivalence set.
371 if (!output_info->IsInSameEquivalenceSet(input_info)) { 376 if (!output_info->IsInSameEquivalenceSet(input_info)) {
372 output_info->AddToEquivalenceSetOf(input_info); 377 output_info->AddToEquivalenceSetOf(input_info);
378 flush_required_ = true;
rmcilroy 2016/06/02 12:51:34 This scares me a bit since if we add another call
oth 2016/06/02 14:14:24 Done. If flushes aren't correctly emitted many te
rmcilroy 2016/06/02 15:07:13 Acknowledged, I'm fine with this if you are.
373 } 379 }
374 380
375 bool output_is_observable = 381 bool output_is_observable =
376 RegisterIsObservable(output_info->register_value()); 382 RegisterIsObservable(output_info->register_value());
377 if (output_is_observable) { 383 if (output_is_observable) {
378 // Force store to be emitted when register is observable. 384 // Force store to be emitted when register is observable.
379 output_info->set_materialized(false); 385 output_info->set_materialized(false);
380 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); 386 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent();
381 OutputRegisterTransfer(materialized_info, output_info, source_info); 387 OutputRegisterTransfer(materialized_info, output_info, source_info);
382 } else if (source_info.is_valid()) { 388 } else if (source_info.is_valid()) {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 if (info->materialized()) { 603 if (info->materialized()) {
598 CreateMaterializedEquivalent(info); 604 CreateMaterializedEquivalent(info);
599 } 605 }
600 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false); 606 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false);
601 } 607 }
602 } 608 }
603 609
604 } // namespace interpreter 610 } // namespace interpreter
605 } // namespace internal 611 } // namespace internal
606 } // namespace v8 612 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-register-optimizer.h ('k') | test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698