Index: src/arm/stub-cache-arm.cc |
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc |
index 3189cf8f9e2f1c27e214fbaf44bb700d46923a7e..00020f803352d21fc04d9aae306d101d8099c02e 100644 |
--- a/src/arm/stub-cache-arm.cc |
+++ b/src/arm/stub-cache-arm.cc |
@@ -437,91 +437,58 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm, |
} |
+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()); |
+ } |
+} |
+ |
+ |
// Generate StoreTransition code, value is passed in r0 register. |
// When leaving generated code after success, the receiver_reg and name_reg |
// may be clobbered. Upon branch to miss_label, the receiver and name |
// registers have their original values. |
-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 scratch3, |
- Label* miss_label, |
- Label* miss_restore_name, |
- Label* slow) { |
+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 scratch3, |
+ Label* miss_label, |
+ Label* slow) { |
// r0 : value |
Label exit; |
- // Check that the map of the object hasn't changed. |
- __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, |
- DO_SMI_CHECK); |
- |
- // Perform global security token check if needed. |
- if (object->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
- } |
- |
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()); |
- } |
- 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); |
- __ b(ne, miss_restore_name); |
+ __ b(ne, 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; |
__ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex); |
@@ -535,7 +502,7 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
__ bind(&heap_number); |
__ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
- miss_restore_name, DONT_DO_SMI_CHECK); |
+ miss_label, DONT_DO_SMI_CHECK); |
__ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
__ bind(&do_store); |
@@ -566,8 +533,7 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
__ mov(scratch1, Operand(transition)); |
__ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
- // Update the write barrier for the map field and pass the now unused |
- // name_reg as scratch register. |
+ // Update the write barrier for the map field. |
__ RecordWriteField(receiver_reg, |
HeapObject::kMapOffset, |
scratch1, |
@@ -608,15 +574,12 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
__ JumpIfSmi(value_reg, &exit); |
// Update the write barrier for the array address. |
- // Pass the now unused name_reg as a scratch register. |
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, |
kLRHasNotBeenSaved, |
kDontSaveFPRegs, |
@@ -640,15 +603,12 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
__ JumpIfSmi(value_reg, &exit); |
// Update the write barrier for the array address. |
- // Ok to clobber receiver_reg and name_reg, since we return. |
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, |
kLRHasNotBeenSaved, |
kDontSaveFPRegs, |
@@ -668,27 +628,18 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
// When leaving generated code after success, the receiver_reg and name_reg |
// may be clobbered. Upon branch to miss_label, the receiver and name |
// registers have their original values. |
-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) { |
+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) { |
// r0 : value |
Label exit; |
- // Check that the map of the object hasn't changed. |
- __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, |
- DO_SMI_CHECK); |
- |
- // Perform global security token check if needed. |
- if (object->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
- } |
- |
// Stub never generated for non-global objects that require access |
// checks. |
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
@@ -1342,7 +1293,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()) { |
__ b(success); |
@@ -1352,6 +1304,17 @@ void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
} |
+void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
+ Label* success, |
+ Label* miss) { |
+ if (!miss->is_unused()) { |
+ __ b(success); |
+ GenerateRestoreName(masm(), miss, name); |
+ TailCallBuiltin(masm(), MissBuiltin(kind())); |
+ } |
+} |
+ |
+ |
Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
Handle<JSObject> object, |
Register object_reg, |
@@ -1394,7 +1357,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
__ b(ne, &miss); |
} |
- HandlerFrontendFooter(success, &miss); |
+ HandlerFrontendFooter(name, success, &miss); |
return reg; |
} |
@@ -1415,7 +1378,7 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
} |
- HandlerFrontendFooter(success, &miss); |
+ HandlerFrontendFooter(name, success, &miss); |
} |
@@ -2824,34 +2787,30 @@ 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; |
- // Check that the maps haven't changed. |
- __ JumpIfSmi(receiver(), &miss); |
- CheckPrototypes(object, receiver(), holder, |
- scratch1(), scratch2(), scratch3(), name, &miss); |
+ Label success; |
+ HandlerFrontend(object, receiver(), holder, name, &success); |
+ __ bind(&success); |
// Stub never generated for non-global objects that require access checks. |
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
__ push(receiver()); // receiver |
__ mov(ip, Operand(callback)); // callback info |
- __ Push(ip, this->name(), value()); |
+ __ push(ip); |
+ __ mov(ip, Operand(name)); |
+ __ Push(ip, value()); |
// Do tail-call to the runtime system. |
ExternalReference store_callback_property = |
ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
__ TailCallExternalReference(store_callback_property, 4, 1); |
- // Handle store cache miss. |
- __ bind(&miss); |
- TailCallBuiltin(masm(), MissBuiltin(kind())); |
- |
// Return the generated code. |
- return GetICCode(kind(), Code::CALLBACKS, name); |
+ return GetCode(kind(), Code::CALLBACKS, name); |
} |
@@ -3105,7 +3064,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
__ b(eq, &miss); |
} |
- HandlerFrontendFooter(&success, &miss); |
+ HandlerFrontendFooter(name, &success, &miss); |
__ bind(&success); |
Counters* counters = isolate()->counters(); |
@@ -3118,7 +3077,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
} |
-Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
+Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
MapHandleList* receiver_maps, |
CodeHandleList* handlers, |
Handle<Name> name, |