| Index: src/a64/code-stubs-a64.cc
|
| diff --git a/src/a64/code-stubs-a64.cc b/src/a64/code-stubs-a64.cc
|
| index d444fa4700d23767c21482b7cd053a3e16bd5e69..02ee787be9b905b34ce999fb770aecc77cffab4b 100644
|
| --- a/src/a64/code-stubs-a64.cc
|
| +++ b/src/a64/code-stubs-a64.cc
|
| @@ -27,7 +27,7 @@
|
|
|
| #include "v8.h"
|
|
|
| -#if defined(V8_TARGET_ARCH_A64)
|
| +#if V8_TARGET_ARCH_A64
|
|
|
| #include "bootstrapper.h"
|
| #include "code-stubs.h"
|
| @@ -67,6 +67,17 @@ void FastCloneShallowObjectStub::InitializeInterfaceDescriptor(
|
| }
|
|
|
|
|
| +void CreateAllocationSiteStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + // x2: cache cell
|
| + static Register registers[] = { x2 };
|
| + descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
|
| + descriptor->register_params_ = registers;
|
| + descriptor->deoptimization_handler_ = NULL;
|
| +}
|
| +
|
| +
|
| void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
|
| Isolate* isolate,
|
| CodeStubInterfaceDescriptor* descriptor) {
|
| @@ -240,6 +251,31 @@ void ToBooleanStub::InitializeInterfaceDescriptor(
|
| }
|
|
|
|
|
| +void UnaryOpStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + // x0: value
|
| + static Register registers[] = { x0 };
|
| + descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
|
| + descriptor->register_params_ = registers;
|
| + descriptor->deoptimization_handler_ = FUNCTION_ADDR(UnaryOpIC_Miss);
|
| +}
|
| +
|
| +
|
| +void StoreGlobalStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + // x1: receiver
|
| + // x2: key (unused)
|
| + // x0: value
|
| + static Register registers[] = { x1, x2, x0 };
|
| + descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
|
| + descriptor->register_params_ = registers;
|
| + descriptor->deoptimization_handler_ =
|
| + FUNCTION_ADDR(StoreIC_MissFromStubFailure);
|
| +}
|
| +
|
| +
|
| #define __ ACCESS_MASM(masm)
|
|
|
|
|
| @@ -1047,6 +1083,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
|
| GenerateMiss(masm);
|
| }
|
|
|
| +
|
| void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
|
| // Preserve caller-saved registers x0-x7 and x10-x15. We don't care if x8, x9,
|
| // ip0 and ip1 are corrupted by the call into C.
|
| @@ -1087,247 +1124,6 @@ void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
|
| }
|
|
|
|
|
| -void UnaryOpStub::PrintName(StringStream* stream) {
|
| - const char* op_name = Token::Name(op_);
|
| - const char* overwrite_name = NULL;
|
| - switch (mode_) {
|
| - case UNARY_NO_OVERWRITE:
|
| - overwrite_name = "Alloc";
|
| - break;
|
| - case UNARY_OVERWRITE:
|
| - overwrite_name = "Overwrite";
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| - stream->Add("UnaryOpStub_%s_%s_%s",
|
| - op_name,
|
| - overwrite_name,
|
| - UnaryOpIC::GetName(operand_type_));
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::Generate(MacroAssembler* masm) {
|
| - switch (operand_type_) {
|
| - case UnaryOpIC::UNINITIALIZED:
|
| - GenerateTypeTransition(masm);
|
| - break;
|
| - case UnaryOpIC::SMI:
|
| - GenerateSmiStub(masm);
|
| - break;
|
| - case UnaryOpIC::NUMBER:
|
| - GenerateNumberStub(masm);
|
| - break;
|
| - case UnaryOpIC::GENERIC:
|
| - GenerateGenericStub(masm);
|
| - break;
|
| - }
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
| - __ Mov(x1, Operand(Smi::FromInt(op_)));
|
| - __ Mov(x2, Operand(Smi::FromInt(mode_)));
|
| - __ Mov(x3, Operand(Smi::FromInt(operand_type_)));
|
| - // x0 contains the operand
|
| - __ Push(x0, x1, x2, x3);
|
| -
|
| - __ TailCallExternalReference(
|
| - ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
| - switch (op_) {
|
| - case Token::SUB:
|
| - GenerateSmiStubSub(masm);
|
| - break;
|
| - case Token::BIT_NOT:
|
| - GenerateSmiStubBitNot(masm);
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
| - Label non_smi, slow;
|
| - GenerateSmiCodeSub(masm, &non_smi, &slow);
|
| - __ Bind(&non_smi);
|
| - __ Bind(&slow);
|
| - GenerateTypeTransition(masm);
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
| - Label non_smi;
|
| - GenerateSmiCodeBitNot(masm, &non_smi);
|
| - __ Bind(&non_smi);
|
| - GenerateTypeTransition(masm);
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
| - Label* non_smi,
|
| - Label* slow) {
|
| - __ JumpIfNotSmi(x0, non_smi);
|
| -
|
| - // The result of negating zero or the smallest negative smi is not a smi.
|
| - __ Ands(x1, x0, 0x7fffffff00000000UL);
|
| - __ B(eq, slow);
|
| -
|
| - __ Neg(x0, x0);
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
| - Label* non_smi) {
|
| - __ JumpIfNotSmi(x0, non_smi);
|
| -
|
| - // Eor the top 32 bits with 0xffffffff to invert.
|
| - __ Eor(x0, x0, 0xffffffff00000000UL);
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
|
| - switch (op_) {
|
| - case Token::SUB:
|
| - GenerateNumberStubSub(masm);
|
| - break;
|
| - case Token::BIT_NOT:
|
| - GenerateNumberStubBitNot(masm);
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
|
| - Label non_smi, slow, call_builtin;
|
| - GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
|
| - __ Bind(&non_smi);
|
| - GenerateHeapNumberCodeSub(masm, &slow);
|
| - __ Bind(&slow);
|
| - GenerateTypeTransition(masm);
|
| - __ Bind(&call_builtin);
|
| - __ Push(x0);
|
| - __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) {
|
| - Label non_smi, slow;
|
| - GenerateSmiCodeBitNot(masm, &non_smi);
|
| - __ Bind(&non_smi);
|
| - GenerateHeapNumberCodeBitNot(masm, &slow);
|
| - __ Bind(&slow);
|
| - GenerateTypeTransition(masm);
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
| - Label* slow) {
|
| - Register heap_num = x0;
|
| - Register heap_num_map = x1;
|
| -
|
| - __ LoadRoot(heap_num_map, Heap::kHeapNumberMapRootIndex);
|
| - __ JumpIfNotHeapNumber(heap_num, slow, heap_num_map);
|
| -
|
| - if (mode_ == UNARY_OVERWRITE) {
|
| - Register exponent = w2;
|
| -
|
| - // Flip the sign bit of the existing heap number.
|
| - __ Ldr(exponent, FieldMemOperand(heap_num, HeapNumber::kExponentOffset));
|
| - __ Eor(exponent, exponent, HeapNumber::kSignMask);
|
| - __ Str(exponent, FieldMemOperand(heap_num, HeapNumber::kExponentOffset));
|
| - } else {
|
| - Register allocated_num = x0;
|
| - Register double_bits = x2;
|
| - Register heap_num_orig = x3;
|
| -
|
| - __ Mov(heap_num_orig, heap_num);
|
| -
|
| - // Create a new heap number.
|
| - Label slow_allocate_heapnumber, heapnumber_allocated;
|
| - __ AllocateHeapNumber(allocated_num, &slow_allocate_heapnumber, x6, x7,
|
| - heap_num_map);
|
| - __ B(&heapnumber_allocated);
|
| -
|
| - __ Bind(&slow_allocate_heapnumber);
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| - __ Push(heap_num_orig);
|
| - __ CallRuntime(Runtime::kNumberAlloc, 0);
|
| - __ Pop(heap_num_orig);
|
| - // allocated_num is x0, so contains the result of the runtime allocation.
|
| - }
|
| -
|
| - __ Bind(&heapnumber_allocated);
|
| - // Load the original heap number as a double precision float, and flip the
|
| - // sign bit.
|
| - STATIC_ASSERT(HeapNumber::kExponentOffset ==
|
| - (HeapNumber::kMantissaOffset + 4));
|
| - __ Ldr(double_bits, FieldMemOperand(heap_num_orig,
|
| - HeapNumber::kMantissaOffset));
|
| - __ Eor(double_bits, double_bits, Double::kSignMask);
|
| -
|
| - // Store the negated double to the newly allocated heap number.
|
| - __ Str(double_bits, FieldMemOperand(allocated_num,
|
| - HeapNumber::kValueOffset));
|
| - }
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
|
| - Label* slow) {
|
| - Register heap_num = x0;
|
| - Register smi_num = x0;
|
| -
|
| - __ JumpIfNotHeapNumber(heap_num, slow);
|
| -
|
| - // Convert the heap number to a smi.
|
| - __ HeapNumberECMA262ToInt32(smi_num, heap_num, x6, x7, d0,
|
| - MacroAssembler::SMI);
|
| -
|
| - // Eor the top 32 bits with 0xffffffff to invert.
|
| - __ Eor(x0, smi_num, 0xffffffff00000000UL);
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
| - switch (op_) {
|
| - case Token::SUB: {
|
| - Label non_smi, slow;
|
| - GenerateSmiCodeSub(masm, &non_smi, &slow);
|
| - __ Bind(&non_smi);
|
| - GenerateHeapNumberCodeSub(masm, &slow);
|
| - __ Bind(&slow);
|
| - __ Push(x0);
|
| - __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
|
| - break;
|
| - }
|
| - case Token::BIT_NOT: {
|
| - Label non_smi, slow;
|
| - GenerateSmiCodeBitNot(masm, &non_smi);
|
| - __ Bind(&non_smi);
|
| - GenerateHeapNumberCodeBitNot(masm, &slow);
|
| - __ Bind(&slow);
|
| - __ Push(x0);
|
| - __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
|
| - break;
|
| - }
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -}
|
| -
|
| -
|
| void BinaryOpStub::Initialize() {
|
| // Nothing to do here.
|
| }
|
| @@ -2508,6 +2304,7 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
|
| StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
|
| RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
|
| ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
|
| + CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
|
| }
|
|
|
|
|
| @@ -2752,6 +2549,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
| masm->set_use_real_aborts(false);
|
|
|
| ASM_LOCATION("CEntryStub::Generate entry");
|
| + ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
| +
|
| // Register parameters:
|
| // x0: argc (including receiver, untagged)
|
| // x1: target
|
| @@ -4477,17 +4276,14 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {
|
| // function without changing the state.
|
| __ Cmp(x3, x1);
|
| __ B(eq, &done);
|
| - __ JumpIfRoot(x3, Heap::kUndefinedValueRootIndex, &done);
|
| -
|
| - // Special handling of the Array() function, which caches not only the
|
| - // monomorphic Array function but the initial ElementsKind with special
|
| - // sentinels
|
| - Handle<Object> terminal_kind_sentinel =
|
| - TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
|
| - LAST_FAST_ELEMENTS_KIND);
|
| - __ JumpIfNotSmi(x3, &miss);
|
| - __ Cmp(x3, Operand(terminal_kind_sentinel));
|
| - __ B(gt, &miss);
|
| +
|
| + // 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 cell either some other function or an
|
| + // AllocationSite. Do a map check on the object in ecx.
|
| + __ Ldr(x5, FieldMemOperand(x3, AllocationSite::kMapOffset));
|
| + __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, &miss);
|
| +
|
| // Make sure the function is the Array() function
|
| __ LoadArrayFunction(x3);
|
| __ Cmp(x1, x3);
|
| @@ -4514,14 +4310,15 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {
|
| __ Cmp(x1, x3);
|
| __ B(ne, ¬_array_function);
|
|
|
| - // The target function is the Array constructor, install a sentinel value in
|
| - // the constructor's type info cell that will track the initial ElementsKind
|
| - // that should be used for the array when its constructed.
|
| - Handle<Object> initial_kind_sentinel =
|
| - TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
|
| - GetInitialFastElementsKind());
|
| - __ Mov(x3, Operand(initial_kind_sentinel));
|
| - __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
|
| + // The target function is the Array constructor,
|
| + // Create an AllocationSite if we don't already have it, store it in the cell
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| + CreateAllocationSiteStub create_stub;
|
| + __ Push(x0, x1, x2);
|
| + __ CallStub(&create_stub);
|
| + __ Pop(x2, x1, x0);
|
| + }
|
| __ B(&done);
|
|
|
| __ Bind(¬_array_function);
|
| @@ -6622,9 +6419,11 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
|
|
|
|
|
| void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
|
| - if (entry_hook_ != NULL) {
|
| - // TODO(all) this needs a literal pool blocking scope and predictable code
|
| - // size.
|
| + if (masm->isolate()->function_entry_hook() != NULL) {
|
| + // TODO(all): This needs to be reliably consistent with
|
| + // kReturnAddressDistanceFromFunctionStart in ::Generate.
|
| + Assembler::BlockConstPoolScope no_const_pools(masm);
|
| + AllowStubCallsScope allow_stub_calls(masm, true);
|
| ProfileEntryHookStub stub;
|
| __ Push(lr);
|
| __ CallStub(&stub);
|
| @@ -6640,22 +6439,24 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
|
| static const int kReturnAddressDistanceFromFunctionStart =
|
| Assembler::kCallSizeWithRelocation + (2 * kInstructionSize);
|
|
|
| - // Save live volatile registers.
|
| - __ Push(lr, x1, x5);
|
| - static const int kNumSavedRegs = 3;
|
| + // Save all kCallerSaved registers (including lr), since this can be called
|
| + // from anywhere.
|
| + // TODO(jbramley): What about FP registers?
|
| + __ PushCPURegList(kCallerSaved);
|
| + ASSERT(kCallerSaved.IncludesAliasOf(lr));
|
| + const int kNumSavedRegs = kCallerSaved.Count();
|
|
|
| // Compute the function's address as the first argument.
|
| __ Sub(x0, lr, kReturnAddressDistanceFromFunctionStart);
|
|
|
| -#if defined(V8_HOST_ARCH_A64)
|
| - __ Mov(x10, Operand(reinterpret_cast<intptr_t>(&entry_hook_)));
|
| - __ Ldr(x10, MemOperand(x10));
|
| +#if V8_HOST_ARCH_A64
|
| + uintptr_t entry_hook =
|
| + reinterpret_cast<uintptr_t>(masm->isolate()->function_entry_hook());
|
| + __ Mov(x10, entry_hook);
|
| #else
|
| // Under the simulator we need to indirect the entry hook through a trampoline
|
| // function at a known address.
|
| - Address trampoline_address = reinterpret_cast<Address>(
|
| - reinterpret_cast<intptr_t>(EntryHookTrampoline));
|
| - ApiFunction dispatcher(trampoline_address);
|
| + ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
|
| __ Mov(x10, Operand(ExternalReference(&dispatcher,
|
| ExternalReference::BUILTIN_CALL,
|
| masm->isolate())));
|
| @@ -6671,7 +6472,7 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
|
| __ CallCFunction(x10, 2, 0);
|
| }
|
|
|
| - __ Pop(x5, x1, lr);
|
| + __ PopCPURegList(kCallerSaved);
|
| __ Ret();
|
| }
|
|
|
| @@ -6992,10 +6793,6 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
|
| STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4);
|
| STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
|
|
|
| - Handle<Object> undefined_sentinel(
|
| - masm->isolate()->heap()->undefined_value(),
|
| - masm->isolate());
|
| -
|
| // Is the low bit set? If so, the array is holey.
|
| Label normal_sequence;
|
| __ Tbnz(kind, 0, &normal_sequence);
|
| @@ -7006,15 +6803,20 @@ static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
|
| __ Cbz(x10, &normal_sequence);
|
|
|
| // We are going to create a holey array, but our kind is non-holey.
|
| - // Fix kind and retry.
|
| + // Fix kind and retry (only if we have an allocation site in the cell).
|
| __ Orr(kind, kind, 1);
|
| - __ Cmp(type_info_cell, Operand(undefined_sentinel));
|
| - __ B(eq, &normal_sequence);
|
| + __ JumpIfRoot(type_info_cell, Heap::kUndefinedValueRootIndex,
|
| + &normal_sequence);
|
| +
|
| + __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kValueOffset));
|
| + __ Ldr(x10, FieldMemOperand(x10, 0));
|
| + __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, &normal_sequence);
|
|
|
| // Save the resulting elements kind in type info.
|
| // TODO(jbramley): Tag and store at the same time.
|
| __ SmiTag(x10, kind);
|
| - __ Str(x10, FieldMemOperand(type_info_cell, kPointerSize));
|
| + __ Ldr(x11, FieldMemOperand(type_info_cell, Cell::kValueOffset));
|
| + __ Str(x10, FieldMemOperand(x11, AllocationSite::kPayloadOffset));
|
|
|
| __ Bind(&normal_sequence);
|
| int last_index = GetSequenceIndexFromFastElementsKind(
|
| @@ -7043,8 +6845,8 @@ static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
|
| ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
|
| T stub(kind);
|
| stub.GetCode(isolate)->set_is_pregenerated(true);
|
| - if (AllocationSiteInfo::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
|
| - T stub1(kind, true);
|
| + if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
|
| + T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES);
|
| stub1.GetCode(isolate)->set_is_pregenerated(true);
|
| }
|
| }
|
| @@ -7084,9 +6886,6 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
|
| // -- sp[0] : return address
|
| // -- sp[4] : last argument
|
| // -----------------------------------
|
| - Handle<Object> undefined_sentinel(
|
| - masm->isolate()->heap()->undefined_value(), masm->isolate());
|
| -
|
| Register argc = x0;
|
| Register constructor = x1;
|
| Register type_info_cell = x2;
|
| @@ -7109,8 +6908,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
|
| // In type_info_cell, we expect either undefined or a valid Cell.
|
| Label okay_here;
|
| Handle<Map> cell_map(masm->isolate()->heap()->global_property_cell_map());
|
| - __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel),
|
| - eq, &okay_here);
|
| + __ JumpIfRoot(type_info_cell, Heap::kUndefinedValueRootIndex, &okay_here);
|
| __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kMapOffset));
|
| __ Cmp(x10, Operand(cell_map));
|
| __ Assert(eq, "Expected property cell in type_info_cell");
|
| @@ -7120,11 +6918,20 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
|
| Register kind = x3;
|
| Label no_info, switch_ready;
|
| // Get the elements kind and case on that.
|
| - __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel),
|
| - eq, &no_info);
|
| + __ JumpIfRoot(type_info_cell, Heap::kUndefinedValueRootIndex, &no_info);
|
| __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset));
|
| - __ JumpIfNotSmi(kind, &no_info);
|
| - __ SmiUntag(kind);
|
| +
|
| + // The type cell may have undefined in its value.
|
| + __ JumpIfRoot(kind, Heap::kUndefinedValueRootIndex, &no_info);
|
| +
|
| + // We should have an allocation site object
|
| + if (FLAG_debug_code) {
|
| + __ Ldr(x10, FieldMemOperand(kind, AllocationSite::kMapOffset));
|
| + __ CompareRoot(x10, Heap::kAllocationSiteMapRootIndex);
|
| + __ Assert(eq, "Expected AllocationSite object.");
|
| + }
|
| +
|
| + __ Ldrsw(kind, UntagSmiFieldMemOperand(kind, AllocationSite::kPayloadOffset));
|
| __ B(&switch_ready);
|
|
|
| __ Bind(&no_info);
|
|
|