| 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 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 1680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 __ Allocate(t5, v0, t5, t0, &runtime, TAG_OBJECT); | 1691 __ Allocate(t5, v0, t5, t0, &runtime, TAG_OBJECT); |
| 1692 | 1692 |
| 1693 // v0 = address of new object(s) (tagged) | 1693 // v0 = address of new object(s) (tagged) |
| 1694 // a2 = argument count (smi-tagged) | 1694 // a2 = argument count (smi-tagged) |
| 1695 // Get the arguments boilerplate from the current native context into t0. | 1695 // Get the arguments boilerplate from the current native context into t0. |
| 1696 const int kNormalOffset = | 1696 const int kNormalOffset = |
| 1697 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | 1697 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); |
| 1698 const int kAliasedOffset = | 1698 const int kAliasedOffset = |
| 1699 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | 1699 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); |
| 1700 | 1700 |
| 1701 __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1701 __ lw(t0, NativeContextMemOperand()); |
| 1702 __ lw(t0, FieldMemOperand(t0, JSGlobalObject::kNativeContextOffset)); | |
| 1703 Label skip2_ne, skip2_eq; | 1702 Label skip2_ne, skip2_eq; |
| 1704 __ Branch(&skip2_ne, ne, t2, Operand(zero_reg)); | 1703 __ Branch(&skip2_ne, ne, t2, Operand(zero_reg)); |
| 1705 __ lw(t0, MemOperand(t0, kNormalOffset)); | 1704 __ lw(t0, MemOperand(t0, kNormalOffset)); |
| 1706 __ bind(&skip2_ne); | 1705 __ bind(&skip2_ne); |
| 1707 | 1706 |
| 1708 __ Branch(&skip2_eq, eq, t2, Operand(zero_reg)); | 1707 __ Branch(&skip2_eq, eq, t2, Operand(zero_reg)); |
| 1709 __ lw(t0, MemOperand(t0, kAliasedOffset)); | 1708 __ lw(t0, MemOperand(t0, kAliasedOffset)); |
| 1710 __ bind(&skip2_eq); | 1709 __ bind(&skip2_eq); |
| 1711 | 1710 |
| 1712 // v0 = address of new object (tagged) | 1711 // v0 = address of new object (tagged) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 | 1894 |
| 1896 __ Addu(t5, t5, Operand(FixedArray::kHeaderSize / kPointerSize)); | 1895 __ Addu(t5, t5, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 1897 __ bind(&add_arguments_object); | 1896 __ bind(&add_arguments_object); |
| 1898 __ Addu(t5, t5, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); | 1897 __ Addu(t5, t5, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); |
| 1899 | 1898 |
| 1900 // Do the allocation of both objects in one go. | 1899 // Do the allocation of both objects in one go. |
| 1901 __ Allocate(t5, v0, t0, t1, &runtime, | 1900 __ Allocate(t5, v0, t0, t1, &runtime, |
| 1902 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); | 1901 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); |
| 1903 | 1902 |
| 1904 // Get the arguments boilerplate from the current native context. | 1903 // Get the arguments boilerplate from the current native context. |
| 1905 __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1904 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, t0); |
| 1906 __ lw(t0, FieldMemOperand(t0, JSGlobalObject::kNativeContextOffset)); | |
| 1907 __ lw(t0, MemOperand( | |
| 1908 t0, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); | |
| 1909 | 1905 |
| 1910 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); | 1906 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); |
| 1911 __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex); | 1907 __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex); |
| 1912 __ sw(t1, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | 1908 __ sw(t1, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
| 1913 __ sw(t1, FieldMemOperand(v0, JSObject::kElementsOffset)); | 1909 __ sw(t1, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 1914 | 1910 |
| 1915 // Get the length (smi tagged) and set that as an in-object property too. | 1911 // Get the length (smi tagged) and set that as an in-object property too. |
| 1916 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1912 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1917 __ AssertSmi(a2); | 1913 __ AssertSmi(a2); |
| 1918 __ sw(a2, | 1914 __ sw(a2, |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2452 | 2448 |
| 2453 __ bind(&check_allocation_site); | 2449 __ bind(&check_allocation_site); |
| 2454 // If we came here, we need to see if we are the array function. | 2450 // If we came here, we need to see if we are the array function. |
| 2455 // If we didn't have a matching function, and we didn't find the megamorph | 2451 // If we didn't have a matching function, and we didn't find the megamorph |
| 2456 // sentinel, then we have in the slot either some other function or an | 2452 // sentinel, then we have in the slot either some other function or an |
| 2457 // AllocationSite. | 2453 // AllocationSite. |
| 2458 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 2454 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
| 2459 __ Branch(&miss, ne, feedback_map, Operand(at)); | 2455 __ Branch(&miss, ne, feedback_map, Operand(at)); |
| 2460 | 2456 |
| 2461 // Make sure the function is the Array() function | 2457 // Make sure the function is the Array() function |
| 2462 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, t2); | 2458 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, t2); |
| 2463 __ Branch(&megamorphic, ne, a1, Operand(t2)); | 2459 __ Branch(&megamorphic, ne, a1, Operand(t2)); |
| 2464 __ jmp(&done); | 2460 __ jmp(&done); |
| 2465 | 2461 |
| 2466 __ bind(&miss); | 2462 __ bind(&miss); |
| 2467 | 2463 |
| 2468 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2464 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 2469 // megamorphic. | 2465 // megamorphic. |
| 2470 __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex); | 2466 __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex); |
| 2471 __ Branch(&initialize, eq, t2, Operand(at)); | 2467 __ Branch(&initialize, eq, t2, Operand(at)); |
| 2472 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2468 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 2473 // write-barrier is needed. | 2469 // write-barrier is needed. |
| 2474 __ bind(&megamorphic); | 2470 __ bind(&megamorphic); |
| 2475 __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize); | 2471 __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize); |
| 2476 __ Addu(t2, a2, Operand(t2)); | 2472 __ Addu(t2, a2, Operand(t2)); |
| 2477 __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); | 2473 __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); |
| 2478 __ sw(at, FieldMemOperand(t2, FixedArray::kHeaderSize)); | 2474 __ sw(at, FieldMemOperand(t2, FixedArray::kHeaderSize)); |
| 2479 __ jmp(&done); | 2475 __ jmp(&done); |
| 2480 | 2476 |
| 2481 // An uninitialized cache is patched with the function. | 2477 // An uninitialized cache is patched with the function. |
| 2482 __ bind(&initialize); | 2478 __ bind(&initialize); |
| 2483 // Make sure the function is the Array() function. | 2479 // Make sure the function is the Array() function. |
| 2484 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, t2); | 2480 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, t2); |
| 2485 __ Branch(¬_array_function, ne, a1, Operand(t2)); | 2481 __ Branch(¬_array_function, ne, a1, Operand(t2)); |
| 2486 | 2482 |
| 2487 // The target function is the Array constructor, | 2483 // The target function is the Array constructor, |
| 2488 // Create an AllocationSite if we don't already have it, store it in the | 2484 // Create an AllocationSite if we don't already have it, store it in the |
| 2489 // slot. | 2485 // slot. |
| 2490 CreateAllocationSiteStub create_stub(masm->isolate()); | 2486 CreateAllocationSiteStub create_stub(masm->isolate()); |
| 2491 CallStubInRecordCallTarget(masm, &create_stub); | 2487 CallStubInRecordCallTarget(masm, &create_stub); |
| 2492 __ Branch(&done); | 2488 __ Branch(&done); |
| 2493 | 2489 |
| 2494 __ bind(¬_array_function); | 2490 __ bind(¬_array_function); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 __ mov(a3, a1); | 2536 __ mov(a3, a1); |
| 2541 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2537 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2542 } | 2538 } |
| 2543 | 2539 |
| 2544 | 2540 |
| 2545 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { | 2541 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { |
| 2546 // a1 - function | 2542 // a1 - function |
| 2547 // a3 - slot id | 2543 // a3 - slot id |
| 2548 // a2 - vector | 2544 // a2 - vector |
| 2549 // t0 - loaded from vector[slot] | 2545 // t0 - loaded from vector[slot] |
| 2550 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at); | 2546 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, at); |
| 2551 __ Branch(miss, ne, a1, Operand(at)); | 2547 __ Branch(miss, ne, a1, Operand(at)); |
| 2552 | 2548 |
| 2553 __ li(a0, Operand(arg_count())); | 2549 __ li(a0, Operand(arg_count())); |
| 2554 | 2550 |
| 2555 // Increment the call count for monomorphic function calls. | 2551 // Increment the call count for monomorphic function calls. |
| 2556 __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize); | 2552 __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize); |
| 2557 __ Addu(at, a2, Operand(at)); | 2553 __ Addu(at, a2, Operand(at)); |
| 2558 __ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize)); | 2554 __ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize)); |
| 2559 __ Addu(a3, a3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); | 2555 __ Addu(a3, a3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); |
| 2560 __ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize)); | 2556 __ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize)); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2668 | 2664 |
| 2669 // We are going monomorphic, provided we actually have a JSFunction. | 2665 // We are going monomorphic, provided we actually have a JSFunction. |
| 2670 __ JumpIfSmi(a1, &miss); | 2666 __ JumpIfSmi(a1, &miss); |
| 2671 | 2667 |
| 2672 // Goto miss case if we do not have a function. | 2668 // Goto miss case if we do not have a function. |
| 2673 __ GetObjectType(a1, t0, t0); | 2669 __ GetObjectType(a1, t0, t0); |
| 2674 __ Branch(&miss, ne, t0, Operand(JS_FUNCTION_TYPE)); | 2670 __ Branch(&miss, ne, t0, Operand(JS_FUNCTION_TYPE)); |
| 2675 | 2671 |
| 2676 // Make sure the function is not the Array() function, which requires special | 2672 // Make sure the function is not the Array() function, which requires special |
| 2677 // behavior on MISS. | 2673 // behavior on MISS. |
| 2678 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, t0); | 2674 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, t0); |
| 2679 __ Branch(&miss, eq, a1, Operand(t0)); | 2675 __ Branch(&miss, eq, a1, Operand(t0)); |
| 2680 | 2676 |
| 2681 // Make sure the function belongs to the same native context (which implies | 2677 // Make sure the function belongs to the same native context. |
| 2682 // the same global object). | |
| 2683 __ lw(t0, FieldMemOperand(a1, JSFunction::kContextOffset)); | 2678 __ lw(t0, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 2684 __ lw(t0, ContextOperand(t0, Context::GLOBAL_OBJECT_INDEX)); | 2679 __ lw(t0, ContextMemOperand(t0, Context::NATIVE_CONTEXT_INDEX)); |
| 2685 __ lw(t1, GlobalObjectOperand()); | 2680 __ lw(t1, NativeContextMemOperand()); |
| 2686 __ Branch(&miss, ne, t0, Operand(t1)); | 2681 __ Branch(&miss, ne, t0, Operand(t1)); |
| 2687 | 2682 |
| 2688 // Update stats. | 2683 // Update stats. |
| 2689 __ lw(t0, FieldMemOperand(a2, with_types_offset)); | 2684 __ lw(t0, FieldMemOperand(a2, with_types_offset)); |
| 2690 __ Addu(t0, t0, Operand(Smi::FromInt(1))); | 2685 __ Addu(t0, t0, Operand(Smi::FromInt(1))); |
| 2691 __ sw(t0, FieldMemOperand(a2, with_types_offset)); | 2686 __ sw(t0, FieldMemOperand(a2, with_types_offset)); |
| 2692 | 2687 |
| 2693 // Initialize the call counter. | 2688 // Initialize the call counter. |
| 2694 __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize); | 2689 __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize); |
| 2695 __ Addu(at, a2, Operand(at)); | 2690 __ Addu(at, a2, Operand(at)); |
| (...skipping 2428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5124 | 5119 |
| 5125 | 5120 |
| 5126 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | 5121 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { |
| 5127 Register context_reg = cp; | 5122 Register context_reg = cp; |
| 5128 Register slot_reg = a2; | 5123 Register slot_reg = a2; |
| 5129 Register result_reg = v0; | 5124 Register result_reg = v0; |
| 5130 Label slow_case; | 5125 Label slow_case; |
| 5131 | 5126 |
| 5132 // Go up context chain to the script context. | 5127 // Go up context chain to the script context. |
| 5133 for (int i = 0; i < depth(); ++i) { | 5128 for (int i = 0; i < depth(); ++i) { |
| 5134 __ lw(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | 5129 __ lw(result_reg, ContextMemOperand(context_reg, Context::PREVIOUS_INDEX)); |
| 5135 context_reg = result_reg; | 5130 context_reg = result_reg; |
| 5136 } | 5131 } |
| 5137 | 5132 |
| 5138 // Load the PropertyCell value at the specified slot. | 5133 // Load the PropertyCell value at the specified slot. |
| 5139 __ sll(at, slot_reg, kPointerSizeLog2); | 5134 __ sll(at, slot_reg, kPointerSizeLog2); |
| 5140 __ Addu(at, at, Operand(context_reg)); | 5135 __ Addu(at, at, Operand(context_reg)); |
| 5141 __ lw(result_reg, ContextOperand(at, 0)); | 5136 __ lw(result_reg, ContextMemOperand(at, 0)); |
| 5142 __ lw(result_reg, FieldMemOperand(result_reg, PropertyCell::kValueOffset)); | 5137 __ lw(result_reg, FieldMemOperand(result_reg, PropertyCell::kValueOffset)); |
| 5143 | 5138 |
| 5144 // Check that value is not the_hole. | 5139 // Check that value is not the_hole. |
| 5145 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 5140 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 5146 __ Branch(&slow_case, eq, result_reg, Operand(at)); | 5141 __ Branch(&slow_case, eq, result_reg, Operand(at)); |
| 5147 __ Ret(); | 5142 __ Ret(); |
| 5148 | 5143 |
| 5149 // Fallback to the runtime. | 5144 // Fallback to the runtime. |
| 5150 __ bind(&slow_case); | 5145 __ bind(&slow_case); |
| 5151 __ SmiTag(slot_reg); | 5146 __ SmiTag(slot_reg); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5163 Register cell_details_reg = t2; | 5158 Register cell_details_reg = t2; |
| 5164 Label fast_heapobject_case, fast_smi_case, slow_case; | 5159 Label fast_heapobject_case, fast_smi_case, slow_case; |
| 5165 | 5160 |
| 5166 if (FLAG_debug_code) { | 5161 if (FLAG_debug_code) { |
| 5167 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 5162 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 5168 __ Check(ne, kUnexpectedValue, value_reg, Operand(at)); | 5163 __ Check(ne, kUnexpectedValue, value_reg, Operand(at)); |
| 5169 } | 5164 } |
| 5170 | 5165 |
| 5171 // Go up context chain to the script context. | 5166 // Go up context chain to the script context. |
| 5172 for (int i = 0; i < depth(); ++i) { | 5167 for (int i = 0; i < depth(); ++i) { |
| 5173 __ lw(cell_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | 5168 __ lw(cell_reg, ContextMemOperand(context_reg, Context::PREVIOUS_INDEX)); |
| 5174 context_reg = cell_reg; | 5169 context_reg = cell_reg; |
| 5175 } | 5170 } |
| 5176 | 5171 |
| 5177 // Load the PropertyCell at the specified slot. | 5172 // Load the PropertyCell at the specified slot. |
| 5178 __ sll(at, slot_reg, kPointerSizeLog2); | 5173 __ sll(at, slot_reg, kPointerSizeLog2); |
| 5179 __ Addu(at, at, Operand(context_reg)); | 5174 __ Addu(at, at, Operand(context_reg)); |
| 5180 __ lw(cell_reg, ContextOperand(at, 0)); | 5175 __ lw(cell_reg, ContextMemOperand(at, 0)); |
| 5181 | 5176 |
| 5182 // Load PropertyDetails for the cell (actually only the cell_type and kind). | 5177 // Load PropertyDetails for the cell (actually only the cell_type and kind). |
| 5183 __ lw(cell_details_reg, | 5178 __ lw(cell_details_reg, |
| 5184 FieldMemOperand(cell_reg, PropertyCell::kDetailsOffset)); | 5179 FieldMemOperand(cell_reg, PropertyCell::kDetailsOffset)); |
| 5185 __ SmiUntag(cell_details_reg); | 5180 __ SmiUntag(cell_details_reg); |
| 5186 __ And(cell_details_reg, cell_details_reg, | 5181 __ And(cell_details_reg, cell_details_reg, |
| 5187 PropertyDetails::PropertyCellTypeField::kMask | | 5182 PropertyDetails::PropertyCellTypeField::kMask | |
| 5188 PropertyDetails::KindField::kMask | | 5183 PropertyDetails::KindField::kMask | |
| 5189 PropertyDetails::kAttributesReadOnlyMask); | 5184 PropertyDetails::kAttributesReadOnlyMask); |
| 5190 | 5185 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5571 MemOperand(fp, 6 * kPointerSize), NULL); | 5566 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5572 } | 5567 } |
| 5573 | 5568 |
| 5574 | 5569 |
| 5575 #undef __ | 5570 #undef __ |
| 5576 | 5571 |
| 5577 } // namespace internal | 5572 } // namespace internal |
| 5578 } // namespace v8 | 5573 } // namespace v8 |
| 5579 | 5574 |
| 5580 #endif // V8_TARGET_ARCH_MIPS | 5575 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |