| 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 19 matching lines...) Expand all Loading... |
| 30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
| 31 #include "register-allocator-inl.h" | 31 #include "register-allocator-inl.h" |
| 32 | 32 |
| 33 namespace v8 { namespace internal { | 33 namespace v8 { namespace internal { |
| 34 | 34 |
| 35 // ------------------------------------------------------------------------- | 35 // ------------------------------------------------------------------------- |
| 36 // VirtualFrame implementation. | 36 // VirtualFrame implementation. |
| 37 | 37 |
| 38 // When cloned, a frame is a deep copy of the original. | 38 // When cloned, a frame is a deep copy of the original. |
| 39 VirtualFrame::VirtualFrame(VirtualFrame* original) | 39 VirtualFrame::VirtualFrame(VirtualFrame* original) |
| 40 : elements_(original->elements_.length()), | 40 : elements_(original->element_count()), |
| 41 stack_pointer_(original->stack_pointer_) { | 41 stack_pointer_(original->stack_pointer_) { |
| 42 elements_.AddAll(original->elements_); | 42 elements_.AddAll(original->elements_); |
| 43 // Copy register locations from original. | 43 // Copy register locations from original. |
| 44 memcpy(®ister_locations_, | 44 memcpy(®ister_locations_, |
| 45 original->register_locations_, | 45 original->register_locations_, |
| 46 sizeof(register_locations_)); | 46 sizeof(register_locations_)); |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| 50 FrameElement VirtualFrame::CopyElementAt(int index) { | 50 FrameElement VirtualFrame::CopyElementAt(int index) { |
| 51 ASSERT(index >= 0); | 51 ASSERT(index >= 0); |
| 52 ASSERT(index < elements_.length()); | 52 ASSERT(index < element_count()); |
| 53 | 53 |
| 54 FrameElement target = elements_[index]; | 54 FrameElement target = elements_[index]; |
| 55 FrameElement result; | 55 FrameElement result; |
| 56 | 56 |
| 57 switch (target.type()) { | 57 switch (target.type()) { |
| 58 case FrameElement::CONSTANT: | 58 case FrameElement::CONSTANT: |
| 59 // We do not copy constants and instead return a fresh unsynced | 59 // We do not copy constants and instead return a fresh unsynced |
| 60 // constant. | 60 // constant. |
| 61 result = FrameElement::ConstantElement(target.handle(), | 61 result = FrameElement::ConstantElement(target.handle(), |
| 62 FrameElement::NOT_SYNCED); | 62 FrameElement::NOT_SYNCED); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 88 return result; | 88 return result; |
| 89 } | 89 } |
| 90 | 90 |
| 91 | 91 |
| 92 // Modify the state of the virtual frame to match the actual frame by adding | 92 // Modify the state of the virtual frame to match the actual frame by adding |
| 93 // extra in-memory elements to the top of the virtual frame. The extra | 93 // extra in-memory elements to the top of the virtual frame. The extra |
| 94 // elements will be externally materialized on the actual frame (eg, by | 94 // elements will be externally materialized on the actual frame (eg, by |
| 95 // pushing an exception handler). No code is emitted. | 95 // pushing an exception handler). No code is emitted. |
| 96 void VirtualFrame::Adjust(int count) { | 96 void VirtualFrame::Adjust(int count) { |
| 97 ASSERT(count >= 0); | 97 ASSERT(count >= 0); |
| 98 ASSERT(stack_pointer_ == elements_.length() - 1); | 98 ASSERT(stack_pointer_ == element_count() - 1); |
| 99 | 99 |
| 100 for (int i = 0; i < count; i++) { | 100 for (int i = 0; i < count; i++) { |
| 101 elements_.Add(FrameElement::MemoryElement()); | 101 elements_.Add(FrameElement::MemoryElement()); |
| 102 } | 102 } |
| 103 stack_pointer_ += count; | 103 stack_pointer_ += count; |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 void VirtualFrame::ForgetElements(int count) { | 107 void VirtualFrame::ForgetElements(int count) { |
| 108 ASSERT(count >= 0); | 108 ASSERT(count >= 0); |
| 109 ASSERT(elements_.length() >= count); | 109 ASSERT(element_count() >= count); |
| 110 | 110 |
| 111 for (int i = 0; i < count; i++) { | 111 for (int i = 0; i < count; i++) { |
| 112 FrameElement last = elements_.RemoveLast(); | 112 FrameElement last = elements_.RemoveLast(); |
| 113 if (last.is_register()) { | 113 if (last.is_register()) { |
| 114 // A hack to properly count register references for the code | 114 // A hack to properly count register references for the code |
| 115 // generator's current frame and also for other frames. The | 115 // generator's current frame and also for other frames. The |
| 116 // same code appears in PrepareMergeTo. | 116 // same code appears in PrepareMergeTo. |
| 117 if (cgen()->frame() == this) { | 117 if (cgen()->frame() == this) { |
| 118 Unuse(last.reg()); | 118 Unuse(last.reg()); |
| 119 } else { | 119 } else { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } else if (index == stack_pointer_ + 1) { | 165 } else if (index == stack_pointer_ + 1) { |
| 166 SyncElementByPushing(index); | 166 SyncElementByPushing(index); |
| 167 } else { | 167 } else { |
| 168 SyncRange(stack_pointer_ + 1, index); | 168 SyncRange(stack_pointer_ + 1, index); |
| 169 } | 169 } |
| 170 } | 170 } |
| 171 | 171 |
| 172 | 172 |
| 173 // Make the type of all elements be MEMORY. | 173 // Make the type of all elements be MEMORY. |
| 174 void VirtualFrame::SpillAll() { | 174 void VirtualFrame::SpillAll() { |
| 175 for (int i = 0; i < elements_.length(); i++) { | 175 for (int i = 0; i < element_count(); i++) { |
| 176 SpillElementAt(i); | 176 SpillElementAt(i); |
| 177 } | 177 } |
| 178 } | 178 } |
| 179 | 179 |
| 180 | 180 |
| 181 void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { | 181 void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { |
| 182 // Perform state changes on this frame that will make merge to the | 182 // Perform state changes on this frame that will make merge to the |
| 183 // expected frame simpler or else increase the likelihood that his | 183 // expected frame simpler or else increase the likelihood that his |
| 184 // frame will match another. | 184 // frame will match another. |
| 185 for (int i = 0; i < elements_.length(); i++) { | 185 for (int i = 0; i < element_count(); i++) { |
| 186 FrameElement source = elements_[i]; | 186 FrameElement source = elements_[i]; |
| 187 FrameElement target = expected->elements_[i]; | 187 FrameElement target = expected->elements_[i]; |
| 188 | 188 |
| 189 if (!target.is_valid() || | 189 if (!target.is_valid() || |
| 190 (target.is_memory() && !source.is_memory() && source.is_synced())) { | 190 (target.is_memory() && !source.is_memory() && source.is_synced())) { |
| 191 // No code needs to be generated to invalidate valid elements. | 191 // No code needs to be generated to invalidate valid elements. |
| 192 // No code needs to be generated to move values to memory if | 192 // No code needs to be generated to move values to memory if |
| 193 // they are already synced. We perform those moves here, before | 193 // they are already synced. We perform those moves here, before |
| 194 // merging. | 194 // merging. |
| 195 if (source.is_register()) { | 195 if (source.is_register()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 216 elements_[i].set_static_type(target.static_type()); | 216 elements_[i].set_static_type(target.static_type()); |
| 217 } | 217 } |
| 218 } | 218 } |
| 219 | 219 |
| 220 | 220 |
| 221 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { | 221 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { |
| 222 ASSERT(height() >= dropped_args); | 222 ASSERT(height() >= dropped_args); |
| 223 ASSERT(height() >= spilled_args); | 223 ASSERT(height() >= spilled_args); |
| 224 ASSERT(dropped_args <= spilled_args); | 224 ASSERT(dropped_args <= spilled_args); |
| 225 | 225 |
| 226 SyncRange(0, elements_.length() - 1); | 226 SyncRange(0, element_count() - 1); |
| 227 // Spill registers. | 227 // Spill registers. |
| 228 for (int i = 0; i < kNumRegisters; i++) { | 228 for (int i = 0; i < kNumRegisters; i++) { |
| 229 if (is_used(i)) { | 229 if (is_used(i)) { |
| 230 SpillElementAt(register_locations_[i]); | 230 SpillElementAt(register_locations_[i]); |
| 231 } | 231 } |
| 232 } | 232 } |
| 233 | 233 |
| 234 // Spill the arguments. | 234 // Spill the arguments. |
| 235 for (int i = elements_.length() - spilled_args; i < elements_.length(); i++) { | 235 for (int i = element_count() - spilled_args; i < element_count(); i++) { |
| 236 if (!elements_[i].is_memory()) { | 236 if (!elements_[i].is_memory()) { |
| 237 SpillElementAt(i); | 237 SpillElementAt(i); |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 | 240 |
| 241 // Forget the frame elements that will be popped by the call. | 241 // Forget the frame elements that will be popped by the call. |
| 242 Forget(dropped_args); | 242 Forget(dropped_args); |
| 243 } | 243 } |
| 244 | 244 |
| 245 | 245 |
| 246 void VirtualFrame::PrepareForReturn() { | 246 void VirtualFrame::PrepareForReturn() { |
| 247 // Spill all locals. This is necessary to make sure all locals have | 247 // Spill all locals. This is necessary to make sure all locals have |
| 248 // the right value when breaking at the return site in the debugger. | 248 // the right value when breaking at the return site in the debugger. |
| 249 // Set their static type to unknown so that they will match the known | 249 // Set their static type to unknown so that they will match the known |
| 250 // return frame. | 250 // return frame. |
| 251 for (int i = 0; i < expression_base_index(); i++) { | 251 for (int i = 0; i < expression_base_index(); i++) { |
| 252 SpillElementAt(i); | 252 SpillElementAt(i); |
| 253 elements_[i].set_static_type(StaticType::unknown()); | 253 elements_[i].set_static_type(StaticType::unknown()); |
| 254 } | 254 } |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 void VirtualFrame::SetElementAt(int index, Result* value) { | 258 void VirtualFrame::SetElementAt(int index, Result* value) { |
| 259 int frame_index = elements_.length() - index - 1; | 259 int frame_index = element_count() - index - 1; |
| 260 ASSERT(frame_index >= 0); | 260 ASSERT(frame_index >= 0); |
| 261 ASSERT(frame_index < elements_.length()); | 261 ASSERT(frame_index < element_count()); |
| 262 ASSERT(value->is_valid()); | 262 ASSERT(value->is_valid()); |
| 263 FrameElement original = elements_[frame_index]; | 263 FrameElement original = elements_[frame_index]; |
| 264 | 264 |
| 265 // Early exit if the element is the same as the one being set. | 265 // Early exit if the element is the same as the one being set. |
| 266 bool same_register = original.is_register() | 266 bool same_register = original.is_register() |
| 267 && value->is_register() | 267 && value->is_register() |
| 268 && original.reg().is(value->reg()); | 268 && original.reg().is(value->reg()); |
| 269 bool same_constant = original.is_constant() | 269 bool same_constant = original.is_constant() |
| 270 && value->is_constant() | 270 && value->is_constant() |
| 271 && original.handle().is_identical_to(value->handle()); | 271 && original.handle().is_identical_to(value->handle()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 292 // There was an early bailout for the case of setting a | 292 // There was an early bailout for the case of setting a |
| 293 // register element to itself. | 293 // register element to itself. |
| 294 ASSERT(i != frame_index); | 294 ASSERT(i != frame_index); |
| 295 elements_[frame_index] = elements_[i]; | 295 elements_[frame_index] = elements_[i]; |
| 296 elements_[i] = CopyElementAt(frame_index); | 296 elements_[i] = CopyElementAt(frame_index); |
| 297 if (elements_[frame_index].is_synced()) { | 297 if (elements_[frame_index].is_synced()) { |
| 298 elements_[i].set_sync(); | 298 elements_[i].set_sync(); |
| 299 } | 299 } |
| 300 elements_[frame_index].clear_sync(); | 300 elements_[frame_index].clear_sync(); |
| 301 register_locations_[value->reg().code()] = frame_index; | 301 register_locations_[value->reg().code()] = frame_index; |
| 302 for (int j = i + 1; j < elements_.length(); j++) { | 302 for (int j = i + 1; j < element_count(); j++) { |
| 303 if (elements_[j].is_copy() && elements_[j].index() == i) { | 303 if (elements_[j].is_copy() && elements_[j].index() == i) { |
| 304 elements_[j].set_index(frame_index); | 304 elements_[j].set_index(frame_index); |
| 305 } | 305 } |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 } else { | 308 } else { |
| 309 // The register value->reg() was not already used on the frame. | 309 // The register value->reg() was not already used on the frame. |
| 310 Use(value->reg(), frame_index); | 310 Use(value->reg(), frame_index); |
| 311 elements_[frame_index] = | 311 elements_[frame_index] = |
| 312 FrameElement::RegisterElement(value->reg(), | 312 FrameElement::RegisterElement(value->reg(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 328 } | 328 } |
| 329 | 329 |
| 330 | 330 |
| 331 void VirtualFrame::Push(Register reg, StaticType static_type) { | 331 void VirtualFrame::Push(Register reg, StaticType static_type) { |
| 332 if (is_used(reg)) { | 332 if (is_used(reg)) { |
| 333 int index = register_index(reg); | 333 int index = register_index(reg); |
| 334 FrameElement element = CopyElementAt(index); | 334 FrameElement element = CopyElementAt(index); |
| 335 ASSERT(static_type.merge(element.static_type()) == element.static_type()); | 335 ASSERT(static_type.merge(element.static_type()) == element.static_type()); |
| 336 elements_.Add(element); | 336 elements_.Add(element); |
| 337 } else { | 337 } else { |
| 338 Use(reg, elements_.length()); | 338 Use(reg, element_count()); |
| 339 FrameElement element = | 339 FrameElement element = |
| 340 FrameElement::RegisterElement(reg, | 340 FrameElement::RegisterElement(reg, |
| 341 FrameElement::NOT_SYNCED, | 341 FrameElement::NOT_SYNCED, |
| 342 static_type); | 342 static_type); |
| 343 elements_.Add(element); | 343 elements_.Add(element); |
| 344 } | 344 } |
| 345 } | 345 } |
| 346 | 346 |
| 347 | 347 |
| 348 void VirtualFrame::Push(Handle<Object> value) { | 348 void VirtualFrame::Push(Handle<Object> value) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 363 } | 363 } |
| 364 | 364 |
| 365 | 365 |
| 366 bool VirtualFrame::Equals(VirtualFrame* other) { | 366 bool VirtualFrame::Equals(VirtualFrame* other) { |
| 367 #ifdef DEBUG | 367 #ifdef DEBUG |
| 368 for (int i = 0; i < kNumRegisters; i++) { | 368 for (int i = 0; i < kNumRegisters; i++) { |
| 369 if (register_locations_[i] != other->register_locations_[i]) { | 369 if (register_locations_[i] != other->register_locations_[i]) { |
| 370 return false; | 370 return false; |
| 371 } | 371 } |
| 372 } | 372 } |
| 373 if (elements_.length() != other->elements_.length()) return false; | 373 if (element_count() != other->element_count()) return false; |
| 374 #endif | 374 #endif |
| 375 if (stack_pointer_ != other->stack_pointer_) return false; | 375 if (stack_pointer_ != other->stack_pointer_) return false; |
| 376 for (int i = 0; i < elements_.length(); i++) { | 376 for (int i = 0; i < element_count(); i++) { |
| 377 if (!elements_[i].Equals(other->elements_[i])) return false; | 377 if (!elements_[i].Equals(other->elements_[i])) return false; |
| 378 } | 378 } |
| 379 | 379 |
| 380 return true; | 380 return true; |
| 381 } | 381 } |
| 382 | 382 |
| 383 | 383 |
| 384 // Specialization of List::ResizeAdd to non-inlined version for FrameElements. | 384 // Specialization of List::ResizeAdd to non-inlined version for FrameElements. |
| 385 // The function ResizeAdd becomes a real function, whose implementation is the | 385 // The function ResizeAdd becomes a real function, whose implementation is the |
| 386 // inlined ResizeAddInternal. | 386 // inlined ResizeAddInternal. |
| 387 template <> | 387 template <> |
| 388 void List<FrameElement, | 388 void List<FrameElement, |
| 389 FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element) { | 389 FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element) { |
| 390 ResizeAddInternal(element); | 390 ResizeAddInternal(element); |
| 391 } | 391 } |
| 392 | 392 |
| 393 } } // namespace v8::internal | 393 } } // namespace v8::internal |
| OLD | NEW |