OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2516 // edi : the function to call | 2516 // edi : the function to call |
2517 Isolate* isolate = masm->isolate(); | 2517 Isolate* isolate = masm->isolate(); |
2518 Label slow, non_function; | 2518 Label slow, non_function; |
2519 | 2519 |
2520 // Check that the function really is a JavaScript function. | 2520 // Check that the function really is a JavaScript function. |
2521 __ JumpIfSmi(edi, &non_function); | 2521 __ JumpIfSmi(edi, &non_function); |
2522 | 2522 |
2523 // The receiver might implicitly be the global object. This is | 2523 // The receiver might implicitly be the global object. This is |
2524 // indicated by passing the hole as the receiver to the call | 2524 // indicated by passing the hole as the receiver to the call |
2525 // function stub. | 2525 // function stub. |
2526 Label call; | |
2527 if (ReceiverMightBeImplicit()) { | 2526 if (ReceiverMightBeImplicit()) { |
2528 Label try_call, patch_current_context; | 2527 Label try_call, patch_current_context; |
2529 if (ReceiverMightBeImplicit()) { | 2528 // Get the receiver from the stack. |
2530 // Get the receiver from the stack. | 2529 // +1 ~ return address |
2531 // +1 ~ return address | 2530 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); |
2532 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); | 2531 // Call as function is indicated with the hole. |
2533 // Call as function is indicated with the hole. | 2532 __ cmp(eax, isolate->factory()->the_hole_value()); |
2534 __ cmp(eax, isolate->factory()->the_hole_value()); | 2533 __ j(not_equal, &try_call, Label::kNear); |
2535 __ j(not_equal, &try_call, Label::kNear); | |
2536 } | |
2537 | 2534 |
2538 // Patch the global object on the stack. | 2535 // Patch the global object on the stack. |
2539 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), | 2536 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), |
2540 isolate->factory()->undefined_value()); | 2537 isolate->factory()->undefined_value()); |
2541 | 2538 |
2542 // Goto slow case if we do not have a function. | |
2543 __ bind(&try_call); | 2539 __ bind(&try_call); |
2544 } | 2540 } |
2545 | 2541 |
2546 // Goto slow case if we do not have a function. | 2542 // Goto slow case if we do not have a function. |
2547 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2543 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2548 __ j(not_equal, &slow); | 2544 __ j(not_equal, &slow); |
2549 | 2545 |
2550 __ bind(&call); | |
2551 | |
2552 if (RecordCallTarget()) { | 2546 if (RecordCallTarget()) { |
2553 GenerateRecordCallTarget(masm); | 2547 GenerateRecordCallTarget(masm); |
2554 } | 2548 } |
2555 | 2549 |
2556 // Fast-case: Just invoke the function. | 2550 // Fast-case: Just invoke the function. |
2557 ParameterCount actual(argc_); | 2551 ParameterCount actual(argc_); |
2558 | 2552 |
2559 if (ReceiverMightBeImplicit()) { | 2553 if (ReceiverMightBeImplicit()) { |
dcarney
2014/01/13 18:39:35
this block can be removed
| |
2560 Label call_as_function; | 2554 Label call_as_function; |
2561 __ cmp(eax, isolate->factory()->the_hole_value()); | 2555 __ cmp(eax, isolate->factory()->the_hole_value()); |
2562 __ j(equal, &call_as_function); | 2556 __ j(equal, &call_as_function); |
2563 __ InvokeFunction(edi, | 2557 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2564 actual, | |
2565 JUMP_FUNCTION, | |
2566 NullCallWrapper(), | |
2567 CALL_AS_METHOD); | |
2568 __ bind(&call_as_function); | 2558 __ bind(&call_as_function); |
2569 } | 2559 } |
2570 __ InvokeFunction(edi, | 2560 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2571 actual, | |
2572 JUMP_FUNCTION, | |
2573 NullCallWrapper(), | |
2574 CALL_AS_FUNCTION); | |
2575 | 2561 |
2576 // Slow-case: Non-function called. | 2562 // Slow-case: Non-function called. |
2577 __ bind(&slow); | 2563 __ bind(&slow); |
2578 if (RecordCallTarget()) { | 2564 if (RecordCallTarget()) { |
2579 // If there is a call target cache, mark it megamorphic in the | 2565 // If there is a call target cache, mark it megamorphic in the |
2580 // non-function case. MegamorphicSentinel is an immortal immovable | 2566 // non-function case. MegamorphicSentinel is an immortal immovable |
2581 // object (undefined) so no write barrier is needed. | 2567 // object (undefined) so no write barrier is needed. |
2582 __ mov(FieldOperand(ebx, Cell::kValueOffset), | 2568 __ mov(FieldOperand(ebx, Cell::kValueOffset), |
2583 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); | 2569 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
2584 } | 2570 } |
2585 // Check for function proxy. | 2571 // Check for function proxy. |
2586 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); | 2572 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
2587 __ j(not_equal, &non_function); | 2573 __ j(not_equal, &non_function); |
2588 __ pop(ecx); | 2574 __ pop(ecx); |
2589 __ push(edi); // put proxy as additional argument under return address | 2575 __ push(edi); // put proxy as additional argument under return address |
2590 __ push(ecx); | 2576 __ push(ecx); |
2591 __ Set(eax, Immediate(argc_ + 1)); | 2577 __ Set(eax, Immediate(argc_ + 1)); |
2592 __ Set(ebx, Immediate(0)); | 2578 __ Set(ebx, Immediate(0)); |
2593 __ SetCallKind(ecx, CALL_AS_FUNCTION); | |
2594 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 2579 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
2595 { | 2580 { |
2596 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); | 2581 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); |
2597 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 2582 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
2598 } | 2583 } |
2599 | 2584 |
2600 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 2585 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
2601 // of the original receiver from the call site). | 2586 // of the original receiver from the call site). |
2602 __ bind(&non_function); | 2587 __ bind(&non_function); |
2603 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); | 2588 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); |
2604 __ Set(eax, Immediate(argc_)); | 2589 __ Set(eax, Immediate(argc_)); |
2605 __ Set(ebx, Immediate(0)); | 2590 __ Set(ebx, Immediate(0)); |
2606 __ SetCallKind(ecx, CALL_AS_FUNCTION); | |
2607 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 2591 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
2608 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); | 2592 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); |
2609 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 2593 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
2610 } | 2594 } |
2611 | 2595 |
2612 | 2596 |
2613 void CallConstructStub::Generate(MacroAssembler* masm) { | 2597 void CallConstructStub::Generate(MacroAssembler* masm) { |
2614 // eax : number of arguments | 2598 // eax : number of arguments |
2615 // ebx : cache cell for call target | 2599 // ebx : cache cell for call target |
2616 // edi : constructor function | 2600 // edi : constructor function |
(...skipping 27 matching lines...) Expand all Loading... | |
2644 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 2628 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
2645 __ jmp(&do_call); | 2629 __ jmp(&do_call); |
2646 | 2630 |
2647 __ bind(&non_function_call); | 2631 __ bind(&non_function_call); |
2648 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 2632 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
2649 __ bind(&do_call); | 2633 __ bind(&do_call); |
2650 // Set expected number of arguments to zero (not changing eax). | 2634 // Set expected number of arguments to zero (not changing eax). |
2651 __ Set(ebx, Immediate(0)); | 2635 __ Set(ebx, Immediate(0)); |
2652 Handle<Code> arguments_adaptor = | 2636 Handle<Code> arguments_adaptor = |
2653 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 2637 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
2654 __ SetCallKind(ecx, CALL_AS_METHOD); | |
2655 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET); | 2638 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET); |
2656 } | 2639 } |
2657 | 2640 |
2658 | 2641 |
2659 bool CEntryStub::NeedsImmovableCode() { | 2642 bool CEntryStub::NeedsImmovableCode() { |
2660 return false; | 2643 return false; |
2661 } | 2644 } |
2662 | 2645 |
2663 | 2646 |
2664 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 2647 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
(...skipping 2678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5343 __ mov(edi, eax); | 5326 __ mov(edi, eax); |
5344 int parameter_count_offset = | 5327 int parameter_count_offset = |
5345 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 5328 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
5346 __ mov(eax, MemOperand(ebp, parameter_count_offset)); | 5329 __ mov(eax, MemOperand(ebp, parameter_count_offset)); |
5347 // The parameter count above includes the receiver for the arguments passed to | 5330 // The parameter count above includes the receiver for the arguments passed to |
5348 // the deoptimization handler. Subtract the receiver for the parameter count | 5331 // the deoptimization handler. Subtract the receiver for the parameter count |
5349 // for the call. | 5332 // for the call. |
5350 __ sub(eax, Immediate(1)); | 5333 __ sub(eax, Immediate(1)); |
5351 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 5334 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
5352 ParameterCount argument_count(eax); | 5335 ParameterCount argument_count(eax); |
5353 __ InvokeFunction( | 5336 __ InvokeFunction(edi, argument_count, JUMP_FUNCTION, NullCallWrapper()); |
5354 edi, argument_count, JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
5355 } | 5337 } |
5356 | 5338 |
5357 | 5339 |
5358 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 5340 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
5359 if (masm->isolate()->function_entry_hook() != NULL) { | 5341 if (masm->isolate()->function_entry_hook() != NULL) { |
5360 ProfileEntryHookStub stub; | 5342 ProfileEntryHookStub stub; |
5361 masm->CallStub(&stub); | 5343 masm->CallStub(&stub); |
5362 } | 5344 } |
5363 } | 5345 } |
5364 | 5346 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5713 __ bind(&fast_elements_case); | 5695 __ bind(&fast_elements_case); |
5714 GenerateCase(masm, FAST_ELEMENTS); | 5696 GenerateCase(masm, FAST_ELEMENTS); |
5715 } | 5697 } |
5716 | 5698 |
5717 | 5699 |
5718 #undef __ | 5700 #undef __ |
5719 | 5701 |
5720 } } // namespace v8::internal | 5702 } } // namespace v8::internal |
5721 | 5703 |
5722 #endif // V8_TARGET_ARCH_IA32 | 5704 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |