| OLD | NEW |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 | 38 |
| 39 // ------------------------------------------------------------------------- | 39 // ------------------------------------------------------------------------- |
| 40 // Result implementation. | 40 // Result implementation. |
| 41 | 41 |
| 42 | 42 |
| 43 Result::Result(Register reg, CodeGenerator* cgen) | 43 Result::Result(Register reg, CodeGenerator* cgen) |
| 44 : type_(REGISTER), | 44 : type_(REGISTER), |
| 45 cgen_(cgen) { | 45 cgen_(cgen) { |
| 46 data_.reg_ = reg; | 46 data_.reg_ = reg; |
| 47 ASSERT(!reg().is(no_reg)); | 47 ASSERT(!reg.is(no_reg)); |
| 48 cgen_->allocator()->Use(reg); | 48 cgen_->allocator()->Use(reg); |
| 49 } | 49 } |
| 50 | 50 |
| 51 | 51 |
| 52 void Result::Unuse() { | 52 void Result::Unuse() { |
| 53 ASSERT(!reg().is(no_reg)); | 53 ASSERT(!reg().is(no_reg)); |
| 54 cgen_->allocator()->Unuse(reg()); | 54 cgen_->allocator()->Unuse(reg()); |
| 55 data_.reg_ = no_reg; | 55 data_.reg_ = no_reg; |
| 56 } | 56 } |
| 57 | 57 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 233 |
| 234 // Clear the dirty bits for the range of elements in [begin, end). | 234 // Clear the dirty bits for the range of elements in [begin, end). |
| 235 void VirtualFrame::SyncRange(int begin, int end) { | 235 void VirtualFrame::SyncRange(int begin, int end) { |
| 236 ASSERT(begin >= 0); | 236 ASSERT(begin >= 0); |
| 237 ASSERT(end <= elements_.length()); | 237 ASSERT(end <= elements_.length()); |
| 238 for (int i = begin; i < end; i++) { | 238 for (int i = begin; i < end; i++) { |
| 239 SyncElementAt(i); | 239 SyncElementAt(i); |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 | 242 |
| 243 |
| 243 // Make the type of all elements be MEMORY. | 244 // Make the type of all elements be MEMORY. |
| 244 void VirtualFrame::SpillAll() { | 245 void VirtualFrame::SpillAll() { |
| 245 for (int i = 0; i < elements_.length(); i++) { | 246 for (int i = 0; i < elements_.length(); i++) { |
| 246 SpillElementAt(i); | 247 SpillElementAt(i); |
| 247 } | 248 } |
| 248 } | 249 } |
| 249 | 250 |
| 250 | 251 |
| 251 void VirtualFrame::PrepareForCall(int frame_arg_count) { | 252 void VirtualFrame::PrepareForCall(int frame_arg_count) { |
| 252 ASSERT(height() >= frame_arg_count); | 253 ASSERT(height() >= frame_arg_count); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 for (int i = 0; i < elements_.length(); i++) { | 290 for (int i = 0; i < elements_.length(); i++) { |
| 290 if (!elements_[i].is_memory() && !elements_[i].is_register()) { | 291 if (!elements_[i].is_memory() && !elements_[i].is_register()) { |
| 291 return false; | 292 return false; |
| 292 } | 293 } |
| 293 } | 294 } |
| 294 | 295 |
| 295 return true; | 296 return true; |
| 296 } | 297 } |
| 297 | 298 |
| 298 | 299 |
| 300 bool VirtualFrame::RequiresMergeCode() { |
| 301 // A frame requires merge code to be generated in the event that |
| 302 // there are duplicated non-synched registers or else elements not |
| 303 // in a (memory or register) location in the frame. We look for |
| 304 // non-synced non-location elements and count occurrences of |
| 305 // non-synced registers. |
| 306 RegisterFile non_synced_regs; |
| 307 for (int i = 0; i < elements_.length(); i++) { |
| 308 FrameElement element = elements_[i]; |
| 309 if (!element.is_synced()) { |
| 310 if (element.is_register()) { |
| 311 non_synced_regs.Use(elements_[i].reg()); |
| 312 } else if (!element.is_memory()) { |
| 313 // Not memory or register and not synced. |
| 314 return true; |
| 315 } |
| 316 } |
| 317 } |
| 318 |
| 319 for (int i = 0; i < RegisterFile::kNumRegisters; i++) { |
| 320 if (non_synced_regs.count(i) > 1) { |
| 321 return true; |
| 322 } |
| 323 } |
| 324 |
| 325 return false; |
| 326 } |
| 327 |
| 328 |
| 299 void VirtualFrame::MakeMergable() { | 329 void VirtualFrame::MakeMergable() { |
| 300 Comment cmnt(masm_, "[ Make frame mergable"); | 330 Comment cmnt(masm_, "[ Make frame mergable"); |
| 301 // Remove constants from the frame and ensure that no registers are | 331 // Remove constants from the frame and ensure that no registers are |
| 302 // multiply referenced within the frame. Allocate elements to their | 332 // multiply referenced within the frame. Allocate elements to their |
| 303 // new locations from the top down so that the topmost elements have | 333 // new locations from the top down so that the topmost elements have |
| 304 // a chance to be in registers, then fill them into memory from the | 334 // a chance to be in registers, then fill them into memory from the |
| 305 // bottom up. (NB: Currently when spilling registers that are | 335 // bottom up. (NB: Currently when spilling registers that are |
| 306 // multiply referenced, it is the lowermost occurrence that gets to | 336 // multiply referenced, it is the lowermost occurrence that gets to |
| 307 // stay in the register.) | 337 // stay in the register.) |
| 308 FrameElement* new_elements = new FrameElement[elements_.length()]; | 338 FrameElement* new_elements = new FrameElement[elements_.length()]; |
| 309 FrameElement memory_element; | 339 FrameElement memory_element; |
| 310 for (int i = elements_.length() - 1; i >= 0; i--) { | 340 for (int i = elements_.length() - 1; i >= 0; i--) { |
| 311 FrameElement element = elements_[i]; | 341 FrameElement element = elements_[i]; |
| 312 if (element.is_constant() || | 342 if (element.is_constant() || |
| 313 (element.is_register() && | 343 (element.is_register() && |
| 314 frame_registers_.count(element.reg().code()) > 1)) { | 344 frame_registers_.count(element.reg().code()) > 1)) { |
| 315 // A simple strategy is to locate these elements in memory if they are | 345 // A simple strategy is to locate these elements in memory if they are |
| 316 // synced (avoiding a spill right now) and otherwise to prefer a | 346 // synced (avoiding a spill right now) and otherwise to prefer a |
| 317 // register for them. | 347 // register for them. |
| 318 if (element.is_synced()) { | 348 if (element.is_synced()) { |
| 319 new_elements[i] = memory_element; | 349 new_elements[i] = memory_element; |
| 320 } else { | 350 } else { |
| 321 // This code path is currently not triggered. UNIMPLEMENTED is | |
| 322 // temporarily used to trap when it becomes active so we can test | |
| 323 // it. | |
| 324 UNIMPLEMENTED(); | |
| 325 Register reg = cgen_->allocator()->AllocateWithoutSpilling(); | 351 Register reg = cgen_->allocator()->AllocateWithoutSpilling(); |
| 326 if (reg.is(no_reg)) { | 352 if (reg.is(no_reg)) { |
| 327 new_elements[i] = memory_element; | 353 new_elements[i] = memory_element; |
| 328 } else { | 354 } else { |
| 329 FrameElement register_element(reg, FrameElement::NOT_SYNCED); | 355 FrameElement register_element(reg, FrameElement::NOT_SYNCED); |
| 330 new_elements[i] = register_element; | 356 new_elements[i] = register_element; |
| 331 } | 357 } |
| 332 } | 358 } |
| 333 | 359 |
| 334 // We have not moved register references, but record that we will so | 360 // We have not moved register references, but record that we will so |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 ASSERT(!elements_[j].is_memory()); | 451 ASSERT(!elements_[j].is_memory()); |
| 426 } | 452 } |
| 427 #endif | 453 #endif |
| 428 stack_pointer_ = i + 1; | 454 stack_pointer_ = i + 1; |
| 429 __ add(Operand(esp), | 455 __ add(Operand(esp), |
| 430 Immediate((stack_pointer_ - i) * kPointerSize)); | 456 Immediate((stack_pointer_ - i) * kPointerSize)); |
| 431 } | 457 } |
| 432 stack_pointer_--; | 458 stack_pointer_--; |
| 433 __ pop(target.reg()); | 459 __ pop(target.reg()); |
| 434 } | 460 } |
| 435 Use(target.reg()); | 461 } else { |
| 436 } else if (source.is_constant()) { | 462 // Source is constant. |
| 437 // Not yet implemented. When done, code in common with the | 463 __ Set(target.reg(), Immediate(source.handle())); |
| 438 // memory-to-register just above case can be factored out. | |
| 439 UNIMPLEMENTED(); | |
| 440 } | 464 } |
| 465 Use(target.reg()); |
| 441 elements_[i] = target; | 466 elements_[i] = target; |
| 442 } | 467 } |
| 443 } | 468 } |
| 444 | 469 |
| 470 // At this point, the frames should be identical. |
| 445 ASSERT(stack_pointer_ == expected->stack_pointer_); | 471 ASSERT(stack_pointer_ == expected->stack_pointer_); |
| 472 #ifdef DEBUG |
| 473 for (int i = 0; i < elements_.length(); i++) { |
| 474 FrameElement expect = expected->elements_[i]; |
| 475 if (expect.is_memory()) { |
| 476 ASSERT(elements_[i].is_memory()); |
| 477 ASSERT(elements_[i].is_synced() && expect.is_synced()); |
| 478 } else if (expect.is_register()) { |
| 479 ASSERT(elements_[i].is_register()); |
| 480 ASSERT(elements_[i].reg().is(expect.reg())); |
| 481 ASSERT(elements_[i].is_synced() == expect.is_synced()); |
| 482 } else { |
| 483 ASSERT(expect.is_constant()); |
| 484 ASSERT(elements_[i].is_constant()); |
| 485 ASSERT(elements_[i].handle().location() == |
| 486 expect.handle().location()); |
| 487 ASSERT(elements_[i].is_synced() == expect.is_synced()); |
| 488 } |
| 489 } |
| 490 #endif |
| 491 } |
| 492 |
| 493 |
| 494 void VirtualFrame::DetachFromCodeGenerator() { |
| 495 // Tell the global register allocator that it is free to reallocate all |
| 496 // register references contained in this frame. The frame elements remain |
| 497 // register references, so the frame-internal reference count is not |
| 498 // decremented. |
| 499 for (int i = 0; i < elements_.length(); i++) { |
| 500 if (elements_[i].is_register()) { |
| 501 cgen_->allocator()->Unuse(elements_[i].reg()); |
| 502 } |
| 503 } |
| 504 } |
| 505 |
| 506 |
| 507 void VirtualFrame::AttachToCodeGenerator() { |
| 508 // Tell the global register allocator that the frame-internal register |
| 509 // references are live again. |
| 510 for (int i = 0; i < elements_.length(); i++) { |
| 511 if (elements_[i].is_register()) { |
| 512 cgen_->allocator()->Use(elements_[i].reg()); |
| 513 } |
| 514 } |
| 446 } | 515 } |
| 447 | 516 |
| 448 | 517 |
| 449 void VirtualFrame::Enter() { | 518 void VirtualFrame::Enter() { |
| 450 // Registers live on entry: esp, ebp, esi, edi. | 519 // Registers live on entry: esp, ebp, esi, edi. |
| 451 Comment cmnt(masm_, "[ Enter JS frame"); | 520 Comment cmnt(masm_, "[ Enter JS frame"); |
| 452 EmitPush(ebp); | 521 EmitPush(ebp); |
| 453 | 522 |
| 454 frame_pointer_ = stack_pointer_; | 523 frame_pointer_ = stack_pointer_; |
| 455 __ mov(ebp, Operand(esp)); | 524 __ mov(ebp, Operand(esp)); |
| 456 | 525 |
| 457 // Store the context and the function in the frame. | 526 // Store the context in the frame. The context is kept in esi, so the |
| 458 Push(esi); | 527 // register reference is not owned by the frame (ie, the frame is not free |
| 459 // The frame owns the register reference now. | 528 // to spill it). This is implemented by making the in-frame value be |
| 460 cgen_->allocator()->Unuse(esi); | 529 // memory. |
| 530 EmitPush(esi); |
| 461 | 531 |
| 532 // Store the function in the frame. The frame owns the register reference |
| 533 // now (ie, it can keep it in edi or spill it later). |
| 462 Push(edi); | 534 Push(edi); |
| 463 cgen_->allocator()->Unuse(edi); | 535 cgen_->allocator()->Unuse(edi); |
| 464 } | 536 } |
| 465 | 537 |
| 466 | 538 |
| 467 void VirtualFrame::Exit() { | 539 void VirtualFrame::Exit() { |
| 468 Comment cmnt(masm_, "[ Exit JS frame"); | 540 Comment cmnt(masm_, "[ Exit JS frame"); |
| 469 // Record the location of the JS exit code for patching when setting | 541 // Record the location of the JS exit code for patching when setting |
| 470 // break point. | 542 // break point. |
| 471 __ RecordJSReturn(); | 543 __ RecordJSReturn(); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 return false; | 789 return false; |
| 718 } | 790 } |
| 719 } | 791 } |
| 720 return true; | 792 return true; |
| 721 } | 793 } |
| 722 #endif | 794 #endif |
| 723 | 795 |
| 724 #undef __ | 796 #undef __ |
| 725 | 797 |
| 726 } } // namespace v8::internal | 798 } } // namespace v8::internal |
| OLD | NEW |