summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/ic.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-02-14 11:27:26 +0100
committerMichaël Zasso <targos@protonmail.com>2017-02-22 15:55:42 +0100
commit7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch)
treee7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/src/ic/ic.cc
parent5f08871ee93ea739148cc49e0f7679e33c70295a (diff)
downloadnode-new-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/ic/ic.cc')
-rw-r--r--deps/v8/src/ic/ic.cc657
1 files changed, 499 insertions, 158 deletions
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc
index 0e751bd358..7e0cefdca9 100644
--- a/deps/v8/src/ic/ic.cc
+++ b/deps/v8/src/ic/ic.cc
@@ -4,6 +4,8 @@
#include "src/ic/ic.h"
+#include <iostream>
+
#include "src/accessors.h"
#include "src/api-arguments-inl.h"
#include "src/api.h"
@@ -16,6 +18,7 @@
#include "src/frames-inl.h"
#include "src/ic/call-optimization.h"
#include "src/ic/handler-compiler.h"
+#include "src/ic/handler-configuration-inl.h"
#include "src/ic/ic-compiler.h"
#include "src/ic/ic-inl.h"
#include "src/ic/stub-cache.h"
@@ -98,38 +101,51 @@ void IC::TraceIC(const char* type, Handle<Object> name) {
void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
State new_state) {
- if (FLAG_trace_ic) {
- PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type);
-
- // TODO(jkummerow): Add support for "apply". The logic is roughly:
- // marker = [fp_ + kMarkerOffset];
- // if marker is smi and marker.value == INTERNAL and
- // the frame's code == builtin(Builtins::kFunctionApply):
- // then print "apply from" and advance one frame
-
- Object* maybe_function =
- Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
- if (maybe_function->IsJSFunction()) {
- JSFunction* function = JSFunction::cast(maybe_function);
- JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
- stdout, true);
+ if (!FLAG_trace_ic) return;
+ PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type);
+
+ // TODO(jkummerow): Add support for "apply". The logic is roughly:
+ // marker = [fp_ + kMarkerOffset];
+ // if marker is smi and marker.value == INTERNAL and
+ // the frame's code == builtin(Builtins::kFunctionApply):
+ // then print "apply from" and advance one frame
+
+ Object* maybe_function =
+ Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
+ if (maybe_function->IsJSFunction()) {
+ JSFunction* function = JSFunction::cast(maybe_function);
+ int code_offset = 0;
+ if (function->IsInterpreted()) {
+ code_offset = InterpretedFrame::GetBytecodeOffset(fp());
+ } else {
+ code_offset =
+ static_cast<int>(pc() - function->code()->instruction_start());
}
+ JavaScriptFrame::PrintFunctionAndOffset(function, function->abstract_code(),
+ code_offset, stdout, true);
+ }
- const char* modifier = "";
- if (kind() == Code::KEYED_STORE_IC) {
- KeyedAccessStoreMode mode =
- casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
- modifier = GetTransitionMarkModifier(mode);
- }
- void* map = nullptr;
- if (!receiver_map().is_null()) {
- map = reinterpret_cast<void*>(*receiver_map());
- }
- PrintF(" (%c->%c%s) map=%p ", TransitionMarkFromState(old_state),
- TransitionMarkFromState(new_state), modifier, map);
- name->ShortPrint(stdout);
- PrintF("]\n");
+ const char* modifier = "";
+ if (kind() == Code::KEYED_STORE_IC) {
+ KeyedAccessStoreMode mode =
+ casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
+ modifier = GetTransitionMarkModifier(mode);
}
+ Map* map = nullptr;
+ if (!receiver_map().is_null()) {
+ map = *receiver_map();
+ }
+ PrintF(" (%c->%c%s) map=(%p", TransitionMarkFromState(old_state),
+ TransitionMarkFromState(new_state), modifier,
+ reinterpret_cast<void*>(map));
+ if (map != nullptr) {
+ PrintF(" dict=%u own=%u type=", map->is_dictionary_map(),
+ map->NumberOfOwnDescriptors());
+ std::cout << map->instance_type();
+ }
+ PrintF(") ");
+ name->ShortPrint(stdout);
+ PrintF("]\n");
}
@@ -171,6 +187,16 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
StackFrame* frame = it.frame();
DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
#endif
+ // For interpreted functions, some bytecode handlers construct a
+ // frame. We have to skip the constructed frame to find the interpreted
+ // function's frame. Check if the there is an additional frame, and if there
+ // is skip this frame. However, the pc should not be updated. The call to
+ // ICs happen from bytecode handlers.
+ Object* frame_type =
+ Memory::Object_at(fp + TypedFrameConstants::kFrameTypeOffset);
+ if (frame_type == Smi::FromInt(StackFrame::STUB)) {
+ fp = Memory::Address_at(fp + TypedFrameConstants::kCallerFPOffset);
+ }
fp_ = fp;
if (FLAG_enable_embedded_constant_pool) {
constant_pool_address_ = constant_pool;
@@ -224,11 +250,6 @@ SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
// corresponding to the frame.
StackFrameIterator it(isolate());
while (it.frame()->fp() != this->fp()) it.Advance();
- if (FLAG_ignition && it.frame()->type() == StackFrame::STUB) {
- // Advance over bytecode handler frame.
- // TODO(rmcilroy): Remove this once bytecode handlers don't need a frame.
- it.Advance();
- }
JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
// Find the function on the stack and both the active code for the
// function and the original code.
@@ -504,19 +525,6 @@ void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK);
}
-
-// static
-Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate,
- ExtraICState extra_state) {
- // TODO(ishell): remove extra_ic_state
- if (FLAG_compiled_keyed_generic_loads) {
- return KeyedLoadGenericStub(isolate).GetCode();
- } else {
- return isolate->builtins()->KeyedLoadIC_Megamorphic();
- }
-}
-
-
static bool MigrateDeprecated(Handle<Object> object) {
if (!object->IsJSObject()) return false;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
@@ -562,11 +570,11 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
nexus->ConfigureMonomorphic(name, map, handler);
} else if (kind() == Code::STORE_IC) {
StoreICNexus* nexus = casted_nexus<StoreICNexus>();
- nexus->ConfigureMonomorphic(map, Handle<Code>::cast(handler));
+ nexus->ConfigureMonomorphic(map, handler);
} else {
DCHECK(kind() == Code::KEYED_STORE_IC);
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
- nexus->ConfigureMonomorphic(name, map, Handle<Code>::cast(handler));
+ nexus->ConfigureMonomorphic(name, map, handler);
}
vector_set_ = true;
@@ -691,11 +699,8 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
return true;
}
-bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) {
- DCHECK(code->IsSmi() || code->IsCode());
- if (!code->IsSmi() && !Code::cast(*code)->is_handler()) {
- return false;
- }
+bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) {
+ DCHECK(IsHandler(*handler));
if (is_keyed() && state() != RECOMPUTE_HANDLER) return false;
Handle<Map> map = receiver_map();
MapHandleList maps;
@@ -735,16 +740,16 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) {
number_of_valid_maps++;
if (number_of_valid_maps > 1 && is_keyed()) return false;
if (number_of_valid_maps == 1) {
- ConfigureVectorState(name, receiver_map(), code);
+ ConfigureVectorState(name, receiver_map(), handler);
} else {
if (handler_to_overwrite >= 0) {
- handlers.Set(handler_to_overwrite, code);
+ handlers.Set(handler_to_overwrite, handler);
if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
maps.Set(handler_to_overwrite, map);
}
} else {
maps.Add(map);
- handlers.Add(code);
+ handlers.Add(handler);
}
ConfigureVectorState(name, &maps, &handlers);
@@ -754,8 +759,7 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) {
}
void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
- DCHECK(handler->IsSmi() ||
- (handler->IsCode() && Handle<Code>::cast(handler)->is_handler()));
+ DCHECK(IsHandler(*handler));
ConfigureVectorState(name, receiver_map(), handler);
}
@@ -786,24 +790,28 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
return transitioned_map == target_map;
}
-void IC::PatchCache(Handle<Name> name, Handle<Object> code) {
- DCHECK(code->IsCode() || (code->IsSmi() && (kind() == Code::LOAD_IC ||
- kind() == Code::KEYED_LOAD_IC)));
+void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
+ DCHECK(IsHandler(*handler));
+ // Currently only LoadIC and KeyedLoadIC support non-code handlers.
+ DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC ||
+ kind() == Code::KEYED_LOAD_IC ||
+ kind() == Code::STORE_IC ||
+ kind() == Code::KEYED_STORE_IC);
switch (state()) {
case UNINITIALIZED:
case PREMONOMORPHIC:
- UpdateMonomorphicIC(code, name);
+ UpdateMonomorphicIC(handler, name);
break;
case RECOMPUTE_HANDLER:
case MONOMORPHIC:
if (kind() == Code::LOAD_GLOBAL_IC) {
- UpdateMonomorphicIC(code, name);
+ UpdateMonomorphicIC(handler, name);
break;
}
// Fall through.
case POLYMORPHIC:
if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
- if (UpdatePolymorphicIC(name, code)) break;
+ if (UpdatePolymorphicIC(name, handler)) break;
// For keyed stubs, we can't know whether old handlers were for the
// same key.
CopyICToMegamorphicCache(name);
@@ -812,7 +820,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> code) {
ConfigureVectorState(MEGAMORPHIC, name);
// Fall through.
case MEGAMORPHIC:
- UpdateMegamorphicCache(*receiver_map(), *name, *code);
+ UpdateMegamorphicCache(*receiver_map(), *name, *handler);
// Indicate that we've handled this case.
DCHECK(UseVector());
vector_set_ = true;
@@ -825,6 +833,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> code) {
Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
ExtraICState extra_state) {
+ DCHECK(!FLAG_tf_store_ic_stub);
LanguageMode mode = StoreICState::GetLanguageMode(extra_state);
return is_strict(mode)
? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
@@ -833,13 +842,186 @@ Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
if (FLAG_tf_load_ic_stub) {
- return handle(Smi::FromInt(index.GetLoadByFieldOffset()), isolate());
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
+ return LoadHandler::LoadField(isolate(), index);
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
LoadFieldStub stub(isolate(), index);
return stub.GetCode();
}
+namespace {
+
+template <bool fill_array = true>
+int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
+ Handle<JSObject> holder, Handle<Name> name,
+ Handle<FixedArray> array, int first_index) {
+ DCHECK(holder.is_null() || holder->HasFastProperties());
+
+ // We don't encode the requirement to check access rights because we already
+ // passed the access check for current native context and the access
+ // can't be revoked.
+
+ HandleScope scope(isolate);
+ int checks_count = 0;
+
+ if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
+ // The validity cell check for primitive and global proxy receivers does
+ // not guarantee that certain native context ever had access to other
+ // native context. However, a handler created for one native context could
+ // be used in other native context through the megamorphic stub cache.
+ // So we record the original native context to which this handler
+ // corresponds.
+ if (fill_array) {
+ Handle<Context> native_context = isolate->native_context();
+ array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
+ native_context->self_weak_cell());
+ }
+ checks_count++;
+
+ } else if (receiver_map->IsJSGlobalObjectMap()) {
+ if (fill_array) {
+ Handle<JSGlobalObject> global = isolate->global_object();
+ Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
+ global, name, PropertyCellType::kInvalidated);
+ DCHECK(cell->value()->IsTheHole(isolate));
+ Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
+ array->set(LoadHandler::kFirstPrototypeIndex + checks_count, *weak_cell);
+ }
+ checks_count++;
+ }
+
+ // Create/count entries for each global or dictionary prototype appeared in
+ // the prototype chain contains from receiver till holder.
+ PrototypeIterator::WhereToEnd end = name->IsPrivate()
+ ? PrototypeIterator::END_AT_NON_HIDDEN
+ : PrototypeIterator::END_AT_NULL;
+ for (PrototypeIterator iter(receiver_map, end); !iter.IsAtEnd();
+ iter.Advance()) {
+ Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
+ if (holder.is_identical_to(current)) break;
+ Handle<Map> current_map(current->map(), isolate);
+
+ if (current_map->IsJSGlobalObjectMap()) {
+ if (fill_array) {
+ Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
+ Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
+ global, name, PropertyCellType::kInvalidated);
+ DCHECK(cell->value()->IsTheHole(isolate));
+ Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
+ array->set(first_index + checks_count, *weak_cell);
+ }
+ checks_count++;
+
+ } else if (current_map->is_dictionary_map()) {
+ DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
+ if (fill_array) {
+ DCHECK_EQ(NameDictionary::kNotFound,
+ current->property_dictionary()->FindEntry(name));
+ Handle<WeakCell> weak_cell =
+ Map::GetOrCreatePrototypeWeakCell(current, isolate);
+ array->set(first_index + checks_count, *weak_cell);
+ }
+ checks_count++;
+ }
+ }
+ return checks_count;
+}
+
+// Returns 0 if the validity cell check is enough to ensure that the
+// prototype chain from |receiver_map| till |holder| did not change.
+// If the |holder| is an empty handle then the full prototype chain is
+// checked.
+// Returns -1 if the handler has to be compiled or the number of prototype
+// checks otherwise.
+int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
+ Handle<JSObject> holder, Handle<Name> name) {
+ return InitPrototypeChecks<false>(isolate, receiver_map, holder, name,
+ Handle<FixedArray>(), 0);
+}
+
+} // namespace
+
+Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
+ Handle<JSObject> holder,
+ Handle<Name> name,
+ Handle<Object> smi_handler) {
+ int checks_count =
+ GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
+ DCHECK_LE(0, checks_count);
+
+ if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
+ DCHECK(!receiver_map->is_dictionary_map());
+ DCHECK_LE(1, checks_count); // For native context.
+ smi_handler =
+ LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
+ } else if (receiver_map->is_dictionary_map() &&
+ !receiver_map->IsJSGlobalObjectMap()) {
+ smi_handler =
+ LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
+ }
+
+ Handle<Cell> validity_cell =
+ Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+ DCHECK(!validity_cell.is_null());
+
+ Handle<WeakCell> holder_cell =
+ Map::GetOrCreatePrototypeWeakCell(holder, isolate());
+
+ if (checks_count == 0) {
+ return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
+ validity_cell);
+ }
+ Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
+ LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
+ handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
+ handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
+ handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
+ InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
+ LoadHandler::kFirstPrototypeIndex);
+ return handler_array;
+}
+
+Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
+ Handle<Name> name) {
+ Handle<JSObject> holder; // null handle
+ int checks_count =
+ GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
+ DCHECK_LE(0, checks_count);
+
+ bool do_negative_lookup_on_receiver =
+ receiver_map->is_dictionary_map() && !receiver_map->IsJSGlobalObjectMap();
+ Handle<Object> smi_handler =
+ LoadHandler::LoadNonExistent(isolate(), do_negative_lookup_on_receiver);
+
+ if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
+ DCHECK(!receiver_map->is_dictionary_map());
+ DCHECK_LE(1, checks_count); // For native context.
+ smi_handler =
+ LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
+ }
+
+ Handle<Object> validity_cell =
+ Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+ if (validity_cell.is_null()) {
+ DCHECK_EQ(0, checks_count);
+ validity_cell = handle(Smi::FromInt(0), isolate());
+ }
+
+ Factory* factory = isolate()->factory();
+ if (checks_count == 0) {
+ return factory->NewTuple3(factory->null_value(), smi_handler,
+ validity_cell);
+ }
+ Handle<FixedArray> handler_array(factory->NewFixedArray(
+ LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
+ handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
+ handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
+ handler_array->set(LoadHandler::kHolderCellIndex, *factory->null_value());
+ InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
+ LoadHandler::kFirstPrototypeIndex);
+ return handler_array;
+}
bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
DCHECK(lookup->state() == LookupIterator::ACCESSOR);
@@ -884,6 +1066,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) {
// This is the first time we execute this inline cache. Set the target to
// the pre monomorphic stub to delay setting the monomorphic state.
+ TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic);
ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
TRACE_IC("LoadIC", lookup->name());
return;
@@ -894,7 +1077,10 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
lookup->state() == LookupIterator::ACCESS_CHECK) {
code = slow_stub();
} else if (!lookup->IsFound()) {
- if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) {
+ if (kind() == Code::LOAD_IC) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
+ code = LoadNonExistent(receiver_map(), lookup->name());
+ } else if (kind() == Code::LOAD_GLOBAL_IC) {
code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
receiver_map());
// TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
@@ -964,30 +1150,80 @@ StubCache* IC::stub_cache() {
return nullptr;
}
-void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* code) {
- if (code->IsSmi()) {
- // TODO(jkummerow): Support Smis in the code cache.
- Handle<Map> map_handle(map, isolate());
- Handle<Name> name_handle(name, isolate());
- FieldIndex index =
- FieldIndex::ForLoadByFieldOffset(map, Smi::cast(code)->value());
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
- LoadFieldStub stub(isolate(), index);
- Code* handler = *stub.GetCode();
- stub_cache()->Set(*name_handle, *map_handle, handler);
- return;
+void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) {
+ stub_cache()->Set(name, map, handler);
+}
+
+void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
+ if (!FLAG_runtime_call_stats) return;
+
+ if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC ||
+ kind() == Code::KEYED_LOAD_IC) {
+ switch (lookup->state()) {
+ case LookupIterator::ACCESS_CHECK:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_AccessCheck);
+ break;
+ case LookupIterator::INTEGER_INDEXED_EXOTIC:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Exotic);
+ break;
+ case LookupIterator::INTERCEPTOR:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Interceptor);
+ break;
+ case LookupIterator::JSPROXY:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_JSProxy);
+ break;
+ case LookupIterator::NOT_FOUND:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_NonExistent);
+ break;
+ case LookupIterator::ACCESSOR:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor);
+ break;
+ case LookupIterator::DATA:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Data);
+ break;
+ case LookupIterator::TRANSITION:
+ TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Transition);
+ break;
+ }
+ } else if (kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC) {
+ switch (lookup->state()) {
+ case LookupIterator::ACCESS_CHECK:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_AccessCheck);
+ break;
+ case LookupIterator::INTEGER_INDEXED_EXOTIC:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Exotic);
+ break;
+ case LookupIterator::INTERCEPTOR:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Interceptor);
+ break;
+ case LookupIterator::JSPROXY:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_JSProxy);
+ break;
+ case LookupIterator::NOT_FOUND:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_NonExistent);
+ break;
+ case LookupIterator::ACCESSOR:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor);
+ break;
+ case LookupIterator::DATA:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Data);
+ break;
+ case LookupIterator::TRANSITION:
+ TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Transition);
+ break;
+ }
+ } else {
+ TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
}
- DCHECK(code->IsCode());
- stub_cache()->Set(name, map, Code::cast(code));
}
Handle<Object> IC::ComputeHandler(LookupIterator* lookup,
Handle<Object> value) {
// Try to find a globally shared handler stub.
- Handle<Object> handler_or_index = GetMapIndependentHandler(lookup);
- if (!handler_or_index.is_null()) {
- DCHECK(handler_or_index->IsCode() || handler_or_index->IsSmi());
- return handler_or_index;
+ Handle<Object> shared_handler = GetMapIndependentHandler(lookup);
+ if (!shared_handler.is_null()) {
+ DCHECK(IC::IsHandler(*shared_handler));
+ return shared_handler;
}
// Otherwise check the map's handler cache for a map-specific handler, and
@@ -1007,16 +1243,16 @@ Handle<Object> IC::ComputeHandler(LookupIterator* lookup,
stub_holder_map = receiver_map();
}
- Handle<Code> code = PropertyHandlerCompiler::Find(
+ Handle<Object> handler = 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()) {
- Handle<Object> handler;
- if (maybe_handler_.ToHandle(&handler)) {
- if (!handler.is_identical_to(code)) {
- TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
- return code;
+ if (!handler.is_null()) {
+ Handle<Object> current_handler;
+ if (maybe_handler_.ToHandle(&current_handler)) {
+ if (!current_handler.is_identical_to(handler)) {
+ TraceHandlerCacheHitStats(lookup);
+ return handler;
}
} else {
// maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
@@ -1024,24 +1260,27 @@ Handle<Object> IC::ComputeHandler(LookupIterator* lookup,
// cache (which just missed) is different from the cached handler.
if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
- Code* megamorphic_cached_code = stub_cache()->Get(*lookup->name(), map);
- if (megamorphic_cached_code != *code) {
- TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
- return code;
+ Object* megamorphic_cached_handler =
+ stub_cache()->Get(*lookup->name(), map);
+ if (megamorphic_cached_handler != *handler) {
+ TraceHandlerCacheHitStats(lookup);
+ return handler;
}
} else {
- TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
- return code;
+ TraceHandlerCacheHitStats(lookup);
+ return handler;
}
}
}
- code = CompileHandler(lookup, value, flag);
- DCHECK(code->is_handler());
- DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag);
- Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
-
- return code;
+ handler = CompileHandler(lookup, value, flag);
+ DCHECK(IC::IsHandler(*handler));
+ if (handler->IsCode()) {
+ Handle<Code> code = Handle<Code>::cast(handler);
+ DCHECK_EQ(Code::ExtractCacheHolderFromFlags(code->flags()), flag);
+ Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
+ }
+ return handler;
}
Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
@@ -1111,17 +1350,33 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
}
// 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()) {
+ if (!holder->HasFastProperties() ||
+ (info->is_sloppy() && !receiver->IsJSReceiver())) {
+ DCHECK(!holder->HasFastProperties() || !receiver_is_holder);
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
return slow_stub();
}
+ if (FLAG_tf_load_ic_stub) {
+ Handle<Object> smi_handler = LoadHandler::LoadApiGetter(
+ isolate(), lookup->GetAccessorIndex());
+ if (receiver_is_holder) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterDH);
+ return smi_handler;
+ }
+ if (kind() != Code::LOAD_GLOBAL_IC) {
+ TRACE_HANDLER_STATS(isolate(),
+ LoadIC_LoadApiGetterFromPrototypeDH);
+ return LoadFromPrototype(map, holder, lookup->name(),
+ smi_handler);
+ }
+ } else {
+ if (receiver_is_holder) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub);
+ int index = lookup->GetAccessorIndex();
+ LoadApiGetterStub stub(isolate(), true, index);
+ return stub.GetCode();
+ }
+ }
break; // Custom-compiled handler.
}
}
@@ -1153,18 +1408,36 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
// -------------- Fields --------------
if (lookup->property_details().type() == DATA) {
FieldIndex field = lookup->GetFieldIndex();
+ Handle<Object> smi_handler = SimpleFieldLoad(field);
if (receiver_is_holder) {
- return SimpleFieldLoad(field);
+ return smi_handler;
+ }
+ if (FLAG_tf_load_ic_stub && kind() != Code::LOAD_GLOBAL_IC) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
+ return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
}
break; // Custom-compiled handler.
}
// -------------- Constant properties --------------
DCHECK(lookup->property_details().type() == DATA_CONSTANT);
- if (receiver_is_holder) {
- TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
- LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
- return stub.GetCode();
+ if (FLAG_tf_load_ic_stub) {
+ Handle<Object> smi_handler =
+ LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
+ if (receiver_is_holder) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
+ return smi_handler;
+ }
+ if (kind() != Code::LOAD_GLOBAL_IC) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
+ return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
+ }
+ } else {
+ if (receiver_is_holder) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
+ LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
+ return stub.GetCode();
+ }
}
break; // Custom-compiled handler.
}
@@ -1182,9 +1455,9 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
return Handle<Code>::null();
}
-Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
- Handle<Object> unused,
- CacheHolderFlag cache_holder) {
+Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
+ Handle<Object> unused,
+ CacheHolderFlag cache_holder) {
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
#ifdef DEBUG
// Only used by DCHECKs below.
@@ -1229,6 +1502,10 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
DCHECK(IsCompatibleReceiver(lookup, map));
Handle<Object> accessors = lookup->GetAccessors();
if (accessors->IsAccessorPair()) {
+ if (lookup->TryLookupCachedProperty()) {
+ DCHECK_EQ(LookupIterator::DATA, lookup->state());
+ return ComputeHandler(lookup);
+ }
DCHECK(holder->HasFastProperties());
DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
@@ -1421,7 +1698,9 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
if ((object->IsJSObject() && key->IsSmi()) ||
(object->IsString() && key->IsNumber())) {
UpdateLoadElement(Handle<HeapObject>::cast(object));
- TRACE_IC("LoadIC", key);
+ if (is_vector_set()) {
+ TRACE_IC("LoadIC", key);
+ }
}
}
@@ -1580,6 +1859,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
if (state() == UNINITIALIZED) {
// This is the first time we execute this inline cache. Set the target to
// the pre monomorphic stub to delay setting the monomorphic state.
+ TRACE_HANDLER_STATS(isolate(), StoreIC_Premonomorphic);
ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
TRACE_IC("StoreIC", lookup->name());
return;
@@ -1589,13 +1869,72 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
if (!use_ic) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'");
}
- Handle<Code> code =
- use_ic ? Handle<Code>::cast(ComputeHandler(lookup, value)) : slow_stub();
+ Handle<Object> handler = use_ic ? ComputeHandler(lookup, value)
+ : Handle<Object>::cast(slow_stub());
- PatchCache(lookup->name(), code);
+ PatchCache(lookup->name(), handler);
TRACE_IC("StoreIC", lookup->name());
}
+Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
+ Handle<JSObject> holder,
+ Handle<Map> transition,
+ Handle<Name> name) {
+ int descriptor = transition->LastAdded();
+ Handle<DescriptorArray> descriptors(transition->instance_descriptors());
+ PropertyDetails details = descriptors->GetDetails(descriptor);
+ Representation representation = details.representation();
+ DCHECK(!representation.IsNone());
+
+ // Declarative handlers don't support access checks.
+ DCHECK(!transition->is_access_check_needed());
+
+ Handle<Object> smi_handler;
+ if (details.type() == DATA_CONSTANT) {
+ smi_handler = StoreHandler::TransitionToConstant(isolate(), descriptor);
+
+ } else {
+ DCHECK_EQ(DATA, details.type());
+ bool extend_storage =
+ Map::cast(transition->GetBackPointer())->unused_property_fields() == 0;
+
+ FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
+ smi_handler = StoreHandler::TransitionToField(
+ isolate(), descriptor, index, representation, extend_storage);
+ }
+ // |holder| is either a receiver if the property is non-existent or
+ // one of the prototypes.
+ DCHECK(!holder.is_null());
+ bool is_nonexistent = holder->map() == transition->GetBackPointer();
+ if (is_nonexistent) holder = Handle<JSObject>::null();
+
+ int checks_count =
+ GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
+ DCHECK_LE(0, checks_count);
+ DCHECK(!receiver_map->IsJSGlobalObjectMap());
+
+ Handle<Object> validity_cell =
+ Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+ if (validity_cell.is_null()) {
+ DCHECK_EQ(0, checks_count);
+ validity_cell = handle(Smi::FromInt(0), isolate());
+ }
+
+ Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition);
+
+ Factory* factory = isolate()->factory();
+ if (checks_count == 0) {
+ return factory->NewTuple3(transition_cell, smi_handler, validity_cell);
+ }
+ Handle<FixedArray> handler_array(factory->NewFixedArray(
+ StoreHandler::kFirstPrototypeIndex + checks_count, TENURED));
+ handler_array->set(StoreHandler::kSmiHandlerIndex, *smi_handler);
+ handler_array->set(StoreHandler::kValidityCellIndex, *validity_cell);
+ handler_array->set(StoreHandler::kTransitionCellIndex, *transition_cell);
+ InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
+ StoreHandler::kFirstPrototypeIndex);
+ return handler_array;
+}
static Handle<Code> PropertyCellStoreHandler(
Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder,
@@ -1632,8 +1971,13 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
}
-
DCHECK(lookup->IsCacheableTransition());
+ if (FLAG_tf_store_ic_stub) {
+ Handle<Map> transition = lookup->transition_map();
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransitionDH);
+ return StoreTransition(receiver_map(), holder, transition,
+ lookup->name());
+ }
break; // Custom-compiled handler.
}
@@ -1711,17 +2055,25 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
// -------------- Fields --------------
if (lookup->property_details().type() == DATA) {
- 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();
- }
- if (use_stub) {
- TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub);
- StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
- lookup->representation());
- return stub.GetCode();
+ if (FLAG_tf_store_ic_stub) {
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH);
+ int descriptor = lookup->GetFieldDescriptorIndex();
+ FieldIndex index = lookup->GetFieldIndex();
+ return StoreHandler::StoreField(isolate(), descriptor, index,
+ lookup->representation());
+ } else {
+ 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();
+ }
+ if (use_stub) {
+ TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub);
+ StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+ lookup->representation());
+ return stub.GetCode();
+ }
}
break; // Custom-compiled handler.
}
@@ -1742,9 +2094,9 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
return Handle<Code>::null();
}
-Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
- Handle<Object> value,
- CacheHolderFlag cache_holder) {
+Handle<Object> 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.
@@ -1765,6 +2117,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
cell->set_value(isolate()->heap()->the_hole_value());
return code;
}
+ DCHECK(!FLAG_tf_store_ic_stub);
Handle<Map> transition = lookup->transition_map();
// Currently not handled by CompileStoreTransition.
DCHECK(holder->HasFastProperties());
@@ -1836,6 +2189,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
// -------------- Fields --------------
if (lookup->property_details().type() == DATA) {
+ DCHECK(!FLAG_tf_store_ic_stub);
#ifdef DEBUG
bool use_stub = true;
if (lookup->representation().IsHeapObject()) {
@@ -1981,7 +2335,6 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
}
}
- TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_Polymorphic);
MapHandleList transitioned_maps(target_receiver_maps.length());
CodeHandleList handlers(target_receiver_maps.length());
PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
@@ -2241,7 +2594,6 @@ void CallIC::HandleMiss(Handle<Object> function) {
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
// Runtime functions don't follow the IC's calling convention.
@@ -2258,7 +2610,6 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
// Runtime functions don't follow the IC's calling convention.
@@ -2279,7 +2630,7 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
} else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
Handle<Name> key(vector->GetName(vector_slot), isolate);
- DCHECK_NE(*key, *isolate->factory()->empty_string());
+ DCHECK_NE(*key, isolate->heap()->empty_string());
DCHECK_EQ(*isolate->global_object(), *receiver);
LoadGlobalICNexus nexus(vector, vector_slot);
LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
@@ -2298,7 +2649,6 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
// Runtime functions don't follow the IC's calling convention.
@@ -2309,7 +2659,7 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
vector->GetKind(vector_slot));
Handle<String> name(vector->GetName(vector_slot), isolate);
- DCHECK_NE(*name, *isolate->factory()->empty_string());
+ DCHECK_NE(*name, isolate->heap()->empty_string());
LoadGlobalICNexus nexus(vector, vector_slot);
LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
@@ -2330,7 +2680,7 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
vector->GetKind(vector_slot));
Handle<String> name(vector->GetName(vector_slot), isolate);
- DCHECK_NE(*name, *isolate->factory()->empty_string());
+ DCHECK_NE(*name, isolate->heap()->empty_string());
Handle<JSGlobalObject> global = isolate->global_object();
@@ -2343,7 +2693,7 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
script_contexts, lookup_result.context_index);
Handle<Object> result =
FixedArray::get(*script_context, lookup_result.slot_index, isolate);
- if (*result == *isolate->factory()->the_hole_value()) {
+ if (*result == isolate->heap()->the_hole_value()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
}
@@ -2370,7 +2720,6 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
// Used from ic-<arch>.cc
RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
// Runtime functions don't follow the IC's calling convention.
@@ -2387,7 +2736,6 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
typedef LoadWithVectorDescriptor Descriptor;
DCHECK_EQ(Descriptor::kParameterCount, args.length());
@@ -2406,7 +2754,6 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
// Runtime functions don't follow the IC's calling convention.
@@ -2434,7 +2781,6 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
// Runtime functions don't follow the IC's calling convention.
@@ -2470,7 +2816,6 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
// Runtime functions don't follow the IC's calling convention.
Handle<Object> object = args.at<Object>(0);
@@ -2609,7 +2954,6 @@ MaybeHandle<Object> BinaryOpIC::Transition(
RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
typedef BinaryOpDescriptor Descriptor;
@@ -2622,7 +2966,6 @@ RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
typedef BinaryOpWithAllocationSiteDescriptor Descriptor;
@@ -2686,7 +3029,6 @@ Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
// Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
@@ -2711,7 +3053,6 @@ Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss) {
- TimerEventScope<TimerEventIcMiss> timer(isolate);
DCHECK(args.length() == 1);
HandleScope scope(isolate);
Handle<Object> object = args.at<Object>(0);
@@ -2729,7 +3070,7 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
HandleScope scope(isolate);
- if (FLAG_runtime_call_stats) {
+ if (V8_UNLIKELY(FLAG_runtime_stats)) {
RETURN_RESULT_OR_FAILURE(
isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
language_mode));