Index: src/arm64/code-stubs-arm64.cc |
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc |
index abc047a127b64172889b95a0010ac7202bdf9c98..5e2e79ce47c6639a5f20ff7e581dd17439a57fa3 100644 |
--- a/src/arm64/code-stubs-arm64.cc |
+++ b/src/arm64/code-stubs-arm64.cc |
@@ -2730,16 +2730,32 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
} |
-static void GenerateRecordCallTarget(MacroAssembler* masm, |
- Register argc, |
+static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, |
+ Register argc, Register function, |
+ Register feedback_vector, |
+ Register index) { |
+ FrameScope scope(masm, StackFrame::INTERNAL); |
+ |
+ // Arguments register must be smi-tagged to call out. |
+ __ SmiTag(argc); |
+ __ Push(argc, function, feedback_vector, index); |
+ |
+ DCHECK(feedback_vector.Is(x2) && index.Is(x3)); |
+ __ CallStub(stub); |
+ |
+ __ Pop(index, feedback_vector, function, argc); |
+ __ SmiUntag(argc); |
+} |
+ |
+ |
+static void GenerateRecordCallTarget(MacroAssembler* masm, Register argc, |
Register function, |
- Register feedback_vector, |
- Register index, |
- Register scratch1, |
- Register scratch2) { |
+ Register feedback_vector, Register index, |
+ Register scratch1, Register scratch2, |
+ Register scratch3) { |
ASM_LOCATION("GenerateRecordCallTarget"); |
- DCHECK(!AreAliased(scratch1, scratch2, |
- argc, function, feedback_vector, index)); |
+ DCHECK(!AreAliased(scratch1, scratch2, scratch3, argc, function, |
+ feedback_vector, index)); |
// Cache the called function in a feedback vector slot. Cache states are |
// uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. |
// argc : number of arguments to the construct function |
@@ -2754,22 +2770,37 @@ static void GenerateRecordCallTarget(MacroAssembler* masm, |
masm->isolate()->heap()->uninitialized_symbol()); |
// Load the cache state. |
- __ Add(scratch1, feedback_vector, |
+ Register feedback = scratch1; |
+ Register feedback_map = scratch2; |
+ Register feedback_value = scratch3; |
+ __ Add(feedback, feedback_vector, |
Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
- __ Ldr(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
+ __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); |
// A monomorphic cache hit or an already megamorphic state: invoke the |
// function without changing the state. |
- __ Cmp(scratch1, function); |
+ Label check_allocation_site; |
+ __ Ldr(feedback_value, FieldMemOperand(feedback, WeakCell::kValueOffset)); |
+ __ Cmp(function, feedback_value); |
__ B(eq, &done); |
+ __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); |
+ __ B(eq, &done); |
+ __ Ldr(feedback_map, FieldMemOperand(feedback, 0)); |
+ __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); |
+ __ B(ne, FLAG_pretenuring_call_new ? &miss : &check_allocation_site); |
+ |
+ // If function is not equal to the weak cell value, and the weak cell value is |
+ // cleared, we have a new chance to become monomorphic. |
+ __ JumpIfSmi(feedback_value, &initialize); |
+ __ B(&megamorphic); |
if (!FLAG_pretenuring_call_new) { |
+ __ bind(&check_allocation_site); |
// If we came here, we need to see if we are the array function. |
// If we didn't have a matching function, and we didn't find the megamorph |
// sentinel, then we have in the slot either some other function or an |
// AllocationSite. Do a map check on the object in scratch1 register. |
- __ Ldr(scratch2, FieldMemOperand(scratch1, AllocationSite::kMapOffset)); |
- __ JumpIfNotRoot(scratch2, Heap::kAllocationSiteMapRootIndex, &miss); |
+ __ JumpIfNotRoot(feedback_map, Heap::kAllocationSiteMapRootIndex, &miss); |
// Make sure the function is the Array() function |
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); |
@@ -2805,39 +2836,17 @@ static void GenerateRecordCallTarget(MacroAssembler* masm, |
// The target function is the Array constructor, |
// Create an AllocationSite if we don't already have it, store it in the |
// slot. |
- { |
- FrameScope scope(masm, StackFrame::INTERNAL); |
- CreateAllocationSiteStub create_stub(masm->isolate()); |
- |
- // Arguments register must be smi-tagged to call out. |
- __ SmiTag(argc); |
- __ Push(argc, function, feedback_vector, index); |
- |
- // CreateAllocationSiteStub expect the feedback vector in x2 and the slot |
- // index in x3. |
- DCHECK(feedback_vector.Is(x2) && index.Is(x3)); |
- __ CallStub(&create_stub); |
- |
- __ Pop(index, feedback_vector, function, argc); |
- __ SmiUntag(argc); |
- } |
+ CreateAllocationSiteStub create_stub(masm->isolate()); |
+ CallStubInRecordCallTarget(masm, &create_stub, argc, function, |
+ feedback_vector, index); |
__ B(&done); |
__ Bind(¬_array_function); |
} |
- // An uninitialized cache is patched with the function. |
- |
- __ Add(scratch1, feedback_vector, |
- Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
- __ Add(scratch1, scratch1, FixedArray::kHeaderSize - kHeapObjectTag); |
- __ Str(function, MemOperand(scratch1, 0)); |
- |
- __ Push(function); |
- __ RecordWrite(feedback_vector, scratch1, function, kLRHasNotBeenSaved, |
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
- __ Pop(function); |
- |
+ CreateWeakCellStub create_stub(masm->isolate()); |
+ CallStubInRecordCallTarget(masm, &create_stub, argc, function, |
+ feedback_vector, index); |
__ Bind(&done); |
} |
@@ -2976,7 +2985,7 @@ void CallConstructStub::Generate(MacroAssembler* masm) { |
&slow); |
if (RecordCallTarget()) { |
- GenerateRecordCallTarget(masm, x0, function, x2, x3, x4, x5); |
+ GenerateRecordCallTarget(masm, x0, function, x2, x3, x4, x5, x11); |
__ Add(x5, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); |
if (FLAG_pretenuring_call_new) { |