OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 if (esi_caches != kIllegalIndex) { | 303 if (esi_caches != kIllegalIndex) { |
304 __ mov(esi, Operand(ebp, fp_relative(context_index()))); | 304 __ mov(esi, Operand(ebp, fp_relative(context_index()))); |
305 } | 305 } |
306 } | 306 } |
307 | 307 |
308 | 308 |
309 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) { | 309 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) { |
310 // We have already done X-to-memory moves. | 310 // We have already done X-to-memory moves. |
311 ASSERT(stack_pointer_ >= expected->stack_pointer_); | 311 ASSERT(stack_pointer_ >= expected->stack_pointer_); |
312 | 312 |
313 // Perform register-to-register moves. | 313 for (int i = 0; i < kNumRegisters; i++) { |
314 int start = 0; | 314 // Move the right value into register i if it is currently in a register. |
315 int end = elements_.length() - 1; | 315 int index = expected->register_locations_[i]; |
316 bool any_moves_blocked; // Did we fail to make some moves this iteration? | 316 int use_index = register_locations_[i]; |
317 bool should_break_cycles = false; | 317 // Fast check if register is unused in target or already correct |
318 bool any_moves_made; // Did we make any progress this iteration? | 318 if (index != kIllegalIndex |
319 do { | 319 && index != use_index |
320 any_moves_blocked = false; | 320 && elements_[index].is_register()) { |
321 any_moves_made = false; | 321 Register source = elements_[index].reg(); |
322 int first_move_blocked = kIllegalIndex; | 322 Register target = { i }; |
323 int last_move_blocked = kIllegalIndex; | 323 if (use_index == kIllegalIndex) { // Target is currently unused. |
324 for (int i = start; i <= end; i++) { | 324 // Copy contents of source from source to target. |
325 FrameElement source = elements_[i]; | 325 // Set frame element register to target. |
326 FrameElement target = expected->elements_[i]; | 326 elements_[index].set_reg(target); |
327 if (source.is_register() && target.is_register()) { | 327 Use(target, index); |
328 if (target.reg().is(source.reg())) { | 328 Unuse(source); |
329 if (target.is_synced() && !source.is_synced()) { | 329 __ mov(target, source); |
330 __ mov(Operand(ebp, fp_relative(i)), source.reg()); | 330 } else { |
331 } | 331 // Exchange contents of registers source and target. |
332 elements_[i] = target; | 332 elements_[use_index].set_reg(source); |
333 } else { | 333 elements_[index].set_reg(target); |
334 // We need to move source to target. | 334 register_locations_[target.code()] = index; |
335 if (is_used(target.reg())) { | 335 register_locations_[source.code()] = use_index; |
336 // The move is blocked because the target contains valid data. | 336 __ xchg(source, target); |
337 // If we are stuck with only cycles remaining, then we spill source. | |
338 // Otherwise, we just need more iterations. | |
339 if (should_break_cycles) { | |
340 SpillElementAt(i); | |
341 should_break_cycles = false; | |
342 } else { // Record a blocked move. | |
343 if (!any_moves_blocked) { | |
344 first_move_blocked = i; | |
345 } | |
346 last_move_blocked = i; | |
347 any_moves_blocked = true; | |
348 } | |
349 } else { | |
350 // The move is not blocked. This frame element can be moved from | |
351 // its source register to its target register. | |
352 if (target.is_synced() && !source.is_synced()) { | |
353 SyncElementAt(i); | |
354 } | |
355 Use(target.reg(), i); | |
356 Unuse(source.reg()); | |
357 elements_[i] = target; | |
358 __ mov(target.reg(), source.reg()); | |
359 any_moves_made = true; | |
360 } | |
361 } | |
362 } | 337 } |
363 } | 338 } |
364 // Update control flags for next iteration. | 339 } |
365 should_break_cycles = (any_moves_blocked && !any_moves_made); | |
366 if (any_moves_blocked) { | |
367 start = first_move_blocked; | |
368 end = last_move_blocked; | |
369 } | |
370 } while (any_moves_blocked); | |
371 } | 340 } |
372 | 341 |
373 | 342 |
374 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { | 343 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { |
375 // Move memory, constants, and copies to registers. This is the | 344 // Move memory, constants, and copies to registers. This is the |
376 // final step and is done from the bottom up so that the backing | 345 // final step and is done from the bottom up so that the backing |
377 // elements of copies are in their correct locations when we | 346 // elements of copies are in their correct locations when we |
378 // encounter the copies. | 347 // encounter the copies. |
379 for (int i = 0; i < elements_.length(); i++) { | 348 for (int i = 0; i < kNumRegisters; i++) { |
380 FrameElement source = elements_[i]; | 349 int index = expected->register_locations_[i]; |
381 FrameElement target = expected->elements_[i]; | 350 if (index != kIllegalIndex) { |
382 if (target.is_register() && !source.is_register()) { | 351 FrameElement source = elements_[index]; |
| 352 FrameElement target = expected->elements_[index]; |
383 switch (source.type()) { | 353 switch (source.type()) { |
384 case FrameElement::INVALID: // Fall through. | 354 case FrameElement::INVALID: // Fall through. |
385 case FrameElement::REGISTER: | |
386 UNREACHABLE(); | 355 UNREACHABLE(); |
387 break; | 356 break; |
388 | 357 case FrameElement::REGISTER: |
| 358 ASSERT(source.reg().is(target.reg())); |
| 359 continue; // Go to next iteration. Skips Use(target.reg()) below. |
| 360 break; |
389 case FrameElement::MEMORY: | 361 case FrameElement::MEMORY: |
390 ASSERT(i <= stack_pointer_); | 362 ASSERT(index <= stack_pointer_); |
391 __ mov(target.reg(), Operand(ebp, fp_relative(i))); | 363 __ mov(target.reg(), Operand(ebp, fp_relative(index))); |
392 break; | 364 break; |
393 | 365 |
394 case FrameElement::CONSTANT: | 366 case FrameElement::CONSTANT: |
395 if (cgen_->IsUnsafeSmi(source.handle())) { | 367 if (cgen_->IsUnsafeSmi(source.handle())) { |
396 cgen_->LoadUnsafeSmi(target.reg(), source.handle()); | 368 cgen_->LoadUnsafeSmi(target.reg(), source.handle()); |
397 } else { | 369 } else { |
398 __ Set(target.reg(), Immediate(source.handle())); | 370 __ Set(target.reg(), Immediate(source.handle())); |
399 } | 371 } |
400 break; | 372 break; |
401 | 373 |
402 case FrameElement::COPY: { | 374 case FrameElement::COPY: { |
403 FrameElement backing = elements_[source.index()]; | 375 int backing_index = source.index(); |
| 376 FrameElement backing = elements_[backing_index]; |
404 ASSERT(backing.is_memory() || backing.is_register()); | 377 ASSERT(backing.is_memory() || backing.is_register()); |
405 if (backing.is_memory()) { | 378 if (backing.is_memory()) { |
406 ASSERT(source.index() <= stack_pointer_); | 379 ASSERT(backing_index <= stack_pointer_); |
407 __ mov(target.reg(), Operand(ebp, fp_relative(source.index()))); | 380 // Code optimization if backing store should also move |
| 381 // to a register: move backing store to its register first. |
| 382 if (expected->elements_[backing_index].is_register()) { |
| 383 FrameElement new_backing = expected->elements_[backing_index]; |
| 384 Register new_backing_reg = new_backing.reg(); |
| 385 ASSERT(!is_used(new_backing_reg)); |
| 386 elements_[backing_index] = new_backing; |
| 387 Use(new_backing_reg, backing_index); |
| 388 __ mov(new_backing_reg, |
| 389 Operand(ebp, fp_relative(backing_index))); |
| 390 __ mov(target.reg(), new_backing_reg); |
| 391 } else { |
| 392 __ mov(target.reg(), Operand(ebp, fp_relative(backing_index))); |
| 393 } |
408 } else { | 394 } else { |
409 __ mov(target.reg(), backing.reg()); | 395 __ mov(target.reg(), backing.reg()); |
410 } | 396 } |
411 } | 397 } |
412 } | 398 } |
413 // Ensure the proper sync state. If the source was memory no | 399 // Ensure the proper sync state. If the source was memory no |
414 // code needs to be emitted. | 400 // code needs to be emitted. |
415 if (target.is_synced() && !source.is_memory()) { | 401 if (target.is_synced() && !source.is_synced()) { |
416 SyncElementAt(i); | 402 __ mov(Operand(ebp, fp_relative(index)), target.reg()); |
417 } | 403 } |
418 Use(target.reg(), i); | 404 Use(target.reg(), index); |
419 elements_[i] = target; | 405 elements_[index] = target; |
420 } | 406 } |
421 } | 407 } |
422 } | 408 } |
423 | 409 |
424 | 410 |
425 void VirtualFrame::Enter() { | 411 void VirtualFrame::Enter() { |
426 // Registers live on entry: esp, ebp, esi, edi. | 412 // Registers live on entry: esp, ebp, esi, edi. |
427 Comment cmnt(masm_, "[ Enter JS frame"); | 413 Comment cmnt(masm_, "[ Enter JS frame"); |
428 | 414 |
429 #ifdef DEBUG | 415 #ifdef DEBUG |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 ASSERT(stack_pointer_ == elements_.length() - 1); | 1039 ASSERT(stack_pointer_ == elements_.length() - 1); |
1054 elements_.Add(FrameElement::MemoryElement()); | 1040 elements_.Add(FrameElement::MemoryElement()); |
1055 stack_pointer_++; | 1041 stack_pointer_++; |
1056 __ push(immediate); | 1042 __ push(immediate); |
1057 } | 1043 } |
1058 | 1044 |
1059 | 1045 |
1060 #undef __ | 1046 #undef __ |
1061 | 1047 |
1062 } } // namespace v8::internal | 1048 } } // namespace v8::internal |
OLD | NEW |