Chromium Code Reviews| Index: src/ia32/stub-cache-ia32.cc |
| diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc |
| index c6251157f28c373895feecbaba9e609023203ef9..9ff682625ed0cfdbeeea019cc10879dd90c25815 100644 |
| --- a/src/ia32/stub-cache-ia32.cc |
| +++ b/src/ia32/stub-cache-ia32.cc |
| @@ -758,6 +758,14 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| } |
| +void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
| + Code* code = masm->isolate()->builtins()->builtin( |
| + Builtins::kKeyedLoadIC_MissForceGeneric); |
|
Mads Ager (chromium)
2011/04/28 13:02:01
Four space indent?
|
| + Handle<Code> ic(code); |
| + __ jmp(ic, RelocInfo::CODE_TARGET); |
| +} |
| + |
| + |
| // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| // but may be destroyed if store is successful. |
| void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| @@ -2694,42 +2702,34 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
| } |
| -MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
| - JSObject* receiver) { |
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(Handle<Map> receiver_map) { |
| // ----------- S t a t e ------------- |
| // -- eax : value |
| // -- ecx : key |
| // -- edx : receiver |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - Label miss; |
| + Label miss, miss_force_generic; |
| - // Check that the receiver isn't a smi. |
| - __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(zero, &miss, not_taken); |
| - |
| - // Check that the map matches. |
| - __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| - Immediate(Handle<Map>(receiver->map()))); |
| - __ j(not_equal, &miss, not_taken); |
| + __ CheckMap(edx, receiver_map, &miss, false); |
| // Check that the key is a smi. |
| __ test(ecx, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &miss, not_taken); |
| + __ j(not_zero, &miss_force_generic, not_taken); |
| // Get the elements array and make sure it is a fast element array, not 'cow'. |
| __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
| Immediate(factory()->fixed_array_map())); |
| - __ j(not_equal, &miss, not_taken); |
| + __ j(not_equal, &miss_force_generic, not_taken); |
| // Check that the key is within bounds. |
| - if (receiver->IsJSArray()) { |
| - __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
| - __ j(above_equal, &miss, not_taken); |
| + if (receiver_map->instance_type() == JS_ARRAY_TYPE) { |
| + __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
| + __ j(above_equal, &miss_force_generic, not_taken); |
| } else { |
| - __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. |
| - __ j(above_equal, &miss, not_taken); |
| + __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. |
| + __ j(above_equal, &miss_force_generic, not_taken); |
| } |
| // Do the store and update the write barrier. Make sure to preserve |
| @@ -2746,11 +2746,43 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
| Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| __ jmp(ic, RelocInfo::CODE_TARGET); |
| + // Handle store cache miss, replacing the ic with the generic stub. |
| + __ bind(&miss_force_generic); |
| + Handle<Code> ic_force_generic = |
| + isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| + __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| + |
| // Return the generated code. |
| return GetCode(NORMAL, NULL); |
| } |
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
| + ZoneMapList* receiver_maps, |
| + ZoneCodeList* handler_ics) { |
| + // ----------- S t a t e ------------- |
| + // -- eax : receiver |
| + // -- ecx : name |
| + // -- esp[0] : return address |
| + // ----------------------------------- |
| + Label miss; |
| + __ JumpIfSmi(eax, &miss); |
| + |
| + int receiver_count = receiver_maps->length(); |
| + for (int current = 0; current < receiver_count; ++current) { |
| + // Check map and tail call if there's a match |
| + __ cmp(FieldOperand(edx, HeapObject::kMapOffset), receiver_maps->at(current)); |
| + __ j(equal, handler_ics->at(current)); |
| + } |
| + __ bind(&miss); |
| + Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| + __ jmp(ic, RelocInfo::CODE_TARGET); |
| + |
| + // Return the generated code. |
| + return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| +} |
| + |
| + |
| MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
| JSObject* object, |
| JSObject* last) { |
| @@ -3160,26 +3192,20 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
| } |
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized( |
| + Handle<Map> receiver_map) { |
| // ----------- S t a t e ------------- |
| // -- eax : key |
| // -- edx : receiver |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - Label miss; |
| + Label miss, miss_force_generic; |
| - // Check that the receiver isn't a smi. |
| - __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(zero, &miss, not_taken); |
| - |
| - // Check that the map matches. |
| - __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| - Immediate(Handle<Map>(receiver->map()))); |
| - __ j(not_equal, &miss, not_taken); |
| + __ CheckMap(edx, receiver_map, &miss, false); |
| // Check that the key is a smi. |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &miss, not_taken); |
| + __ j(not_zero, &miss_force_generic, not_taken); |
| // Get the elements array. |
| __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
| @@ -3187,24 +3213,53 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
| // Check that the key is within bounds. |
| __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
| - __ j(above_equal, &miss, not_taken); |
| + __ j(above_equal, &miss_force_generic, not_taken); |
| // Load the result and make sure it's not the hole. |
| __ mov(ebx, Operand(ecx, eax, times_2, |
| FixedArray::kHeaderSize - kHeapObjectTag)); |
| __ cmp(ebx, factory()->the_hole_value()); |
| - __ j(equal, &miss, not_taken); |
| + __ j(equal, &miss_force_generic, not_taken); |
| __ mov(eax, ebx); |
| __ ret(0); |
| __ bind(&miss); |
| GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| + __ bind(&miss_force_generic); |
| + GenerateKeyedLoadMissForceGeneric(masm()); |
| + |
| // Return the generated code. |
| return GetCode(NORMAL, NULL); |
| } |
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic( |
| + ZoneMapList* receiver_maps, |
| + ZoneCodeList* handler_ics) { |
| + // ----------- S t a t e ------------- |
| + // -- eax : key |
| + // -- edx : receiver |
| + // -- esp[0] : return address |
| + // ----------------------------------- |
| + Label miss; |
| + |
| + __ JumpIfSmi(eax, &miss); |
| + |
| + int receiver_count = receiver_maps->length(); |
| + for (int current = 0; current < receiver_count; ++current) { |
| + // Check map and tail call if there's a match |
| + __ cmp(FieldOperand(edx, HeapObject::kMapOffset), receiver_maps->at(current)); |
| + __ j(equal, handler_ics->at(current)); |
| + } |
| + __bind(&miss); |
| + GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| + |
| + // Return the generated code. |
| + return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| +} |
| + |
| + |
| // Specialized stub for constructing objects from functions which only have only |
| // simple assignments of the form this.x = ...; in their body. |
| MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| @@ -3351,18 +3406,18 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| // -- edx : receiver |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - Label slow, failed_allocation; |
| + Label slow, failed_allocation, miss; |
| // Check that the object isn't a smi. |
| __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(zero, &slow, not_taken); |
| + __ j(zero, &miss, not_taken); |
| // Check that the key is a smi. |
| __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &slow, not_taken); |
| + __ j(not_zero, &miss, not_taken); |
| // Check that the map matches. |
| - __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
| + __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false); |
| __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
| // eax: key, known to be a smi. |
| @@ -3373,7 +3428,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| __ SmiUntag(ecx); // Untag the index. |
| __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
| // Unsigned comparison catches both negative and too-large values. |
| - __ j(above_equal, &slow); |
| + __ j(above_equal, &miss); |
| __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
| // ebx: base pointer of external storage |
| switch (array_type) { |
| @@ -3482,19 +3537,25 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| __ bind(&slow); |
| Counters* counters = isolate()->counters(); |
| __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
| + |
| // ----------- S t a t e ------------- |
| // -- eax : key |
| // -- edx : receiver |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - __ pop(ebx); |
| - __ push(edx); // receiver |
| - __ push(eax); // name |
| - __ push(ebx); // return address |
| + Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Slow(); |
| + __ jmp(ic, RelocInfo::CODE_TARGET); |
| + |
| + __ bind(&miss); |
| + // ----------- S t a t e ------------- |
| + // -- eax : key |
| + // -- edx : receiver |
| + // -- esp[0] : return address |
| + // ----------------------------------- |
| - // Perform tail call to the entry. |
| - __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| + Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| // Return the generated code. |
| return GetCode(flags); |
| @@ -3509,18 +3570,18 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| // -- edx : receiver |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - Label slow, check_heap_number; |
| + Label slow, check_heap_number, miss; |
| // Check that the object isn't a smi. |
| __ test(edx, Immediate(kSmiTagMask)); |
| - __ j(zero, &slow); |
| + __ j(zero, &miss); |
| // Check that the map matches. |
| - __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
| + __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false); |
| // Check that the key is a smi. |
| __ test(ecx, Immediate(kSmiTagMask)); |
| - __ j(not_zero, &slow); |
| + __ j(not_zero, &miss); |
| // Check that the index is in range. |
| __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| @@ -3694,6 +3755,9 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| // Slow case: call runtime. |
| __ bind(&slow); |
| + Counters* counters = isolate()->counters(); |
| + __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); |
| + |
| // ----------- S t a t e ------------- |
| // -- eax : value |
| // -- ecx : key |
| @@ -3701,17 +3765,23 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| // -- esp[0] : return address |
| // ----------------------------------- |
| - __ pop(ebx); |
| - __ push(edx); |
| - __ push(ecx); |
| - __ push(eax); |
| - __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes |
| - __ push(Immediate(Smi::FromInt( |
| - Code::ExtractExtraICStateFromFlags(flags) & kStrictMode))); |
| - __ push(ebx); // return address |
| - |
| - // Do tail-call to runtime routine. |
| - __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| + bool strict = (Code::ExtractExtraICStateFromFlags(flags) & kStrictMode) != 0; |
| + Handle<Code> ic = strict |
| + ? isolate()->builtins()->KeyedStoreIC_Slow_Strict() |
| + : isolate()->builtins()->KeyedStoreIC_Slow_NonStrict(); |
| + __ jmp(ic, RelocInfo::CODE_TARGET); |
| + |
| + // Miss case: call runtime. |
| + __ bind(&miss); |
| + // ----------- S t a t e ------------- |
| + // -- eax : value |
| + // -- ecx : key |
| + // -- edx : receiver |
| + // -- esp[0] : return address |
| + // ----------------------------------- |
| + |
| + Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| return GetCode(flags); |
| } |