| OLD | NEW | 
|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 564 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 575   // 2. Get the function to call (passed as receiver) from the stack, check | 575   // 2. Get the function to call (passed as receiver) from the stack, check | 
| 576   //    if it is a function. | 576   //    if it is a function. | 
| 577   Label non_function; | 577   Label non_function; | 
| 578   // 1 ~ return address. | 578   // 1 ~ return address. | 
| 579   __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 579   __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 
| 580   __ test(edi, Immediate(kSmiTagMask)); | 580   __ test(edi, Immediate(kSmiTagMask)); | 
| 581   __ j(zero, &non_function, not_taken); | 581   __ j(zero, &non_function, not_taken); | 
| 582   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 582   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 
| 583   __ j(not_equal, &non_function, not_taken); | 583   __ j(not_equal, &non_function, not_taken); | 
| 584 | 584 | 
|  | 585   // Change context eagerly in case we need the global receiver. | 
|  | 586   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 
| 585 | 587 | 
| 586   // 3a. Patch the first argument if necessary when calling a function. |  | 
| 587   Label shift_arguments; | 588   Label shift_arguments; | 
| 588   { Label convert_to_object, use_global_receiver, patch_receiver; | 589   __ jmp(&shift_arguments); | 
| 589     // Change context eagerly in case we need the global receiver. |  | 
| 590     __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |  | 
| 591 | 590 | 
| 592     __ mov(ebx, Operand(esp, eax, times_4, 0));  // First argument. | 591   // 3. Patch the first argument when calling a non-function.  The | 
| 593     __ test(ebx, Immediate(kSmiTagMask)); | 592   //    CALL_NON_FUNCTION builtin expects the non-function callee as | 
| 594     __ j(zero, &convert_to_object); | 593   //    receiver, so overwrite the first argument which will ultimately | 
| 595 | 594   //    become the receiver. | 
| 596     __ cmp(ebx, Factory::null_value()); |  | 
| 597     __ j(equal, &use_global_receiver); |  | 
| 598     __ cmp(ebx, Factory::undefined_value()); |  | 
| 599     __ j(equal, &use_global_receiver); |  | 
| 600 |  | 
| 601     // We don't use IsObjectJSObjectType here because we jump on success. |  | 
| 602     __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); |  | 
| 603     __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |  | 
| 604     __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE)); |  | 
| 605     __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); |  | 
| 606     __ j(below_equal, &shift_arguments); |  | 
| 607 |  | 
| 608     __ bind(&convert_to_object); |  | 
| 609     __ EnterInternalFrame();  // In order to preserve argument count. |  | 
| 610     __ SmiTag(eax); |  | 
| 611     __ push(eax); |  | 
| 612 |  | 
| 613     __ push(ebx); |  | 
| 614     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |  | 
| 615     __ mov(ebx, eax); |  | 
| 616 |  | 
| 617     __ pop(eax); |  | 
| 618     __ SmiUntag(eax); |  | 
| 619     __ LeaveInternalFrame(); |  | 
| 620     // Restore the function to edi. |  | 
| 621     __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |  | 
| 622     __ jmp(&patch_receiver); |  | 
| 623 |  | 
| 624     // Use the global receiver object from the called function as the |  | 
| 625     // receiver. |  | 
| 626     __ bind(&use_global_receiver); |  | 
| 627     const int kGlobalIndex = |  | 
| 628         Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |  | 
| 629     __ mov(ebx, FieldOperand(esi, kGlobalIndex)); |  | 
| 630     __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset)); |  | 
| 631     __ mov(ebx, FieldOperand(ebx, kGlobalIndex)); |  | 
| 632     __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |  | 
| 633 |  | 
| 634     __ bind(&patch_receiver); |  | 
| 635     __ mov(Operand(esp, eax, times_4, 0), ebx); |  | 
| 636 |  | 
| 637     __ jmp(&shift_arguments); |  | 
| 638   } |  | 
| 639 |  | 
| 640   // 3b. Patch the first argument when calling a non-function.  The |  | 
| 641   //     CALL_NON_FUNCTION builtin expects the non-function callee as |  | 
| 642   //     receiver, so overwrite the first argument which will ultimately |  | 
| 643   //     become the receiver. |  | 
| 644   __ bind(&non_function); | 595   __ bind(&non_function); | 
| 645   __ mov(Operand(esp, eax, times_4, 0), edi); | 596   __ mov(Operand(esp, eax, times_4, 0), edi); | 
| 646   // Clear edi to indicate a non-function being called. | 597   // Clear edi to indicate a non-function being called. | 
| 647   __ Set(edi, Immediate(0)); | 598   __ Set(edi, Immediate(0)); | 
| 648 | 599 | 
| 649   // 4. Shift arguments and return address one slot down on the stack | 600   // 4. Shift arguments and return address one slot down on the stack | 
| 650   //    (overwriting the original receiver).  Adjust argument count to make | 601   //    (overwriting the original receiver).  Adjust argument count to make | 
| 651   //    the original first argument the new receiver. | 602   //    the original first argument the new receiver. | 
| 652   __ bind(&shift_arguments); | 603   __ bind(&shift_arguments); | 
| 653   { Label loop; | 604   { Label loop; | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 726       StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 677       StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 
| 727   const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 678   const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 
| 728   __ push(eax);  // limit | 679   __ push(eax);  // limit | 
| 729   __ push(Immediate(0));  // index | 680   __ push(Immediate(0));  // index | 
| 730 | 681 | 
| 731   // Change context eagerly to get the right global object if | 682   // Change context eagerly to get the right global object if | 
| 732   // necessary. | 683   // necessary. | 
| 733   __ mov(edi, Operand(ebp, 4 * kPointerSize)); | 684   __ mov(edi, Operand(ebp, 4 * kPointerSize)); | 
| 734   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 685   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 
| 735 | 686 | 
| 736   // Compute the receiver. | 687   // Push the receiver. | 
| 737   Label call_to_object, use_global_receiver, push_receiver; |  | 
| 738   __ mov(ebx, Operand(ebp, 3 * kPointerSize)); | 688   __ mov(ebx, Operand(ebp, 3 * kPointerSize)); | 
| 739   __ test(ebx, Immediate(kSmiTagMask)); |  | 
| 740   __ j(zero, &call_to_object); |  | 
| 741   __ cmp(ebx, Factory::null_value()); |  | 
| 742   __ j(equal, &use_global_receiver); |  | 
| 743   __ cmp(ebx, Factory::undefined_value()); |  | 
| 744   __ j(equal, &use_global_receiver); |  | 
| 745 |  | 
| 746   // If given receiver is already a JavaScript object then there's no |  | 
| 747   // reason for converting it. |  | 
| 748   // We don't use IsObjectJSObjectType here because we jump on success. |  | 
| 749   __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); |  | 
| 750   __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |  | 
| 751   __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE)); |  | 
| 752   __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); |  | 
| 753   __ j(below_equal, &push_receiver); |  | 
| 754 |  | 
| 755   // Convert the receiver to an object. |  | 
| 756   __ bind(&call_to_object); |  | 
| 757   __ push(ebx); |  | 
| 758   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |  | 
| 759   __ mov(ebx, Operand(eax)); |  | 
| 760   __ jmp(&push_receiver); |  | 
| 761 |  | 
| 762   // Use the current global receiver object as the receiver. |  | 
| 763   __ bind(&use_global_receiver); |  | 
| 764   const int kGlobalOffset = |  | 
| 765       Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |  | 
| 766   __ mov(ebx, FieldOperand(esi, kGlobalOffset)); |  | 
| 767   __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset)); |  | 
| 768   __ mov(ebx, FieldOperand(ebx, kGlobalOffset)); |  | 
| 769   __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |  | 
| 770 |  | 
| 771   // Push the receiver. |  | 
| 772   __ bind(&push_receiver); |  | 
| 773   __ push(ebx); | 689   __ push(ebx); | 
| 774 | 690 | 
| 775   // Copy all arguments from the array to the stack. | 691   // Copy all arguments from the array to the stack. | 
| 776   Label entry, loop; | 692   Label entry, loop; | 
| 777   __ mov(eax, Operand(ebp, kIndexOffset)); | 693   __ mov(eax, Operand(ebp, kIndexOffset)); | 
| 778   __ jmp(&entry); | 694   __ jmp(&entry); | 
| 779   __ bind(&loop); | 695   __ bind(&loop); | 
| 780   __ mov(edx, Operand(ebp, 2 * kPointerSize));  // load arguments | 696   __ mov(edx, Operand(ebp, 2 * kPointerSize));  // load arguments | 
| 781 | 697 | 
| 782   // Use inline caching to speed up access to arguments. | 698   // Use inline caching to speed up access to arguments. | 
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1566   Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1482   Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 
| 1567   generator.Generate(); | 1483   generator.Generate(); | 
| 1568 } | 1484 } | 
| 1569 | 1485 | 
| 1570 | 1486 | 
| 1571 #undef __ | 1487 #undef __ | 
| 1572 | 1488 | 
| 1573 } }  // namespace v8::internal | 1489 } }  // namespace v8::internal | 
| 1574 | 1490 | 
| 1575 #endif  // V8_TARGET_ARCH_IA32 | 1491 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW | 
|---|