Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Unified Diff: src/ic/ic.cc

Issue 1974793002: [IC] Only cache handlers on a map that were compiled for that map (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: make gcc happy Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic/ic.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic/ic.cc
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
index 05255522d0d5b809250318746b895d080236c94f..1de52b08c571fc929aed9b239bb3afec302a2501 100644
--- a/src/ic/ic.cc
+++ b/src/ic/ic.cc
@@ -936,14 +936,28 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
+ // Try to find a globally shared handler stub.
+ Handle<Code> code = GetMapIndependentHandler(lookup);
+ if (!code.is_null()) return code;
+
+ // Otherwise check the map's handler cache for a map-specific handler, and
+ // compile one if the cache comes up empty.
bool receiver_is_holder =
lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
CacheHolderFlag flag;
- Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
- receiver_map(), receiver_is_holder, isolate(), &flag);
+ Handle<Map> stub_holder_map;
+ if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
+ stub_holder_map = IC::GetHandlerCacheHolder(
+ receiver_map(), receiver_is_holder, isolate(), &flag);
+ } else {
+ DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
+ // Store handlers cannot be cached on prototypes.
+ flag = kCacheOnReceiver;
+ stub_holder_map = receiver_map();
+ }
- Handle<Code> code = PropertyHandlerCompiler::Find(
- lookup->name(), stub_holder_map, kind(), flag);
+ code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(),
+ flag);
// Use the cached value if it exists, and if it is different from the
// handler that just missed.
if (!code.is_null()) {
@@ -974,25 +988,13 @@ Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
code = CompileHandler(lookup, value, flag);
DCHECK(code->is_handler());
-
- // TODO(mvstanton): we'd only like to cache code on the map when it's custom
- // code compiled for this map, otherwise it's already cached in the global
- // code cache. We are also guarding against installing code with flags that
- // don't match the desired CacheHolderFlag computed above, which would lead to
- // invalid lookups later.
- bool is_normal = receiver_is_holder &&
- !lookup->GetHolder<JSReceiver>()->HasFastProperties();
- if (!is_normal && Code::ExtractCacheHolderFromFlags(code->flags()) == flag) {
- Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
- }
+ DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag);
+ Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
return code;
}
-
-Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
- Handle<Object> unused,
- CacheHolderFlag cache_holder) {
+Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
Handle<Object> receiver = lookup->GetReceiver();
if (receiver->IsString() &&
Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
@@ -1024,17 +1026,8 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
bool receiver_is_holder = receiver.is_identical_to(holder);
switch (lookup->state()) {
- case LookupIterator::INTERCEPTOR: {
- DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor);
- NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
- // Perform a lookup behind the interceptor. Copy the LookupIterator since
- // the original iterator will be used to fetch the value.
- LookupIterator it = *lookup;
- it.Next();
- LookupForRead(&it);
- return compiler.CompileLoadInterceptor(&it);
- }
+ case LookupIterator::INTERCEPTOR:
+ break; // Custom-compiled handler.
case LookupIterator::ACCESSOR: {
// Use simple field loads for some well-known callback properties.
@@ -1057,73 +1050,59 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
if (IsCompatibleReceiver(lookup, map)) {
Handle<Object> accessors = lookup->GetAccessors();
if (accessors->IsAccessorPair()) {
- if (!holder->HasFastProperties()) break;
+ if (!holder->HasFastProperties()) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
+ }
// When debugging we need to go the slow path to flood the accessor.
- if (GetSharedFunctionInfo()->HasDebugInfo()) break;
- Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
- isolate());
- CallOptimization call_optimization(getter);
- NamedLoadHandlerCompiler compiler(isolate(), map, holder,
- cache_holder);
- if (call_optimization.is_simple_api_call()) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
- int index = lookup->GetAccessorIndex();
- return compiler.CompileLoadCallback(lookup->name(),
- call_optimization, index);
+ if (GetSharedFunctionInfo()->HasDebugInfo()) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
}
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
- int expected_arguments = Handle<JSFunction>::cast(getter)
- ->shared()
- ->internal_formal_parameter_count();
- return compiler.CompileLoadViaGetter(
- lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
+ break; // Custom-compiled handler.
} else if (accessors->IsAccessorInfo()) {
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
- if (v8::ToCData<Address>(info->getter()) == nullptr) break;
- if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) {
- // This case should be already handled in LoadIC::UpdateCaches.
- UNREACHABLE();
- break;
+ if (v8::ToCData<Address>(info->getter()) == nullptr) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
}
- if (!holder->HasFastProperties()) break;
+ // Ruled out by IsCompatibleReceiver() above.
+ DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
+ if (!holder->HasFastProperties()) return slow_stub();
if (receiver_is_holder) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub);
int index = lookup->GetAccessorIndex();
LoadApiGetterStub stub(isolate(), true, index);
return stub.GetCode();
}
- if (info->is_sloppy() && !receiver->IsJSReceiver()) break;
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
- NamedLoadHandlerCompiler compiler(isolate(), map, holder,
- cache_holder);
- return compiler.CompileLoadCallback(lookup->name(), info);
+ if (info->is_sloppy() && !receiver->IsJSReceiver()) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
+ }
+ break; // Custom-compiled handler.
}
}
- break;
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
}
case LookupIterator::DATA: {
if (lookup->is_dictionary_holder()) {
- if (kind() != Code::LOAD_IC) break;
+ if (kind() != Code::LOAD_IC) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
+ }
if (holder->IsJSGlobalObject()) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
- NamedLoadHandlerCompiler compiler(isolate(), map, holder,
- cache_holder);
- Handle<PropertyCell> cell = lookup->GetPropertyCell();
- Handle<Code> code = compiler.CompileLoadGlobal(
- cell, lookup->name(), lookup->IsConfigurable());
- // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
- CacheHolderFlag flag;
- Handle<Map> stub_holder_map =
- GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag);
- Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
- return code;
+ break; // Custom-compiled handler.
}
// There is only one shared stub for loading normalized
// properties. It does not traverse the prototype chain, so the
// property must be found in the object for the stub to be
// applicable.
- if (!receiver_is_holder) break;
+ if (!receiver_is_holder) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
+ }
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal);
return isolate()->builtins()->LoadIC_Normal();
}
@@ -1134,9 +1113,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
if (receiver_is_holder) {
return SimpleFieldLoad(field);
}
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField);
- NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
- return compiler.CompileLoadField(lookup->name(), field);
+ break; // Custom-compiled handler.
}
// -------------- Constant properties --------------
@@ -1146,6 +1123,128 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
return stub.GetCode();
}
+ break; // Custom-compiled handler.
+ }
+
+ case LookupIterator::INTEGER_INDEXED_EXOTIC:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return slow_stub();
+ case LookupIterator::ACCESS_CHECK:
+ case LookupIterator::JSPROXY:
+ case LookupIterator::NOT_FOUND:
+ case LookupIterator::TRANSITION:
+ UNREACHABLE();
+ }
+
+ return Handle<Code>::null();
+}
+
+Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
+ Handle<Object> unused,
+ CacheHolderFlag cache_holder) {
+ Handle<JSObject> holder = lookup->GetHolder<JSObject>();
+#ifdef DEBUG
+ // Only used by DCHECKs below.
+ Handle<Object> receiver = lookup->GetReceiver();
+ bool receiver_is_holder = receiver.is_identical_to(holder);
+#endif
+ // Non-map-specific handler stubs have already been selected.
+ DCHECK(!receiver->IsString() ||
+ !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
+ DCHECK(!receiver->IsStringWrapper() ||
+ !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
+
+ DCHECK(!(
+ receiver->IsJSFunction() &&
+ Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
+ receiver->IsConstructor() &&
+ !Handle<JSFunction>::cast(receiver)
+ ->map()
+ ->has_non_instance_prototype()));
+
+ Handle<Map> map = receiver_map();
+ switch (lookup->state()) {
+ case LookupIterator::INTERCEPTOR: {
+ DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor);
+ NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+ // Perform a lookup behind the interceptor. Copy the LookupIterator since
+ // the original iterator will be used to fetch the value.
+ LookupIterator it = *lookup;
+ it.Next();
+ LookupForRead(&it);
+ return compiler.CompileLoadInterceptor(&it);
+ }
+
+ case LookupIterator::ACCESSOR: {
+#ifdef DEBUG
+ int object_offset;
+ DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
+ &object_offset));
+ DCHECK(!Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(),
+ &object_offset));
+#endif
+
+ DCHECK(IsCompatibleReceiver(lookup, map));
+ Handle<Object> accessors = lookup->GetAccessors();
+ if (accessors->IsAccessorPair()) {
+ DCHECK(holder->HasFastProperties());
+ DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
+ Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
+ isolate());
+ CallOptimization call_optimization(getter);
+ NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+ if (call_optimization.is_simple_api_call()) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
+ int index = lookup->GetAccessorIndex();
+ return compiler.CompileLoadCallback(lookup->name(), call_optimization,
+ index);
+ }
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
+ int expected_arguments = Handle<JSFunction>::cast(getter)
+ ->shared()
+ ->internal_formal_parameter_count();
+ return compiler.CompileLoadViaGetter(
+ lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
+ } else {
+ DCHECK(accessors->IsAccessorInfo());
+ Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
+ DCHECK(v8::ToCData<Address>(info->getter()) != nullptr);
+ DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
+ DCHECK(holder->HasFastProperties());
+ DCHECK(!receiver_is_holder);
+ DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
+ NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+ return compiler.CompileLoadCallback(lookup->name(), info);
+ }
+ UNREACHABLE();
+ }
+
+ case LookupIterator::DATA: {
+ if (lookup->is_dictionary_holder()) {
+ DCHECK(kind() == Code::LOAD_IC);
+ DCHECK(holder->IsJSGlobalObject());
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
+ NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+ Handle<PropertyCell> cell = lookup->GetPropertyCell();
+ Handle<Code> code = compiler.CompileLoadGlobal(
+ cell, lookup->name(), lookup->IsConfigurable());
+ return code;
+ }
+
+ // -------------- Fields --------------
+ if (lookup->property_details().type() == DATA) {
+ FieldIndex field = lookup->GetFieldIndex();
+ DCHECK(!receiver_is_holder);
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField);
+ NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+ return compiler.CompileLoadField(lookup->name(), field);
+ }
+
+ // -------------- Constant properties --------------
+ DCHECK(lookup->property_details().type() == DATA_CONSTANT);
+ DCHECK(!receiver_is_holder);
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
return compiler.CompileLoadConstant(lookup->name(),
@@ -1153,15 +1252,13 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
}
case LookupIterator::INTEGER_INDEXED_EXOTIC:
- break;
case LookupIterator::ACCESS_CHECK:
case LookupIterator::JSPROXY:
case LookupIterator::NOT_FOUND:
case LookupIterator::TRANSITION:
UNREACHABLE();
}
-
- TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ UNREACHABLE();
return slow_stub();
}
@@ -1513,10 +1610,7 @@ static Handle<Code> PropertyCellStoreHandler(
return code;
}
-
-Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
- Handle<Object> value,
- CacheHolderFlag cache_holder) {
+Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
// This is currently guaranteed by checks in StoreIC::Store.
@@ -1528,27 +1622,17 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
case LookupIterator::TRANSITION: {
auto store_target = lookup->GetStoreTarget();
if (store_target->IsJSGlobalObject()) {
- // TODO(dcarney): this currently just deopts. Use the transition cell.
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
- auto cell = isolate()->factory()->NewPropertyCell();
- cell->set_value(*value);
- auto code = PropertyCellStoreHandler(
- isolate(), store_target, Handle<JSGlobalObject>::cast(store_target),
- lookup->name(), cell, PropertyCellType::kConstant);
- cell->set_value(isolate()->heap()->the_hole_value());
- return code;
+ break; // Custom-compiled handler.
}
- Handle<Map> transition = lookup->transition_map();
// Currently not handled by CompileStoreTransition.
if (!holder->HasFastProperties()) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
DCHECK(lookup->IsCacheableTransition());
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition);
- NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
- return compiler.CompileStoreTransition(transition, lookup->name());
+ break; // Custom-compiled handler.
}
case LookupIterator::INTERCEPTOR: {
@@ -1561,74 +1645,62 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
case LookupIterator::ACCESSOR: {
if (!holder->HasFastProperties()) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
Handle<Object> accessors = lookup->GetAccessors();
if (accessors->IsAccessorInfo()) {
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
- if (v8::ToCData<Address>(info->setter()) == 0) {
- TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0");
- break;
+ if (v8::ToCData<Address>(info->setter()) == nullptr) {
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == nullptr");
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
!lookup->HolderIsReceiverOrHiddenPrototype()) {
TRACE_GENERIC_IC(isolate(), "StoreIC",
"special data property in prototype chain");
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
receiver_map())) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
- if (info->is_sloppy() && !receiver->IsJSReceiver()) break;
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
- NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
- return compiler.CompileStoreCallback(receiver, lookup->name(), info,
- language_mode());
+ if (info->is_sloppy() && !receiver->IsJSReceiver()) {
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
+ }
+ break; // Custom-compiled handler.
} else if (accessors->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
isolate());
if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
CallOptimization call_optimization(setter);
- NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
if (call_optimization.is_simple_api_call()) {
if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
- return compiler.CompileStoreCallback(receiver, lookup->name(),
- call_optimization,
- lookup->GetAccessorIndex());
+ break; // Custom-compiled handler.
}
TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver");
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
- int expected_arguments = JSFunction::cast(*setter)
- ->shared()
- ->internal_formal_parameter_count();
- return compiler.CompileStoreViaSetter(receiver, lookup->name(),
- lookup->GetAccessorIndex(),
- expected_arguments);
+ break; // Custom-compiled handler.
}
- break;
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
}
case LookupIterator::DATA: {
if (lookup->is_dictionary_holder()) {
if (holder->IsJSGlobalObject()) {
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
- DCHECK(holder.is_identical_to(receiver) ||
- receiver->map()->prototype() == *holder);
- auto cell = lookup->GetPropertyCell();
- auto updated_type = PropertyCell::UpdatedType(
- cell, value, lookup->property_details());
- auto code = PropertyCellStoreHandler(
- isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
- lookup->name(), cell, updated_type);
- return code;
+ break; // Custom-compiled handler.
}
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal);
DCHECK(holder.is_identical_to(receiver));
@@ -1649,6 +1721,127 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
lookup->representation());
return stub.GetCode();
}
+ break; // Custom-compiled handler.
+ }
+
+ // -------------- Constant properties --------------
+ DCHECK(lookup->property_details().type() == DATA_CONSTANT);
+ TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return slow_stub();
+ }
+
+ case LookupIterator::INTEGER_INDEXED_EXOTIC:
+ case LookupIterator::ACCESS_CHECK:
+ case LookupIterator::JSPROXY:
+ case LookupIterator::NOT_FOUND:
+ UNREACHABLE();
+ }
+ return Handle<Code>::null();
+}
+
+Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
+ Handle<Object> value,
+ CacheHolderFlag cache_holder) {
+ DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
+
+ // This is currently guaranteed by checks in StoreIC::Store.
+ Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
+ Handle<JSObject> holder = lookup->GetHolder<JSObject>();
+ DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
+
+ switch (lookup->state()) {
+ case LookupIterator::TRANSITION: {
+ auto store_target = lookup->GetStoreTarget();
+ if (store_target->IsJSGlobalObject()) {
+ // TODO(dcarney): this currently just deopts. Use the transition cell.
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
+ auto cell = isolate()->factory()->NewPropertyCell();
+ cell->set_value(*value);
+ auto code = PropertyCellStoreHandler(
+ isolate(), store_target, Handle<JSGlobalObject>::cast(store_target),
+ lookup->name(), cell, PropertyCellType::kConstant);
+ cell->set_value(isolate()->heap()->the_hole_value());
+ return code;
+ }
+ Handle<Map> transition = lookup->transition_map();
+ // Currently not handled by CompileStoreTransition.
+ DCHECK(holder->HasFastProperties());
+
+ DCHECK(lookup->IsCacheableTransition());
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition);
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
+ return compiler.CompileStoreTransition(transition, lookup->name());
+ }
+
+ case LookupIterator::INTERCEPTOR:
+ UNREACHABLE();
+
+ case LookupIterator::ACCESSOR: {
+ DCHECK(holder->HasFastProperties());
+ Handle<Object> accessors = lookup->GetAccessors();
+ if (accessors->IsAccessorInfo()) {
+ Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
+ DCHECK(v8::ToCData<Address>(info->setter()) != 0);
+ DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() ||
+ lookup->HolderIsReceiverOrHiddenPrototype());
+ DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
+ receiver_map()));
+ DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
+ return compiler.CompileStoreCallback(receiver, lookup->name(), info,
+ language_mode());
+ } else {
+ DCHECK(accessors->IsAccessorPair());
+ Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
+ isolate());
+ DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
+ CallOptimization call_optimization(setter);
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
+ if (call_optimization.is_simple_api_call()) {
+ DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder));
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
+ return compiler.CompileStoreCallback(receiver, lookup->name(),
+ call_optimization,
+ lookup->GetAccessorIndex());
+ }
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
+ int expected_arguments = JSFunction::cast(*setter)
+ ->shared()
+ ->internal_formal_parameter_count();
+ return compiler.CompileStoreViaSetter(receiver, lookup->name(),
+ lookup->GetAccessorIndex(),
+ expected_arguments);
+ }
+ }
+
+ case LookupIterator::DATA: {
+ if (lookup->is_dictionary_holder()) {
+ DCHECK(holder->IsJSGlobalObject());
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
+ DCHECK(holder.is_identical_to(receiver) ||
+ receiver->map()->prototype() == *holder);
+ auto cell = lookup->GetPropertyCell();
+ auto updated_type =
+ PropertyCell::UpdatedType(cell, value, lookup->property_details());
+ auto code = PropertyCellStoreHandler(
+ isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
+ lookup->name(), cell, updated_type);
+ return code;
+ }
+
+ // -------------- Fields --------------
+ if (lookup->property_details().type() == DATA) {
+#ifdef DEBUG
+ bool use_stub = true;
+ if (lookup->representation().IsHeapObject()) {
+ // Only use a generic stub if no types need to be tracked.
+ Handle<FieldType> field_type = lookup->GetFieldType();
+ use_stub = !field_type->IsClass();
+ }
+ DCHECK(!use_stub);
+#endif
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField);
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
return compiler.CompileStoreField(lookup);
@@ -1656,8 +1849,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
// -------------- Constant properties --------------
DCHECK(lookup->property_details().type() == DATA_CONSTANT);
- TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
- break;
+ UNREACHABLE();
}
case LookupIterator::INTEGER_INDEXED_EXOTIC:
@@ -1666,7 +1858,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
case LookupIterator::NOT_FOUND:
UNREACHABLE();
}
- TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ UNREACHABLE();
return slow_stub();
}
« no previous file with comments | « src/ic/ic.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698