summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/ic.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ic/ic.cc')
-rw-r--r--deps/v8/src/ic/ic.cc126
1 files changed, 58 insertions, 68 deletions
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc
index 54f4be7a22..4ac5fd7abe 100644
--- a/deps/v8/src/ic/ic.cc
+++ b/deps/v8/src/ic/ic.cc
@@ -15,6 +15,7 @@
#include "src/execution/execution.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
+#include "src/execution/protectors-inl.h"
#include "src/execution/runtime-profiler.h"
#include "src/handles/handles-inl.h"
#include "src/ic/call-optimization.h"
@@ -47,8 +48,6 @@ char IC::TransitionMarkFromState(IC::State state) {
return 'X';
case UNINITIALIZED:
return '0';
- case PREMONOMORPHIC:
- return '.';
case MONOMORPHIC:
return '1';
case RECOMPUTE_HANDLER:
@@ -343,11 +342,6 @@ bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
return changed;
}
-void IC::ConfigureVectorState(Handle<Map> map) {
- nexus()->ConfigurePremonomorphic(map);
- OnFeedbackChanged("Premonomorphic");
-}
-
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Object> handler) {
ConfigureVectorState(name, map, MaybeObjectHandle(handler));
@@ -383,11 +377,11 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
// of its properties; throw a TypeError in that case.
if (IsAnyHas() ? !object->IsJSReceiver()
: object->IsNullOrUndefined(isolate())) {
- if (use_ic && state() != PREMONOMORPHIC) {
+ if (use_ic) {
// Ensure the IC state progresses.
TRACE_HANDLER_STATS(isolate(), LoadIC_NonReceiver);
update_receiver_map(object);
- PatchCache(name, slow_stub());
+ SetCache(name, LoadHandler::LoadSlow(isolate()));
TraceIC("LoadIC", name);
}
@@ -490,7 +484,7 @@ MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
} else {
// Given combination of indices can't be encoded, so use slow stub.
TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_SlowStub);
- PatchCache(name, slow_stub());
+ SetCache(name, LoadHandler::LoadSlow(isolate()));
}
TraceIC("LoadGlobalIC", name);
}
@@ -613,11 +607,11 @@ bool IC::IsTransitionOfMonomorphicTarget(Map source_map, Map target_map) {
return transitioned_map == target_map;
}
-void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
- PatchCache(name, MaybeObjectHandle(handler));
+void IC::SetCache(Handle<Name> name, Handle<Object> handler) {
+ SetCache(name, MaybeObjectHandle(handler));
}
-void IC::PatchCache(Handle<Name> name, const MaybeObjectHandle& handler) {
+void IC::SetCache(Handle<Name> name, const MaybeObjectHandle& handler) {
DCHECK(IsHandler(*handler));
// Currently only load and store ICs support non-code handlers.
DCHECK(IsAnyLoad() || IsAnyStore() || IsAnyHas());
@@ -625,7 +619,6 @@ void IC::PatchCache(Handle<Name> name, const MaybeObjectHandle& handler) {
case NO_FEEDBACK:
UNREACHABLE();
case UNINITIALIZED:
- case PREMONOMORPHIC:
UpdateMonomorphicIC(handler, name);
break;
case RECOMPUTE_HANDLER:
@@ -659,7 +652,7 @@ __attribute__((__aligned__(32)))
void LoadIC::UpdateCaches(LookupIterator* lookup) {
Handle<Object> code;
if (lookup->state() == LookupIterator::ACCESS_CHECK) {
- code = slow_stub();
+ code = LoadHandler::LoadSlow(isolate());
} else if (!lookup->IsFound()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
@@ -683,7 +676,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
code = ComputeHandler(lookup);
}
- PatchCache(lookup->name(), code);
+ SetCache(lookup->name(), code);
TraceIC("LoadIC", lookup->name());
}
@@ -798,7 +791,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
isolate());
if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
- return slow_stub();
+ return LoadHandler::LoadSlow(isolate());
}
if ((getter->IsFunctionTemplateInfo() &&
@@ -807,7 +800,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
JSFunction::cast(*getter).shared().BreakAtEntry())) {
// Do not install an IC if the api function has a breakpoint.
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
- return slow_stub();
+ return LoadHandler::LoadSlow(isolate());
}
Handle<Smi> smi_handler;
@@ -817,7 +810,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
!holder->HasFastProperties()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
- return slow_stub();
+ return LoadHandler::LoadSlow(isolate());
}
CallOptimization::HolderLookup holder_lookup;
@@ -868,7 +861,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
!holder->HasFastProperties() ||
(info->is_sloppy() && !receiver->IsJSReceiver())) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
- return slow_stub();
+ return LoadHandler::LoadSlow(isolate());
}
Handle<Smi> smi_handler = LoadHandler::LoadNativeDataProperty(
@@ -1076,7 +1069,7 @@ bool AllowConvertHoleElementToUndefined(Isolate* isolate,
}
// For other {receiver}s we need to check the "no elements" protector.
- if (isolate->IsNoElementsProtectorIntact()) {
+ if (Protectors::IsNoElementsIntact(isolate)) {
if (receiver_map->IsStringMap()) {
return true;
}
@@ -1315,12 +1308,11 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
case LookupIterator::INTERCEPTOR: {
Handle<JSObject> holder = it->GetHolder<JSObject>();
InterceptorInfo info = holder->GetNamedInterceptor();
- if (it->HolderIsReceiverOrHiddenPrototype()) {
- return !info.non_masking() && receiver.is_identical_to(holder) &&
- !info.setter().IsUndefined(isolate());
- } else if (!info.getter().IsUndefined(isolate()) ||
- !info.query().IsUndefined(isolate())) {
- return false;
+ if ((it->HolderIsReceiverOrHiddenPrototype() &&
+ !info.non_masking()) ||
+ !info.getter().IsUndefined(isolate()) ||
+ !info.query().IsUndefined(isolate())) {
+ return true;
}
break;
}
@@ -1403,7 +1395,7 @@ MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
} else {
// Given combination of indices can't be encoded, so use slow stub.
TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_SlowStub);
- PatchCache(name, slow_stub());
+ SetCache(name, StoreHandler::StoreSlow(isolate()));
}
TraceIC("StoreGlobalIC", name);
}
@@ -1432,11 +1424,11 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
// If the object is undefined or null it's illegal to try to set any
// properties on it; throw a TypeError in that case.
if (object->IsNullOrUndefined(isolate())) {
- if (use_ic && state() != PREMONOMORPHIC) {
+ if (use_ic) {
// Ensure the IC state progresses.
TRACE_HANDLER_STATS(isolate(), StoreIC_NonReceiver);
update_receiver_map(object);
- PatchCache(name, slow_stub());
+ SetCache(name, StoreHandler::StoreSlow(isolate()));
TraceIC("StoreIC", name);
}
return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
@@ -1481,30 +1473,11 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
}
handler = ComputeHandler(lookup);
} else {
- if (state() == UNINITIALIZED && IsStoreGlobalIC() &&
- lookup->state() == LookupIterator::INTERCEPTOR) {
- InterceptorInfo info =
- lookup->GetHolder<JSObject>()->GetNamedInterceptor();
- if (!lookup->HolderIsReceiverOrHiddenPrototype() &&
- !info.getter().IsUndefined(isolate())) {
- // Utilize premonomorphic state for global store ics that run into
- // an interceptor because the property doesn't exist yet.
- // After we actually set the property, we'll have more information.
- // Premonomorphism gives us a chance to find more information the
- // second time.
- TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_Premonomorphic);
- ConfigureVectorState(receiver_map());
- TraceIC("StoreGlobalIC", lookup->name());
- return;
- }
- }
-
set_slow_stub_reason("LookupForWrite said 'false'");
- // TODO(marja): change slow_stub to return MaybeObjectHandle.
- handler = MaybeObjectHandle(slow_stub());
+ handler = MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
- PatchCache(lookup->name(), handler);
+ SetCache(lookup->name(), handler);
TraceIC("StoreIC", lookup->name());
}
@@ -1542,12 +1515,27 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
case LookupIterator::INTERCEPTOR: {
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
- USE(holder);
+ InterceptorInfo info = holder->GetNamedInterceptor();
+
+ // If the interceptor is on the receiver
+ if (lookup->HolderIsReceiverOrHiddenPrototype() && !info.non_masking()) {
+ // return a store interceptor smi handler if there is one,
+ if (!info.setter().IsUndefined(isolate())) {
+ return MaybeObjectHandle(StoreHandler::StoreInterceptor(isolate()));
+ }
+ // otherwise return a slow-case smi handler.
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
+ }
- DCHECK(!holder->GetNamedInterceptor().setter().IsUndefined(isolate()));
- // TODO(jgruber): Update counter name.
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
- return MaybeObjectHandle(BUILTIN_CODE(isolate(), StoreInterceptorIC));
+ // If the interceptor is a getter/query interceptor on the prototype
+ // chain, return an invalidatable slow handler so it can turn fast if the
+ // interceptor is masked by a regular property later.
+ DCHECK(!info.getter().IsUndefined(isolate()) ||
+ !info.query().IsUndefined(isolate()));
+ Handle<Object> handler = StoreHandler::StoreThroughPrototype(
+ isolate(), receiver_map(), holder,
+ StoreHandler::StoreSlow(isolate()));
+ return MaybeObjectHandle(handler);
}
case LookupIterator::ACCESSOR: {
@@ -1559,7 +1547,9 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
if (!holder->HasFastProperties()) {
set_slow_stub_reason("accessor on slow map");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ MaybeObjectHandle handler =
+ MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
+ return handler;
}
Handle<Object> accessors = lookup->GetAccessors();
if (accessors->IsAccessorInfo()) {
@@ -1567,18 +1557,18 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
if (v8::ToCData<Address>(info->setter()) == kNullAddress) {
set_slow_stub_reason("setter == kNullAddress");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
if (AccessorInfo::cast(*accessors).is_special_data_property() &&
!lookup->HolderIsReceiverOrHiddenPrototype()) {
set_slow_stub_reason("special data property in prototype chain");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
if (!AccessorInfo::IsCompatibleReceiverMap(info, receiver_map())) {
set_slow_stub_reason("incompatible receiver type");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
Handle<Smi> smi_handler = StoreHandler::StoreNativeDataProperty(
@@ -1598,7 +1588,7 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
set_slow_stub_reason("setter not a function");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
if ((setter->IsFunctionTemplateInfo() &&
@@ -1607,7 +1597,7 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
JSFunction::cast(*setter).shared().BreakAtEntry())) {
// Do not install an IC if the api function has a breakpoint.
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
CallOptimization call_optimization(isolate(), setter);
@@ -1631,11 +1621,11 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
}
set_slow_stub_reason("incompatible receiver");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
} else if (setter->IsFunctionTemplateInfo()) {
set_slow_stub_reason("setter non-simple template");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
Handle<Smi> smi_handler =
@@ -1651,7 +1641,7 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
isolate(), receiver_map(), holder, smi_handler));
}
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
case LookupIterator::DATA: {
@@ -1694,7 +1684,7 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
DCHECK_EQ(kDescriptor, lookup->property_details().location());
set_slow_stub_reason("constant property");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
- return MaybeObjectHandle(slow_stub());
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
}
case LookupIterator::JSPROXY: {
Handle<JSReceiver> receiver =
@@ -1905,7 +1895,7 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
// TODO(mvstanton): Consider embedding store_mode in the state of the slow
// keyed store ic for uniformity.
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
- handler = slow_stub();
+ handler = StoreHandler::StoreSlow(isolate());
} else {
{
@@ -2532,7 +2522,7 @@ static bool CanFastCloneObject(Handle<Map> map) {
}
DescriptorArray descriptors = map->instance_descriptors();
- for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
PropertyDetails details = descriptors.GetDetails(i);
Name key = descriptors.GetKey(i);
if (details.kind() != kData || !details.IsEnumerable() ||