| Index: src/a64/ic-a64.cc
|
| diff --git a/src/a64/ic-a64.cc b/src/a64/ic-a64.cc
|
| index feae809a5797d34429ee803e33ad83f8760369e5..bdc7f00016ea540918d0e1cbd134a47003be3f03 100644
|
| --- a/src/a64/ic-a64.cc
|
| +++ b/src/a64/ic-a64.cc
|
| @@ -102,7 +102,7 @@ static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// Helper function used from LoadIC/CallIC GenerateNormal.
|
| +// Helper function used from LoadIC GenerateNormal.
|
| //
|
| // elements: Property dictionary. It is not clobbered if a jump to the miss
|
| // label is done.
|
| @@ -426,360 +426,8 @@ static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -Object* CallIC_Miss(Arguments args);
|
| -
|
| -void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
|
| - int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state) {
|
| - // ----------- S t a t e -------------
|
| - // -- x1 : receiver
|
| - // -- x2 : name
|
| - // -----------------------------------
|
| - Register receiver = x1;
|
| - Register name = x2;
|
| -
|
| - Label number, non_number, non_string, boolean, probe, miss;
|
| -
|
| - // Probe the stub cache.
|
| - Code::Flags flags = Code::ComputeFlags(kind,
|
| - MONOMORPHIC,
|
| - extra_state,
|
| - Code::NORMAL,
|
| - argc);
|
| - masm->isolate()->stub_cache()->GenerateProbe(
|
| - masm, flags, receiver, name, x3, x4, x5, x6);
|
| -
|
| - // If the stub cache probing failed, the receiver might be a value.
|
| - // For value objects, we use the map of the prototype objects for
|
| - // the corresponding JSValue for the cache and that is what we need
|
| - // to probe.
|
| -
|
| - // Check for number.
|
| - __ JumpIfSmi(receiver, &number);
|
| - Register receiver_type = x3;
|
| - __ JumpIfNotObjectType(receiver, x4, receiver_type, HEAP_NUMBER_TYPE,
|
| - &non_number);
|
| -
|
| - __ Bind(&number);
|
| - StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| - masm, Context::NUMBER_FUNCTION_INDEX, receiver);
|
| - __ B(&probe);
|
| -
|
| - // Check for string.
|
| - __ Bind(&non_number);
|
| - __ Cmp(receiver_type, FIRST_NONSTRING_TYPE);
|
| - __ B(hs, &non_string);
|
| - StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| - masm, Context::STRING_FUNCTION_INDEX, receiver);
|
| - __ B(&probe);
|
| -
|
| - // Check for boolean.
|
| - __ Bind(&non_string);
|
| - __ JumpIfRoot(receiver, Heap::kTrueValueRootIndex, &boolean);
|
| - __ JumpIfNotRoot(receiver, Heap::kFalseValueRootIndex, &miss);
|
| -
|
| - __ Bind(&boolean);
|
| - StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| - masm, Context::BOOLEAN_FUNCTION_INDEX, receiver);
|
| -
|
| - // Probe the stub cache for the value object.
|
| - __ Bind(&probe);
|
| - masm->isolate()->stub_cache()->GenerateProbe(
|
| - masm, flags, receiver, name, x3, x4, x5, x6);
|
| -
|
| - __ Bind(&miss);
|
| - // Fall-through on miss.
|
| -}
|
| -
|
| -
|
| -static void GenerateFunctionTailCall(MacroAssembler* masm,
|
| - int argc,
|
| - Label* miss,
|
| - Register function,
|
| - Register scratch) {
|
| - ASSERT(!AreAliased(function, scratch));
|
| -
|
| - // Check that the value is a JSFunction.
|
| - __ JumpIfSmi(function, miss);
|
| - __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss);
|
| -
|
| - // Invoke the function.
|
| - ParameterCount actual(argc);
|
| - __ InvokeFunction(function, actual, JUMP_FUNCTION, NullCallWrapper());
|
| -}
|
| -
|
| -
|
| -void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- x2 : name
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| - Label miss;
|
| - Register name = x2;
|
| -
|
| - // Get the receiver of the function from the stack.
|
| - Register receiver = x1;
|
| - __ Peek(receiver, argc * kXRegSizeInBytes);
|
| -
|
| - Register elements = x0;
|
| - GenerateNameDictionaryReceiverCheck(masm, receiver, elements, x3, x4, &miss);
|
| -
|
| - // Search the dictionary.
|
| - Register function = x1;
|
| - GenerateDictionaryLoad(masm, &miss, elements, name, function, x3, x4);
|
| -
|
| - GenerateFunctionTailCall(masm, argc, &miss, function, x4);
|
| -
|
| - __ Bind(&miss);
|
| - // Fall-through on miss.
|
| -}
|
| -
|
| -
|
| -void CallICBase::GenerateMiss(MacroAssembler* masm,
|
| - int argc,
|
| - IC::UtilityId id,
|
| - ExtraICState extra_state) {
|
| - // ----------- S t a t e -------------
|
| - // -- x2 : name
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| - Isolate* isolate = masm->isolate();
|
| -
|
| - if (id == IC::kCallIC_Miss) {
|
| - __ IncrementCounter(isolate->counters()->call_miss(), 1, x3, x4);
|
| - } else {
|
| - __ IncrementCounter(isolate->counters()->keyed_call_miss(), 1, x3, x4);
|
| - }
|
| -
|
| - // Get the receiver of the function from the stack.
|
| - __ Peek(x3, argc * kXRegSizeInBytes);
|
| -
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| -
|
| - // Push the receiver and the name of the function.
|
| - __ Push(x3, x2);
|
| -
|
| - // Call the entry.
|
| - __ Mov(x0, 2);
|
| - __ Mov(x1, Operand(ExternalReference(IC_Utility(id), isolate)));
|
| -
|
| - CEntryStub stub(1);
|
| - __ CallStub(&stub);
|
| -
|
| - // Move result to x1 and leave the internal frame.
|
| - __ Mov(x1, x0);
|
| - }
|
| -
|
| - // Check if the receiver is a global object of some sort.
|
| - // This can happen only for regular CallIC but not KeyedCallIC.
|
| - if (id == IC::kCallIC_Miss) {
|
| - Label invoke, global;
|
| - __ Peek(x2, argc * kPointerSize); // receiver
|
| - __ JumpIfSmi(x2, &invoke);
|
| - __ JumpIfObjectType(x2, x3, x3, JS_GLOBAL_OBJECT_TYPE, &global);
|
| - __ Cmp(x3, JS_BUILTINS_OBJECT_TYPE);
|
| - __ B(ne, &invoke);
|
| -
|
| - // Patch the receiver on the stack.
|
| - __ Bind(&global);
|
| - __ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
|
| - __ Poke(x2, argc * kXRegSizeInBytes);
|
| - __ Bind(&invoke);
|
| - }
|
| -
|
| - // Invoke the function.
|
| - ParameterCount actual(argc);
|
| - __ InvokeFunction(x1, actual, JUMP_FUNCTION, NullCallWrapper());
|
| -}
|
| -
|
| -
|
| -void CallIC::GenerateMegamorphic(MacroAssembler* masm,
|
| - int argc,
|
| - ExtraICState extra_ic_state) {
|
| - // ----------- S t a t e -------------
|
| - // -- x2 : name
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| -
|
| - // Get the receiver of the function from the stack.
|
| - // GenerateMonomorphicCacheProbe expects the receiver to be in x1.
|
| - Register receiver = x1;
|
| - __ Peek(receiver, argc * kXRegSizeInBytes);
|
| -
|
| - GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state);
|
| - GenerateMiss(masm, argc, extra_ic_state);
|
| -}
|
| -
|
| -
|
| -void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- x2 : name / key
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| - Register key = x2;
|
| -
|
| - // Get the receiver of the function from the stack.
|
| - Register receiver = x1;
|
| - __ Peek(receiver, argc * kXRegSizeInBytes);
|
| -
|
| - Label key_is_not_smi;
|
| - Label key_is_smi;
|
| - Label slow_call;
|
| - Label not_fast_array;
|
| - Label slow_load;
|
| - Label do_call;
|
| - Label key_is_index_name;
|
| - Label lookup_monomorphic_cache;
|
| -
|
| - __ JumpIfNotSmi(key, &key_is_not_smi);
|
| - __ Bind(&key_is_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.
|
| - // Live values:
|
| - // x1: receiver
|
| - // x2: key
|
| - GenerateKeyedLoadReceiverCheck(masm, receiver, x10, x11,
|
| - Map::kHasIndexedInterceptor, &slow_call);
|
| -
|
| - // Due to the requirements of some helpers, both 'function' and 'receiver' are
|
| - // mapped to x1. However, they are never live at the same time.
|
| - Register function = x1;
|
| - Register elements_map = x3;
|
| - Register elements = x4;
|
| - GenerateFastArrayLoad(masm, receiver, key, elements, elements_map, x10,
|
| - function, ¬_fast_array, &slow_load);
|
| - Counters* counters = masm->isolate()->counters();
|
| - __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1, x10, x11);
|
| -
|
| - __ Bind(&do_call);
|
| - // Live values:
|
| - // x1: function
|
| - // x2: key
|
| - // GenerateFunctionTailCall requires that function is x1. This is enforced by
|
| - // MacroAssembler::InvokeFunction.
|
| - GenerateFunctionTailCall(masm, argc, &slow_call, function, x10);
|
| -
|
| - // It should not be possible for execution to fall through a tail call.
|
| - if (__ emit_debug_code()) {
|
| - __ Unreachable();
|
| - }
|
| -
|
| - __ Bind(¬_fast_array);
|
| - // Check whether the elements is a number dictionary.
|
| - // Live values:
|
| - // x1: receiver
|
| - // x2: key
|
| - // x3: elements map
|
| - // x4: elements
|
| - __ JumpIfNotRoot(elements_map, Heap::kHashTableMapRootIndex, &slow_load);
|
| - __ LoadFromNumberDictionary(&slow_load, elements, key, function,
|
| - x10, x11, x12, x13);
|
| - __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1, x10, x11);
|
| - __ B(&do_call);
|
| -
|
| - __ Bind(&slow_load);
|
| - // This branch is taken when calling KeyedCallIC_Miss (via GenerateMiss) is
|
| - // neither required nor beneficial.
|
| - // Live values:
|
| - // x1: receiver
|
| - // x2: key
|
| - __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, x10, x11);
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| - // The key needs to be preserved across the runtime call.
|
| - __ Push(key);
|
| - // Pass the receiver and the key as argument to KeyedGetProperty.
|
| - __ Push(receiver, key);
|
| - __ CallRuntime(Runtime::kKeyedGetProperty, 2);
|
| - __ Pop(key);
|
| - }
|
| - // The return value is in x0 (as per AAPCS64).
|
| - __ Mov(function, x0);
|
| - __ B(&do_call);
|
| -
|
| - __ Bind(&key_is_not_smi);
|
| - // The key isn't a SMI. Check to see if it's a name.
|
| - // Live values:
|
| - // x1: receiver
|
| - // x2: key
|
| - Register map = x6;
|
| - Register hash = x7;
|
| - GenerateKeyNameCheck(masm, key, map, hash, &key_is_index_name, &slow_call);
|
| -
|
| - // If the check fell through, the key is known to be a unique name.
|
| - //
|
| - // If the receiver is a regular JS object with slow properties then do
|
| - // a quick inline probe of the receiver's dictionary.
|
| - // Otherwise do the monomorphic cache probe.
|
| - GenerateKeyedLoadReceiverCheck(masm, receiver, map, x10,
|
| - Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
|
| -
|
| - __ Ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
| - __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
|
| - __ JumpIfNotRoot(elements_map, Heap::kHashTableMapRootIndex,
|
| - &lookup_monomorphic_cache);
|
| -
|
| - GenerateDictionaryLoad(masm, &slow_load, elements, key, function, x10, x11);
|
| - __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, x10, x11);
|
| - __ B(&do_call);
|
| -
|
| - __ Bind(&lookup_monomorphic_cache);
|
| - // Live values:
|
| - // x1: receiver
|
| - // x2: key
|
| - // These assignments are expected by GenerateMonomorphicCacheProbe.
|
| - __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, x10, x11);
|
| - ASSERT(receiver.Is(x1));
|
| - ASSERT(key.Is(x2));
|
| - GenerateMonomorphicCacheProbe(masm,
|
| - argc,
|
| - Code::KEYED_CALL_IC,
|
| - kNoExtraICState);
|
| - // Fall through on miss.
|
| -
|
| - __ Bind(&slow_call);
|
| - // This branch is taken if:
|
| - // - the receiver requires boxing or access check,
|
| - // - the key is neither smi nor a unique name,
|
| - // - the value loaded is not a function,
|
| - // - there is hope that the runtime will create a monomorphic call stub
|
| - // that will get fetched next time.
|
| - __ IncrementCounter(counters->keyed_call_generic_slow(), 1, x10, x11);
|
| - GenerateMiss(masm, argc);
|
| -
|
| - __ Bind(&key_is_index_name);
|
| - // Live values:
|
| - // x1: receiver
|
| - // x2: key
|
| - // x7: hash
|
| - // The key is an array index string, so calculate its hash and derive the
|
| - // numerical index from it.
|
| - __ IndexFromHash(hash, key);
|
| - __ B(&key_is_smi);
|
| -}
|
| -
|
| -
|
| -void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- x2 : name
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| - Register name = x2;
|
| -
|
| - // Check if the name is really a name.
|
| - Label miss;
|
| - __ JumpIfSmi(name, &miss);
|
| - __ IsObjectNameType(name, x0, &miss);
|
| - CallICBase::GenerateNormal(masm, argc);
|
| -
|
| - __ Bind(&miss);
|
| - GenerateMiss(masm, argc);
|
| -}
|
| -
|
| -
|
| -void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
| +void LoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
| + ExtraICState extra_state) {
|
| // ----------- S t a t e -------------
|
| // -- x2 : name
|
| // -- lr : return address
|
| @@ -787,9 +435,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
| // -----------------------------------
|
|
|
| // Probe the stub cache.
|
| - ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
|
| Code::Flags flags = Code::ComputeFlags(
|
| - Code::HANDLER, MONOMORPHIC, extra_ic_state,
|
| + Code::HANDLER, MONOMORPHIC, extra_state,
|
| Code::NORMAL, Code::LOAD_IC);
|
| masm->isolate()->stub_cache()->GenerateProbe(
|
| masm, flags, x0, x2, x3, x4, x5, x6);
|
| @@ -942,51 +589,6 @@ void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| -void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
|
| - int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- x2 : key / name
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| - Register key = x2;
|
| -
|
| - Label slow, not_mapped, do_call;
|
| -
|
| - // Get the receiver of the function from the stack.
|
| - Register map = x0;
|
| - Register function = x1;
|
| - Register receiver = x3;
|
| - __ Peek(receiver, argc * kXRegSizeInBytes);
|
| -
|
| - MemOperand mapped_location =
|
| - GenerateMappedArgumentsLookup(masm, receiver, key, map, x10, x11,
|
| - ¬_mapped, &slow);
|
| - // If we fell through, mapped_location will load the function.
|
| - __ Ldr(function, mapped_location);
|
| -
|
| - __ Bind(&do_call);
|
| - // Live values:
|
| - // x1: function
|
| - // GenerateFunctionTailCall requires that function is x1. This is enforced by
|
| - // MacroAssembler::InvokeFunction.
|
| - GenerateFunctionTailCall(masm, argc, &slow, function, x10);
|
| -
|
| - __ Bind(¬_mapped);
|
| - // The argument is not mapped, but 'map' has been populated.
|
| - MemOperand unmapped_location =
|
| - GenerateUnmappedArgumentsLookup(masm, key, map, x10, &slow);
|
| - // If we fell through, unmapped_location will load the function.
|
| - __ Ldr(function, unmapped_location);
|
| - // Check for the hole value before calling the function. For the mapped case,
|
| - // GenerateMappedArgumentsLookup does this check automatically. If we're not
|
| - // going to the slow case, we re-use the tail call code at do_call.
|
| - __ JumpIfNotRoot(function, Heap::kTheHoleValueRootIndex, &do_call);
|
| -
|
| - __ Bind(&slow);
|
| - GenerateMiss(masm, argc);
|
| -}
|
| -
|
| -
|
| void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
| // ---------- S t a t e --------------
|
| // -- lr : return address
|
|
|