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 |