| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 stack_pointer_(original->stack_pointer_), | 78 stack_pointer_(original->stack_pointer_), |
| 79 frame_pointer_(original->frame_pointer_), | 79 frame_pointer_(original->frame_pointer_), |
| 80 frame_registers_(original->frame_registers_) { | 80 frame_registers_(original->frame_registers_) { |
| 81 // Copy all the elements from the original. | 81 // Copy all the elements from the original. |
| 82 for (int i = 0; i < original->elements_.length(); i++) { | 82 for (int i = 0; i < original->elements_.length(); i++) { |
| 83 elements_.Add(original->elements_[i]); | 83 elements_.Add(original->elements_[i]); |
| 84 } | 84 } |
| 85 } | 85 } |
| 86 | 86 |
| 87 | 87 |
| 88 FrameElement VirtualFrame::CopyElementAt(int index) { |
| 89 ASSERT(index >= 0); |
| 90 ASSERT(index < elements_.length()); |
| 91 |
| 92 FrameElement target = elements_[index]; |
| 93 FrameElement result; |
| 94 |
| 95 switch (target.type()) { |
| 96 case FrameElement::CONSTANT: |
| 97 // We do not copy constants and instead return a fresh unsynced |
| 98 // constant. |
| 99 result = FrameElement::ConstantElement(target.handle(), |
| 100 FrameElement::NOT_SYNCED); |
| 101 break; |
| 102 |
| 103 case FrameElement::COPY: |
| 104 // We do not allow copies of copies, so we follow one link to |
| 105 // the actual backing store of a copy before making a copy. |
| 106 index = target.index(); |
| 107 ASSERT(elements_[index].is_memory() || elements_[index].is_register()); |
| 108 // Fall through. |
| 109 |
| 110 case FrameElement::MEMORY: // Fall through. |
| 111 case FrameElement::REGISTER: |
| 112 // All copies are backed by memory or register locations. |
| 113 result.type_ = |
| 114 FrameElement::TypeField::encode(FrameElement::COPY) | |
| 115 FrameElement::SyncField::encode(FrameElement::NOT_SYNCED); |
| 116 result.data_.index_ = index; |
| 117 break; |
| 118 |
| 119 case FrameElement::INVALID: |
| 120 // We should not try to copy invalid elements. |
| 121 UNREACHABLE(); |
| 122 break; |
| 123 } |
| 124 return result; |
| 125 } |
| 126 |
| 127 |
| 88 // Modify the state of the virtual frame to match the actual frame by adding | 128 // Modify the state of the virtual frame to match the actual frame by adding |
| 89 // extra in-memory elements to the top of the virtual frame. The extra | 129 // extra in-memory elements to the top of the virtual frame. The extra |
| 90 // elements will be externally materialized on the actual frame (eg, by | 130 // elements will be externally materialized on the actual frame (eg, by |
| 91 // pushing an exception handler). No code is emitted. | 131 // pushing an exception handler). No code is emitted. |
| 92 void VirtualFrame::Adjust(int count) { | 132 void VirtualFrame::Adjust(int count) { |
| 93 ASSERT(count >= 0); | 133 ASSERT(count >= 0); |
| 94 ASSERT(stack_pointer_ == elements_.length() - 1); | 134 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 95 | 135 |
| 96 for (int i = 0; i < count; i++) { | 136 for (int i = 0; i < count; i++) { |
| 97 elements_.Add(FrameElement::MemoryElement()); | 137 elements_.Add(FrameElement::MemoryElement()); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 | 200 |
| 161 Register result = { best_register_code }; | 201 Register result = { best_register_code }; |
| 162 if (result.is_valid()) { | 202 if (result.is_valid()) { |
| 163 Spill(result); | 203 Spill(result); |
| 164 ASSERT(!cgen_->allocator()->is_used(result)); | 204 ASSERT(!cgen_->allocator()->is_used(result)); |
| 165 } | 205 } |
| 166 return result; | 206 return result; |
| 167 } | 207 } |
| 168 | 208 |
| 169 | 209 |
| 170 // Spill an element, making its type be MEMORY. | |
| 171 // Does not decrement usage counts, if element is a register. | |
| 172 void VirtualFrame::RawSpillElementAt(int index) { | |
| 173 if (elements_[index].is_valid()) { | |
| 174 SyncElementAt(index); | |
| 175 // The element is now in memory. | |
| 176 elements_[index] = FrameElement::MemoryElement(); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 | |
| 181 // Make the type of the element at a given index be MEMORY. | 210 // Make the type of the element at a given index be MEMORY. |
| 182 void VirtualFrame::SpillElementAt(int index) { | 211 void VirtualFrame::SpillElementAt(int index) { |
| 212 if (!elements_[index].is_valid()) return; |
| 213 |
| 183 if (elements_[index].is_register()) { | 214 if (elements_[index].is_register()) { |
| 184 Unuse(elements_[index].reg()); | 215 Unuse(elements_[index].reg()); |
| 185 } | 216 } |
| 186 RawSpillElementAt(index); | 217 SyncElementAt(index); |
| 218 // The element is now in memory. |
| 219 elements_[index] = FrameElement::MemoryElement(); |
| 187 } | 220 } |
| 188 | 221 |
| 189 | 222 |
| 190 // Clear the dirty bit for the element at a given index. | 223 // Clear the dirty bit for the element at a given index if it is a |
| 191 // The element must be on the physical stack, or the first | 224 // valid element. The stack address corresponding to the element must |
| 192 // element below the stack pointer (created by a single push). | 225 // be allocated on the physical stack, or the first element above the |
| 226 // stack pointer so it can be allocated by a single push instruction. |
| 193 void VirtualFrame::RawSyncElementAt(int index) { | 227 void VirtualFrame::RawSyncElementAt(int index) { |
| 194 FrameElement element = elements_[index]; | 228 FrameElement element = elements_[index]; |
| 195 if (element.is_valid() && !element.is_synced()) { | 229 |
| 196 if (index <= stack_pointer_) { | 230 if (!element.is_valid() || element.is_synced()) return; |
| 197 // Write elements below the stack pointer to their (already allocated) | 231 |
| 198 // actual frame location. | 232 if (index <= stack_pointer_) { |
| 199 if (element.is_constant()) { | 233 // Emit code to write elements below the stack pointer to their |
| 234 // (already allocated) stack address. |
| 235 switch (element.type()) { |
| 236 case FrameElement::INVALID: // Fall through. |
| 237 case FrameElement::MEMORY: |
| 238 // There was an early bailout for invalid and synced elements |
| 239 // (memory elements are always synced). |
| 240 UNREACHABLE(); |
| 241 break; |
| 242 |
| 243 case FrameElement::REGISTER: |
| 244 __ mov(Operand(ebp, fp_relative(index)), element.reg()); |
| 245 break; |
| 246 |
| 247 case FrameElement::CONSTANT: |
| 200 __ Set(Operand(ebp, fp_relative(index)), Immediate(element.handle())); | 248 __ Set(Operand(ebp, fp_relative(index)), Immediate(element.handle())); |
| 201 } else { | 249 break; |
| 202 ASSERT(element.is_register()); | 250 |
| 203 __ mov(Operand(ebp, fp_relative(index)), element.reg()); | 251 case FrameElement::COPY: { |
| 204 } | 252 int backing_index = element.index(); |
| 205 } else { | 253 FrameElement backing_element = elements_[backing_index]; |
| 206 // Push elements above the stack pointer to allocate space and sync | 254 if (backing_element.is_memory()) { |
| 207 // them. Space should have already been allocated in the actual frame | 255 Result temp = cgen_->allocator()->Allocate(); |
| 208 // for all the elements below this one. | 256 ASSERT(temp.is_valid()); |
| 209 ASSERT(index == stack_pointer_ + 1); | 257 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index))); |
| 210 stack_pointer_++; | 258 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); |
| 211 if (element.is_constant()) { | 259 } else { |
| 212 __ push(Immediate(element.handle())); | 260 ASSERT(backing_element.is_register()); |
| 213 } else { | 261 __ mov(Operand(ebp, fp_relative(index)), backing_element.reg()); |
| 214 ASSERT(element.is_register()); | 262 } |
| 215 __ push(element.reg()); | 263 break; |
| 216 } | 264 } |
| 217 } | 265 } |
| 218 | 266 |
| 219 elements_[index].set_sync(); | 267 } else { |
| 268 // Push elements above the stack pointer to allocate space and |
| 269 // sync them. Space should have already been allocated in the |
| 270 // actual frame for all the elements below this one. |
| 271 ASSERT(index == stack_pointer_ + 1); |
| 272 stack_pointer_++; |
| 273 switch (element.type()) { |
| 274 case FrameElement::INVALID: // Fall through. |
| 275 case FrameElement::MEMORY: |
| 276 // There was an early bailout for invalid and synced elements |
| 277 // (memory elements are always synced). |
| 278 UNREACHABLE(); |
| 279 break; |
| 280 |
| 281 case FrameElement::REGISTER: |
| 282 __ push(element.reg()); |
| 283 break; |
| 284 |
| 285 case FrameElement::CONSTANT: |
| 286 __ push(Immediate(element.handle())); |
| 287 break; |
| 288 |
| 289 case FrameElement::COPY: { |
| 290 int backing_index = element.index(); |
| 291 FrameElement backing = elements_[backing_index]; |
| 292 ASSERT(backing.is_memory() || backing.is_register()); |
| 293 if (backing.is_memory()) { |
| 294 __ push(Operand(ebp, fp_relative(backing_index))); |
| 295 } else { |
| 296 __ push(backing.reg()); |
| 297 } |
| 298 break; |
| 299 } |
| 300 } |
| 220 } | 301 } |
| 302 |
| 303 elements_[index].set_sync(); |
| 221 } | 304 } |
| 222 | 305 |
| 223 | 306 |
| 224 // Clear the dirty bits for the range of elements in [begin, end). | 307 // Clear the dirty bits for the range of elements in [begin, end). |
| 225 void VirtualFrame::SyncRange(int begin, int end) { | 308 void VirtualFrame::SyncRange(int begin, int end) { |
| 226 ASSERT(begin >= 0); | 309 ASSERT(begin >= 0); |
| 227 ASSERT(end <= elements_.length()); | 310 ASSERT(end <= elements_.length()); |
| 228 for (int i = begin; i < end; i++) { | 311 for (int i = begin; i < end; i++) { |
| 229 RawSyncElementAt(i); | 312 RawSyncElementAt(i); |
| 230 } | 313 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 246 SpillElementAt(i); | 329 SpillElementAt(i); |
| 247 } | 330 } |
| 248 } | 331 } |
| 249 | 332 |
| 250 | 333 |
| 251 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { | 334 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { |
| 252 ASSERT(height() >= dropped_args); | 335 ASSERT(height() >= dropped_args); |
| 253 ASSERT(height() >= spilled_args); | 336 ASSERT(height() >= spilled_args); |
| 254 ASSERT(dropped_args <= spilled_args); | 337 ASSERT(dropped_args <= spilled_args); |
| 255 | 338 |
| 256 // Below the arguments to the function being called, spill all registers and | |
| 257 // make sure that locals have the right values by synching them. The synching | |
| 258 // is necessary to give the debugger a consistent view of the values of | |
| 259 // locals in the frame. Spill the arguments to the function being called. | |
| 260 int arg_base_index = elements_.length() - spilled_args; | 339 int arg_base_index = elements_.length() - spilled_args; |
| 261 for (int i = 0; i < arg_base_index; i++) { | 340 // Spill the arguments. We spill from the top down so that the |
| 341 // backing stores of register copies will be spilled only after all |
| 342 // the copies are spilled---it is better to spill via a |
| 343 // register-to-memory move than a memory-to-memory move. |
| 344 for (int i = elements_.length() - 1; i >= arg_base_index; i--) { |
| 345 SpillElementAt(i); |
| 346 } |
| 347 |
| 348 // Below the arguments, spill registers and sync everything else. |
| 349 // Syncing is necessary for the locals and parameters to give the |
| 350 // debugger a consistent view of the frame. |
| 351 for (int i = arg_base_index - 1; i >= 0; i--) { |
| 262 FrameElement element = elements_[i]; | 352 FrameElement element = elements_[i]; |
| 263 if (element.is_register()) { | 353 if (element.is_register()) { |
| 264 SpillElementAt(i); | 354 SpillElementAt(i); |
| 265 } else if (element.is_valid()) { | 355 } else if (element.is_valid()) { |
| 266 SyncElementAt(i); | 356 SyncElementAt(i); |
| 267 } | 357 } |
| 268 } | 358 } |
| 269 // The arguments are spilled. | |
| 270 for (int i = arg_base_index; i < elements_.length(); i++) { | |
| 271 SpillElementAt(i); | |
| 272 } | |
| 273 | 359 |
| 274 // Forget the frame elements that will be popped by the call. | 360 // Forget the frame elements that will be popped by the call. |
| 275 Forget(dropped_args); | 361 Forget(dropped_args); |
| 276 } | 362 } |
| 277 | 363 |
| 278 | 364 |
| 279 void VirtualFrame::MakeMergable() { | 365 void VirtualFrame::MakeMergable() { |
| 280 Comment cmnt(masm_, "[ Make frame mergable"); | 366 Comment cmnt(masm_, "[ Make frame mergable"); |
| 281 // We should always be merging the code generator's current frame to an | 367 // We should always be merging the code generator's current frame to an |
| 282 // expected frame. | 368 // expected frame. |
| 283 ASSERT(cgen_->frame() == this); | 369 ASSERT(cgen_->frame() == this); |
| 284 ASSERT(cgen_->HasValidEntryRegisters()); | 370 ASSERT(cgen_->HasValidEntryRegisters()); |
| 285 | 371 |
| 286 // Remove constants from the frame and ensure that no registers are | 372 // Remove constants from the frame and ensure that there are no |
| 287 // multiply referenced within the frame. Allocate elements to their new | 373 // copies. Allocate elements to their new locations from the top |
| 288 // locations from the top down so that the topmost elements have a chance | 374 // down so that the topmost elements have a chance to be in |
| 289 // to be in registers, then fill them into memory from the bottom up. | 375 // registers, then fill them into memory from the bottom up. |
| 290 // (NB: Currently when spilling registers that are multiply referenced, it | 376 // |
| 291 // is the lowermost occurrence that gets to stay in the register.) | 377 // Compute the new frame elements first. The elements of |
| 378 // new_elements are initially invalid. |
| 379 FrameElement* new_elements = new FrameElement[elements_.length()]; |
| 380 // Array of flags, true if we have found a the topmost copy of a |
| 381 // register. Every element after the first is initialized to 0 (ie, |
| 382 // false). |
| 383 bool topmost_found[RegisterFile::kNumRegisters] = { false }; |
| 384 // "Singleton" memory element. They have no internal state. |
| 385 FrameElement memory_element = FrameElement::MemoryElement(); |
| 292 | 386 |
| 293 // The elements of new_elements are initially invalid. | |
| 294 FrameElement* new_elements = new FrameElement[elements_.length()]; | |
| 295 FrameElement memory_element = FrameElement::MemoryElement(); | |
| 296 for (int i = elements_.length() - 1; i >= 0; i--) { | 387 for (int i = elements_.length() - 1; i >= 0; i--) { |
| 297 FrameElement element = elements_[i]; | 388 FrameElement element = elements_[i]; |
| 298 if (element.is_constant() || | 389 |
| 299 (element.is_register() && | 390 switch (element.type()) { |
| 300 frame_registers_.count(element.reg()) > 1)) { | 391 case FrameElement::INVALID: // Fall through. |
| 301 // A simple strategy is to locate these elements in memory if they are | 392 case FrameElement::MEMORY: |
| 302 // synced (avoiding a spill right now) and otherwise to prefer a | 393 new_elements[i] = element; |
| 303 // register for them. | 394 break; |
| 304 if (element.is_synced()) { | 395 |
| 305 new_elements[i] = memory_element; | 396 case FrameElement::REGISTER: |
| 306 } else { | 397 // If this is not the first (and only) register reference we |
| 307 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); | 398 // try to find a good home for it, otherwise it can stay in |
| 308 if (fresh.is_valid()) { | 399 // the register. |
| 309 // We immediately record the frame's use of the register so that | 400 if (topmost_found[element.reg().code()]) { |
| 310 // it will not be allocated again. | 401 // A simple strategy is to spill to memory if it is already |
| 311 Use(fresh.reg()); | 402 // synced (avoiding a spill now), and otherwise to prefer a |
| 312 new_elements[i] = | 403 // register if one is available. |
| 313 FrameElement::RegisterElement(fresh.reg(), | 404 if (element.is_synced()) { |
| 314 FrameElement::NOT_SYNCED); | 405 // We do not unuse this register reference because we want |
| 406 // the register allocator to count the other one (higher |
| 407 // up in the new frame). |
| 408 new_elements[i] = memory_element; |
| 409 } else { |
| 410 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); |
| 411 if (fresh.is_valid()) { |
| 412 // We immediately record the frame's use of the register |
| 413 // so that the register allocator will not try to use it |
| 414 // again. |
| 415 Use(fresh.reg()); |
| 416 new_elements[i] = |
| 417 FrameElement::RegisterElement(fresh.reg(), |
| 418 FrameElement::NOT_SYNCED); |
| 419 } else { |
| 420 new_elements[i] = memory_element; |
| 421 } |
| 422 } |
| 315 } else { | 423 } else { |
| 424 // The only occurrence can stay in the register. |
| 425 new_elements[i] = element; |
| 426 } |
| 427 break; |
| 428 |
| 429 case FrameElement::CONSTANT: |
| 430 // Prefer spilling synced constants and registers for the rest. |
| 431 if (element.is_synced()) { |
| 316 new_elements[i] = memory_element; | 432 new_elements[i] = memory_element; |
| 433 } else { |
| 434 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); |
| 435 if (fresh.is_valid()) { |
| 436 // We immediately record the frame's use of the register |
| 437 // so that the register allocator will not try to use it |
| 438 // again. |
| 439 Use(fresh.reg()); |
| 440 new_elements[i] = |
| 441 FrameElement::RegisterElement(fresh.reg(), |
| 442 FrameElement::NOT_SYNCED); |
| 443 } else { |
| 444 new_elements[i] = memory_element; |
| 445 } |
| 317 } | 446 } |
| 447 break; |
| 448 |
| 449 case FrameElement::COPY: { |
| 450 FrameElement backing = elements_[element.index()]; |
| 451 if (backing.is_memory()) { |
| 452 new_elements[i] = memory_element; |
| 453 } else { |
| 454 ASSERT(backing.is_register()); |
| 455 if (topmost_found[backing.reg().code()]) { |
| 456 if (element.is_synced()) { |
| 457 new_elements[i] = memory_element; |
| 458 } else { |
| 459 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); |
| 460 if (fresh.is_valid()) { |
| 461 // We immediately record the frame's use of the |
| 462 // register so that the register allocator will not |
| 463 // try to use it again. |
| 464 Use(fresh.reg()); |
| 465 new_elements[i] = |
| 466 FrameElement::RegisterElement(fresh.reg(), |
| 467 FrameElement::NOT_SYNCED); |
| 468 } else { |
| 469 new_elements[i] = memory_element; |
| 470 } |
| 471 } |
| 472 // When performing the moves (from bottom to top) later, |
| 473 // we will need to know what register this one is a copy |
| 474 // of and the original backing element will already be |
| 475 // overwritten. We store that information in this |
| 476 // elements frame slot so that it looks like this is a |
| 477 // move from a register rather than a copy. |
| 478 if (element.is_synced()) { |
| 479 backing.set_sync(); |
| 480 } else { |
| 481 backing.clear_sync(); |
| 482 } |
| 483 Use(backing.reg()); |
| 484 elements_[i] = backing; |
| 485 |
| 486 } else { |
| 487 // This is the top occurrence of the register. |
| 488 topmost_found[backing.reg().code()] = true; |
| 489 if (element.is_synced()) { |
| 490 backing.set_sync(); |
| 491 } else { |
| 492 backing.clear_sync(); |
| 493 } |
| 494 // Record the register reference immediately so that |
| 495 // register allocator does not try to use this register as |
| 496 // a temp register when performing the moves. |
| 497 Use(backing.reg()); |
| 498 new_elements[i] = backing; |
| 499 } |
| 500 } |
| 501 break; |
| 318 } | 502 } |
| 319 | |
| 320 // We have not moved register references, but record that we will so | |
| 321 // that we do not unnecessarily spill the last reference within the | |
| 322 // frame. | |
| 323 if (element.is_register()) { | |
| 324 Unuse(element.reg()); | |
| 325 } | |
| 326 } else { | |
| 327 // The element is in memory or a singly-frame-referenced register. | |
| 328 new_elements[i] = element; | |
| 329 } | 503 } |
| 330 } | 504 } |
| 331 | 505 |
| 332 // Perform the moves. | 506 // Perform the moves. Reference counts for register targets have |
| 507 // already been incremented. |
| 333 for (int i = 0; i < elements_.length(); i++) { | 508 for (int i = 0; i < elements_.length(); i++) { |
| 334 FrameElement source = elements_[i]; | 509 FrameElement source = elements_[i]; |
| 335 FrameElement target = new_elements[i]; | 510 FrameElement target = new_elements[i]; |
| 336 ASSERT(!target.is_valid() || target.is_register() || target.is_memory()); | 511 ASSERT(!target.is_valid() || target.is_register() || target.is_memory()); |
| 337 if (target.is_register()) { | 512 if (target.is_register()) { |
| 338 if (source.is_constant()) { | 513 if (source.is_constant()) { |
| 339 __ Set(target.reg(), Immediate(source.handle())); | 514 __ Set(target.reg(), Immediate(source.handle())); |
| 340 } else if (source.is_register() && !source.reg().is(target.reg())) { | 515 } else if (source.is_register() && !source.reg().is(target.reg())) { |
| 516 Unuse(source.reg()); |
| 341 __ mov(target.reg(), source.reg()); | 517 __ mov(target.reg(), source.reg()); |
| 342 } | 518 } |
| 519 // Otherwise the source and target are the same register or the |
| 520 // source is a copy. If the source is a copy that implies that |
| 521 // it is the same register as the target (copies that are moved |
| 522 // to other registers appear as register-to-register moves). |
| 343 elements_[i] = target; | 523 elements_[i] = target; |
| 524 ASSERT(target.is_synced() == source.is_synced()); |
| 344 } else if (target.is_memory()) { | 525 } else if (target.is_memory()) { |
| 345 if (!source.is_memory()) { | 526 if (!source.is_memory()) { |
| 346 // Spilling a source register would decrement its reference count, | 527 SpillElementAt(i); |
| 347 // but we have already done that when computing new target elements, | |
| 348 // so we use a raw spill. | |
| 349 RawSpillElementAt(i); | |
| 350 } | 528 } |
| 351 } | 529 } |
| 352 // Invalid elements do not need to be moved. | 530 // Invalid elements do not need to be moved. |
| 353 } | 531 } |
| 354 | 532 |
| 355 delete[] new_elements; | 533 delete[] new_elements; |
| 356 ASSERT(cgen_->HasValidEntryRegisters()); | 534 ASSERT(cgen_->HasValidEntryRegisters()); |
| 357 } | 535 } |
| 358 | 536 |
| 359 | 537 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 ASSERT(elements_[i].handle().location() == | 596 ASSERT(elements_[i].handle().location() == |
| 419 expect.handle().location()); | 597 expect.handle().location()); |
| 420 ASSERT(elements_[i].is_synced() == expect.is_synced()); | 598 ASSERT(elements_[i].is_synced() == expect.is_synced()); |
| 421 } | 599 } |
| 422 } | 600 } |
| 423 #endif | 601 #endif |
| 424 } | 602 } |
| 425 | 603 |
| 426 | 604 |
| 427 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame *expected) { | 605 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame *expected) { |
| 606 // Move registers, constants, and copies to memory. |
| 428 for (int i = 0; i < elements_.length(); i++) { | 607 for (int i = 0; i < elements_.length(); i++) { |
| 429 FrameElement source = elements_[i]; | 608 FrameElement source = elements_[i]; |
| 430 FrameElement target = expected->elements_[i]; | 609 FrameElement target = expected->elements_[i]; |
| 431 if (target.is_memory() && !source.is_memory()) { | 610 if (target.is_memory() && !source.is_memory()) { |
| 432 ASSERT(source.is_register() || source.is_constant()); | 611 ASSERT(source.is_register() || |
| 612 source.is_constant() || |
| 613 source.is_copy()); |
| 433 SpillElementAt(i); | 614 SpillElementAt(i); |
| 434 } | 615 } |
| 435 } | 616 } |
| 436 } | 617 } |
| 437 | 618 |
| 438 | 619 |
| 439 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame *expected) { | 620 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame *expected) { |
| 621 // Perform register-to-register moves. |
| 440 int start = 0; | 622 int start = 0; |
| 441 int end = elements_.length() - 1; | 623 int end = elements_.length() - 1; |
| 442 bool any_moves_blocked; // Did we fail to make some moves this iteration? | 624 bool any_moves_blocked; // Did we fail to make some moves this iteration? |
| 443 bool should_break_cycles = false; | 625 bool should_break_cycles = false; |
| 444 bool any_moves_made; // Did we make any progress this iteration? | 626 bool any_moves_made; // Did we make any progress this iteration? |
| 445 do { | 627 do { |
| 446 any_moves_blocked = false; | 628 any_moves_blocked = false; |
| 447 any_moves_made = false; | 629 any_moves_made = false; |
| 448 int first_move_blocked = kIllegalIndex; | 630 int first_move_blocked = kIllegalIndex; |
| 449 int last_move_blocked = kIllegalIndex; | 631 int last_move_blocked = kIllegalIndex; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 should_break_cycles = (any_moves_blocked && !any_moves_made); | 673 should_break_cycles = (any_moves_blocked && !any_moves_made); |
| 492 if (any_moves_blocked) { | 674 if (any_moves_blocked) { |
| 493 start = first_move_blocked; | 675 start = first_move_blocked; |
| 494 end = last_move_blocked; | 676 end = last_move_blocked; |
| 495 } | 677 } |
| 496 } while (any_moves_blocked); | 678 } while (any_moves_blocked); |
| 497 } | 679 } |
| 498 | 680 |
| 499 | 681 |
| 500 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { | 682 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { |
| 501 // Finally, constant-to-register and memory-to-register. We do these from | 683 // Move memory, constants, and copies to registers. This is the |
| 502 // the top down so we can use pop for memory-to-register moves above the | 684 // final step and is done from the bottom up so that the backing |
| 503 // expected stack pointer. | 685 // elements of copies are in their correct locations when we |
| 504 for (int i = elements_.length() - 1; i >= 0; i--) { | 686 // encounter the copies. |
| 687 for (int i = 0; i < elements_.length(); i++) { |
| 505 FrameElement source = elements_[i]; | 688 FrameElement source = elements_[i]; |
| 506 FrameElement target = expected->elements_[i]; | 689 FrameElement target = expected->elements_[i]; |
| 507 if (target.is_register() && !source.is_register()) { | 690 if (target.is_register() && !source.is_register()) { |
| 508 ASSERT(source.is_constant() || source.is_memory()); | 691 switch (source.type()) { |
| 509 if (source.is_memory()) { | 692 case FrameElement::INVALID: // Fall through. |
| 510 ASSERT(i <= stack_pointer_); | 693 case FrameElement::REGISTER: |
| 511 if (i <= expected->stack_pointer_) { | 694 UNREACHABLE(); |
| 512 // Elements below both stack pointers can just be moved. | 695 break; |
| 696 |
| 697 case FrameElement::MEMORY: |
| 698 ASSERT(i <= stack_pointer_); |
| 513 __ mov(target.reg(), Operand(ebp, fp_relative(i))); | 699 __ mov(target.reg(), Operand(ebp, fp_relative(i))); |
| 514 } else { | 700 break; |
| 515 // Elements below the current stack pointer but above the expected | 701 |
| 516 // one can be popped, but first we may have to adjust the stack | 702 case FrameElement::CONSTANT: |
| 517 // pointer downward. | 703 __ Set(target.reg(), Immediate(source.handle())); |
| 518 if (stack_pointer_ > i) { | 704 break; |
| 519 // Sync elements between i and stack pointer, and bring | 705 |
| 520 // stack pointer down to i. | 706 case FrameElement::COPY: { |
| 521 #ifdef DEBUG | 707 FrameElement backing = elements_[source.index()]; |
| 522 // In debug builds check to ensure this is safe. | 708 ASSERT(backing.is_memory() || backing.is_register()); |
| 523 for (int j = stack_pointer_; j > i; j--) { | 709 if (backing.is_memory()) { |
| 524 ASSERT(!elements_[j].is_memory()); | 710 ASSERT(source.index() <= stack_pointer_); |
| 525 } | 711 __ mov(target.reg(), Operand(ebp, fp_relative(source.index()))); |
| 526 #endif | 712 } else { |
| 527 int difference = stack_pointer_ - i; | 713 __ mov(target.reg(), backing.reg()); |
| 528 __ add(Operand(esp), Immediate(difference * kPointerSize)); | |
| 529 stack_pointer_ = i; | |
| 530 } | 714 } |
| 531 stack_pointer_--; | |
| 532 __ pop(target.reg()); | |
| 533 } | 715 } |
| 534 } else { | 716 } |
| 535 // Source is constant. | 717 // Ensure the proper sync state. If the source was memory no |
| 536 __ Set(target.reg(), Immediate(source.handle())); | 718 // code needs to be emitted. |
| 537 if (target.is_synced()) { | 719 if (target.is_synced() && !source.is_memory()) { |
| 538 SyncElementAt(i); | 720 SyncElementAt(i); |
| 539 } | |
| 540 } | 721 } |
| 541 Use(target.reg()); | 722 Use(target.reg()); |
| 542 elements_[i] = target; | 723 elements_[i] = target; |
| 543 } | 724 } |
| 544 } | 725 } |
| 545 } | 726 } |
| 546 | 727 |
| 547 | 728 |
| 548 void VirtualFrame::DetachFromCodeGenerator() { | 729 void VirtualFrame::DetachFromCodeGenerator() { |
| 549 // Tell the global register allocator that it is free to reallocate all | 730 // Tell the global register allocator that it is free to reallocate all |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 } | 835 } |
| 655 } | 836 } |
| 656 } | 837 } |
| 657 | 838 |
| 658 | 839 |
| 659 void VirtualFrame::SetElementAt(int index, Result* value) { | 840 void VirtualFrame::SetElementAt(int index, Result* value) { |
| 660 int frame_index = elements_.length() - index - 1; | 841 int frame_index = elements_.length() - index - 1; |
| 661 ASSERT(frame_index >= 0); | 842 ASSERT(frame_index >= 0); |
| 662 ASSERT(frame_index < elements_.length()); | 843 ASSERT(frame_index < elements_.length()); |
| 663 ASSERT(value->is_valid()); | 844 ASSERT(value->is_valid()); |
| 664 FrameElement target = elements_[frame_index]; | 845 FrameElement original = elements_[frame_index]; |
| 665 | 846 |
| 666 if (target.is_register()) { | 847 // Early exit if the element is the same as the one being set. |
| 667 Unuse(target.reg()); | 848 bool same_register = original.is_register() |
| 849 && value->is_register() |
| 850 && original.reg().is(value->reg()); |
| 851 bool same_constant = original.is_constant() |
| 852 && value->is_constant() |
| 853 && original.handle().is_identical_to(value->handle()); |
| 854 if (same_register || same_constant) { |
| 855 value->Unuse(); |
| 856 return; |
| 668 } | 857 } |
| 669 | 858 |
| 859 // If the original may be a copy, adjust to preserve the copy-on-write |
| 860 // semantics of copied elements. |
| 861 if (original.is_register() || original.is_memory()) { |
| 862 FrameElement ignored = AdjustCopies(frame_index); |
| 863 } |
| 864 |
| 865 // If the original is a register reference, deallocate it. |
| 866 if (original.is_register()) { |
| 867 Unuse(original.reg()); |
| 868 } |
| 869 |
| 870 FrameElement new_element; |
| 670 if (value->is_register()) { | 871 if (value->is_register()) { |
| 671 Use(value->reg()); | 872 // There are two cases depending no whether the register already |
| 672 // Write the new value to the frame, if it is changed. | 873 // occurs in the frame or not. |
| 673 // Otherwise, if target equals value, keep its current sync state. | 874 if (register_count(value->reg()) == 0) { |
| 674 if (!target.is_register() || | 875 Use(value->reg()); |
| 675 !value->reg().is(target.reg())) { | |
| 676 elements_[frame_index] = | 876 elements_[frame_index] = |
| 677 FrameElement::RegisterElement(value->reg(), | 877 FrameElement::RegisterElement(value->reg(), |
| 678 FrameElement::NOT_SYNCED); | 878 FrameElement::NOT_SYNCED); |
| 879 } else { |
| 880 for (int i = 0; i < elements_.length(); i++) { |
| 881 FrameElement element = elements_[i]; |
| 882 if (element.is_register() && element.reg().is(value->reg())) { |
| 883 // The register backing store is lower in the frame than its |
| 884 // copy. |
| 885 if (i < frame_index) { |
| 886 elements_[frame_index] = CopyElementAt(i); |
| 887 } else { |
| 888 // There was an early bailout for the case of setting a |
| 889 // register element to itself. |
| 890 ASSERT(i != frame_index); |
| 891 element.clear_sync(); |
| 892 elements_[frame_index] = element; |
| 893 elements_[i] = CopyElementAt(frame_index); |
| 894 } |
| 895 // Exit the loop once the appropriate copy is inserted. |
| 896 break; |
| 897 } |
| 898 } |
| 679 } | 899 } |
| 680 } else { | 900 } else { |
| 681 ASSERT(value->is_constant()); | 901 ASSERT(value->is_constant()); |
| 682 // Write the new value to the frame element, if it is a change. | 902 elements_[frame_index] = |
| 683 // Otherwise, do nothing, and keep the current sync state. | 903 FrameElement::ConstantElement(value->handle(), |
| 684 if (!target.is_constant() || | 904 FrameElement::NOT_SYNCED); |
| 685 !value->handle().is_identical_to(target.handle())) { | |
| 686 elements_[frame_index] = | |
| 687 FrameElement::ConstantElement(value->handle(), | |
| 688 FrameElement::NOT_SYNCED); | |
| 689 } | |
| 690 } | 905 } |
| 691 value->Unuse(); | 906 value->Unuse(); |
| 692 } | 907 } |
| 693 | 908 |
| 694 | 909 |
| 695 void VirtualFrame::SaveContextRegister() { | 910 void VirtualFrame::SaveContextRegister() { |
| 696 FrameElement current = elements_[context_index()]; | 911 FrameElement current = elements_[context_index()]; |
| 697 ASSERT(current.is_register() || current.is_memory()); | 912 ASSERT(current.is_register() || current.is_memory()); |
| 698 if (!current.is_register() || !current.reg().is(esi)) { | 913 if (!current.is_register() || !current.reg().is(esi)) { |
| 699 if (current.is_register()) { | 914 if (current.is_register()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 726 | 941 |
| 727 void VirtualFrame::PushReceiverSlotAddress() { | 942 void VirtualFrame::PushReceiverSlotAddress() { |
| 728 Result temp = cgen_->allocator()->Allocate(); | 943 Result temp = cgen_->allocator()->Allocate(); |
| 729 ASSERT(temp.is_valid()); | 944 ASSERT(temp.is_valid()); |
| 730 __ lea(temp.reg(), ParameterAt(-1)); | 945 __ lea(temp.reg(), ParameterAt(-1)); |
| 731 Push(&temp); | 946 Push(&temp); |
| 732 } | 947 } |
| 733 | 948 |
| 734 | 949 |
| 735 void VirtualFrame::LoadFrameSlotAt(int index) { | 950 void VirtualFrame::LoadFrameSlotAt(int index) { |
| 951 FrameElement new_element = CopyElementAt(index); |
| 952 elements_.Add(new_element); |
| 953 } |
| 954 |
| 955 |
| 956 // Before changing an element which is copied, adjust so that the |
| 957 // first copy becomes the new backing store and all the other copies |
| 958 // are updated. If the original was in memory, the new backing store |
| 959 // is allocated to a register. Return a copy of the new backing store |
| 960 // or an invalid element if the original was not a copy. |
| 961 FrameElement VirtualFrame::AdjustCopies(int index) { |
| 962 FrameElement original = elements_[index]; |
| 963 ASSERT(original.is_memory() || original.is_register()); |
| 964 |
| 965 // Go looking for a first copy above index. |
| 966 int i = index + 1; |
| 967 while (i < elements_.length()) { |
| 968 FrameElement elt = elements_[i]; |
| 969 if (elt.is_copy() && elt.index() == index) break; |
| 970 i++; |
| 971 } |
| 972 |
| 973 if (i < elements_.length()) { |
| 974 // There was a first copy. Make it the new backing element. |
| 975 Register backing_reg; |
| 976 if (original.is_memory()) { |
| 977 Result fresh = cgen_->allocator()->Allocate(); |
| 978 ASSERT(fresh.is_valid()); |
| 979 backing_reg = fresh.reg(); |
| 980 __ mov(backing_reg, Operand(ebp, fp_relative(index))); |
| 981 } else { |
| 982 // The original was in a register. |
| 983 backing_reg = original.reg(); |
| 984 } |
| 985 FrameElement new_backing_element = |
| 986 FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED); |
| 987 if (elements_[i].is_synced()) { |
| 988 new_backing_element.set_sync(); |
| 989 } |
| 990 Use(backing_reg); |
| 991 elements_[i] = new_backing_element; |
| 992 |
| 993 // Update the other copies. |
| 994 FrameElement copy = CopyElementAt(i); |
| 995 for (int j = i; j < elements_.length(); j++) { |
| 996 FrameElement elt = elements_[j]; |
| 997 if (elt.is_copy() && elt.index() == index) { |
| 998 if (elt.is_synced()) { |
| 999 copy.set_sync(); |
| 1000 } else { |
| 1001 copy.clear_sync(); |
| 1002 } |
| 1003 elements_[j] = copy; |
| 1004 } |
| 1005 } |
| 1006 |
| 1007 copy.clear_sync(); |
| 1008 return copy; |
| 1009 } |
| 1010 |
| 1011 return FrameElement::InvalidElement(); |
| 1012 } |
| 1013 |
| 1014 |
| 1015 void VirtualFrame::TakeFrameSlotAt(int index) { |
| 1016 ASSERT(index >= 0); |
| 1017 ASSERT(index <= elements_.length()); |
| 1018 FrameElement original = elements_[index]; |
| 1019 |
| 1020 switch (original.type()) { |
| 1021 case FrameElement::INVALID: |
| 1022 UNREACHABLE(); |
| 1023 break; |
| 1024 |
| 1025 case FrameElement::MEMORY: { |
| 1026 // Allocate the element to a register. If it is not copied, |
| 1027 // push that register on top of the frame. If it is copied, |
| 1028 // make the first copy the backing store and push a fresh copy |
| 1029 // on top of the frame. |
| 1030 FrameElement copy = AdjustCopies(index); |
| 1031 if (copy.is_valid()) { |
| 1032 // The original element was a copy. Push the copy of the new |
| 1033 // backing store. |
| 1034 elements_.Add(copy); |
| 1035 } else { |
| 1036 // The element was not a copy. Move it to a register and push |
| 1037 // that. |
| 1038 Result fresh = cgen_->allocator()->Allocate(); |
| 1039 ASSERT(fresh.is_valid()); |
| 1040 FrameElement new_element = |
| 1041 FrameElement::RegisterElement(fresh.reg(), |
| 1042 FrameElement::NOT_SYNCED); |
| 1043 Use(fresh.reg()); |
| 1044 elements_.Add(new_element); |
| 1045 __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); |
| 1046 } |
| 1047 break; |
| 1048 } |
| 1049 |
| 1050 case FrameElement::REGISTER: { |
| 1051 // If the element is not copied, push it on top of the frame. |
| 1052 // If it is copied, make the first copy be the new backing store |
| 1053 // and push a fresh copy on top of the frame. |
| 1054 FrameElement copy = AdjustCopies(index); |
| 1055 if (copy.is_valid()) { |
| 1056 // The original element was a copy. Push the copy of the new |
| 1057 // backing store. |
| 1058 elements_.Add(copy); |
| 1059 // This is the only case where we have to unuse the original |
| 1060 // register. The original is still counted and so is the new |
| 1061 // backing store of the copies. |
| 1062 Unuse(original.reg()); |
| 1063 } else { |
| 1064 // The element was not a copy. Push it. |
| 1065 original.clear_sync(); |
| 1066 elements_.Add(original); |
| 1067 } |
| 1068 break; |
| 1069 } |
| 1070 |
| 1071 case FrameElement::CONSTANT: |
| 1072 elements_.Add(original); |
| 1073 break; |
| 1074 |
| 1075 case FrameElement::COPY: |
| 1076 elements_.Add(original); |
| 1077 break; |
| 1078 } |
| 1079 elements_[index] = FrameElement::InvalidElement(); |
| 1080 } |
| 1081 |
| 1082 |
| 1083 void VirtualFrame::StoreToFrameSlotAt(int index) { |
| 1084 // Store the value on top of the frame to the virtual frame slot at |
| 1085 // a given index. The value on top of the frame is left in place. |
| 1086 // This is a duplicating operation, so it can create copies. |
| 736 ASSERT(index >= 0); | 1087 ASSERT(index >= 0); |
| 737 ASSERT(index < elements_.length()); | 1088 ASSERT(index < elements_.length()); |
| 738 | 1089 |
| 739 FrameElement element = elements_[index]; | 1090 FrameElement original = elements_[index]; |
| 740 | 1091 // If the stored-to slot may be copied, adjust to preserve the |
| 741 if (element.is_memory()) { | 1092 // copy-on-write semantics of copied elements. |
| 742 ASSERT(index <= stack_pointer_); | 1093 if (original.is_register() || original.is_memory()) { |
| 743 // Eagerly load memory elements into a register. The element at | 1094 FrameElement ignored = AdjustCopies(index); |
| 744 // the index and the new top of the frame are backed by the same | 1095 } |
| 745 // register location. | 1096 |
| 746 Result temp = cgen_->allocator()->Allocate(); | 1097 // If the stored-to slot is a register reference, deallocate it. |
| 747 ASSERT(temp.is_valid()); | 1098 if (original.is_register()) { |
| 748 FrameElement new_element | 1099 Unuse(original.reg()); |
| 749 = FrameElement::RegisterElement(temp.reg(), | 1100 } |
| 750 FrameElement::SYNCED); | 1101 |
| 751 Use(temp.reg()); | 1102 int top_index = elements_.length() - 1; |
| 752 elements_[index] = new_element; | 1103 FrameElement top = elements_[top_index]; |
| 753 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); | 1104 ASSERT(top.is_valid()); |
| 754 | 1105 |
| 755 Use(temp.reg()); | 1106 if (top.is_copy()) { |
| 756 new_element.clear_sync(); | 1107 // There are two cases based on the relative positions of the |
| 757 elements_.Add(new_element); | 1108 // stored-to slot and the backing slot of the top element. |
| 758 } else { | 1109 int backing_index = top.index(); |
| 759 // For constants and registers, add an (unsynced) copy of the element to | 1110 ASSERT(backing_index != index); |
| 760 // the top of the frame. | 1111 if (backing_index < index) { |
| 761 ASSERT(element.is_register() || element.is_constant()); | 1112 // 1. The top element is a copy of a slot below the stored-to |
| 762 if (element.is_register()) { | 1113 // slot. The stored-to slot becomes an unsynced copy of that |
| 763 Use(element.reg()); | 1114 // same backing slot. |
| 764 } | 1115 elements_[index] = CopyElementAt(backing_index); |
| 765 element.clear_sync(); | 1116 } else { |
| 766 elements_.Add(element); | 1117 // 2. The top element is a copy of a slot above the stored-to |
| 767 } | 1118 // slot. The stored-to slot becomes the new (unsynced) backing |
| 768 } | 1119 // slot and both the top element and the element at the former |
| 769 | 1120 // backing slot become copies of it. The sync state of the top |
| 770 | 1121 // and former backing elements is preserved. |
| 771 void VirtualFrame::TakeFrameSlotAt(int index) { | 1122 FrameElement backing_element = elements_[backing_index]; |
| 772 LoadFrameSlotAt(index); | 1123 ASSERT(backing_element.is_memory() || backing_element.is_register()); |
| 773 | 1124 if (backing_element.is_memory()) { |
| 774 if (elements_[index].is_register()) { | 1125 // Because sets of copies are canonicalized to be backed by |
| 775 Unuse(elements_[index].reg()); | 1126 // their lowest frame element, and because memory frame |
| 776 } | 1127 // elements are backed by the corresponding stack address, we |
| 777 elements_[index] = FrameElement::InvalidElement(); | 1128 // have to move the actual value down in the stack. |
| 778 } | 1129 // |
| 779 | 1130 // TODO(209): considering allocating the stored-to slot to the |
| 780 | 1131 // temp register. Alternatively, allow copies to appear in |
| 781 void VirtualFrame::StoreToFrameSlotAt(int index) { | 1132 // any order in the frame and lazily move the value down to |
| 782 // Store the value on top of the frame to the virtual frame slot at a | 1133 // the slot. |
| 783 // given index. The value on top of the frame is left in place. | 1134 Result temp = cgen_->allocator()->Allocate(); |
| 784 ASSERT(index >= 0); | 1135 ASSERT(temp.is_valid()); |
| 785 ASSERT(index < elements_.length()); | 1136 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index))); |
| 786 FrameElement top = elements_[elements_.length() - 1]; | 1137 __ mov(Operand (ebp, fp_relative(index)), temp.reg()); |
| 787 | 1138 } else if (backing_element.is_synced()) { |
| 788 if (elements_[index].is_register()) { | 1139 // If the element is a register, we will not actually move |
| 789 Unuse(elements_[index].reg()); | 1140 // anything on the stack but only update the virtual frame |
| 790 } | 1141 // element. |
| 791 // The virtual frame slot will be of the same type and have the same value | 1142 backing_element.clear_sync(); |
| 792 // as the frame top. | 1143 } |
| 1144 elements_[index] = backing_element; |
| 1145 |
| 1146 // The old backing element becomes a copy of the new backing |
| 1147 // element. |
| 1148 FrameElement new_element = CopyElementAt(index); |
| 1149 elements_[backing_index] = new_element; |
| 1150 if (backing_element.is_synced()) { |
| 1151 elements_[backing_index].set_sync(); |
| 1152 } |
| 1153 |
| 1154 // All the copies of the old backing element (including the top |
| 1155 // element) become copies of the new backing element. |
| 1156 for (int i = backing_index + 1; i < elements_.length(); i++) { |
| 1157 FrameElement current = elements_[i]; |
| 1158 if (current.is_copy() && current.index() == backing_index) { |
| 1159 elements_[i] = new_element; |
| 1160 if (current.is_synced()) { |
| 1161 elements_[i].set_sync(); |
| 1162 } |
| 1163 } |
| 1164 } |
| 1165 |
| 1166 } |
| 1167 |
| 1168 return; |
| 1169 } |
| 1170 |
| 1171 // Move the top element to the stored-to slot and replace it (the |
| 1172 // top element) with a copy. |
| 793 elements_[index] = top; | 1173 elements_[index] = top; |
| 794 | |
| 795 if (top.is_memory()) { | 1174 if (top.is_memory()) { |
| 796 // TODO(209): consider allocating the slot to a register. | 1175 // TODO(209): consider allocating the stored-to slot to the temp |
| 797 // | 1176 // register. Alternatively, allow copies to appear in any order |
| 798 // Emit code to store memory values into the required frame slot. | 1177 // in the frame and lazily move the value down to the slot. |
| 1178 FrameElement new_top = CopyElementAt(index); |
| 1179 new_top.set_sync(); |
| 1180 elements_[top_index] = new_top; |
| 1181 |
| 1182 // The sync state of the former top element is correct (synced). |
| 1183 // Emit code to move the value down in the frame. |
| 799 Result temp = cgen_->allocator()->Allocate(); | 1184 Result temp = cgen_->allocator()->Allocate(); |
| 800 ASSERT(temp.is_valid()); | 1185 ASSERT(temp.is_valid()); |
| 801 __ mov(temp.reg(), Top()); | 1186 __ mov(temp.reg(), Top()); |
| 802 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); | 1187 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); |
| 1188 } else if (top.is_register()) { |
| 1189 // The stored-to slot has the (unsynced) register reference and |
| 1190 // the top element becomes a copy. The sync state of the top is |
| 1191 // preserved. |
| 1192 FrameElement new_top = CopyElementAt(index); |
| 1193 if (top.is_synced()) { |
| 1194 new_top.set_sync(); |
| 1195 elements_[index].clear_sync(); |
| 1196 } |
| 1197 elements_[top_index] = new_top; |
| 803 } else { | 1198 } else { |
| 804 // We have not actually written the value to memory. | 1199 // The stored-to slot holds the same value as the top but |
| 1200 // unsynced. (We do not have copies of constants yet.) |
| 1201 ASSERT(top.is_constant()); |
| 805 elements_[index].clear_sync(); | 1202 elements_[index].clear_sync(); |
| 806 | 1203 } |
| 807 if (top.is_register()) { | 1204 } |
| 808 // Establish another frame-internal reference to the register. | 1205 |
| 809 Use(top.reg()); | |
| 810 } | |
| 811 } | |
| 812 } | |
| 813 | |
| 814 | 1206 |
| 815 void VirtualFrame::PushTryHandler(HandlerType type) { | 1207 void VirtualFrame::PushTryHandler(HandlerType type) { |
| 816 ASSERT(cgen_->HasValidEntryRegisters()); | 1208 ASSERT(cgen_->HasValidEntryRegisters()); |
| 817 // Grow the expression stack by handler size less two (the return address | 1209 // Grow the expression stack by handler size less two (the return address |
| 818 // is already pushed by a call instruction, and PushTryHandler from the | 1210 // is already pushed by a call instruction, and PushTryHandler from the |
| 819 // macro assembler will leave the top of stack in the eax register to be | 1211 // macro assembler will leave the top of stack in the eax register to be |
| 820 // pushed separately). | 1212 // pushed separately). |
| 821 Adjust(kHandlerSize - 2); | 1213 Adjust(kHandlerSize - 2); |
| 822 __ PushTryHandler(IN_JAVASCRIPT, type); | 1214 __ PushTryHandler(IN_JAVASCRIPT, type); |
| 823 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS | 1215 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS |
| 824 EmitPush(eax); | 1216 EmitPush(eax); |
| 825 } | 1217 } |
| 826 | 1218 |
| 827 | 1219 |
| 828 Result VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { | 1220 Result VirtualFrame::RawCallStub(CodeStub* stub, int frame_arg_count) { |
| 829 ASSERT(cgen_->HasValidEntryRegisters()); | 1221 ASSERT(cgen_->HasValidEntryRegisters()); |
| 830 PrepareForCall(frame_arg_count, frame_arg_count); | |
| 831 __ CallStub(stub); | 1222 __ CallStub(stub); |
| 832 Result result = cgen_->allocator()->Allocate(eax); | 1223 Result result = cgen_->allocator()->Allocate(eax); |
| 833 ASSERT(result.is_valid()); | 1224 ASSERT(result.is_valid()); |
| 834 return result; | 1225 return result; |
| 835 } | 1226 } |
| 836 | 1227 |
| 837 | 1228 |
| 1229 Result VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { |
| 1230 PrepareForCall(frame_arg_count, frame_arg_count); |
| 1231 return RawCallStub(stub, frame_arg_count); |
| 1232 } |
| 1233 |
| 1234 |
| 838 Result VirtualFrame::CallStub(CodeStub* stub, | 1235 Result VirtualFrame::CallStub(CodeStub* stub, |
| 839 Result* arg, | 1236 Result* arg, |
| 840 int frame_arg_count) { | 1237 int frame_arg_count) { |
| 1238 PrepareForCall(frame_arg_count, frame_arg_count); |
| 841 arg->Unuse(); | 1239 arg->Unuse(); |
| 842 return CallStub(stub, frame_arg_count); | 1240 return RawCallStub(stub, frame_arg_count); |
| 843 } | 1241 } |
| 844 | 1242 |
| 845 | 1243 |
| 846 Result VirtualFrame::CallStub(CodeStub* stub, | 1244 Result VirtualFrame::CallStub(CodeStub* stub, |
| 847 Result* arg0, | 1245 Result* arg0, |
| 848 Result* arg1, | 1246 Result* arg1, |
| 849 int frame_arg_count) { | 1247 int frame_arg_count) { |
| 1248 PrepareForCall(frame_arg_count, frame_arg_count); |
| 850 arg0->Unuse(); | 1249 arg0->Unuse(); |
| 851 arg1->Unuse(); | 1250 arg1->Unuse(); |
| 852 return CallStub(stub, frame_arg_count); | 1251 return RawCallStub(stub, frame_arg_count); |
| 853 } | 1252 } |
| 854 | 1253 |
| 855 | 1254 |
| 856 Result VirtualFrame::CallRuntime(Runtime::Function* f, | 1255 Result VirtualFrame::CallRuntime(Runtime::Function* f, |
| 857 int frame_arg_count) { | 1256 int frame_arg_count) { |
| 1257 PrepareForCall(frame_arg_count, frame_arg_count); |
| 858 ASSERT(cgen_->HasValidEntryRegisters()); | 1258 ASSERT(cgen_->HasValidEntryRegisters()); |
| 859 PrepareForCall(frame_arg_count, frame_arg_count); | |
| 860 __ CallRuntime(f, frame_arg_count); | 1259 __ CallRuntime(f, frame_arg_count); |
| 861 Result result = cgen_->allocator()->Allocate(eax); | 1260 Result result = cgen_->allocator()->Allocate(eax); |
| 862 ASSERT(result.is_valid()); | 1261 ASSERT(result.is_valid()); |
| 863 return result; | 1262 return result; |
| 864 } | 1263 } |
| 865 | 1264 |
| 866 | 1265 |
| 867 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, | 1266 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, |
| 868 int frame_arg_count) { | 1267 int frame_arg_count) { |
| 1268 PrepareForCall(frame_arg_count, frame_arg_count); |
| 869 ASSERT(cgen_->HasValidEntryRegisters()); | 1269 ASSERT(cgen_->HasValidEntryRegisters()); |
| 870 PrepareForCall(frame_arg_count, frame_arg_count); | |
| 871 __ CallRuntime(id, frame_arg_count); | 1270 __ CallRuntime(id, frame_arg_count); |
| 872 Result result = cgen_->allocator()->Allocate(eax); | 1271 Result result = cgen_->allocator()->Allocate(eax); |
| 873 ASSERT(result.is_valid()); | 1272 ASSERT(result.is_valid()); |
| 874 return result; | 1273 return result; |
| 875 } | 1274 } |
| 876 | 1275 |
| 877 | 1276 |
| 878 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, | 1277 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, |
| 879 InvokeFlag flag, | 1278 InvokeFlag flag, |
| 880 int frame_arg_count) { | 1279 int frame_arg_count) { |
| 1280 PrepareForCall(frame_arg_count, frame_arg_count); |
| 881 ASSERT(cgen_->HasValidEntryRegisters()); | 1281 ASSERT(cgen_->HasValidEntryRegisters()); |
| 882 PrepareForCall(frame_arg_count, frame_arg_count); | |
| 883 __ InvokeBuiltin(id, flag); | 1282 __ InvokeBuiltin(id, flag); |
| 884 Result result = cgen_->allocator()->Allocate(eax); | 1283 Result result = cgen_->allocator()->Allocate(eax); |
| 885 ASSERT(result.is_valid()); | 1284 ASSERT(result.is_valid()); |
| 886 return result; | 1285 return result; |
| 887 } | 1286 } |
| 888 | 1287 |
| 889 | 1288 |
| 890 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, | 1289 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, |
| 891 RelocInfo::Mode rmode, | 1290 RelocInfo::Mode rmode) { |
| 892 int spilled_args, | |
| 893 int dropped_args) { | |
| 894 ASSERT(cgen_->HasValidEntryRegisters()); | 1291 ASSERT(cgen_->HasValidEntryRegisters()); |
| 895 PrepareForCall(spilled_args, dropped_args); | |
| 896 __ call(code, rmode); | 1292 __ call(code, rmode); |
| 897 Result result = cgen_->allocator()->Allocate(eax); | 1293 Result result = cgen_->allocator()->Allocate(eax); |
| 898 ASSERT(result.is_valid()); | 1294 ASSERT(result.is_valid()); |
| 899 return result; | 1295 return result; |
| 900 } | 1296 } |
| 901 | 1297 |
| 902 | 1298 |
| 903 Result VirtualFrame::CallCodeObject(Handle<Code> code, | 1299 Result VirtualFrame::CallCodeObject(Handle<Code> code, |
| 904 RelocInfo::Mode rmode, | 1300 RelocInfo::Mode rmode, |
| 905 int dropped_args) { | 1301 int dropped_args) { |
| 906 int spilled_args = 0; | 1302 int spilled_args = 0; |
| 907 switch (code->kind()) { | 1303 switch (code->kind()) { |
| 908 case Code::CALL_IC: | 1304 case Code::CALL_IC: |
| 909 spilled_args = dropped_args + 1; | 1305 spilled_args = dropped_args + 1; |
| 910 break; | 1306 break; |
| 911 case Code::FUNCTION: | 1307 case Code::FUNCTION: |
| 912 spilled_args = dropped_args + 1; | 1308 spilled_args = dropped_args + 1; |
| 913 break; | 1309 break; |
| 914 case Code::KEYED_LOAD_IC: | 1310 case Code::KEYED_LOAD_IC: |
| 915 ASSERT(dropped_args == 0); | 1311 ASSERT(dropped_args == 0); |
| 916 spilled_args = 2; | 1312 spilled_args = 2; |
| 917 break; | 1313 break; |
| 918 default: | 1314 default: |
| 919 // The other types of code objects are called with values | 1315 // The other types of code objects are called with values |
| 920 // in specific registers, and are handled in functions with | 1316 // in specific registers, and are handled in functions with |
| 921 // a different signature. | 1317 // a different signature. |
| 922 UNREACHABLE(); | 1318 UNREACHABLE(); |
| 923 break; | 1319 break; |
| 924 } | 1320 } |
| 925 return RawCallCodeObject(code, rmode, spilled_args, dropped_args); | 1321 PrepareForCall(spilled_args, dropped_args); |
| 1322 return RawCallCodeObject(code, rmode); |
| 926 } | 1323 } |
| 927 | 1324 |
| 928 | 1325 |
| 929 Result VirtualFrame::CallCodeObject(Handle<Code> code, | 1326 Result VirtualFrame::CallCodeObject(Handle<Code> code, |
| 930 RelocInfo::Mode rmode, | 1327 RelocInfo::Mode rmode, |
| 931 Result* arg, | 1328 Result* arg, |
| 932 int dropped_args) { | 1329 int dropped_args) { |
| 933 int spilled_args = 0; | 1330 int spilled_args = 0; |
| 934 switch (code->kind()) { | 1331 switch (code->kind()) { |
| 935 case Code::CALL_IC: | 1332 case Code::CALL_IC: |
| 936 ASSERT(arg->reg().is(eax)); | 1333 ASSERT(arg->reg().is(eax)); |
| 937 spilled_args = dropped_args + 1; | 1334 spilled_args = dropped_args + 1; |
| 938 break; | 1335 break; |
| 939 case Code::LOAD_IC: | 1336 case Code::LOAD_IC: |
| 940 ASSERT(arg->reg().is(ecx)); | 1337 ASSERT(arg->reg().is(ecx)); |
| 941 ASSERT(dropped_args == 0); | 1338 ASSERT(dropped_args == 0); |
| 942 spilled_args = 1; | 1339 spilled_args = 1; |
| 943 break; | 1340 break; |
| 944 case Code::KEYED_STORE_IC: | 1341 case Code::KEYED_STORE_IC: |
| 945 ASSERT(arg->reg().is(eax)); | 1342 ASSERT(arg->reg().is(eax)); |
| 946 ASSERT(dropped_args == 0); | 1343 ASSERT(dropped_args == 0); |
| 947 spilled_args = 2; | 1344 spilled_args = 2; |
| 948 break; | 1345 break; |
| 949 default: | 1346 default: |
| 950 // No other types of code objects are called with values | 1347 // No other types of code objects are called with values |
| 951 // in exactly one register. | 1348 // in exactly one register. |
| 952 UNREACHABLE(); | 1349 UNREACHABLE(); |
| 953 break; | 1350 break; |
| 954 } | 1351 } |
| 1352 PrepareForCall(spilled_args, dropped_args); |
| 955 arg->Unuse(); | 1353 arg->Unuse(); |
| 956 return RawCallCodeObject(code, rmode, spilled_args, dropped_args); | 1354 return RawCallCodeObject(code, rmode); |
| 957 } | 1355 } |
| 958 | 1356 |
| 959 | 1357 |
| 960 Result VirtualFrame::CallCodeObject(Handle<Code> code, | 1358 Result VirtualFrame::CallCodeObject(Handle<Code> code, |
| 961 RelocInfo::Mode rmode, | 1359 RelocInfo::Mode rmode, |
| 962 Result* arg0, | 1360 Result* arg0, |
| 963 Result* arg1, | 1361 Result* arg1, |
| 964 int dropped_args) { | 1362 int dropped_args) { |
| 965 int spilled_args = 1; | 1363 int spilled_args = 1; |
| 966 switch (code->kind()) { | 1364 switch (code->kind()) { |
| 967 case Code::STORE_IC: | 1365 case Code::STORE_IC: |
| 968 ASSERT(arg0->reg().is(eax)); | 1366 ASSERT(arg0->reg().is(eax)); |
| 969 ASSERT(arg1->reg().is(ecx)); | 1367 ASSERT(arg1->reg().is(ecx)); |
| 970 ASSERT(dropped_args == 0); | 1368 ASSERT(dropped_args == 0); |
| 971 spilled_args = 1; | 1369 spilled_args = 1; |
| 972 break; | 1370 break; |
| 973 case Code::BUILTIN: | 1371 case Code::BUILTIN: |
| 974 ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall)); | 1372 ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall)); |
| 975 ASSERT(arg0->reg().is(eax)); | 1373 ASSERT(arg0->reg().is(eax)); |
| 976 ASSERT(arg1->reg().is(edi)); | 1374 ASSERT(arg1->reg().is(edi)); |
| 977 spilled_args = dropped_args + 1; | 1375 spilled_args = dropped_args + 1; |
| 978 break; | 1376 break; |
| 979 default: | 1377 default: |
| 980 // No other types of code objects are called with values | 1378 // No other types of code objects are called with values |
| 981 // in exactly two registers. | 1379 // in exactly two registers. |
| 982 UNREACHABLE(); | 1380 UNREACHABLE(); |
| 983 break; | 1381 break; |
| 984 } | 1382 } |
| 1383 PrepareForCall(spilled_args, dropped_args); |
| 985 arg0->Unuse(); | 1384 arg0->Unuse(); |
| 986 arg1->Unuse(); | 1385 arg1->Unuse(); |
| 987 return RawCallCodeObject(code, rmode, spilled_args, dropped_args); | 1386 return RawCallCodeObject(code, rmode); |
| 988 } | 1387 } |
| 989 | 1388 |
| 990 | 1389 |
| 991 void VirtualFrame::Drop(int count) { | 1390 void VirtualFrame::Drop(int count) { |
| 992 ASSERT(height() >= count); | 1391 ASSERT(height() >= count); |
| 993 int num_virtual_elements = (elements_.length() - 1) - stack_pointer_; | 1392 int num_virtual_elements = (elements_.length() - 1) - stack_pointer_; |
| 994 | 1393 |
| 995 // Emit code to lower the stack pointer if necessary. | 1394 // Emit code to lower the stack pointer if necessary. |
| 996 if (num_virtual_elements < count) { | 1395 if (num_virtual_elements < count) { |
| 997 int num_dropped = count - num_virtual_elements; | 1396 int num_dropped = count - num_virtual_elements; |
| 998 stack_pointer_ -= num_dropped; | 1397 stack_pointer_ -= num_dropped; |
| 999 __ add(Operand(esp), Immediate(num_dropped * kPointerSize)); | 1398 __ add(Operand(esp), Immediate(num_dropped * kPointerSize)); |
| 1000 } | 1399 } |
| 1001 | 1400 |
| 1002 // Discard elements from the virtual frame and free any registers. | 1401 // Discard elements from the virtual frame and free any registers. |
| 1003 for (int i = 0; i < count; i++) { | 1402 for (int i = 0; i < count; i++) { |
| 1004 FrameElement dropped = elements_.RemoveLast(); | 1403 FrameElement dropped = elements_.RemoveLast(); |
| 1005 if (dropped.is_register()) { | 1404 if (dropped.is_register()) { |
| 1006 Unuse(dropped.reg()); | 1405 Unuse(dropped.reg()); |
| 1007 } | 1406 } |
| 1008 } | 1407 } |
| 1009 } | 1408 } |
| 1010 | 1409 |
| 1011 | 1410 |
| 1012 Result VirtualFrame::Pop() { | 1411 Result VirtualFrame::Pop() { |
| 1013 FrameElement popped = elements_.RemoveLast(); | 1412 FrameElement element = elements_.RemoveLast(); |
| 1014 bool pop_needed = (stack_pointer_ == elements_.length()); | 1413 int index = elements_.length(); |
| 1414 ASSERT(element.is_valid()); |
| 1015 | 1415 |
| 1016 if (popped.is_constant()) { | 1416 bool pop_needed = (stack_pointer_ == index); |
| 1017 if (pop_needed) { | 1417 if (pop_needed) { |
| 1018 stack_pointer_--; | 1418 stack_pointer_--; |
| 1019 __ add(Operand(esp), Immediate(kPointerSize)); | 1419 if (element.is_memory()) { |
| 1420 Result temp = cgen_->allocator()->Allocate(); |
| 1421 ASSERT(temp.is_valid()); |
| 1422 __ pop(temp.reg()); |
| 1423 return temp; |
| 1020 } | 1424 } |
| 1021 return Result(popped.handle(), cgen_); | 1425 |
| 1022 } else if (popped.is_register()) { | 1426 __ add(Operand(esp), Immediate(kPointerSize)); |
| 1023 Unuse(popped.reg()); | 1427 } |
| 1024 if (pop_needed) { | 1428 ASSERT(!element.is_memory()); |
| 1025 stack_pointer_--; | 1429 |
| 1026 __ add(Operand(esp), Immediate(kPointerSize)); | 1430 // The top element is a register, constant, or a copy. Unuse |
| 1027 } | 1431 // registers and follow copies to their backing store. |
| 1028 return Result(popped.reg(), cgen_); | 1432 if (element.is_register()) { |
| 1029 } else { | 1433 Unuse(element.reg()); |
| 1030 ASSERT(popped.is_memory()); | 1434 } else if (element.is_copy()) { |
| 1435 ASSERT(element.index() < index); |
| 1436 index = element.index(); |
| 1437 element = elements_[index]; |
| 1438 } |
| 1439 ASSERT(!element.is_copy()); |
| 1440 |
| 1441 // The element is memory, a register, or a constant. |
| 1442 if (element.is_memory()) { |
| 1443 // Memory elements could only be the backing store of a copy. |
| 1444 // Allocate the original to a register. |
| 1445 ASSERT(index <= stack_pointer_); |
| 1031 Result temp = cgen_->allocator()->Allocate(); | 1446 Result temp = cgen_->allocator()->Allocate(); |
| 1032 ASSERT(temp.is_valid()); | 1447 ASSERT(temp.is_valid()); |
| 1033 ASSERT(pop_needed); | 1448 Use(temp.reg()); |
| 1034 stack_pointer_--; | 1449 FrameElement new_element = |
| 1035 __ pop(temp.reg()); | 1450 FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED); |
| 1036 return temp; | 1451 elements_[index] = new_element; |
| 1452 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); |
| 1453 return Result(temp.reg(), cgen_); |
| 1454 } else if (element.is_register()) { |
| 1455 return Result(element.reg(), cgen_); |
| 1456 } else { |
| 1457 ASSERT(element.is_constant()); |
| 1458 return Result(element.handle(), cgen_); |
| 1037 } | 1459 } |
| 1038 } | 1460 } |
| 1039 | 1461 |
| 1040 | 1462 |
| 1041 void VirtualFrame::EmitPop(Register reg) { | 1463 void VirtualFrame::EmitPop(Register reg) { |
| 1042 ASSERT(stack_pointer_ == elements_.length() - 1); | 1464 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 1043 stack_pointer_--; | 1465 stack_pointer_--; |
| 1044 elements_.RemoveLast(); | 1466 elements_.RemoveLast(); |
| 1045 __ pop(reg); | 1467 __ pop(reg); |
| 1046 } | 1468 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1072 | 1494 |
| 1073 void VirtualFrame::EmitPush(Immediate immediate) { | 1495 void VirtualFrame::EmitPush(Immediate immediate) { |
| 1074 ASSERT(stack_pointer_ == elements_.length() - 1); | 1496 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 1075 elements_.Add(FrameElement::MemoryElement()); | 1497 elements_.Add(FrameElement::MemoryElement()); |
| 1076 stack_pointer_++; | 1498 stack_pointer_++; |
| 1077 __ push(immediate); | 1499 __ push(immediate); |
| 1078 } | 1500 } |
| 1079 | 1501 |
| 1080 | 1502 |
| 1081 void VirtualFrame::Push(Register reg) { | 1503 void VirtualFrame::Push(Register reg) { |
| 1082 Use(reg); | 1504 FrameElement new_element; |
| 1083 elements_.Add(FrameElement::RegisterElement(reg, | 1505 if (register_count(reg) == 0) { |
| 1084 FrameElement::NOT_SYNCED)); | 1506 Use(reg); |
| 1507 new_element = |
| 1508 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED); |
| 1509 } else { |
| 1510 for (int i = 0; i < elements_.length(); i++) { |
| 1511 FrameElement element = elements_[i]; |
| 1512 if (element.is_register() && element.reg().is(reg)) { |
| 1513 new_element = CopyElementAt(i); |
| 1514 break; |
| 1515 } |
| 1516 } |
| 1517 } |
| 1518 elements_.Add(new_element); |
| 1085 } | 1519 } |
| 1086 | 1520 |
| 1087 | 1521 |
| 1088 void VirtualFrame::Push(Handle<Object> value) { | 1522 void VirtualFrame::Push(Handle<Object> value) { |
| 1089 elements_.Add(FrameElement::ConstantElement(value, | 1523 elements_.Add(FrameElement::ConstantElement(value, |
| 1090 FrameElement::NOT_SYNCED)); | 1524 FrameElement::NOT_SYNCED)); |
| 1091 } | 1525 } |
| 1092 | 1526 |
| 1093 | 1527 |
| 1094 void VirtualFrame::Push(Result* result) { | 1528 void VirtualFrame::Push(Result* result) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1120 return false; | 1554 return false; |
| 1121 } | 1555 } |
| 1122 } | 1556 } |
| 1123 return true; | 1557 return true; |
| 1124 } | 1558 } |
| 1125 #endif | 1559 #endif |
| 1126 | 1560 |
| 1127 #undef __ | 1561 #undef __ |
| 1128 | 1562 |
| 1129 } } // namespace v8::internal | 1563 } } // namespace v8::internal |
| OLD | NEW |