summaryrefslogtreecommitdiff
path: root/deps/v8/src/ia32/stub-cache-ia32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ia32/stub-cache-ia32.cc')
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc220
1 files changed, 79 insertions, 141 deletions
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index 28e043d64..2b391e0b3 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/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());
@@ -1181,6 +1132,10 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
int save_at_depth,
Label* miss,
PrototypeCheckType check) {
+ // Make sure that the type feedback oracle harvests the receiver map.
+ // TODO(svenpanne) Remove this hack when all ICs are reworked.
+ __ mov(scratch1, Handle<Map>(object->map()));
+
Handle<JSObject> first = object;
// Make sure there's no overlap between holder and object registers.
ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
@@ -1286,7 +1241,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 +1252,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 +1318,7 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend(
__ j(not_equal, &miss);
}
- HandlerFrontendFooter(success, &miss);
+ HandlerFrontendFooter(name, success, &miss);
return reg;
}
@@ -1372,7 +1339,7 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend(
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
}
- HandlerFrontendFooter(success, &miss);
+ HandlerFrontendFooter(name, success, &miss);
}
@@ -1724,11 +1691,11 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
GenerateLoadFunctionFromCell(cell, function, &miss);
}
- Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
- Handle<Cell> kind_feedback_cell =
- isolate()->factory()->NewCell(kind);
+ Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
+ site->set_transition_info(Smi::FromInt(GetInitialFastElementsKind()));
+ Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
__ mov(eax, Immediate(argc));
- __ mov(ebx, kind_feedback_cell);
+ __ mov(ebx, site_feedback_cell);
__ mov(edi, function);
ArrayConstructorStub stub(isolate());
@@ -2899,19 +2866,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 +2886,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 +2941,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 +2953,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 +3158,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 +3171,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
}
-Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
+Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
Handle<Name> name,