| Index: src/arm64/lithium-arm64.cc
|
| diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc
|
| index d18808a587b1cd2a50dc9a58120786de46a978ea..d6b4176e9f7a82e20e741b4ae7ccb20da04890a7 100644
|
| --- a/src/arm64/lithium-arm64.cc
|
| +++ b/src/arm64/lithium-arm64.cc
|
| @@ -679,69 +679,76 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
| ASSERT(argument_count_ >= 0);
|
|
|
| if (instr != NULL) {
|
| - // Associate the hydrogen instruction first, since we may need it for
|
| - // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
|
| - instr->set_hydrogen_value(current);
|
| + AddInstruction(instr, current);
|
| + }
|
| +
|
| + current_instruction_ = old_current;
|
| +}
|
| +
|
| +
|
| +void LChunkBuilder::AddInstruction(LInstruction* instr,
|
| + HInstruction* hydrogen_val) {
|
| + // Associate the hydrogen instruction first, since we may need it for
|
| + // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
|
| + instr->set_hydrogen_value(hydrogen_val);
|
|
|
| #if DEBUG
|
| - // Make sure that the lithium instruction has either no fixed register
|
| - // constraints in temps or the result OR no uses that are only used at
|
| - // start. If this invariant doesn't hold, the register allocator can decide
|
| - // to insert a split of a range immediately before the instruction due to an
|
| - // already allocated register needing to be used for the instruction's fixed
|
| - // register constraint. In this case, the register allocator won't see an
|
| - // interference between the split child and the use-at-start (it would if
|
| - // the it was just a plain use), so it is free to move the split child into
|
| - // the same register that is used for the use-at-start.
|
| - // See https://code.google.com/p/chromium/issues/detail?id=201590
|
| - if (!(instr->ClobbersRegisters() &&
|
| - instr->ClobbersDoubleRegisters(isolate()))) {
|
| - int fixed = 0;
|
| - int used_at_start = 0;
|
| - for (UseIterator it(instr); !it.Done(); it.Advance()) {
|
| - LUnallocated* operand = LUnallocated::cast(it.Current());
|
| - if (operand->IsUsedAtStart()) ++used_at_start;
|
| - }
|
| - if (instr->Output() != NULL) {
|
| - if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
|
| - }
|
| - for (TempIterator it(instr); !it.Done(); it.Advance()) {
|
| - LUnallocated* operand = LUnallocated::cast(it.Current());
|
| - if (operand->HasFixedPolicy()) ++fixed;
|
| - }
|
| - ASSERT(fixed == 0 || used_at_start == 0);
|
| + // Make sure that the lithium instruction has either no fixed register
|
| + // constraints in temps or the result OR no uses that are only used at
|
| + // start. If this invariant doesn't hold, the register allocator can decide
|
| + // to insert a split of a range immediately before the instruction due to an
|
| + // already allocated register needing to be used for the instruction's fixed
|
| + // register constraint. In this case, the register allocator won't see an
|
| + // interference between the split child and the use-at-start (it would if
|
| + // the it was just a plain use), so it is free to move the split child into
|
| + // the same register that is used for the use-at-start.
|
| + // See https://code.google.com/p/chromium/issues/detail?id=201590
|
| + if (!(instr->ClobbersRegisters() &&
|
| + instr->ClobbersDoubleRegisters(isolate()))) {
|
| + int fixed = 0;
|
| + int used_at_start = 0;
|
| + for (UseIterator it(instr); !it.Done(); it.Advance()) {
|
| + LUnallocated* operand = LUnallocated::cast(it.Current());
|
| + if (operand->IsUsedAtStart()) ++used_at_start;
|
| + }
|
| + if (instr->Output() != NULL) {
|
| + if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
|
| }
|
| + for (TempIterator it(instr); !it.Done(); it.Advance()) {
|
| + LUnallocated* operand = LUnallocated::cast(it.Current());
|
| + if (operand->HasFixedPolicy()) ++fixed;
|
| + }
|
| + ASSERT(fixed == 0 || used_at_start == 0);
|
| + }
|
| #endif
|
|
|
| - if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
|
| - instr = AssignPointerMap(instr);
|
| - }
|
| - if (FLAG_stress_environments && !instr->HasEnvironment()) {
|
| - instr = AssignEnvironment(instr);
|
| + if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
|
| + instr = AssignPointerMap(instr);
|
| + }
|
| + if (FLAG_stress_environments && !instr->HasEnvironment()) {
|
| + instr = AssignEnvironment(instr);
|
| + }
|
| + chunk_->AddInstruction(instr, current_block_);
|
| +
|
| + if (instr->IsCall()) {
|
| + HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
|
| + LInstruction* instruction_needing_environment = NULL;
|
| + if (hydrogen_val->HasObservableSideEffects()) {
|
| + HSimulate* sim = HSimulate::cast(hydrogen_val->next());
|
| + instruction_needing_environment = instr;
|
| + sim->ReplayEnvironment(current_block_->last_environment());
|
| + hydrogen_value_for_lazy_bailout = sim;
|
| }
|
| - chunk_->AddInstruction(instr, current_block_);
|
| -
|
| - if (instr->IsCall()) {
|
| - HValue* hydrogen_value_for_lazy_bailout = current;
|
| - LInstruction* instruction_needing_environment = NULL;
|
| - if (current->HasObservableSideEffects()) {
|
| - HSimulate* sim = HSimulate::cast(current->next());
|
| - instruction_needing_environment = instr;
|
| - sim->ReplayEnvironment(current_block_->last_environment());
|
| - hydrogen_value_for_lazy_bailout = sim;
|
| - }
|
| - LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
|
| - bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
|
| - chunk_->AddInstruction(bailout, current_block_);
|
| - if (instruction_needing_environment != NULL) {
|
| - // Store the lazy deopt environment with the instruction if needed.
|
| - // Right now it is only used for LInstanceOfKnownGlobal.
|
| - instruction_needing_environment->
|
| - SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
|
| - }
|
| + LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
|
| + bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
|
| + chunk_->AddInstruction(bailout, current_block_);
|
| + if (instruction_needing_environment != NULL) {
|
| + // Store the lazy deopt environment with the instruction if needed.
|
| + // Right now it is only used for LInstanceOfKnownGlobal.
|
| + instruction_needing_environment->
|
| + SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
|
| }
|
| }
|
| - current_instruction_ = old_current;
|
| }
|
|
|
|
|
|
|