| Index: src/ia32/ic-ia32.cc
|
| ===================================================================
|
| --- src/ia32/ic-ia32.cc (revision 4791)
|
| +++ src/ia32/ic-ia32.cc (working copy)
|
| @@ -1046,22 +1046,21 @@
|
| // Defined in ic.cc.
|
| Object* CallIC_Miss(Arguments args);
|
|
|
| -void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
| +// The generated code does not accept smi keys.
|
| +// The generated code falls through if both probes miss.
|
| +static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
|
| + int argc,
|
| + Code::Kind kind,
|
| + Label* miss) {
|
| // ----------- S t a t e -------------
|
| // -- ecx : name
|
| - // -- esp[0] : return address
|
| - // -- esp[(argc - n) * 4] : arg[n] (zero-based)
|
| - // -- ...
|
| - // -- esp[(argc + 1) * 4] : receiver
|
| + // -- edx : receiver
|
| // -----------------------------------
|
| - Label number, non_number, non_string, boolean, probe, miss;
|
| + Label number, non_number, non_string, boolean, probe;
|
|
|
| - // Get the receiver of the function from the stack; 1 ~ return address.
|
| - __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| -
|
| // Probe the stub cache.
|
| Code::Flags flags =
|
| - Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
|
| + Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
|
| StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax);
|
|
|
| // If the stub cache probing failed, the receiver might be a value.
|
| @@ -1081,7 +1080,7 @@
|
|
|
| // Check for string.
|
| __ bind(&non_number);
|
| - __ cmp(ebx, FIRST_NONSTRING_TYPE);
|
| + __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
|
| __ j(above_equal, &non_string, taken);
|
| StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| masm, Context::STRING_FUNCTION_INDEX, edx);
|
| @@ -1092,7 +1091,7 @@
|
| __ cmp(edx, Factory::true_value());
|
| __ j(equal, &boolean, not_taken);
|
| __ cmp(edx, Factory::false_value());
|
| - __ j(not_equal, &miss, taken);
|
| + __ j(not_equal, miss, taken);
|
| __ bind(&boolean);
|
| StubCompiler::GenerateLoadGlobalFunctionPrototype(
|
| masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
|
| @@ -1100,10 +1099,6 @@
|
| // Probe the stub cache for the value object.
|
| __ bind(&probe);
|
| StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
|
| -
|
| - // Cache miss: Jump to runtime.
|
| - __ bind(&miss);
|
| - GenerateMiss(masm, argc);
|
| }
|
|
|
|
|
| @@ -1143,8 +1138,8 @@
|
| __ InvokeFunction(edi, actual, JUMP_FUNCTION);
|
| }
|
|
|
| -
|
| -void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
| +// The generated code never falls through.
|
| +static void GenerateCallNormal(MacroAssembler* masm, int argc, Label* miss) {
|
| // ----------- S t a t e -------------
|
| // -- ecx : name
|
| // -- esp[0] : return address
|
| @@ -1152,20 +1147,20 @@
|
| // -- ...
|
| // -- esp[(argc + 1) * 4] : receiver
|
| // -----------------------------------
|
| - Label miss, global_object, non_global_object;
|
| + Label global_object, non_global_object;
|
|
|
| // Get the receiver of the function from the stack; 1 ~ return address.
|
| __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
|
|
| // Check that the receiver isn't a smi.
|
| __ test(edx, Immediate(kSmiTagMask));
|
| - __ j(zero, &miss, not_taken);
|
| + __ j(zero, miss, not_taken);
|
|
|
| // Check that the receiver is a valid JS object.
|
| __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
|
| __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
|
| __ cmp(eax, FIRST_JS_OBJECT_TYPE);
|
| - __ j(below, &miss, not_taken);
|
| + __ j(below, miss, not_taken);
|
|
|
| // If this assert fails, we have to check upper bound too.
|
| ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
|
| @@ -1181,8 +1176,8 @@
|
| // Check that the global object does not require access checks.
|
| __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
|
| __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
|
| - __ j(not_equal, &miss, not_taken);
|
| - GenerateNormalHelper(masm, argc, true, &miss);
|
| + __ j(not_equal, miss, not_taken);
|
| + GenerateNormalHelper(masm, argc, true, miss);
|
|
|
| // Accessing non-global object: Check for access to global proxy.
|
| Label global_proxy, invoke;
|
| @@ -1193,22 +1188,18 @@
|
| // require access checks.
|
| __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
|
| __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
|
| - __ j(not_equal, &miss, not_taken);
|
| + __ j(not_equal, miss, not_taken);
|
| __ bind(&invoke);
|
| - GenerateNormalHelper(masm, argc, false, &miss);
|
| + GenerateNormalHelper(masm, argc, false, miss);
|
|
|
| // Global object proxy access: Check access rights.
|
| __ bind(&global_proxy);
|
| - __ CheckAccessGlobalProxy(edx, eax, &miss);
|
| + __ CheckAccessGlobalProxy(edx, eax, miss);
|
| __ jmp(&invoke);
|
| -
|
| - // Cache miss: Jump to runtime.
|
| - __ bind(&miss);
|
| - GenerateMiss(masm, argc);
|
| }
|
|
|
|
|
| -void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
|
| +static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
|
| // ----------- S t a t e -------------
|
| // -- ecx : name
|
| // -- esp[0] : return address
|
| @@ -1230,7 +1221,7 @@
|
| // Call the entry.
|
| CEntryStub stub(1);
|
| __ mov(eax, Immediate(2));
|
| - __ mov(ebx, Immediate(ExternalReference(IC_Utility(kCallIC_Miss))));
|
| + __ mov(ebx, Immediate(ExternalReference(IC_Utility(id))));
|
| __ CallStub(&stub);
|
|
|
| // Move result to edi and exit the internal frame.
|
| @@ -1261,6 +1252,106 @@
|
| }
|
|
|
|
|
| +void CallIC::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
|
| + // -----------------------------------
|
| +
|
| + Label miss;
|
| + // Get the receiver of the function from the stack; 1 ~ return address.
|
| + __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| + GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, &miss);
|
| + __ bind(&miss);
|
| + GenerateMiss(masm, argc);
|
| +}
|
| +
|
| +
|
| +void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
| + Label miss;
|
| + GenerateCallNormal(masm, argc, &miss);
|
| + __ bind(&miss);
|
| + GenerateMiss(masm, argc);
|
| +}
|
| +
|
| +
|
| +void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
|
| + GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
|
| +}
|
| +
|
| +
|
| +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 miss, skip_probe;
|
| +
|
| + // Do not probe monomorphic cache if a key is a smi.
|
| + __ test(ecx, Immediate(kSmiTagMask));
|
| + __ j(equal, &skip_probe, taken);
|
| +
|
| + GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &skip_probe);
|
| +
|
| + __ bind(&skip_probe);
|
| +
|
| + __ mov(eax, ecx);
|
| + __ EnterInternalFrame();
|
| + __ push(ecx);
|
| + __ call(Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_Generic)),
|
| + RelocInfo::CODE_TARGET);
|
| + __ pop(ecx);
|
| + __ LeaveInternalFrame();
|
| + __ mov(edi, eax);
|
| +
|
| + __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
|
| +
|
| + // Check that the receiver isn't a smi.
|
| + __ test(edx, Immediate(kSmiTagMask));
|
| + __ j(zero, &miss, not_taken);
|
| +
|
| + // Check that the receiver is a valid JS object.
|
| + __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, eax);
|
| + __ j(below, &miss, not_taken);
|
| +
|
| + // Check that the value is a JavaScript function.
|
| + __ test(edi, Immediate(kSmiTagMask));
|
| + __ j(zero, &miss, not_taken);
|
| + __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
|
| + __ j(not_equal, &miss, not_taken);
|
| +
|
| + // Invoke the function.
|
| + ParameterCount actual(argc);
|
| + __ InvokeFunction(edi, actual, JUMP_FUNCTION);
|
| +
|
| + __ bind(&miss);
|
| + GenerateMiss(masm, argc);
|
| +}
|
| +
|
| +
|
| +void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
| + Label miss;
|
| + GenerateCallNormal(masm, argc, &miss);
|
| + __ bind(&miss);
|
| + GenerateMiss(masm, argc);
|
| +}
|
| +
|
| +
|
| +void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
|
| + GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
|
| +}
|
| +
|
| +
|
| // Defined in ic.cc.
|
| Object* LoadIC_Miss(Arguments args);
|
|
|
|
|