| Index: runtime/vm/flow_graph_compiler_x64.cc
|
| diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
|
| index bfc547d799e1f43bf1596939da941407ebf53a44..baa818ca620b2d4427c263aed2777949e09758b6 100644
|
| --- a/runtime/vm/flow_graph_compiler_x64.cc
|
| +++ b/runtime/vm/flow_graph_compiler_x64.cc
|
| @@ -28,11 +28,34 @@ void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) {
|
| #define __ assem->
|
| __ Comment("Deopt stub for id %d", deopt_id_);
|
| __ Bind(entry_label());
|
| - for (intptr_t i = 0; i < registers_.length(); i++) {
|
| - if (registers_[i] != kNoRegister) {
|
| - __ pushq(registers_[i]);
|
| +
|
| + if (deoptimization_env_ == NULL) {
|
| + for (intptr_t i = 0; i < registers_.length(); i++) {
|
| + if (registers_[i] != kNoRegister) {
|
| + __ pushq(registers_[i]);
|
| + }
|
| + }
|
| + } else {
|
| + // We have a deoptimization environment, we have to tear down optimized
|
| + // frame and recreate non-optimized one.
|
| + __ leaq(RSP,
|
| + Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize));
|
| +
|
| + const ZoneGrowableArray<Value*>& values = deoptimization_env_->values();
|
| + const GrowableArray<Location>* locations = deoptimization_env_->locations();
|
| +
|
| + for (intptr_t i = 0; i < values.length(); i++) {
|
| + Location loc = (*locations)[i];
|
| + if (loc.IsInvalid()) {
|
| + ASSERT(values[i]->IsConstant());
|
| + __ PushObject(values[i]->AsConstant()->value());
|
| + } else {
|
| + ASSERT(loc.IsRegister());
|
| + __ pushq(loc.reg());
|
| + }
|
| }
|
| }
|
| +
|
| if (compiler->IsLeaf()) {
|
| Label L;
|
| __ call(&L);
|
| @@ -1081,6 +1104,50 @@ void FlowGraphCompiler::LoadDoubleOrSmiToXmm(XmmRegister result,
|
|
|
|
|
| #undef __
|
| +#define __ compiler_->assembler()->
|
| +
|
| +
|
| +void ParallelMoveResolver::EmitMove(int index) {
|
| + Location source = moves_[index].src();
|
| + Location destination = moves_[index].dest();
|
| +
|
| + ASSERT(destination.IsRegister());
|
| + if (source.IsRegister()) {
|
| + __ movq(destination.reg(), source.reg());
|
| + } else {
|
| + ASSERT(source.IsConstant());
|
| + __ LoadObject(destination.reg(), source.constant());
|
| + }
|
| + moves_[index].Eliminate();
|
| +}
|
| +
|
| +
|
| +void ParallelMoveResolver::EmitSwap(int index) {
|
| + Location source = moves_[index].src();
|
| + Location destination = moves_[index].dest();
|
| +
|
| + ASSERT(source.IsRegister() && destination.IsRegister());
|
| + __ xchgq(destination.reg(), source.reg());
|
| +
|
| + // The swap of source and destination has executed a move from source to
|
| + // destination.
|
| + moves_[index].Eliminate();
|
| +
|
| + // Any unperformed (including pending) move with a source of either
|
| + // this move's source or destination needs to have their source
|
| + // changed to reflect the state of affairs after the swap.
|
| + for (int i = 0; i < moves_.length(); ++i) {
|
| + MoveOperands other_move = moves_[i];
|
| + if (other_move.Blocks(source)) {
|
| + moves_[i].set_src(destination);
|
| + } else if (other_move.Blocks(destination)) {
|
| + moves_[i].set_src(source);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +#undef __
|
|
|
| } // namespace dart
|
|
|
|
|