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

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: Rebase 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
(...skipping 19 matching lines...) Expand all
202 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( 210 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray(
203 int fixed_register_count, int parameter_count, 211 int fixed_register_count, int parameter_count,
204 Handle<FixedArray> handler_table) { 212 Handle<FixedArray> handler_table) {
205 FlushState(); 213 FlushState();
206 return next_stage_->ToBytecodeArray(fixed_register_count, parameter_count, 214 return next_stage_->ToBytecodeArray(fixed_register_count, parameter_count,
207 handler_table); 215 handler_table);
208 } 216 }
209 217
210 // override 218 // override
211 void BytecodeRegisterOptimizer::Write(BytecodeNode* node) { 219 void BytecodeRegisterOptimizer::Write(BytecodeNode* node) {
212 flushed_ = false;
213
214 // 220 //
215 // Transfers with observable registers as the destination will be 221 // Transfers with observable registers as the destination will be
216 // immediately materialized so the source position information will 222 // immediately materialized so the source position information will
217 // be ordered correctly. 223 // be ordered correctly.
218 // 224 //
219 // Transfers without observable destination registers will initially 225 // Transfers without observable destination registers will initially
220 // be emitted as Nop's with the source position. They may, or may 226 // be emitted as Nop's with the source position. They may, or may
221 // not, be materialized by the optimizer. However, the source 227 // not, be materialized by the optimizer. However, the source
222 // position is not lost and being attached to a Nop is fine as the 228 // position is not lost and being attached to a Nop is fine as the
223 // destination register is not observable in the debugger. 229 // destination register is not observable in the debugger.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 273
268 // override 274 // override
269 void BytecodeRegisterOptimizer::BindLabel(const BytecodeLabel& target, 275 void BytecodeRegisterOptimizer::BindLabel(const BytecodeLabel& target,
270 BytecodeLabel* label) { 276 BytecodeLabel* label) {
271 // There is no need to flush here, it will have been flushed when |target| 277 // There is no need to flush here, it will have been flushed when |target|
272 // was bound. 278 // was bound.
273 next_stage_->BindLabel(target, label); 279 next_stage_->BindLabel(target, label);
274 } 280 }
275 281
276 void BytecodeRegisterOptimizer::FlushState() { 282 void BytecodeRegisterOptimizer::FlushState() {
277 if (flushed_) { 283 if (!flush_required_) {
278 return; 284 return;
279 } 285 }
280 286
281 // Materialize all live registers. 287 // Materialize all live registers and break equivalences.
282 size_t count = register_info_table_.size(); 288 size_t count = register_info_table_.size();
283 for (size_t i = 0; i < count; ++i) { 289 for (size_t i = 0; i < count; ++i) {
284 RegisterInfo* reg_info = register_info_table_[i]; 290 RegisterInfo* reg_info = register_info_table_[i];
285 if (!reg_info->IsOnlyMemberOfEquivalenceSet() && 291 if (reg_info->materialized()) {
286 !reg_info->materialized()) { 292 // Walk equivalents of materialized registers, materializing
287 DCHECK(RegisterIsTemporary(reg_info->register_value()) || 293 // each equivalent register as necessary and placing in their
288 reg_info->register_value() == accumulator_); 294 // own equivalence set.
289 Materialize(reg_info); 295 RegisterInfo* equivalent;
296 while ((equivalent = reg_info->GetEquivalent()) != reg_info) {
297 if (!equivalent->materialized()) {
298 OutputRegisterTransfer(reg_info, equivalent);
299 }
300 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
301 }
290 } 302 }
291 } 303 }
292 304
293 // Break all existing equivalences. 305 flush_required_ = false;
294 for (size_t i = 0; i < count; ++i) {
295 RegisterInfo* reg_info = register_info_table_[i];
296 if (!reg_info->IsOnlyMemberOfEquivalenceSet()) {
297 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
298 }
299 }
300
301 flushed_ = true;
302 } 306 }
303 307
304 void BytecodeRegisterOptimizer::WriteToNextStage(BytecodeNode* node) const { 308 void BytecodeRegisterOptimizer::WriteToNextStage(BytecodeNode* node) const {
305 next_stage_->Write(node); 309 next_stage_->Write(node);
306 } 310 }
307 311
308 void BytecodeRegisterOptimizer::WriteToNextStage( 312 void BytecodeRegisterOptimizer::WriteToNextStage(
309 BytecodeNode* node, const BytecodeSourceInfo& source_info) const { 313 BytecodeNode* node, const BytecodeSourceInfo& source_info) const {
310 node->source_info().Update(source_info); 314 node->source_info().Update(source_info);
311 next_stage_->Write(node); 315 next_stage_->Write(node);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 return result; 373 return result;
370 } 374 }
371 375
372 void BytecodeRegisterOptimizer::Materialize(RegisterInfo* info) { 376 void BytecodeRegisterOptimizer::Materialize(RegisterInfo* info) {
373 if (!info->materialized()) { 377 if (!info->materialized()) {
374 RegisterInfo* materialized = info->GetMaterializedEquivalent(); 378 RegisterInfo* materialized = info->GetMaterializedEquivalent();
375 OutputRegisterTransfer(materialized, info); 379 OutputRegisterTransfer(materialized, info);
376 } 380 }
377 } 381 }
378 382
383 void BytecodeRegisterOptimizer::AddToEquivalenceSet(
384 RegisterInfo* set_member, RegisterInfo* non_set_member) {
385 non_set_member->AddToEquivalenceSetOf(set_member);
386 // Flushing is only required when two or more registers are placed
387 // in the same equivalence set.
388 flush_required_ = true;
389 }
390
379 void BytecodeRegisterOptimizer::RegisterTransfer( 391 void BytecodeRegisterOptimizer::RegisterTransfer(
380 RegisterInfo* input_info, RegisterInfo* output_info, 392 RegisterInfo* input_info, RegisterInfo* output_info,
381 const BytecodeSourceInfo& source_info) { 393 const BytecodeSourceInfo& source_info) {
382 // Materialize an alternate in the equivalence set that 394 // Materialize an alternate in the equivalence set that
383 // |output_info| is leaving. 395 // |output_info| is leaving.
384 if (output_info->materialized()) { 396 if (output_info->materialized()) {
385 CreateMaterializedEquivalent(output_info); 397 CreateMaterializedEquivalent(output_info);
386 } 398 }
387 399
388 // Add |output_info| to new equivalence set. 400 // Add |output_info| to new equivalence set.
389 if (!output_info->IsInSameEquivalenceSet(input_info)) { 401 if (!output_info->IsInSameEquivalenceSet(input_info)) {
390 output_info->AddToEquivalenceSetOf(input_info); 402 AddToEquivalenceSet(input_info, output_info);
391 } 403 }
392 404
393 bool output_is_observable = 405 bool output_is_observable =
394 RegisterIsObservable(output_info->register_value()); 406 RegisterIsObservable(output_info->register_value());
395 if (output_is_observable) { 407 if (output_is_observable) {
396 // Force store to be emitted when register is observable. 408 // Force store to be emitted when register is observable.
397 output_info->set_materialized(false); 409 output_info->set_materialized(false);
398 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); 410 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent();
399 OutputRegisterTransfer(materialized_info, output_info, source_info); 411 OutputRegisterTransfer(materialized_info, output_info, source_info);
400 } else if (source_info.is_valid()) { 412 } else if (source_info.is_valid()) {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 if (info->materialized()) { 627 if (info->materialized()) {
616 CreateMaterializedEquivalent(info); 628 CreateMaterializedEquivalent(info);
617 } 629 }
618 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false); 630 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false);
619 } 631 }
620 } 632 }
621 633
622 } // namespace interpreter 634 } // namespace interpreter
623 } // namespace internal 635 } // namespace internal
624 } // namespace v8 636 } // 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