| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 2529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 // (9) Sliced string. Replace subject with parent. Go to (4). | 2540 // (9) Sliced string. Replace subject with parent. Go to (4). |
| 2541 // Load offset into r11 and replace subject string with parent. | 2541 // Load offset into r11 and replace subject string with parent. |
| 2542 __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | 2542 __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 2543 __ SmiUntag(r11); | 2543 __ SmiUntag(r11); |
| 2544 __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 2544 __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 2545 __ b(&check_underlying); // Go to (4). | 2545 __ b(&check_underlying); // Go to (4). |
| 2546 #endif // V8_INTERPRETED_REGEXP | 2546 #endif // V8_INTERPRETED_REGEXP |
| 2547 } | 2547 } |
| 2548 | 2548 |
| 2549 | 2549 |
| 2550 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 2550 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, |
| 2551 bool is_super) { |
| 2551 // r3 : number of arguments to the construct function | 2552 // r3 : number of arguments to the construct function |
| 2552 // r5 : Feedback vector | 2553 // r4 : the function to call |
| 2554 // r5 : feedback vector |
| 2553 // r6 : slot in feedback vector (Smi) | 2555 // r6 : slot in feedback vector (Smi) |
| 2554 // r4 : the function to call | 2556 // r7 : original constructor (for IsSuperConstructorCall) |
| 2555 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2557 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 2556 | 2558 |
| 2557 // Number-of-arguments register must be smi-tagged to call out. | 2559 // Number-of-arguments register must be smi-tagged to call out. |
| 2558 __ SmiTag(r3); | 2560 __ SmiTag(r3); |
| 2559 __ Push(r6, r5, r4, r3); | 2561 if (is_super) { |
| 2562 __ Push(r6, r5, r4, r3, r7); |
| 2563 } else { |
| 2564 __ Push(r6, r5, r4, r3); |
| 2565 } |
| 2560 | 2566 |
| 2561 __ CallStub(stub); | 2567 __ CallStub(stub); |
| 2562 | 2568 |
| 2563 __ Pop(r6, r5, r4, r3); | 2569 if (is_super) { |
| 2570 __ Pop(r6, r5, r4, r3, r7); |
| 2571 } else { |
| 2572 __ Pop(r6, r5, r4, r3); |
| 2573 } |
| 2564 __ SmiUntag(r3); | 2574 __ SmiUntag(r3); |
| 2565 } | 2575 } |
| 2566 | 2576 |
| 2567 | 2577 |
| 2568 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 2578 static void GenerateRecordCallTarget(MacroAssembler* masm, bool is_super) { |
| 2569 // Cache the called function in a feedback vector slot. Cache states | 2579 // Cache the called function in a feedback vector slot. Cache states |
| 2570 // are uninitialized, monomorphic (indicated by a JSFunction), and | 2580 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 2571 // megamorphic. | 2581 // megamorphic. |
| 2572 // r3 : number of arguments to the construct function | 2582 // r3 : number of arguments to the construct function |
| 2573 // r4 : the function to call | 2583 // r4 : the function to call |
| 2574 // r5 : Feedback vector | 2584 // r5 : feedback vector |
| 2575 // r6 : slot in feedback vector (Smi) | 2585 // r6 : slot in feedback vector (Smi) |
| 2586 // r7 : original constructor (for IsSuperConstructorCall) |
| 2576 Label initialize, done, miss, megamorphic, not_array_function; | 2587 Label initialize, done, miss, megamorphic, not_array_function; |
| 2577 | 2588 |
| 2578 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), | 2589 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), |
| 2579 masm->isolate()->heap()->megamorphic_symbol()); | 2590 masm->isolate()->heap()->megamorphic_symbol()); |
| 2580 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), | 2591 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), |
| 2581 masm->isolate()->heap()->uninitialized_symbol()); | 2592 masm->isolate()->heap()->uninitialized_symbol()); |
| 2582 | 2593 |
| 2583 // Load the cache state into r7. | 2594 // Load the cache state into r8. |
| 2584 __ SmiToPtrArrayOffset(r7, r6); | 2595 __ SmiToPtrArrayOffset(r8, r6); |
| 2585 __ add(r7, r5, r7); | 2596 __ add(r8, r5, r8); |
| 2586 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize)); | 2597 __ LoadP(r8, FieldMemOperand(r8, FixedArray::kHeaderSize)); |
| 2587 | 2598 |
| 2588 // A monomorphic cache hit or an already megamorphic state: invoke the | 2599 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 2589 // function without changing the state. | 2600 // function without changing the state. |
| 2590 // We don't know if r7 is a WeakCell or a Symbol, but it's harmless to read at | 2601 // We don't know if r8 is a WeakCell or a Symbol, but it's harmless to read at |
| 2591 // this position in a symbol (see static asserts in type-feedback-vector.h). | 2602 // this position in a symbol (see static asserts in type-feedback-vector.h). |
| 2592 Label check_allocation_site; | 2603 Label check_allocation_site; |
| 2593 Register feedback_map = r8; | 2604 Register feedback_map = r9; |
| 2594 Register weak_value = r9; | 2605 Register weak_value = r10; |
| 2595 __ LoadP(weak_value, FieldMemOperand(r7, WeakCell::kValueOffset)); | 2606 __ LoadP(weak_value, FieldMemOperand(r8, WeakCell::kValueOffset)); |
| 2596 __ cmp(r4, weak_value); | 2607 __ cmp(r4, weak_value); |
| 2597 __ beq(&done); | 2608 __ beq(&done); |
| 2598 __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex); | 2609 __ CompareRoot(r8, Heap::kmegamorphic_symbolRootIndex); |
| 2599 __ beq(&done); | 2610 __ beq(&done); |
| 2600 __ LoadP(feedback_map, FieldMemOperand(r7, HeapObject::kMapOffset)); | 2611 __ LoadP(feedback_map, FieldMemOperand(r8, HeapObject::kMapOffset)); |
| 2601 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); | 2612 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); |
| 2602 __ bne(FLAG_pretenuring_call_new ? &miss : &check_allocation_site); | 2613 __ bne(FLAG_pretenuring_call_new ? &miss : &check_allocation_site); |
| 2603 | 2614 |
| 2604 // If the weak cell is cleared, we have a new chance to become monomorphic. | 2615 // If the weak cell is cleared, we have a new chance to become monomorphic. |
| 2605 __ JumpIfSmi(weak_value, &initialize); | 2616 __ JumpIfSmi(weak_value, &initialize); |
| 2606 __ b(&megamorphic); | 2617 __ b(&megamorphic); |
| 2607 | 2618 |
| 2608 if (!FLAG_pretenuring_call_new) { | 2619 if (!FLAG_pretenuring_call_new) { |
| 2609 __ bind(&check_allocation_site); | 2620 __ bind(&check_allocation_site); |
| 2610 // If we came here, we need to see if we are the array function. | 2621 // If we came here, we need to see if we are the array function. |
| 2611 // If we didn't have a matching function, and we didn't find the megamorph | 2622 // If we didn't have a matching function, and we didn't find the megamorph |
| 2612 // sentinel, then we have in the slot either some other function or an | 2623 // sentinel, then we have in the slot either some other function or an |
| 2613 // AllocationSite. | 2624 // AllocationSite. |
| 2614 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); | 2625 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); |
| 2615 __ bne(&miss); | 2626 __ bne(&miss); |
| 2616 | 2627 |
| 2617 // Make sure the function is the Array() function | 2628 // Make sure the function is the Array() function |
| 2618 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7); | 2629 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r8); |
| 2619 __ cmp(r4, r7); | 2630 __ cmp(r4, r8); |
| 2620 __ bne(&megamorphic); | 2631 __ bne(&megamorphic); |
| 2621 __ b(&done); | 2632 __ b(&done); |
| 2622 } | 2633 } |
| 2623 | 2634 |
| 2624 __ bind(&miss); | 2635 __ bind(&miss); |
| 2625 | 2636 |
| 2626 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2637 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 2627 // megamorphic. | 2638 // megamorphic. |
| 2628 __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex); | 2639 __ CompareRoot(r8, Heap::kuninitialized_symbolRootIndex); |
| 2629 __ beq(&initialize); | 2640 __ beq(&initialize); |
| 2630 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2641 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 2631 // write-barrier is needed. | 2642 // write-barrier is needed. |
| 2632 __ bind(&megamorphic); | 2643 __ bind(&megamorphic); |
| 2633 __ SmiToPtrArrayOffset(r7, r6); | 2644 __ SmiToPtrArrayOffset(r8, r6); |
| 2634 __ add(r7, r5, r7); | 2645 __ add(r8, r5, r8); |
| 2635 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); | 2646 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); |
| 2636 __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0); | 2647 __ StoreP(ip, FieldMemOperand(r8, FixedArray::kHeaderSize), r0); |
| 2637 __ jmp(&done); | 2648 __ jmp(&done); |
| 2638 | 2649 |
| 2639 // An uninitialized cache is patched with the function | 2650 // An uninitialized cache is patched with the function |
| 2640 __ bind(&initialize); | 2651 __ bind(&initialize); |
| 2641 | 2652 |
| 2642 if (!FLAG_pretenuring_call_new) { | 2653 if (!FLAG_pretenuring_call_new) { |
| 2643 // Make sure the function is the Array() function. | 2654 // Make sure the function is the Array() function. |
| 2644 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7); | 2655 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r8); |
| 2645 __ cmp(r4, r7); | 2656 __ cmp(r4, r8); |
| 2646 __ bne(¬_array_function); | 2657 __ bne(¬_array_function); |
| 2647 | 2658 |
| 2648 // The target function is the Array constructor, | 2659 // The target function is the Array constructor, |
| 2649 // Create an AllocationSite if we don't already have it, store it in the | 2660 // Create an AllocationSite if we don't already have it, store it in the |
| 2650 // slot. | 2661 // slot. |
| 2651 CreateAllocationSiteStub create_stub(masm->isolate()); | 2662 CreateAllocationSiteStub create_stub(masm->isolate()); |
| 2652 CallStubInRecordCallTarget(masm, &create_stub); | 2663 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
| 2653 __ b(&done); | 2664 __ b(&done); |
| 2654 | 2665 |
| 2655 __ bind(¬_array_function); | 2666 __ bind(¬_array_function); |
| 2656 } | 2667 } |
| 2657 | 2668 |
| 2658 CreateWeakCellStub create_stub(masm->isolate()); | 2669 CreateWeakCellStub create_stub(masm->isolate()); |
| 2659 CallStubInRecordCallTarget(masm, &create_stub); | 2670 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
| 2660 __ bind(&done); | 2671 __ bind(&done); |
| 2661 } | 2672 } |
| 2662 | 2673 |
| 2663 | 2674 |
| 2664 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | 2675 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { |
| 2665 // Do not transform the receiver for strict mode functions and natives. | 2676 // Do not transform the receiver for strict mode functions and natives. |
| 2666 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); | 2677 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); |
| 2667 __ lwz(r7, FieldMemOperand(r6, SharedFunctionInfo::kCompilerHintsOffset)); | 2678 __ lwz(r7, FieldMemOperand(r6, SharedFunctionInfo::kCompilerHintsOffset)); |
| 2668 __ TestBit(r7, | 2679 __ TestBit(r7, |
| 2669 #if V8_TARGET_ARCH_PPC64 | 2680 #if V8_TARGET_ARCH_PPC64 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2792 // r7 : original constructor (for IsSuperConstructorCall) | 2803 // r7 : original constructor (for IsSuperConstructorCall) |
| 2793 Label slow, non_function_call; | 2804 Label slow, non_function_call; |
| 2794 | 2805 |
| 2795 // Check that the function is not a smi. | 2806 // Check that the function is not a smi. |
| 2796 __ JumpIfSmi(r4, &non_function_call); | 2807 __ JumpIfSmi(r4, &non_function_call); |
| 2797 // Check that the function is a JSFunction. | 2808 // Check that the function is a JSFunction. |
| 2798 __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE); | 2809 __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE); |
| 2799 __ bne(&slow); | 2810 __ bne(&slow); |
| 2800 | 2811 |
| 2801 if (RecordCallTarget()) { | 2812 if (RecordCallTarget()) { |
| 2802 if (IsSuperConstructorCall()) { | 2813 GenerateRecordCallTarget(masm, IsSuperConstructorCall()); |
| 2803 __ push(r7); | |
| 2804 } | |
| 2805 // TODO(mstarzinger): Consider tweaking target recording to avoid push/pop. | |
| 2806 GenerateRecordCallTarget(masm); | |
| 2807 if (IsSuperConstructorCall()) { | |
| 2808 __ pop(r7); | |
| 2809 } | |
| 2810 | 2814 |
| 2811 __ SmiToPtrArrayOffset(r8, r6); | 2815 __ SmiToPtrArrayOffset(r8, r6); |
| 2812 __ add(r8, r5, r8); | 2816 __ add(r8, r5, r8); |
| 2813 if (FLAG_pretenuring_call_new) { | 2817 if (FLAG_pretenuring_call_new) { |
| 2814 // Put the AllocationSite from the feedback vector into r5. | 2818 // Put the AllocationSite from the feedback vector into r5. |
| 2815 // By adding kPointerSize we encode that we know the AllocationSite | 2819 // By adding kPointerSize we encode that we know the AllocationSite |
| 2816 // entry is at the feedback vector slot given by r6 + 1. | 2820 // entry is at the feedback vector slot given by r6 + 1. |
| 2817 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize)); | 2821 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize)); |
| 2818 } else { | 2822 } else { |
| 2819 // Put the AllocationSite from the feedback vector into r5, or undefined. | 2823 // Put the AllocationSite from the feedback vector into r5, or undefined. |
| (...skipping 2853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5673 kStackUnwindSpace, NULL, | 5677 kStackUnwindSpace, NULL, |
| 5674 MemOperand(fp, 6 * kPointerSize), NULL); | 5678 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5675 } | 5679 } |
| 5676 | 5680 |
| 5677 | 5681 |
| 5678 #undef __ | 5682 #undef __ |
| 5679 } // namespace internal | 5683 } // namespace internal |
| 5680 } // namespace v8 | 5684 } // namespace v8 |
| 5681 | 5685 |
| 5682 #endif // V8_TARGET_ARCH_PPC | 5686 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |