43 #define kSavedValue root
48 #define kSavedDoubleValue fp_scratch
51 LGapResolver::LGapResolver(LCodeGen* owner)
52 : cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(
false),
53 saved_destination_(
NULL), need_to_restore_root_(
false) { }
56 #define __ ACCESS_MASM(cgen_->masm())
58 void LGapResolver::Resolve(LParallelMove* parallel_move) {
62 BuildInitialMoveList(parallel_move);
64 for (
int i = 0; i < moves_.length(); ++i) {
65 LMoveOperands move = moves_[i];
70 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
73 if (in_cycle_) RestoreValue();
78 for (
int i = 0; i < moves_.length(); ++i) {
79 LMoveOperands move = moves_[i];
81 if (!move.IsEliminated()) {
82 ASSERT(move.source()->IsConstantOperand());
87 if (need_to_restore_root_) {
89 __ InitializeRootRegister();
90 need_to_restore_root_ =
false;
97 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
102 const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
103 for (
int i = 0; i < moves->length(); ++i) {
104 LMoveOperands move = moves->at(i);
105 if (!move.IsRedundant()) moves_.Add(move, cgen_->zone());
111 void LGapResolver::PerformMove(
int index) {
116 LMoveOperands& current_move = moves_[index];
118 ASSERT(!current_move.IsPending());
119 ASSERT(!current_move.IsRedundant());
125 LOperand* destination = current_move.destination();
126 current_move.set_destination(
NULL);
132 for (
int i = 0; i < moves_.length(); ++i) {
133 LMoveOperands other_move = moves_[i];
134 if (other_move.Blocks(destination) && !other_move.IsPending()) {
144 current_move.set_destination(destination);
149 LMoveOperands other_move = moves_[root_index_];
150 if (other_move.Blocks(destination)) {
151 ASSERT(other_move.IsPending());
161 void LGapResolver::Verify() {
162 #ifdef ENABLE_SLOW_ASSERTS
164 for (
int i = 0; i < moves_.length(); ++i) {
165 LOperand* destination = moves_[i].destination();
166 for (
int j = i + 1; j < moves_.length(); ++j) {
167 SLOW_ASSERT(!destination->Equals(moves_[j].destination()));
174 void LGapResolver::BreakCycle(
int index) {
175 ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
187 LOperand* source = moves_[index].source();
188 saved_destination_ = moves_[index].destination();
190 if (source->IsRegister()) {
191 need_to_restore_root_ =
true;
193 }
else if (source->IsStackSlot()) {
194 need_to_restore_root_ =
true;
196 }
else if (source->IsDoubleRegister()) {
200 }
else if (source->IsDoubleStackSlot()) {
211 moves_[index].Eliminate();
215 void LGapResolver::RestoreValue() {
219 if (saved_destination_->IsRegister()) {
221 }
else if (saved_destination_->IsStackSlot()) {
222 __ Str(
kSavedValue, cgen_->ToMemOperand(saved_destination_));
223 }
else if (saved_destination_->IsDoubleRegister()) {
226 }
else if (saved_destination_->IsDoubleStackSlot()) {
234 saved_destination_ =
NULL;
238 void LGapResolver::EmitMove(
int index) {
239 LOperand* source = moves_[index].source();
240 LOperand* destination = moves_[index].destination();
245 if (source->IsRegister()) {
246 Register source_register = cgen_->ToRegister(source);
247 if (destination->IsRegister()) {
248 __ Mov(cgen_->ToRegister(destination), source_register);
250 ASSERT(destination->IsStackSlot());
251 __ Str(source_register, cgen_->ToMemOperand(destination));
254 }
else if (source->IsStackSlot()) {
255 MemOperand source_operand = cgen_->ToMemOperand(source);
256 if (destination->IsRegister()) {
257 __ Ldr(cgen_->ToRegister(destination), source_operand);
259 ASSERT(destination->IsStackSlot());
260 EmitStackSlotMove(index);
263 }
else if (source->IsConstantOperand()) {
264 LConstantOperand* constant_source = LConstantOperand::cast(source);
265 if (destination->IsRegister()) {
266 Register dst = cgen_->ToRegister(destination);
267 if (cgen_->IsSmi(constant_source)) {
268 __ Mov(dst, cgen_->ToSmi(constant_source));
269 }
else if (cgen_->IsInteger32Constant(constant_source)) {
270 __ Mov(dst, cgen_->ToInteger32(constant_source));
272 __ LoadObject(dst, cgen_->ToHandle(constant_source));
274 }
else if (destination->IsDoubleRegister()) {
276 __ Fmov(result, cgen_->ToDouble(constant_source));
278 ASSERT(destination->IsStackSlot());
280 need_to_restore_root_ =
true;
281 if (cgen_->IsSmi(constant_source)) {
283 }
else if (cgen_->IsInteger32Constant(constant_source)) {
286 __ LoadObject(
kSavedValue, cgen_->ToHandle(constant_source));
291 }
else if (source->IsDoubleRegister()) {
293 if (destination->IsDoubleRegister()) {
294 __ Fmov(cgen_->ToDoubleRegister(destination), src);
296 ASSERT(destination->IsDoubleStackSlot());
297 __ Str(src, cgen_->ToMemOperand(destination));
300 }
else if (source->IsDoubleStackSlot()) {
302 if (destination->IsDoubleRegister()) {
303 __ Ldr(cgen_->ToDoubleRegister(destination), src);
305 ASSERT(destination->IsDoubleStackSlot());
306 EmitStackSlotMove(index);
314 moves_[index].Eliminate();
318 void LGapResolver::EmitStackSlotMove(
int index) {
325 LOperand* src = moves_[index].source();
326 LOperand* dst = moves_[index].destination();
328 ASSERT(src->IsStackSlot());
329 ASSERT(dst->IsStackSlot());
330 __ Ldr(temp, cgen_->ToMemOperand(src));
331 __ Str(temp, cgen_->ToMemOperand(dst));
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
#define SLOW_ASSERT(condition)
#define kSavedDoubleValue
#define ASSERT(condition)
DwVfpRegister DoubleRegister