| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 2531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2542 // (9) Sliced string. Replace subject with parent. Go to (4). | 2542 // (9) Sliced string. Replace subject with parent. Go to (4). |
| 2543 // Load offset into t0 and replace subject string with parent. | 2543 // Load offset into t0 and replace subject string with parent. |
| 2544 __ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | 2544 __ ld(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 2545 __ SmiUntag(t0); | 2545 __ SmiUntag(t0); |
| 2546 __ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 2546 __ ld(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 2547 __ jmp(&check_underlying); // Go to (4). | 2547 __ jmp(&check_underlying); // Go to (4). |
| 2548 #endif // V8_INTERPRETED_REGEXP | 2548 #endif // V8_INTERPRETED_REGEXP |
| 2549 } | 2549 } |
| 2550 | 2550 |
| 2551 | 2551 |
| 2552 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 2552 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, |
| 2553 bool is_super) { |
| 2553 // a0 : number of arguments to the construct function | 2554 // a0 : number of arguments to the construct function |
| 2554 // a2 : Feedback vector | 2555 // a2 : feedback vector |
| 2555 // a3 : slot in feedback vector (Smi) | 2556 // a3 : slot in feedback vector (Smi) |
| 2556 // a1 : the function to call | 2557 // a1 : the function to call |
| 2558 // a4 : original constructor (for IsSuperConstructorCall) |
| 2557 FrameScope scope(masm, StackFrame::INTERNAL); | 2559 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2558 const RegList kSavedRegs = 1 << 4 | // a0 | 2560 const RegList kSavedRegs = 1 << 4 | // a0 |
| 2559 1 << 5 | // a1 | 2561 1 << 5 | // a1 |
| 2560 1 << 6 | // a2 | 2562 1 << 6 | // a2 |
| 2561 1 << 7; // a3 | 2563 1 << 7 | // a3 |
| 2564 BoolToInt(is_super) << 8; // a4 |
| 2565 |
| 2562 | 2566 |
| 2563 // Number-of-arguments register must be smi-tagged to call out. | 2567 // Number-of-arguments register must be smi-tagged to call out. |
| 2564 __ SmiTag(a0); | 2568 __ SmiTag(a0); |
| 2565 __ MultiPush(kSavedRegs); | 2569 __ MultiPush(kSavedRegs); |
| 2566 | 2570 |
| 2567 __ CallStub(stub); | 2571 __ CallStub(stub); |
| 2568 | 2572 |
| 2569 __ MultiPop(kSavedRegs); | 2573 __ MultiPop(kSavedRegs); |
| 2570 __ SmiUntag(a0); | 2574 __ SmiUntag(a0); |
| 2571 } | 2575 } |
| 2572 | 2576 |
| 2573 | 2577 |
| 2574 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 2578 static void GenerateRecordCallTarget(MacroAssembler* masm, bool is_super) { |
| 2575 // Cache the called function in a feedback vector slot. Cache states | 2579 // Cache the called function in a feedback vector slot. Cache states |
| 2576 // are uninitialized, monomorphic (indicated by a JSFunction), and | 2580 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 2577 // megamorphic. | 2581 // megamorphic. |
| 2578 // a0 : number of arguments to the construct function | 2582 // a0 : number of arguments to the construct function |
| 2579 // a1 : the function to call | 2583 // a1 : the function to call |
| 2580 // a2 : Feedback vector | 2584 // a2 : feedback vector |
| 2581 // a3 : slot in feedback vector (Smi) | 2585 // a3 : slot in feedback vector (Smi) |
| 2586 // a4 : original constructor (for IsSuperConstructorCall) |
| 2582 Label initialize, done, miss, megamorphic, not_array_function; | 2587 Label initialize, done, miss, megamorphic, not_array_function; |
| 2583 | 2588 |
| 2584 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), | 2589 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), |
| 2585 masm->isolate()->heap()->megamorphic_symbol()); | 2590 masm->isolate()->heap()->megamorphic_symbol()); |
| 2586 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), | 2591 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), |
| 2587 masm->isolate()->heap()->uninitialized_symbol()); | 2592 masm->isolate()->heap()->uninitialized_symbol()); |
| 2588 | 2593 |
| 2589 // Load the cache state into a4. | 2594 // Load the cache state into a5. |
| 2590 __ dsrl(a4, a3, 32 - kPointerSizeLog2); | 2595 __ dsrl(a5, a3, 32 - kPointerSizeLog2); |
| 2591 __ Daddu(a4, a2, Operand(a4)); | 2596 __ Daddu(a5, a2, Operand(a5)); |
| 2592 __ ld(a4, FieldMemOperand(a4, FixedArray::kHeaderSize)); | 2597 __ ld(a5, FieldMemOperand(a5, FixedArray::kHeaderSize)); |
| 2593 | 2598 |
| 2594 // A monomorphic cache hit or an already megamorphic state: invoke the | 2599 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 2595 // function without changing the state. | 2600 // function without changing the state. |
| 2596 // We don't know if a4 is a WeakCell or a Symbol, but it's harmless to read at | 2601 // We don't know if a5 is a WeakCell or a Symbol, but it's harmless to read at |
| 2597 // 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). |
| 2598 Label check_allocation_site; | 2603 Label check_allocation_site; |
| 2599 Register feedback_map = a5; | 2604 Register feedback_map = a6; |
| 2600 Register weak_value = t0; | 2605 Register weak_value = t0; |
| 2601 __ ld(weak_value, FieldMemOperand(a4, WeakCell::kValueOffset)); | 2606 __ ld(weak_value, FieldMemOperand(a5, WeakCell::kValueOffset)); |
| 2602 __ Branch(&done, eq, a1, Operand(weak_value)); | 2607 __ Branch(&done, eq, a1, Operand(weak_value)); |
| 2603 __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); | 2608 __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); |
| 2604 __ Branch(&done, eq, a4, Operand(at)); | 2609 __ Branch(&done, eq, a5, Operand(at)); |
| 2605 __ ld(feedback_map, FieldMemOperand(a4, HeapObject::kMapOffset)); | 2610 __ ld(feedback_map, FieldMemOperand(a5, HeapObject::kMapOffset)); |
| 2606 __ LoadRoot(at, Heap::kWeakCellMapRootIndex); | 2611 __ LoadRoot(at, Heap::kWeakCellMapRootIndex); |
| 2607 __ Branch(FLAG_pretenuring_call_new ? &miss : &check_allocation_site, ne, | 2612 __ Branch(FLAG_pretenuring_call_new ? &miss : &check_allocation_site, ne, |
| 2608 feedback_map, Operand(at)); | 2613 feedback_map, Operand(at)); |
| 2609 | 2614 |
| 2610 // 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. |
| 2611 __ JumpIfSmi(weak_value, &initialize); | 2616 __ JumpIfSmi(weak_value, &initialize); |
| 2612 __ jmp(&megamorphic); | 2617 __ jmp(&megamorphic); |
| 2613 | 2618 |
| 2614 if (!FLAG_pretenuring_call_new) { | 2619 if (!FLAG_pretenuring_call_new) { |
| 2615 __ bind(&check_allocation_site); | 2620 __ bind(&check_allocation_site); |
| 2616 // 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. |
| 2617 // 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 |
| 2618 // 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 |
| 2619 // AllocationSite. | 2624 // AllocationSite. |
| 2620 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 2625 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
| 2621 __ Branch(&miss, ne, feedback_map, Operand(at)); | 2626 __ Branch(&miss, ne, feedback_map, Operand(at)); |
| 2622 | 2627 |
| 2623 // Make sure the function is the Array() function | 2628 // Make sure the function is the Array() function |
| 2624 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a4); | 2629 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a5); |
| 2625 __ Branch(&megamorphic, ne, a1, Operand(a4)); | 2630 __ Branch(&megamorphic, ne, a1, Operand(a5)); |
| 2626 __ jmp(&done); | 2631 __ jmp(&done); |
| 2627 } | 2632 } |
| 2628 | 2633 |
| 2629 __ bind(&miss); | 2634 __ bind(&miss); |
| 2630 | 2635 |
| 2631 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2636 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 2632 // megamorphic. | 2637 // megamorphic. |
| 2633 __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex); | 2638 __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex); |
| 2634 __ Branch(&initialize, eq, a4, Operand(at)); | 2639 __ Branch(&initialize, eq, a5, Operand(at)); |
| 2635 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2640 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 2636 // write-barrier is needed. | 2641 // write-barrier is needed. |
| 2637 __ bind(&megamorphic); | 2642 __ bind(&megamorphic); |
| 2638 __ dsrl(a4, a3, 32 - kPointerSizeLog2); | 2643 __ dsrl(a5, a3, 32 - kPointerSizeLog2); |
| 2639 __ Daddu(a4, a2, Operand(a4)); | 2644 __ Daddu(a5, a2, Operand(a5)); |
| 2640 __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); | 2645 __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); |
| 2641 __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize)); | 2646 __ sd(at, FieldMemOperand(a5, FixedArray::kHeaderSize)); |
| 2642 __ jmp(&done); | 2647 __ jmp(&done); |
| 2643 | 2648 |
| 2644 // An uninitialized cache is patched with the function. | 2649 // An uninitialized cache is patched with the function. |
| 2645 __ bind(&initialize); | 2650 __ bind(&initialize); |
| 2646 if (!FLAG_pretenuring_call_new) { | 2651 if (!FLAG_pretenuring_call_new) { |
| 2647 // Make sure the function is the Array() function. | 2652 // Make sure the function is the Array() function. |
| 2648 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a4); | 2653 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a5); |
| 2649 __ Branch(¬_array_function, ne, a1, Operand(a4)); | 2654 __ Branch(¬_array_function, ne, a1, Operand(a5)); |
| 2650 | 2655 |
| 2651 // The target function is the Array constructor, | 2656 // The target function is the Array constructor, |
| 2652 // Create an AllocationSite if we don't already have it, store it in the | 2657 // Create an AllocationSite if we don't already have it, store it in the |
| 2653 // slot. | 2658 // slot. |
| 2654 CreateAllocationSiteStub create_stub(masm->isolate()); | 2659 CreateAllocationSiteStub create_stub(masm->isolate()); |
| 2655 CallStubInRecordCallTarget(masm, &create_stub); | 2660 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
| 2656 __ Branch(&done); | 2661 __ Branch(&done); |
| 2657 | 2662 |
| 2658 __ bind(¬_array_function); | 2663 __ bind(¬_array_function); |
| 2659 } | 2664 } |
| 2660 | 2665 |
| 2661 CreateWeakCellStub create_stub(masm->isolate()); | 2666 CreateWeakCellStub create_stub(masm->isolate()); |
| 2662 CallStubInRecordCallTarget(masm, &create_stub); | 2667 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
| 2663 __ bind(&done); | 2668 __ bind(&done); |
| 2664 } | 2669 } |
| 2665 | 2670 |
| 2666 | 2671 |
| 2667 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | 2672 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { |
| 2668 __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 2673 __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 2669 | 2674 |
| 2670 // Do not transform the receiver for strict mode functions. | 2675 // Do not transform the receiver for strict mode functions. |
| 2671 int32_t strict_mode_function_mask = | 2676 int32_t strict_mode_function_mask = |
| 2672 1 << SharedFunctionInfo::kStrictModeBitWithinByte ; | 2677 1 << SharedFunctionInfo::kStrictModeBitWithinByte ; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2787 // a3 : slot in feedback vector (Smi, for RecordCallTarget) | 2792 // a3 : slot in feedback vector (Smi, for RecordCallTarget) |
| 2788 // a4 : original constructor (for IsSuperConstructorCall) | 2793 // a4 : original constructor (for IsSuperConstructorCall) |
| 2789 Label slow, non_function_call; | 2794 Label slow, non_function_call; |
| 2790 // Check that the function is not a smi. | 2795 // Check that the function is not a smi. |
| 2791 __ JumpIfSmi(a1, &non_function_call); | 2796 __ JumpIfSmi(a1, &non_function_call); |
| 2792 // Check that the function is a JSFunction. | 2797 // Check that the function is a JSFunction. |
| 2793 __ GetObjectType(a1, a5, a5); | 2798 __ GetObjectType(a1, a5, a5); |
| 2794 __ Branch(&slow, ne, a5, Operand(JS_FUNCTION_TYPE)); | 2799 __ Branch(&slow, ne, a5, Operand(JS_FUNCTION_TYPE)); |
| 2795 | 2800 |
| 2796 if (RecordCallTarget()) { | 2801 if (RecordCallTarget()) { |
| 2797 if (IsSuperConstructorCall()) { | 2802 GenerateRecordCallTarget(masm, IsSuperConstructorCall()); |
| 2798 __ push(a4); | |
| 2799 } | |
| 2800 GenerateRecordCallTarget(masm); | |
| 2801 if (IsSuperConstructorCall()) { | |
| 2802 __ pop(a4); | |
| 2803 } | |
| 2804 | 2803 |
| 2805 __ dsrl(at, a3, 32 - kPointerSizeLog2); | 2804 __ dsrl(at, a3, 32 - kPointerSizeLog2); |
| 2806 __ Daddu(a5, a2, at); | 2805 __ Daddu(a5, a2, at); |
| 2807 if (FLAG_pretenuring_call_new) { | 2806 if (FLAG_pretenuring_call_new) { |
| 2808 // Put the AllocationSite from the feedback vector into a2. | 2807 // Put the AllocationSite from the feedback vector into a2. |
| 2809 // By adding kPointerSize we encode that we know the AllocationSite | 2808 // By adding kPointerSize we encode that we know the AllocationSite |
| 2810 // entry is at the feedback vector slot given by a3 + 1. | 2809 // entry is at the feedback vector slot given by a3 + 1. |
| 2811 __ ld(a2, FieldMemOperand(a5, FixedArray::kHeaderSize + kPointerSize)); | 2810 __ ld(a2, FieldMemOperand(a5, FixedArray::kHeaderSize + kPointerSize)); |
| 2812 } else { | 2811 } else { |
| 2813 Label feedback_register_initialized; | 2812 Label feedback_register_initialized; |
| (...skipping 2796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5610 MemOperand(fp, 6 * kPointerSize), NULL); | 5609 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5611 } | 5610 } |
| 5612 | 5611 |
| 5613 | 5612 |
| 5614 #undef __ | 5613 #undef __ |
| 5615 | 5614 |
| 5616 } // namespace internal | 5615 } // namespace internal |
| 5617 } // namespace v8 | 5616 } // namespace v8 |
| 5618 | 5617 |
| 5619 #endif // V8_TARGET_ARCH_MIPS64 | 5618 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |