| Index: src/ic/arm64/ic-arm64.cc
|
| diff --git a/src/ic/arm64/ic-arm64.cc b/src/ic/arm64/ic-arm64.cc
|
| index 790917fcdf223b54473bfa4d02b4f07a2864b852..0ced207d8a5bdaa5eee1fc4b6333e37c3300f547 100644
|
| --- a/src/ic/arm64/ic-arm64.cc
|
| +++ b/src/ic/arm64/ic-arm64.cc
|
| @@ -15,18 +15,6 @@ namespace internal {
|
|
|
| #define __ ACCESS_MASM(masm)
|
|
|
| -
|
| -// "type" holds an instance type on entry and is not clobbered.
|
| -// Generated code branch on "global_object" if type is any kind of global
|
| -// JS object.
|
| -static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type,
|
| - Label* global_object) {
|
| - __ Cmp(type, JS_GLOBAL_OBJECT_TYPE);
|
| - __ Ccmp(type, JS_GLOBAL_PROXY_TYPE, ZFlag, ne);
|
| - __ B(eq, global_object);
|
| -}
|
| -
|
| -
|
| // Helper function used from LoadIC GenerateNormal.
|
| //
|
| // elements: Property dictionary. It is not clobbered if a jump to the miss
|
| @@ -116,144 +104,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss,
|
| kDontSaveFPRegs);
|
| }
|
|
|
| -
|
| -// Checks the receiver for special cases (value type, slow case bits).
|
| -// Falls through for regular JS object and return the map of the
|
| -// receiver in 'map_scratch' if the receiver is not a SMI.
|
| -static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
|
| - Register receiver,
|
| - Register map_scratch,
|
| - Register scratch,
|
| - int interceptor_bit, Label* slow) {
|
| - DCHECK(!AreAliased(map_scratch, scratch));
|
| -
|
| - // Check that the object isn't a smi.
|
| - __ JumpIfSmi(receiver, slow);
|
| - // Get the map of the receiver.
|
| - __ Ldr(map_scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - // Check bit field.
|
| - __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kBitFieldOffset));
|
| - __ Tbnz(scratch, Map::kIsAccessCheckNeeded, slow);
|
| - __ Tbnz(scratch, interceptor_bit, slow);
|
| -
|
| - // Check that the object is some kind of JS object EXCEPT JS Value type.
|
| - // In the case that the object is a value-wrapper object, we enter the
|
| - // runtime system to make sure that indexing into string objects work
|
| - // as intended.
|
| - STATIC_ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
|
| - __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kInstanceTypeOffset));
|
| - __ Cmp(scratch, JS_OBJECT_TYPE);
|
| - __ B(lt, slow);
|
| -}
|
| -
|
| -
|
| -// Loads an indexed element from a fast case array.
|
| -//
|
| -// receiver - holds the receiver on entry.
|
| -// Unchanged unless 'result' is the same register.
|
| -//
|
| -// key - holds the smi key on entry.
|
| -// Unchanged unless 'result' is the same register.
|
| -//
|
| -// elements - holds the elements of the receiver and its prototypes. Clobbered.
|
| -//
|
| -// result - holds the result on exit if the load succeeded.
|
| -// Allowed to be the the same as 'receiver' or 'key'.
|
| -// Unchanged on bailout so 'receiver' and 'key' can be safely
|
| -// used by further computation.
|
| -static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
|
| - Register key, Register elements,
|
| - Register scratch1, Register scratch2,
|
| - Register result, Label* slow) {
|
| - DCHECK(!AreAliased(receiver, key, elements, scratch1, scratch2));
|
| -
|
| - Label check_prototypes, check_next_prototype;
|
| - Label done, in_bounds, absent;
|
| -
|
| - // Check for fast array.
|
| - __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| - __ AssertFastElements(elements);
|
| -
|
| - // Check that the key (index) is within bounds.
|
| - __ Ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
| - __ Cmp(key, scratch1);
|
| - __ B(lo, &in_bounds);
|
| -
|
| - // Out of bounds. Check the prototype chain to see if we can just return
|
| - // 'undefined'.
|
| - __ Cmp(key, Operand(Smi::kZero));
|
| - __ B(lt, slow); // Negative keys can't take the fast OOB path.
|
| - __ Bind(&check_prototypes);
|
| - __ Ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - __ Bind(&check_next_prototype);
|
| - __ Ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
|
| - // scratch2: current prototype
|
| - __ JumpIfRoot(scratch2, Heap::kNullValueRootIndex, &absent);
|
| - __ Ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
|
| - __ Ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
| - // elements: elements of current prototype
|
| - // scratch2: map of current prototype
|
| - __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE);
|
| - __ B(lo, slow);
|
| - __ Ldrb(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset));
|
| - __ Tbnz(scratch1, Map::kIsAccessCheckNeeded, slow);
|
| - __ Tbnz(scratch1, Map::kHasIndexedInterceptor, slow);
|
| - __ JumpIfNotRoot(elements, Heap::kEmptyFixedArrayRootIndex, slow);
|
| - __ B(&check_next_prototype);
|
| -
|
| - __ Bind(&absent);
|
| - __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
|
| - __ B(&done);
|
| -
|
| - __ Bind(&in_bounds);
|
| - // Fast case: Do the load.
|
| - __ Add(scratch1, elements, FixedArray::kHeaderSize - kHeapObjectTag);
|
| - __ SmiUntag(scratch2, key);
|
| - __ Ldr(scratch2, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2));
|
| -
|
| - // In case the loaded value is the_hole we have to check the prototype chain.
|
| - __ JumpIfRoot(scratch2, Heap::kTheHoleValueRootIndex, &check_prototypes);
|
| -
|
| - // Move the value to the result register.
|
| - // 'result' can alias with 'receiver' or 'key' but these two must be
|
| - // preserved if we jump to 'slow'.
|
| - __ Mov(result, scratch2);
|
| - __ Bind(&done);
|
| -}
|
| -
|
| -
|
| -// Checks whether a key is an array index string or a unique name.
|
| -// Falls through if a key is a unique name.
|
| -// The map of the key is returned in 'map_scratch'.
|
| -// If the jump to 'index_string' is done the hash of the key is left
|
| -// in 'hash_scratch'.
|
| -static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
|
| - Register map_scratch, Register hash_scratch,
|
| - Label* index_string, Label* not_unique) {
|
| - DCHECK(!AreAliased(key, map_scratch, hash_scratch));
|
| -
|
| - // Is the key a name?
|
| - Label unique;
|
| - __ JumpIfObjectType(key, map_scratch, hash_scratch, LAST_UNIQUE_NAME_TYPE,
|
| - not_unique, hi);
|
| - STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
|
| - __ B(eq, &unique);
|
| -
|
| - // Is the string an array index with cached numeric value?
|
| - __ Ldr(hash_scratch.W(), FieldMemOperand(key, Name::kHashFieldOffset));
|
| - __ TestAndBranchIfAllClear(hash_scratch, Name::kContainsCachedArrayIndexMask,
|
| - index_string);
|
| -
|
| - // Is the string internalized? We know it's a string, so a single bit test is
|
| - // enough.
|
| - __ Ldrb(hash_scratch, FieldMemOperand(map_scratch, Map::kInstanceTypeOffset));
|
| - STATIC_ASSERT(kInternalizedTag == 0);
|
| - __ TestAndBranchIfAnySet(hash_scratch, kIsNotInternalizedMask, not_unique);
|
| -
|
| - __ Bind(&unique);
|
| - // Fall through if the key is a unique name.
|
| -}
|
| -
|
| void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
| Register dictionary = x0;
|
| DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
|
| @@ -323,127 +173,6 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
| __ TailCallRuntime(Runtime::kKeyedGetProperty);
|
| }
|
|
|
| -static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, Register key,
|
| - Register receiver, Register scratch1,
|
| - Register scratch2, Register scratch3,
|
| - Register scratch4, Register scratch5,
|
| - Label* slow) {
|
| - DCHECK(!AreAliased(key, receiver, scratch1, scratch2, scratch3, scratch4,
|
| - scratch5));
|
| -
|
| - Isolate* isolate = masm->isolate();
|
| - Label check_number_dictionary;
|
| - // If we can load the value, it should be returned in x0.
|
| - Register result = x0;
|
| -
|
| - GenerateKeyedLoadReceiverCheck(masm, receiver, scratch1, scratch2,
|
| - Map::kHasIndexedInterceptor, slow);
|
| -
|
| - // Check the receiver's map to see if it has fast elements.
|
| - __ CheckFastElements(scratch1, scratch2, &check_number_dictionary);
|
| -
|
| - GenerateFastArrayLoad(masm, receiver, key, scratch3, scratch2, scratch1,
|
| - result, slow);
|
| - __ IncrementCounter(isolate->counters()->ic_keyed_load_generic_smi(), 1,
|
| - scratch1, scratch2);
|
| - __ Ret();
|
| -
|
| - __ Bind(&check_number_dictionary);
|
| - __ Ldr(scratch3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| - __ Ldr(scratch2, FieldMemOperand(scratch3, JSObject::kMapOffset));
|
| -
|
| - // Check whether we have a number dictionary.
|
| - __ JumpIfNotRoot(scratch2, Heap::kHashTableMapRootIndex, slow);
|
| -
|
| - __ LoadFromNumberDictionary(slow, scratch3, key, result, scratch1, scratch2,
|
| - scratch4, scratch5);
|
| - __ Ret();
|
| -}
|
| -
|
| -static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, Register key,
|
| - Register receiver, Register scratch1,
|
| - Register scratch2, Register scratch3,
|
| - Register scratch4, Register scratch5,
|
| - Label* slow) {
|
| - DCHECK(!AreAliased(key, receiver, scratch1, scratch2, scratch3, scratch4,
|
| - scratch5));
|
| -
|
| - Isolate* isolate = masm->isolate();
|
| - Label probe_dictionary, property_array_property;
|
| - // If we can load the value, it should be returned in x0.
|
| - Register result = x0;
|
| -
|
| - GenerateKeyedLoadReceiverCheck(masm, receiver, scratch1, scratch2,
|
| - Map::kHasNamedInterceptor, slow);
|
| -
|
| - // If the receiver is a fast-case object, check the stub cache. Otherwise
|
| - // probe the dictionary.
|
| - __ Ldr(scratch2, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
| - __ Ldr(scratch3, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
| - __ JumpIfRoot(scratch3, Heap::kHashTableMapRootIndex, &probe_dictionary);
|
| -
|
| - // The handlers in the stub cache expect a vector and slot. Since we won't
|
| - // change the IC from any downstream misses, a dummy vector can be used.
|
| - Register vector = LoadWithVectorDescriptor::VectorRegister();
|
| - Register slot = LoadWithVectorDescriptor::SlotRegister();
|
| - DCHECK(!AreAliased(vector, slot, scratch1, scratch2, scratch3, scratch4));
|
| - Handle<TypeFeedbackVector> dummy_vector =
|
| - TypeFeedbackVector::DummyVector(masm->isolate());
|
| - int slot_index = dummy_vector->GetIndex(
|
| - FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot));
|
| - __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
|
| - __ Mov(slot, Operand(Smi::FromInt(slot_index)));
|
| -
|
| - masm->isolate()->load_stub_cache()->GenerateProbe(
|
| - masm, receiver, key, scratch1, scratch2, scratch3, scratch4);
|
| - // Cache miss.
|
| - KeyedLoadIC::GenerateMiss(masm);
|
| -
|
| - // Do a quick inline probe of the receiver's dictionary, if it exists.
|
| - __ Bind(&probe_dictionary);
|
| - __ Ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
|
| - GenerateGlobalInstanceTypeCheck(masm, scratch1, slow);
|
| - // Load the property.
|
| - GenerateDictionaryLoad(masm, slow, scratch2, key, result, scratch1, scratch3);
|
| - __ IncrementCounter(isolate->counters()->ic_keyed_load_generic_symbol(), 1,
|
| - scratch1, scratch2);
|
| - __ Ret();
|
| -}
|
| -
|
| -void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
| - // The return address is in lr.
|
| - Label slow, check_name, index_smi, index_name;
|
| -
|
| - Register key = LoadDescriptor::NameRegister();
|
| - Register receiver = LoadDescriptor::ReceiverRegister();
|
| - DCHECK(key.is(x2));
|
| - DCHECK(receiver.is(x1));
|
| -
|
| - __ JumpIfNotSmi(key, &check_name);
|
| - __ Bind(&index_smi);
|
| - // Now the key is known to be a smi. This place is also jumped to from below
|
| - // where a numeric string is converted to a smi.
|
| - GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
|
| -
|
| - // Slow case.
|
| - __ Bind(&slow);
|
| - __ IncrementCounter(masm->isolate()->counters()->ic_keyed_load_generic_slow(),
|
| - 1, x4, x3);
|
| - GenerateRuntimeGetProperty(masm);
|
| -
|
| - __ Bind(&check_name);
|
| - GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow);
|
| -
|
| - GenerateKeyedLoadWithNameKey(masm, key, receiver, x4, x5, x6, x7, x3, &slow);
|
| -
|
| - __ Bind(&index_name);
|
| - __ IndexFromHash(x3, key);
|
| - // Now jump to the place where smi keys are handled.
|
| - __ B(&index_smi);
|
| -}
|
| -
|
| -
|
| static void StoreIC_PushArgs(MacroAssembler* masm) {
|
| __ Push(StoreWithVectorDescriptor::ValueRegister(),
|
| StoreWithVectorDescriptor::SlotRegister(),
|
|
|