Index: src/ia32/stub-cache-ia32.cc |
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc |
index 77efbd869e240ecbf986b9a528ad75703b90e05b..66333755ef4a5c2943333f45b6afcb442cc1098d 100644 |
--- a/src/ia32/stub-cache-ia32.cc |
+++ b/src/ia32/stub-cache-ia32.cc |
@@ -779,87 +779,53 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm, |
} |
-// Both name_reg and receiver_reg are preserved on jumps to miss_label, |
-// but may be destroyed if store is successful. |
-void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
- Handle<JSObject> object, |
- LookupResult* lookup, |
- Handle<Map> transition, |
- Handle<Name> name, |
- Register receiver_reg, |
- Register name_reg, |
- Register value_reg, |
- Register scratch1, |
- Register scratch2, |
- Register unused, |
- Label* miss_label, |
- Label* miss_restore_name, |
- Label* slow) { |
- // Check that the map of the object hasn't changed. |
- __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
- miss_label, DO_SMI_CHECK); |
- |
- // Perform global security token check if needed. |
- if (object->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); |
- } |
- |
+void BaseStoreStubCompiler::GenerateNegativeHolderLookup( |
+ MacroAssembler* masm, |
+ Handle<JSObject> holder, |
+ Register holder_reg, |
+ Handle<Name> name, |
+ Label* miss) { |
+ if (holder->IsJSGlobalObject()) { |
+ GenerateCheckPropertyCell( |
+ masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); |
+ } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
+ GenerateDictionaryNegativeLookup( |
+ masm, miss, holder_reg, name, scratch1(), scratch2()); |
+ } |
+} |
+ |
+ |
+// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
+// store is successful. |
+void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
+ Handle<JSObject> object, |
+ LookupResult* lookup, |
+ Handle<Map> transition, |
+ Handle<Name> name, |
+ Register receiver_reg, |
+ Register storage_reg, |
+ Register value_reg, |
+ Register scratch1, |
+ Register scratch2, |
+ Register unused, |
+ Label* miss_label, |
+ Label* slow) { |
int descriptor = transition->LastAdded(); |
DescriptorArray* descriptors = transition->instance_descriptors(); |
PropertyDetails details = descriptors->GetDetails(descriptor); |
Representation representation = details.representation(); |
ASSERT(!representation.IsNone()); |
- // Ensure no transitions to deprecated maps are followed. |
- __ CheckMapDeprecated(transition, scratch1, miss_label); |
- |
- // Check that we are allowed to write this. |
- if (object->GetPrototype()->IsJSObject()) { |
- JSObject* holder; |
- // holder == object indicates that no property was found. |
- if (lookup->holder() != *object) { |
- holder = lookup->holder(); |
- } else { |
- // Find the top object. |
- holder = *object; |
- do { |
- holder = JSObject::cast(holder->GetPrototype()); |
- } while (holder->GetPrototype()->IsJSObject()); |
- } |
- // We need an extra register, push |
- Register holder_reg = CheckPrototypes( |
- object, receiver_reg, Handle<JSObject>(holder), name_reg, |
- scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER); |
- // If no property was found, and the holder (the last object in the |
- // prototype chain) is in slow mode, we need to do a negative lookup on the |
- // holder. |
- if (lookup->holder() == *object) { |
- if (holder->IsJSGlobalObject()) { |
- GenerateCheckPropertyCell( |
- masm, |
- Handle<GlobalObject>(GlobalObject::cast(holder)), |
- name, |
- scratch1, |
- miss_restore_name); |
- } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
- GenerateDictionaryNegativeLookup( |
- masm, miss_restore_name, holder_reg, name, scratch1, scratch2); |
- } |
- } |
- } |
- |
- Register storage_reg = name_reg; |
- |
if (details.type() == CONSTANT_FUNCTION) { |
Handle<HeapObject> constant( |
HeapObject::cast(descriptors->GetValue(descriptor))); |
__ LoadHeapObject(scratch1, constant); |
__ cmp(value_reg, scratch1); |
- __ j(not_equal, miss_restore_name); |
+ __ j(not_equal, miss_label); |
} else if (FLAG_track_fields && representation.IsSmi()) { |
- __ JumpIfNotSmi(value_reg, miss_restore_name); |
+ __ JumpIfNotSmi(value_reg, miss_label); |
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
- __ JumpIfSmi(value_reg, miss_restore_name); |
+ __ JumpIfSmi(value_reg, miss_label); |
} else if (FLAG_track_double_fields && representation.IsDouble()) { |
Label do_store, heap_number; |
__ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); |
@@ -879,7 +845,7 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
__ bind(&heap_number); |
__ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
- miss_restore_name, DONT_DO_SMI_CHECK); |
+ miss_label, DONT_DO_SMI_CHECK); |
if (CpuFeatures::IsSupported(SSE2)) { |
CpuFeatureScope use_sse2(masm, SSE2); |
__ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
@@ -959,15 +925,12 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
if (!FLAG_track_fields || !representation.IsSmi()) { |
// Update the write barrier for the array address. |
- // Pass the value being stored in the now unused name_reg. |
if (!FLAG_track_double_fields || !representation.IsDouble()) { |
- __ mov(name_reg, value_reg); |
- } else { |
- ASSERT(storage_reg.is(name_reg)); |
+ __ mov(storage_reg, value_reg); |
} |
__ RecordWriteField(receiver_reg, |
offset, |
- name_reg, |
+ storage_reg, |
scratch1, |
kDontSaveFPRegs, |
EMIT_REMEMBERED_SET, |
@@ -986,15 +949,12 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
if (!FLAG_track_fields || !representation.IsSmi()) { |
// Update the write barrier for the array address. |
- // Pass the value being stored in the now unused name_reg. |
if (!FLAG_track_double_fields || !representation.IsDouble()) { |
- __ mov(name_reg, value_reg); |
- } else { |
- ASSERT(storage_reg.is(name_reg)); |
+ __ mov(storage_reg, value_reg); |
} |
__ RecordWriteField(scratch1, |
offset, |
- name_reg, |
+ storage_reg, |
receiver_reg, |
kDontSaveFPRegs, |
EMIT_REMEMBERED_SET, |
@@ -1010,24 +970,15 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
// 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, |
- Handle<JSObject> object, |
- LookupResult* lookup, |
- Register receiver_reg, |
- Register name_reg, |
- Register value_reg, |
- Register scratch1, |
- Register scratch2, |
- Label* miss_label) { |
- // Check that the map of the object hasn't changed. |
- __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
- miss_label, DO_SMI_CHECK); |
- |
- // Perform global security token check if needed. |
- if (object->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); |
- } |
- |
+void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
+ Handle<JSObject> object, |
+ LookupResult* lookup, |
+ Register receiver_reg, |
+ Register name_reg, |
+ Register value_reg, |
+ Register scratch1, |
+ Register scratch2, |
+ Label* miss_label) { |
// Stub never generated for non-global objects that require access |
// checks. |
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
@@ -1286,7 +1237,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
} |
-void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
+void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
+ Label* success, |
Label* miss) { |
if (!miss->is_unused()) { |
__ jmp(success); |
@@ -1296,6 +1248,17 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
} |
+void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
+ Label* success, |
+ Label* miss) { |
+ if (!miss->is_unused()) { |
+ __ jmp(success); |
+ GenerateRestoreName(masm(), miss, name); |
+ TailCallBuiltin(masm(), MissBuiltin(kind())); |
+ } |
+} |
+ |
+ |
Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
Handle<JSObject> object, |
Register object_reg, |
@@ -1351,7 +1314,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
__ j(not_equal, &miss); |
} |
- HandlerFrontendFooter(success, &miss); |
+ HandlerFrontendFooter(name, success, &miss); |
return reg; |
} |
@@ -1372,7 +1335,7 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
} |
- HandlerFrontendFooter(success, &miss); |
+ HandlerFrontendFooter(name, success, &miss); |
} |
@@ -2899,19 +2862,13 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( |
Handle<Code> StoreStubCompiler::CompileStoreCallback( |
- Handle<Name> name, |
Handle<JSObject> object, |
Handle<JSObject> holder, |
+ Handle<Name> name, |
Handle<ExecutableAccessorInfo> callback) { |
- Label miss, miss_restore_name; |
- // Check that the maps haven't changed, preserving the value register. |
- __ JumpIfSmi(receiver(), &miss); |
- CheckPrototypes(object, receiver(), holder, |
- scratch1(), this->name(), scratch2(), |
- name, &miss_restore_name); |
- |
- // Stub never generated for non-global objects that require access checks. |
- ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
+ Label success; |
+ HandlerFrontend(object, receiver(), holder, name, &success); |
+ __ bind(&success); |
__ pop(scratch1()); // remove the return address |
__ push(receiver()); |
@@ -2925,13 +2882,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( |
ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
__ TailCallExternalReference(store_callback_property, 4, 1); |
- // Handle store cache miss. |
- GenerateRestoreName(masm(), &miss_restore_name, name); |
- __ bind(&miss); |
- TailCallBuiltin(masm(), MissBuiltin(kind())); |
- |
// Return the generated code. |
- return GetICCode(kind(), Code::CALLBACKS, name); |
+ return GetCode(kind(), Code::CALLBACKS, name); |
} |
@@ -2985,20 +2937,6 @@ void StoreStubCompiler::GenerateStoreViaSetter( |
Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
Handle<JSObject> object, |
Handle<Name> name) { |
- Label miss; |
- |
- // Check that the map of the object hasn't changed. |
- __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
- |
- // Perform global security token check if needed. |
- if (object->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(receiver(), scratch1(), scratch2(), &miss); |
- } |
- |
- // Stub never generated for non-global objects that require access |
- // checks. |
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
- |
__ pop(scratch1()); // remove the return address |
__ push(receiver()); |
__ push(this->name()); |
@@ -3011,12 +2949,8 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
__ TailCallExternalReference(store_ic_property, 4, 1); |
- // Handle store cache miss. |
- __ bind(&miss); |
- TailCallBuiltin(masm(), MissBuiltin(kind())); |
- |
// Return the generated code. |
- return GetICCode(kind(), Code::INTERCEPTOR, name); |
+ return GetCode(kind(), Code::INTERCEPTOR, name); |
} |
@@ -3220,7 +3154,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
__ Check(not_equal, "DontDelete cells can't contain the hole"); |
} |
- HandlerFrontendFooter(&success, &miss); |
+ HandlerFrontendFooter(name, &success, &miss); |
__ bind(&success); |
Counters* counters = isolate()->counters(); |
@@ -3233,7 +3167,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
} |
-Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
+Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
MapHandleList* receiver_maps, |
CodeHandleList* handlers, |
Handle<Name> name, |