| 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 |