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