| Index: src/ia32/ic-ia32.cc
|
| diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
|
| index 53481f25107a3fd8e81233453fa01cd9c88828d5..ea9b6884af6a989c6fa110969c132413c30c5c0f 100644
|
| --- a/src/ia32/ic-ia32.cc
|
| +++ b/src/ia32/ic-ia32.cc
|
| @@ -947,381 +947,17 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// The generated code does not accept smi keys.
|
| -// The generated code falls through if both probes miss.
|
| -void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
|
| - int argc,
|
| - Code::Kind kind,
|
| - ExtraICState extra_state) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- edx : receiver
|
| - // -----------------------------------
|
| - 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);
|
| - Isolate* isolate = masm->isolate();
|
| - isolate->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, eax);
|
| -
|
| - // 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(edx, &number);
|
| - __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
|
| - __ j(not_equal, &non_number);
|
| - __ bind(&number);
|
| - StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| - masm, Context::NUMBER_FUNCTION_INDEX, edx);
|
| - __ jmp(&probe);
|
| -
|
| - // Check for string.
|
| - __ bind(&non_number);
|
| - __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
|
| - __ j(above_equal, &non_string);
|
| - StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| - masm, Context::STRING_FUNCTION_INDEX, edx);
|
| - __ jmp(&probe);
|
| -
|
| - // Check for boolean.
|
| - __ bind(&non_string);
|
| - __ cmp(edx, isolate->factory()->true_value());
|
| - __ j(equal, &boolean);
|
| - __ cmp(edx, isolate->factory()->false_value());
|
| - __ j(not_equal, &miss);
|
| - __ bind(&boolean);
|
| - StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| - masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
|
| -
|
| - // Probe the stub cache for the value object.
|
| - __ bind(&probe);
|
| - isolate->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
|
| - __ bind(&miss);
|
| -}
|
| -
|
| -
|
| -static void GenerateFunctionTailCall(MacroAssembler* masm,
|
| - int argc,
|
| - Label* miss) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- edi : function
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| -
|
| - // Check that the result is not a smi.
|
| - __ JumpIfSmi(edi, miss);
|
| -
|
| - // Check that the value is a JavaScript function, fetching its map into eax.
|
| - __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
|
| - __ j(not_equal, miss);
|
| -
|
| - // Invoke the function.
|
| - ParameterCount actual(argc);
|
| - __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
|
| -}
|
| -
|
| -
|
| -// The generated code falls through if the call should be handled by runtime.
|
| -void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| - Label miss;
|
| -
|
| - // Get the receiver of the function from the stack; 1 ~ return address.
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| -
|
| - GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
|
| -
|
| - // eax: elements
|
| - // Search the dictionary placing the result in edi.
|
| - GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi);
|
| - GenerateFunctionTailCall(masm, argc, &miss);
|
| -
|
| - __ bind(&miss);
|
| -}
|
| -
|
| -
|
| -void CallICBase::GenerateMiss(MacroAssembler* masm,
|
| - int argc,
|
| - IC::UtilityId id,
|
| - ExtraICState extra_state) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| -
|
| - Counters* counters = masm->isolate()->counters();
|
| - if (id == IC::kCallIC_Miss) {
|
| - __ IncrementCounter(counters->call_miss(), 1);
|
| - } else {
|
| - __ IncrementCounter(counters->keyed_call_miss(), 1);
|
| - }
|
| -
|
| - // Get the receiver of the function from the stack; 1 ~ return address.
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| -
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| -
|
| - // Push the receiver and the name of the function.
|
| - __ push(edx);
|
| - __ push(ecx);
|
| -
|
| - // Call the entry.
|
| - CEntryStub stub(1);
|
| - __ mov(eax, Immediate(2));
|
| - __ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate())));
|
| - __ CallStub(&stub);
|
| -
|
| - // Move result to edi and exit the internal frame.
|
| - __ mov(edi, eax);
|
| - }
|
| -
|
| - // 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;
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
|
| - __ JumpIfSmi(edx, &invoke, Label::kNear);
|
| - __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| - __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
| - __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
|
| - __ j(equal, &global, Label::kNear);
|
| - __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
|
| - __ j(not_equal, &invoke, Label::kNear);
|
| -
|
| - // Patch the receiver on the stack.
|
| - __ bind(&global);
|
| - __ mov(Operand(esp, (argc + 1) * kPointerSize),
|
| - masm->isolate()->factory()->undefined_value());
|
| -
|
| - __ bind(&invoke);
|
| - }
|
| -
|
| - // Invoke the function.
|
| - ParameterCount actual(argc);
|
| - __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
|
| -}
|
| -
|
| -
|
| -void CallIC::GenerateMegamorphic(MacroAssembler* masm,
|
| - int argc,
|
| +void LoadIC::GenerateMegamorphic(MacroAssembler* masm,
|
| ExtraICState extra_state) {
|
| // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| -
|
| - // Get the receiver of the function from the stack; 1 ~ return address.
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| - CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC,
|
| - extra_state);
|
| -
|
| - GenerateMiss(masm, argc, extra_state);
|
| -}
|
| -
|
| -
|
| -void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| -
|
| - // Get the receiver of the function from the stack; 1 ~ return address.
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| -
|
| - Label do_call, slow_call, slow_load, slow_reload_receiver;
|
| - Label check_number_dictionary, check_name, lookup_monomorphic_cache;
|
| - Label index_smi, index_name;
|
| -
|
| - // Check that the key is a smi.
|
| - __ JumpIfNotSmi(ecx, &check_name);
|
| -
|
| - __ bind(&index_smi);
|
| - // Now the key is known to be a smi. This place is also jumped to from
|
| - // where a numeric string is converted to a smi.
|
| -
|
| - GenerateKeyedLoadReceiverCheck(
|
| - masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
|
| -
|
| - GenerateFastArrayLoad(
|
| - masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
|
| - Isolate* isolate = masm->isolate();
|
| - Counters* counters = isolate->counters();
|
| - __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
|
| -
|
| - __ bind(&do_call);
|
| - // receiver in edx is not used after this point.
|
| - // ecx: key
|
| - // edi: function
|
| - GenerateFunctionTailCall(masm, argc, &slow_call);
|
| -
|
| - __ bind(&check_number_dictionary);
|
| - // eax: elements
|
| - // ecx: smi key
|
| - // Check whether the elements is a number dictionary.
|
| - __ CheckMap(eax,
|
| - isolate->factory()->hash_table_map(),
|
| - &slow_load,
|
| - DONT_DO_SMI_CHECK);
|
| - __ mov(ebx, ecx);
|
| - __ SmiUntag(ebx);
|
| - // ebx: untagged index
|
| - // Receiver in edx will be clobbered, need to reload it on miss.
|
| - __ LoadFromNumberDictionary(
|
| - &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
|
| - __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
|
| - __ jmp(&do_call);
|
| -
|
| - __ bind(&slow_reload_receiver);
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| -
|
| - __ bind(&slow_load);
|
| - // This branch is taken when calling KeyedCallIC_Miss is neither required
|
| - // nor beneficial.
|
| - __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
|
| -
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| - __ push(ecx); // save the key
|
| - __ push(edx); // pass the receiver
|
| - __ push(ecx); // pass the key
|
| - __ CallRuntime(Runtime::kKeyedGetProperty, 2);
|
| - __ pop(ecx); // restore the key
|
| - // Leave the internal frame.
|
| - }
|
| -
|
| - __ mov(edi, eax);
|
| - __ jmp(&do_call);
|
| -
|
| - __ bind(&check_name);
|
| - GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow_call);
|
| -
|
| - // 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, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
|
| -
|
| - __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
|
| - __ CheckMap(ebx,
|
| - isolate->factory()->hash_table_map(),
|
| - &lookup_monomorphic_cache,
|
| - DONT_DO_SMI_CHECK);
|
| -
|
| - GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
|
| - __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
|
| - __ jmp(&do_call);
|
| -
|
| - __ bind(&lookup_monomorphic_cache);
|
| - __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
|
| - CallICBase::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);
|
| - GenerateMiss(masm, argc);
|
| -
|
| - __ bind(&index_name);
|
| - __ IndexFromHash(ebx, ecx);
|
| - // Now jump to the place where smi keys are handled.
|
| - __ jmp(&index_smi);
|
| -}
|
| -
|
| -
|
| -void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
|
| - int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| - Label slow, notin;
|
| - Factory* factory = masm->isolate()->factory();
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| - Operand mapped_location =
|
| - GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow);
|
| - __ mov(edi, mapped_location);
|
| - GenerateFunctionTailCall(masm, argc, &slow);
|
| - __ bind(¬in);
|
| - // The unmapped lookup expects that the parameter map is in ebx.
|
| - Operand unmapped_location =
|
| - GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
|
| - __ cmp(unmapped_location, factory->the_hole_value());
|
| - __ j(equal, &slow);
|
| - __ mov(edi, unmapped_location);
|
| - GenerateFunctionTailCall(masm, argc, &slow);
|
| - __ bind(&slow);
|
| - GenerateMiss(masm, argc);
|
| -}
|
| -
|
| -
|
| -void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| - // -----------------------------------
|
| -
|
| - // Check if the name is really a name.
|
| - Label miss;
|
| - __ JumpIfSmi(ecx, &miss);
|
| - Condition cond = masm->IsObjectNameType(ecx, eax, eax);
|
| - __ j(NegateCondition(cond), &miss);
|
| - CallICBase::GenerateNormal(masm, argc);
|
| - __ bind(&miss);
|
| - GenerateMiss(masm, argc);
|
| -}
|
| -
|
| -
|
| -void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
|
| - // ----------- S t a t e -------------
|
| // -- ecx : name
|
| // -- edx : receiver
|
| // -- esp[0] : return address
|
| // -----------------------------------
|
|
|
| // 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, edx, ecx, ebx, eax);
|
|
|