Index: runtime/vm/flow_graph_compiler_ia32.cc |
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc |
index a81a07587378194695e00deffdf6529fce7b94b8..d563434f0f83ef4746819304705659b6f0e234aa 100644 |
--- a/runtime/vm/flow_graph_compiler_ia32.cc |
+++ b/runtime/vm/flow_graph_compiler_ia32.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) { |
- __ pushl(registers_[i]); |
+ |
+ if (deoptimization_env_ == NULL) { |
srdjan
2012/07/11 17:22:32
ASSERT in ia32 that deoptimization_env_ == NULL (s
|
+ for (intptr_t i = 0; i < registers_.length(); i++) { |
+ if (registers_[i] != kNoRegister) { |
+ __ pushl(registers_[i]); |
+ } |
+ } |
+ } else { |
+ // We have a deoptimization environment, we have to tear down optimized |
+ // frame and recreate non-optimized one. |
+ __ leal(ESP, |
+ Address(EBP, 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()); |
+ __ pushl(loc.reg()); |
+ } |
} |
} |
+ |
if (compiler->IsLeaf()) { |
Label L; |
__ call(&L); |
@@ -1077,6 +1100,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()) { |
+ __ movl(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()); |
+ __ xchgl(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 |