| 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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 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 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, | 1858 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, |
| 1859 FixedArray::kHeaderSize)); | 1859 FixedArray::kHeaderSize)); |
| 1860 | 1860 |
| 1861 // A monomorphic cache hit or an already megamorphic state: invoke the | 1861 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 1862 // function without changing the state. | 1862 // function without changing the state. |
| 1863 __ cmp(ecx, edi); | 1863 __ cmp(ecx, edi); |
| 1864 __ j(equal, &done, Label::kFar); | 1864 __ j(equal, &done, Label::kFar); |
| 1865 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); | 1865 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); |
| 1866 __ j(equal, &done, Label::kFar); | 1866 __ j(equal, &done, Label::kFar); |
| 1867 | 1867 |
| 1868 if (!FLAG_pretenuring_call_new) { | 1868 if (!FLAG_pretenuring_call_new && FLAG_allocation_site_transitioning) { |
| 1869 // If we came here, we need to see if we are the array function. | 1869 // If we came here, we need to see if we are the array function. |
| 1870 // If we didn't have a matching function, and we didn't find the megamorph | 1870 // If we didn't have a matching function, and we didn't find the megamorph |
| 1871 // sentinel, then we have in the slot either some other function or an | 1871 // sentinel, then we have in the slot either some other function or an |
| 1872 // AllocationSite. Do a map check on the object in ecx. | 1872 // AllocationSite. Do a map check on the object in ecx. |
| 1873 Handle<Map> allocation_site_map = isolate->factory()->allocation_site_map(); | 1873 Handle<Map> allocation_site_map = isolate->factory()->allocation_site_map(); |
| 1874 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); | 1874 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); |
| 1875 __ j(not_equal, &miss); | 1875 __ j(not_equal, &miss); |
| 1876 | 1876 |
| 1877 // Make sure the function is the Array() function | 1877 // Make sure the function is the Array() function |
| 1878 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); | 1878 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1891 // write-barrier is needed. | 1891 // write-barrier is needed. |
| 1892 __ bind(&megamorphic); | 1892 __ bind(&megamorphic); |
| 1893 __ mov( | 1893 __ mov( |
| 1894 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), | 1894 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), |
| 1895 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); | 1895 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); |
| 1896 __ jmp(&done, Label::kFar); | 1896 __ jmp(&done, Label::kFar); |
| 1897 | 1897 |
| 1898 // An uninitialized cache is patched with the function or sentinel to | 1898 // An uninitialized cache is patched with the function or sentinel to |
| 1899 // indicate the ElementsKind if function is the Array constructor. | 1899 // indicate the ElementsKind if function is the Array constructor. |
| 1900 __ bind(&initialize); | 1900 __ bind(&initialize); |
| 1901 if (!FLAG_pretenuring_call_new) { | 1901 if (!FLAG_pretenuring_call_new && FLAG_allocation_site_transitioning) { |
| 1902 // Make sure the function is the Array() function | 1902 // Make sure the function is the Array() function |
| 1903 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); | 1903 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); |
| 1904 __ cmp(edi, ecx); | 1904 __ cmp(edi, ecx); |
| 1905 __ j(not_equal, ¬_array_function); | 1905 __ j(not_equal, ¬_array_function); |
| 1906 | 1906 |
| 1907 // The target function is the Array constructor, | 1907 // The target function is the Array constructor, |
| 1908 // Create an AllocationSite if we don't already have it, store it in the | 1908 // Create an AllocationSite if we don't already have it, store it in the |
| 1909 // slot. | 1909 // slot. |
| 1910 { | 1910 { |
| 1911 FrameScope scope(masm, StackFrame::INTERNAL); | 1911 FrameScope scope(masm, StackFrame::INTERNAL); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 | 2080 |
| 2081 if (RecordCallTarget()) { | 2081 if (RecordCallTarget()) { |
| 2082 GenerateRecordCallTarget(masm); | 2082 GenerateRecordCallTarget(masm); |
| 2083 | 2083 |
| 2084 if (FLAG_pretenuring_call_new) { | 2084 if (FLAG_pretenuring_call_new) { |
| 2085 // Put the AllocationSite from the feedback vector into ebx. | 2085 // Put the AllocationSite from the feedback vector into ebx. |
| 2086 // By adding kPointerSize we encode that we know the AllocationSite | 2086 // By adding kPointerSize we encode that we know the AllocationSite |
| 2087 // entry is at the feedback vector slot given by edx + 1. | 2087 // entry is at the feedback vector slot given by edx + 1. |
| 2088 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, | 2088 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, |
| 2089 FixedArray::kHeaderSize + kPointerSize)); | 2089 FixedArray::kHeaderSize + kPointerSize)); |
| 2090 } else { | 2090 } else if (FLAG_allocation_site_transitioning) { |
| 2091 Label feedback_register_initialized; | 2091 Label feedback_register_initialized; |
| 2092 // Put the AllocationSite from the feedback vector into ebx, or undefined. | 2092 // Put the AllocationSite from the feedback vector into ebx, or undefined. |
| 2093 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, | 2093 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, |
| 2094 FixedArray::kHeaderSize)); | 2094 FixedArray::kHeaderSize)); |
| 2095 Handle<Map> allocation_site_map = | 2095 Handle<Map> allocation_site_map = |
| 2096 isolate()->factory()->allocation_site_map(); | 2096 isolate()->factory()->allocation_site_map(); |
| 2097 __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map)); | 2097 __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map)); |
| 2098 __ j(equal, &feedback_register_initialized); | 2098 __ j(equal, &feedback_register_initialized); |
| 2099 __ mov(ebx, isolate()->factory()->undefined_value()); | 2099 __ mov(ebx, isolate()->factory()->undefined_value()); |
| 2100 __ bind(&feedback_register_initialized); | 2100 __ bind(&feedback_register_initialized); |
| 2101 } else { |
| 2102 __ mov(ebx, isolate()->factory()->undefined_value()); |
| 2101 } | 2103 } |
| 2102 | 2104 |
| 2103 __ AssertUndefinedOrAllocationSite(ebx); | 2105 __ AssertUndefinedOrAllocationSite(ebx); |
| 2104 } | 2106 } |
| 2105 | 2107 |
| 2106 // Jump to the function-specific construct stub. | 2108 // Jump to the function-specific construct stub. |
| 2107 Register jmp_reg = ecx; | 2109 Register jmp_reg = ecx; |
| 2108 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2110 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 2109 __ mov(jmp_reg, FieldOperand(jmp_reg, | 2111 __ mov(jmp_reg, FieldOperand(jmp_reg, |
| 2110 SharedFunctionInfo::kConstructStubOffset)); | 2112 SharedFunctionInfo::kConstructStubOffset)); |
| (...skipping 2322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4433 // Will both indicate a NULL and a Smi. | 4435 // Will both indicate a NULL and a Smi. |
| 4434 __ test(ecx, Immediate(kSmiTagMask)); | 4436 __ test(ecx, Immediate(kSmiTagMask)); |
| 4435 __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); | 4437 __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); |
| 4436 __ CmpObjectType(ecx, MAP_TYPE, ecx); | 4438 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
| 4437 __ Assert(equal, kUnexpectedInitialMapForArrayFunction); | 4439 __ Assert(equal, kUnexpectedInitialMapForArrayFunction); |
| 4438 | 4440 |
| 4439 // We should either have undefined in ebx or a valid AllocationSite | 4441 // We should either have undefined in ebx or a valid AllocationSite |
| 4440 __ AssertUndefinedOrAllocationSite(ebx); | 4442 __ AssertUndefinedOrAllocationSite(ebx); |
| 4441 } | 4443 } |
| 4442 | 4444 |
| 4443 Label no_info; | 4445 if (FLAG_allocation_site_transitioning) { |
| 4444 // If the feedback vector is the undefined value call an array constructor | 4446 Label no_info; |
| 4445 // that doesn't use AllocationSites. | 4447 // If the feedback vector is the undefined value call an array constructor |
| 4446 __ cmp(ebx, isolate()->factory()->undefined_value()); | 4448 // that doesn't use AllocationSites. |
| 4447 __ j(equal, &no_info); | 4449 __ cmp(ebx, isolate()->factory()->undefined_value()); |
| 4450 __ j(equal, &no_info); |
| 4448 | 4451 |
| 4449 // Only look at the lower 16 bits of the transition info. | 4452 // Only look at the lower 16 bits of the transition info. |
| 4450 __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset)); | 4453 __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset)); |
| 4451 __ SmiUntag(edx); | 4454 __ SmiUntag(edx); |
| 4452 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 4455 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
| 4453 __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask)); | 4456 __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask)); |
| 4454 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 4457 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 4455 | 4458 |
| 4456 __ bind(&no_info); | 4459 __ bind(&no_info); |
| 4460 } |
| 4461 |
| 4457 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); | 4462 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
| 4458 } | 4463 } |
| 4459 | 4464 |
| 4460 | 4465 |
| 4461 void InternalArrayConstructorStub::GenerateCase( | 4466 void InternalArrayConstructorStub::GenerateCase( |
| 4462 MacroAssembler* masm, ElementsKind kind) { | 4467 MacroAssembler* masm, ElementsKind kind) { |
| 4463 Label not_zero_case, not_one_case; | 4468 Label not_zero_case, not_one_case; |
| 4464 Label normal_sequence; | 4469 Label normal_sequence; |
| 4465 | 4470 |
| 4466 __ test(eax, eax); | 4471 __ test(eax, eax); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4702 Operand(ebp, 7 * kPointerSize), | 4707 Operand(ebp, 7 * kPointerSize), |
| 4703 NULL); | 4708 NULL); |
| 4704 } | 4709 } |
| 4705 | 4710 |
| 4706 | 4711 |
| 4707 #undef __ | 4712 #undef __ |
| 4708 | 4713 |
| 4709 } } // namespace v8::internal | 4714 } } // namespace v8::internal |
| 4710 | 4715 |
| 4711 #endif // V8_TARGET_ARCH_IA32 | 4716 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |