OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 __ mov(Operand::StaticVariable(ExternalReference::builtin_passed_function()), | 47 __ mov(Operand::StaticVariable(ExternalReference::builtin_passed_function()), |
48 edi); | 48 edi); |
49 __ JumpToBuiltin(ExternalReference(id)); | 49 __ JumpToBuiltin(ExternalReference(id)); |
50 } | 50 } |
51 | 51 |
52 | 52 |
53 DEFINE_bool(inline_new, true, "use fast inline allocation"); | 53 DEFINE_bool(inline_new, true, "use fast inline allocation"); |
54 | 54 |
55 | 55 |
56 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { | 56 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
| 57 // ----------- S t a t e ------------- |
| 58 // -- eax: number of arguments |
| 59 // -- edi: constructor function |
| 60 // ----------------------------------- |
| 61 |
57 // Enter an internal frame. | 62 // Enter an internal frame. |
58 __ EnterFrame(StackFrame::INTERNAL); | 63 __ EnterInternalFrame(); |
59 | 64 |
60 // Store a smi-tagged arguments count on the stack. | 65 // Store a smi-tagged arguments count on the stack. |
61 __ shl(eax, kSmiTagSize); | 66 __ shl(eax, kSmiTagSize); |
62 __ push(eax); | 67 __ push(eax); |
63 | 68 |
64 // Push the function to invoke on the stack. | 69 // Push the function to invoke on the stack. |
65 __ push(edi); | 70 __ push(edi); |
66 | 71 |
67 // Try to allocate the object without transitioning into C code. If any of the | 72 // Try to allocate the object without transitioning into C code. If any of the |
68 // preconditions is not met, the code bails out to the runtime call. | 73 // preconditions is not met, the code bails out to the runtime call. |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 __ j(greater_equal, &exit, not_taken); | 294 __ j(greater_equal, &exit, not_taken); |
290 | 295 |
291 // Throw away the result of the constructor invocation and use the | 296 // Throw away the result of the constructor invocation and use the |
292 // on-stack receiver as the result. | 297 // on-stack receiver as the result. |
293 __ bind(&use_receiver); | 298 __ bind(&use_receiver); |
294 __ mov(eax, Operand(esp, 0)); | 299 __ mov(eax, Operand(esp, 0)); |
295 | 300 |
296 // Restore the arguments count and exit the internal frame. | 301 // Restore the arguments count and exit the internal frame. |
297 __ bind(&exit); | 302 __ bind(&exit); |
298 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count | 303 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count |
299 __ ExitFrame(StackFrame::INTERNAL); | 304 __ ExitInternalFrame(); |
300 | 305 |
301 // Remove caller arguments from the stack and return. | 306 // Remove caller arguments from the stack and return. |
302 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 307 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
303 __ pop(ecx); | 308 __ pop(ecx); |
304 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 309 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
305 __ push(ecx); | 310 __ push(ecx); |
306 __ ret(0); | 311 __ ret(0); |
307 | 312 |
308 // Compute the offset from the beginning of the JSConstructCall | 313 // Compute the offset from the beginning of the JSConstructCall |
309 // builtin code object to the return address after the call. | 314 // builtin code object to the return address after the call. |
310 ASSERT(return_site.is_bound()); | 315 ASSERT(return_site.is_bound()); |
311 construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize; | 316 construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize; |
312 } | 317 } |
313 | 318 |
314 | 319 |
315 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 320 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
316 bool is_construct) { | 321 bool is_construct) { |
317 // Clear the context before we push it when entering the JS frame. | 322 // Clear the context before we push it when entering the JS frame. |
318 __ xor_(esi, Operand(esi)); // clear esi | 323 __ xor_(esi, Operand(esi)); // clear esi |
319 | 324 |
320 // Enter an internal frame. | 325 // Enter an internal frame. |
321 __ EnterFrame(StackFrame::INTERNAL); | 326 __ EnterInternalFrame(); |
322 | 327 |
323 // Load the previous frame pointer (ebx) to access C arguments | 328 // Load the previous frame pointer (ebx) to access C arguments |
324 __ mov(ebx, Operand(ebp, 0)); | 329 __ mov(ebx, Operand(ebp, 0)); |
325 | 330 |
326 // Get the function from the frame and setup the context. | 331 // Get the function from the frame and setup the context. |
327 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); | 332 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); |
328 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); | 333 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); |
329 | 334 |
330 // Push the function and the receiver onto the stack. | 335 // Push the function and the receiver onto the stack. |
331 __ push(ecx); | 336 __ push(ecx); |
(...skipping 23 matching lines...) Expand all Loading... |
355 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 360 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), |
356 code_target); | 361 code_target); |
357 } else { | 362 } else { |
358 ParameterCount actual(eax); | 363 ParameterCount actual(eax); |
359 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 364 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
360 } | 365 } |
361 | 366 |
362 // Exit the JS frame. Notice that this also removes the empty | 367 // Exit the JS frame. Notice that this also removes the empty |
363 // context and the function left on the stack by the code | 368 // context and the function left on the stack by the code |
364 // invocation. | 369 // invocation. |
365 __ ExitFrame(StackFrame::INTERNAL); | 370 __ ExitInternalFrame(); |
366 __ ret(1 * kPointerSize); // remove receiver | 371 __ ret(1 * kPointerSize); // remove receiver |
367 } | 372 } |
368 | 373 |
369 | 374 |
370 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 375 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
371 Generate_JSEntryTrampolineHelper(masm, false); | 376 Generate_JSEntryTrampolineHelper(masm, false); |
372 } | 377 } |
373 | 378 |
374 | 379 |
375 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 380 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
376 Generate_JSEntryTrampolineHelper(masm, true); | 381 Generate_JSEntryTrampolineHelper(masm, true); |
377 } | 382 } |
378 | 383 |
379 | 384 |
380 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 385 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
381 __ EnterFrame(StackFrame::INTERNAL); | 386 __ EnterInternalFrame(); |
382 | 387 |
383 __ push(Operand(ebp, 4 * kPointerSize)); // push this | 388 __ push(Operand(ebp, 4 * kPointerSize)); // push this |
384 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments | 389 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments |
385 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 390 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
386 | 391 |
387 // Eagerly check for stack-overflow before pushing all the arguments | 392 // Eagerly check for stack-overflow before pushing all the arguments |
388 // to the stack. | 393 // to the stack. |
389 Label okay; | 394 Label okay; |
390 __ lea(ecx, Operand(esp, -3 * kPointerSize)); // receiver, limit, index | 395 __ lea(ecx, Operand(esp, -3 * kPointerSize)); // receiver, limit, index |
391 __ mov(edx, Operand(eax)); | 396 __ mov(edx, Operand(eax)); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 __ bind(&entry); | 480 __ bind(&entry); |
476 __ cmp(eax, Operand(ebp, kLimitOffset)); | 481 __ cmp(eax, Operand(ebp, kLimitOffset)); |
477 __ j(not_equal, &loop); | 482 __ j(not_equal, &loop); |
478 | 483 |
479 // Invoke the function. | 484 // Invoke the function. |
480 ParameterCount actual(eax); | 485 ParameterCount actual(eax); |
481 __ shr(eax, kSmiTagSize); | 486 __ shr(eax, kSmiTagSize); |
482 __ mov(edi, Operand(ebp, 4 * kPointerSize)); | 487 __ mov(edi, Operand(ebp, 4 * kPointerSize)); |
483 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 488 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
484 | 489 |
485 __ ExitFrame(StackFrame::INTERNAL); | 490 __ ExitInternalFrame(); |
486 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 491 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
487 } | 492 } |
488 | 493 |
489 | 494 |
490 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 495 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
491 __ push(ebp); | 496 __ push(ebp); |
492 __ mov(ebp, Operand(esp)); | 497 __ mov(ebp, Operand(esp)); |
493 | 498 |
494 // Store the arguments adaptor context sentinel. | 499 // Store the arguments adaptor context sentinel. |
495 __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL)); | 500 __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL)); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 __ bind(&fill); | 584 __ bind(&fill); |
580 __ inc(ecx); | 585 __ inc(ecx); |
581 __ push(Immediate(Factory::undefined_value())); | 586 __ push(Immediate(Factory::undefined_value())); |
582 __ cmp(ecx, Operand(ebx)); | 587 __ cmp(ecx, Operand(ebx)); |
583 __ j(less, &fill); | 588 __ j(less, &fill); |
584 | 589 |
585 // Restore function pointer. | 590 // Restore function pointer. |
586 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 591 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
587 } | 592 } |
588 | 593 |
589 // Mark the adaptor frame as special by overwriting the context slot | 594 // Call the entry point. |
590 // in the stack with a sentinel. | |
591 Label return_site; | 595 Label return_site; |
592 __ bind(&invoke); | 596 __ bind(&invoke); |
593 __ call(Operand(edx)); | 597 __ call(Operand(edx)); |
594 __ bind(&return_site); | 598 __ bind(&return_site); |
595 | 599 |
596 ExitArgumentsAdaptorFrame(masm); | 600 ExitArgumentsAdaptorFrame(masm); |
597 __ ret(0); | 601 __ ret(0); |
598 | 602 |
599 // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline | 603 // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline |
600 // builtin code object to the return address after the call. | 604 // builtin code object to the return address after the call. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 __ j(equal, &use_global_receiver); | 658 __ j(equal, &use_global_receiver); |
655 | 659 |
656 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); | 660 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); |
657 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 661 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
658 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 662 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
659 __ j(less, &call_to_object); | 663 __ j(less, &call_to_object); |
660 __ cmp(ecx, LAST_JS_OBJECT_TYPE); | 664 __ cmp(ecx, LAST_JS_OBJECT_TYPE); |
661 __ j(less_equal, &done); | 665 __ j(less_equal, &done); |
662 | 666 |
663 __ bind(&call_to_object); | 667 __ bind(&call_to_object); |
664 __ EnterFrame(StackFrame::INTERNAL); // preserves eax, ebx, edi | 668 __ EnterInternalFrame(); // preserves eax, ebx, edi |
665 | 669 |
666 // Store the arguments count on the stack (smi tagged). | 670 // Store the arguments count on the stack (smi tagged). |
667 ASSERT(kSmiTag == 0); | 671 ASSERT(kSmiTag == 0); |
668 __ shl(eax, kSmiTagSize); | 672 __ shl(eax, kSmiTagSize); |
669 __ push(eax); | 673 __ push(eax); |
670 | 674 |
671 __ push(edi); // save edi across the call | 675 __ push(edi); // save edi across the call |
672 __ push(ebx); | 676 __ push(ebx); |
673 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 677 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
674 __ mov(Operand(ebx), eax); | 678 __ mov(Operand(ebx), eax); |
675 __ pop(edi); // restore edi after the call | 679 __ pop(edi); // restore edi after the call |
676 | 680 |
677 // Get the arguments count and untag it. | 681 // Get the arguments count and untag it. |
678 __ pop(eax); | 682 __ pop(eax); |
679 __ shr(eax, kSmiTagSize); | 683 __ shr(eax, kSmiTagSize); |
680 | 684 |
681 __ ExitFrame(StackFrame::INTERNAL); | 685 __ ExitInternalFrame(); |
682 __ jmp(&patch_receiver); | 686 __ jmp(&patch_receiver); |
683 | 687 |
684 // Use the global object from the called function as the receiver. | 688 // Use the global object from the called function as the receiver. |
685 __ bind(&use_global_receiver); | 689 __ bind(&use_global_receiver); |
686 const int kGlobalIndex = | 690 const int kGlobalIndex = |
687 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 691 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
688 __ mov(ebx, FieldOperand(esi, kGlobalIndex)); | 692 __ mov(ebx, FieldOperand(esi, kGlobalIndex)); |
689 | 693 |
690 __ bind(&patch_receiver); | 694 __ bind(&patch_receiver); |
691 __ mov(Operand(esp, eax, times_4, 0), ebx); | 695 __ mov(Operand(esp, eax, times_4, 0), ebx); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 bool convert_call_to_jmp) { | 744 bool convert_call_to_jmp) { |
741 // Save the content of all general purpose registers in memory. This copy in | 745 // Save the content of all general purpose registers in memory. This copy in |
742 // memory is later pushed onto the JS expression stack for the fake JS frame | 746 // memory is later pushed onto the JS expression stack for the fake JS frame |
743 // generated and also to the C frame generated on top of that. In the JS | 747 // generated and also to the C frame generated on top of that. In the JS |
744 // frame ONLY the registers containing pointers will be pushed on the | 748 // frame ONLY the registers containing pointers will be pushed on the |
745 // expression stack. This causes the GC to update these pointers so that | 749 // expression stack. This causes the GC to update these pointers so that |
746 // they will have the correct value when returning from the debugger. | 750 // they will have the correct value when returning from the debugger. |
747 __ SaveRegistersToMemory(kJSCallerSaved); | 751 __ SaveRegistersToMemory(kJSCallerSaved); |
748 | 752 |
749 // Enter an internal frame. | 753 // Enter an internal frame. |
750 __ EnterFrame(StackFrame::INTERNAL); | 754 __ EnterInternalFrame(); |
751 | 755 |
752 // Store the registers containing object pointers on the expression stack to | 756 // Store the registers containing object pointers on the expression stack to |
753 // make sure that these are correctly updated during GC. | 757 // make sure that these are correctly updated during GC. |
754 __ PushRegistersFromMemory(pointer_regs); | 758 __ PushRegistersFromMemory(pointer_regs); |
755 | 759 |
756 #ifdef DEBUG | 760 #ifdef DEBUG |
757 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 761 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
758 #endif | 762 #endif |
759 __ Set(eax, Immediate(0)); // no arguments | 763 __ Set(eax, Immediate(0)); // no arguments |
760 __ mov(Operand(ebx), Immediate(ExternalReference::debug_break())); | 764 __ mov(Operand(ebx), Immediate(ExternalReference::debug_break())); |
761 | 765 |
762 CEntryDebugBreakStub ceb; | 766 CEntryDebugBreakStub ceb; |
763 __ CallStub(&ceb); | 767 __ CallStub(&ceb); |
764 | 768 |
765 // Restore the register values containing object pointers from the expression | 769 // Restore the register values containing object pointers from the expression |
766 // stack in the reverse order as they where pushed. | 770 // stack in the reverse order as they where pushed. |
767 __ PopRegistersToMemory(pointer_regs); | 771 __ PopRegistersToMemory(pointer_regs); |
768 | 772 |
769 // Get rid of the internal frame. | 773 // Get rid of the internal frame. |
770 __ ExitFrame(StackFrame::INTERNAL); | 774 __ ExitInternalFrame(); |
771 | 775 |
772 // If this call did not replace a call but patched other code then there will | 776 // If this call did not replace a call but patched other code then there will |
773 // be an unwanted return address left on the stack. Here we get rid of that. | 777 // be an unwanted return address left on the stack. Here we get rid of that. |
774 if (convert_call_to_jmp) { | 778 if (convert_call_to_jmp) { |
775 __ pop(eax); | 779 __ pop(eax); |
776 } | 780 } |
777 | 781 |
778 // Finally restore all registers. | 782 // Finally restore all registers. |
779 __ RestoreRegistersFromMemory(kJSCallerSaved); | 783 __ RestoreRegistersFromMemory(kJSCallerSaved); |
780 | 784 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc). | 876 // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc). |
873 // ----------- S t a t e ------------- | 877 // ----------- S t a t e ------------- |
874 // No registers used on entry. | 878 // No registers used on entry. |
875 // ----------------------------------- | 879 // ----------------------------------- |
876 Generate_DebugBreakCallHelper(masm, 0, false); | 880 Generate_DebugBreakCallHelper(masm, 0, false); |
877 } | 881 } |
878 | 882 |
879 #undef __ | 883 #undef __ |
880 | 884 |
881 } } // namespace v8::internal | 885 } } // namespace v8::internal |
OLD | NEW |