Chromium Code Reviews| 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 25 matching lines...) Expand all Loading... | |
| 36 | 36 |
| 37 // ------------------------------------------------------------------------- | 37 // ------------------------------------------------------------------------- |
| 38 // Virtual frames | 38 // Virtual frames |
| 39 // | 39 // |
| 40 // The virtual frame is an abstraction of the physical stack frame. It | 40 // The virtual frame is an abstraction of the physical stack frame. It |
| 41 // encapsulates the parameters, frame-allocated locals, and the expression | 41 // encapsulates the parameters, frame-allocated locals, and the expression |
| 42 // stack. It supports push/pop operations on the expression stack, as well | 42 // stack. It supports push/pop operations on the expression stack, as well |
| 43 // as random access to the expression stack elements, locals, and | 43 // as random access to the expression stack elements, locals, and |
| 44 // parameters. | 44 // parameters. |
| 45 | 45 |
| 46 class VirtualFrame : public ZoneObject { | 46 class VirtualFrame: public ZoneObject { |
| 47 public: | 47 public: |
| 48 // A utility class to introduce a scope where the virtual frame is | 48 // A utility class to introduce a scope where the virtual frame is |
| 49 // expected to remain spilled. The constructor spills the code | 49 // expected to remain spilled. The constructor spills the code |
| 50 // generator's current frame, but no attempt is made to require it | 50 // generator's current frame, but no attempt is made to require it |
| 51 // to stay spilled. It is intended as documentation while the code | 51 // to stay spilled. It is intended as documentation while the code |
| 52 // generator is being transformed. | 52 // generator is being transformed. |
| 53 class SpilledScope BASE_EMBEDDED { | 53 class SpilledScope BASE_EMBEDDED { |
| 54 public: | 54 public: |
| 55 SpilledScope() : previous_state_(cgen()->in_spilled_code()) { | 55 SpilledScope() : previous_state_(cgen()->in_spilled_code()) { |
| 56 ASSERT(cgen()->has_valid_frame()); | 56 ASSERT(cgen()->has_valid_frame()); |
| 57 cgen()->frame()->SpillAll(); | 57 cgen()->frame()->SpillAll(); |
| 58 cgen()->set_in_spilled_code(true); | 58 cgen()->set_in_spilled_code(true); |
| 59 } | 59 } |
| 60 | 60 |
| 61 ~SpilledScope() { | 61 ~SpilledScope() { |
| 62 cgen()->set_in_spilled_code(previous_state_); | 62 cgen()->set_in_spilled_code(previous_state_); |
| 63 } | 63 } |
| 64 | 64 |
| 65 private: | 65 private: |
| 66 bool previous_state_; | 66 bool previous_state_; |
| 67 | 67 |
| 68 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } | 68 CodeGenerator* cgen() {return CodeGeneratorScope::Current();} |
| 69 }; | 69 }; |
| 70 | 70 |
| 71 // An illegal index into the virtual frame. | 71 // An illegal index into the virtual frame. |
| 72 static const int kIllegalIndex = -1; | 72 static const int kIllegalIndex = -1; |
| 73 | 73 |
| 74 // Construct an initial virtual frame on entry to a JS function. | 74 // Construct an initial virtual frame on entry to a JS function. |
| 75 VirtualFrame(); | 75 VirtualFrame(); |
| 76 | 76 |
| 77 // Construct a virtual frame as a clone of an existing one. | 77 // Construct a virtual frame as a clone of an existing one. |
| 78 explicit VirtualFrame(VirtualFrame* original); | 78 explicit VirtualFrame(VirtualFrame* original); |
| 79 | 79 |
| 80 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } | 80 CodeGenerator* cgen() { |
| 81 MacroAssembler* masm() { return cgen()->masm(); } | 81 return CodeGeneratorScope::Current(); |
| 82 } | |
|
Erik Corry
2009/06/24 11:46:35
I'd prefer for these whitespace changes not to be
| |
| 83 MacroAssembler* masm() { | |
| 84 return cgen()->masm(); | |
| 85 } | |
| 82 | 86 |
| 83 // Create a duplicate of an existing valid frame element. | 87 // Create a duplicate of an existing valid frame element. |
| 84 FrameElement CopyElementAt(int index); | 88 FrameElement CopyElementAt(int index); |
| 85 | 89 |
| 86 // The number of elements on the virtual frame. | 90 // The number of elements on the virtual frame. |
| 87 int element_count() { return elements_.length(); } | 91 int element_count() { |
| 92 return elements_.length(); | |
| 93 } | |
| 88 | 94 |
| 89 // The height of the virtual expression stack. | 95 // The height of the virtual expression stack. |
| 90 int height() { | 96 int height() { |
| 91 return element_count() - expression_base_index(); | 97 return element_count() - expression_base_index(); |
| 92 } | 98 } |
| 93 | 99 |
| 94 int register_location(int num) { | 100 int register_location(int num) { |
| 95 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); | 101 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); |
| 96 return register_locations_[num]; | 102 return register_locations_[num]; |
| 97 } | 103 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 // Store the top value on the virtual frame into a local frame slot. The | 254 // Store the top value on the virtual frame into a local frame slot. The |
| 249 // value is left in place on top of the frame. | 255 // value is left in place on top of the frame. |
| 250 void StoreToLocalAt(int index) { | 256 void StoreToLocalAt(int index) { |
| 251 StoreToFrameSlotAt(local0_index() + index); | 257 StoreToFrameSlotAt(local0_index() + index); |
| 252 } | 258 } |
| 253 | 259 |
| 254 // Push the address of the receiver slot on the frame. | 260 // Push the address of the receiver slot on the frame. |
| 255 void PushReceiverSlotAddress(); | 261 void PushReceiverSlotAddress(); |
| 256 | 262 |
| 257 // Push the function on top of the frame. | 263 // Push the function on top of the frame. |
| 258 void PushFunction() { PushFrameSlotAt(function_index()); } | 264 void PushFunction() { |
| 265 PushFrameSlotAt(function_index()); | |
| 266 } | |
| 259 | 267 |
| 260 // Save the value of the esi register to the context frame slot. | 268 // Save the value of the esi register to the context frame slot. |
| 261 void SaveContextRegister(); | 269 void SaveContextRegister(); |
| 262 | 270 |
| 263 // Restore the esi register from the value of the context frame | 271 // Restore the esi register from the value of the context frame |
| 264 // slot. | 272 // slot. |
| 265 void RestoreContextRegister(); | 273 void RestoreContextRegister(); |
| 266 | 274 |
| 267 // A parameter as an assembly operand. | 275 // A parameter as an assembly operand. |
| 268 Operand ParameterAt(int index) { | 276 Operand ParameterAt(int index) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 283 TakeFrameSlotAt(param0_index() + index); | 291 TakeFrameSlotAt(param0_index() + index); |
| 284 } | 292 } |
| 285 | 293 |
| 286 // Store the top value on the virtual frame into a parameter frame slot. | 294 // Store the top value on the virtual frame into a parameter frame slot. |
| 287 // The value is left in place on top of the frame. | 295 // The value is left in place on top of the frame. |
| 288 void StoreToParameterAt(int index) { | 296 void StoreToParameterAt(int index) { |
| 289 StoreToFrameSlotAt(param0_index() + index); | 297 StoreToFrameSlotAt(param0_index() + index); |
| 290 } | 298 } |
| 291 | 299 |
| 292 // The receiver frame slot. | 300 // The receiver frame slot. |
| 293 Operand Receiver() { return ParameterAt(-1); } | 301 Operand Receiver() { |
| 302 return ParameterAt(-1); | |
| 303 } | |
| 294 | 304 |
| 295 // Push a try-catch or try-finally handler on top of the virtual frame. | 305 // Push a try-catch or try-finally handler on top of the virtual frame. |
| 296 void PushTryHandler(HandlerType type); | 306 void PushTryHandler(HandlerType type); |
| 297 | 307 |
| 298 // Call stub given the number of arguments it expects on (and | 308 // Call stub given the number of arguments it expects on (and |
| 299 // removes from) the stack. | 309 // removes from) the stack. |
| 300 Result CallStub(CodeStub* stub, int arg_count) { | 310 Result CallStub(CodeStub* stub, int arg_count) { |
| 301 PrepareForCall(arg_count, arg_count); | 311 PrepareForCall(arg_count, arg_count); |
| 302 return RawCallStub(stub); | 312 return RawCallStub(stub); |
| 303 } | 313 } |
| 304 | 314 |
| 305 // Call stub that takes a single argument passed in eax. The | 315 // Call stub that takes a single argument passed in eax. The |
| 306 // argument is given as a result which does not have to be eax or | 316 // argument is given as a result which does not have to be eax or |
| 307 // even a register. The argument is consumed by the call. | 317 // even a register. The argument is consumed by the call. |
| 308 Result CallStub(CodeStub* stub, Result* arg); | 318 Result CallStub(CodeStub* stub, Result* arg); |
| 309 | 319 |
| 310 // Call stub that takes a pair of arguments passed in edx (arg0) and | 320 // Call stub that takes a pair of arguments passed in edx (arg0) and |
| 311 // eax (arg1). The arguments are given as results which do not have | 321 // eax (arg1). The arguments are given as results which do not have |
| 312 // to be in the proper registers or even in registers. The | 322 // to be in the proper registers or even in registers. The |
| 313 // arguments are consumed by the call. | 323 // arguments are consumed by the call. |
| 314 Result CallStub(CodeStub* stub, Result* arg0, Result* arg1); | 324 Result CallStub(CodeStub* stub, Result* arg0, Result* arg1); |
| 315 | 325 |
| 316 // Call runtime given the number of arguments expected on (and | 326 // Call runtime given the number of arguments expected on (and |
| 317 // removed from) the stack. | 327 // removed from) the stack. |
| 318 Result CallRuntime(Runtime::Function* f, int arg_count); | 328 Result CallRuntime(Runtime::Function* f, int arg_count); |
| 319 Result CallRuntime(Runtime::FunctionId id, int arg_count); | 329 Result CallRuntime(Runtime::FunctionId id, int arg_count); |
| 320 | 330 |
| 321 // Invoke builtin given the number of arguments it expects on (and | 331 // Invoke builtin given the number of arguments it expects on (and |
| 322 // removes from) the stack. | 332 // removes from) the stack. |
| 323 Result InvokeBuiltin(Builtins::JavaScript id, | 333 Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count); |
| 324 InvokeFlag flag, | |
| 325 int arg_count); | |
| 326 | 334 |
| 327 // Call load IC. Name and receiver are found on top of the frame. | 335 // Call load IC. Name and receiver are found on top of the frame. |
| 328 // Receiver is not dropped. | 336 // Receiver is not dropped. |
| 329 Result CallLoadIC(RelocInfo::Mode mode); | 337 Result CallLoadIC(RelocInfo::Mode mode); |
| 330 | 338 |
| 331 // Call keyed load IC. Key and receiver are found on top of the | 339 // Call keyed load IC. Key and receiver are found on top of the |
| 332 // frame. They are not dropped. | 340 // frame. They are not dropped. |
| 333 Result CallKeyedLoadIC(RelocInfo::Mode mode); | 341 Result CallKeyedLoadIC(RelocInfo::Mode mode); |
| 334 | 342 |
| 335 // Call store IC. Name, value, and receiver are found on top of the | 343 // Call store IC. Name, value, and receiver are found on top of the |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 350 // frame. Function is not dropped. The argument count does not | 358 // frame. Function is not dropped. The argument count does not |
| 351 // include the receiver. | 359 // include the receiver. |
| 352 Result CallConstructor(int arg_count); | 360 Result CallConstructor(int arg_count); |
| 353 | 361 |
| 354 // Drop a number of elements from the top of the expression stack. May | 362 // Drop a number of elements from the top of the expression stack. May |
| 355 // emit code to affect the physical frame. Does not clobber any registers | 363 // emit code to affect the physical frame. Does not clobber any registers |
| 356 // excepting possibly the stack pointer. | 364 // excepting possibly the stack pointer. |
| 357 void Drop(int count); | 365 void Drop(int count); |
| 358 | 366 |
| 359 // Drop one element. | 367 // Drop one element. |
| 360 void Drop() { Drop(1); } | 368 void Drop() { |
| 369 Drop(1); | |
| 370 } | |
| 361 | 371 |
| 362 // Duplicate the top element of the frame. | 372 // Duplicate the top element of the frame. |
| 363 void Dup() { PushFrameSlotAt(element_count() - 1); } | 373 void Dup() { |
| 374 PushFrameSlotAt(element_count() - 1); | |
| 375 } | |
| 364 | 376 |
| 365 // Pop an element from the top of the expression stack. Returns a | 377 // Pop an element from the top of the expression stack. Returns a |
| 366 // Result, which may be a constant or a register. | 378 // Result, which may be a constant or a register. |
| 367 Result Pop(); | 379 Result Pop(); |
| 368 | 380 |
| 369 // Pop and save an element from the top of the expression stack and | 381 // Pop and save an element from the top of the expression stack and |
| 370 // emit a corresponding pop instruction. | 382 // emit a corresponding pop instruction. |
| 371 void EmitPop(Register reg); | 383 void EmitPop(Register reg); |
| 372 void EmitPop(Operand operand); | 384 void EmitPop(Operand operand); |
| 373 | 385 |
| 374 // Push an element on top of the expression stack and emit a | 386 // Push an element on top of the expression stack and emit a |
| 375 // corresponding push instruction. | 387 // corresponding push instruction. |
| 376 void EmitPush(Register reg); | 388 void EmitPush(Register reg); |
| 377 void EmitPush(Operand operand); | 389 void EmitPush(Operand operand); |
| 378 void EmitPush(Immediate immediate); | 390 void EmitPush(Immediate immediate); |
| 379 | 391 |
| 380 // Push an element on the virtual frame. | 392 // Push an element on the virtual frame. |
| 381 void Push(Register reg, StaticType static_type = StaticType()); | 393 void Push(Register reg); |
| 382 void Push(Handle<Object> value); | 394 void Push(Handle<Object> value); |
| 383 void Push(Smi* value) { Push(Handle<Object>(value)); } | 395 void Push(Smi* value) { |
| 396 Push(Handle<Object> (value)); | |
| 397 } | |
| 384 | 398 |
| 385 // Pushing a result invalidates it (its contents become owned by the | 399 // Pushing a result invalidates it (its contents become owned by the |
| 386 // frame). | 400 // frame). |
| 387 void Push(Result* result) { | 401 void Push(Result* result) { |
| 388 if (result->is_register()) { | 402 if (result->is_register()) { |
| 389 Push(result->reg(), result->static_type()); | 403 Push(result->reg()); |
| 390 } else { | 404 } else { |
| 391 ASSERT(result->is_constant()); | 405 ASSERT(result->is_constant()); |
| 392 Push(result->handle()); | 406 Push(result->handle()); |
| 393 } | 407 } |
| 394 result->Unuse(); | 408 result->Unuse(); |
| 395 } | 409 } |
| 396 | 410 |
| 397 // Nip removes zero or more elements from immediately below the top | 411 // Nip removes zero or more elements from immediately below the top |
| 398 // of the frame, leaving the previous top-of-frame value on top of | 412 // of the frame, leaving the previous top-of-frame value on top of |
| 399 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). | 413 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 411 | 425 |
| 412 // The index of the element that is at the processor's stack pointer | 426 // The index of the element that is at the processor's stack pointer |
| 413 // (the esp register). | 427 // (the esp register). |
| 414 int stack_pointer_; | 428 int stack_pointer_; |
| 415 | 429 |
| 416 // The index of the register frame element using each register, or | 430 // The index of the register frame element using each register, or |
| 417 // kIllegalIndex if a register is not on the frame. | 431 // kIllegalIndex if a register is not on the frame. |
| 418 int register_locations_[RegisterAllocator::kNumRegisters]; | 432 int register_locations_[RegisterAllocator::kNumRegisters]; |
| 419 | 433 |
| 420 // The number of frame-allocated locals and parameters respectively. | 434 // The number of frame-allocated locals and parameters respectively. |
| 421 int parameter_count() { return cgen()->scope()->num_parameters(); } | 435 int parameter_count() { |
| 422 int local_count() { return cgen()->scope()->num_stack_slots(); } | 436 return cgen()->scope()->num_parameters(); |
| 437 } | |
| 438 int local_count() { | |
| 439 return cgen()->scope()->num_stack_slots(); | |
| 440 } | |
| 423 | 441 |
| 424 // The index of the element that is at the processor's frame pointer | 442 // The index of the element that is at the processor's frame pointer |
| 425 // (the ebp register). The parameters, receiver, and return address | 443 // (the ebp register). The parameters, receiver, and return address |
| 426 // are below the frame pointer. | 444 // are below the frame pointer. |
| 427 int frame_pointer() { return parameter_count() + 2; } | 445 int frame_pointer() { |
| 446 return parameter_count() + 2; | |
| 447 } | |
| 428 | 448 |
| 429 // The index of the first parameter. The receiver lies below the first | 449 // The index of the first parameter. The receiver lies below the first |
| 430 // parameter. | 450 // parameter. |
| 431 int param0_index() { return 1; } | 451 int param0_index() { |
| 452 return 1; | |
| 453 } | |
| 432 | 454 |
| 433 // The index of the context slot in the frame. It is immediately | 455 // The index of the context slot in the frame. It is immediately |
| 434 // above the frame pointer. | 456 // above the frame pointer. |
| 435 int context_index() { return frame_pointer() + 1; } | 457 int context_index() { |
| 458 return frame_pointer() + 1; | |
| 459 } | |
| 436 | 460 |
| 437 // The index of the function slot in the frame. It is above the frame | 461 // The index of the function slot in the frame. It is above the frame |
| 438 // pointer and the context slot. | 462 // pointer and the context slot. |
| 439 int function_index() { return frame_pointer() + 2; } | 463 int function_index() { |
| 464 return frame_pointer() + 2; | |
| 465 } | |
| 440 | 466 |
| 441 // The index of the first local. Between the frame pointer and the | 467 // The index of the first local. Between the frame pointer and the |
| 442 // locals lie the context and the function. | 468 // locals lie the context and the function. |
| 443 int local0_index() { return frame_pointer() + 3; } | 469 int local0_index() { |
| 470 return frame_pointer() + 3; | |
| 471 } | |
| 444 | 472 |
| 445 // The index of the base of the expression stack. | 473 // The index of the base of the expression stack. |
| 446 int expression_base_index() { return local0_index() + local_count(); } | 474 int expression_base_index() { |
| 475 return local0_index() + local_count(); | |
| 476 } | |
| 447 | 477 |
| 448 // Convert a frame index into a frame pointer relative offset into the | 478 // Convert a frame index into a frame pointer relative offset into the |
| 449 // actual stack. | 479 // actual stack. |
| 450 int fp_relative(int index) { | 480 int fp_relative(int index) { |
| 451 ASSERT(index < element_count()); | 481 ASSERT(index < element_count()); |
| 452 ASSERT(frame_pointer() < element_count()); // FP is on the frame. | 482 ASSERT(frame_pointer() < element_count()); // FP is on the frame. |
| 453 return (frame_pointer() - index) * kPointerSize; | 483 return (frame_pointer() - index) * kPointerSize; |
| 454 } | 484 } |
| 455 | 485 |
| 456 // Record an occurrence of a register in the virtual frame. This has the | 486 // Record an occurrence of a register in the virtual frame. This has the |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 // (via PrepareForCall). | 570 // (via PrepareForCall). |
| 541 Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); | 571 Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); |
| 542 | 572 |
| 543 bool Equals(VirtualFrame* other); | 573 bool Equals(VirtualFrame* other); |
| 544 | 574 |
| 545 // Classes that need raw access to the elements_ array. | 575 // Classes that need raw access to the elements_ array. |
| 546 friend class DeferredCode; | 576 friend class DeferredCode; |
| 547 friend class JumpTarget; | 577 friend class JumpTarget; |
| 548 }; | 578 }; |
| 549 | 579 |
| 550 | |
| 551 } } // namespace v8::internal | 580 } } // namespace v8::internal |
| 552 | 581 |
| 553 #endif // V8_IA32_VIRTUAL_FRAME_IA32_H_ | 582 #endif // V8_IA32_VIRTUAL_FRAME_IA32_H_ |
| OLD | NEW |