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_ARM | 5 #if V8_TARGET_ARCH_ARM |
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 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 __ Allocate(r9, r0, r9, r4, &runtime, TAG_OBJECT); | 1593 __ Allocate(r9, r0, r9, r4, &runtime, TAG_OBJECT); |
1594 | 1594 |
1595 // r0 = address of new object(s) (tagged) | 1595 // r0 = address of new object(s) (tagged) |
1596 // r2 = argument count (smi-tagged) | 1596 // r2 = argument count (smi-tagged) |
1597 // Get the arguments boilerplate from the current native context into r4. | 1597 // Get the arguments boilerplate from the current native context into r4. |
1598 const int kNormalOffset = | 1598 const int kNormalOffset = |
1599 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | 1599 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); |
1600 const int kAliasedOffset = | 1600 const int kAliasedOffset = |
1601 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | 1601 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); |
1602 | 1602 |
1603 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1603 __ ldr(r4, NativeContextMemOperand()); |
1604 __ ldr(r4, FieldMemOperand(r4, JSGlobalObject::kNativeContextOffset)); | |
1605 __ cmp(r6, Operand::Zero()); | 1604 __ cmp(r6, Operand::Zero()); |
1606 __ ldr(r4, MemOperand(r4, kNormalOffset), eq); | 1605 __ ldr(r4, MemOperand(r4, kNormalOffset), eq); |
1607 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); | 1606 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); |
1608 | 1607 |
1609 // r0 = address of new object (tagged) | 1608 // r0 = address of new object (tagged) |
1610 // r2 = argument count (smi-tagged) | 1609 // r2 = argument count (smi-tagged) |
1611 // r4 = address of arguments map (tagged) | 1610 // r4 = address of arguments map (tagged) |
1612 // r6 = mapped parameter count (tagged) | 1611 // r6 = mapped parameter count (tagged) |
1613 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); | 1612 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); |
1614 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); | 1613 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1786 __ b(eq, &add_arguments_object); | 1785 __ b(eq, &add_arguments_object); |
1787 __ add(r9, r9, Operand(FixedArray::kHeaderSize / kPointerSize)); | 1786 __ add(r9, r9, Operand(FixedArray::kHeaderSize / kPointerSize)); |
1788 __ bind(&add_arguments_object); | 1787 __ bind(&add_arguments_object); |
1789 __ add(r9, r9, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); | 1788 __ add(r9, r9, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); |
1790 | 1789 |
1791 // Do the allocation of both objects in one go. | 1790 // Do the allocation of both objects in one go. |
1792 __ Allocate(r9, r0, r4, r5, &runtime, | 1791 __ Allocate(r9, r0, r4, r5, &runtime, |
1793 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); | 1792 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); |
1794 | 1793 |
1795 // Get the arguments boilerplate from the current native context. | 1794 // Get the arguments boilerplate from the current native context. |
1796 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1795 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r4); |
1797 __ ldr(r4, FieldMemOperand(r4, JSGlobalObject::kNativeContextOffset)); | |
1798 __ ldr(r4, MemOperand( | |
1799 r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); | |
1800 | 1796 |
1801 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); | 1797 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); |
1802 __ LoadRoot(r5, Heap::kEmptyFixedArrayRootIndex); | 1798 __ LoadRoot(r5, Heap::kEmptyFixedArrayRootIndex); |
1803 __ str(r5, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 1799 __ str(r5, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
1804 __ str(r5, FieldMemOperand(r0, JSObject::kElementsOffset)); | 1800 __ str(r5, FieldMemOperand(r0, JSObject::kElementsOffset)); |
1805 | 1801 |
1806 // Get the length (smi tagged) and set that as an in-object property too. | 1802 // Get the length (smi tagged) and set that as an in-object property too. |
1807 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1803 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
1808 __ AssertSmi(r2); | 1804 __ AssertSmi(r2); |
1809 __ str(r2, | 1805 __ str(r2, |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2322 | 2318 |
2323 __ bind(&check_allocation_site); | 2319 __ bind(&check_allocation_site); |
2324 // If we came here, we need to see if we are the array function. | 2320 // If we came here, we need to see if we are the array function. |
2325 // If we didn't have a matching function, and we didn't find the megamorph | 2321 // If we didn't have a matching function, and we didn't find the megamorph |
2326 // sentinel, then we have in the slot either some other function or an | 2322 // sentinel, then we have in the slot either some other function or an |
2327 // AllocationSite. | 2323 // AllocationSite. |
2328 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); | 2324 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); |
2329 __ b(ne, &miss); | 2325 __ b(ne, &miss); |
2330 | 2326 |
2331 // Make sure the function is the Array() function | 2327 // Make sure the function is the Array() function |
2332 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r5); | 2328 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r5); |
2333 __ cmp(r1, r5); | 2329 __ cmp(r1, r5); |
2334 __ b(ne, &megamorphic); | 2330 __ b(ne, &megamorphic); |
2335 __ jmp(&done); | 2331 __ jmp(&done); |
2336 | 2332 |
2337 __ bind(&miss); | 2333 __ bind(&miss); |
2338 | 2334 |
2339 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2335 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
2340 // megamorphic. | 2336 // megamorphic. |
2341 __ CompareRoot(r5, Heap::kuninitialized_symbolRootIndex); | 2337 __ CompareRoot(r5, Heap::kuninitialized_symbolRootIndex); |
2342 __ b(eq, &initialize); | 2338 __ b(eq, &initialize); |
2343 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2339 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
2344 // write-barrier is needed. | 2340 // write-barrier is needed. |
2345 __ bind(&megamorphic); | 2341 __ bind(&megamorphic); |
2346 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2342 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); |
2347 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); | 2343 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); |
2348 __ str(ip, FieldMemOperand(r5, FixedArray::kHeaderSize)); | 2344 __ str(ip, FieldMemOperand(r5, FixedArray::kHeaderSize)); |
2349 __ jmp(&done); | 2345 __ jmp(&done); |
2350 | 2346 |
2351 // An uninitialized cache is patched with the function | 2347 // An uninitialized cache is patched with the function |
2352 __ bind(&initialize); | 2348 __ bind(&initialize); |
2353 | 2349 |
2354 // Make sure the function is the Array() function | 2350 // Make sure the function is the Array() function |
2355 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r5); | 2351 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r5); |
2356 __ cmp(r1, r5); | 2352 __ cmp(r1, r5); |
2357 __ b(ne, ¬_array_function); | 2353 __ b(ne, ¬_array_function); |
2358 | 2354 |
2359 // The target function is the Array constructor, | 2355 // The target function is the Array constructor, |
2360 // Create an AllocationSite if we don't already have it, store it in the | 2356 // Create an AllocationSite if we don't already have it, store it in the |
2361 // slot. | 2357 // slot. |
2362 CreateAllocationSiteStub create_stub(masm->isolate()); | 2358 CreateAllocationSiteStub create_stub(masm->isolate()); |
2363 CallStubInRecordCallTarget(masm, &create_stub); | 2359 CallStubInRecordCallTarget(masm, &create_stub); |
2364 __ b(&done); | 2360 __ b(&done); |
2365 | 2361 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2410 __ mov(r3, r1); | 2406 __ mov(r3, r1); |
2411 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2407 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
2412 } | 2408 } |
2413 | 2409 |
2414 | 2410 |
2415 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { | 2411 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { |
2416 // r1 - function | 2412 // r1 - function |
2417 // r3 - slot id | 2413 // r3 - slot id |
2418 // r2 - vector | 2414 // r2 - vector |
2419 // r4 - allocation site (loaded from vector[slot]) | 2415 // r4 - allocation site (loaded from vector[slot]) |
2420 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r5); | 2416 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r5); |
2421 __ cmp(r1, r5); | 2417 __ cmp(r1, r5); |
2422 __ b(ne, miss); | 2418 __ b(ne, miss); |
2423 | 2419 |
2424 __ mov(r0, Operand(arg_count())); | 2420 __ mov(r0, Operand(arg_count())); |
2425 | 2421 |
2426 // Increment the call count for monomorphic function calls. | 2422 // Increment the call count for monomorphic function calls. |
2427 __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2423 __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); |
2428 __ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize)); | 2424 __ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize)); |
2429 __ ldr(r3, FieldMemOperand(r2, 0)); | 2425 __ ldr(r3, FieldMemOperand(r2, 0)); |
2430 __ add(r3, r3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); | 2426 __ add(r3, r3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2537 | 2533 |
2538 // We are going monomorphic, provided we actually have a JSFunction. | 2534 // We are going monomorphic, provided we actually have a JSFunction. |
2539 __ JumpIfSmi(r1, &miss); | 2535 __ JumpIfSmi(r1, &miss); |
2540 | 2536 |
2541 // Goto miss case if we do not have a function. | 2537 // Goto miss case if we do not have a function. |
2542 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 2538 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
2543 __ b(ne, &miss); | 2539 __ b(ne, &miss); |
2544 | 2540 |
2545 // Make sure the function is not the Array() function, which requires special | 2541 // Make sure the function is not the Array() function, which requires special |
2546 // behavior on MISS. | 2542 // behavior on MISS. |
2547 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | 2543 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r4); |
2548 __ cmp(r1, r4); | 2544 __ cmp(r1, r4); |
2549 __ b(eq, &miss); | 2545 __ b(eq, &miss); |
2550 | 2546 |
2551 // Make sure the function belongs to the same native context (which implies | 2547 // Make sure the function belongs to the same native context. |
2552 // the same global object). | |
2553 __ ldr(r4, FieldMemOperand(r1, JSFunction::kContextOffset)); | 2548 __ ldr(r4, FieldMemOperand(r1, JSFunction::kContextOffset)); |
2554 __ ldr(r4, ContextOperand(r4, Context::GLOBAL_OBJECT_INDEX)); | 2549 __ ldr(r4, ContextMemOperand(r4, Context::NATIVE_CONTEXT_INDEX)); |
2555 __ ldr(ip, GlobalObjectOperand()); | 2550 __ ldr(ip, NativeContextMemOperand()); |
2556 __ cmp(r4, ip); | 2551 __ cmp(r4, ip); |
2557 __ b(ne, &miss); | 2552 __ b(ne, &miss); |
2558 | 2553 |
2559 // Update stats. | 2554 // Update stats. |
2560 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); | 2555 __ ldr(r4, FieldMemOperand(r2, with_types_offset)); |
2561 __ add(r4, r4, Operand(Smi::FromInt(1))); | 2556 __ add(r4, r4, Operand(Smi::FromInt(1))); |
2562 __ str(r4, FieldMemOperand(r2, with_types_offset)); | 2557 __ str(r4, FieldMemOperand(r2, with_types_offset)); |
2563 | 2558 |
2564 // Initialize the call counter. | 2559 // Initialize the call counter. |
2565 __ Move(r5, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); | 2560 __ Move(r5, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); |
(...skipping 2339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4905 } | 4900 } |
4906 | 4901 |
4907 | 4902 |
4908 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | 4903 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { |
4909 Register context = cp; | 4904 Register context = cp; |
4910 Register result = r0; | 4905 Register result = r0; |
4911 Register slot = r2; | 4906 Register slot = r2; |
4912 | 4907 |
4913 // Go up the context chain to the script context. | 4908 // Go up the context chain to the script context. |
4914 for (int i = 0; i < depth(); ++i) { | 4909 for (int i = 0; i < depth(); ++i) { |
4915 __ ldr(result, ContextOperand(context, Context::PREVIOUS_INDEX)); | 4910 __ ldr(result, ContextMemOperand(context, Context::PREVIOUS_INDEX)); |
4916 context = result; | 4911 context = result; |
4917 } | 4912 } |
4918 | 4913 |
4919 // Load the PropertyCell value at the specified slot. | 4914 // Load the PropertyCell value at the specified slot. |
4920 __ add(result, context, Operand(slot, LSL, kPointerSizeLog2)); | 4915 __ add(result, context, Operand(slot, LSL, kPointerSizeLog2)); |
4921 __ ldr(result, ContextOperand(result)); | 4916 __ ldr(result, ContextMemOperand(result)); |
4922 __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 4917 __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
4923 | 4918 |
4924 // If the result is not the_hole, return. Otherwise, handle in the runtime. | 4919 // If the result is not the_hole, return. Otherwise, handle in the runtime. |
4925 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 4920 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
4926 __ Ret(ne); | 4921 __ Ret(ne); |
4927 | 4922 |
4928 // Fallback to runtime. | 4923 // Fallback to runtime. |
4929 __ SmiTag(slot); | 4924 __ SmiTag(slot); |
4930 __ push(slot); | 4925 __ push(slot); |
4931 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1, 1); | 4926 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1, 1); |
(...skipping 15 matching lines...) Expand all Loading... |
4947 | 4942 |
4948 Label fast_heapobject_case, fast_smi_case, slow_case; | 4943 Label fast_heapobject_case, fast_smi_case, slow_case; |
4949 | 4944 |
4950 if (FLAG_debug_code) { | 4945 if (FLAG_debug_code) { |
4951 __ CompareRoot(value, Heap::kTheHoleValueRootIndex); | 4946 __ CompareRoot(value, Heap::kTheHoleValueRootIndex); |
4952 __ Check(ne, kUnexpectedValue); | 4947 __ Check(ne, kUnexpectedValue); |
4953 } | 4948 } |
4954 | 4949 |
4955 // Go up the context chain to the script context. | 4950 // Go up the context chain to the script context. |
4956 for (int i = 0; i < depth(); i++) { | 4951 for (int i = 0; i < depth(); i++) { |
4957 __ ldr(context_temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 4952 __ ldr(context_temp, ContextMemOperand(context, Context::PREVIOUS_INDEX)); |
4958 context = context_temp; | 4953 context = context_temp; |
4959 } | 4954 } |
4960 | 4955 |
4961 // Load the PropertyCell at the specified slot. | 4956 // Load the PropertyCell at the specified slot. |
4962 __ add(cell, context, Operand(slot, LSL, kPointerSizeLog2)); | 4957 __ add(cell, context, Operand(slot, LSL, kPointerSizeLog2)); |
4963 __ ldr(cell, ContextOperand(cell)); | 4958 __ ldr(cell, ContextMemOperand(cell)); |
4964 | 4959 |
4965 // Load PropertyDetails for the cell (actually only the cell_type and kind). | 4960 // Load PropertyDetails for the cell (actually only the cell_type and kind). |
4966 __ ldr(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset)); | 4961 __ ldr(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset)); |
4967 __ SmiUntag(cell_details); | 4962 __ SmiUntag(cell_details); |
4968 __ and_(cell_details, cell_details, | 4963 __ and_(cell_details, cell_details, |
4969 Operand(PropertyDetails::PropertyCellTypeField::kMask | | 4964 Operand(PropertyDetails::PropertyCellTypeField::kMask | |
4970 PropertyDetails::KindField::kMask | | 4965 PropertyDetails::KindField::kMask | |
4971 PropertyDetails::kAttributesReadOnlyMask)); | 4966 PropertyDetails::kAttributesReadOnlyMask)); |
4972 | 4967 |
4973 // Check if PropertyCell holds mutable data. | 4968 // Check if PropertyCell holds mutable data. |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5372 MemOperand(fp, 6 * kPointerSize), NULL); | 5367 MemOperand(fp, 6 * kPointerSize), NULL); |
5373 } | 5368 } |
5374 | 5369 |
5375 | 5370 |
5376 #undef __ | 5371 #undef __ |
5377 | 5372 |
5378 } // namespace internal | 5373 } // namespace internal |
5379 } // namespace v8 | 5374 } // namespace v8 |
5380 | 5375 |
5381 #endif // V8_TARGET_ARCH_ARM | 5376 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |