| 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 | 
|---|