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 |